diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 5873b5bd7..b069791d2 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -1,6 +1,6 @@ --- name: Bug report -about: Something isn't working as expected, and it isn't "Unsupported." (Note our contributor agreement at https://github.com/verilator/verilator/.github/blob/master/CONTRIBUTING.adoc) +about: Something isn't working as expected, and it isn't "Unsupported." (Note our contributor agreement at https://github.com/verilator/verilator/blob/master/docs/CONTRIBUTING.adoc) title: '' labels: new assignees: '' diff --git a/.github/ISSUE_TEMPLATE/feature.md b/.github/ISSUE_TEMPLATE/feature.md index b36225b94..1514b1287 100644 --- a/.github/ISSUE_TEMPLATE/feature.md +++ b/.github/ISSUE_TEMPLATE/feature.md @@ -1,6 +1,6 @@ --- name: Feature Request -about: Request something should be supported, or a new feature added. (Note our contributor agreement at https://github.com/verilator/verilator/.github/blob/master/CONTRIBUTING.adoc) +about: Request something should be supported, or a new feature added. (Note our contributor agreement at https://github.com/verilator/verilator/blob/master/docs/CONTRIBUTING.adoc) title: '' labels: new assignees: '' diff --git a/.github/ISSUE_TEMPLATE/questions.md b/.github/ISSUE_TEMPLATE/questions.md index b634a5513..1d746589f 100644 --- a/.github/ISSUE_TEMPLATE/questions.md +++ b/.github/ISSUE_TEMPLATE/questions.md @@ -1,6 +1,6 @@ --- name: Q and A, or Other -about: Ask a question, not related to a specific bug or feature request. (Note our contributor agreement at https://github.com/verilator/verilator/.github/blob/master/CONTRIBUTING.adoc) +about: Ask a question, not related to a specific bug or feature request. (Note our contributor agreement at https://github.com/verilator/verilator/blob/master/docs/CONTRIBUTING.adoc) title: '' labels: new assignees: '' diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 000000000..98ba13ed7 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,137 @@ +# DESCRIPTION: Github actions config +# This name is key to badges in README.adoc, so we use the name build +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +name: build + +on: + push: + pull_request: + workflow_dispatch: + schedule: + - cron: '0 0 * * 0' # weekly + +env: + CI_OS_NAME: linux + CI_COMMIT: ${{ github.sha }} + CCACHE_COMPRESS: 1 + CCACHE_DIR: ${{ github.workspace }}/.ccache + CCACHE_MAXSIZE: 2Gi # 2GiB for clang and gcc, 4GiB in total + +jobs: + + + Matrix: + runs-on: ubuntu-latest + name: Generate Build matrix + outputs: + matrix: ${{ steps.generate.outputs.matrix }} + steps: + - uses: actions/checkout@v2 + - id: generate + name: Run 'generate_matrix.sh' + run: | + if [ '${{ github.event_name}}' = 'pull_request' ]; then + matrix='[ "ubuntu-20.04" ]' + else + matrix='[ "ubuntu-16.04", "ubuntu-18.04", "ubuntu-20.04" ]' + fi + echo "::set-output name=matrix::$matrix" + + + Build: + needs: Matrix + strategy: + fail-fast: false + matrix: + os: ${{ fromJson(needs.Matrix.outputs.matrix) }} + debug: [ opt, dbg ] + compiler: + - { cc: clang, cxx: clang++ } + - { cc: gcc, cxx: g++ } + runs-on: ${{ matrix.os }} + name: Build | ${{ matrix.os }} | ${{ matrix.compiler.cc }} | ${{ matrix.debug }} + env: + CI_BUILD_STAGE_NAME: build + CI_RUNS_ON: ${{ matrix.os }} + CI_MAKE_SRC_TARGET: ${{ matrix.debug }} + CC: ${{ matrix.compiler.cc }} + CXX: ${{ matrix.compiler.cxx }} + CACHE_KEY: ${{ matrix.os }}-${{ matrix.compiler.cc }} + steps: + + - name: Checkout + uses: actions/checkout@v2 + + - name: Cache + uses: actions/cache@v2 + env: + cache-name: ccache + with: + path: ${{ github.workspace }}/.ccache + key: ${{ env.CACHE_KEY }}-${{ env.cache-name }}-${{ github.sha }} + restore-keys: ${{ env.CACHE_KEY }}-${{ env.cache-name }} + + - name: Install packages for build + run: ./ci/ci-install.bash + + - name: Build + run: | + ./ci/ci-script.bash + tar cvzf verilator-${{ matrix.os}}-${CI_COMMIT}-${{ matrix.compiler.cc }}-${{ matrix.debug }}.tgz ./bin + + - uses: actions/upload-artifact@v2 + with: + path: verilator-${{ matrix.os}}-${{ env.CI_COMMIT }}-${{ matrix.compiler.cc }}-${{ matrix.debug }}.tgz + + + Test: + needs: [ Matrix, Build ] + strategy: + fail-fast: false + max-parallel: 8 + matrix: + os: ${{ fromJson(needs.Matrix.outputs.matrix) }} + compiler: + - { cc: clang, cxx: clang++ } + - { cc: gcc, cxx: g++ } + suite: + - dist-vlt-0 + - dist-vlt-1 + - vltmt-0 + - vltmt-1 + runs-on: ${{ matrix.os }} + name: Test | ${{ matrix.os }} | ${{ matrix.compiler.cc }} | ${{ matrix.suite }} + env: + CI_BUILD_STAGE_NAME: test + CI_RUNS_ON: ${{ matrix.os }} + CC: ${{ matrix.compiler.cc }} + CXX: ${{ matrix.compiler.cxx }} + CACHE_KEY: ${{ matrix.os }}-${{ matrix.compiler.cc }} + steps: + + - name: Checkout + uses: actions/checkout@v2 + + - name: Cache + uses: actions/cache@v2 + env: + cache-name: ccache + with: + path: ${{ github.workspace }}/.ccache + key: ${{ env.CACHE_KEY }}-${{ env.cache-name }}-${{ github.sha }} + restore-keys: ${{ env.CACHE_KEY }}-${{ env.cache-name }} + + - uses: actions/download-artifact@v2 + + - name: Install Verilator and test dependencies + run: | + tar xvzf artifact/verilator-${{ matrix.os}}-${CI_COMMIT}-${{ matrix.compiler.cc }}-opt.tgz + tar xvzf artifact/verilator-${{ matrix.os}}-${CI_COMMIT}-${{ matrix.compiler.cc }}-dbg.tgz + rm -rf artifact + ./ci/ci-install.bash + + - name: Test + env: + TESTS: ${{ matrix.suite }} + run: ./ci/ci-script.bash diff --git a/.github/workflows/clang-format.yml b/.github/workflows/clang-format.yml new file mode 100644 index 000000000..6cf4c5b4b --- /dev/null +++ b/.github/workflows/clang-format.yml @@ -0,0 +1,44 @@ +# DESCRIPTION: Github actions config +# This name is key to badges in README.adoc, so we use the name build +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +name: clang-format + +on: + push: + pull_request_target: + workflow_dispatch: + +jobs: + format: + runs-on: ubuntu-20.04 + name: Ubuntu 20.04 | format + env: + CI_OS_NAME: linux + CI_RUNS_ON: ubuntu-20.04 + CI_COMMIT: ${{ github.sha }} + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + token: ${{ secrets.GITHUB_TOKEN }} + - name: Install packages for build + env: + CI_BUILD_STAGE_NAME: build + run: | + bash ci/ci-install.bash && + sudo apt-get install clang-10 yapf3 && + git config --global user.email "action@example.com" && + git config --global user.name "github action" + - name: Format code + run: | + autoconf && + ./configure && + make -j 2 format CLANGFORMAT=clang-format-10 && + git status + - name: Push + run: | + if [ -n "$(git status --porcelain)" ]; then + git commit . -m "Apply clang-format" && + git push origin + fi diff --git a/.github/workflows/contributor.yml b/.github/workflows/contributor.yml new file mode 100644 index 000000000..627d00ab3 --- /dev/null +++ b/.github/workflows/contributor.yml @@ -0,0 +1,17 @@ +# DESCRIPTION: Github actions config +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +name: Contributor Agreement + +on: + push: + pull_request: + workflow_dispatch: + +jobs: + Test: + name: "'docs/CONTRIBUTORS' was signed" + runs-on: ubuntu-20.04 + steps: + - uses: actions/checkout@v2 + - run: test_regress/t/t_dist_contributors.pl diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml new file mode 100644 index 000000000..00623317b --- /dev/null +++ b/.github/workflows/coverage.yml @@ -0,0 +1,98 @@ +# DESCRIPTION: Github actions config +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +name: coverage + +on: + workflow_dispatch: + schedule: + - cron: '0 0 * * 0' # weekly + +env: + CI_OS_NAME: linux + CI_COMMIT: ${{ github.sha }} + CCACHE_COMPRESS: 1 + CCACHE_DIR: ${{ github.workspace }}/.ccache + CCACHE_MAXSIZE: 2Gi # 2GiB for clang and gcc, 4GiB in total + COVERAGE: 1 + +jobs: + + + Build: + runs-on: ubuntu-20.04 + env: + CI_BUILD_STAGE_NAME: build + steps: + + - uses: actions/checkout@v2 + + - uses: actions/cache@v2 + env: + cache-name: ccache + with: + path: ${{ github.workspace }}/.ccache + key: coverage-${{ env.cache-name }}-${{ github.sha }} + restore-keys: coverage-${{ env.cache-name }} + + - name: Install dependencies for build + env: + CI_BUILD_STAGE_NAME: build + run: ./ci/ci-install.bash + + - name: Build Verilator + run: | + ./ci/ci-script.bash + + mkdir tarball/ + cp -vr bin tarball/ + cp -vr src/obj*/*.gcno tarball/ + tar cvzf verilator-${CI_COMMIT}.tgz -C ./tarball . + + - uses: actions/upload-artifact@v2 + with: + path: verilator-${{ env.CI_COMMIT }}.tgz + + + Test: + needs: Build + strategy: + fail-fast: false + matrix: + test: + - vlt- + - vltmt- + num: + - 0 + - 1 + - 2 + - 3 + include: + - { test: dist, num: '' } + name: test-${{ matrix.test }}${{ matrix.num }} + runs-on: ubuntu-20.04 + env: + CI_BUILD_STAGE_NAME: test + steps: + + - uses: actions/checkout@v2 + + - uses: actions/cache@v2 + env: + cache-name: ccache + with: + path: ${{ github.workspace }}/.ccache + key: coverage-${{ env.cache-name }}-${{ github.sha }} + restore-keys: coverage-${{ env.cache-name }} + + - uses: actions/download-artifact@v2 + + - name: Install Verilator and test dependencies + run: | + tar xvzf artifact/verilator-${CI_COMMIT}.tgz + ./ci/ci-install.bash + + - name: Test + env: + TESTS: coverage-${{ matrix.test }}${{ matrix.num }} + run: ./ci/ci-script.bash diff --git a/.gitignore b/.gitignore index d426d7134..8721ca5a8 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,8 @@ *.tex *.pdf /Makefile +/.ccache +/artifact/ README TAGS autom4te.cache diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index a10734230..000000000 --- a/.travis.yml +++ /dev/null @@ -1,149 +0,0 @@ -# DESCRIPTION: Travis-CI config -# -# Copyright 2003-2020 by Wilson Snyder. This program is free software; you -# can redistribute it and/or modify it under the terms of either the GNU -# Lesser General Public License Version 3 or the Perl Artistic License -# Version 2.0. -# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 - -version: ~> 1.0 - -language: cpp - -cache: - directories: - - $HOME/.ccache - -env: - global: - - VERILATOR_ROOT=$TRAVIS_BUILD_DIR - -# The list and order of build stages -stages: - - build # Build Verilator - - test # Run tests - -# Dump info about the environment for debugging -before_install: - # To dump the script that Travis itself is executing, add 'cat $0' here - - cd "$TRAVIS_BUILD_DIR" # Skipping the git clone in later stages requires this - - export CCACHE_MAXSIZE=$(ci/travis-ccache-size.bash) # Set here after the 'cd' - - env | sort - - ls -lA . - - ls -lA bin - - g++ -E -dM -c -x c++ /dev/null | sort - - clang++ -E -dM -c -x c++ /dev/null | sort - -# Install all dependencies -# We run twice to attempt on failure to recover from temp network problems -install: - - ./ci/travis-install.bash || ./ci/travis-install.bash - -before_script: - # ccache maintenance - - ./ci/travis-ccache-maint.bash - # Don't produce core dumps (esp. on FreeBSD) - - ulimit -c 0 - # On Focal, set the SystemC installation location - - | - if [ "$TRAVIS_DIST" = "focal" ] && [ "$M32" != "1" ]; then - export SYSTEMC_INCLUDE=/usr/include - export SYSTEMC_LIBDIR=/usr/lib/x86_64-linux-gnu - fi - # Override compiler for M32 - - | - if [ "$M32" = "1" ]; then - export CC="$CC -m32" - export CXX="$CXX -m32" - unset M32 # verilated.mk actually references $(M32) so unset - fi - -before_cache: - - ccache -s -z - -# All jobs run the same script -script: ./ci/travis-script.bash - -# Enumerate all the jobs -jobs: - include: - ############################################################################ - # Jobs in the 'build' stage - ############################################################################ - # GCC builds - - {stage: build, if: type = cron, os: linux, dist: trusty, compiler: gcc, workspaces: {create: {name: trusty-gcc, paths: .}}} - - {stage: build, if: type = cron, os: linux, dist: xenial, compiler: gcc, workspaces: {create: {name: xenial-gcc, paths: .}}} - - {stage: build, if: type = cron, os: linux, dist: bionic, compiler: gcc, workspaces: {create: {name: bionic-gcc, paths: .}}} - - {stage: build, os: linux, dist: focal, compiler: gcc, workspaces: {create: {name: focal-gcc, paths: .}}} - # Clang builds - - {stage: build, if: type = cron, os: linux, dist: xenial, compiler: clang, workspaces: {create: {name: xenial-clang, paths: .}}} - - {stage: build, os: linux, dist: focal, compiler: clang, workspaces: {create: {name: focal-clang, paths: .}}} - # Coverage build - - {stage: build, if: type = cron, os: linux, dist: focal, compiler: gcc, workspaces: {create: {name: coverage, paths: .}}, env: COVERAGE=1} - # 32-bit build - - {stage: build, if: type = cron, os: linux, dist: focal, compiler: gcc, workspaces: {create: {name: focal-gcc-m32, paths: .}}, env: M32=1} - # OS X build - - {stage: build, if: type = cron, os: osx, osx_image: xcode11.6, compiler: clang, workspaces: {create: {name: osx-xcode11.6, paths: .}}} - # FreeBSD build - #- {stage: build, if: type = cron, os: freebsd, compiler: clang, workspaces: {create: {name: freebsd, paths: .}}} - ############################################################################ - # Jobs in the 'test' stage - ############################################################################ - # GCC tests - - {stage: test, if: type = cron, os: linux, dist: trusty, compiler: gcc, workspaces: {use: trusty-gcc}, git: {clone: false}, env: TESTS=dist-vlt-0} - - {stage: test, if: type = cron, os: linux, dist: trusty, compiler: gcc, workspaces: {use: trusty-gcc}, git: {clone: false}, env: TESTS=dist-vlt-1} - - {stage: test, if: type = cron, os: linux, dist: trusty, compiler: gcc, workspaces: {use: trusty-gcc}, git: {clone: false}, env: TESTS=vltmt-0} - - {stage: test, if: type = cron, os: linux, dist: trusty, compiler: gcc, workspaces: {use: trusty-gcc}, git: {clone: false}, env: TESTS=vltmt-1} - - {stage: test, if: type = cron, os: linux, dist: xenial, compiler: gcc, workspaces: {use: xenial-gcc}, git: {clone: false}, env: TESTS=dist-vlt-0} - - {stage: test, if: type = cron, os: linux, dist: xenial, compiler: gcc, workspaces: {use: xenial-gcc}, git: {clone: false}, env: TESTS=dist-vlt-1} - - {stage: test, if: type = cron, os: linux, dist: xenial, compiler: gcc, workspaces: {use: xenial-gcc}, git: {clone: false}, env: TESTS=vltmt-0} - - {stage: test, if: type = cron, os: linux, dist: xenial, compiler: gcc, workspaces: {use: xenial-gcc}, git: {clone: false}, env: TESTS=vltmt-1} - - {stage: test, if: type = cron, os: linux, dist: bionic, compiler: gcc, workspaces: {use: bionic-gcc}, git: {clone: false}, env: TESTS=dist-vlt-0} - - {stage: test, if: type = cron, os: linux, dist: bionic, compiler: gcc, workspaces: {use: bionic-gcc}, git: {clone: false}, env: TESTS=dist-vlt-1} - - {stage: test, if: type = cron, os: linux, dist: bionic, compiler: gcc, workspaces: {use: bionic-gcc}, git: {clone: false}, env: TESTS=vltmt-0} - - {stage: test, if: type = cron, os: linux, dist: bionic, compiler: gcc, workspaces: {use: bionic-gcc}, git: {clone: false}, env: TESTS=vltmt-1} - - {stage: test, if: type != cron, os: linux, dist: focal, compiler: gcc, workspaces: {use: focal-gcc}, git: {clone: false}, env: TESTS=dist-vlt-0} - - {stage: test, if: type != cron, os: linux, dist: focal, compiler: gcc, workspaces: {use: focal-gcc}, git: {clone: false}, env: TESTS=dist-vlt-1} - - {stage: test, if: type = cron, os: linux, dist: focal, compiler: gcc, workspaces: {use: focal-gcc}, git: {clone: false}, env: TESTS=vltmt-0} - - {stage: test, if: type = cron, os: linux, dist: focal, compiler: gcc, workspaces: {use: focal-gcc}, git: {clone: false}, env: TESTS=vltmt-1} - # Clang tests - - {stage: test, if: type = cron, os: linux, dist: xenial, compiler: clang, workspaces: {use: xenial-clang}, git: {clone: false}, env: TESTS=dist-vlt-0} - - {stage: test, if: type = cron, os: linux, dist: xenial, compiler: clang, workspaces: {use: xenial-clang}, git: {clone: false}, env: TESTS=dist-vlt-1} - - {stage: test, if: type = cron, os: linux, dist: xenial, compiler: clang, workspaces: {use: xenial-clang}, git: {clone: false}, env: TESTS=vltmt-0} - - {stage: test, if: type = cron, os: linux, dist: xenial, compiler: clang, workspaces: {use: xenial-clang}, git: {clone: false}, env: TESTS=vltmt-1} - - {stage: test, if: type = cron, os: linux, dist: focal, compiler: clang, workspaces: {use: focal-clang}, git: {clone: false}, env: TESTS=dist-vlt-0} - - {stage: test, if: type = cron, os: linux, dist: focal, compiler: clang, workspaces: {use: focal-clang}, git: {clone: false}, env: TESTS=dist-vlt-1} - - {stage: test, if: type != cron, os: linux, dist: focal, compiler: clang, workspaces: {use: focal-clang}, git: {clone: false}, env: TESTS=vltmt-0} - - {stage: test, if: type != cron, os: linux, dist: focal, compiler: clang, workspaces: {use: focal-clang}, git: {clone: false}, env: TESTS=vltmt-1} - # Coverage tests - - {stage: test, if: type = cron, os: linux, dist: focal, compiler: gcc, workspaces: {use: coverage}, git: {clone: false}, env: TESTS=coverage-dist} - - {stage: test, if: type = cron, os: linux, dist: focal, compiler: gcc, workspaces: {use: coverage}, git: {clone: false}, env: TESTS=coverage-vlt-0} - - {stage: test, if: type = cron, os: linux, dist: focal, compiler: gcc, workspaces: {use: coverage}, git: {clone: false}, env: TESTS=coverage-vlt-1} - - {stage: test, if: type = cron, os: linux, dist: focal, compiler: gcc, workspaces: {use: coverage}, git: {clone: false}, env: TESTS=coverage-vlt-2} - - {stage: test, if: type = cron, os: linux, dist: focal, compiler: gcc, workspaces: {use: coverage}, git: {clone: false}, env: TESTS=coverage-vlt-3} - - {stage: test, if: type = cron, os: linux, dist: focal, compiler: gcc, workspaces: {use: coverage}, git: {clone: false}, env: TESTS=coverage-vltmt-0} - - {stage: test, if: type = cron, os: linux, dist: focal, compiler: gcc, workspaces: {use: coverage}, git: {clone: false}, env: TESTS=coverage-vltmt-1} - - {stage: test, if: type = cron, os: linux, dist: focal, compiler: gcc, workspaces: {use: coverage}, git: {clone: false}, env: TESTS=coverage-vltmt-2} - - {stage: test, if: type = cron, os: linux, dist: focal, compiler: gcc, workspaces: {use: coverage}, git: {clone: false}, env: TESTS=coverage-vltmt-3} - # 32-bit tests - - {stage: test, if: type = cron, os: linux, dist: focal, compiler: gcc, workspaces: {use: focal-gcc-m32}, git: {clone: false}, env: [M32=1, TESTS=dist-vlt-0]} - - {stage: test, if: type = cron, os: linux, dist: focal, compiler: gcc, workspaces: {use: focal-gcc-m32}, git: {clone: false}, env: [M32=1, TESTS=dist-vlt-1]} - - {stage: test, if: type = cron, os: linux, dist: focal, compiler: gcc, workspaces: {use: focal-gcc-m32}, git: {clone: false}, env: [M32=1, TESTS=vltmt-0]} - - {stage: test, if: type = cron, os: linux, dist: focal, compiler: gcc, workspaces: {use: focal-gcc-m32}, git: {clone: false}, env: [M32=1, TESTS=vltmt-1]} - # OS X tests - - {stage: test, if: type = cron, os: osx, osx_image: xcode11.6, compiler: clang, workspaces: {use: osx-xcode11.6}, git: {clone: false}, env: TESTS=dist-vlt-0} - - {stage: test, if: type = cron, os: osx, osx_image: xcode11.6, compiler: clang, workspaces: {use: osx-xcode11.6}, git: {clone: false}, env: TESTS=dist-vlt-1} - - {stage: test, if: type = cron, os: osx, osx_image: xcode11.6, compiler: clang, workspaces: {use: osx-xcode11.6}, git: {clone: false}, env: TESTS=vltmt-0} - - {stage: test, if: type = cron, os: osx, osx_image: xcode11.6, compiler: clang, workspaces: {use: osx-xcode11.6}, git: {clone: false}, env: TESTS=vltmt-1} - # FreeBSD tests - #- {stage: test, if: type = cron, os: freebsd, compiler: clang, workspaces: {use: freebsd}, git: {clone: false}, env: TESTS=dist-vlt-0} - #- {stage: test, if: type = cron, os: freebsd, compiler: clang, workspaces: {use: freebsd}, git: {clone: false}, env: TESTS=dist-vlt-1} - #- {stage: test, if: type = cron, os: freebsd, compiler: clang, workspaces: {use: freebsd}, git: {clone: false}, env: TESTS=vltmt-0} - #- {stage: test, if: type = cron, os: freebsd, compiler: clang, workspaces: {use: freebsd}, git: {clone: false}, env: TESTS=vltmt-1} - -notifications: - email: - if: repo = verilator/verilator - recipients: - - wsnyder@wsnyder.org - - todd.strader@gmail.com diff --git a/Changes b/Changes index 3e06d6263..1547bfedb 100644 --- a/Changes +++ b/Changes @@ -3,6 +3,62 @@ Revision history for Verilator The contributors that suggested a given feature are shown in []. Thanks! +* Verilator 4.108 2021-01-10 + +** Many VPI changes for IEEE compatibility, which may alter behavior from previous releases. + +** Support randomize() class method and rand (#2607). [Krzysztof Bieganski] + +*** Support $cast and new CASTCONST warning. + +*** Add --top option as alias of --top-module. + +*** Add LATCH and NOLATCH warnings (#1609) (#2740). [Julien Margetts] + +**** Remove Unix::Processors internal test dependency. + +**** Report UNUSED on parameters, localparam and genvars (#2627). [Charles Eric LaForest] + +**** Add error on real to non-real output pins (#2690). [Peter Monsson] + +**** Support package imports before parameters in interfaces (#2714). [James Hanlon] + +**** Support --sanitize in internal tests (#2705). [Yutetsu TAKATSUKASA] + +**** Fix passing parameter type instantiations by position number. + +**** Fix DPI open array handling issues. + +**** Fix error when dotted refers to missing module (#2095). [Alexander Grobman] + +**** Fix little endian packed array counting (#2499). [phantom-killua] + +**** Fix showing reference locations for BLKANDNBLK (#2170). [Yuri Victorovich] + +**** Fix genblk naming to match IEEE (#2686). [tinshark] + +**** Fix VPI memory word indexing (#2695). [Marlon James] + +**** Fix vpiLeftRange on little-endian memories (#2696). [Marlon James] + +**** Fix VPI module tree (#2704). [Todd Strader] + +**** Fix vpi_release_handle to be called implicitly per IEEE (#2706). + +**** Fix to allow inheriting 'VerilatedVcdFile' class. (#2720) [HyungKi Jeong] + +**** Fix $urandom_range maximum value (#2723). [Nandu Raj] + +**** Fix tracing empty sc module (#2729). + +**** Fix generate for unrolling to be signed (#2730). [yanx21] + +**** Fix to emit timescale in hierarchical blocks (#2735). [Yutetsu TAKATSUKASA] + +**** Fix to ignore coverage on real ports (#2741) (#2745). [Paul Wright] + + + * Verilator 4.106 2020-12-02 ** Change -sv option to select 1800-2017 instead of 1800-2005. @@ -3835,7 +3891,7 @@ of input ports exists for tracing. This uses outline mode in Emacs. See C-h m [M-x describe-mode]. -Copyright 2001-2020 by Wilson Snyder. This program is free software; you +Copyright 2001-2021 by Wilson Snyder. This program is free software; you can redistribute it and/or modify it under the terms of either the GNU Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. diff --git a/MANIFEST.SKIP b/MANIFEST.SKIP index cea857c16..6c8b4c4c0 100644 --- a/MANIFEST.SKIP +++ b/MANIFEST.SKIP @@ -1,3 +1,4 @@ +\.ccache/ \.clang-format \.clang-tidy \.git/ @@ -23,6 +24,7 @@ /obj_dir/ /obj_dist/ /obj_iv/ +/obj_ms/ /obj_nc/ /obj_opt/ /obj_vcs/ @@ -45,6 +47,7 @@ src/Makefile$ src/Makefile_obj$ include/verilated.mk$ test_regress/.gdbinit$ +test_regress/transcript codecov.yml config.cache$ config.status$ diff --git a/Makefile.in b/Makefile.in index 7d2a929e2..acb3e43bd 100644 --- a/Makefile.in +++ b/Makefile.in @@ -7,7 +7,7 @@ # #***************************************************************************** # -# Copyright 2003-2020 by Wilson Snyder. This program is free software; you +# Copyright 2003-2021 by Wilson Snyder. This program is free software; you # can redistribute it and/or modify it under the terms of either the GNU # Lesser General Public License Version 3 or the Perl Artistic License # Version 2.0. @@ -153,6 +153,7 @@ DISTFILES_INC = $(INFOS) .gitignore \ .*attributes */.*attributes */*/.*attributes \ src/.*ignore src/*.in src/*.cpp src/*.[chly] \ src/astgen src/bisonpre src/*fix src/cppcheck_filtered \ + src/config_rev \ src/vlcovgen src/mkinstalldirs \ src/.gdbinit \ src/*.pl src/*.pod \ @@ -219,7 +220,7 @@ all_nomsg: verilator_exe $(VL_INST_MAN_FILES) verilator_exe verilator_bin verilator_bin_dbg verilator_coverage_bin_dbg: @echo ------------------------------------------------------------ @echo "making verilator in src" - $(MAKE) -C src $(OBJCACHE_JOBS) + $(MAKE) -C src $(OBJCACHE_JOBS) $(CI_MAKE_SRC_TARGET) .PHONY:msg_test msg_test: all_nomsg @@ -421,6 +422,7 @@ endif # Use --xml flag to see the cppcheck code to use for suppression CPPCHECK_CPP = $(wildcard \ + $(srcdir)/examples/*/*.cpp \ $(srcdir)/include/*.cpp \ $(srcdir)/src/*.cpp ) CPPCHECK_H = $(wildcard \ @@ -429,7 +431,7 @@ CPPCHECK_H = $(wildcard \ CPPCHECK_YL = $(wildcard \ $(srcdir)/src/*.y \ $(srcdir)/src/*.l ) -CPPCHECK = src/cppcheck_filtered +CPPCHECK = src/cppcheck_filtered cppcheck CPPCHECK_FLAGS = --enable=all --inline-suppr \ --suppress=unusedScopedObject --suppress=cstyleCast --suppress=useInitializationList \ --suppress=nullPointerRedundantCheck @@ -461,15 +463,36 @@ analyzer-include: -rm -rf examples/*/obj* scan-build $(MAKE) -k examples +format: clang-format yapf + CLANGFORMAT = clang-format CLANGFORMAT_FLAGS = -i -CLANGFORMAT_FILES = $(CPPCHECK_CPP) $(CPPCHECK_H) $(CPPCHECK_YL) test_regress/t/*.c* +CLANGFORMAT_FILES = $(CPPCHECK_CPP) $(CPPCHECK_H) $(CPPCHECK_YL) test_regress/t/*.c* test_regress/t/*.h clang-format: @$(CLANGFORMAT) --version | egrep 10.0 > /dev/null \ || echo "*** You are not using clang-format 10.0, indents may differ from master's ***" $(CLANGFORMAT) $(CLANGFORMAT_FLAGS) $(CLANGFORMAT_FILES) +YAPF = yapf3 +YAPF_FLAGS = -i +YAPF_FILES = \ + examples/xml_py/vl_file_copy \ + examples/xml_py/vl_hier_graph \ + src/config_rev \ + src/cppcheck_filtered \ + src/flexfix \ + src/vlcovgen \ + nodist/code_coverage \ + nodist/code_coverage.dat \ + nodist/dot_importer \ + nodist/fuzzer/actual_fail \ + nodist/fuzzer/generate_dictionary \ + nodist/install_test \ + +yapf: + $(YAPF) $(YAPF_FLAGS) $(YAPF_FILES) + ftp: info install-msg: diff --git a/README.adoc b/README.adoc index a77349e97..f97ba1f06 100644 --- a/README.adoc +++ b/README.adoc @@ -6,7 +6,7 @@ image:https://img.shields.io/badge/License-LGPL%20v3-blue.svg[license LGPLv3,lin image:https://img.shields.io/badge/License-Artistic%202.0-0298c3.svg[license Artistic-2.0,link=https://opensource.org/licenses/Artistic-2.0] image:https://api.codacy.com/project/badge/Grade/fa78caa433c84a4ab9049c43e9debc6f[Code Quality,link=https://www.codacy.com/gh/verilator/verilator] image:https://codecov.io/gh/verilator/verilator/branch/master/graph/badge.svg[Coverage,link=https://codecov.io/gh/verilator/verilator] -image:https://travis-ci.com/verilator/verilator.svg?branch=master[Build Status (Travis CI),link=https://travis-ci.com/verilator/verilator] +image:https://github.com/verilator/verilator/workflows/build/badge.svg[Build Status (GitHub),link=https://github.com/verilator/verilator/actions?query=workflow%3Abuild] endif::[] ifdef::env-github[] @@ -145,7 +145,7 @@ perhaps Icarus may. == Open License -Verilator is Copyright 2003-2020 by Wilson Snyder. (Report bugs to +Verilator is Copyright 2003-2021 by Wilson Snyder. (Report bugs to https://verilator.org/issues[Verilator Issues].) Verilator is free software; you can redistribute it and/or modify it under diff --git a/bin/verilator b/bin/verilator index 2df1ec7aa..e581f0867 100755 --- a/bin/verilator +++ b/bin/verilator @@ -1,7 +1,7 @@ #!/usr/bin/env perl ###################################################################### # -# Copyright 2003-2020 by Wilson Snyder. This program is free software; you +# Copyright 2003-2021 by Wilson Snyder. This program is free software; you # can redistribute it and/or modify it under the terms of either the GNU # Lesser General Public License Version 3 or the Perl Artistic License # Version 2.0. @@ -409,6 +409,7 @@ arguments. --threads-max-mtasks Tune maximum mtask partitioning --timescale Sets default timescale --timescale-override Overrides all timescales + --top Alias of --top-module --top-module Name of top level input module --trace Enable waveform creation --trace-coverage Enable tracing of coverage @@ -1260,8 +1261,8 @@ With -E, show comments in preprocessor output. =item --prefix I Specifies the name of the top level class and makefile. Defaults to V -prepended to the name of the --top-module switch, or V prepended to the -first Verilog filename passed on the command line. +prepended to the name of the --top switch, or V prepended to the first +Verilog filename passed on the command line. =item --prof-cfuncs @@ -1523,6 +1524,8 @@ sc_set_time_resolution, or the C++ code instantiating the Verilated module. As 1fs is the finest time precision it may be desirable to always use a precision of 1fs. +=item --top I + =item --top-module I When the input Verilog contains more than one top level module, specifies @@ -1636,8 +1639,8 @@ into Verilator. (Similar to perl -V.) See also --getenv. =item -v I Read the filename as a Verilog library. Any modules in the file may be -used to resolve cell instantiations in the top level module, else ignored. -Note -v is fairly standard across Verilog tools. +used to resolve instances in the top level module, else ignored. Note -v +is fairly standard across Verilog tools. =item --no-verilate @@ -1714,7 +1717,7 @@ than using this option. Disable all lint related warning messages, and all style warnings. This is equivalent to "-Wno-ALWCOMBORDER -Wno-BSSPACE -Wno-CASEINCOMPLETE --Wno-CASEOVERLAP -Wno-CASEX -Wno-CASEWITHX -Wno-CMPCONST -Wno-COLONPLUS +-Wno-CASEOVERLAP -Wno-CASEX -Wno-CASTCONST -Wno-CASEWITHX -Wno-CMPCONST -Wno-COLONPLUS -Wno-ENDLABEL -Wno-IMPLICIT -Wno-LITENDIAN -Wno-PINCONNECTEMPTY -Wno-PINMISSING -Wno-SYNCASYNCNET -Wno-UNDRIVEN -Wno-UNSIGNED -Wno-UNUSED -Wno-WIDTH" plus the list shown for Wno-style. @@ -1746,7 +1749,7 @@ Enables the specified warning message. Enable all lint related warning messages (note by default they are already enabled), but do not affect style messages. This is equivalent to "-Wwarn-ALWCOMBORDER -Wwarn-BSSPACE -Wwarn-CASEINCOMPLETE --Wwarn-CASEOVERLAP -Wwarn-CASEX -Wwarn-CASEWITHX -Wwarn-CMPCONST +-Wwarn-CASEOVERLAP -Wwarn-CASEX -Wwarn-CASTCONST -Wwarn-CASEWITHX -Wwarn-CMPCONST -Wwarn-COLONPLUS -Wwarn-ENDLABEL -Wwarn-IMPLICIT -Wwarn-LITENDIAN -Wwarn-PINMISSING -Wwarn-REALCVT -Wwarn-UNSIGNED -Wwarn-WIDTH". @@ -3101,8 +3104,8 @@ Enable/disable waveform tracing for all future signals declared in the specified filename (or wildcard with '*' or '?', or all files if omitted) and range of line numbers (or all lines if omitted). -For tracing_off, cells below any module in the files/ranges specified will -also not be traced. +For tracing_off, instances below any module in the files/ranges specified +will also not be traced. =item clock_enable -module "" -var "" @@ -3774,13 +3777,13 @@ for use by downstream applications. =item /*verilator tracing_off*/ Disable waveform tracing for all future signals that are declared in this -module, or cells below this module. Often this is placed just after a -primitive's module statement, so that the entire module and cells below it -are not traced. +module, or instances below this module. Often this is placed just after a +primitive's module statement, so that the entire module and instances below +it are not traced. =item /*verilator tracing_on*/ -Re-enable waveform tracing for all future signals or cells that are +Re-enable waveform tracing for all future signals or instances that are declared. =back @@ -3834,8 +3837,8 @@ for example a[2].b is acceptable, while a[x].b is generally not. References into generated and arrayed instances use the instance names specified in the Verilog standard; arrayed instances are named -{cellName}[{instanceNumber}] in Verilog, which becomes -{cellname}__BRA__{instanceNumber}__KET__ inside the generated C++ code. +{instanceName}[{instanceNumber}] in Verilog, which becomes +{instanceName}__BRA__{instanceNumber}__KET__ inside the generated C++ code. =head2 Latches @@ -4314,15 +4317,6 @@ not overlap. Ignoring this warning will only suppress the lint check, it will simulate correctly. -=item CASEX - -Warns that it is simply better style to use casez, and C in place of -C's. See -L - -Ignoring this warning will only suppress the lint check, it will simulate -correctly. - =item CASEWITHX Warns that a case statement contains a constant with a C. Verilator is @@ -4333,6 +4327,25 @@ instead intended is to use a casez with C. Ignoring this warning will only suppress the lint check, it will simulate correctly. +=item CASEX + +Warns that it is simply better style to use casez, and C in place of +C's. See +L + +Ignoring this warning will only suppress the lint check, it will simulate +correctly. + +=item CASTCONST + +Warns that a dynamic cast ($cast) is unnecessary as the $cast will always +succeed or fail. If it will always fail, the $cast is useless. If it will +always succeed a static cast may be preferred. + +Ignoring this warning will only suppress the lint check, it will simulate +correctly. On other simulators, not fixing CASTCONST may result in +decreased performance. + =item CDCRSTLOGIC With --cdc only, warns that asynchronous flop reset terms come from other @@ -4510,9 +4523,9 @@ top module statement is processed. Warns that a wire is being implicitly declared (it is a single bit wide output from a sub-module.) While legal in Verilog, implicit declarations only work for single bit wide signals (not buses), do not allow using a -signal before it is implicitly declared by a cell, and can lead to dangling -nets. A better option is the /*AUTOWIRE*/ feature of Verilog-Mode for -Emacs, available from L +signal before it is implicitly declared by an instance, and can lead to +dangling nets. A better option is the /*AUTOWIRE*/ feature of Verilog-Mode +for Emacs, available from L Ignoring this warning will only suppress the lint check, it will simulate correctly. @@ -4578,6 +4591,16 @@ exposed is acceptable. Ignoring this warning will only suppress the lint check, it will simulate correctly. +=item LATCH + +Warns that a signal is not assigned in all control paths of a combinational +always block, resulting in the inference of a latch. For intentional +latches, consider using the always_latch (SystemVerilog) keyword instead. +The warning may be disabled with a lint_off pragma around the always block. + +Ignoring this warning will only suppress the lint check, it will simulate +correctly. + =item LITENDIAN Warns that a packed vector is declared with little endian bit numbering @@ -4585,10 +4608,10 @@ Warns that a packed vector is declared with little endian bit numbering and little numbering is now thus often due to simple oversight instead of intent. -Also warns that a cell is declared with little endian range (i.e. [0:7] or -[7]) and is connected to a N-wide signal. Based on IEEE the bits will -likely be backwards from what you expect (i.e. cell [0] will connect to -signal bit [N-1] not bit [0]). +Also warns that an instance is declared with little endian range +(i.e. [0:7] or [7]) and is connected to a N-wide signal. Based on IEEE the +bits will likely be backwards from what you expect (i.e. instance [0] will +connect to signal bit [N-1] not bit [0]). Ignoring this warning will only suppress the lint check, it will simulate correctly. @@ -4620,18 +4643,18 @@ instantiated by any other module, and both modules were put on the command line (not in a library). Three likely cases: 1. A single module is intended to be the top. This warning then occurs -because some low level cell is being read in, but is not really needed as -part of the design. The best solution for this situation is to ensure that -only the top module is put on the command line without any flags, and all -remaining library files are read in as libraries with -v, or are +because some low level instance is being read in, but is not really needed +as part of the design. The best solution for this situation is to ensure +that only the top module is put on the command line without any flags, and +all remaining library files are read in as libraries with -v, or are automatically resolved by having filenames that match the module names. 2. A single module is intended to be the top, the name of it is known, and all other modules should be ignored if not part of the design. The best -solution is to use the --top-module option to specify the top module's -name. All other modules that are not part of the design will be for the -most part ignored (they must be clean in syntax and their contents will be -removed as part of the Verilog module elaboration process.) +solution is to use the --top option to specify the top module's name. All +other modules that are not part of the design will be for the most part +ignored (they must be clean in syntax and their contents will be removed as +part of the Verilog module elaboration process.) 3. Multiple modules are intended to be design tops, e.g. when linting a library file. As multiple modules are desired, disable the MULTITOP @@ -4641,29 +4664,37 @@ based on the top module name followed by __02E (a Verilator-encoded ASCII ".'). This renaming is done even if the two modules' signals seem identical, e.g. multiple modules with a "clk" input. +=item NOLATCH + +Warns that no latch was detected in an always_latch block. The warning may +be disabled with a lint_off pragma around the always block, but recoding +using a regular always may be more appropriate. + +Ignoring this warning will only suppress the lint check, it will simulate +correctly. + =item PINCONNECTEMPTY -Warns that a cell instantiation has a pin which is connected to -.pin_name(), e.g. not another signal, but with an explicit mention of the -pin. It may be desirable to disable PINCONNECTEMPTY, as this indicates -intention to have a no-connect. +Warns that an instance has a pin which is connected to .pin_name(), +e.g. not another signal, but with an explicit mention of the pin. It may +be desirable to disable PINCONNECTEMPTY, as this indicates intention to +have a no-connect. Disabled by default as this is a code style warning; it will simulate correctly. =item PINMISSING -Warns that a module has a pin which is not mentioned in a cell -instantiation. If a pin is not missing it should still be specified on the -cell declaration with a empty connection, using "(.pin_name())". +Warns that a module has a pin which is not mentioned in an instance. If a +pin is not missing it should still be specified on the instance declaration +with a empty connection, using "(.pin_name())". Ignoring this warning will only suppress the lint check, it will simulate correctly. =item PINNOCONNECT -Warns that a cell instantiation has a pin which is not connected to another -signal. +Warns that an instance has a pin which is not connected to another signal. Disabled by default as this is a code style warning; it will simulate correctly. @@ -4679,6 +4710,11 @@ declared before being used. Error that a procedural assignment is setting a wire. According to IEEE, a var/reg must be used as the target of procedural assignments. +=item RANDC + +Warns that the 'randc' keyword is currently unsupported, and that it is +being converted to 'rand'. + =item REALCVT Warns that a real number is being implicitly rounded to an integer, with @@ -4782,12 +4818,12 @@ correctly. =item TASKNSVAR -Error when a call to a task or function has a output from that task tied to +Error when a call to a task or function has an inout from that task tied to a non-simple signal. Instead connect the task output to a temporary signal of the appropriate width, and use that signal to set the appropriate expression as the next statement. For example: - task foo; output sig; ... endtask + task foo(inout sig); ... endtask always @* begin foo(bus_we_select_from[2]); // Will get TASKNSVAR error end @@ -4901,7 +4937,7 @@ potentially resolving the conflict. If you run with --report-unoptflat Verilator will suggest possible candidates for C. The UNOPTFLAT warning may also be due to clock enables, identified from the -reported path going through a clock gating cell. To fix these, use the +reported path going through a clock gating instance. To fix these, use the clock_enable meta comment described above. The UNOPTFLAT warning may also occur where outputs from a block of logic @@ -4960,10 +4996,10 @@ design simulate incorrectly; see the details under --bbox-unsup. =item UNUSED -Warns that the specified signal is never used/consumed. Verilator is -fairly liberal in the usage calculations; making a signal public, a signal -matching --unused-regexp ("*unused*") or accessing only a single array -element marks the entire signal as used. +Warns that the specified signal or parameter is never used/consumed. +Verilator is fairly liberal in the usage calculations; making a signal +public, a signal matching --unused-regexp ("*unused*") or accessing only a +single array element marks the entire signal as used. Disabled by default as this is a code style warning; it will simulate correctly. @@ -5476,21 +5512,21 @@ by your code or you'll get strange results. =item Should a module be in Verilog or SystemC? -Sometimes there is a block that just interconnects cells, and have a choice -as to if you write it in Verilog or SystemC. Everything else being equal, -best performance is when Verilator sees all of the design. So, look at the -hierarchy of your design, labeling cells as to if they are SystemC or -Verilog. Then: +Sometimes there is a block that just interconnects instances, and have a +choice as to if you write it in Verilog or SystemC. Everything else being +equal, best performance is when Verilator sees all of the design. So, look +at the hierarchy of your design, labeling instances as to if they are +SystemC or Verilog. Then: -A module with only SystemC cells below must be SystemC. +A module with only SystemC instances below must be SystemC. -A module with a mix of Verilog and SystemC cells below must be SystemC. (As -Verilator cannot connect to lower-level SystemC cells.) +A module with a mix of Verilog and SystemC instances below must be +SystemC. (As Verilator cannot connect to lower-level SystemC instances.) -A module with only Verilog cells below can be either, but for best +A module with only Verilog instances below can be either, but for best performance should be Verilog. (The exception is if you have a design that is instantiated many times; in this case Verilating one of the lower -modules and instantiating that Verilated cells multiple times into a +modules and instantiating that Verilated instances multiple times into a SystemC module *may* be faster.) =back @@ -5679,7 +5715,7 @@ remain anonymous. The latest version is available from L. -Copyright 2003-2020 by Wilson Snyder. This program is free software; you can +Copyright 2003-2021 by Wilson Snyder. This program is free software; you can redistribute it and/or modify the Verilator internals under the terms of either the GNU Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. diff --git a/bin/verilator_coverage b/bin/verilator_coverage index e3d0bf45e..bd0fee254 100755 --- a/bin/verilator_coverage +++ b/bin/verilator_coverage @@ -1,7 +1,7 @@ #!/usr/bin/env perl ###################################################################### # -# Copyright 2003-2020 by Wilson Snyder. This program is free software; you +# Copyright 2003-2021 by Wilson Snyder. This program is free software; you # can redistribute it and/or modify it under the terms of either the GNU # Lesser General Public License Version 3 or the Perl Artistic License # Version 2.0. @@ -278,7 +278,7 @@ Specifies a module search directory. The latest version is available from L. -Copyright 2003-2020 by Wilson Snyder. This program is free software; you +Copyright 2003-2021 by Wilson Snyder. This program is free software; you can redistribute it and/or modify the Verilator internals under the terms of either the GNU Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. diff --git a/bin/verilator_difftree b/bin/verilator_difftree index aa22b4534..4b181318f 100755 --- a/bin/verilator_difftree +++ b/bin/verilator_difftree @@ -208,7 +208,7 @@ Do not show differences in line numbering. The latest version is available from L. -Copyright 2005-2020 by Wilson Snyder. This program is free software; you +Copyright 2005-2021 by Wilson Snyder. This program is free software; you can redistribute it and/or modify it under the terms of either the GNU Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. diff --git a/bin/verilator_gantt b/bin/verilator_gantt index 1de46b104..ac9683385 100755 --- a/bin/verilator_gantt +++ b/bin/verilator_gantt @@ -617,7 +617,7 @@ verilator_gantt.vcd. The latest version is available from L. -Copyright 2018-2020 by Wilson Snyder. This program is free software; you +Copyright 2018-2021 by Wilson Snyder. This program is free software; you can redistribute it and/or modify it under the terms of either the GNU Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. diff --git a/bin/verilator_includer b/bin/verilator_includer index 182d2f7d7..d6c26860b 100755 --- a/bin/verilator_includer +++ b/bin/verilator_includer @@ -1,7 +1,7 @@ #!/usr/bin/env perl # DESCRIPTION: Print include statements for each ARGV # -# Copyright 2003-2020 by Wilson Snyder. This program is free software; you +# Copyright 2003-2021 by Wilson Snyder. This program is free software; you # can redistribute it and/or modify it under the terms of either the GNU # Lesser General Public License Version 3 or the Perl Artistic License # Version 2.0. diff --git a/bin/verilator_profcfunc b/bin/verilator_profcfunc index f69a5124b..c8a29be83 100755 --- a/bin/verilator_profcfunc +++ b/bin/verilator_profcfunc @@ -228,7 +228,7 @@ Displays this message and program version and exits. The latest version is available from L. -Copyright 2007-2020 by Wilson Snyder. This program is free software; you +Copyright 2007-2021 by Wilson Snyder. This program is free software; you can redistribute it and/or modify it under the terms of either the GNU Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. diff --git a/ci/travis-ccache-maint.bash b/ci/ci-ccache-maint.bash similarity index 79% rename from ci/travis-ccache-maint.bash rename to ci/ci-ccache-maint.bash index a8f2ddfc0..0c0cf00e6 100755 --- a/ci/travis-ccache-maint.bash +++ b/ci/ci-ccache-maint.bash @@ -1,5 +1,5 @@ #!/usr/bin/env bash -# DESCRIPTION: Verilator: Travis CI ccache maintenance +# DESCRIPTION: Verilator: CI ccache maintenance # # Copyright 2020 by Geza Lore. This program is free software; you # can redistribute it and/or modify it under the terms of either the GNU @@ -19,8 +19,8 @@ set -x ccache --version # Flush ccache if requested in commit message -COMMIT="${TRAVIS_PULL_REQUEST_SHA:-$TRAVIS_COMMIT}" -if git log --format=%B -n 1 "$COMMIT" | grep -q -i '\[travis\s\+ccache\s\+clear\]'; then +COMMIT="${CI_PULL_REQUEST_SHA:-$CI_COMMIT}" +if git log --format=%B -n 1 "$COMMIT" | grep -q -i '\[CI\s\+ccache\s\+clear\]'; then echo "Flushing ccache due to commit message" ccache -C fi diff --git a/ci/travis-install.bash b/ci/ci-install.bash similarity index 62% rename from ci/travis-install.bash rename to ci/ci-install.bash index 9178e66b5..ff0719f4e 100755 --- a/ci/travis-install.bash +++ b/ci/ci-install.bash @@ -1,5 +1,5 @@ #!/usr/bin/env bash -# DESCRIPTION: Verilator: Travis CI dependency install script +# DESCRIPTION: Verilator: CI dependency install script # # Copyright 2020 by Geza Lore. This program is free software; you # can redistribute it and/or modify it under the terms of either the GNU @@ -14,25 +14,23 @@ # required by the particular build stage. ################################################################################ -# Note that Travis runs "apt-get update" when "apt-get install" is used in the -# .travis.yml file directly, but since we invoke it via this script, we need to -# run it manually where requried, otherwise some packages cannot be found. - set -e set -x +cd $(dirname "$0")/.. + fatal() { echo "ERROR: $(basename "$0"): $1" >&2; exit 1; } -if [ "$TRAVIS_OS_NAME" = "linux" ]; then +if [ "$CI_OS_NAME" = "linux" ]; then MAKE=make -elif [ "$TRAVIS_OS_NAME" = "osx" ]; then +elif [ "$CI_OS_NAME" = "osx" ]; then MAKE=make -elif [ "$TRAVIS_OS_NAME" = "freebsd" ]; then +elif [ "$CI_OS_NAME" = "freebsd" ]; then MAKE=gmake else - fatal "Unknown os: '$TRAVIS_OS_NAME'" + fatal "Unknown os: '$CI_OS_NAME'" fi install-vcddiff() { @@ -43,61 +41,71 @@ install-vcddiff() { sudo cp "${TMP_DIR}/vcddiff" /usr/local/bin } -if [ "$TRAVIS_BUILD_STAGE_NAME" = "build" ]; then +if [ "$CI_BUILD_STAGE_NAME" = "build" ]; then ############################################################################## # Dependencies of jobs in the 'build' stage, i.e.: packages required to # build Verilator - if [ "$TRAVIS_OS_NAME" = "linux" ]; then + if [ "$CI_OS_NAME" = "linux" ]; then sudo apt-get update - sudo apt-get install libfl-dev - sudo apt-get install libgoogle-perftools-dev + sudo apt-get install libfl-dev libgoogle-perftools-dev ccache + if [ "$CI_RUNS_ON" = "ubuntu-20.04" ]; then + sudo apt-get install libsystemc libsystemc-dev + fi if [ "$COVERAGE" = 1 ]; then - yes yes | sudo cpan -fi Unix::Processors Parallel::Forker + yes yes | sudo cpan -fi Parallel::Forker fi if [ "$M32" = 1 ]; then sudo apt-get install gcc-multilib g++-multilib fi - elif [ "$TRAVIS_OS_NAME" = "osx" ]; then + elif [ "$CI_OS_NAME" = "osx" ]; then brew update brew install ccache perl gperftools - elif [ "$TRAVIS_OS_NAME" = "freebsd" ]; then + elif [ "$CI_OS_NAME" = "freebsd" ]; then sudo pkg install -y autoconf bison ccache gmake perl5 else - fatal "Unknown os: '$TRAVIS_OS_NAME'" + fatal "Unknown os: '$CI_OS_NAME'" fi -elif [ "$TRAVIS_BUILD_STAGE_NAME" = "test" ]; then + + if [ -n "$CCACHE_DIR" ]; then + mkdir -p "$CCACHE_DIR" && ./ci/ci-ccache-maint.bash + fi +elif [ "$CI_BUILD_STAGE_NAME" = "test" ]; then ############################################################################## # Dependencies of jobs in the 'test' stage, i.e.: packages required to # run the tests - if [ "$TRAVIS_OS_NAME" = "linux" ]; then + if [ "$CI_OS_NAME" = "linux" ]; then sudo apt-get update - sudo apt-get install gdb gtkwave lcov - if [ "$TRAVIS_DIST" = "focal" ]; then + # libfl-dev needed for internal coverage's test runs + sudo apt-get install gdb gtkwave lcov libfl-dev ccache + if [ "$CI_RUNS_ON" = "ubuntu-20.04" ]; then sudo apt-get install libsystemc-dev fi if [ "$M32" = 1 ]; then sudo apt-get install lib32z1-dev gcc-multilib g++-multilib fi - elif [ "$TRAVIS_OS_NAME" = "osx" ]; then + elif [ "$CI_OS_NAME" = "osx" ]; then brew update # brew cask install gtkwave # fst2vcd hangs at launch, so don't bother brew install ccache perl - elif [ "$TRAVIS_OS_NAME" = "freebsd" ]; then + elif [ "$CI_OS_NAME" = "freebsd" ]; then # fst2vcd fails with "Could not open '', exiting." sudo pkg install -y ccache gmake perl5 python3 else - fatal "Unknown os: '$TRAVIS_OS_NAME'" + fatal "Unknown os: '$CI_OS_NAME'" fi # Common installs - if [ "$TRAVIS_DIST" != "trusty" ]; then - TRAVIS_CPAN_REPO=https://cpan.org + if [ "$CI_RUNS_ON" != "ubuntu-14.04" ]; then + CI_CPAN_REPO=https://cpan.org fi - yes yes | sudo cpan -M $TRAVIS_CPAN_REPO -fi Unix::Processors Parallel::Forker + yes yes | sudo cpan -M $CI_CPAN_REPO -fi Parallel::Forker install-vcddiff + + autoconf + ./configure --enable-longtests --enable-ccwarn else ############################################################################## # Unknown build stage - fatal "Unknown build stage: '$TRAVIS_BUILD_STAGE_NAME'" + fatal "Unknown build stage: '$CI_BUILD_STAGE_NAME'" fi diff --git a/ci/travis-script.bash b/ci/ci-script.bash similarity index 74% rename from ci/travis-script.bash rename to ci/ci-script.bash index b1405c9f0..bcfc24285 100755 --- a/ci/travis-script.bash +++ b/ci/ci-script.bash @@ -1,5 +1,5 @@ #!/usr/bin/env bash -# DESCRIPTION: Verilator: Travis CI main job script +# DESCRIPTION: Verilator: CI main job script # # Copyright 2020 by Geza Lore. This program is free software; you # can redistribute it and/or modify it under the terms of either the GNU @@ -10,9 +10,8 @@ ################################################################################ # This is the main script executed in the 'script' phase by all jobs. We use a -# single script to keep the .travis.yml spec simple. We pass job parameters via -# environment variables using 'env' keys. Having different 'env' keys in jobs -# ensures they use different Travis build caches. +# single script to keep the CI setting simple. We pass job parameters via +# environment variables using 'env' keys. ################################################################################ set -e @@ -22,20 +21,20 @@ fatal() { echo "ERROR: $(basename "$0"): $1" >&2; exit 1; } -if [ "$TRAVIS_OS_NAME" = "linux" ]; then +if [ "$CI_OS_NAME" = "linux" ]; then export MAKE=make NPROC=$(nproc) -elif [ "$TRAVIS_OS_NAME" = "osx" ]; then +elif [ "$CI_OS_NAME" = "osx" ]; then export MAKE=make NPROC=$(sysctl -n hw.logicalcpu) -elif [ "$TRAVIS_OS_NAME" = "freebsd" ]; then +elif [ "$CI_OS_NAME" = "freebsd" ]; then export MAKE=gmake NPROC=$(sysctl -n hw.ncpu) else - fatal "Unknown os: '$TRAVIS_OS_NAME'" + fatal "Unknown os: '$CI_OS_NAME'" fi -if [ "$TRAVIS_BUILD_STAGE_NAME" = "build" ]; then +if [ "$CI_BUILD_STAGE_NAME" = "build" ]; then ############################################################################## # Build verilator @@ -43,7 +42,7 @@ if [ "$TRAVIS_BUILD_STAGE_NAME" = "build" ]; then autoconf ./configure --enable-longtests --enable-ccwarn "$MAKE" -j "$NPROC" -k - if [ "$TRAVIS_OS_NAME" = "osx" ]; then + if [ "$CI_OS_NAME" = "osx" ]; then file bin/verilator_bin file bin/verilator_bin_dbg md5 bin/verilator_bin @@ -54,13 +53,15 @@ if [ "$TRAVIS_BUILD_STAGE_NAME" = "build" ]; then else nodist/code_coverage --stages 1-2 fi -elif [ "$TRAVIS_BUILD_STAGE_NAME" = "test" ]; then +elif [ "$CI_BUILD_STAGE_NAME" = "test" ]; then ############################################################################## # Run tests - if [ "$TRAVIS_OS_NAME" = "osx" ]; then - export VERILATOR_TEST_NO_GDB=1 # Pain to get GDB to work on OS X - export VERILATOR_TEST_NO_GPROF=1 # Apple Clang has no -pg + export VERILATOR_TEST_NO_CONTRIBUTORS=1 # Separate workflow check + + if [ "$CI_OS_NAME" = "osx" ]; then + export VERILATOR_TEST_NO_GDB=1 # Pain to get GDB to work on OS X + export VERILATOR_TEST_NO_GPROF=1 # Apple Clang has no -pg # export PATH="/Applications/gtkwave.app/Contents/Resources/bin:$PATH" # fst2vcd file bin/verilator_bin file bin/verilator_bin_dbg @@ -70,21 +71,24 @@ elif [ "$TRAVIS_BUILD_STAGE_NAME" = "test" ]; then stat bin/verilator_bin_dbg # For some reason, the dbg exe is corrupted by this point ('file' reports # it as data rather than a Mach-O). Unclear if this is an OS X issue or - # one for Travis. Remove the file and re-link... + # CI's. Remove the file and re-link... rm bin/verilator_bin_dbg "$MAKE" -j "$NPROC" -k - elif [ "$TRAVIS_OS_NAME" = "freebsd" ]; then + elif [ "$CI_OS_NAME" = "freebsd" ]; then export VERILATOR_TEST_NO_GDB=1 # Disable for now, ideally should run export VERILATOR_TEST_NO_GPROF=1 # gprof is a bit different on FreeBSD, disable fi + # Run sanitize on Ubuntu 20.04 only + [ "$CI_RUNS_ON" = 'ubuntu-20.04' ] && sanitize='--sanitize' || sanitize='' + # Run the specified test case $TESTS in dist-vlt-0) - "$MAKE" -C test_regress SCENARIOS="--dist --vlt" DRIVER_HASHSET=--hashset=0/2 + "$MAKE" -C test_regress SCENARIOS="--dist --vlt $sanitize" DRIVER_HASHSET=--hashset=0/2 ;; dist-vlt-1) - "$MAKE" -C test_regress SCENARIOS="--dist --vlt" DRIVER_HASHSET=--hashset=1/2 + "$MAKE" -C test_regress SCENARIOS="--dist --vlt $sanitize" DRIVER_HASHSET=--hashset=1/2 ;; vltmt-0) "$MAKE" -C test_regress SCENARIOS=--vltmt DRIVER_HASHSET=--hashset=0/2 @@ -92,6 +96,9 @@ elif [ "$TRAVIS_BUILD_STAGE_NAME" = "test" ]; then vltmt-1) "$MAKE" -C test_regress SCENARIOS=--vltmt DRIVER_HASHSET=--hashset=1/2 ;; + coverage-all) + nodist/code_coverage --stages 3- + ;; coverage-dist) nodist/code_coverage --stages 3- --scenarios=--dist ;; @@ -130,5 +137,5 @@ elif [ "$TRAVIS_BUILD_STAGE_NAME" = "test" ]; then else ############################################################################## # Unknown build stage - fatal "Unknown build stage: '$TRAVIS_BUILD_STAGE_NAME'" + fatal "Unknown build stage: '$CI_BUILD_STAGE_NAME'" fi diff --git a/ci/docker/buildenv/Dockerfile b/ci/docker/buildenv/Dockerfile index 6f9dd3539..7e6682357 100644 --- a/ci/docker/buildenv/Dockerfile +++ b/ci/docker/buildenv/Dockerfile @@ -40,7 +40,7 @@ RUN apt-get update \ WORKDIR /tmp -RUN cpan install -fi Unix::Processors Parallel::Forker +RUN cpan install -fi Parallel::Forker RUN git clone https://github.com/veripool/vcddiff.git && \ make -C vcddiff && \ diff --git a/ci/docker/run/verilator-wrap.sh b/ci/docker/run/verilator-wrap.sh index aa7a3be60..80d839b5b 100755 --- a/ci/docker/run/verilator-wrap.sh +++ b/ci/docker/run/verilator-wrap.sh @@ -27,5 +27,5 @@ if [ -e ${obj_dir} ]; then cp -r /usr/local/share/verilator/bin ${obj_dir}/vlt cp -r /usr/local/share/verilator/include ${obj_dir}/vlt # Point Makefile to that folder - perl -i -pe 's/VERILATOR_ROOT = \/usr\/local\/share\/verilator/VERILATOR_ROOT = vlt/g' ${obj_dir}/*.mk + sed -i 's/VERILATOR_ROOT = \/usr\/local\/share\/verilator/VERILATOR_ROOT = vlt/g' ${obj_dir}/*.mk fi diff --git a/ci/travis-ccache-size.bash b/ci/travis-ccache-size.bash deleted file mode 100755 index 60a5b412d..000000000 --- a/ci/travis-ccache-size.bash +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env bash -# DESCRIPTION: Verilator: Travis CI ccache sizer -# -# Copyright 2020 by Geza Lore. This program is free software; you -# can redistribute it and/or modify it under the terms of either the GNU -# Lesser General Public License Version 3 or the Perl Artistic License -# Version 2.0. -# -# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 - -################################################################################ -# This script computes the size of the ccache to be used for a job. We want the -# ccache to be just big enough to be able to hold a whole build so a re-build -# of the same does not miss in the cache due to capacity, but we don't want the -# ccache too big as pulling it down from the network takes time, and it is -# unlikely objects from much earlier builds would be useful. -################################################################################ - -fatal() { - echo "ERROR: $(basename "$0"): $1" >&2; exit 1; -} - -if [ "$TRAVIS_BUILD_STAGE_NAME" = "build" ]; then - if [ "$COVERAGE" == 1 ]; then - echo "1024M" - else - echo "768M" - fi -elif [ "$TRAVIS_BUILD_STAGE_NAME" = "test" ]; then - if [[ $TESTS == coverage-* ]]; then - echo "1536M" - else - echo "256M" - fi -else - fatal "Unknown build stage: '$TRAVIS_BUILD_STAGE_NAME'" -fi diff --git a/codecov.yml b/codecov.yml index 91e26fb48..c4e52ff0d 100644 --- a/codecov.yml +++ b/codecov.yml @@ -1,6 +1,6 @@ # DESCRIPTION: codecov.io config # -# Copyright 2020-2020 by Wilson Snyder. This program is free software; you +# Copyright 2020-2021 by Wilson Snyder. This program is free software; you # can redistribute it and/or modify it under the terms of either the GNU # Lesser General Public License Version 3 or the Perl Artistic License # Version 2.0. @@ -15,7 +15,7 @@ codecov: coverage: precision: 2 round: down - range: "70...100" + range: "50...100" ignore: - "ci" - "docs" diff --git a/configure.ac b/configure.ac index 563c93a29..f3c39b4bd 100644 --- a/configure.ac +++ b/configure.ac @@ -1,13 +1,13 @@ # DESCRIPTION: Process this file with autoconf to produce a configure script. # -# Copyright 2003-2020 by Wilson Snyder. Verilator is free software; you +# Copyright 2003-2021 by Wilson Snyder. Verilator is free software; you # can redistribute it and/or modify it under the terms of either the GNU Lesser # General Public License Version 3 or the Perl Artistic License Version 2.0. # SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 #AC_INIT([Verilator],[#.### YYYY-MM-DD]) #AC_INIT([Verilator],[#.### devel]) -AC_INIT([Verilator],[4.106 2020-12-02], +AC_INIT([Verilator],[4.108 2021-01-10], [https://verilator.org], [verilator],[https://verilator.org]) # When releasing, also update header of Changes file @@ -139,6 +139,11 @@ if test "x$PERL" = "x" ; then AC_MSG_ERROR([Cannot find "perl" in your PATH, please install it]) fi +AC_PATH_PROG(PYTHON3,python3) +if test "x$PYTHON3" = "x" ; then + AC_MSG_ERROR([Cannot find "python3" in your PATH, please install it]) +fi + AC_PATH_PROG(LEX,flex) if test "x$LEX" = "x" ; then AC_MSG_ERROR([Cannot find "flex" in your PATH, please install it]) diff --git a/docs/CONTRIBUTING.adoc b/docs/CONTRIBUTING.adoc index e205d80b0..eda1108e6 100644 --- a/docs/CONTRIBUTING.adoc +++ b/docs/CONTRIBUTING.adoc @@ -27,8 +27,8 @@ contributions flow more efficiently. * You may attach a patch to the issue, or (preferred) may request a GitHub pull request. -** Verilator uses Travis CI to provide continuous integration. You may - want to setup Travis CI on your GitHub branch to ensure your changes +** Verilator uses GitHub Actions to provide continuous integration. You may + want to enable Actions on your GitHub branch to ensure your changes keep the tests passing. See link:internals.adoc[docs/internals]. * Your source-code contributions must be certified as open source, under diff --git a/docs/CONTRIBUTORS b/docs/CONTRIBUTORS index 4d7c136a9..67b634c82 100644 --- a/docs/CONTRIBUTORS +++ b/docs/CONTRIBUTORS @@ -49,9 +49,11 @@ Marshal Qiao Matthew Ballance Michael Killough Mike Popoloski +Nandu Raj Nathan Kohagen Nathan Myers Patrick Stewart +Paul Wright Peter Horvath Peter Monsson Philipp Wagner @@ -72,6 +74,7 @@ Tobias Wölfel Todd Strader Tomasz Gorochowik Tymoteusz Blazejczyk +Unai Martinez-Corral Victor Besyakov Vassilis Papaefstathiou Veripool API Bot @@ -80,3 +83,4 @@ Yossi Nivin Yuri Victorovich Yutetsu TAKATSUKASA Yves Mathieu +HyungKi Jeong diff --git a/docs/Makefile.in b/docs/Makefile.in index 3f68f1ebb..8c755ab43 100644 --- a/docs/Makefile.in +++ b/docs/Makefile.in @@ -7,7 +7,7 @@ # #***************************************************************************** # -# Copyright 2003-2020 by Wilson Snyder. This program is free software; you +# Copyright 2003-2021 by Wilson Snyder. This program is free software; you # can redistribute it and/or modify it under the terms of either the GNU # Lesser General Public License Version 3 or the Perl Artistic License # Version 2.0. diff --git a/docs/TODO b/docs/TODO index 357a15b28..ce1b15083 100644 --- a/docs/TODO +++ b/docs/TODO @@ -1,6 +1,6 @@ // DESCRIPTION: Verilator: List of To Do issues. // -// Copyright 2004-2020 by Wilson Snyder. This program is free software; you can +// Copyright 2004-2021 by Wilson Snyder. This program is free software; you can // redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -84,7 +84,7 @@ "if (a) { ... b=2; } else { ... b=2;}" -> "b=2; if ..." Careful though, as b could appear in the statement or multiple times in statement (Could just require exatly two 'b's in statement) -** Simplify XOR/XNOR/AND/OR bit selection trees +** Simplify XOR/AND/OR bit selection trees Foo = A[1] ^ A[2] ^ A[3] etc are better as ^ ( A & 32'b...1110 ) ** Combine variables into wider elements Parallel statements on different bits should become single signal diff --git a/docs/install.adoc b/docs/install.adoc index 65ae632f3..2cf4498b6 100644 --- a/docs/install.adoc +++ b/docs/install.adoc @@ -100,7 +100,6 @@ Those developing Verilator itself may also want these (see internals.adoc): sudo apt-get install gdb asciidoctor graphviz cmake clang clang-format gprof lcov cpan install Pod::Perldoc - cpan install Unix::Processors cpan install Parallel::Forker ==== Install SystemC @@ -298,7 +297,7 @@ or https://verilator.org/verilator_doc.pdf[Verilator manual (PDF)]. == License -Copyright 2008-2020 by Wilson Snyder. Verilator is free software; you can +Copyright 2008-2021 by Wilson Snyder. Verilator is free software; you can redistribute it and/or modify it under the terms of either the GNU Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. // SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 diff --git a/docs/internals.adoc b/docs/internals.adoc index aab4d8099..0a2f64909 100644 --- a/docs/internals.adoc +++ b/docs/internals.adoc @@ -409,8 +409,9 @@ style indentation; the `c-set-style` undoes that.) * Comment every member variable. -Indentation is automatically maintained with "make clang-format" (using -clang-format version 10.0.0). For those manually formatting: +Indentation is automatically maintained with "make format" using +clang-format version 10.0.0, and yapf for python, and is automatically +corrected in the CI actions. For those manually formatting C++ code: * Use 4 spaces per level, and no tabs. @@ -696,7 +697,7 @@ Verilator problem. When enabling the long tests, some additional PERL modules are needed, which you can install using cpan. - cpan install Unix::Processors + cpan install Parallel::Forker There are some traps to avoid when running regression tests @@ -728,20 +729,17 @@ test, run the following command. === Continuous Integration -Verilator has a https://travis-ci.com/verilator/verilator[Travis CI environment] -which automatically tests the master branch for test failures on new commits. It -also runs a daily cron job to validate all of the tests against different OS and -compiler versions. +Verilator uses GitHub Actions which automatically tests the master branch +for test failures on new commits. It also runs a daily cron job to validate +all of the tests against different OS and compiler versions. -Developers can connect Travis CI to their GitHub account so that the CI -environment can check their branches too by doing the following: +Developers can enable Actions on their GitHub repository so that the CI +environment can check their branches too by enabling the build workflow: -* Go to https://github.com/marketplace/travis-ci and follow the prompts - -* Only the Open Source (FREE) version of Travis CI is required - -* Under a Travis CI project click More options > Settings in order to set up a -cron job on a particular branch +* On GitHub, navigate to the main page of the repository. +* Under your repository name, click Actions. +* In the left sidebar, click the workflow you want to enable ("build"). +* Click Enable workflow. === Fuzzing @@ -1026,7 +1024,7 @@ IEEE 1800-2017 33 Config:: Little/no tool support or industry use. == Distribution -Copyright 2008-2020 by Wilson Snyder. Verilator is free software; you can +Copyright 2008-2021 by Wilson Snyder. Verilator is free software; you can redistribute it and/or modify it under the terms of either the GNU Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. // SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 diff --git a/docs/xml.adoc b/docs/xml.adoc index 0189b44cf..b200e5de3 100644 --- a/docs/xml.adoc +++ b/docs/xml.adoc @@ -66,7 +66,7 @@ elements in the `` elements using the `dtype_id` attribute. == Distribution -Copyright 2020-2020 by Wilson Snyder. Verilator is free software; you can +Copyright 2020-2021 by Wilson Snyder. Verilator is free software; you can redistribute it and/or modify it under the terms of either the GNU Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. // SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 diff --git a/examples/make_hello_c/sim_main.cpp b/examples/make_hello_c/sim_main.cpp index 17cd87887..e95be4fa6 100644 --- a/examples/make_hello_c/sim_main.cpp +++ b/examples/make_hello_c/sim_main.cpp @@ -37,6 +37,6 @@ int main(int argc, char** argv, char** env) { // Destroy model delete top; - // Fin + // Return good completion status exit(0); } diff --git a/examples/make_hello_sc/sc_main.cpp b/examples/make_hello_sc/sc_main.cpp index 208ba582b..6fef7ca31 100644 --- a/examples/make_hello_sc/sc_main.cpp +++ b/examples/make_hello_sc/sc_main.cpp @@ -33,12 +33,13 @@ int sc_main(int argc, char* argv[]) { // Simulate until $finish while (!Verilated::gotFinish()) { + // Simulate 1ns sc_start(1, SC_NS); } // Final model cleanup top->final(); - // Fin + // Return good completion status return 0; } diff --git a/examples/make_protect_lib/sim_main.cpp b/examples/make_protect_lib/sim_main.cpp index d89aa3482..c7762ba54 100644 --- a/examples/make_protect_lib/sim_main.cpp +++ b/examples/make_protect_lib/sim_main.cpp @@ -13,7 +13,7 @@ #include "Vtop.h" #if VM_TRACE -# include +#include #endif vluint64_t main_time = 0; @@ -70,6 +70,6 @@ int main(int argc, char** argv, char** env) { delete top; top = nullptr; - // Fin + // Return good completion status exit(0); } diff --git a/examples/make_tracing_c/sim_main.cpp b/examples/make_tracing_c/sim_main.cpp index 571df64a8..bcd853162 100644 --- a/examples/make_tracing_c/sim_main.cpp +++ b/examples/make_tracing_c/sim_main.cpp @@ -5,6 +5,9 @@ // SPDX-License-Identifier: CC0-1.0 //====================================================================== +// For std::unique_ptr +#include + // Include common routines #include @@ -43,7 +46,8 @@ int main(int argc, char** argv, char** env) { Verilated::mkdir("logs"); // Construct the Verilated model, from Vtop.h generated from Verilating "top.v" - Vtop* top = new Vtop; // Or use a const unique_ptr, or the VL_UNIQUE_PTR wrapper + // Using unique_ptr is similar to "Vtop* top = new Vtop" then deleting at end + const std::unique_ptr top{new Vtop}; // Set some inputs top->reset_l = !0; @@ -97,10 +101,6 @@ int main(int argc, char** argv, char** env) { VerilatedCov::write("logs/coverage.dat"); #endif - // Destroy model - delete top; - top = nullptr; - - // Fin + // Return good completion status exit(0); } diff --git a/examples/make_tracing_sc/sc_main.cpp b/examples/make_tracing_sc/sc_main.cpp index 9df44e1e1..4f7628113 100644 --- a/examples/make_tracing_sc/sc_main.cpp +++ b/examples/make_tracing_sc/sc_main.cpp @@ -6,6 +6,9 @@ // SPDX-License-Identifier: CC0-1.0 //====================================================================== +// For std::unique_ptr +#include + // SystemC global header #include @@ -45,20 +48,22 @@ int sc_main(int argc, char* argv[]) { ios::sync_with_stdio(); // Define clocks - sc_clock clk("clk", 10, SC_NS, 0.5, 3, SC_NS, true); - sc_clock fastclk("fastclk", 2, SC_NS, 0.5, 2, SC_NS, true); + sc_clock clk{"clk", 10, SC_NS, 0.5, 3, SC_NS, true}; + sc_clock fastclk{"fastclk", 2, SC_NS, 0.5, 2, SC_NS, true}; // Define interconnect sc_signal reset_l; sc_signal in_small; sc_signal in_quad; - sc_signal > in_wide; + sc_signal> in_wide; sc_signal out_small; sc_signal out_quad; - sc_signal > out_wide; + sc_signal> out_wide; // Construct the Verilated model, from inside Vtop.h - Vtop* top = new Vtop("top"); + // Using unique_ptr is similar to "Vtop* top = new Vtop" then deleting at end + const std::unique_ptr top{new Vtop{"top"}}; + // Attach signals to the model top->clk(clk); top->fastclk(fastclk); @@ -129,10 +134,6 @@ int sc_main(int argc, char* argv[]) { VerilatedCov::write("logs/coverage.dat"); #endif - // Destroy model - delete top; - top = nullptr; - - // Fin + // Return good completion status return 0; } diff --git a/examples/xml_py/Makefile b/examples/xml_py/Makefile index 8180c0650..1a6f5cd38 100644 --- a/examples/xml_py/Makefile +++ b/examples/xml_py/Makefile @@ -22,9 +22,9 @@ VERILATOR = $(VERILATOR_ROOT)/bin/verilator endif DOT = dot -PYTHON = python3 +PYTHON3 = python3 -PYTHON_VERSION := $(shell ${PYTHON} --version 2>&1) +PYTHON_VERSION := $(shell ${PYTHON3} --version 2>&1) PYTHON_VERSION_FULL := $(wordlist 2,4,$(subst ., ,${PYTHON_VERSION})) PYTHON_VERSION_MAJOR := $(word 1,${PYTHON_VERSION_FULL}) PYTHON_VERSION_MINOR := $(word 2,${PYTHON_VERSION_FULL}) @@ -45,13 +45,13 @@ test: \ test-vl_file_copy: @echo "-- vl_file_copy example" - $(PYTHON) vl_file_copy -odir copied top.v + $(PYTHON3) vl_file_copy -odir copied top.v @cmp copied/top.v top.v @cmp copied/sub.v sub.v test-vl_hier_graph: @echo "-- vl_hier_graph example" - $(PYTHON) vl_hier_graph -o graph.dot top.v + $(PYTHON3) vl_hier_graph -o graph.dot top.v @echo "Manually run: " $(DOT) -Tpdf -o graph.pdf graph.dot ###################################################################### diff --git a/examples/xml_py/vl_file_copy b/examples/xml_py/vl_file_copy index 0a5125c2a..d3f46629d 100755 --- a/examples/xml_py/vl_file_copy +++ b/examples/xml_py/vl_file_copy @@ -10,24 +10,29 @@ import sys import tempfile import xml.etree.ElementTree as ET from shutil import copy2 -from pprint import pprint,pformat +from pprint import pprint, pformat ####################################################################### + class VlFileCopy: - def __init__(self, - verilator_args, # presently all verilator options are passed-thru - # ideally this script would check against options mentioned in help - debug=0, - output_dir='copied'): # directory name we output file uses + def __init__( + self, + verilator_args, # presently all verilator options are passed-thru + # ideally this script would check against options mentioned in help + debug=0, + output_dir='copied'): # directory name we output file uses self.debug = debug xml_temp = tempfile.NamedTemporaryFile() - args = ['--xml-output', xml_temp.name, - '--bbox-sys', # Parse some stuff can't translate - '--bbox-unsup', - '--prefix vlxml'] # So we know name of .xml output + args = [ + '--xml-output', + xml_temp.name, + '--bbox-sys', # Parse some stuff can't translate + '--bbox-unsup', + '--prefix vlxml' + ] # So we know name of .xml output args += verilator_args self.run_verilator(args) self.tree = ET.parse(xml_temp.name) @@ -55,16 +60,18 @@ class VlFileCopy: print("\t%s " % command) status = subprocess.call(command, shell=True) if status != 0: - raise Exception("Command failed running Verilator with '"+command+"', stopped") + raise Exception("Command failed running Verilator with '" + + command + "', stopped") + ####################################################################### -if __name__=='__main__': +if __name__ == '__main__': parser = argparse.ArgumentParser( allow_abbrev=False, formatter_class=argparse.RawTextHelpFormatter, description= -"""Example of using Verilator XML output to copy a list of files to an + """Example of using Verilator XML output to copy a list of files to an output directory (-odir, defaults to 'copied'), e.g. to easily create a tarball of the design to pass to others. @@ -72,8 +79,7 @@ Example usage: vl_file_copy -f input.vc top.v -odir mycopy # This will make at least mycopy/top.v """, - epilog= -"""All other arguments are pass-thru to Verilator: e.g.: + epilog="""All other arguments are pass-thru to Verilator: e.g.: +define+= Set preprocessor define -F Parse options from a file, relatively @@ -87,26 +93,30 @@ Example usage: This file ONLY is placed under the Creative Commons Public Domain, for any use, without warranty, 2019 by Wilson Snyder. SPDX-License-Identifier: CC0-1.0 -""" - ) - parser.add_argument('-debug', '--debug', - action='store_const', const=9, +""") + parser.add_argument('-debug', + '--debug', + action='store_const', + const=9, help='enable debug') - parser.add_argument('-odir', '--odir', - action='store', metavar='directory', required=True, + parser.add_argument('-odir', + '--odir', + action='store', + metavar='directory', + required=True, help='target output directory') (args, rem) = parser.parse_known_args() - print("NOTE: vl_file_copy is only an example starting point for writing your own tool.") + print( + "NOTE: vl_file_copy is only an example starting point for writing your own tool." + ) # That is: # 1. We will accept basic patches # 2. We are not expecting to make this globally useful. (e.g. we don't cleanup obj_dir) # 3. "make install" will not install this. # 4. This has not had production-worthy validation. - fc = VlFileCopy(output_dir = args.odir, - debug = args.debug, - verilator_args = rem) + fc = VlFileCopy(output_dir=args.odir, debug=args.debug, verilator_args=rem) ###################################################################### ### Local Variables: diff --git a/examples/xml_py/vl_hier_graph b/examples/xml_py/vl_hier_graph index 038518614..af9f83023 100755 --- a/examples/xml_py/vl_hier_graph +++ b/examples/xml_py/vl_hier_graph @@ -10,26 +10,31 @@ import sys import tempfile import xml.etree.ElementTree as ET from shutil import copy2 -from pprint import pprint,pformat +from pprint import pprint, pformat ####################################################################### + class VlHierGraph: - def __init__(self, - verilator_args, # presently all verilator options are passed-thru - # ideally this script would check against options mentioned in help - debug=0, - output_filename='graph.dot'): # output filename + def __init__( + self, + verilator_args, # presently all verilator options are passed-thru + # ideally this script would check against options mentioned in help + debug=0, + output_filename='graph.dot'): # output filename self.debug = debug self.next_vertex_number = 0 self.name_to_number = {} xml_temp = tempfile.NamedTemporaryFile() - args = ['--xml-output', xml_temp.name, - '--bbox-sys', # Parse some stuff can't translate - '--bbox-unsup', - '--prefix vlxml'] # So we know name of .xml output + args = [ + '--xml-output', + xml_temp.name, + '--bbox-sys', # Parse some stuff can't translate + '--bbox-unsup', + '--prefix vlxml' + ] # So we know name of .xml output args += verilator_args self.run_verilator(args) self.tree = ET.parse(xml_temp.name) @@ -39,7 +44,9 @@ class VlHierGraph: fh.write("digraph {\n") fh.write(" dpi=300;\n") fh.write(" order=LR;\n") - fh.write(" node [fontsize=8 shape=\"box\" margin=0.01 width=0 height=0]") + fh.write( + " node [fontsize=8 shape=\"box\" margin=0.01 width=0 height=0]" + ) fh.write(" edge [fontsize=6]") # Find cells root = self.tree.getroot() @@ -48,8 +55,7 @@ class VlHierGraph: # origNames are before parameterization, name if after mod_name = module.get('name') mod_number = self.name_to_vertex_number(mod_name) - fh.write(" n%d [label=\"%s\"" - % (mod_number, mod_name)) + fh.write(" n%d [label=\"%s\"" % (mod_number, mod_name)) if module.get('topModule'): fh.write(" color=\"red\" rank=1") fh.write("];\n") @@ -58,8 +64,8 @@ class VlHierGraph: inst_name = instance.get('name') def_name = instance.get('defName') def_number = self.name_to_vertex_number(def_name) - fh.write(" n%d->n%d [label=\"%s\"];\n" - % (mod_number, def_number, inst_name)); + fh.write(" n%d->n%d [label=\"%s\"];\n" % + (mod_number, def_number, inst_name)) fh.write("}\n") @@ -80,24 +86,25 @@ class VlHierGraph: print("\t%s " % command) status = subprocess.call(command, shell=True) if status != 0: - raise Exception("Command failed running Verilator with '"+command+"', stopped") + raise Exception("Command failed running Verilator with '" + + command + "', stopped") + ####################################################################### -if __name__=='__main__': +if __name__ == '__main__': parser = argparse.ArgumentParser( allow_abbrev=False, formatter_class=argparse.RawTextHelpFormatter, description= -"""Example of using Verilator XML output to create a .dot file showing the + """Example of using Verilator XML output to create a .dot file showing the design module hierarchy. Example usage: vl_hier_graph -f input.vc top.v -o graph.dot dot -Tpdf -o graph.pdf graph.dot """, - epilog= -"""All other arguments are pass-thru to Verilator: e.g.: + epilog="""All other arguments are pass-thru to Verilator: e.g.: +define+= Set preprocessor define -F Parse options from a file, relatively @@ -111,26 +118,32 @@ Example usage: This file ONLY is placed under the Creative Commons Public Domain, for any use, without warranty, 2019 by Wilson Snyder. SPDX-License-Identifier: CC0-1.0 -""" - ) - parser.add_argument('-debug', '--debug', - action='store_const', const=9, +""") + parser.add_argument('-debug', + '--debug', + action='store_const', + const=9, help='enable debug') - parser.add_argument('-o', '--o', - action='store', metavar='filename', required=True, + parser.add_argument('-o', + '--o', + action='store', + metavar='filename', + required=True, help='output filename') (args, rem) = parser.parse_known_args() - print("NOTE: vl_hier_graph is only an example starting point for writing your own tool.") + print( + "NOTE: vl_hier_graph is only an example starting point for writing your own tool." + ) # That is: # 1. We will accept basic patches # 2. We are not expecting to make this globally useful. (e.g. we don't cleanup obj_dir) # 3. "make install" will not install this. # 4. This has not had production-worthy validation. - fc = VlHierGraph(output_filename = args.o, - debug = args.debug, - verilator_args = rem) + fc = VlHierGraph(output_filename=args.o, + debug=args.debug, + verilator_args=rem) ###################################################################### ### Local Variables: diff --git a/include/gtkwave/fstapi.c b/include/gtkwave/fstapi.c index d311c756d..3cb4652c9 100644 --- a/include/gtkwave/fstapi.c +++ b/include/gtkwave/fstapi.c @@ -1806,6 +1806,7 @@ xc->already_in_flush = 0; static void *fstWriterFlushContextPrivate1(void *ctx) { struct fstWriterContext *xc = (struct fstWriterContext *)ctx; +struct fstWriterContext *xc_parent; pthread_mutex_lock(&(xc->xc_parent->mutex)); fstWriterFlushContextPrivate2(xc); @@ -1816,10 +1817,11 @@ free(xc->curval_mem); free(xc->valpos_mem); free(xc->vchg_mem); tmpfile_close(&xc->tchn_handle, &xc->tchn_handle_nam); +xc_parent = xc->xc_parent; free(xc); -xc->xc_parent->in_pthread = 0; -pthread_mutex_unlock(&(xc->xc_parent->mutex)); +xc_parent->in_pthread = 0; +pthread_mutex_unlock(&(xc_parent->mutex)); return(NULL); } diff --git a/include/verilated.cpp b/include/verilated.cpp index 101054439..0a1bf95cd 100644 --- a/include/verilated.cpp +++ b/include/verilated.cpp @@ -1,7 +1,7 @@ // -*- mode: C++; c-file-style: "cc-mode" -*- //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you can +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you can // redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -72,10 +72,27 @@ Verilated::CommandArgValues Verilated::s_args; VerilatedImp::VerilatedImpU VerilatedImp::s_s; -struct VerilatedImpInitializer { - VerilatedImpInitializer() { VerilatedImp::setup(); } - ~VerilatedImpInitializer() { VerilatedImp::teardown(); } -} s_VerilatedImpInitializer; +// Guarantees to call setup() and teardown() just once. +struct VerilatedInitializer { + VerilatedInitializer() { setup(); } + ~VerilatedInitializer() { teardown(); } + void setup() { + static bool done = false; + if (!done) { + VerilatedImp::setup(); + Verilated::s_ns.setup(); + done = true; + } + } + void teardown() { + static bool done = false; + if (!done) { + VerilatedImp::teardown(); + Verilated::s_ns.teardown(); + done = true; + } + } +} s_VerilatedInitializer; //=========================================================================== // User definable functions @@ -261,10 +278,8 @@ Verilated::Serialized::Serialized() { s_timeprecision = VL_TIME_PRECISION; // Initial value until overriden by _Vconfigure } -Verilated::NonSerialized::NonSerialized() { - s_profThreadsFilenamep = strdup("profile_threads.dat"); -} -Verilated::NonSerialized::~NonSerialized() { +void Verilated::NonSerialized::setup() { s_profThreadsFilenamep = strdup("profile_threads.dat"); } +void Verilated::NonSerialized::teardown() { if (s_profThreadsFilenamep) { VL_DO_CLEAR(free(const_cast(s_profThreadsFilenamep)), s_profThreadsFilenamep = nullptr); @@ -2352,7 +2367,7 @@ static void removeCb(Verilated::VoidPCb cb, void* datap, VoidPCbList& cbs) { std::pair pair(cb, datap); cbs.remove(pair); } -static void runCallbacks(VoidPCbList& cbs) VL_MT_SAFE { +static void runCallbacks(const VoidPCbList& cbs) VL_MT_SAFE { for (const auto& i : cbs) i.first(i.second); } @@ -2478,22 +2493,10 @@ void Verilated::endOfEvalGuts(VerilatedEvalMsgQueue* evalMsgQp) VL_MT_SAFE { // // To avoid the trouble, all member variables are enclosed in VerilatedImpU union. // ctor nor dtor of members are not called automatically. -// VerilatedImp::setup() and teardown() guarantees to initialize/destruct just once. +// VerilatedInitializer::setup() and teardown() guarantees to initialize/destruct just once. -void VerilatedImp::setup() { - static bool done = false; - if (!done) { - new (&VerilatedImp::s_s) VerilatedImpData(); - done = true; - } -} -void VerilatedImp::teardown() { - static bool done = false; - if (!done) { - VerilatedImp::s_s.~VerilatedImpU(); - done = true; - } -} +void VerilatedImp::setup() { new (&VerilatedImp::s_s) VerilatedImpData(); } +void VerilatedImp::teardown() { VerilatedImp::s_s.~VerilatedImpU(); } //=========================================================================== // VerilatedImp:: Methods @@ -2640,7 +2643,7 @@ vluint32_t VerilatedVarProps::entSize() const { size_t VerilatedVarProps::totalSize() const { size_t size = entSize(); - for (int udim = 0; udim <= udims(); ++udim) size *= m_unpacked[udim].elements(); + for (int udim = 0; udim < udims(); ++udim) size *= m_unpacked[udim].elements(); return size; } @@ -2737,7 +2740,7 @@ void VerilatedScope::varInsert(int finalize, const char* namep, void* datap, boo } va_end(ap); - m_varsp->insert(std::make_pair(namep, var)); + m_varsp->emplace(namep, var); } // cppcheck-suppress unusedFunction // Used by applications @@ -2784,6 +2787,10 @@ void VerilatedHierarchy::add(VerilatedScope* fromp, VerilatedScope* top) { VerilatedImp::hierarchyAdd(fromp, top); } +void VerilatedHierarchy::remove(VerilatedScope* fromp, VerilatedScope* top) { + VerilatedImp::hierarchyRemove(fromp, top); +} + //=========================================================================== // VerilatedOneThreaded:: Methods diff --git a/include/verilated.h b/include/verilated.h index d8e8badb0..6abb68521 100644 --- a/include/verilated.h +++ b/include/verilated.h @@ -1,7 +1,7 @@ // -*- mode: C++; c-file-style: "cc-mode" -*- //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you can +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you can // redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -363,6 +363,7 @@ public: // But internals only - called from VerilatedModule's class VerilatedHierarchy final { public: static void add(VerilatedScope* fromp, VerilatedScope* top); + static void remove(VerilatedScope* fromp, VerilatedScope* top); }; //=========================================================================== @@ -399,8 +400,8 @@ class Verilated final { vluint32_t s_profThreadsWindow = 2; ///< +prof+threads window size // Slow path const char* s_profThreadsFilenamep; ///< +prof+threads filename - NonSerialized(); - ~NonSerialized(); + void setup(); + void teardown(); } s_ns; // no need to be save-restored (serialized) the @@ -429,6 +430,8 @@ class Verilated final { } t_s; private: + friend struct VerilatedInitializer; + // CONSTRUCTORS VL_UNCOPYABLE(Verilated); @@ -658,9 +661,9 @@ inline IData VL_URANDOM_RANGE_I(IData hi, IData lo) { vluint64_t rnd = vl_rand64(); if (VL_LIKELY(hi > lo)) { // Modulus isn't very fast but it's common that hi-low is power-of-two - return (rnd % (hi - lo)) + lo; + return (rnd % (hi - lo + 1)) + lo; } else { - return (rnd % (lo - hi)) + hi; + return (rnd % (lo - hi + 1)) + hi; } } @@ -1370,12 +1373,6 @@ static inline WDataOutP VL_XOR_W(int words, WDataOutP owp, WDataInP lwp, WDataIn for (int i = 0; (i < words); ++i) owp[i] = (lwp[i] ^ rwp[i]); return owp; } -// EMIT_RULE: VL_XNOR: oclean=dirty; obits=lbits; lbits==rbits; -static inline WDataOutP VL_XNOR_W(int words, WDataOutP owp, WDataInP lwp, - WDataInP rwp) VL_MT_SAFE { - for (int i = 0; (i < words); ++i) owp[i] = (lwp[i] ^ ~rwp[i]); - return owp; -} // EMIT_RULE: VL_NOT: oclean=dirty; obits=lbits; static inline WDataOutP VL_NOT_W(int words, WDataOutP owp, WDataInP lwp) VL_MT_SAFE { for (int i = 0; i < words; ++i) owp[i] = ~(lwp[i]); diff --git a/include/verilated.mk.in b/include/verilated.mk.in index eb6b2b72c..13930785d 100644 --- a/include/verilated.mk.in +++ b/include/verilated.mk.in @@ -2,7 +2,7 @@ ###################################################################### # DESCRIPTION: Makefile commands for all verilated target files # -# Copyright 2003-2020 by Wilson Snyder. This program is free software; you +# Copyright 2003-2021 by Wilson Snyder. This program is free software; you # can redistribute it and/or modify it under the terms of either the GNU # Lesser General Public License Version 3 or the Perl Artistic License # Version 2.0. diff --git a/include/verilated.v b/include/verilated.v index 4353c02cf..85bff0940 100644 --- a/include/verilated.v +++ b/include/verilated.v @@ -4,7 +4,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you can +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you can // redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/include/verilated_config.h.in b/include/verilated_config.h.in index 5075967a7..334781991 100644 --- a/include/verilated_config.h.in +++ b/include/verilated_config.h.in @@ -1,7 +1,7 @@ // -*- mode: C++; c-file-style: "cc-mode" -*- //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you can +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you can // redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/include/verilated_cov.cpp b/include/verilated_cov.cpp index 45f111cd9..f351c3140 100644 --- a/include/verilated_cov.cpp +++ b/include/verilated_cov.cpp @@ -3,7 +3,7 @@ // // THIS MODULE IS PUBLICLY LICENSED // -// Copyright 2001-2020 by Wilson Snyder. This program is free software; you +// Copyright 2001-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -123,8 +123,8 @@ private: if (iter != m_valueIndexes.end()) return iter->second; m_nextIndex++; assert(m_nextIndex > 0); // Didn't rollover - m_valueIndexes.insert(std::make_pair(value, m_nextIndex)); - m_indexValues.insert(std::make_pair(m_nextIndex, value)); + m_valueIndexes.emplace(value, m_nextIndex); + m_indexValues.emplace(m_nextIndex, value); return m_nextIndex; } static std::string dequote(const std::string& text) VL_PURE { @@ -390,7 +390,7 @@ public: cit->second.second += itemp->count(); cit->second.first = combineHier(oldhier, hier); } else { - eventCounts.insert(std::make_pair(name, make_pair(hier, itemp->count()))); + eventCounts.emplace(name, make_pair(hier, itemp->count())); } } diff --git a/include/verilated_cov.h b/include/verilated_cov.h index 331eed6c8..4fd213a7d 100644 --- a/include/verilated_cov.h +++ b/include/verilated_cov.h @@ -3,7 +3,7 @@ // // THIS MODULE IS PUBLICLY LICENSED // -// Copyright 2001-2020 by Wilson Snyder. This program is free software; you +// Copyright 2001-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/include/verilated_cov_key.h b/include/verilated_cov_key.h index 9a184a518..21e64b308 100644 --- a/include/verilated_cov_key.h +++ b/include/verilated_cov_key.h @@ -3,7 +3,7 @@ // // THIS MODULE IS PUBLICLY LICENSED // -// Copyright 2001-2020 by Wilson Snyder. This program is free software; you +// Copyright 2001-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -29,69 +29,27 @@ #define VLCOVGEN_ITEM(string_parsed_by_vlcovgen) // clang-format off -VLCOVGEN_ITEM("name=>'col0_name', short=>'C0', group=>1, default=>undef, descr=>'The column title for the header line of this column'") -VLCOVGEN_ITEM("name=>'col1_name', short=>'C1', group=>1, default=>undef, ") -VLCOVGEN_ITEM("name=>'col2_name', short=>'C2', group=>1, default=>undef, ") -VLCOVGEN_ITEM("name=>'col3_name', short=>'C3', group=>1, default=>undef, ") -VLCOVGEN_ITEM("name=>'column', short=>'n', group=>1, default=>0, descr=>'Column number for the item. Used to disambiguate multiple coverage points on the same line number'") -VLCOVGEN_ITEM("name=>'filename', short=>'f', group=>1, default=>undef, descr=>'Filename of the item'") -VLCOVGEN_ITEM("name=>'groupdesc', short=>'d', group=>1, default=>'', descr=>'Description of the covergroup this item belongs to'") -VLCOVGEN_ITEM("name=>'groupname', short=>'g', group=>1, default=>'', descr=>'Group name of the covergroup this item belongs to'") -VLCOVGEN_ITEM("name=>'groupcmt', short=>'O', group=>1, default=>'', ") -VLCOVGEN_ITEM("name=>'linescov', short=>'S', group=>1, default=>'', descr=>'List of comma-separated lines covered'") -VLCOVGEN_ITEM("name=>'per_instance',short=>'P', group=>1, default=>0, descr=>'True if every hierarchy is independently counted; otherwise all hierarchies will be combined into a single count'") -VLCOVGEN_ITEM("name=>'row0_name', short=>'R0', group=>1, default=>undef, descr=>'The row title for the header line of this row'") -VLCOVGEN_ITEM("name=>'row1_name', short=>'R1', group=>1, default=>undef, ") -VLCOVGEN_ITEM("name=>'row2_name', short=>'R2', group=>1, default=>undef, ") -VLCOVGEN_ITEM("name=>'row3_name', short=>'R3', group=>1, default=>undef, ") -VLCOVGEN_ITEM("name=>'table', short=>'T', group=>1, default=>undef, descr=>'The name of the table for automatically generated tables'") -VLCOVGEN_ITEM("name=>'thresh', short=>'s', group=>1, default=>undef, ") -VLCOVGEN_ITEM("name=>'type', short=>'t', group=>1, default=>'', descr=>'Type of coverage (block, line, fsm, etc)'") +VLCOVGEN_ITEM("'name':'column', 'short':'n', 'group':1, 'default':0, 'descr':'Column number for the item. Used to disambiguate multiple coverage points on the same line number'") +VLCOVGEN_ITEM("'name':'filename', 'short':'f', 'group':1, 'default':None, 'descr':'Filename of the item'") +VLCOVGEN_ITEM("'name':'linescov', 'short':'S', 'group':1, 'default':'', 'descr':'List of comma-separated lines covered'") +VLCOVGEN_ITEM("'name':'per_instance','short':'P', 'group':1, 'default':0, 'descr':'True if every hierarchy is independently counted; otherwise all hierarchies will be combined into a single count'") +VLCOVGEN_ITEM("'name':'thresh', 'short':'s', 'group':1, 'default':None, 'descr':'Number of hits to consider covered (aka at_least)'") +VLCOVGEN_ITEM("'name':'type', 'short':'t', 'group':1, 'default':'', 'descr':'Type of coverage (block, line, fsm, etc)'") // Bin attributes -VLCOVGEN_ITEM("name=>'col0', short=>'c0', group=>0, default=>undef, descr=>'The (enumeration) value name for this column in a table cross' ") -VLCOVGEN_ITEM("name=>'col1', short=>'c1', group=>0, default=>undef, ") -VLCOVGEN_ITEM("name=>'col2', short=>'c2', group=>0, default=>undef, ") -VLCOVGEN_ITEM("name=>'col3', short=>'c3', group=>0, default=>undef, ") -VLCOVGEN_ITEM("name=>'comment', short=>'o', group=>0, default=>'', descr=>'Textual description for the item'") -VLCOVGEN_ITEM("name=>'hier', short=>'h', group=>0, default=>'', descr=>'Hierarchy path name for the item'") -VLCOVGEN_ITEM("name=>'limit', short=>'L', group=>0, default=>undef, ") -VLCOVGEN_ITEM("name=>'lineno', short=>'l', group=>0, default=>0, descr=>'Line number for the item'") -VLCOVGEN_ITEM("name=>'row0', short=>'r0', group=>0, default=>undef, descr=>'The (enumeration) value name for this row in a table cross'") -VLCOVGEN_ITEM("name=>'row1', short=>'r1', group=>0, default=>undef, ") -VLCOVGEN_ITEM("name=>'row2', short=>'r2', group=>0, default=>undef, ") -VLCOVGEN_ITEM("name=>'row3', short=>'r3', group=>0, default=>undef, ") -VLCOVGEN_ITEM("name=>'weight', short=>'w', group=>0, default=>undef, descr=>'For totaling items, weight of this item'") +VLCOVGEN_ITEM("'name':'comment', 'short':'o', 'group':0, 'default':'', 'descr':'Textual description for the item'") +VLCOVGEN_ITEM("'name':'hier', 'short':'h', 'group':0, 'default':'', 'descr':'Hierarchy path name for the item'") +VLCOVGEN_ITEM("'name':'lineno', 'short':'l', 'group':0, 'default':0, 'descr':'Line number for the item'") +VLCOVGEN_ITEM("'name':'weight', 'short':'w', 'group':0, 'default':None, 'descr':'For totaling items, weight of this item'") // clang-format on // VLCOVGEN_CIK_AUTO_EDIT_BEGIN -#define VL_CIK_COL0 "c0" -#define VL_CIK_COL0_NAME "C0" -#define VL_CIK_COL1 "c1" -#define VL_CIK_COL1_NAME "C1" -#define VL_CIK_COL2 "c2" -#define VL_CIK_COL2_NAME "C2" -#define VL_CIK_COL3 "c3" -#define VL_CIK_COL3_NAME "C3" #define VL_CIK_COLUMN "n" #define VL_CIK_COMMENT "o" #define VL_CIK_FILENAME "f" -#define VL_CIK_GROUPCMT "O" -#define VL_CIK_GROUPDESC "d" -#define VL_CIK_GROUPNAME "g" #define VL_CIK_HIER "h" -#define VL_CIK_LIMIT "L" #define VL_CIK_LINENO "l" #define VL_CIK_LINESCOV "S" #define VL_CIK_PER_INSTANCE "P" -#define VL_CIK_ROW0 "r0" -#define VL_CIK_ROW0_NAME "R0" -#define VL_CIK_ROW1 "r1" -#define VL_CIK_ROW1_NAME "R1" -#define VL_CIK_ROW2 "r2" -#define VL_CIK_ROW2_NAME "R2" -#define VL_CIK_ROW3 "r3" -#define VL_CIK_ROW3_NAME "R3" -#define VL_CIK_TABLE "T" #define VL_CIK_THRESH "s" #define VL_CIK_TYPE "t" #define VL_CIK_WEIGHT "w" @@ -106,34 +64,13 @@ class VerilatedCovKey final { public: static std::string shortKey(const std::string& key) VL_PURE { // VLCOVGEN_SHORT_AUTO_EDIT_BEGIN - if (key == "col0") return VL_CIK_COL0; - if (key == "col0_name") return VL_CIK_COL0_NAME; - if (key == "col1") return VL_CIK_COL1; - if (key == "col1_name") return VL_CIK_COL1_NAME; - if (key == "col2") return VL_CIK_COL2; - if (key == "col2_name") return VL_CIK_COL2_NAME; - if (key == "col3") return VL_CIK_COL3; - if (key == "col3_name") return VL_CIK_COL3_NAME; if (key == "column") return VL_CIK_COLUMN; if (key == "comment") return VL_CIK_COMMENT; if (key == "filename") return VL_CIK_FILENAME; - if (key == "groupcmt") return VL_CIK_GROUPCMT; - if (key == "groupdesc") return VL_CIK_GROUPDESC; - if (key == "groupname") return VL_CIK_GROUPNAME; if (key == "hier") return VL_CIK_HIER; - if (key == "limit") return VL_CIK_LIMIT; if (key == "lineno") return VL_CIK_LINENO; if (key == "linescov") return VL_CIK_LINESCOV; if (key == "per_instance") return VL_CIK_PER_INSTANCE; - if (key == "row0") return VL_CIK_ROW0; - if (key == "row0_name") return VL_CIK_ROW0_NAME; - if (key == "row1") return VL_CIK_ROW1; - if (key == "row1_name") return VL_CIK_ROW1_NAME; - if (key == "row2") return VL_CIK_ROW2; - if (key == "row2_name") return VL_CIK_ROW2_NAME; - if (key == "row3") return VL_CIK_ROW3; - if (key == "row3_name") return VL_CIK_ROW3_NAME; - if (key == "table") return VL_CIK_TABLE; if (key == "thresh") return VL_CIK_THRESH; if (key == "type") return VL_CIK_TYPE; if (key == "weight") return VL_CIK_WEIGHT; diff --git a/include/verilated_dpi.cpp b/include/verilated_dpi.cpp index c1cc63f10..816b92c2e 100644 --- a/include/verilated_dpi.cpp +++ b/include/verilated_dpi.cpp @@ -1,7 +1,7 @@ // -*- mode: C++; c-file-style: "cc-mode" -*- //************************************************************************* // -// Copyright 2009-2020 by Wilson Snyder. This program is free software; you can +// Copyright 2009-2021 by Wilson Snyder. This program is free software; you can // redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -37,11 +37,6 @@ //====================================================================== // Internal macros -// Not supported yet -#define _VL_SVDPI_UNIMP() \ - VL_FATAL_MT(__FILE__, __LINE__, "", \ - (std::string("%%Error: Unsupported DPI function: ") + VL_FUNC).c_str()) - #define _VL_SVDPI_WARN(...) VL_PRINTF_MT(__VA_ARGS__) // Function requires a "context" in the import declaration @@ -258,16 +253,6 @@ static void* _vl_sv_adjusted_datap(const VerilatedDpiOpenVar* varp, int nargs, i return datap; } -static int _vl_sv_adjusted_bit(const VerilatedDpiOpenVar* varp, int indx) { - if (VL_UNLIKELY(indx < varp->low(0) || indx > varp->high(0))) { - _VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function packed index out of bounds; %d " - "outside [%d:%d].\n", - indx, varp->left(0), varp->right(0)); - return 0; - } - return indx - varp->low(0); -} - /// Return pointer to simulator open array element, or nullptr if outside range static void* _vl_svGetArrElemPtr(const svOpenArrayHandle h, int nargs, int indx1, int indx2, int indx3) VL_MT_SAFE { @@ -283,7 +268,7 @@ static void _vl_svGetBitArrElemVecVal(svBitVecVal* d, const svOpenArrayHandle s, const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(s); void* datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3); if (VL_UNLIKELY(!datap)) return; - switch (varp->vltype()) { + switch (varp->vltype()) { // LCOV_EXCL_BR_LINE case VLVT_UINT8: d[0] = *(reinterpret_cast(datap)); return; case VLVT_UINT16: d[0] = *(reinterpret_cast(datap)); return; case VLVT_UINT32: d[0] = *(reinterpret_cast(datap)); return; @@ -299,10 +284,10 @@ static void _vl_svGetBitArrElemVecVal(svBitVecVal* d, const svOpenArrayHandle s, for (int i = 0; i < VL_WORDS_I(varp->packed().elements()); ++i) d[i] = wdatap[i]; return; } - default: + default: // LCOV_EXCL_START // Errored earlier _VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n", varp->vltype()); - return; + return; // LCOV_EXCL_STOP } } /// Copy to user logic array from simulator open array @@ -311,7 +296,7 @@ static void _vl_svGetLogicArrElemVecVal(svLogicVecVal* d, const svOpenArrayHandl const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(s); void* datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3); if (VL_UNLIKELY(!datap)) return; - switch (varp->vltype()) { + switch (varp->vltype()) { // LCOV_EXCL_BR_LINE case VLVT_UINT8: d[0].aval = *(reinterpret_cast(datap)); d[0].bval = 0; @@ -330,7 +315,7 @@ static void _vl_svGetLogicArrElemVecVal(svLogicVecVal* d, const svOpenArrayHandl d[0].aval = lwp[0]; d[0].bval = 0; d[1].aval = lwp[1]; - d[0].bval = 0; + d[1].bval = 0; break; } case VLVT_WDATA: { @@ -341,10 +326,10 @@ static void _vl_svGetLogicArrElemVecVal(svLogicVecVal* d, const svOpenArrayHandl } return; } - default: + default: // LCOV_EXCL_START // Errored earlier _VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n", varp->vltype()); - return; + return; // LCOV_EXCL_STOP } } @@ -354,7 +339,7 @@ static void _vl_svPutBitArrElemVecVal(const svOpenArrayHandle d, const svBitVecV const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(d); void* datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3); if (VL_UNLIKELY(!datap)) return; - switch (varp->vltype()) { + switch (varp->vltype()) { // LCOV_EXCL_BR_LINE case VLVT_UINT8: *(reinterpret_cast(datap)) = s[0]; return; case VLVT_UINT16: *(reinterpret_cast(datap)) = s[0]; return; case VLVT_UINT32: *(reinterpret_cast(datap)) = s[0]; return; @@ -364,10 +349,10 @@ static void _vl_svPutBitArrElemVecVal(const svOpenArrayHandle d, const svBitVecV for (int i = 0; i < VL_WORDS_I(varp->packed().elements()); ++i) wdatap[i] = s[i]; return; } - default: + default: // LCOV_EXCL_START // Errored earlier _VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n", varp->vltype()); - return; + return; // LCOV_EXCL_STOP } } /// Copy to simulator open array from from user logic array @@ -376,7 +361,7 @@ static void _vl_svPutLogicArrElemVecVal(const svOpenArrayHandle d, const svLogic const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(d); void* datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3); if (VL_UNLIKELY(!datap)) return; - switch (varp->vltype()) { + switch (varp->vltype()) { // LCOV_EXCL_BR_LINE case VLVT_UINT8: *(reinterpret_cast(datap)) = s[0].aval; return; case VLVT_UINT16: *(reinterpret_cast(datap)) = s[0].aval; return; case VLVT_UINT32: *(reinterpret_cast(datap)) = s[0].aval; return; @@ -388,10 +373,10 @@ static void _vl_svPutLogicArrElemVecVal(const svOpenArrayHandle d, const svLogic for (int i = 0; i < VL_WORDS_I(varp->packed().elements()); ++i) wdatap[i] = s[i].aval; return; } - default: + default: // LCOV_EXCL_START // Errored earlier _VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n", varp->vltype()); - return; + return; // LCOV_EXCL_STOP } } @@ -400,31 +385,14 @@ static svBit _vl_svGetBitArrElem(const svOpenArrayHandle s, int nargs, int indx1 int indx3, int indx4) VL_MT_SAFE { // One extra index supported, as need bit number const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(s); - void* datap; - int lsb; - if (varp->packed().elements()) { - datap = _vl_sv_adjusted_datap(varp, nargs - 1, indx1, indx2, indx3); - lsb = _vl_sv_adjusted_bit( - varp, ((nargs == 1) ? indx1 : (nargs == 2) ? indx2 : (nargs == 3) ? indx3 : indx4)); - } else { - datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3); - lsb = 0; - } + void* datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3); if (VL_UNLIKELY(!datap)) return 0; - switch (varp->vltype()) { - case VLVT_UINT8: return (*(reinterpret_cast(datap)) >> lsb) & 1; - case VLVT_UINT16: return (*(reinterpret_cast(datap)) >> lsb) & 1; - case VLVT_UINT32: return (*(reinterpret_cast(datap)) >> lsb) & 1; - case VLVT_UINT64: - return (*(reinterpret_cast(datap)) >> static_cast(lsb)) & 1ULL; - case VLVT_WDATA: { - WDataOutP wdatap = (reinterpret_cast(datap)); - return VL_BITRSHIFT_W(wdatap, lsb) & 1; - } - default: + switch (varp->vltype()) { // LCOV_EXCL_BR_LINE + case VLVT_UINT8: return (*(reinterpret_cast(datap))) & 1; + default: // LCOV_EXCL_START // Errored earlier _VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n", varp->vltype()); - return 0; + return 0; // LCOV_EXCL_STOP } } /// Update simulator open array from bit @@ -433,27 +401,14 @@ static void _vl_svPutBitArrElem(const svOpenArrayHandle d, svBit value, int narg // One extra index supported, as need bit number value &= 1; // Make sure clean const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(d); - void* datap; - int lsb; - if (varp->packed().elements()) { - datap = _vl_sv_adjusted_datap(varp, nargs - 1, indx1, indx2, indx3); - lsb = _vl_sv_adjusted_bit( - varp, ((nargs == 1) ? indx1 : (nargs == 2) ? indx2 : (nargs == 3) ? indx3 : indx4)); - } else { - datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3); - lsb = 0; - } + void* datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3); if (VL_UNLIKELY(!datap)) return; - switch (varp->vltype()) { - case VLVT_UINT8: VL_ASSIGNBIT_II(-1, lsb, *(reinterpret_cast(datap)), value); return; - case VLVT_UINT16: VL_ASSIGNBIT_II(-1, lsb, *(reinterpret_cast(datap)), value); return; - case VLVT_UINT32: VL_ASSIGNBIT_II(-1, lsb, *(reinterpret_cast(datap)), value); return; - case VLVT_UINT64: VL_ASSIGNBIT_QI(-1, lsb, *(reinterpret_cast(datap)), value); return; - case VLVT_WDATA: VL_ASSIGNBIT_WI(-1, lsb, (reinterpret_cast(datap)), value); return; - default: + switch (varp->vltype()) { // LCOV_EXCL_BR_LINE + case VLVT_UINT8: *(reinterpret_cast(datap)) = value; return; + default: // LCOV_EXCL_START // Errored earlier _VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n", varp->vltype()); - return; + return; // LCOV_EXCL_STOP } } @@ -643,13 +598,6 @@ svBit svGetBitArrElem(const svOpenArrayHandle s, int indx1, ...) { out = _vl_svGetBitArrElem(s, 3, indx1, indx2, indx3, 0); break; } - case 4: { - int indx2 = va_arg(ap, int); - int indx3 = va_arg(ap, int); - int indx4 = va_arg(ap, int); - out = _vl_svGetBitArrElem(s, 4, indx1, indx2, indx3, indx4); - break; - } default: out = _vl_svGetBitArrElem(s, -1, 0, 0, 0, 0); break; // Will error } va_end(ap); @@ -683,13 +631,6 @@ svLogic svGetLogicArrElem(const svOpenArrayHandle s, int indx1, ...) { out = _vl_svGetBitArrElem(s, 3, indx1, indx2, indx3, 0); break; } - case 4: { - int indx2 = va_arg(ap, int); - int indx3 = va_arg(ap, int); - int indx4 = va_arg(ap, int); - out = _vl_svGetBitArrElem(s, 4, indx1, indx2, indx3, indx4); - break; - } default: out = _vl_svGetBitArrElem(s, -1, 0, 0, 0, 0); break; // Will error } va_end(ap); @@ -725,13 +666,6 @@ void svPutBitArrElem(const svOpenArrayHandle d, svBit value, int indx1, ...) { _vl_svPutBitArrElem(d, value, 3, indx1, indx2, indx3, 0); break; } - case 4: { - int indx2 = va_arg(ap, int); - int indx3 = va_arg(ap, int); - int indx4 = va_arg(ap, int); - _vl_svPutBitArrElem(d, value, 4, indx1, indx2, indx3, indx4); - break; - } default: _vl_svPutBitArrElem(d, value, -1, 0, 0, 0, 0); break; // Will error } va_end(ap); @@ -763,13 +697,6 @@ void svPutLogicArrElem(const svOpenArrayHandle d, svLogic value, int indx1, ...) _vl_svPutBitArrElem(d, value, 3, indx1, indx2, indx3, 0); break; } - case 4: { - int indx2 = va_arg(ap, int); - int indx3 = va_arg(ap, int); - int indx4 = va_arg(ap, int); - _vl_svPutBitArrElem(d, value, 4, indx1, indx2, indx3, indx4); - break; - } default: _vl_svPutBitArrElem(d, value, -1, 0, 0, 0, 0); break; // Will error } va_end(ap); diff --git a/include/verilated_dpi.h b/include/verilated_dpi.h index ff20f7360..3b9744ee4 100644 --- a/include/verilated_dpi.h +++ b/include/verilated_dpi.h @@ -1,7 +1,7 @@ // -*- mode: C++; c-file-style: "cc-mode" -*- //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you can +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you can // redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/include/verilated_fst_c.cpp b/include/verilated_fst_c.cpp index 80c149abc..8f2ba2cfd 100644 --- a/include/verilated_fst_c.cpp +++ b/include/verilated_fst_c.cpp @@ -3,7 +3,7 @@ // // THIS MODULE IS PUBLICLY LICENSED // -// Copyright 2001-2020 by Wilson Snyder. This program is free software; you +// Copyright 2001-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/include/verilated_fst_c.h b/include/verilated_fst_c.h index a4c4a779c..f21a6087c 100644 --- a/include/verilated_fst_c.h +++ b/include/verilated_fst_c.h @@ -3,7 +3,7 @@ // // THIS MODULE IS PUBLICLY LICENSED // -// Copyright 2001-2020 by Wilson Snyder. This program is free software; you +// Copyright 2001-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/include/verilated_heavy.h b/include/verilated_heavy.h index 0fd47d274..91d2272ae 100644 --- a/include/verilated_heavy.h +++ b/include/verilated_heavy.h @@ -1,7 +1,7 @@ // -*- mode: C++; c-file-style: "cc-mode" -*- //************************************************************************* // -// Copyright 2010-2020 by Wilson Snyder. This program is free software; you can +// Copyright 2010-2021 by Wilson Snyder. This program is free software; you can // redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -87,6 +87,51 @@ public: void print(QData addr, bool addrstamp, const void* valuep); }; +//=================================================================== +// Verilog wide-number-in-array container +// Similar to std::array, but lighter weight, only methods needed +// by Verilator, to help compile time. +// +// This is only used when we need an upper-level container and so can't +// simply use a C style array (which is just a pointer). + +template class VlWide final { + EData m_storage[T_Words]; + +public: + // cppcheck-suppress uninitVar + VlWide() = default; + ~VlWide() = default; + VlWide(const VlWide&) = default; + VlWide(VlWide&&) = default; + + // OPERATOR METHODS + VlWide& operator=(const VlWide&) = default; + VlWide& operator=(VlWide&&) = default; + const EData& operator[](size_t index) const { return m_storage[index]; }; + EData& operator[](size_t index) { return m_storage[index]; }; + operator WDataOutP() { return &m_storage[0]; } + + // METHODS + const EData& at(size_t index) const { return m_storage[index]; } + EData& at(size_t index) { return m_storage[index]; } + WData* data() { return &m_storage[0]; } + const WData* data() const { return &m_storage[0]; } + bool operator<(const VlWide& rhs) const { + return VL_LT_W(T_Words, data(), rhs.data()); + } +}; + +// Convert a C array to std::array reference by pointer magic, without copy. +// Data type (second argument) is so the function template can automatically generate. +template VlWide& VL_CVT_W_A(WDataInP inp, const VlWide&) { + return *((VlWide*)inp); +} + +template std::string VL_TO_STRING(const VlWide& obj) { + return VL_TO_STRING_W(T_Words, obj.data()); +} + //=================================================================== // Verilog queue and dynamic array container // There are no multithreaded locks on this; the base variable must @@ -444,45 +489,6 @@ template std::string VL_TO_STRING(const VlQueue& obj) { return obj.to_string(); } -//=================================================================== -// Verilog array container -// Similar to std::array, but lighter weight, only methods needed -// by Verilator, to help compile time. -// -// This is only used when we need an upper-level container and so can't -// simply use a C style array (which is just a pointer). - -template class VlWide final { - WData m_storage[T_Words]; - -public: - // cppcheck-suppress uninitVar - VlWide() = default; - ~VlWide() = default; - VlWide(const VlWide&) = default; - VlWide(VlWide&&) = default; - VlWide& operator=(const VlWide&) = default; - VlWide& operator=(VlWide&&) = default; - // METHODS - const WData& at(size_t index) const { return m_storage[index]; } - WData& at(size_t index) { return m_storage[index]; } - WData* data() { return &m_storage[0]; } - const WData* data() const { return &m_storage[0]; } - bool operator<(const VlWide& rhs) const { - return VL_LT_W(T_Words, data(), rhs.data()); - } -}; - -// Convert a C array to std::array reference by pointer magic, without copy. -// Data type (second argument) is so the function template can automatically generate. -template VlWide& VL_CVT_W_A(WDataInP inp, const VlWide&) { - return *((VlWide*)inp); -} - -template std::string VL_TO_STRING(const VlWide& obj) { - return VL_TO_STRING_W(T_Words, obj.data()); -} - //=================================================================== // Verilog associative array container // There are no multithreaded locks on this; the base variable must @@ -560,8 +566,7 @@ public: T_Value& at(const T_Key& index) { const auto it = m_map.find(index); if (it == m_map.end()) { - std::pair pit - = m_map.insert(std::make_pair(index, m_defaultValue)); + std::pair pit = m_map.emplace(index, m_defaultValue); return pit.first->second; } return it->second; @@ -788,6 +793,41 @@ void VL_WRITEMEM_N(bool hex, int bits, const std::string& filename, } } +//=================================================================== +// Verilog packed array container +// For when a standard C++[] array is not sufficient, e.g. an +// array under a queue, or methods operating on the array + +template class VlUnpacked final { +private: + // TYPES + typedef std::array Array; + +public: + typedef typename Array::const_iterator const_iterator; + +private: + // MEMBERS + Array m_array; // State of the assoc array + +public: + // CONSTRUCTORS + VlUnpacked() = default; + ~VlUnpacked() = default; + VlUnpacked(const VlUnpacked&) = default; + VlUnpacked(VlUnpacked&&) = default; + VlUnpacked& operator=(const VlUnpacked&) = default; + VlUnpacked& operator=(VlUnpacked&&) = default; + + // METHODS + // Raw access + WData* data() { return &m_array[0]; } + const WData* data() const { return &m_array[0]; } + + T_Value& operator[](size_t index) { return m_array[index]; }; + const T_Value& operator[](size_t index) const { return m_array[index]; }; +}; + //=================================================================== // Verilog class reference container // There are no multithreaded locks on this; the base variable must @@ -802,6 +842,17 @@ inline T VL_NULL_CHECK(T t, const char* filename, int linenum) { return t; } +template +static inline bool VL_CAST_DYNAMIC(VlClassRef in, VlClassRef& outr) { + VlClassRef casted = std::dynamic_pointer_cast(in); + if (VL_LIKELY(casted)) { + outr = casted; + return true; + } else { + return false; + } +} + //====================================================================== // Conversion functions diff --git a/include/verilated_imp.h b/include/verilated_imp.h index ba0993570..e81f5e908 100644 --- a/include/verilated_imp.h +++ b/include/verilated_imp.h @@ -1,7 +1,7 @@ // -*- mode: C++; c-file-style: "cc-mode" -*- //************************************************************************* // -// Copyright 2009-2020 by Wilson Snyder. This program is free software; you can +// Copyright 2009-2021 by Wilson Snyder. This program is free software; you can // redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -61,7 +61,7 @@ private: std::function m_cb; ///< Lambda to execute when message received public: // CONSTRUCTORS - VerilatedMsg(const std::function& cb) + explicit VerilatedMsg(const std::function& cb) : m_mtaskId{Verilated::mtaskId()} , m_cb{cb} {} ~VerilatedMsg() = default; @@ -331,7 +331,7 @@ public: if (it != s_s.v.m_userMap.end()) { it->second = userData; } else { - s_s.v.m_userMap.insert(it, std::make_pair(std::make_pair(scopep, userKey), userData)); + s_s.v.m_userMap.emplace(std::make_pair(scopep, userKey), userData); } } static inline void* userFind(const void* scopep, void* userKey) VL_MT_SAFE { @@ -374,9 +374,7 @@ public: // But only for verilated*.cpp // Slow ok - called once/scope at construction const VerilatedLockGuard lock(s_s.v.m_nameMutex); const auto it = s_s.v.m_nameMap.find(scopep->name()); - if (it == s_s.v.m_nameMap.end()) { - s_s.v.m_nameMap.insert(it, std::make_pair(scopep->name(), scopep)); - } + if (it == s_s.v.m_nameMap.end()) s_s.v.m_nameMap.emplace(scopep->name(), scopep); } static inline const VerilatedScope* scopeFind(const char* namep) VL_MT_SAFE { const VerilatedLockGuard lock(s_s.v.m_nameMutex); @@ -413,6 +411,16 @@ public: // But only for verilated*.cpp const VerilatedLockGuard lock(s_s.v.m_hierMapMutex); s_s.v.m_hierMap[fromp].push_back(top); } + static void hierarchyRemove(const VerilatedScope* fromp, + const VerilatedScope* top) VL_MT_SAFE { + // Slow ok - called at destruction for VPI accessible elements + const VerilatedLockGuard lock(s_s.v.m_hierMapMutex); + VerilatedHierarchyMap& map = s_s.v.m_hierMap; + if (map.find(fromp) == map.end()) return; + VerilatedScopeVector& scopes = map[fromp]; + const auto it = find(scopes.begin(), scopes.end(), top); + if (it != scopes.end()) scopes.erase(it); + } static const VerilatedHierarchyMap* hierarchyMap() VL_MT_SAFE_POSTINIT { // Thread save only assuming this is called only after model construction completed return &s_s.v.m_hierMap; @@ -432,7 +440,7 @@ public: // But only for verilated*.cpp const VerilatedLockGuard lock(s_s.v.m_exportMutex); const auto it = s_s.v.m_exportMap.find(namep); if (it == s_s.v.m_exportMap.end()) { - s_s.v.m_exportMap.insert(it, std::make_pair(namep, s_s.v.m_exportNext++)); + s_s.v.m_exportMap.emplace(namep, s_s.v.m_exportNext++); return s_s.v.m_exportNext++; } else { return it->second; diff --git a/include/verilated_intrinsics.h b/include/verilated_intrinsics.h index 11b532fd7..4deea30e1 100644 --- a/include/verilated_intrinsics.h +++ b/include/verilated_intrinsics.h @@ -1,7 +1,7 @@ // -*- mode: C++; c-file-style: "cc-mode" -*- //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you can +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you can // redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -24,8 +24,8 @@ // clang-format off -// Use VL_DISABLE_INTRINSICS to disable all intrinsics based optimization -#if !defined(VL_DISABLE_INTRINSICS) && !defined(VL_PORTABLE_ONLY) +// Use VL_PORTABLE_ONLY to disable all intrinsics based optimization +#ifndef VL_PORTABLE_ONLY # if defined(__SSE2__) && !defined(VL_DISABLE_SSE2) # define VL_HAVE_SSE2 1 # include diff --git a/include/verilated_save.cpp b/include/verilated_save.cpp index 26d626102..7743859af 100644 --- a/include/verilated_save.cpp +++ b/include/verilated_save.cpp @@ -3,7 +3,7 @@ // // THIS MODULE IS PUBLICLY LICENSED // -// Copyright 2001-2020 by Wilson Snyder. This program is free software; you +// Copyright 2001-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/include/verilated_save.h b/include/verilated_save.h index bb40d86fc..e39ca820e 100644 --- a/include/verilated_save.h +++ b/include/verilated_save.h @@ -3,7 +3,7 @@ // // THIS MODULE IS PUBLICLY LICENSED // -// Copyright 2000-2020 by Wilson Snyder. This program is free software; you +// Copyright 2000-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/include/verilated_sc.h b/include/verilated_sc.h index a807b8302..31884ba53 100644 --- a/include/verilated_sc.h +++ b/include/verilated_sc.h @@ -1,7 +1,7 @@ // -*- mode: C++; c-file-style: "cc-mode" -*- //************************************************************************* // -// Copyright 2009-2020 by Wilson Snyder. This program is free software; you can +// Copyright 2009-2021 by Wilson Snyder. This program is free software; you can // redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/include/verilated_sym_props.h b/include/verilated_sym_props.h index 2df07855e..41d0b3193 100644 --- a/include/verilated_sym_props.h +++ b/include/verilated_sym_props.h @@ -1,7 +1,7 @@ // -*- mode: C++; c-file-style: "cc-mode" -*- //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you can +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you can // redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -44,15 +44,15 @@ protected: friend class VerilatedVarProps; friend class VerilatedScope; VerilatedRange() = default; - VerilatedRange(int left, int right) - : m_left{left} - , m_right{right} {} void init(int left, int right) { m_left = left; m_right = right; } public: + VerilatedRange(int left, int right) + : m_left{left} + , m_right{right} {} ~VerilatedRange() = default; int left() const { return m_left; } int right() const { return m_right; } @@ -75,15 +75,15 @@ class VerilatedVarProps VL_NOT_FINAL { const vluint32_t m_magic; // Magic number const VerilatedVarType m_vltype; // Data type const VerilatedVarFlags m_vlflags; // Direction - const int m_pdims; // Packed dimensions - const int m_udims; // Unpacked dimensions + const int m_pdims; // Packed dimensions, 0 = none + const int m_udims; // Unpacked dimensions, 0 = none VerilatedRange m_packed; // Packed array range std::vector m_unpacked; // Unpacked array ranges void initUnpacked(const int* ulims) { for (int i = 0; i < m_udims; ++i) { - const int left = ulims ? ulims[2 * i + 0] : 0; - const int right = ulims ? ulims[2 * i + 1] : 0; - m_unpacked.push_back(VerilatedRange(left, right)); + const int uleft = ulims ? ulims[2 * i + 0] : 0; + const int uright = ulims ? ulims[2 * i + 1] : 0; + m_unpacked.emplace_back(uleft, uright); } } // CONSTRUCTORS diff --git a/include/verilated_syms.h b/include/verilated_syms.h index 29fdfcb90..295bcc1b8 100644 --- a/include/verilated_syms.h +++ b/include/verilated_syms.h @@ -1,7 +1,7 @@ // -*- mode: C++; c-file-style: "cc-mode" -*- //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you can +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you can // redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/include/verilated_threads.cpp b/include/verilated_threads.cpp index 7318c92de..54f029d11 100644 --- a/include/verilated_threads.cpp +++ b/include/verilated_threads.cpp @@ -1,7 +1,7 @@ // -*- mode: C++; c-file-style: "cc-mode" -*- //============================================================================= // -// Copyright 2012-2020 by Wilson Snyder. This program is free software; you can +// Copyright 2012-2021 by Wilson Snyder. This program is free software; you can // redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/include/verilated_threads.h b/include/verilated_threads.h index 4b6678c92..b502d9971 100644 --- a/include/verilated_threads.h +++ b/include/verilated_threads.h @@ -3,7 +3,7 @@ // // THIS MODULE IS PUBLICLY LICENSED // -// Copyright 2012-2020 by Wilson Snyder. This program is free software; you +// Copyright 2012-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/include/verilated_trace.h b/include/verilated_trace.h index bb4bc68b9..a16617146 100644 --- a/include/verilated_trace.h +++ b/include/verilated_trace.h @@ -3,7 +3,7 @@ // // THIS MODULE IS PUBLICLY LICENSED // -// Copyright 2001-2020 by Wilson Snyder. This program is free software; you +// Copyright 2001-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -216,7 +216,6 @@ protected: double timeRes() const { return m_timeRes; } double timeUnit() const { return m_timeUnit; } std::string timeResStr() const; - std::string timeUnitStr() const; void traceInit() VL_MT_UNSAFE; diff --git a/include/verilated_trace_imp.cpp b/include/verilated_trace_imp.cpp index 840eb8be3..fe4580794 100644 --- a/include/verilated_trace_imp.cpp +++ b/include/verilated_trace_imp.cpp @@ -3,7 +3,7 @@ // // THIS MODULE IS PUBLICLY LICENSED // -// Copyright 2001-2020 by Wilson Snyder. This program is free software; you +// Copyright 2001-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -47,7 +47,7 @@ static double timescaleToDouble(const char* unitp) { unitp = endp; for (; *unitp && isspace(*unitp); unitp++) {} switch (*unitp) { - case 's': value *= 1e1; break; + case 's': value *= 1e0; break; case 'm': value *= 1e-3; break; case 'u': value *= 1e-6; break; case 'n': value *= 1e-9; break; @@ -70,7 +70,7 @@ static std::string doubleToTimescale(double value) { else if (value >= 1e-18) { suffixp = "as"; value *= 1e18; } // clang-format on char valuestr[100]; - sprintf(valuestr, "%3.0f%s", value, suffixp); + sprintf(valuestr, "%0.0f%s", value, suffixp); return valuestr; // Gets converted to string, so no ref to stack } @@ -374,10 +374,6 @@ template <> std::string VerilatedTrace::timeResStr() const { return doubleToTimescale(m_timeRes); } -template <> std::string VerilatedTrace::timeUnitStr() const { - return doubleToTimescale(m_timeUnit); -} - //========================================================================= // External interface to client code @@ -643,4 +639,39 @@ static inline void cvtQDataToStr(char* dstp, QData value) { #define cvtEDataToStr cvtIDataToStr +//============================================================================= + +#ifdef VERILATED_VCD_TEST + +void verilated_trace_imp_selftest() { +#define SELF_CHECK(got, exp) \ + do { \ + if ((got) != (exp)) VL_FATAL_MT(__FILE__, __LINE__, "", "%Error: selftest\n"); \ + } while (0) + +#define SELF_CHECK_TS(scale) \ + SELF_CHECK(doubleToTimescale(timescaleToDouble(scale)), std::string{scale}); + SELF_CHECK_TS("1s"); + SELF_CHECK_TS("100ms"); + SELF_CHECK_TS("10ms"); + SELF_CHECK_TS("1ms"); + SELF_CHECK_TS("100us"); + SELF_CHECK_TS("10us"); + SELF_CHECK_TS("1us"); + SELF_CHECK_TS("100ns"); + SELF_CHECK_TS("10ns"); + SELF_CHECK_TS("1ns"); + SELF_CHECK_TS("100ps"); + SELF_CHECK_TS("10ps"); + SELF_CHECK_TS("1ps"); + SELF_CHECK_TS("100fs"); + SELF_CHECK_TS("10fs"); + SELF_CHECK_TS("1fs"); + SELF_CHECK_TS("100as"); + SELF_CHECK_TS("10as"); + SELF_CHECK_TS("1as"); +} + +#endif + #endif // VL_CPPCHECK diff --git a/include/verilated_vcd_c.cpp b/include/verilated_vcd_c.cpp index ce26b6c62..0460dd8eb 100644 --- a/include/verilated_vcd_c.cpp +++ b/include/verilated_vcd_c.cpp @@ -3,7 +3,7 @@ // // THIS MODULE IS PUBLICLY LICENSED // -// Copyright 2001-2020 by Wilson Snyder. This program is free software; you +// Copyright 2001-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -198,7 +198,7 @@ void VerilatedVcd::makeNameMap() { std::string newname = std::string("top"); if (hiername[0] != '\t') newname += ' '; newname += hiername; - newmapp->insert(std::make_pair(newname, decl)); + newmapp->emplace(newname, decl); } deleteNameMap(); m_namemapp = newmapp; @@ -511,7 +511,7 @@ void VerilatedVcd::declare(vluint32_t code, const char* name, const char* wirep, decl += buf; } decl += " $end\n"; - m_namemapp->insert(std::make_pair(hiername, decl)); + m_namemapp->emplace(hiername, decl); } void VerilatedVcd::declBit(vluint32_t code, const char* name, bool array, int arraynum) { @@ -777,6 +777,8 @@ void VerilatedVcd::fullDouble(vluint32_t code, const double newval) { #ifdef VERILATED_VCD_TEST #include +extern void verilated_trace_imp_selftest(); + vluint32_t v1, v2, s1, s2[3]; vluint32_t tri96[3]; vluint32_t tri96__tri[3]; @@ -843,6 +845,8 @@ void vcdChange(void*, VerilatedVcd* vcdp) { // clang-format off void vcdTestMain(const char* filenamep) { + verilated_trace_imp_selftest(); + v1 = v2 = s1 = 0; s2[0] = s2[1] = s2[2] = 0; tri96[2] = tri96[1] = tri96[0] = 0; @@ -889,6 +893,7 @@ void vcdTestMain(const char* filenamep) { } # endif vcdp->close(); + VL_DO_CLEAR(delete vcdp, vcdp = nullptr); } } #endif diff --git a/include/verilated_vcd_c.h b/include/verilated_vcd_c.h index 8424bd6e6..6c7408691 100644 --- a/include/verilated_vcd_c.h +++ b/include/verilated_vcd_c.h @@ -3,7 +3,7 @@ // // THIS MODULE IS PUBLICLY LICENSED // -// Copyright 2001-2020 by Wilson Snyder. This program is free software; you +// Copyright 2001-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -34,7 +34,7 @@ class VerilatedVcd; // VerilatedFile /// File handling routines, which can be overrode for e.g. socket I/O -class VerilatedVcdFile final { +class VerilatedVcdFile VL_NOT_FINAL { private: int m_fd = 0; ///< File descriptor we're writing to public: diff --git a/include/verilated_vcd_sc.cpp b/include/verilated_vcd_sc.cpp index a09935527..d5ccb0df4 100644 --- a/include/verilated_vcd_sc.cpp +++ b/include/verilated_vcd_sc.cpp @@ -3,7 +3,7 @@ // // THIS MODULE IS PUBLICLY LICENSED // -// Copyright 2001-2020 by Wilson Snyder. This program is free software; you +// Copyright 2001-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/include/verilated_vcd_sc.h b/include/verilated_vcd_sc.h index 2836879c1..513344499 100644 --- a/include/verilated_vcd_sc.h +++ b/include/verilated_vcd_sc.h @@ -1,7 +1,7 @@ // -*- mode: C++; c-file-style: "cc-mode" -*- //============================================================================= // -// Copyright 2001-2020 by Wilson Snyder. This program is free software; you can +// Copyright 2001-2021 by Wilson Snyder. This program is free software; you can // redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/include/verilated_vpi.cpp b/include/verilated_vpi.cpp index fe730dbfa..cb2a0c032 100644 --- a/include/verilated_vpi.cpp +++ b/include/verilated_vpi.cpp @@ -1,7 +1,7 @@ // -*- mode: C++; c-file-style: "cc-mode" -*- //************************************************************************* // -// Copyright 2009-2020 by Wilson Snyder. This program is free software; you can +// Copyright 2009-2021 by Wilson Snyder. This program is free software; you can // redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -56,6 +56,11 @@ constexpr unsigned VL_VPI_LINE_SIZE = 8192; // Base VPI handled object class VerilatedVpio VL_NOT_FINAL { + // CONSTANTS + /// Magic value stored in front of object to detect double free etc + /// Must be odd, as aligned pointer can never be odd + static constexpr vluint32_t activeMagic() { return 0xfeed100f; } + // MEM MANGLEMENT static VL_THREAD_LOCAL vluint8_t* t_freeHead; @@ -73,16 +78,27 @@ public: if (VL_LIKELY(t_freeHead)) { vluint8_t* newp = t_freeHead; t_freeHead = *(reinterpret_cast(newp)); + *(reinterpret_cast(newp)) = activeMagic(); return newp + 8; } // +8: 8 bytes for next vluint8_t* newp = reinterpret_cast(::operator new(chunk + 8)); + *(reinterpret_cast(newp)) = activeMagic(); return newp + 8; } static void operator delete(void* obj, size_t /*size*/)VL_MT_SAFE { vluint8_t* oldp = (static_cast(obj)) - 8; + if (VL_UNLIKELY(*(reinterpret_cast(oldp)) != activeMagic())) { + VL_FATAL_MT(__FILE__, __LINE__, "", + "vpi_release_handle() called on same object twice, or on non-Verilator " + "VPI object"); + } +#ifdef VL_VPI_IMMEDIATE_FREE // Define to aid in finding leaky handles + ::operator delete(oldp); +#else *(reinterpret_cast(oldp)) = t_freeHead; t_freeHead = oldp; +#endif } // MEMBERS static VerilatedVpio* castp(vpiHandle h) { @@ -97,32 +113,44 @@ public: virtual vluint32_t size() const { return 0; } virtual const VerilatedRange* rangep() const { return nullptr; } virtual vpiHandle dovpi_scan() { return nullptr; } + virtual PLI_INT32 dovpi_remove_cb() { return 0; } }; -typedef PLI_INT32 (*VerilatedPliCb)(struct t_cb_data*); - -class VerilatedVpioCb final : public VerilatedVpio { - t_cb_data m_cbData; - s_vpi_value m_value; +class VerilatedVpioTimedCb final : public VerilatedVpio { + // A handle to a timed callback created with vpi_register_cb + // User can call vpi_remove_cb or vpi_release_handle on it + vluint64_t m_id; // Unique id/sequence number to find schedule's event QData m_time; public: - // cppcheck-suppress uninitVar // m_value - VerilatedVpioCb(const t_cb_data* cbDatap, QData time) - : m_cbData(*cbDatap) - , m_time(time) { // Need () or GCC 4.8 false warning - m_value.format = cbDatap->value ? cbDatap->value->format : vpiSuppressVal; - m_cbData.value = &m_value; - } - virtual ~VerilatedVpioCb() override = default; - static VerilatedVpioCb* castp(vpiHandle h) { - return dynamic_cast(reinterpret_cast(h)); + VerilatedVpioTimedCb(vluint64_t id, QData time) + : m_id(id) + , m_time{time} {} + virtual ~VerilatedVpioTimedCb() override = default; + static VerilatedVpioTimedCb* castp(vpiHandle h) { + return dynamic_cast(reinterpret_cast(h)); } virtual vluint32_t type() const override { return vpiCallback; } - vluint32_t reason() const { return m_cbData.reason; } - VerilatedPliCb cb_rtnp() const { return m_cbData.cb_rtn; } - t_cb_data* cb_datap() { return &(m_cbData); } - QData time() const { return m_time; } + virtual PLI_INT32 dovpi_remove_cb() override; +}; + +class VerilatedVpioReasonCb final : public VerilatedVpio { + // A handle to a non-timed callback created with vpi_register_cb + // User can call vpi_remove_cb or vpi_release_handle on it + vluint64_t m_id; // Unique id/sequence number to find schedule's event + PLI_INT32 m_reason; // VPI callback reason code + +public: + // cppcheck-suppress uninitVar // m_value + VerilatedVpioReasonCb(vluint64_t id, PLI_INT32 reason) + : m_id(id) + , m_reason{reason} {} + virtual ~VerilatedVpioReasonCb() override = default; + static VerilatedVpioReasonCb* castp(vpiHandle h) { + return dynamic_cast(reinterpret_cast(h)); + } + virtual vluint32_t type() const override { return vpiCallback; } + virtual PLI_INT32 dovpi_remove_cb() override; }; class VerilatedVpioConst final : public VerilatedVpio { @@ -147,7 +175,6 @@ public: VerilatedVpioParam(const VerilatedVar* varp, const VerilatedScope* scopep) : m_varp{varp} , m_scopep{scopep} {} - virtual ~VerilatedVpioParam() override = default; static VerilatedVpioParam* castp(vpiHandle h) { @@ -167,7 +194,6 @@ public: class VerilatedVpioRange final : public VerilatedVpio { const VerilatedRange* m_range; - vlsint32_t m_iteration = 0; public: explicit VerilatedVpioRange(const VerilatedRange* range) @@ -179,15 +205,28 @@ public: virtual vluint32_t type() const override { return vpiRange; } virtual vluint32_t size() const override { return m_range->elements(); } virtual const VerilatedRange* rangep() const override { return m_range; } - int iteration() const { return m_iteration; } - void iterationInc() { ++m_iteration; } +}; + +class VerilatedVpioRangeIter final : public VerilatedVpio { + // Only supports 1 dimension + const VerilatedRange* m_range; + bool m_done = false; + +public: + explicit VerilatedVpioRangeIter(const VerilatedRange* range) + : m_range{range} {} + virtual ~VerilatedVpioRangeIter() override = default; + static VerilatedVpioRangeIter* castp(vpiHandle h) { + return dynamic_cast(reinterpret_cast(h)); + } + virtual vluint32_t type() const override { return vpiIterator; } virtual vpiHandle dovpi_scan() override { - if (!iteration()) { - VerilatedVpioRange* nextp = new VerilatedVpioRange(*this); - nextp->iterationInc(); - return ((nextp)->castVpiHandle()); + if (VL_UNLIKELY(m_done)) { + delete this; // IEEE 37.2.2 vpi_scan at end does a vpi_release_handle + return nullptr; } - return nullptr; // End of list - only one deep + m_done = true; + return ((new VerilatedVpioRange(m_range))->castVpiHandle()); } }; @@ -209,16 +248,16 @@ public: }; class VerilatedVpioVar VL_NOT_FINAL : public VerilatedVpio { - const VerilatedVar* m_varp; - const VerilatedScope* m_scopep; + const VerilatedVar* m_varp = nullptr; + const VerilatedScope* m_scopep = nullptr; vluint8_t* m_prevDatap = nullptr; // Previous value of data, for cbValueChange union { vluint8_t u8[4]; vluint32_t u32; } m_mask; // memoized variable mask - vluint32_t m_entSize; // memoized variable size + vluint32_t m_entSize = 0; // memoized variable size protected: - void* m_varDatap; // varp()->datap() adjusted for array entries + void* m_varDatap = nullptr; // varp()->datap() adjusted for array entries vlsint32_t m_index = 0; const VerilatedRange& get_range() const { // Determine number of dimensions and return outermost @@ -233,6 +272,19 @@ public: m_entSize = varp->entSize(); m_varDatap = varp->datap(); } + explicit VerilatedVpioVar(const VerilatedVpioVar* varp) { + if (varp) { + m_varp = varp->m_varp; + m_scopep = varp->m_scopep; + m_mask.u32 = varp->m_mask.u32; + m_entSize = varp->m_entSize; + m_varDatap = varp->m_varDatap; + m_index = varp->m_index; + // Not copying m_prevDatap, must be nullptr + } else { + m_mask.u32 = 0; + } + } virtual ~VerilatedVpioVar() override { if (m_prevDatap) VL_DO_CLEAR(delete[] m_prevDatap, m_prevDatap = nullptr); } @@ -310,13 +362,18 @@ public: m_it = varsp->begin(); m_started = true; } else if (VL_UNLIKELY(m_it == varsp->end())) { + delete this; // IEEE 37.2.2 vpi_scan at end does a vpi_release_handle return nullptr; } else { ++m_it; } - if (m_it == varsp->end()) return nullptr; + if (VL_UNLIKELY(m_it == varsp->end())) { + delete this; // IEEE 37.2.2 vpi_scan at end does a vpi_release_handle + return nullptr; + } return ((new VerilatedVpioVar(&(m_it->second), m_scopep))->castVpiHandle()); } + delete this; // IEEE 37.2.2 vpi_scan at end does a vpi_release_handle return nullptr; // End of list - only one deep } }; @@ -343,9 +400,11 @@ public: if (!(m_done = (m_iteration == m_varp->unpacked().left()))) m_iteration += m_direction; } virtual vpiHandle dovpi_scan() override { - vpiHandle result; - if (m_done) return nullptr; - result = vpi_handle_by_index(m_handle, m_iteration); + if (VL_UNLIKELY(m_done)) { + delete this; // IEEE 37.2.2 vpi_scan at end does a vpi_release_handle + return nullptr; + } + vpiHandle result = vpi_handle_by_index(m_handle, m_iteration); iterationInc(); return result; } @@ -385,7 +444,10 @@ public: } virtual vluint32_t type() const override { return vpiIterator; } virtual vpiHandle dovpi_scan() override { - if (m_it == m_vec->end()) return nullptr; + if (m_it == m_vec->end()) { + delete this; // IEEE 37.2.2 vpi_scan at end does a vpi_release_handle + return nullptr; + } const VerilatedScope* modp = *m_it++; return (new VerilatedVpioModule(modp))->castVpiHandle(); } @@ -393,10 +455,42 @@ public: //====================================================================== +typedef PLI_INT32 (*VerilatedPliCb)(struct t_cb_data*); + +class VerilatedVpiCbHolder final { + // Holds information needed to call a callback + vluint64_t m_id; + s_cb_data m_cbData; + s_vpi_value m_value; + VerilatedVpioVar m_varo; // If a cbValueChange callback, the object we will return + +public: + // cppcheck-suppress uninitVar // m_value + VerilatedVpiCbHolder(vluint64_t id, const s_cb_data* cbDatap, const VerilatedVpioVar* varop) + : m_id(id) + , m_cbData(*cbDatap) + , m_varo(varop) { + m_value.format = cbDatap->value ? cbDatap->value->format : vpiSuppressVal; + m_cbData.value = &m_value; + if (varop) { + m_cbData.obj = m_varo.castVpiHandle(); + m_varo.createPrevDatap(); + } else { + m_cbData.obj = NULL; + } + } + ~VerilatedVpiCbHolder() = default; + VerilatedPliCb cb_rtnp() const { return m_cbData.cb_rtn; } + s_cb_data* cb_datap() { return &m_cbData; } + vluint64_t id() const { return m_id; } + bool invalid() const { return !m_id; } + void invalidate() { m_id = 0; } +}; + struct VerilatedVpiTimedCbsCmp { - /// Ordering sets keyed by time, then callback descriptor - bool operator()(const std::pair& a, - const std::pair& b) const { + /// Ordering sets keyed by time, then callback unique id + bool operator()(const std::pair& a, + const std::pair& b) const { if (a.first < b.first) return true; if (a.first > b.first) return false; return a.second < b.second; @@ -407,57 +501,70 @@ class VerilatedVpiError; class VerilatedVpiImp final { enum { CB_ENUM_MAX_VALUE = cbAtEndOfSimTime + 1 }; // Maxium callback reason - typedef std::list VpioCbList; - typedef std::set, VerilatedVpiTimedCbsCmp> VpioTimedCbs; + typedef std::list VpioCbList; + typedef std::map, VerilatedVpiCbHolder> VpioTimedCbs; VpioCbList m_cbObjLists[CB_ENUM_MAX_VALUE]; // Callbacks for each supported reason VpioTimedCbs m_timedCbs; // Time based callbacks VerilatedVpiError* m_errorInfop = nullptr; // Container for vpi error info VerilatedAssertOneThread m_assertOne; ///< Assert only called from single thread + vluint64_t m_nextCallbackId = 1; // Id to identify callback static VerilatedVpiImp s_s; // Singleton public: - VerilatedVpiImp() = default; - ~VerilatedVpiImp() = default; static void assertOneCheck() { s_s.m_assertOne.check(); } - static void cbReasonAdd(VerilatedVpioCb* vop) { - if (vop->reason() == cbValueChange) { - if (VerilatedVpioVar* varop = VerilatedVpioVar::castp(vop->cb_datap()->obj)) { - varop->createPrevDatap(); - } - } - if (VL_UNCOVERABLE(vop->reason() >= CB_ENUM_MAX_VALUE)) { + static vluint64_t nextCallbackId() { return ++s_s.m_nextCallbackId; } + + static void cbReasonAdd(vluint64_t id, const s_cb_data* cb_data_p) { + // The passed cb_data_p was property of the user, so need to recreate + if (VL_UNCOVERABLE(cb_data_p->reason >= CB_ENUM_MAX_VALUE)) { VL_FATAL_MT(__FILE__, __LINE__, "", "vpi bb reason too large"); } - s_s.m_cbObjLists[vop->reason()].push_back(vop); + VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_register_cb reason=%d id=%" VL_PRI64 "d obj=%p\n", + cb_data_p->reason, id, cb_data_p->obj);); + VerilatedVpioVar* varop = nullptr; + if (cb_data_p->reason == cbValueChange) varop = VerilatedVpioVar::castp(cb_data_p->obj); + s_s.m_cbObjLists[cb_data_p->reason].emplace_back(id, cb_data_p, varop); } - static void cbTimedAdd(VerilatedVpioCb* vop) { - s_s.m_timedCbs.insert(std::make_pair(vop->time(), vop)); + static void cbTimedAdd(vluint64_t id, const s_cb_data* cb_data_p, QData time) { + // The passed cb_data_p was property of the user, so need to recreate + VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_register_cb reason=%d id=%" VL_PRI64 + "d delay=%" VL_PRI64 "u\n", + cb_data_p->reason, id, time);); + s_s.m_timedCbs.emplace(std::piecewise_construct, + std::forward_as_tuple(std::make_pair(time, id)), + std::forward_as_tuple(id, cb_data_p, nullptr)); } - static void cbReasonRemove(VerilatedVpioCb* cbp) { - VpioCbList& cbObjList = s_s.m_cbObjLists[cbp->reason()]; + static void cbReasonRemove(vluint64_t id, vluint32_t reason) { + // Id might no longer exist, if already removed due to call after event, or teardown + VpioCbList& cbObjList = s_s.m_cbObjLists[reason]; // We do not remove it now as we may be iterating the list, // instead set to nullptr and will cleanup later for (auto& ir : cbObjList) { - if (ir == cbp) ir = nullptr; + if (ir.id() == id) ir.invalidate(); } } - static void cbTimedRemove(VerilatedVpioCb* cbp) { - const auto it = s_s.m_timedCbs.find(std::make_pair(cbp->time(), cbp)); - if (VL_LIKELY(it != s_s.m_timedCbs.end())) s_s.m_timedCbs.erase(it); + static void cbTimedRemove(vluint64_t id, QData time) { + // Id might no longer exist, if already removed due to call after event, or teardown + const auto it = s_s.m_timedCbs.find(std::make_pair(time, id)); + if (VL_LIKELY(it != s_s.m_timedCbs.end())) it->second.invalidate(); } static void callTimedCbs() VL_MT_UNSAFE_ONE { assertOneCheck(); QData time = VL_TIME_Q(); for (auto it = s_s.m_timedCbs.begin(); it != s_s.m_timedCbs.end();) { - if (VL_UNLIKELY(it->first <= time)) { - VerilatedVpioCb* vop = it->second; + if (VL_UNLIKELY(it->first.first <= time)) { + VerilatedVpiCbHolder& ho = it->second; const auto last_it = it; - ++it; // Timed callbacks are one-shot + ++it; + if (VL_UNLIKELY(!ho.invalid())) { + VL_DEBUG_IF_PLI( + VL_DBG_MSGF("- vpi: timed_callback id=%" VL_PRI64 "d\n", ho.id());); + ho.invalidate(); // Timed callbacks are one-shot + (ho.cb_rtnp())(ho.cb_datap()); + } s_s.m_timedCbs.erase(last_it); - VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: timed_callback %p\n", vop);); - (vop->cb_rtnp())(vop->cb_datap()); } else { ++it; } @@ -465,7 +572,7 @@ public: } static QData cbNextDeadline() { const auto it = s_s.m_timedCbs.cbegin(); - if (VL_LIKELY(it != s_s.m_timedCbs.cend())) return it->first; + if (VL_LIKELY(it != s_s.m_timedCbs.cend())) return it->first.first; return ~0ULL; // maxquad } static bool callCbs(vluint32_t reason) VL_MT_UNSAFE_ONE { @@ -476,16 +583,18 @@ public: for (auto it = cbObjList.begin(); true;) { // cbReasonRemove sets to nullptr, so we know on removal the old end() will still exist bool was_last = it == last; - if (VL_UNLIKELY(!*it)) { // Deleted earlier, cleanup + if (VL_UNLIKELY(it->invalid())) { // Deleted earlier, cleanup it = cbObjList.erase(it); if (was_last) break; continue; } - VerilatedVpioCb* vop = *it++; - VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: reason_callback %d %p\n", reason, vop);); - (vop->cb_rtnp())(vop->cb_datap()); + VerilatedVpiCbHolder& ho = *it; + VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: reason_callback reason=%d id=%" VL_PRI64 "d\n", + reason, ho.id());); + (ho.cb_rtnp())(ho.cb_datap()); called = true; if (was_last) break; + ++it; } return called; } @@ -500,24 +609,25 @@ public: for (auto it = cbObjList.begin(); true;) { // cbReasonRemove sets to nullptr, so we know on removal the old end() will still exist bool was_last = it == last; - if (VL_UNLIKELY(!*it)) { // Deleted earlier, cleanup + if (VL_UNLIKELY(it->invalid())) { // Deleted earlier, cleanup it = cbObjList.erase(it); if (was_last) break; continue; } - VerilatedVpioCb* vop = *it++; - if (VerilatedVpioVar* varop = VerilatedVpioVar::castp(vop->cb_datap()->obj)) { + VerilatedVpiCbHolder& ho = *it++; + if (VerilatedVpioVar* varop = VerilatedVpioVar::castp(ho.cb_datap()->obj)) { void* newDatap = varop->varDatap(); void* prevDatap = varop->prevDatap(); // Was malloced when we added the callback VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: value_test %s v[0]=%d/%d %p %p\n", varop->fullname(), *((CData*)newDatap), *((CData*)prevDatap), newDatap, prevDatap);); if (memcmp(prevDatap, newDatap, varop->entSize()) != 0) { - VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: value_callback %p %s v[0]=%d\n", vop, - varop->fullname(), *((CData*)newDatap));); + VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: value_callback %" VL_PRI64 + "d %s v[0]=%d\n", + ho.id(), varop->fullname(), *((CData*)newDatap));); update.insert(varop); - vpi_get_value(vop->cb_datap()->obj, vop->cb_datap()->value); - (vop->cb_rtnp())(vop->cb_datap()); + vpi_get_value(ho.cb_datap()->obj, ho.cb_datap()->value); + (ho.cb_rtnp())(ho.cb_datap()); called = true; } } @@ -616,6 +726,17 @@ bool VerilatedVpi::callCbs(vluint32_t reason) VL_MT_UNSAFE_ONE { QData VerilatedVpi::cbNextDeadline() VL_MT_UNSAFE_ONE { return VerilatedVpiImp::cbNextDeadline(); } +PLI_INT32 VerilatedVpioTimedCb::dovpi_remove_cb() { + VerilatedVpiImp::cbTimedRemove(m_id, m_time); + delete this; // IEEE 37.2.2 a vpi_remove_cb does a vpi_release_handle + return 1; +} +PLI_INT32 VerilatedVpioReasonCb::dovpi_remove_cb() { + VerilatedVpiImp::cbReasonRemove(m_id, m_reason); + delete this; // IEEE 37.2.2 a vpi_remove_cb does a vpi_release_handle + return 1; +} + //====================================================================== // VerilatedVpiImp implementation @@ -1018,6 +1139,9 @@ void VerilatedVpiError::selfTest() VL_MT_UNSAFE_ONE { // callback related vpiHandle vpi_register_cb(p_cb_data cb_data_p) { + // Returns handle so user can remove the callback, user must vpi_release_handle it + // Don't confuse with the callback-activated t_cb_data object handle + // which is the object causing the callback rather than the callback itself VerilatedVpiImp::assertOneCheck(); _VL_VPI_ERROR_RESET(); // cppcheck-suppress nullPointer @@ -1029,10 +1153,10 @@ vpiHandle vpi_register_cb(p_cb_data cb_data_p) { case cbAfterDelay: { QData time = 0; if (cb_data_p->time) time = _VL_SET_QII(cb_data_p->time->high, cb_data_p->time->low); - VerilatedVpioCb* vop = new VerilatedVpioCb(cb_data_p, VL_TIME_Q() + time); - VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_register_cb %d %p delay=%" VL_PRI64 "u\n", - cb_data_p->reason, vop, time);); - VerilatedVpiImp::cbTimedAdd(vop); + QData abstime = VL_TIME_Q() + time; + vluint64_t id = VerilatedVpiImp::nextCallbackId(); + VerilatedVpioTimedCb* vop = new VerilatedVpioTimedCb{id, abstime}; + VerilatedVpiImp::cbTimedAdd(id, cb_data_p, abstime); return vop->castVpiHandle(); } case cbReadWriteSynch: // FALLTHRU // Supported via vlt_main.cpp @@ -1045,9 +1169,9 @@ vpiHandle vpi_register_cb(p_cb_data cb_data_p) { case cbEnterInteractive: // FALLTHRU // NOP, but need to return handle, so make object case cbExitInteractive: // FALLTHRU // NOP, but need to return handle, so make object case cbInteractiveScopeChange: { // FALLTHRU // NOP, but need to return handle, so make object - VerilatedVpioCb* vop = new VerilatedVpioCb(cb_data_p, 0); - VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_register_cb %d %p\n", cb_data_p->reason, vop);); - VerilatedVpiImp::cbReasonAdd(vop); + vluint64_t id = VerilatedVpiImp::nextCallbackId(); + VerilatedVpioReasonCb* vop = new VerilatedVpioReasonCb{id, cb_data_p->reason}; + VerilatedVpiImp::cbReasonAdd(id, cb_data_p); return vop->castVpiHandle(); } default: @@ -1060,15 +1184,10 @@ vpiHandle vpi_register_cb(p_cb_data cb_data_p) { PLI_INT32 vpi_remove_cb(vpiHandle cb_obj) { VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_remove_cb %p\n", cb_obj);); VerilatedVpiImp::assertOneCheck(); - VerilatedVpioCb* vop = VerilatedVpioCb::castp(cb_obj); _VL_VPI_ERROR_RESET(); + VerilatedVpio* vop = VerilatedVpio::castp(cb_obj); if (VL_UNLIKELY(!vop)) return 0; - if (vop->cb_datap()->reason == cbAfterDelay) { - VerilatedVpiImp::cbTimedRemove(vop); - } else { - VerilatedVpiImp::cbReasonRemove(vop); - } - return 1; + return vop->dovpi_remove_cb(); } void vpi_get_cb_info(vpiHandle /*object*/, p_cb_data /*cb_data_p*/) { _VL_VPI_UNIMP(); } @@ -1137,8 +1256,11 @@ vpiHandle vpi_handle_by_index(vpiHandle object, PLI_INT32 indx) { // Used to get array entries VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_handle_by_index %p %d\n", object, indx);); VerilatedVpiImp::assertOneCheck(); - VerilatedVpioVar* varop = VerilatedVpioVar::castp(object); _VL_VPI_ERROR_RESET(); + // Memory words are not indexable + VerilatedVpioMemoryWord* vop = VerilatedVpioMemoryWord::castp(object); + if (VL_UNLIKELY(vop)) return nullptr; + VerilatedVpioVar* varop = VerilatedVpioVar::castp(object); if (VL_LIKELY(varop)) { if (varop->varp()->dims() < 2) return nullptr; if (VL_LIKELY(varop->varp()->unpacked().left() >= varop->varp()->unpacked().right())) { @@ -1249,7 +1371,7 @@ vpiHandle vpi_iterate(PLI_INT32 type, vpiHandle object) { VerilatedVpiError::strFromVpiMethod(type), vop->fullname(), vop->varp()->dims()); } - return ((new VerilatedVpioRange(vop->rangep()))->castVpiHandle()); + return ((new VerilatedVpioRangeIter(vop->rangep()))->castVpiHandle()); } case vpiReg: { VerilatedVpioScope* vop = VerilatedVpioScope::castp(object); @@ -1991,9 +2113,8 @@ PLI_INT32 vpi_chk_error(p_vpi_error_info error_info_p) { } PLI_INT32 vpi_free_object(vpiHandle object) { - VerilatedVpiImp::assertOneCheck(); - _VL_VPI_ERROR_RESET(); - return vpi_release_handle(object); // Deprecated + // vpi_free_object is IEEE deprecated, use vpi_release_handle + return vpi_release_handle(object); } PLI_INT32 vpi_release_handle(vpiHandle object) { @@ -2002,7 +2123,6 @@ PLI_INT32 vpi_release_handle(vpiHandle object) { VerilatedVpio* vop = VerilatedVpio::castp(object); _VL_VPI_ERROR_RESET(); if (VL_UNLIKELY(!vop)) return 0; - vpi_remove_cb(object); // May not be a callback, but that's ok VL_DO_DANGLING(delete vop, vop); return 1; } diff --git a/include/verilated_vpi.h b/include/verilated_vpi.h index eebb3736b..9efa044e8 100644 --- a/include/verilated_vpi.h +++ b/include/verilated_vpi.h @@ -1,7 +1,7 @@ // -*- mode: C++; c-file-style: "cc-mode" -*- //************************************************************************* // -// Copyright 2009-2020 by Wilson Snyder. This program is free software; you can +// Copyright 2009-2021 by Wilson Snyder. This program is free software; you can // redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/include/verilatedos.h b/include/verilatedos.h index abe297843..d4625e643 100644 --- a/include/verilatedos.h +++ b/include/verilatedos.h @@ -1,7 +1,7 @@ // -*- mode: C++; c-file-style: "cc-mode" -*- //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you can +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you can // redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -118,7 +118,7 @@ # define VL_PREFETCH_RW(p) ///< Prefetch data with read/write intent #endif -#ifdef VL_THREADED +#if defined(VL_THREADED) && !defined(VL_CPPCHECK) # if defined(_MSC_VER) && _MSC_VER >= 1900 # define VL_THREAD_LOCAL thread_local # elif defined(__GNUC__) @@ -450,7 +450,7 @@ typedef unsigned long long vluint64_t; ///< 64-bit unsigned type # define NOMINMAX # include "Windows.h" # define VL_CPU_RELAX() YieldProcessor() -# elif defined(__i386__) || defined(__x86_64__) +# elif defined(__i386__) || defined(__x86_64__) || defined(VL_CPPCHECK) /// For more efficient busy waiting on SMT CPUs, let the processor know /// we're just waiting so it can let another thread run # define VL_CPU_RELAX() asm volatile("rep; nop" ::: "memory") diff --git a/include/vltstd/svdpi.h b/include/vltstd/svdpi.h index f77630af7..6b560e2cf 100644 --- a/include/vltstd/svdpi.h +++ b/include/vltstd/svdpi.h @@ -102,7 +102,7 @@ typedef uint32_t svBitVecVal; * Because the contents of the unused bits is undetermined, * the following macros can be handy. */ -#define SV_MASK(N) (~(-1 << (N))) +#define SV_MASK(N) (~(0xffffffffU << (N))) #define SV_GET_UNSIGNED_BITS(VALUE, N) \ ((N) == 32 ? (VALUE) : ((VALUE) & SV_MASK(N))) diff --git a/nodist/bisondiff b/nodist/bisondiff deleted file mode 100755 index f925c15a2..000000000 --- a/nodist/bisondiff +++ /dev/null @@ -1,82 +0,0 @@ -#!/usr/bin/env perl -###################################################################### -# -# Copyright 2007-2020 by Wilson Snyder. This program is free software; you -# can redistribute it and/or modify it under the terms of either the GNU -# Lesser General Public License Version 3 or the Perl Artistic License -# Version 2.0. -# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 -# -###################################################################### - -# DESCRIPTION: Diff bison files - -use warnings; -use Getopt::Long; -use IO::File; -use strict; - -our $Debug; -our $Opt_Unsup; - -if (! GetOptions ( - #"help" => \&usage, - "debug" => sub { $Debug = 1; }, - "unsup!" => \$Opt_Unsup, # Ignore unsupported - )) { - die "usage();" -} - -diff($ARGV[0],$ARGV[1]); - -sub diff { - my $a=shift; - my $b=shift; - - my $ta = "/tmp/bisondiff.$$.a"; - my $tb = "/tmp/bisondiff.$$.b"; - - prep($a,$ta); - prep($b,$tb); - - system("diff -u -w $ta $tb"); -} - -sub prep { - my $filename = shift; - my $wfilename = shift; - - my $fh = IO::File->new("<$filename") or die "%Error: $! $filename"; - my $fho = IO::File->new(">$wfilename") or die "%Error: $! writing $wfilename"; - - my %declared; - my %used; - - my $body = 0; - my $rule = ""; - my $skip = 1; - while (defined(my $line = $fh->getline)) { - if ($skip == 1) { - next if $line !~ /%token/; - $skip = 2; - } - - if ($Opt_Unsup) { - $line =~ s!//UNSUP!|!g; - $line =~ s!(\s+)\|(\s+)!$1$2!g; # As "UNSUP" often replaces "|" - } - - # %type - $line =~ s/^(%\S+)<(\S+)>/$1/; - # rule - $line =~ s/^([a-zA-Z0-9_]+)<\S+>:/$1:/; - # Productions - $line =~ s/[ \t]{[^}]*?}/\t{}/g; - - $fho->print($line); - } -} - -# Local Variables: -# compile-command: "./bisondiff --unsup $VP/Parser/VParseBison.y ../src/verilog.y" -# End: diff --git a/nodist/code_coverage b/nodist/code_coverage index 598d5b94a..ce797e942 100755 --- a/nodist/code_coverage +++ b/nodist/code_coverage @@ -1,509 +1,398 @@ -#!/usr/bin/env perl -# See copyright, etc in below POD section. +#!/usr/bin/env python3 ###################################################################### -use warnings; -use Cwd; -use File::Copy qw(cp); -use File::Path qw(mkpath); -use File::Spec; -use FindBin qw($RealBin); -use Getopt::Long; -use Parallel::Forker; -use Unix::Processors; -use IO::File; -use Pod::Usage; -use strict; -use vars qw($Debug); +import argparse +import glob +import multiprocessing +import os +import re +import subprocess -our $Opt_Stop = 1; -our $Opt_Fastcov = 1; -our $Exclude_Branch_Regexp; -our $Exclude_Line_Regexp; -our $Remove_Gcda_Regexp; +RealPath = os.path.dirname(os.path.realpath(__file__)) +Exclude_Branch_Regexps = [] +Exclude_Line_Regexps = [] +Remove_Gcda_Regexps = [] +Remove_Sources = [] +Source_Globs = [] -our @Remove_Sources; -our @Source_Globs; +if 'VERILATOR_ROOT' not in os.environ: + os.environ['VERILATOR_ROOT'] = os.getcwd() -our $Fork = new Parallel::Forker(use_sig_child => 1, poll_interval => 10*1000); -$Fork->max_proc(Unix::Processors->new->max_online * 1.5); -$SIG{CHLD} = sub { Parallel::Forker::sig_child($Fork); }; -$SIG{TERM} = sub { $Fork->kill_tree_all('TERM') if $Fork && $Fork->in_parent; die "Quitting...\n"; }; +###################################################################### -#====================================================================== -# main -our $Opt_Hashset; -our $opt_stages = ''; -our $Opt_Scenarios; -our %Opt_Stages; -our @Opt_Tests; +def test(): + if not os.path.exists("nodist/code_coverage.dat"): + sys.exit("%Error: Run code_coverage from the top of the verilator kit") + exec(open("./nodist/code_coverage.dat").read()) -autoflush STDOUT 1; -autoflush STDERR 1; -Getopt::Long::config("no_auto_abbrev"); -if (! GetOptions( - "debug" => sub { $Debug = 1; }, - "hashset=s" => \$Opt_Hashset, # driver.pl hashset - "<>" => sub { die "%Error: Unknown parameter: $_[0]\n"; }, - "fastcov!" => \$Opt_Fastcov, # use fastcov, not documented, for debug - "scenarios=s" => \$Opt_Scenarios, # driver.pl scenarios - "stage=s" => \$opt_stages, # starting stage number - "stages=s" => \$opt_stages, # starting stage number - "stop!" => \$Opt_Stop, # stop/do not stop on error in tests - "test=s@" => \@Opt_Tests, # test name - )) { - die "%Error: Bad usage, try 'code_coverage --help'\n"; -} - -{ - my $start = 0; - my $end = 99; - if ($opt_stages && $opt_stages =~ /^(\d+)$/) { - $start = $end = $1; - } elsif ($opt_stages && $opt_stages =~ /^(\d+)-(\d+$)$/) { - $start = $1; $end = $2; - } elsif ($opt_stages && $opt_stages =~ /^-(\d+$)$/) { - $end = $1; - } elsif ($opt_stages && $opt_stages =~ /^(\d+)-$/) { - $start = $1; - } elsif ($opt_stages) { - die "%Error: --stages not understood: $opt_stages,"; - } - for (my $n = $start; $n <= $end; ++$n) { $Opt_Stages{$n} = 1; } -} - -test(); -exit(0); - -####################################################################### - -sub test { - -r "nodist/code_coverage.dat" or die "%Error: Run from the top of the verilator kit,"; - require "./nodist/code_coverage.dat"; - - if ($Opt_Stages{1}) { - ci_fold_start("configure"); - print "Stage 1: configure (coverage on)\n"; - run("make distclean || true"); - run("autoconf"); + if Args.stage_enabled[1]: + ci_fold_start("configure") + print("Stage 1: configure (coverage on)") + run("make distclean || true") + run("autoconf") # Exceptions can pollute the branch coverage data - run("./configure --enable-longtests CXX='g++ --coverage -fno-exceptions -DVL_GCOV'"); - ci_fold_end(); - } + run("./configure --enable-longtests CXX='g++ --coverage -fno-exceptions -DVL_GCOV'" + ) + ci_fold_end() - if ($Opt_Stages{2}) { - ci_fold_start("build"); - print "Stage 2: build\n"; - my $nproc = Unix::Processors->new->max_online; - run("make -k -j $nproc VERILATOR_NO_OPT_BUILD=1"); + if Args.stage_enabled[2]: + ci_fold_start("build") + print("Stage 2: build") + nproc = multiprocessing.cpu_count() + run("make -k -j " + str(nproc) + " VERILATOR_NO_OPT_BUILD=1") # The optimized versions will not collect good coverage, overwrite them - run("cp bin/verilator_bin_dbg bin/verilator_bin"); - run("cp bin/verilator_coverage_bin_dbg bin/verilator_coverage_bin"); - ci_fold_end(); - } + run("cp bin/verilator_bin_dbg bin/verilator_bin") + run("cp bin/verilator_coverage_bin_dbg bin/verilator_coverage_bin") + ci_fold_end() - if ($Opt_Stages{3}) { - ci_fold_start("test"); - print "Stage 3: make tests (with coverage on)\n"; - if ($#Opt_Tests < 0) { - run("make examples VERILATOR_NO_OPT_BUILD=1") - if !$Opt_Scenarios || $Opt_Scenarios =~ /dist/i; - run("make test_regress VERILATOR_NO_OPT_BUILD=1" - . ($Opt_Scenarios ? " SCENARIOS='".$Opt_Scenarios."'" : "") - . ($Opt_Hashset ? " DRIVER_HASHSET='--hashset=".$Opt_Hashset."'" : "") - . ($Opt_Stop ? '' : ' || true')); - } else { - foreach my $test (@Opt_Tests) { - if (! -f $test && -f "test_regress/t/${test}") { - $test = "test_regress/t/${test}"; - } - run($test); - } - } - ci_fold_end(); - } + if Args.stage_enabled[3]: + ci_fold_start("test") + print("Stage 3: make tests (with coverage on)") + if not Args.tests: + if not Args.scenarios or re.match('dist', Args.scenarios): + run("make examples VERILATOR_NO_OPT_BUILD=1") + run("make test_regress VERILATOR_NO_OPT_BUILD=1" + + (" SCENARIOS='" + Args.scenarios + + "'" if Args.scenarios else "") + + (" DRIVER_HASHSET='--hashset=" + Args.hashset + + "'" if Args.hashset else "") + + ('' if Args.stop else ' || true')) + else: + for test in Args.tests: + if not os.path.exists(test) and os.path.exists( + "test_regress/t/" + test): + test = "test_regress/t/" + test + run(test) + ci_fold_end() - my $cc_dir = "nodist/obj_dir/coverage"; - if ($Opt_Stages{4}) { - ci_fold_start("gcno"); - print "Stage 4: Create gcno files under $cc_dir\n"; - mkpath($cc_dir); - mkpath("$cc_dir/info"); - my $dats = `find . -print | grep .gcda`; - my %dats; - foreach my $dat (split '\n', $dats) { - $dats{$dat} = 1; - } - foreach my $dat (sort keys %dats) { - (my $gcno = $dat) =~ s!\.gcda$!.gcno!; - if ($dat =~ /$Remove_Gcda_Regexp/) { - # Remove .gcda/.gcno for files we don't care about before we slowly - # read them - unlink $dat; - unlink $gcno; - delete $dats{$dat}; - next; - } - } - $dats = `find . -print | grep .gcno`; - my %gcnos; - foreach my $gcno (split '\n', $dats) { - (my $gbase = $gcno) =~ s!.*/!!; - $gcnos{$gbase} = File::Spec->rel2abs($gcno); - } + cc_dir = "nodist/obj_dir/coverage" + if Args.stage_enabled[4]: + ci_fold_start("gcno") + print("Stage 4: Create gcno files under " + cc_dir) + os.makedirs(cc_dir, exist_ok=True) + os.makedirs(cc_dir + "/info", exist_ok=True) + + sp = subprocess.Popen("find . -print | grep .gcda", + shell=True, + stdout=subprocess.PIPE) + datout = sp.stdout.read() + dats = {} + for dat in datout.splitlines(): + dat = dat.decode('utf-8') + dats[dat] = 1 + for dat in sorted(dats.keys()): + gcno = re.sub(r'\.gcda$', '.gcno', dat) + for regexp in Remove_Gcda_Regexps: + if re.search(regexp, dat): + # Remove .gcda/.gcno for files we don't care about before we slowly + # read them + os.unlink(dat) + os.unlink(gcno) + del dats[dat] + break + + sp = subprocess.Popen("find . -print | grep .gcno", + shell=True, + stdout=subprocess.PIPE) + datout = sp.stdout.read() + gcnos = {} + for gcno in datout.splitlines(): + gcno = gcno.decode('utf-8') + gbase = re.sub(r'.*/', '', gcno, count=1) + gcnos[gbase] = os.path.abspath(gcno) # We need a matching .gcno for every .gcda, try to find a matching file elsewhere - foreach my $dat (sort keys %dats) { - (my $gcno = $dat) =~ s!\.gcda$!.gcno!; - (my $gbase = $gcno) =~ s!.*/!!; - if (!-r $gcno) { - if ($gcnos{$gbase}) { - symlink($gcnos{$gbase}, $gcno) - or die "%Error: can't ln -s $gcnos{$gbase} $gcno,"; - } else { - warn "MISSING .gcno for a .gcda: $gcno\n"; - } - } - } - ci_fold_end(); - } + for dat in sorted(dats): + gcno = re.sub(r'\.gcda$', '.gcno', dat) + gbase = re.sub(r'.*/', '', gcno, count=1) + if not os.path.exists(gcno): + if gbase in gcnos: + os.symlink(gcnos[gbase], gcno) + else: + print("MISSING .gcno for a .gcda: " + gcno, + file=sys.stderr) + ci_fold_end() - if ($Opt_Stages{5} && $Opt_Fastcov) { - ci_fold_start("fastcov"); + if Args.stage_enabled[5]: + ci_fold_start("fastcov") # Must run in root directory to find all files - mkpath($cc_dir); - #run("${RealBin}/fastcov.py -b -c src/obj_dbg -X". - # " --exclude /usr --exclude test_regress" - # ." -o ${cc_dir}/app_total.json"); - run("${RealBin}/fastcov.py -b -c src/obj_dbg -X --lcov". - " --exclude /usr --exclude test_regress" - ." -o ${cc_dir}/app_total.info"); - ci_fold_end(); - } + os.makedirs(cc_dir, exist_ok=True) + run(RealPath + "/fastcov.py -b -c src/obj_dbg -X --lcov" + + " --exclude /usr --exclude test_regress" + " -o " + cc_dir + + "/app_total.info") + ci_fold_end() - if ($Opt_Stages{5} && !$Opt_Fastcov) { - ci_fold_start("infos"); - print "Stage 5: make infos\n"; - my $dats = `find . -print | grep .gcda`; - my %dirs; - foreach my $dat (split '\n', $dats) { - (my $dir = $dat) =~ s!/[^/]+$!!; - $dirs{$dir} = 1; - } - - foreach my $dir (sort keys %dirs) { - (my $outname = $dir) =~ s![^a-zA-Z0-9]+!_!g; - $Fork->schedule(run_on_start => sub { - # .info may be empty, so ignore errors (unfortunately) - run("cd $cc_dir/info ; lcov -c -d ../../../../$dir --exclude /usr -o app_test_${outname}.info || true"); - })->run; - } - $Fork->wait_all; - ci_fold_end(); - } - - if ($Opt_Stages{6}) { - ci_fold_start("clone"); + if Args.stage_enabled[6]: + ci_fold_start("clone") # No control file to override single lines, so replicate the sources # Also lets us see the insertion markers in the HTML source res - print "Stage 6: Clone sources under $cc_dir\n"; - clone_sources($cc_dir); - ci_fold_end(); - } + print("Stage 6: Clone sources under " + cc_dir) + clone_sources(cc_dir) + ci_fold_end() - if ($Opt_Stages{8} && !$Opt_Fastcov) { - ci_fold_start("copy"); - print "Stage 8: Copy .gcno files\n"; - my $dats = `find . -print | grep .gcno`; - foreach my $dat (sort (split '\n', $dats)) { - next if $dat =~ /$cc_dir/; - my $outdat = $cc_dir."/".$dat; - #print "cp $dat, $outdat);\n"; - cp($dat, $outdat); - } - ci_fold_end(); - } + if Args.stage_enabled[11]: + ci_fold_start("dirs") + print("Stage 11: Cleanup paths") + cleanup_abs_paths_info(cc_dir, cc_dir + "/app_total.info", + cc_dir + "/app_total.info") + ci_fold_end() - if ($Opt_Stages{10} && !$Opt_Fastcov) { - ci_fold_start("combine"); - print "Stage 10: Combine data files\n"; - { - run("cd $cc_dir ; lcov -c -i -d src/obj_dbg -o app_base.info"); - run("cd $cc_dir ; lcov -a app_base.info -o app_total.info"); - my $infos = `cd $cc_dir ; find info -print | grep .info`; - my $comb = ""; - my @infos = (sort (split /\n/, $infos)); - foreach my $info (@infos) { - $comb .= " -a $info"; - # Need to batch them to avoid overrunning shell command length limit - if (length($comb) > 10000 || $info eq $infos[$#infos]) { - # .info may be empty, so ignore errors (unfortunately) - run("cd $cc_dir ; lcov -a app_total.info $comb -o app_total.info || true"); - $comb = ""; - } - } - } - ci_fold_end(); - } - - if ($Opt_Stages{11}) { - ci_fold_start("dirs"); - print "Stage 11: Cleanup paths\n"; - if ($Opt_Fastcov) { - cleanup_abs_paths_info($cc_dir, "$cc_dir/app_total.info", "$cc_dir/app_total.info"); - #cleanup_abs_paths_json($cc_dir, "$cc_dir/app_total.json", "$cc_dir/app_total.json"); - } else { - cleanup_abs_paths_info($cc_dir, "$cc_dir/app_total.info", "$cc_dir/app_total.info"); - } - ci_fold_end(); - } - - if ($Opt_Stages{12}) { - ci_fold_start("filter"); - print "Stage 12: Filter processed source files\n"; - my $inc = ''; - foreach my $glob (@Source_Globs) { - foreach my $infile (glob $glob) { - $inc .= " '$infile'"; - } - } - my $exc = ''; - foreach my $glob (@Remove_Sources) { + if Args.stage_enabled[12]: + ci_fold_start("filter") + print("Stage 12: Filter processed source files") + inc = '' + for globf in Source_Globs: + for infile in glob.glob(globf): + inc += " '" + infile + "'" + exc = '' + for globf in Remove_Sources: # Fastcov does exact match not globbing at present # Lcov requires whole path match so needs the glob - $glob =~ s!^\*!! if $Opt_Fastcov; - $glob =~ s!\*$!! if $Opt_Fastcov; - $exc .= " '$glob'"; - } - if ($Opt_Fastcov) { - $inc = "--include ".$inc if $inc ne ''; - $exc = "--exclude ".$exc if $exc ne ''; - run("cd $cc_dir ; ${RealBin}/fastcov.py -C app_total.info ${inc} ${exc} -x --lcov -o app_total_f.info"); - } else { - run("cd $cc_dir ; lcov --remove app_total.info $exc -o app_total_f.info"); - } - ci_fold_end(); - } + globf = re.sub(r'^\*', '', globf) + globf = re.sub(r'\*$', '', globf) + exc += " '" + globf + "'" + if inc != '': + inc = "--include " + inc + if exc != '': + exc = "--exclude " + exc + run("cd " + cc_dir + " ; " + RealPath + + "/fastcov.py -C app_total.info " + inc + " " + exc + + " -x --lcov -o app_total_f.info") + ci_fold_end() - if ($Opt_Stages{17}) { - ci_fold_start("report"); - print "Stage 17: Create HTML\n"; - run("cd $cc_dir ; genhtml app_total_f.info --demangle-cpp" - ." --rc lcov_branch_coverage=1 --rc genhtml_hi_limit=100 --output-directory html"); - ci_fold_end(); - } + if Args.stage_enabled[17]: + ci_fold_start("report") + print("Stage 17: Create HTML") + run("cd " + cc_dir + " ; genhtml app_total_f.info --demangle-cpp" + + " --rc lcov_branch_coverage=1 --rc genhtml_hi_limit=100 --output-directory html" + ) + ci_fold_end() - if ($Opt_Stages{18}) { - ci_fold_start("upload"); - print "Stage 18: Upload\n"; - my $cmd = "bash <(curl -s https://codecov.io/bash) -f $cc_dir/app_total.info"; - print "print: Not running: export CODECOV_TOKEN=\n"; - print "print: Not running: $cmd\n"; - ci_fold_end(); - } + if Args.stage_enabled[18]: + ci_fold_start("upload") + print("Stage 18: Upload") + cmd = "bash <(curl -s https://codecov.io/bash) -f " + cc_dir + "/app_total.info" + print("print: Not running: export CODECOV_TOKEN=") + print("print: Not running: " + cmd) + ci_fold_end() - if ($Opt_Stages{19}) { - print "*-* All Finished *-*\n"; - print "\n"; - print "* See report in ${cc_dir}/html/index.html\n"; - print "* Remember to make distclean && ./configure before working on non-coverage\n"; - } -} + if Args.stage_enabled[19]: + print("*-* All Finished *-*") + print("") + print("* See report in " + cc_dir + "/html/index.html") + print( + "* Remember to make distclean && ./configure before working on non-coverage" + ) -sub clone_sources { - my $cc_dir = shift; - my $excluded_lines = 0; - my $excluded_br_lines = 0; - foreach my $glob (@Source_Globs) { - foreach my $infile (glob $glob) { - $infile !~ m!^/! - or die "%Error: source globs should be relative not absolute filenames,"; - my $outfile = $cc_dir."/".$infile; - (my $outpath = $outfile) =~ s!/[^/]*$!!; - mkpath($outpath); - my $fh = IO::File->new("<$infile") or die "%Error: $! $infile,"; - my $ofh = IO::File->new(">$outfile") or die "%Error: $! $outfile,"; - my $lineno = 0; - while (defined(my $line = $fh->getline)) { - $lineno++; - chomp $line; - if ($line =~ /LCOV_EXCL_LINE/) { - $line .= " LCOV_EXCL_BR_LINE"; - } - elsif ($line =~ /LCOV_EXCL_START/) { - $line .= " LCOV_EXCL_BR_START"; - } - elsif ($line =~ /LCOV_EXCL_STOP/) { - $line .= " LCOV_EXCL_BR_STOP"; - } - elsif ($line =~ /$Exclude_Line_Regexp/) { - $line .= " //code_coverage: // LCOV_EXCL_LINE LCOV_EXCL_BR_LINE"; - $excluded_lines++; - $excluded_br_lines++; - #print "$infile:$lineno: $line"; - } - elsif ($line =~ /$Exclude_Branch_Regexp/) { - $line .= " //code_coverage: // LCOV_EXCL_BR_LINE"; - $excluded_br_lines++; - #print "$infile:$lineno: $line"; - } - $ofh->print("$line\n"); - } - } - } - print "Number of source lines automatically LCOV_EXCL_LINE'ed: $excluded_lines\n"; - print "Number of source lines automatically LCOV_EXCL_BR_LINE'ed: $excluded_br_lines\n"; -} -sub cleanup_abs_paths_info { - my $cc_dir = shift; - my $infile = shift; - my $outfile = shift; - my $fh = IO::File->new("<$infile") or die "%Error: $! $infile,"; - my @lines; - while (defined(my $line = $fh->getline)) { - if ($line =~ m!^SF:!) { - $line =~ s!$ENV{VERILATOR_ROOT}/!!; - $line =~ s!$cc_dir/!!; - $line =~ s!obj_dbg/verilog.y$!verilog.y!; - #print "Remaining SF: ",$line; - } - push @lines, $line; - } - my $ofh = IO::File->new(">$outfile") or die "%Error: $! $outfile,"; - $ofh->print(@lines); -} +def clone_sources(cc_dir): + excluded_lines = 0 + excluded_br_lines = 0 + for globf in Source_Globs: + for infile in glob.glob(globf): + if re.match(r'^/', infile): + sys.exit( + "%Error: source globs should be relative not absolute filenames, " + + infile) + outfile = cc_dir + "/" + infile + outpath = re.sub(r'/[^/]*$', '', outfile, count=1) + os.makedirs(outpath, exist_ok=True) + with open(infile) as fh: + with open(outfile, "w") as ofh: + lineno = 0 + for line in fh: + lineno += 1 + line = line.rstrip() + done = False + if re.search(r'LCOV_EXCL_LINE', line): + line += " LCOV_EXCL_BR_LINE" + done = True + elif re.search(r'LCOV_EXCL_START', line): + line += " LCOV_EXCL_BR_START" + done = True + elif re.search(r'LCOV_EXCL_STOP', line): + line += " LCOV_EXCL_BR_STOP" + done = True -sub cleanup_abs_paths_json { - my $cc_dir = shift; - my $infile = shift; - my $outfile = shift; - # Handcrafted cleanup, alternative would be to deserialize/serialize JSON - # But JSON::Parse not installed by default - # JSON::PP more likely to be installed, but slower - my $fh = IO::File->new("<$infile") or die "%Error: $! $infile,"; - my @lines; - while (defined(my $line = $fh->getline)) { - $line =~ s!"$ENV{VERILATOR_ROOT}/!"!g; - $line =~ s!"$cc_dir/!"!g; - $line =~ s!obj_dbg/verilog.y$!verilog.y!g; - push @lines, $line; - } - my $ofh = IO::File->new(">$outfile") or die "%Error: $! $outfile,"; - $ofh->print(@lines); -} + for regexp in Exclude_Line_Regexps: + if done: + break + if re.search(regexp, line): + #print("%s:%d: %s" % (infile, lineno, line) + line += " //code_coverage: // LCOV_EXCL_LINE LCOV_EXCL_BR_LINE" + excluded_lines += 1 + excluded_br_lines += 1 + done = True -####################################################################### + for regexp in Exclude_Branch_Regexps: + if done: + break + if re.search(regexp, line): + #print("%s:%d: %s" % (infile, lineno, line) + line += " //code_coverage: // LCOV_EXCL_BR_LINE" + excluded_br_lines += 1 + done = True + + ofh.write(line + "\n") + print("Number of source lines automatically LCOV_EXCL_LINE'ed: %d" % + excluded_lines) + print("Number of source lines automatically LCOV_EXCL_BR_LINE'ed: %d" % + excluded_br_lines) + + +def cleanup_abs_paths_info(cc_dir, infile, outfile): + lines = [] + with open(infile) as fh: + for line in fh: + if re.search(r'^SF:', line): + line = re.sub(os.environ['VERILATOR_ROOT'] + '/', + '', + line, + count=1) + line = re.sub(cc_dir + '/', '', line, count=1) + line = re.sub(r'obj_dbg/verilog.y$', 'verilog.y', line) + #print("Remaining SF: "+line) + lines.append(line) + + with open(outfile, "w") as ofh: + for line in lines: + ofh.write(line) + + +def cleanup_abs_paths_json(cc_dir, infile, outfile): + # Handcrafted cleanup, alternative would be to deserialize/serialize JSON, + # but this is much faster + lines = [] + with open(infile) as fh: + for line in fh: + line = re.sub('"' + os.environ['VERILATOR_ROOT'] + '/', '"', line) + line = re.sub('"' + cc_dir + '/', '"', line) + line = re.sub(r'obj_dbg/verilog.y$', 'verilog.y', line) + lines.append(line) + + with open(outfile, "w") as ofh: + for line in lines: + ofh.write(line) + + +###################################################################### # .dat file callbacks -sub exclude_branch_regexp { - $Exclude_Branch_Regexp = shift; -} -sub exclude_line_regexp { - $Exclude_Line_Regexp = shift; -} -sub remove_gcda_regexp { - $Remove_Gcda_Regexp = shift; -} -sub remove_source { - my @srcs = @_; - push @Remove_Sources, @srcs; -} -sub source_globs { - my @dirs = @_; - push @Source_Globs, @dirs; -} + +def exclude_branch_regexp(*regexps): + Exclude_Branch_Regexps.extend(regexps) + + +def exclude_line_regexp(*regexps): + Exclude_Line_Regexps.extend(regexps) + + +def remove_gcda_regexp(*regexps): + Remove_Gcda_Regexps.extend(regexps) + + +def remove_source(*sources): + Remove_Sources.extend(sources) + + +def source_globs(*dirs): + Source_Globs.extend(dirs) + ####################################################################### -sub run { - # Run a system command, check errors - my $command = shift; - print "\t$command\n"; - system "$command"; - my $status = $?; - ($status == 0) or die "%Error: Command Failed $command, $status, stopped"; -} -our $_Ci_Action; -sub ci_fold_start { - $_Ci_Action = shift; - print "travis_fold:start:$_Ci_Action\n"; -} -sub ci_fold_end { - print "travis_fold:end:$_Ci_Action\n"; -} +def run(command): + # run a system command, check errors + print("\t%s" % command) + os.system(command) + status = subprocess.call(command, shell=True) + if status < 0: + raise Exception("%Error: Command failed " + command + ", stopped") + + +def ci_fold_start(action): + print("::group::" + action) + + +def ci_fold_end(): + print("::endgroup::\n") + ####################################################################### -__END__ +####################################################################### -=pod - -=head1 NAME - -code_coverage - Build and collect Verilator coverage - -=head1 SYNOPSIS +parser = argparse.ArgumentParser( + allow_abbrev=False, + formatter_class=argparse.RawDescriptionHelpFormatter, + description= + """code_coverage builds Verilator with C++ coverage support and runs +tests with coverage enabled. This will rebuild the current object +files. Run as: cd $VERILATOR_ROOT - nodist/code_coverage - -=head1 DESCRIPTION - -code_coverage builds Verilator with C++ coverage support and runs tests -with coverage enabled. - -This will rebuild the current object files. - -=head1 ARGUMENTS - -=over 4 - -=item --hashset I - -Pass test hashset onto driver.pl test harness. - -=item --help - -Displays this message and program version and exits. - -=item --scenarios I - -Pass test scenarios onto driver.pl test harness. - -=item --stages I - -Runs a specific stage or range of stages (see the script). - -=item --no-stop - -Do not stop collecting data if tests fail. - -=item --test I - -Instead of normal regressions, run the specified test. May be specified -multiple times for multiple tests. - -=back - -=head1 DISTRIBUTION - -Copyright 2019-2020 by Wilson Snyder. This program is free software; you + nodist/code_coverage""", + epilog= + """Copyright 2019-2021 by Wilson Snyder. This program is free software; you can redistribute it and/or modify it under the terms of either the GNU Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. -SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 +SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0""") -=head1 AUTHORS +parser.add_argument('--debug', action='store_true', help='enable debug') +parser.add_argument('--hashset', + action='store', + help='pass test hashset onto driver.pl test harness') +parser.add_argument('--scenarios', + action='store', + help='pass test scenarios onto driver.pl test harness') +parser.add_argument( + '--stages', + action='store', + help='runs a specific stage or range of stages (see the script)') +parser.add_argument( + '--test', + action='append', + dest='tests', + default=[], + help= + 'Instead of normal regressions, run the specified test(s), may be used multiple times' +) +parser.add_argument('--no-stop', + dest='stop', + action='store_false', + help='do not stop collecting data if tests fail') -Wilson Snyder +parser.set_defaults(stop=True) +Args = parser.parse_args() -=head1 SEE ALSO +if True: + start = 0 + end = 99 + Args.stage_enabled = {} + if Args.stages: + match_one = re.match(r'^(\d+)$', Args.stages) + match_range = re.match(r'^(\d+)-(\d+)$', Args.stages) + match_to = re.match(r'^-(\d+)$', Args.stages) + match_from = re.match(r'^(\d+)-$', Args.stages) + if match_one: + start = end = int(match_one.group(1)) + elif match_range: + start = int(match_range.group(1)) + end = int(match_range.group(2)) + elif match_to: + end = int(match_to.group(1)) + elif match_from: + start = int(match_from.group(1)) + else: + os.exit("%Error: --stages not understood: " + Args.stages) + for n in range(1, 100): + Args.stage_enabled[n] = False + for n in range(start, end + 1): + Args.stage_enabled[n] = True -C - -=cut +test() ###################################################################### ### Local Variables: diff --git a/nodist/code_coverage.dat b/nodist/code_coverage.dat index a3a276afa..14f516a59 100644 --- a/nodist/code_coverage.dat +++ b/nodist/code_coverage.dat @@ -1,63 +1,62 @@ -# -*- Perl -*- +# -*- Python -*- # DESCRIPTION: Verilator: Internal C++ code lcov control file # -# Copyright 2019-2020 by Wilson Snyder. This program is free software; you +# Copyright 2019-2021 by Wilson Snyder. This program is free software; you # can redistribute it and/or modify it under the terms of either the GNU # Lesser General Public License Version 3 or the Perl Artistic License # Version 2.0. # SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 -source_globs("src/*.cpp", - "src/*.h", - "src/*.l", - "src/*.y", - "src/obj_dbg/*.h", - "src/obj_dbg/*.cpp", - "include/*.c", - "include/*.cpp", - "include/*.h", - "include/*/*.h", - "include/*/*.cpp", - "include/*/*.c", - ); +source_globs("src/*.cpp") +source_globs("src/*.h") +source_globs("src/*.l") +source_globs("src/*.y") +source_globs("src/obj_dbg/*.h") +source_globs("src/obj_dbg/*.cpp") +source_globs("include/*.c") +source_globs("include/*.cpp") +source_globs("include/*.h") +source_globs("include/*/*.h") +source_globs("include/*/*.cpp") +source_globs("include/*/*.c") # Note *'s are removed when using fastcov -remove_source("/usr/*"); -remove_source("*/include/sysc/*"); -remove_source("*/V3ClkGater.cpp"); -remove_source("*/V3ClkGater.h"); -remove_source("*/V3GraphDfa.cpp"); -remove_source("*/V3GraphDfa.h"); -remove_source("*/V3Lexer_pregen.yy.cpp"); -remove_source("*/V3PreLex_pregen.yy.cpp"); -remove_source("*/verilog.c"); -remove_source("*include/gtkwave/*"); +remove_source("/usr/*") +remove_source("*/include/sysc/*") +remove_source("*/V3ClkGater.cpp") +remove_source("*/V3ClkGater.h") +remove_source("*/V3GraphDfa.cpp") +remove_source("*/V3GraphDfa.h") +remove_source("*/V3Lexer_pregen.yy.cpp") +remove_source("*/V3PreLex_pregen.yy.cpp") +remove_source("*/verilog.c") +remove_source("*include/gtkwave/*") # Something wrong in generation, unfortunately as would like this #genhtml: ERROR: cannot read /svaha/wsnyder/SandBox/homecvs/v4/verilator/src/obj_dbg/verilog.y -#remove_source("*/src/obj_dbg/verilog.y"); -remove_source("*test_regress/*"); -remove_source("*examples/*"); +#remove_source("*/src/obj_dbg/verilog.y") +remove_source("*test_regress/*") +remove_source("*examples/*") # Remove collected coverage on each little test main file # Would just be removed with remove_source in later step -remove_gcda_regexp(qr!test_regress/.*/(Vt_|Vtop_).*\.gcda!); +remove_gcda_regexp(r'test_regress/.*/(Vt_|Vtop_).*\.gcda') # Exclude line entirely, also excludes from function and branch coverage -exclude_line_regexp(qr/(\bv3fatalSrc\b - |\bfatalSrc\b - |\bVL_UNCOVERABLE\b - |\bVL_UNREACHABLE\b - |\bVL_FATAL - |\bUASSERT - |\bNUM_ASSERT - |\bERROR_RSVD_WORD - |\bV3ERROR_NA - |\bUINFO\b)/x); +exclude_line_regexp(r'\bv3fatalSrc\b') +exclude_line_regexp(r'\bfatalSrc\b') +exclude_line_regexp(r'\bVL_UNCOVERABLE\b') +exclude_line_regexp(r'\bVL_UNREACHABLE\b') +exclude_line_regexp(r'\bVL_FATAL') +exclude_line_regexp(r'\bUASSERT') +exclude_line_regexp(r'\bNUM_ASSERT') +exclude_line_regexp(r'\bERROR_RSVD_WORD') +exclude_line_regexp(r'\bV3ERROR_NA') +exclude_line_regexp(r'\bUINFO\b') # Exclude for branch coverage only -exclude_branch_regexp(qr/(\bdebug\(\) - |\bassert\( - |\bBROKEN_RTK\( - |\bSELF_CHECK)/x); +exclude_branch_regexp(r'\bdebug\(\)') +exclude_branch_regexp(r'\bassert\(') +exclude_branch_regexp(r'\bBROKEN_RTK\(') +exclude_branch_regexp(r'\bSELF_CHECK') -1; +True diff --git a/nodist/dot_importer b/nodist/dot_importer index d44d02f61..2ff96c4e3 100755 --- a/nodist/dot_importer +++ b/nodist/dot_importer @@ -1,164 +1,109 @@ -#!/usr/bin/env perl -# See copyright, etc in below POD section. +#!/usr/bin/env python3 ###################################################################### -use warnings; -use Getopt::Long; -use IO::File; -use Pod::Usage; -use Data::Dumper; $Data::Dumper::Indent=1; -use strict; -use vars qw($Debug); +import argparse +import re -#====================================================================== +###################################################################### -our @Header; -our %Vertexes; -our @Edges; -our %Edges; +Header = [] +Vertexes = [] +Edges = [] -#====================================================================== +####################################################################### + + +def dotread(filename): + with open(filename) as fh: + header = True + vnum = 0 + + vertex_re = re.compile(r'^\t([a-zA-Z0-9_]+)\t(.*)$') + edge_re = re.compile( + r'^\t([a-zA-Z0-9_]+)\s+->\s+([a-zA-Z0-9_]+)\s*(.*)$') + + for line in fh: + vertex_match = re.search(vertex_re, line) + edge_match = re.search(edge_re, line) + if vertex_match: + if vertex_match.group(1) != 'nTITLE': + header = False + Vertexes.append({ + 'num': vnum, + 'line': line, + 'name': vertex_match.group(1) + }) + vnum += 1 + elif edge_match: + fromv = edge_match.group(1) + tov = edge_match.group(2) + w = re.match(r'weight=(\d+)', line) + weight = w.group(1) if w else 1 + w = re.match(r'style=(\S+)', line) + cutable = w.group(1) if w else None + edge = { + 'num': vnum, + 'line': line, + 'weight': weight, + 'cutable': cutable, + 'from': fromv, + 'to': tov + } + vnum += 1 + Edges.append(edge) + elif header: + Header.append(line) + print("IGNORE: " + line) + + +####################################################################### + + +def cwrite(filename): + with open(filename, "w") as fh: + fh.write("void V3GraphTestImport::dotImport() {\n") + fh.write(" auto* gp = &m_graph;\n") + for ver in sorted(Vertexes, key=lambda ver: ver['num']): + fh.write( + " auto* %s = new V3GraphTestVertex(gp, \"%s\"); if (%s) {}\n" + % (ver['name'], ver['name'], ver['name'])) + fh.write("\n") + for edge in Edges: + fh.write(" new V3GraphEdge(gp, %s, %s, %s, %s);\n" % + (edge['from'], edge['to'], edge['weight'], + "true" if edge['cutable'] else "false")) + fh.write("}\n") + + +###################################################################### # main -$Debug = 0; -my $opt_filename; -autoflush STDOUT 1; -autoflush STDERR 1; -if (! GetOptions( - "help" => \&usage, - "debug" => \&debug, - "<>" => \¶meter, - )) { - usage(); -} - -dotread($opt_filename); -cwrite("graph_export.cpp"); - -#---------------------------------------------------------------------- - -sub usage { - pod2usage(-verbose=>2, -exitval=>0, -output=>\*STDOUT); - exit(1); # Unreachable -} - -sub debug { - $Debug = 1; -} - -sub parameter { - my $param = shift; - if (!$opt_filename) { - $opt_filename = $param; - } else { - die "%Error: Unknown parameter: $param\n"; - } -} - -####################################################################### - -sub dotread { - my $filename = shift; - - my $fh = IO::File->new($filename) or die "%Error: $! $filename,"; - my $header = 1; - my $vnum = 0; - while (defined (my $line = $fh->getline)) { - if ($line =~ /^\t([a-zA-Z0-9_]+)\t(.*)$/) { - next if $1 eq 'nTITLE'; - $header = 0; - $Vertexes{$1} = {num => $vnum++, - line => $line, - name => $1,}; - } - elsif ($line =~ /^\t([a-zA-Z0-9_]+)\s+->\s+([a-zA-Z0-9_]+)\s+(.*)$/) { - my $from=$1; my $to=$2; - my $weight = 1; $weight = $1 if $line =~ /weight=(\d+)/; - my $cutable = undef; $cutable = $1 if $line =~ /style=(\S+)/; - my $edge = {num => $vnum++, - line => $line, - weight => $weight, - cutable => $cutable, - from => $from, - to => $to,}; - push @Edges, $edge; - $Edges{$from}{$to} = $edge; - } - elsif ($header) { - push @Header, $line; - print "IGNORE: $line"; - } - } -} - -####################################################################### - -sub cwrite { - my $filename = shift; - - my $fh = IO::File->new(">$filename") or die "%Error: $! $filename,"; - $fh->print("void V3GraphTestImport::dotImport() {\n"); - $fh->print(" DfaGraph* gp = &m_graph;\n"); - foreach my $ver (sort {$a->{num} <=> $b->{num}} (values %Vertexes)) { - $fh->printf(" V3GraphTestVertex* %s = new V3GraphTestVertex(gp, \"%s\"); if (%s) {}\n", - $ver->{name}, $ver->{name}, $ver->{name}); - } - $fh->print("\n"); - foreach my $edge (@Edges) { - $fh->printf(" new V3GraphEdge(gp, %s, %s, %s, %s);\n", - $edge->{from}, $edge->{to}, - $edge->{weight}, $edge->{cutable}?"true":"false"); - } - $fh->print("}\n"); -} - -####################################################################### -__END__ - -=pod - -=head1 NAME - -dot_importer - Take graph .dot file and convert into .cpp file - -=head1 SYNOPSIS - - dot_importer a.dot - -=head1 DESCRIPTION - -Dot_importer takes a graphvis .dot file and converts into .cpp file. This -.cpp file is then manually included in V3GraphTest.cpp to verify various -sub-algorithms. - -=head1 ARGUMENTS - -=over 4 - -=item --help - -Displays this message and program version and exits. - -=back - -=head1 DISTRIBUTION - -Copyright 2005-2020 by Wilson Snyder. This program is free software; you +parser = argparse.ArgumentParser( + allow_abbrev=False, + formatter_class=argparse.RawDescriptionHelpFormatter, + description= + """dot_importer takes a graphvis .dot file and converts into .cpp file. +This x.cpp file is then manually included in V3GraphTest.cpp to verify +various xsub-algorithms.""", + epilog= + """Copyright 2005-2021 by Wilson Snyder. This program is free software; you can redistribute it and/or modify it under the terms of either the GNU Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. -SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 +SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0""") -=head1 AUTHORS +parser.add_argument('--debug', + action='store_const', + const=9, + help='enable debug') +parser.add_argument('filename', help='input .dot filename to process') -Wilson Snyder - -=head1 SEE ALSO - -=cut +Args = parser.parse_args() +dotread(Args.filename) +cwrite("graph_export.cpp") ###################################################################### ### Local Variables: -### compile-command: "./dot_importer | tee ~/d/a.dot" +### compile-command: "./dot_importer ../test_regress/obj_vlt/t_EXAMPLE/*orderg_o*.dot && cat graph_export.cpp" ### End: diff --git a/nodist/dot_pruner b/nodist/dot_pruner deleted file mode 100755 index aad378e5a..000000000 --- a/nodist/dot_pruner +++ /dev/null @@ -1,205 +0,0 @@ -#!/usr/bin/env perl -# See copyright, etc in below POD section. -###################################################################### - -use warnings; -use Getopt::Long; -use IO::File; -use Pod::Usage; -use Data::Dumper; $Data::Dumper::Indent=1; -use strict; -use vars qw($Debug); - -#====================================================================== - -our @Header; -our %Vertexes; -our %Edges; -our %User; -our %User2; - -#====================================================================== -# main - -$Debug = 0; -my $opt_filename; -my $opt_circle; -autoflush STDOUT 1; -autoflush STDERR 1; -if (! GetOptions( - "help" => \&usage, - "debug" => \&debug, - "<>" => \¶meter, - "circle=s" => \$opt_circle, - )) { - usage(); -} - -dotread($opt_filename); -circle($opt_circle) if $opt_circle; -simplify(); -dotwrite(); - -#---------------------------------------------------------------------- - -sub usage { - pod2usage(-verbose=>2, -exitval=>0, -output=>\*STDOUT); - exit(1); # Unreachable -} - -sub debug { - $Debug = 1; -} - -sub parameter { - my $param = shift; - if (!$opt_filename) { - $opt_filename = $param; - } else { - die "%Error: Unknown parameter: $param\n"; - } -} - -####################################################################### - -sub dotread { - my $filename = shift; - - my $fh = IO::File->new($filename) or die "%Error: $! $filename,"; - my $header = 1; - while (defined (my $line = $fh->getline)) { - if ($line =~ /^\t([a-zA-Z0-9_]+)\t(.*)$/) { - $header = 0; - $Vertexes{$1} = $2; - } - elsif ($line =~ /^\t([a-zA-Z0-9_]+)\s+->\s+([a-zA-Z0-9_]+)\s+(.*)$/) { - $Edges{$1}{$2} = $3; - } - elsif ($header) { - push @Header, $line; - } - } -} - -###################################################################### - -sub simplify { - foreach my $ver (sort (keys %Vertexes)) { - $Vertexes{$ver} = _simplify($Vertexes{$ver}); - } - foreach my $v1 (sort (keys %Edges)) { - foreach my $v2 (sort (keys %{$Edges{$v1}})) { - $Edges{$v1}{$v2} = _simplify($Edges{$v1}{$v2}); - } - } -} - -sub _simplify { - my $text = shift; - $text =~ s/__DOT__/./g; - return $text; -} - - -sub dotwrite { - foreach my $line (@Header) { - print "$line"; - } - foreach my $ver (sort (keys %Vertexes)) { - print "\t$ver\t$Vertexes{$ver}\n"; - } - foreach my $v1 (sort (keys %Edges)) { - foreach my $v2 (sort (keys %{$Edges{$v1}})) { - print "\t$v1 -> $v2\t$Edges{$v1}{$v2}\n"; - } - } - print "}\n"; -} - -###################################################################### - -sub circle { - my $node = shift; - %User = (); - %User2 = (); - _circle_recurse($node, 1); - - foreach my $ver (keys %Vertexes) { - if (!$User{$ver}) { - delete $Vertexes{$ver}; - delete $Edges{$ver}; - } - } - foreach my $v1 (sort (keys %Edges)) { - foreach my $v2 (sort (keys %{$Edges{$v1}})) { - if (!$Vertexes{$v2}) { delete $Edges{$v1}{$v2}; } - } - } -} - -sub _circle_recurse { - my $node = $_[0]; - my $level = $_[1]; - $Vertexes{$node} or warn "%Warning: Can't find ref node $node\n"; - - $User{$node} = 1 if (($User2{$node}||0)==1); - return $User{$node} if $User2{$node}; - - $User2{$node} = 1; - my $r = 0; - foreach my $v2 (keys %{$Edges{$node}}) { - $r |= _circle_recurse($v2,$level++)||0; - } - $User{$node} = 1 if $r; - $User2{$node} = 2; - return $r; -} - -####################################################################### -__END__ - -=pod - -=head1 NAME - -dot_pruner - - -=head1 SYNOPSIS - - dot_pruner *.log - -=head1 DESCRIPTION - -dd - -=head1 ARGUMENTS - -=over 4 - -=item --help - -Displays this message and program version and exits. - -=back - -=head1 DISTRIBUTION - -Copyright 2005-2020 by Wilson Snyder. This program is free software; you -can redistribute it and/or modify it under the terms of either the GNU -Lesser General Public License Version 3 or the Perl Artistic License -Version 2.0. - -SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 - -=head1 AUTHORS - -Wilson Snyder - -=head1 SEE ALSO - -=cut - -###################################################################### -### Local Variables: -### compile-command: "./dot_pruner | tee ~/d/a.dot" -### End: diff --git a/nodist/flexdiff b/nodist/flexdiff deleted file mode 100755 index 1969cf482..000000000 --- a/nodist/flexdiff +++ /dev/null @@ -1,61 +0,0 @@ -#!/usr/bin/env perl -###################################################################### -# -# Copyright 2007-2020 by Wilson Snyder. This program is free software; you -# can redistribute it and/or modify it under the terms of either the GNU -# Lesser General Public License Version 3 or the Perl Artistic License -# Version 2.0. -# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 -# -###################################################################### - -# DESCRIPTION: Diff flex files - -use warnings; -use IO::File; -use strict; - -my $Debug; - -diff($ARGV[0],$ARGV[1]); - -sub diff { - my $a=shift; - my $b=shift; - - my $ta = "/tmp/flexdiff.$$.a"; - my $tb = "/tmp/flexdiff.$$.b"; - - prep($a,$ta); - prep($b,$tb); - - system("diff -u -w $ta $tb"); -} - -sub prep { - my $filename = shift; - my $wfilename = shift; - - my $fh = IO::File->new("<$filename") or die "%Error: $! $filename"; - my $fho = IO::File->new(">$wfilename") or die "%Error: $! writing $wfilename"; - - my %declared; - my %used; - my @lines; - - while (defined(my $line = $fh->getline)) { - # Productions - #$line =~ s/[ \t]{[^}]*?}/\t{}/g; - $line =~ s/StashPrefix;//g; - $line =~ s/VALTEXT;//g; - $line =~ s/CALLBACK\([^)]*\);//g; - push @lines, $line; - } - - #@lines = sort @lines; - $fho->print(@lines); -} - -# Local Variables: -# compile-command: "./flexdiff $VP/Parser/VParseLex.l ../src/verilog.l" -# End: diff --git a/nodist/fuzzer/actual_fail b/nodist/fuzzer/actual_fail index e8d860fae..4ddcc9c06 100755 --- a/nodist/fuzzer/actual_fail +++ b/nodist/fuzzer/actual_fail @@ -16,6 +16,7 @@ from glob import glob from subprocess import getstatusoutput from argparse import ArgumentParser + def interesting(s): if 'assert' in s: return 1 if 'Assert' in s: return 1 @@ -33,17 +34,19 @@ def interesting(s): def main(): p = ArgumentParser() - p.add_argument('--dir',default='out1/queue') + p.add_argument('--dir', default='out1/queue') args = p.parse_args() - for infile in glob(args.dir+'/*'): + for infile in glob(args.dir + '/*'): # Input filenames are known not to contain spaces or other unusual # characters, therefore this works. - status,output = getstatusoutput('../../bin/verilator_bin --cc '+infile) + status, output = getstatusoutput('../../bin/verilator_bin --cc ' + + infile) if interesting(output): print(infile) print(status) print(output) -if __name__=='__main__': + +if __name__ == '__main__': main() diff --git a/nodist/fuzzer/generate_dictionary b/nodist/fuzzer/generate_dictionary index f7196b2e3..b030f23ea 100755 --- a/nodist/fuzzer/generate_dictionary +++ b/nodist/fuzzer/generate_dictionary @@ -15,7 +15,8 @@ from subprocess import getstatusoutput from os import system -def take_while(f,a): + +def take_while(f, a): # any(a) => (a->bool)->[a]->[a] # Does the same think as Haskell's takewhile. out = [] @@ -26,44 +27,50 @@ def take_while(f,a): return out return out -def skip_while(f,a): + +def skip_while(f, a): # any(a) => (a->bool)->[a]->[a] # Basically, the opposite thing from skipwhile while len(a) and f(a[0]): a = a[1:] return a + def print_lines(a): # printable(a) => [a]->void for elem in a: print(elem) -def write_file(filename,contents): + +def write_file(filename, contents): # str->str->void - f = open(filename,'w') + f = open(filename, 'w') f.write(contents) + def parse_line(s): # str->maybe str - if len(s)==0: return - part = skip_while(lambda x: x!='"',s) - if len(part)==0 or part[0]!='"': return None - literal_part = take_while(lambda x: x!='"',part[1:]) - return ''.join(filter(lambda x: x!='\\',literal_part)) + if len(s) == 0: return + part = skip_while(lambda x: x != '"', s) + if len(part) == 0 or part[0] != '"': return None + literal_part = take_while(lambda x: x != '"', part[1:]) + return ''.join(filter(lambda x: x != '\\', literal_part)) + def main(): - status,output = getstatusoutput('flex -T ../../src/verilog.l') - assert status==0 + status, output = getstatusoutput('flex -T ../../src/verilog.l') + assert status == 0 lines = output.splitlines() - lines = take_while(lambda x: 'beginning dump of nfa' not in x,lines) - tokens = set(filter(lambda x: x,map(parse_line,lines))) + lines = take_while(lambda x: 'beginning dump of nfa' not in x, lines) + tokens = set(filter(lambda x: x, map(parse_line, lines))) dirname = 'dictionary' - r = system('mkdir -p '+dirname) - assert(r==0) - for i,token in enumerate(tokens): - write_file(dirname+'/'+str(i),token) + r = system('mkdir -p ' + dirname) + assert (r == 0) + for i, token in enumerate(tokens): + write_file(dirname + '/' + str(i), token) -if __name__=='__main__': + +if __name__ == '__main__': main() diff --git a/nodist/install_test b/nodist/install_test index edc59f8c8..1d2464fad 100755 --- a/nodist/install_test +++ b/nodist/install_test @@ -1,211 +1,140 @@ -#!/usr/bin/env perl -# See copyright, etc in below POD section. +#!/usr/bin/env python3 ###################################################################### -use warnings; -use Getopt::Long; -use Cwd; -use IO::File; -use Pod::Usage; -use strict; -use vars qw($Debug); +import argparse +import multiprocessing +import os +import shutil +import subprocess -#====================================================================== -# main +###################################################################### -our $Opt_Stage = 0; -our $Opt_Jobs = calc_jobs(); -autoflush STDOUT 1; -autoflush STDERR 1; -Getopt::Long::config("no_auto_abbrev"); -if (! GetOptions( - "debug" => sub { $Debug = 1; }, - "<>" => sub { die "%Error: Unknown parameter: $_[0]\n"; }, - "stage=i" => \$Opt_Stage, - "j=i" => \$Opt_Jobs, - )) { - die "%Error: Bad usage, try 'install_test --help'\n"; -} +def test(): + if not os.path.exists("nodist/install_test"): + sys.exit("%Error: Run from the top of the verilator kit") -test(); -exit(0); - -####################################################################### - -sub test { - -r "nodist/install_test" or die "%Error: Run from the top of the verilator kit,"; - - cleanenv(); - run("make distclean") if -r "Makefile"; + cleanenv() + if os.path.exists("Makefile"): + run("make distclean") # Try building from a scratch area - my $srcdir = getcwd(); - my $blddir = $srcdir."/test_regress/obj_dir/install_test_bld"; - my $prefix = $srcdir."/test_regress/obj_dir/install_test_prefix"; - my $testdirp= $srcdir."/test_regress/obj_dir/install_test_testp"; - my $testdirn= $srcdir."/test_regress/obj_dir/install_test_testn"; + srcdir = os.getcwd() + blddir = srcdir + "/test_regress/obj_dir/install_test_bld" + prefix = srcdir + "/test_regress/obj_dir/install_test_prefix" + testdirp = srcdir + "/test_regress/obj_dir/install_test_testp" + testdirn = srcdir + "/test_regress/obj_dir/install_test_testn" - if ($Opt_Stage <= 0) { - run("/bin/rm -rf $blddir"); - run("/bin/mkdir -p $blddir"); - run("cd $blddir && $srcdir/configure --prefix $prefix"); - run("cd $blddir && make -j $Opt_Jobs"); - } + if Args.stage <= 0: + print("== stage 0") + run("/bin/rm -rf " + blddir) + run("/bin/mkdir -p " + blddir) + run("cd " + blddir + " && " + srcdir + "/configure --prefix " + prefix) + run("cd " + blddir + " && make -j " + str(calc_jobs())) # Install it under the prefix - if ($Opt_Stage <= 1) { - run("/bin/rm -rf $prefix"); - run("/bin/mkdir -p $prefix"); - run("cd $blddir && make install"); - run("test -e $prefix/share/man/man1/verilator.1"); - run("test -e $prefix/share/verilator/examples/make_tracing_c/Makefile"); - run("test -e $prefix/share/verilator/include/verilated.h"); - run("test -e $prefix/bin/verilator"); - run("test -e $prefix/bin/verilator_bin"); - run("test -e $prefix/bin/verilator_bin_dbg"); - run("test -e $prefix/bin/verilator_gantt"); - run("test -e $prefix/bin/verilator_profcfunc"); - } + if Args.stage <= 1: + print("== stage 1") + run("/bin/rm -rf " + prefix) + run("/bin/mkdir -p " + prefix) + run("cd " + blddir + " && make install") + run("test -e " + prefix + "/share/man/man1/verilator.1") + run("test -e " + prefix + + "/share/verilator/examples/make_tracing_c/Makefile") + run("test -e " + prefix + "/share/verilator/include/verilated.h") + run("test -e " + prefix + "/bin/verilator") + run("test -e " + prefix + "/bin/verilator_bin") + run("test -e " + prefix + "/bin/verilator_bin_dbg") + run("test -e " + prefix + "/bin/verilator_gantt") + run("test -e " + prefix + "/bin/verilator_profcfunc") - # Run a test using just the path - if ($Opt_Stage <= 2) { - my $dir = $testdirp; - run("/bin/rm -rf $dir"); - run("/bin/mkdir -p $dir"); - my $bin1 = $prefix."/bin"; - my $bin2 = $prefix."/share/bin"; - write_verilog($dir); - run("cd $dir && PATH=$bin1:$bin2:\$PATH verilator --cc foo.v --exe foo.cpp"); - run("cd $dir/obj_dir && PATH=$bin1:$bin2:\$PATH make -f Vfoo.mk"); - run("cd $dir && PATH=$bin1:$bin2:\$PATH obj_dir/Vfoo"); - } + # run a test using just the path + if Args.stage <= 2: + print("== stage 2") + dir = testdirp + run("/bin/rm -rf " + dir) + run("/bin/mkdir -p " + dir) + path = prefix + "/bin" + ":" + prefix + "/share/bin" + write_verilog(dir) + run("cd " + dir + " && PATH=" + path + + ":$PATH verilator --cc top.v --exe sim_main.cpp") + run("cd " + dir + "/obj_dir && PATH=" + path + + ":$PATH make -f Vtop.mk") + run("cd " + dir + " && PATH=" + path + ":$PATH obj_dir/Vtop") - # Run a test using exact path to binary - if ($Opt_Stage <= 3) { - my $dir = $testdirn; - run("/bin/rm -rf $dir"); - run("/bin/mkdir -p $dir"); - write_verilog($dir); - my $bin1 = $prefix."/bin"; - my $bin2 = $prefix."/share/bin"; - run("cd $dir && $bin1/verilator --cc foo.v --exe foo.cpp"); - run("cd $dir/obj_dir && make -f Vfoo.mk"); - run("cd $dir/obj_dir && ./Vfoo"); - } + # run a test using exact path to binary + if Args.stage <= 3: + print("== stage 3") + dir = testdirn + run("/bin/rm -rf " + dir) + run("/bin/mkdir -p " + dir) + write_verilog(dir) + bin1 = prefix + "/bin" + run("cd " + dir + " && " + bin1 + + "/verilator --cc top.v --exe sim_main.cpp") + run("cd " + dir + "/obj_dir && make -f Vtop.mk") + run("cd " + dir + "/obj_dir && ./Vtop") - if ($Opt_Stage <= 9) { - print "*-* All Finished *-*\n"; - } -} + if Args.stage <= 9: + print("*-* All Finished *-*") -sub write_verilog { - my $dir = shift; - IO::File->new(">$dir/foo.v")->print('module t; initial begin $display("HELLO WORLD"); $finish; end endmodule'."\n"); - my $fh = IO::File->new(">$dir/foo.cpp"); - $fh->print('#include "Vfoo.h"' ,"\n"); - $fh->print('unsigned int main_time = 0;' ,"\n"); - $fh->print('double sc_time_stamp() {' ,"\n"); - $fh->print(' return main_time;' ,"\n"); - $fh->print('}' ,"\n"); - $fh->print('int main() {' ,"\n"); - $fh->print(' Vfoo *top = new Vfoo;' ,"\n"); - $fh->print(' while (!Verilated::gotFinish()) {',"\n"); - $fh->print(' top->eval();' ,"\n"); - $fh->print(' main_time++;' ,"\n"); - $fh->print(' }' ,"\n"); - $fh->print(' top->final();' ,"\n"); - $fh->print('}' ,"\n"); -} -sub cleanenv { - foreach my $var (keys %ENV) { - if ($var eq "VERILATOR_ROOT" - || $var eq "VERILATOR_INCLUDE" - || $var eq "VERILATOR_NO_OPT_BUILD") { - print "unset $var # Was '$ENV{$var}'\n"; - delete $ENV{$var} - } - } -} +def write_verilog(dir): + shutil.copy2("examples/make_hello_c/top.v", dir + "/top.v") + shutil.copy2("examples/make_hello_c/sim_main.cpp", dir + "/sim_main.cpp") + + +def cleanenv(): + for var in os.environ: + if (var == "VERILATOR_ROOT" or var == "VERILATOR_INCLUDE" + or var == "VERILATOR_NO_OPT_BUILD"): + print("unset %s # Was '%s'" % (var, os.environ[var])) + del os.environ[var] + + +def calc_jobs(): + return multiprocessing.cpu_count() + 1 + + +def run(command): + # run a system command, check errors + print("\t%s" % command) + os.system(command) + status = subprocess.call(command, shell=True) + if status < 0: + raise Exception("%Error: Command failed " + command + ", stopped") + ####################################################################### - -sub calc_jobs { - my $ok = eval " - use Unix::Processors; - return Unix::Processors->new->max_online; - "; - $ok && !$@ or return 1; - print "driver.pl: Found $ok cores, using -j ",$ok+1,"\n" if $Debug; - return $ok + 1; -} - -sub run { - # Run a system command, check errors - my $command = shift; - print "\t$command\n"; - system "$command"; - my $status = $?; - ($status == 0) or die "%Error: Command Failed $command, $status, stopped"; -} - ####################################################################### -__END__ -=pod - -=head1 NAME - -install_test - Build and install Verilator several ways - -=head1 SYNOPSIS - - install_test - -=head1 DESCRIPTION - -install_test performs several make-and-install iterations to verify the -kit. It isn't part of the normal "make test" due to the number of builds -required. - -=head1 ARGUMENTS - -=over 4 - -=item --help - -Displays this message and program version and exits. - -=item -j I - -Specify make -j flag. Defaults to number of cores + 1 if Perl's -Unix::Processors is installed, else 1. - -=item -stage I - -Runs a specific test stage (see the script). - -=back - -=head1 DISTRIBUTION - -Copyright 2009-2020 by Wilson Snyder. This program is free software; you +parser = argparse.ArgumentParser( + allow_abbrev=False, + formatter_class=argparse.RawDescriptionHelpFormatter, + description= + """install_test performs several make-and-install iterations to verify the +Verilator kit. It isn't part of the normal "make test" due to the number +of builds required.""", + epilog= + """Copyright 2009-2021 by Wilson Snyder. This program is free software; you can redistribute it and/or modify it under the terms of either the GNU Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. -SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 +SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0""") +parser.add_argument('--debug', + action='store_const', + const=9, + help='enable debug') +parser.add_argument('--stage', + type=int, + default=0, + help='run a specific test stage (see the script)') -=head1 AUTHORS - -Wilson Snyder - -=head1 SEE ALSO - -=cut +Args = parser.parse_args() +test() ###################################################################### ### Local Variables: -### compile-command: "cd .. ; nodist/install_test " +### compile-command: "cd .. ; nodist/install_test" ### End: diff --git a/nodist/invoke_atsim b/nodist/invoke_atsim deleted file mode 100755 index 0d5c61751..000000000 --- a/nodist/invoke_atsim +++ /dev/null @@ -1,49 +0,0 @@ -#!/usr/bin/env perl -# See copyright, etc in below POD section. -###################################################################### - -use warnings; -use strict; - -#====================================================================== -# main - -eval `modulecmd perl add axiom-athdl`; -exec('atsim', @ARGV); - -####################################################################### -__END__ - -=pod - -=head1 NAME - -invoke_atsim - Invoke tool under "modules" command - -=head1 SYNOPSIS - - invoke_atsim {arguments} - -=head1 DESCRIPTION - -=head1 DISTRIBUTION - -Copyright 2005-2020 by Wilson Snyder. This program is free software; you -can redistribute it and/or modify it under the terms of either the GNU -Lesser General Public License Version 3 or the Perl Artistic License -Version 2.0. - -SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 - -=head1 AUTHORS - -Wilson Snyder - -=head1 SEE ALSO - -=cut - -###################################################################### -### Local Variables: -### compile-command: "./invoke_atsim -help" -### End: diff --git a/nodist/invoke_iccr b/nodist/invoke_iccr deleted file mode 100755 index 3a109a041..000000000 --- a/nodist/invoke_iccr +++ /dev/null @@ -1,49 +0,0 @@ -#!/usr/bin/env perl -# See copyright, etc in below POD section. -###################################################################### - -use warnings; -use strict; - -#====================================================================== -# main - -eval `modulecmd perl add cds-ius`; -exec('iccr', @ARGV); - -####################################################################### -__END__ - -=pod - -=head1 NAME - -invoke_iccr - Invoke tool under "modules" command - -=head1 SYNOPSIS - - invoke_iccr {arguments} - -=head1 DESCRIPTION - -=head1 DISTRIBUTION - -Copyright 2007-2020 by Wilson Snyder. This program is free software; you -can redistribute it and/or modify it under the terms of either the GNU -Lesser General Public License Version 3 or the Perl Artistic License -Version 2.0. - -SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 - -=head1 AUTHORS - -Wilson Snyder - -=head1 SEE ALSO - -=cut - -###################################################################### -### Local Variables: -### compile-command: "./invoke_iccr -help" -### End: diff --git a/nodist/invoke_ncverilog b/nodist/invoke_ncverilog deleted file mode 100755 index 16d4f0492..000000000 --- a/nodist/invoke_ncverilog +++ /dev/null @@ -1,49 +0,0 @@ -#!/usr/bin/env perl -# See copyright, etc in below POD section. -###################################################################### - -use warnings; -use strict; - -#====================================================================== -# main - -eval `modulecmd perl add cds-ius/latest`; -exec('ncverilog', @ARGV); - -####################################################################### -__END__ - -=pod - -=head1 NAME - -invoke_ncverilog - Invoke tool under "modules" command - -=head1 SYNOPSIS - - invoke_ncverilog {arguments} - -=head1 DESCRIPTION - -=head1 DISTRIBUTION - -Copyright 2005-2020 by Wilson Snyder. This program is free software; you -can redistribute it and/or modify it under the terms of either the GNU -Lesser General Public License Version 3 or the Perl Artistic License -Version 2.0. - -SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 - -=head1 AUTHORS - -Wilson Snyder - -=head1 SEE ALSO - -=cut - -###################################################################### -### Local Variables: -### compile-command: "./invoke_ncverilog -help" -### End: diff --git a/nodist/invoke_vcs b/nodist/invoke_vcs deleted file mode 100755 index 08ede75ec..000000000 --- a/nodist/invoke_vcs +++ /dev/null @@ -1,49 +0,0 @@ -#!/usr/bin/env perl -# See copyright, etc in below POD section. -###################################################################### - -use warnings; -use strict; - -#====================================================================== -# main - -eval `modulecmd perl add synopsys-sim/latest`; -exec('vcs', @ARGV); - -####################################################################### -__END__ - -=pod - -=head1 NAME - -invoke_vcs - Invoke tool under "modules" command - -=head1 SYNOPSIS - - invoke_vcs {arguments} - -=head1 DESCRIPTION - -=head1 DISTRIBUTION - -Copyright 2005-2020 by Wilson Snyder. This program is free software; you -can redistribute it and/or modify it under the terms of either the GNU -Lesser General Public License Version 3 or the Perl Artistic License -Version 2.0. - -SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 - -=head1 AUTHORS - -Wilson Snyder - -=head1 SEE ALSO - -=cut - -###################################################################### -### Local Variables: -### compile-command: "./invoke_vcs -help" -### End: diff --git a/nodist/vtree_importer b/nodist/vtree_importer deleted file mode 100755 index 2a2d2c497..000000000 --- a/nodist/vtree_importer +++ /dev/null @@ -1,352 +0,0 @@ -#!/usr/bin/env perl -# See copyright, etc in below POD section. -###################################################################### - -use warnings; -use Getopt::Long; -use IO::File; -use Pod::Usage; -use Data::Dumper; $Data::Dumper::Indent=1; -use strict; -use vars qw($Debug); - -#====================================================================== - -our $Tree; -our %OpMap; -gentree(); - -#====================================================================== -# main - -$Debug = 0; -my $opt_filename; -autoflush STDOUT 1; -autoflush STDERR 1; -if (! GetOptions( - "help" => \&usage, - "debug" => \&debug, - "<>" => \¶meter, - )) { - usage(); -} - -vread($opt_filename); -#print Dumper($Tree); -vwrite(); - -print '(query-replace-regexp "(\\([0-9a-z_]+\\))" "\\1" nil nil nil)',"\n"; - -#---------------------------------------------------------------------- - -sub usage { - pod2usage(-verbose=>2, -exitval=>0, -output=>\*STDOUT); - exit(1); # Unreachable -} - -sub debug { - $Debug = 1; -} - -sub parameter { - my $param = shift; - if (!$opt_filename) { - $opt_filename = $param; - } else { - die "%Error: Unknown parameter: $param\n"; - } -} - -####################################################################### - -sub vread { - my $filename = shift; - my $fh = IO::File->new($filename) or die "%Error: $! $filename,"; - my $lasthier=""; - $Tree = { - op => 'NETLIST', - t => [[],[],[],[],[],], - }; - my @stack; - $stack[1] = $Tree; - while (defined (my $line = $fh->getline)) { - if ($line =~ /^\s+(\S+):\s+(\S+)\s+0x\S+\s+{(\d+)}\s+w(\d+)\s+(.*)$/) { - my $hier = $1; - my $op = $2; - my $lineno = $3; - my $width = $4; - my $etc = $5; - - $etc =~ s/__DOT__/./g; - $etc =~ s/__PVT__//g; - - my $self = { - op => $op, - #width => $width, - #lineno => $lineno, - #line => $line, - etc => $etc, - args => [split(/[ \t]+/,$etc)], - t => [[],[],[],[],[],], - }; - - my @hiers = (1,split(/:/,$hier)); - my $depth = $#hiers+1; - my $newchild = $hiers[$#hiers]; - - #print "DD $depth $newchild $op\n"; - - push @{$stack[$depth-1]->{t}[$newchild]}, $self; - $stack[$depth] = $self; - - $lasthier = $hier; - #print " $lasthier\n"; - #print Dumper($Tree); - } - } -} - -###################################################################### - -our $Indent = 0; -use vars qw($Code_Self); -use vars qw($Avoid_Hex); - -sub vwrite { - $Indent = 0; - print vwrite_rec($Tree); -} - -sub vwrite_rec { - my $self = shift; - #print "/*$self->{op}*/"; - my $code = $OpMap{$self->{op}} or die "%Error: No map for $self->{op},"; - local $Code_Self = $self; - #print Dumper($self->{t}[3]),"\n"; - &$code; -} - -###################################################################### -# Tree functions - -sub p { print join("",@_); } - -sub exists1 { return defined $Code_Self->{t}[1][0]; } -sub exists2 { return defined $Code_Self->{t}[2][0]; } -sub exists3 { return defined $Code_Self->{t}[3][0]; } -sub exists4 { return defined $Code_Self->{t}[4][0]; } -sub exists5 { return defined $Code_Self->{t}[5][0]; } - -sub t1 { foreach my $r (@{$Code_Self->{t}[1]}) { vwrite_rec($r); } } -sub t2 { foreach my $r (@{$Code_Self->{t}[2]}) { vwrite_rec($r); } } -sub t3 { foreach my $r (@{$Code_Self->{t}[3]}) { vwrite_rec($r); } } -sub t4 { foreach my $r (@{$Code_Self->{t}[4]}) { vwrite_rec($r); } } -sub t5 { foreach my $r (@{$Code_Self->{t}[5]}) { vwrite_rec($r); } } -sub p1 { p "("; t1; p ")";} -sub p2 { p "("; t2; p ")";} -sub p3 { p "("; t3; p ")";} -sub p4 { p "("; t4; p ")";} -sub p5 { p "("; t5; p ")";} -sub a1 { p $Code_Self->{args}[0]; } -sub a2 { p $Code_Self->{args}[1]; } -sub a3 { p $Code_Self->{args}[2]; } -sub a4 { p $Code_Self->{args}[3]; } -sub a5 { p $Code_Self->{args}[4]; } -sub a6 { p $Code_Self->{args}[5]; } -sub a7 { p $Code_Self->{args}[6]; } - -sub indentInc { $Indent+=2; } -sub indentDec { $Indent-=2; } -sub nl { p "\n"," "x$Indent; } - -###################################################################### - -# nl is a newline -# p# indicates to add parens -# t# indicates tree reference -# a# indicates info from dump where n1 is the width. - -sub gentree { -%OpMap = ( - 'NULLNODE' => sub { "" }, - 'NETLIST' => sub { nl;t1;t2;t3;t4;t5; }, - 'ACTIVE' => sub { p "always_act @(";t1;p ") begin";indentInc;nl;t2;t3;t4;t5;indentDec;p "end";nl; }, - 'ADD' => sub { p1;p " + ";p2; }, - 'ALWAYS' => sub { p "always @(";t1;p ") begin";indentInc;nl;t2;t3;t4;t5;indentDec;p "end";nl; }, - 'ALWAYSPOST' => sub { p "ALWAYSPOST what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; }, - 'AND' => sub { p1;p " & ";p2; }, - 'ARRAYSEL' => sub { t1;p "[";t2;p "]"; }, - 'ASSIGN' => sub { t2;p " = ";t1;p ";";nl; }, - 'ASSIGNDLY' => sub { t2;p " <= ";t1;p ";";nl; }, - 'ASSIGNPOST' => sub { p "ASSIGNPOST what{";t1;p " = ";t2;p ";";nl; }, - 'ASSIGNPRE' => sub { p "ASSIGNPRE what{";t1;p " = ";t2;p ";";nl; }, - 'ASSIGNW' => sub { p "assign ";t2;p " = ";t1;p ";";nl; }, - 'ATTROF' => sub { p "ATTROF what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; }, - 'BEGIN' => sub { p "begin";indentInc;nl;t1;t2;t3;t4;t5;indentDec;p "end";nl; }, - 'BITSEL' => sub { t1;local $Avoid_Hex=1; p "[";t2;p "]"; }, - 'CASE' => sub { p "CASE what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; }, - 'CASEITEM' => sub { p "CASEITEM what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; }, - 'CAST' => sub { p "CAST what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; }, - 'CCALL' => sub { p "CCALL what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; }, - 'CELL' => sub { a1;p " ";a7;p " (/*CELL*/);"; nl; }, - 'CFUNC' => sub { p "CFUNC what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; }, - 'CHANGEDET' => sub { p "CHANGEDET what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; }, - 'CINCLUDE' => sub { p "CINCLUDE what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; }, - 'COMMENT' => sub { p "//COMMENT what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl;nl; }, - 'CONCAT' => sub { p "{";p1;p ",";p2;p "}"; }, - 'CONDITIONAL' => sub { p1;p " ? ";p2;p " : ";p3; }, - 'CONST' => sub { p_const(); }, - 'COVER' => sub { p "COVER what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; }, - 'CRETURN' => sub { p "CRETURN what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; }, - 'CSTMT' => sub { p "CSTMT what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; }, - 'DEFPARAM' => sub { p "defparam ";p1;p " = ";p2;p ";";nl; }, - 'DISPLAY' => sub { p '$write("';p1;p "\",";p2;p3;p4;p5;p ");";nl; }, - 'DIV' => sub { p1;p " / ";p2; }, - 'EQ' => sub { p1;p " == ";p2; }, - 'EQCASE' => sub { p1;p " === ";p2; }, - 'EXTEND' => sub { t1; }, - 'EXTRACT' => sub { t1;local $Avoid_Hex=1; p "[";t2;p ":";t3;p "]"; }, - 'FINISH' => sub { p '$finish;';nl }, - 'FOR' => sub { p "for (";p1;p ",";p2;p ",";p3;p ") begin";indentInc;nl;p4;p5;indentDec;p "end";nl; }, - 'FUNC' => sub { p "FUNC what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; }, - 'FUNCREF' => sub { p "FUNCREF what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; }, - 'GT' => sub { p1;p " > ";p2; }, - 'GTE' => sub { p1;p " >= ";p2; }, - 'IF' => sub { p "if (";p1;p ") begin";indentInc;nl;t2;indentDec;if (exists3) {p "end else begin";indentInc;nl;t3;indentDec;} p "end"; nl; }, - 'INITARRAY' => sub { p "INITARRAY what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; }, - 'INITIAL' => sub { p "initial begin";indentInc;nl;t1;t2;t3;t4;t5;indentDec;p "end";nl; }, - 'LOGAND' => sub { p1;p " && ";p2; }, - 'LOGNOT' => sub { p1;p " || ";p2; }, - 'LOGOR' => sub { p "!";p1; }, - 'LT' => sub { p1;p " < ";p2; }, - 'LTE' => sub { p1;p " <= ";p2; }, - 'MODDIV' => sub { p1;p " % ";p2; }, - 'MODULE' => sub { p "module ";a1;p " (/*AUTOARG*/);";indentInc;nl;t1;t2;t3;t4;t5;indentDec;nl;p "endmodule";nl; }, - 'MUL' => sub { p1;p " * ";p2; }, - 'NEQ' => sub { p1;p " != ";p2; }, - 'NEQCASE' => sub { p1;p " !== ";p2; }, - 'NOT' => sub { p " ~";p1; }, - 'OR' => sub { p1;p " | ";p2; }, - 'PIN' => sub { p ";p ";p1;p " (";p2;p "),";nl; }, - 'PORT' => sub { p ""; }, - 'PRAGMA' => sub { p "PRAGMA what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; }, - 'RAND' => sub { p '$rand'; }, - 'RANGE' => sub { t1; local $Avoid_Hex=1; p "[";t2;p ":";t3;p "]"; }, - 'REDAND' => sub { p "&(";p1;p ")"; }, - 'REDOR' => sub { p "|(";p1;p ")"; }, - 'REDXNOR' => sub { p "~|(";p1;p ")"; }, - 'REDXOR' => sub { p "~^(";p1;p ")"; }, - 'REPLICATE' => sub { p "{";p1;p "{";p2;p "}}"; }, - 'SCCTOR' => sub { p "SCCTOR what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; }, - 'SCHDR' => sub { p "SCHDR what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; }, - 'SCIMP' => sub { p "SCIMP what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; }, - 'SCINT' => sub { p "SCINT what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; }, - 'SCOPE' => sub { t1;t2;t3;t4;t5; }, - 'SENITEM' => sub { a1;p " ";t1; }, - 'SENTREE' => sub { t1;t2;t3;t4;t5; }, - 'SHIFTL' => sub { p1;p " << ";p2; }, - 'SHIFTR' => sub { p1;p " >> ";p2; }, - 'STOP' => sub { p '$stop;';nl; }, - 'SUB' => sub { p1;p " - ";p2; }, - 'TASK' => sub { p "TASK what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; }, - 'TASKREF' => sub { p "TASKREF what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; }, - 'TEXT' => sub { p "TEXT what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; }, - 'TIME' => sub { p '$time'; }, - 'TOPSCOPE' => sub { t1;t2;t3;t4;t5; }, - 'TRACE' => sub { p "TRACE what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; }, - 'UCFUNC' => sub { p '$c(';p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p ")"; }, - 'UCSTMT' => sub { p '$c(';p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p ");";nl; }, - 'NEGATE' => sub { p " -";p1; }, - 'VAR' => sub { p_var(); }, - 'VARPIN' => sub { p "VARPIN what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; }, - 'VARREF' => sub { a1; }, - 'VARSCOPE' => sub { }, - 'WHILE' => sub { t1; p "while (";t2;p ") begin";indentInc;nl;t3;t4;indentDec;p "end";nl; }, - 'WORDSEL' => sub { p1;p "[";p2;p ":";p3;p "]"; }, - 'XNOR' => sub { p1;p " ~^ ";p2; }, - 'XOR' => sub { p1;p " ^";p2; }, -); -} - -sub p_var { - my $self = $Code_Self; - if ($self->{etc} =~ /\[I\]/) { - print "input"; - } elsif ($self->{etc} =~ /\[O\]/) { - print "output"; - } else { - print "reg"; - } - p "\t"; - { - local $Avoid_Hex=1; - t1; - } - p "\t"; - a1; - if (exists2()) { - p " = "; - t2; - } - p ";"; - nl; -} - -sub p_const { - my $v = $Code_Self->{args}[0]; - if ($v =~ /\?32\?h(.*)$/ - || ($Avoid_Hex && $v =~ /^[0-9?]*h(.*)$/)) { - print hex $1; - } else { - print $v; - } -} - -####################################################################### -__END__ - -=pod - -=head1 NAME - -vtree_importer - - -=head1 SYNOPSIS - - vtree_importer *.log - -=head1 DESCRIPTION - -dd - -=head1 ARGUMENTS - -=over 4 - -=item --help - -Displays this message and program version and exits. - -=back - -=head1 DISTRIBUTION - -Copyright 2005-2020 by Wilson Snyder. This program is free software; you -can redistribute it and/or modify it under the terms of either the GNU -Lesser General Public License Version 3 or the Perl Artistic License -Version 2.0. - -SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 - -=head1 AUTHORS - -Wilson Snyder - -=head1 SEE ALSO - -=cut - -###################################################################### -### Local Variables: -### compile-command: "./vtree_importer " -### End: diff --git a/src/.gdbinit b/src/.gdbinit index 8e973680f..76b0e3945 100644 --- a/src/.gdbinit +++ b/src/.gdbinit @@ -1,6 +1,6 @@ # DESCRIPTION: Verilator: GDB startup file with useful defines # -# Copyright 2012-2020 by Wilson Snyder. This program is free software; you +# Copyright 2012-2021 by Wilson Snyder. This program is free software; you # can redistribute it and/or modify it under the terms of either the GNU # Lesser General Public License Version 3 or the Perl Artistic License # Version 2.0. diff --git a/src/Makefile.in b/src/Makefile.in index 29f17f795..5dadd276a 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -7,7 +7,7 @@ # #***************************************************************************** # -# Copyright 2003-2020 by Wilson Snyder. This program is free software; you +# Copyright 2003-2021 by Wilson Snyder. This program is free software; you # can redistribute it and/or modify it under the terms of either the GNU # Lesser General Public License Version 3 or the Perl Artistic License # Version 2.0. @@ -18,7 +18,7 @@ #### Start of system configuration section. #### srcdir = @srcdir@ -PERL = @PERL@ +PYTHON3 = @PYTHON3@ EXEEXT = @EXEEXT@ # VPATH only does sources; fix install_test's not creating ../bin vpath %.h @srcdir@ @@ -52,8 +52,8 @@ obj_dbg: opt: ../bin/verilator_bin ifeq ($(VERILATOR_NO_OPT_BUILD),1) # Faster laptop development... One build ../bin/verilator_bin: ../bin/verilator_bin_dbg - -rm -rf $@ $@.exe - -cp -p $<$(EXEEXT) $@$(EXEEXT) + -cp -p $<$(EXEEXT) $@$(EXEEXT).tmp + -mv -f $@$(EXEEXT).tmp $@$(EXEEXT) else ../bin/verilator_bin: obj_opt ../bin prefiles $(MAKE) -C obj_opt -j 1 TGT=../$@ -f ../Makefile_obj serial @@ -78,17 +78,19 @@ endif prefiles:: prefiles:: config_rev.h # This output goes into srcdir if locally configured, as we need to distribute it as part of the kit. -config_rev.h: ${srcdir}/config_rev.pl $(GIT_CHANGE_DEP) - $(PERL) ${srcdir}/config_rev.pl ${srcdir} >$@ +config_rev.h: ${srcdir}/config_rev $(GIT_CHANGE_DEP) + $(PYTHON3) ${srcdir}/config_rev ${srcdir} >$@ # Human convenience +format: + $(MAKE) -C .. $@ clang-format: $(MAKE) -C .. $@ maintainer-copy:: clean mostlyclean distclean maintainer-clean:: -rm -rf obj_* *.log *.dmp *.vpd core - -rm -f *.o *.d perlxsi.c *_gen_* + -rm -f *.o *.d *_gen_* -rm -f *__gen* obj_* -rm -f .objcache* diff --git a/src/Makefile_obj.in b/src/Makefile_obj.in index b686d5775..a5db6d5e9 100644 --- a/src/Makefile_obj.in +++ b/src/Makefile_obj.in @@ -7,7 +7,7 @@ # #***************************************************************************** # -# Copyright 2003-2020 by Wilson Snyder. This program is free software; you +# Copyright 2003-2021 by Wilson Snyder. This program is free software; you # can redistribute it and/or modify it under the terms of either the GNU # Lesser General Public License Version 3 or the Perl Artistic License # Version 2.0. @@ -41,6 +41,7 @@ LINK = @CXX@ LEX = @LEX@ LFLAGS = -d PERL = @PERL@ +PYTHON3 = @PYTHON3@ YACC = @YACC@ OBJCACHE ?= @OBJCACHE@ @@ -138,7 +139,7 @@ make_info: @echo " Compile flags: " $(CXX) ${CFLAGS} ${CXXFLAGS} ${CPPFLAGS} clean mostlyclean distclean maintainer-clean:: - -rm -f *.o *.d perlxsi.c *_gen_* + -rm -f *.o *.d *_gen_* -rm -f *__gen* -rm -f obj_* .objcache* @@ -228,6 +229,7 @@ RAW_OBJS = \ V3PreShell.o \ V3Premit.o \ V3ProtectLib.o \ + V3Randomize.o \ V3Reloop.o \ V3Scope.o \ V3Scoreboard.o \ @@ -331,7 +333,7 @@ V3Lexer_pregen.yy.cpp: verilog.l V3ParseBison.h $(HEADERS) ${LEX} ${LFLAGS} -o$@ $< V3Lexer.yy.cpp: V3Lexer_pregen.yy.cpp $(FLEXFIX) - $(PERL) $(FLEXFIX) V3Lexer <$< >$@ + $(PYTHON3) $(FLEXFIX) V3Lexer <$< >$@ V3PreLex_pregen.yy.cpp: V3PreLex.l $(HEADERS) ${LEX} --version diff --git a/src/V3Active.cpp b/src/V3Active.cpp index 50aa672c2..a0d3de8fd 100644 --- a/src/V3Active.cpp +++ b/src/V3Active.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -35,11 +35,168 @@ #include "V3EmitCBase.h" #include "V3Const.h" #include "V3SenTree.h" // for SenTreeSet +#include "V3Graph.h" #include //***** See below for main transformation engine +//###################################################################### + +// Extend V3GraphVertex class for use in latch detection graph + +class LatchDetectGraphVertex final : public V3GraphVertex { +public: + enum VertexType : uint8_t { VT_BLOCK, VT_BRANCH, VT_OUTPUT }; + +private: + string m_name; // Only used for .dot file generation + VertexType m_type; // Vertex type (BLOCK/BRANCH/OUTPUT) + + string typestr() const { // " + switch (m_type) { + case VT_BLOCK: return "(||)"; // basic block node + case VT_BRANCH: return "(&&)"; // if/else branch mode + case VT_OUTPUT: return "(out)"; // var assignment + default: return "??"; // unknown + } + } + +public: + LatchDetectGraphVertex(V3Graph* graphp, const string& name, VertexType type = VT_BLOCK) + : V3GraphVertex(graphp) + , m_name(name) + , m_type(type) {} + virtual string name() const { return m_name + " " + typestr(); } + virtual string dotColor() const { return user() ? "green" : "black"; } + virtual int type() const { return m_type; } +}; + +//###################################################################### +// Extend V3Graph class for use as a latch detection graph + +class LatchDetectGraph final : public V3Graph { +protected: + typedef std::vector VarRefVec; + + LatchDetectGraphVertex* m_curVertexp; // Current latch detection graph vertex + VarRefVec m_outputs; // Vector of lvalues encountered on this pass + + VL_DEBUG_FUNC; // Declare debug() + + static LatchDetectGraphVertex* castVertexp(void* vertexp) { + return reinterpret_cast(vertexp); + } + + // Recursively traverse the graph to determine whether every control 'BLOCK' has an assignment + // to the output we are currently analysing (the output whose 'user() is set), if so return + // true. Where a BLOCK contains a BRANCH, both the if and else sides of the branch must return + // true for the BRANCH to evalute to true. A BLOCK however needs only a single one of its + // siblings to evaluate true in order to evaluate true itself. On output vertex only evaluates + // true if it is the vertex we are analyzing on this check + + bool latchCheckInternal(LatchDetectGraphVertex* vertexp) { + bool result = false; + switch (vertexp->type()) { + case LatchDetectGraphVertex::VT_OUTPUT: // Base case + result = vertexp->user(); + break; + case LatchDetectGraphVertex::VT_BLOCK: // (OR of potentially many siblings) + for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep = edgep->outNextp()) { + if (latchCheckInternal(castVertexp(edgep->top()))) { + result = true; + break; + } + } + break; + case LatchDetectGraphVertex::VT_BRANCH: // (AND of both sibling) + // A BRANCH vertex always has exactly 2 siblings + LatchDetectGraphVertex* ifp = castVertexp(vertexp->outBeginp()->top()); + LatchDetectGraphVertex* elsp = castVertexp(vertexp->outBeginp()->outNextp()->top()); + result = latchCheckInternal(ifp) && latchCheckInternal(elsp); + break; + } + vertexp->user(result); + return result; + } + +public: + LatchDetectGraph() { clear(); } + ~LatchDetectGraph() { clear(); } + // ACCESSORS + LatchDetectGraphVertex* currentp() { return m_curVertexp; } + void currentp(LatchDetectGraphVertex* vertex) { m_curVertexp = vertex; } + // METHODS + void begin() { + // Start a new if/else tracking graph + // See NODE STATE comment in ActiveLatchCheckVisitor + AstNode::user1ClearTree(); + m_curVertexp = new LatchDetectGraphVertex(this, "ROOT"); + } + // Clear out userp field of referenced outputs on destruction + // (occurs at the end of each combinational always block) + void clear() { + m_outputs.clear(); + // Calling base class clear will unlink & delete all edges & vertices + V3Graph::clear(); + m_curVertexp = nullptr; + } + // Add a new control path and connect it to its parent + LatchDetectGraphVertex* addPathVertex(LatchDetectGraphVertex* parent, const string& name, + bool branch = false) { + m_curVertexp = new LatchDetectGraphVertex(this, name, + branch ? LatchDetectGraphVertex::VT_BRANCH + : LatchDetectGraphVertex::VT_BLOCK); + new V3GraphEdge(this, parent, m_curVertexp, 1); + return m_curVertexp; + } + // Add a new output variable vertex and store a pointer to it in the user1 field of the + // variables AstNode + LatchDetectGraphVertex* addOutputVertex(AstVarRef* nodep) { + LatchDetectGraphVertex* outVertexp + = new LatchDetectGraphVertex(this, nodep->name(), LatchDetectGraphVertex::VT_OUTPUT); + nodep->varp()->user1p(outVertexp); + m_outputs.push_back(nodep); + return outVertexp; + } + // Connect an output assignment to its parent control block + void addAssignment(AstVarRef* nodep) { + LatchDetectGraphVertex* outVertexp; + if (!nodep->varp()->user1p()) { // Not seen this output before + outVertexp = addOutputVertex(nodep); + } else + outVertexp = castVertexp(nodep->varp()->user1p()); + + new V3GraphEdge(this, m_curVertexp, outVertexp, 1); + } + // Run latchCheckInternal on each variable assigned by the always block to see if all control + // paths make an assignment. Detected latches are flagged in the variables AstVar + void latchCheck(AstNode* nodep, bool latch_expected) { + bool latch_detected = false; + for (const auto& vrp : m_outputs) { + LatchDetectGraphVertex* vertp = castVertexp(vrp->varp()->user1p()); + vertp->user(true); // Identify the output vertex we are checking paths _to_ + if (!latchCheckInternal(castVertexp(verticesBeginp()))) { latch_detected = true; } + if (latch_detected && !latch_expected) { + nodep->v3warn( + LATCH, + "Latch inferred for signal " + << vrp->prettyNameQ() + << " (not all control paths of combinational always assign a value)\n" + << nodep->warnMore() + << "... Suggest use of always_latch for intentional latches"); + if (debug() >= 9) { dumpDotFilePrefixed("latch_" + vrp->name()); } + } + vertp->user(false); // Clear again (see above) + vrp->varp()->isLatched(latch_detected); + } + // Should _all_ variables assigned in always_latch be latches? Probably, but this only + // warns if none of them are + if (latch_expected && !latch_detected) + nodep->v3warn(NOLATCH, "No latches detected in always_latch block"); + } +}; + //###################################################################### // Collect existing active names @@ -135,6 +292,48 @@ public: void main(AstScope* nodep) { iterate(nodep); } }; +//###################################################################### +// Latch checking visitor + +class ActiveLatchCheckVisitor final : public ActiveBaseVisitor { +private: + // NODE STATE + // Input: + // AstVar::user1p // V2LatchGraphVertex* The vertex handling this node + AstUser1InUse m_inuser1; + // STATE + LatchDetectGraph m_graph; // Graph used to detect latches in combo always + // VISITORS + virtual void visit(AstVarRef* nodep) { + AstVar* varp = nodep->varp(); + if (nodep->access().isWriteOrRW() && varp->isSignal() && !varp->isUsedLoopIdx()) { + m_graph.addAssignment(nodep); + } + } + virtual void visit(AstNodeIf* nodep) { + LatchDetectGraphVertex* parentp = m_graph.currentp(); + LatchDetectGraphVertex* branchp = m_graph.addPathVertex(parentp, "BRANCH", true); + m_graph.addPathVertex(branchp, "IF"); + iterateAndNextNull(nodep->ifsp()); + m_graph.addPathVertex(branchp, "ELSE"); + iterateAndNextNull(nodep->elsesp()); + m_graph.currentp(parentp); + } + // Empty visitors, speed things up + virtual void visit(AstNodeMath* nodep) {} + //-------------------- + virtual void visit(AstNode* nodep) { iterateChildren(nodep); } + +public: + // CONSTRUCTORS + ActiveLatchCheckVisitor(AstNode* nodep, VAlwaysKwd kwd) { + m_graph.begin(); + iterate(nodep); + m_graph.latchCheck(nodep, kwd == VAlwaysKwd::ALWAYS_LATCH); + } + virtual ~ActiveLatchCheckVisitor() {} +}; + //###################################################################### // Active AssignDly replacement functions @@ -157,11 +356,14 @@ private: << "... Suggest blocking assignments (=)"); } else if (m_check == CT_LATCH) { // Suppress. Shouldn't matter that the interior of the latch races - } else { + } else if (!(VN_IS(nodep->lhsp(), VarRef) + && VN_CAST(nodep->lhsp(), VarRef)->varp()->isLatched())) { nodep->v3warn(COMBDLY, "Delayed assignments (<=) in non-clocked" " (non flop or latch) block\n" << nodep->warnMore() << "... Suggest blocking assignments (=)"); + // Conversely, we could also suggest latches use delayed assignments, as + // recommended by Cliff Cummings? } AstNode* newp = new AstAssign(nodep->fileline(), nodep->lhsp()->unlinkFrBack(), nodep->rhsp()->unlinkFrBack()); @@ -171,10 +373,9 @@ private: } virtual void visit(AstAssign* nodep) override { if (m_check == CT_SEQ) { - AstNode* las = m_assignp; + VL_RESTORER(m_assignp); m_assignp = nodep; iterateAndNextNull(nodep->lhsp()); - m_assignp = las; } } virtual void visit(AstVarRef* nodep) override { @@ -284,7 +485,6 @@ private: m_namer.scopep()->addActivep(m_scopeFinalp); } nodep->unlinkFrBack(); - m_scopeFinalp->addStmtsp(new AstComment(nodep->fileline(), nodep->typeName(), true)); m_scopeFinalp->addStmtsp(nodep->bodysp()->unlinkFrBackWithNext()); VL_DO_DANGLING(nodep->deleteTree(), nodep); } @@ -343,6 +543,7 @@ private: // Warn and/or convert any delayed assignments if (combo && !sequent) { + ActiveLatchCheckVisitor latchvisitor(nodep, kwd); if (kwd == VAlwaysKwd::ALWAYS_LATCH) { ActiveDlyVisitor dlyvisitor(nodep, ActiveDlyVisitor::CT_LATCH); } else { diff --git a/src/V3Active.h b/src/V3Active.h index 79fff9303..bec002ce1 100644 --- a/src/V3Active.h +++ b/src/V3Active.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3ActiveTop.cpp b/src/V3ActiveTop.cpp index 3982acb29..0745c8ed7 100644 --- a/src/V3ActiveTop.cpp +++ b/src/V3ActiveTop.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3ActiveTop.h b/src/V3ActiveTop.h index 9bc677ff8..567d29314 100644 --- a/src/V3ActiveTop.h +++ b/src/V3ActiveTop.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Assert.cpp b/src/V3Assert.cpp index 8af7193cc..8ed6d686a 100644 --- a/src/V3Assert.cpp +++ b/src/V3Assert.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2005-2020 by Wilson Snyder. This program is free software; you +// Copyright 2005-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -86,18 +86,19 @@ private: varrefp->classOrPackagep(v3Global.rootp()->dollarUnitPkgAddp()); return varrefp; } - AstNode* newIfAssertOn(AstNode* nodep) { + AstNode* newIfAssertOn(AstNode* nodep, bool force) { // Add a internal if to check assertions are on. // Don't make this a AND term, as it's unlikely to need to test this. FileLine* fl = nodep->fileline(); - AstNode* newp - = new AstIf(fl, - // If assertions are off, have constant propagation rip them out later - // This allows syntax errors and such to be detected normally. - (v3Global.opt.assertOn() - ? static_cast(new AstCMath(fl, "Verilated::assertOn()", 1)) - : static_cast(new AstConst(fl, AstConst::BitFalse()))), - nodep, nullptr); + AstNode* newp = new AstIf( + fl, + (force ? new AstConst(fl, AstConst::BitTrue()) + : // If assertions are off, have constant propagation rip them out later + // This allows syntax errors and such to be detected normally. + (v3Global.opt.assertOn() + ? static_cast(new AstCMath(fl, "Verilated::assertOn()", 1)) + : static_cast(new AstConst(fl, AstConst::BitFalse())))), + nodep, nullptr); newp->user1(true); // Don't assert/cover this if return newp; } @@ -114,7 +115,7 @@ private: AstNode* newFireAssert(AstNode* nodep, const string& message) { AstNode* bodysp = newFireAssertUnchecked(nodep, message); - bodysp = newIfAssertOn(bodysp); + bodysp = newIfAssertOn(bodysp, false); return bodysp; } @@ -154,20 +155,21 @@ private: if (bodysp && passsp) bodysp = bodysp->addNext(passsp); ifp = new AstIf(nodep->fileline(), propp, bodysp, nullptr); bodysp = ifp; - } else if (VN_IS(nodep, Assert)) { + } else if (VN_IS(nodep, Assert) || VN_IS(nodep, AssertIntrinsic)) { if (nodep->immediate()) { ++m_statAsImm; } else { ++m_statAsNotImm; } - if (passsp) passsp = newIfAssertOn(passsp); - if (failsp) failsp = newIfAssertOn(failsp); + bool force = VN_IS(nodep, AssertIntrinsic); + if (passsp) passsp = newIfAssertOn(passsp, force); + if (failsp) failsp = newIfAssertOn(failsp, force); if (!failsp) failsp = newFireAssertUnchecked(nodep, "'assert' failed."); ifp = new AstIf(nodep->fileline(), propp, passsp, failsp); // It's more LIKELY that we'll take the nullptr if clause // than the sim-killing else clause: ifp->branchPred(VBranchPred::BP_LIKELY); - bodysp = newIfAssertOn(ifp); + bodysp = newIfAssertOn(ifp, force); } else { nodep->v3fatalSrc("Unknown node type"); } @@ -417,6 +419,10 @@ private: iterateChildren(nodep); newPslAssertion(nodep, nodep->failsp()); } + virtual void visit(AstAssertIntrinsic* nodep) override { + iterateChildren(nodep); + newPslAssertion(nodep, nodep->failsp()); + } virtual void visit(AstCover* nodep) override { iterateChildren(nodep); newPslAssertion(nodep, nullptr); diff --git a/src/V3Assert.h b/src/V3Assert.h index 934a2032d..2738ddbf2 100644 --- a/src/V3Assert.h +++ b/src/V3Assert.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2005-2020 by Wilson Snyder. This program is free software; you +// Copyright 2005-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3AssertPre.cpp b/src/V3AssertPre.cpp index 727e0aafe..307081add 100644 --- a/src/V3AssertPre.cpp +++ b/src/V3AssertPre.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2005-2020 by Wilson Snyder. This program is free software; you +// Copyright 2005-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3AssertPre.h b/src/V3AssertPre.h index 862756748..0b5acb522 100644 --- a/src/V3AssertPre.h +++ b/src/V3AssertPre.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2005-2020 by Wilson Snyder. This program is free software; you +// Copyright 2005-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Ast.cpp b/src/V3Ast.cpp index 9e2b9843b..3c72a8d80 100644 --- a/src/V3Ast.cpp +++ b/src/V3Ast.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -130,7 +130,6 @@ string AstNode::encodeName(const string& namein) { // Then we also won't need to save the table of hased values VName vname{out}; return vname.hashedName(); - return out; } string AstNode::encodeNumber(vlsint64_t num) { diff --git a/src/V3Ast.h b/src/V3Ast.h index ae9402538..2295ff743 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -157,7 +157,7 @@ public: bool isReadOnly() const { return m_e == READ; } // False with READWRITE bool isReadOrRW() const { return m_e == READ || m_e == READWRITE; } bool isWriteOrRW() const { return m_e == WRITE || m_e == READWRITE; } - bool isRW() const { return m_e == READWRITE; } // False with READWRITE + bool isRW() const { return m_e == READWRITE; } }; inline bool operator==(const VAccess& lhs, const VAccess& rhs) { return lhs.m_e == rhs.m_e; } inline bool operator==(const VAccess& lhs, VAccess::en rhs) { return lhs.m_e == rhs; } @@ -380,6 +380,7 @@ public: ENUM_NEXT, // V3Width processes ENUM_PREV, // V3Width processes ENUM_NAME, // V3Width processes + ENUM_VALID, // V3Width processes // MEMBER_BASE, // V3LinkResolve creates for AstPreSel, V3LinkParam removes // @@ -408,7 +409,7 @@ public: "DIM_LOW", "DIM_RIGHT", "DIM_SIZE", "DIM_UNPK_DIMENSIONS", "DT_PUBLIC", "ENUM_BASE", "ENUM_FIRST", "ENUM_LAST", "ENUM_NUM", - "ENUM_NEXT", "ENUM_PREV", "ENUM_NAME", + "ENUM_NEXT", "ENUM_PREV", "ENUM_NAME", "ENUM_VALID", "MEMBER_BASE", "TYPENAME", "VAR_BASE", "VAR_CLOCK_ENABLE", "VAR_PUBLIC", @@ -980,61 +981,53 @@ inline std::ostream& operator<<(std::ostream& os, const VParseRefExp& rhs) { class VNumRange final { public: - int m_hi = 0; // HI part, HI always >= LO - int m_lo = 0; // LO - union { - int mu_flags; - struct { - bool m_ranged : 1; // Has a range - bool m_littleEndian : 1; // Bit vector is little endian - }; - }; + int m_left = 0; + int m_right = 0; + bool m_ranged = false; // Has a range bool operator==(const VNumRange& rhs) const { - return m_hi == rhs.m_hi && m_lo == rhs.m_lo && mu_flags == rhs.mu_flags; + return m_left == rhs.m_left && m_right == rhs.m_right && m_ranged == rhs.m_ranged; } bool operator<(const VNumRange& rhs) const { - if ((m_hi < rhs.m_hi)) return true; - if (!(m_hi == rhs.m_hi)) return false; // lhs > rhs - if ((m_lo < rhs.m_lo)) return true; - if (!(m_lo == rhs.m_lo)) return false; // lhs > rhs - if ((mu_flags < rhs.mu_flags)) return true; - if (!(mu_flags == rhs.mu_flags)) return false; // lhs > rhs + if ((m_left < rhs.m_left)) return true; + if (!(m_left == rhs.m_left)) return false; // lhs > rhs + if ((m_right < rhs.m_right)) return true; + if (!(m_right == rhs.m_right)) return false; // lhs > rhs + if ((m_ranged < rhs.m_ranged)) return true; + if (!(m_ranged == rhs.m_ranged)) return false; // lhs > rhs return false; } // - class LeftRight {}; - VNumRange() - : mu_flags{0} {} - VNumRange(int hi, int lo, bool littleEndian) - : mu_flags{0} { - init(hi, lo, littleEndian); - } - VNumRange(LeftRight, int left, int right) - : mu_flags{0} { - init((right > left) ? right : left, (right > left) ? left : right, (right > left)); - } + VNumRange() {} + VNumRange(int hi, int lo, bool littleEndian) { init(hi, lo, littleEndian); } + VNumRange(int left, int right) + : m_left{left} + , m_right{right} + , m_ranged{true} {} ~VNumRange() = default; // MEMBERS void init(int hi, int lo, bool littleEndian) { - m_hi = hi; - m_lo = lo; - mu_flags = 0; + if (lo > hi) { + int t = hi; + hi = lo; + lo = t; + } + m_left = littleEndian ? lo : hi; + m_right = littleEndian ? hi : lo; m_ranged = true; - m_littleEndian = littleEndian; } - int hi() const { return m_hi; } - int lo() const { return m_lo; } - int left() const { return littleEndian() ? lo() : hi(); } // How to show a declaration - int right() const { return littleEndian() ? hi() : lo(); } + int left() const { return m_left; } + int right() const { return m_right; } + int hi() const { return m_left > m_right ? m_left : m_right; } // How to show a declaration + int lo() const { return m_left > m_right ? m_right : m_left; } // How to show a declaration int leftToRightInc() const { return littleEndian() ? 1 : -1; } int elements() const { return hi() - lo() + 1; } bool ranged() const { return m_ranged; } - bool littleEndian() const { return m_littleEndian; } + bool littleEndian() const { return m_left < m_right; } int hiMaxSelect() const { return (lo() < 0 ? hi() - lo() : hi()); } // Maximum value a [] select may index bool representableByWidth() const { // Could be represented by just width=1, or [width-1:0] - return (!m_ranged || (m_lo == 0 && m_hi >= 1 && !m_littleEndian)); + return (!m_ranged || (m_right == 0 && m_left >= 1)); } void dump(std::ostream& str) const { if (ranged()) { @@ -2151,19 +2144,18 @@ public: class AstNodePreSel VL_NOT_FINAL : public AstNode { // Something that becomes an AstSel public: - AstNodePreSel(AstType t, FileLine* fl, AstNode* lhs, AstNode* rhs, AstNode* ths) + AstNodePreSel(AstType t, FileLine* fl, AstNode* fromp, AstNode* rhs, AstNode* ths) : AstNode{t, fl} { - setOp1p(lhs); + setOp1p(fromp); setOp2p(rhs); setNOp3p(ths); } ASTNODE_BASE_FUNCS(NodePreSel) - AstNode* lhsp() const { return op1p(); } - AstNode* fromp() const { return lhsp(); } + AstNode* fromp() const { return op1p(); } AstNode* rhsp() const { return op2p(); } AstNode* thsp() const { return op3p(); } AstAttrOf* attrp() const { return VN_CAST(op4p(), AttrOf); } - void lhsp(AstNode* nodep) { return setOp1p(nodep); } + void fromp(AstNode* nodep) { return setOp1p(nodep); } void rhsp(AstNode* nodep) { return setOp2p(nodep); } void thsp(AstNode* nodep) { return setOp3p(nodep); } void attrp(AstAttrOf* nodep) { return setOp4p((AstNode*)nodep); } @@ -2396,7 +2388,13 @@ public: virtual void dump(std::ostream& str) const override; virtual void dumpSmall(std::ostream& str) const; virtual bool hasDType() const override { return true; } - virtual AstBasicDType* basicp() const = 0; // (Slow) recurse down to find basic data type + /// Require VlUnpacked, instead of [] for POD elements. + /// A non-POD object is always compound, but some POD elements + /// are compound when methods calls operate on object, or when + /// under another compound-requiring object e.g. class + virtual bool isCompound() const = 0; + // (Slow) recurse down to find basic data type + virtual AstBasicDType* basicp() const = 0; // recurses over typedefs/const/enum to next non-typeref type virtual AstNodeDType* skipRefp() const = 0; // recurses over typedefs to next non-typeref-or-const type @@ -2488,14 +2486,14 @@ public: ASTNODE_BASE_FUNCS(NodeUOrStructDType) virtual const char* broken() const override; virtual void dump(std::ostream& str) const override; + virtual bool isCompound() const override { return false; } // Because don't support unpacked // For basicp() we reuse the size to indicate a "fake" basic type of same size virtual AstBasicDType* basicp() const override { - return (isFourstate() ? VN_CAST( - findLogicRangeDType(VNumRange(width() - 1, 0, false), width(), numeric()), - BasicDType) - : VN_CAST(findBitRangeDType(VNumRange(width() - 1, 0, false), - width(), numeric()), - BasicDType)); + return (isFourstate() + ? VN_CAST(findLogicRangeDType(VNumRange{width() - 1, 0}, width(), numeric()), + BasicDType) + : VN_CAST(findBitRangeDType(VNumRange{width() - 1, 0}, width(), numeric()), + BasicDType)); } virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } @@ -2525,9 +2523,9 @@ public: const auto it = m_members.find(name); return (it == m_members.end()) ? nullptr : it->second; } - static int lsb() { return 0; } - int msb() const { return dtypep()->width() - 1; } // Packed classes look like arrays - VNumRange declRange() const { return VNumRange(msb(), lsb(), false); } + static int lo() { return 0; } + int hi() const { return dtypep()->width() - 1; } // Packed classes look like arrays + VNumRange declRange() const { return VNumRange{hi(), lo()}; } }; class AstNodeArrayDType VL_NOT_FINAL : public AstNodeDType { @@ -2553,17 +2551,17 @@ public: } virtual bool same(const AstNode* samep) const override { const AstNodeArrayDType* asamep = static_cast(samep); - return (msb() == asamep->msb() && subDTypep() == asamep->subDTypep() + return (hi() == asamep->hi() && subDTypep() == asamep->subDTypep() && rangenp()->sameTree(asamep->rangenp())); } // HashedDT doesn't recurse, so need to check children virtual bool similarDType(AstNodeDType* samep) const override { const AstNodeArrayDType* asamep = static_cast(samep); - return (asamep && type() == samep->type() && msb() == asamep->msb() + return (asamep && type() == samep->type() && hi() == asamep->hi() && rangenp()->sameTree(asamep->rangenp()) && subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp())); } virtual V3Hash sameHash() const override { - return V3Hash(V3Hash(m_refDTypep), V3Hash(msb()), V3Hash(lsb())); + return V3Hash(V3Hash(m_refDTypep), V3Hash(hi()), V3Hash(lo())); } virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); } AstNodeDType* childDTypep() const { return VN_CAST(op1p(), NodeDType); } @@ -2587,8 +2585,10 @@ public: virtual int widthTotalBytes() const override { return elementsConst() * subDTypep()->widthTotalBytes(); } - int msb() const; - int lsb() const; + int left() const; + int right() const; + int hi() const; + int lo() const; int elementsConst() const; VNumRange declRange() const; }; @@ -3003,12 +3003,12 @@ inline void AstNodeVarRef::varp(AstVar* varp) { inline bool AstNodeDType::isFourstate() const { return basicp()->isFourstate(); } inline void AstNodeArrayDType::rangep(AstRange* nodep) { setOp2p(nodep); } -inline int AstNodeArrayDType::msb() const { return rangep()->msbConst(); } -inline int AstNodeArrayDType::lsb() const { return rangep()->lsbConst(); } +inline int AstNodeArrayDType::left() const { return rangep()->leftConst(); } +inline int AstNodeArrayDType::right() const { return rangep()->rightConst(); } +inline int AstNodeArrayDType::hi() const { return rangep()->hiConst(); } +inline int AstNodeArrayDType::lo() const { return rangep()->loConst(); } inline int AstNodeArrayDType::elementsConst() const { return rangep()->elementsConst(); } -inline VNumRange AstNodeArrayDType::declRange() const { - return VNumRange(msb(), lsb(), rangep()->littleEndian()); -} +inline VNumRange AstNodeArrayDType::declRange() const { return VNumRange{left(), right()}; } inline const char* AstNodeFTaskRef::broken() const { BROKEN_RTN(m_taskp && !m_taskp->brokeExists()); diff --git a/src/V3AstConstOnly.h b/src/V3AstConstOnly.h index 1e9286c47..c686d429c 100644 --- a/src/V3AstConstOnly.h +++ b/src/V3AstConstOnly.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index a8f0bcba0..262b0421b 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -68,7 +68,7 @@ void AstNodeUOrStructDType::repairMemberCache() { if (m_members.find(itemp->name()) != m_members.end()) { itemp->v3error("Duplicate declaration of member name: " << itemp->prettyNameQ()); } else { - m_members.insert(make_pair(itemp->name(), itemp)); + m_members.emplace(itemp->name(), itemp); } } } @@ -463,21 +463,22 @@ public: } virtual string primitive(const AstVar* varp) const { string type; - if (varp->basicp()->keyword().isDpiUnsignable() && !varp->basicp()->isSigned()) { - type = "unsigned "; - } - type += varp->basicp()->keyword().dpiType(); + const AstBasicDTypeKwd keyword = varp->basicp()->keyword(); + if (keyword.isDpiUnsignable() && !varp->basicp()->isSigned()) type = "unsigned "; + type += keyword.dpiType(); return type; } string convert(const AstVar* varp) const { if (varp->isDpiOpenArray()) { return openArray(varp); - } else if (!varp->basicp()) { - return "UNKNOWN"; - } else if (varp->basicp()->isDpiBitVec() || varp->basicp()->isDpiLogicVec()) { - return bitLogicVector(varp, varp->basicp()->isDpiBitVec()); + } else if (const AstBasicDType* basicp = varp->basicp()) { + if (basicp->isDpiBitVec() || basicp->isDpiLogicVec()) { + return bitLogicVector(varp, basicp->isDpiBitVec()); + } else { + return primitive(varp); + } } else { - return primitive(varp); + return "UNKNOWN"; } } }; @@ -653,12 +654,16 @@ AstNodeDType::CTypeRecursed AstNodeDType::cTypeRecurse(bool compound) const { } else if (const auto* adtypep = VN_CAST_CONST(dtypep, ClassRefDType)) { info.m_type = "VlClassRef<" + EmitCBaseVisitor::prefixNameProtect(adtypep) + ">"; } else if (const auto* adtypep = VN_CAST_CONST(dtypep, UnpackArrayDType)) { - if (compound) { - v3fatalSrc("Dynamic arrays or queues with unpacked elements are not yet supported"); - } + if (adtypep->isCompound()) compound = true; const CTypeRecursed sub = adtypep->subDTypep()->cTypeRecurse(compound); - info.m_type = sub.m_type; - info.m_dims = "[" + cvtToStr(adtypep->declRange().elements()) + "]" + sub.m_dims; + if (compound) { + info.m_type = "VlUnpacked<" + sub.m_type; + info.m_type += ", " + cvtToStr(adtypep->declRange().elements()); + info.m_type += ">"; + } else { + info.m_type = sub.m_type; + info.m_dims = "[" + cvtToStr(adtypep->declRange().elements()) + "]" + sub.m_dims; + } } else if (const AstBasicDType* bdtypep = dtypep->basicp()) { // We don't print msb()/lsb() as multidim packed would require recursion, // and may confuse users as C++ data is stored always with bit 0 used @@ -683,7 +688,7 @@ AstNodeDType::CTypeRecursed AstNodeDType::cTypeRecurse(bool compound) const { info.m_type = "QData" + bitvec; } else if (dtypep->isWide()) { if (compound) { - info.m_type = "VlWide<" + cvtToStr(dtypep->widthWords()) + "> "; + info.m_type = "VlWide<" + cvtToStr(dtypep->widthWords()) + ">"; } else { info.m_type += "WData" + bitvec; // []'s added later info.m_dims = "[" + cvtToStr(dtypep->widthWords()) + "]"; @@ -722,11 +727,13 @@ AstNodeDType* AstNodeDType::dtypeDimensionp(int dimension) { } else if (AstBasicDType* adtypep = VN_CAST(dtypep, BasicDType)) { // AstBasicDType - nothing below, return null if (adtypep->isRanged()) { + // cppcheck-suppress unreadVariable // Cppcheck bug - thinks dim isn't used if ((dim++) == dimension) return adtypep; } return nullptr; } else if (AstNodeUOrStructDType* adtypep = VN_CAST(dtypep, NodeUOrStructDType)) { if (adtypep->packed()) { + // cppcheck-suppress unreadVariable // Cppcheck bug - thinks dim isn't used if ((dim++) == dimension) return adtypep; } return nullptr; @@ -809,7 +816,7 @@ AstNode* AstArraySel::baseFromp(AstNode* nodep) { if (VN_CAST(nodep, NodePreSel)->attrp()) { nodep = VN_CAST(nodep, NodePreSel)->attrp(); } else { - nodep = VN_CAST(nodep, NodePreSel)->lhsp(); + nodep = VN_CAST(nodep, NodePreSel)->fromp(); } continue; } else { @@ -990,7 +997,7 @@ AstBasicDType* AstTypeTable::findInsertSameDType(AstBasicDType* nodep) { DetailedMap& mapr = m_detailedMap; const auto it = mapr.find(key); if (it != mapr.end()) return it->second; - mapr.insert(make_pair(key, nodep)); + mapr.emplace(key, nodep); nodep->generic(true); // No addTypesp; the upper function that called new() is responsible for adding return nodep; @@ -1163,7 +1170,7 @@ void AstClass::insertCache(AstNode* nodep) { if (m_members.find(nodep->name()) != m_members.end()) { nodep->v3error("Duplicate declaration of member name: " << nodep->prettyNameQ()); } else { - m_members.insert(make_pair(nodep->name(), nodep)); + m_members.emplace(nodep->name(), nodep); } } } @@ -1387,15 +1394,17 @@ void AstNodeDType::dumpSmall(std::ostream& str) const { } void AstNodeArrayDType::dumpSmall(std::ostream& str) const { this->AstNodeDType::dumpSmall(str); - if (VN_IS(this, PackArrayDType)) { - str << "p"; + if (auto* adtypep = VN_CAST_CONST(this, UnpackArrayDType)) { + // uc = packed compound object, u = unpacked POD + str << (adtypep->isCompound() ? "uc" : "u"); } else { - str << "u"; + str << "p"; } str << declRange(); } void AstNodeArrayDType::dump(std::ostream& str) const { this->AstNodeDType::dump(str); + if (isCompound()) str << " [COMPOUND]"; str << " " << declRange(); } string AstPackArrayDType::prettyDTypeName() const { @@ -1571,6 +1580,7 @@ void AstVar::dump(std::ostream& str) const { if (isPulldown()) str << " [PULLDOWN]"; if (isUsedClock()) str << " [CLK]"; if (isSigPublic()) str << " [P]"; + if (isLatched()) str << " [LATCHED]"; if (isUsedLoopIdx()) str << " [LOOP]"; if (attrClockEn()) str << " [aCLKEN]"; if (attrIsolateAssign()) str << " [aISO]"; @@ -1605,10 +1615,10 @@ void AstParseRef::dump(std::ostream& str) const { } void AstClassOrPackageRef::dump(std::ostream& str) const { this->AstNode::dump(str); - if (classOrPackagep()) { str << " cpkg=" << nodeAddr(classOrPackagep()); } + if (classOrPackageNodep()) str << " cpkg=" << nodeAddr(classOrPackageNodep()); str << " -> "; - if (classOrPackagep()) { - classOrPackagep()->dump(str); + if (classOrPackageNodep()) { + classOrPackageNodep()->dump(str); } else { str << "UNLINKED"; } diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index 909b741fa..b6bb6653a 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -153,6 +153,13 @@ public: , m_num(this, 1, on) { dtypeSetBit(); } + class Null {}; + AstConst(FileLine* fl, Null) + : ASTGEN_SUPER(fl) + , m_num(V3Number::Null{}, this) { + dtypeSetBit(); // Events 1 bit, objects 64 bits, so autoExtend=1 and use bit here + initWithNumber(); + } ASTNODE_NODE_FUNCS(Const) virtual string name() const override { return num().ascii(); } // * = Value const V3Number& num() const { return m_num; } // * = Value @@ -178,46 +185,25 @@ public: class AstRange final : public AstNodeRange { // Range specification, for use under variables and cells -private: - bool m_littleEndian : 1; // Bit vector is little endian public: - AstRange(FileLine* fl, AstNode* msbp, AstNode* lsbp) + AstRange(FileLine* fl, AstNode* leftp, AstNode* rightp) : ASTGEN_SUPER(fl) { - m_littleEndian = false; - setOp2p(msbp); - setOp3p(lsbp); + setOp2p(leftp); + setOp3p(rightp); } - AstRange(FileLine* fl, int msb, int lsb) + AstRange(FileLine* fl, int left, int right) : ASTGEN_SUPER(fl) { - m_littleEndian = false; - setOp2p(new AstConst(fl, msb)); - setOp3p(new AstConst(fl, lsb)); + setOp2p(new AstConst(fl, left)); + setOp3p(new AstConst(fl, right)); } AstRange(FileLine* fl, const VNumRange& range) : ASTGEN_SUPER(fl) { - m_littleEndian = range.littleEndian(); - setOp2p(new AstConst(fl, range.hi())); - setOp3p(new AstConst(fl, range.lo())); + setOp2p(new AstConst(fl, range.left())); + setOp3p(new AstConst(fl, range.right())); } ASTNODE_NODE_FUNCS(Range) - AstNode* msbp() const { return op2p(); } // op2 = Msb expression - AstNode* lsbp() const { return op3p(); } // op3 = Lsb expression - AstNode* leftp() const { - return littleEndian() ? lsbp() : msbp(); - } // How to show a declaration - AstNode* rightp() const { return littleEndian() ? msbp() : lsbp(); } - int msbConst() const { - AstConst* constp = VN_CAST(msbp(), Const); - return (constp ? constp->toSInt() : 0); - } - int lsbConst() const { - AstConst* constp = VN_CAST(lsbp(), Const); - return (constp ? constp->toSInt() : 0); - } - int elementsConst() const { - return (msbConst() > lsbConst()) ? msbConst() - lsbConst() + 1 - : lsbConst() - msbConst() + 1; - } + AstNode* leftp() const { return op2p(); } + AstNode* rightp() const { return op3p(); } int leftConst() const { AstConst* constp = VN_CAST(leftp(), Const); return (constp ? constp->toSInt() : 0); @@ -226,9 +212,18 @@ public: AstConst* constp = VN_CAST(rightp(), Const); return (constp ? constp->toSInt() : 0); } - int leftToRightInc() const { return littleEndian() ? 1 : -1; } - bool littleEndian() const { return m_littleEndian; } - void littleEndian(bool flag) { m_littleEndian = flag; } + int hiConst() const { + int l = leftConst(); + int r = rightConst(); + return l > r ? l : r; + } + int loConst() const { + int l = leftConst(); + int r = rightConst(); + return l > r ? r : l; + } + int elementsConst() const { return hiConst() - loConst() + 1; } + bool littleEndian() const { return leftConst() < rightConst(); } virtual void dump(std::ostream& str) const override; virtual string emitC() { V3ERROR_NA_RETURN(""); } virtual V3Hash sameHash() const override { return V3Hash(); } @@ -412,6 +407,10 @@ public: AstVarType varType() const { return m_varType; } // * = Type of variable bool isParam() const { return true; } bool isGParam() const { return (varType() == AstVarType::GPARAM); } + virtual bool isCompound() const override { + v3fatalSrc("call isCompound on subdata type, not reference"); + return false; + } }; class AstTypedef final : public AstNode { @@ -512,6 +511,7 @@ public: virtual int widthTotalBytes() const override { return dtypep()->widthTotalBytes(); } virtual string name() const override { return m_name; } virtual void name(const string& flag) override { m_name = flag; } + virtual bool isCompound() const override { return false; } }; class AstAssocArrayDType final : public AstNodeDType { @@ -583,6 +583,7 @@ public: virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } virtual int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); } virtual int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); } + virtual bool isCompound() const override { return true; } }; class AstBracketArrayDType final : public AstNodeDType { @@ -613,6 +614,7 @@ public: virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } virtual int widthAlignBytes() const override { V3ERROR_NA_RETURN(0); } virtual int widthTotalBytes() const override { V3ERROR_NA_RETURN(0); } + virtual bool isCompound() const override { return true; } }; class AstDynArrayDType final : public AstNodeDType { @@ -672,6 +674,7 @@ public: virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } virtual int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); } virtual int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); } + virtual bool isCompound() const override { return true; } }; class AstPackArrayDType final : public AstNodeArrayDType { @@ -698,12 +701,14 @@ public: } ASTNODE_NODE_FUNCS(PackArrayDType) virtual string prettyDTypeName() const override; + virtual bool isCompound() const override { return false; } }; class AstUnpackArrayDType final : public AstNodeArrayDType { // Array data type, ie "some_dtype var_name [2:0]" // Children: DTYPE (moved to refDTypep() in V3Width) // Children: RANGE (array bounds) + bool m_isCompound = false; // Non-POD subDType, or parent requires compound public: AstUnpackArrayDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp, AstRange* rangep) : ASTGEN_SUPER(fl) { @@ -726,8 +731,14 @@ public: } ASTNODE_NODE_FUNCS(UnpackArrayDType) virtual string prettyDTypeName() const override; + virtual bool same(const AstNode* samep) const override { + const AstUnpackArrayDType* sp = static_cast(samep); + return m_isCompound == sp->m_isCompound; + } // Outer dimension comes first. The first element is this node. std::vector unpackDimensions(); + void isCompound(bool flag) { m_isCompound = flag; } + virtual bool isCompound() const override { return m_isCompound; } }; class AstUnsizedArrayDType final : public AstNodeDType { @@ -780,6 +791,7 @@ public: virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } virtual int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); } virtual int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); } + virtual bool isCompound() const override { return true; } }; class AstBasicDType final : public AstNodeDType { @@ -917,26 +929,25 @@ public: bool isDpiPrimitive() const { // DPI uses a primitive type return !isDpiBitVec() && !isDpiLogicVec(); } - // Generally the msb/lsb/etc funcs should be used instead + // Generally the lo/hi/left/right funcs should be used instead of nrange() const VNumRange& nrange() const { return m.m_nrange; } - int msb() const { return (rangep() ? rangep()->msbConst() : m.m_nrange.hi()); } - int lsb() const { return (rangep() ? rangep()->lsbConst() : m.m_nrange.lo()); } - int left() const { return littleEndian() ? lsb() : msb(); } // How to show a declaration - int right() const { return littleEndian() ? msb() : lsb(); } + int hi() const { return (rangep() ? rangep()->hiConst() : m.m_nrange.hi()); } + int lo() const { return (rangep() ? rangep()->loConst() : m.m_nrange.lo()); } + int left() const { return littleEndian() ? lo() : hi(); } // How to show a declaration + int right() const { return littleEndian() ? hi() : lo(); } bool littleEndian() const { return (rangep() ? rangep()->littleEndian() : m.m_nrange.littleEndian()); } bool implicit() const { return keyword() == AstBasicDTypeKwd::LOGIC_IMPLICIT; } - VNumRange declRange() const { - return isRanged() ? VNumRange(msb(), lsb(), littleEndian()) : VNumRange(); - } + VNumRange declRange() const { return isRanged() ? VNumRange{left(), right()} : VNumRange{}; } void cvtRangeConst() { // Convert to smaller representation - if (rangep() && VN_IS(rangep()->msbp(), Const) && VN_IS(rangep()->lsbp(), Const)) { - m.m_nrange.init(rangep()->msbConst(), rangep()->lsbConst(), rangep()->littleEndian()); + if (rangep() && VN_IS(rangep()->leftp(), Const) && VN_IS(rangep()->rightp(), Const)) { + m.m_nrange = VNumRange{rangep()->leftConst(), rangep()->rightConst()}; rangep()->unlinkFrBackWithNext()->deleteTree(); rangep(nullptr); } } + virtual bool isCompound() const override { return isString(); } }; class AstConstDType final : public AstNodeDType { @@ -989,6 +1000,10 @@ public: virtual AstNodeDType* skipRefToEnump() const override { return subDTypep()->skipRefToEnump(); } virtual int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); } virtual int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); } + virtual bool isCompound() const override { + v3fatalSrc("call isCompound on subdata type, not reference"); + return false; + } }; class AstClassRefDType final : public AstNodeDType { @@ -1040,6 +1055,7 @@ public: AstClass* classp() const { return m_classp; } void classp(AstClass* nodep) { m_classp = nodep; } AstPin* paramsp() const { return VN_CAST(op4p(), Pin); } + virtual bool isCompound() const override { return true; } }; class AstIfaceRefDType final : public AstNodeDType { @@ -1095,6 +1111,7 @@ public: AstModport* modportp() const { return m_modportp; } void modportp(AstModport* modportp) { m_modportp = modportp; } bool isModport() { return !m_modportName.empty(); } + virtual bool isCompound() const override { return true; } // But not relevant }; class AstQueueDType final : public AstNodeDType { @@ -1165,6 +1182,7 @@ public: virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } virtual int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); } virtual int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); } + virtual bool isCompound() const override { return true; } }; class AstRefDType final : public AstNodeDType { @@ -1266,6 +1284,10 @@ public: AstNode* typeofp() const { return op2p(); } AstNode* classOrPackageOpp() const { return op3p(); } AstPin* paramsp() const { return VN_CAST(op4p(), Pin); } + virtual bool isCompound() const override { + v3fatalSrc("call isCompound on subdata type, not reference"); + return false; + } }; class AstStructDType final : public AstNodeUOrStructDType { @@ -1348,6 +1370,10 @@ public: virtual string tag() const override { return m_tag; } int lsb() const { return m_lsb; } void lsb(int lsb) { m_lsb = lsb; } + virtual bool isCompound() const override { + v3fatalSrc("call isCompound on subdata type, not reference"); + return false; + } }; class AstVoidDType final : public AstNodeDType { @@ -1375,6 +1401,7 @@ public: virtual int widthAlignBytes() const override { return 1; } virtual int widthTotalBytes() const override { return 1; } virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool isCompound() const override { return false; } }; class AstEnumItem final : public AstNode { @@ -1491,6 +1518,12 @@ public: virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } virtual int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); } virtual int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); } + int itemCount() const { + size_t count = 0; + for (AstNode* itemp = itemsp(); itemp; itemp = itemp->nextp()) count++; + return count; + } + virtual bool isCompound() const override { return false; } }; class AstParseTypeDType final : public AstNodeDType { @@ -1512,6 +1545,10 @@ public: virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } virtual int widthAlignBytes() const override { return 0; } virtual int widthTotalBytes() const override { return 0; } + virtual bool isCompound() const override { + v3fatalSrc("call isCompound on subdata type, not reference"); + return false; + } }; //###################################################################### @@ -1651,8 +1688,8 @@ public: AstSelExtract(FileLine* fl, AstNode* fromp, AstNode* msbp, AstNode* lsbp) : ASTGEN_SUPER(fl, fromp, msbp, lsbp) {} ASTNODE_NODE_FUNCS(SelExtract) - AstNode* msbp() const { return rhsp(); } - AstNode* lsbp() const { return thsp(); } + AstNode* leftp() const { return rhsp(); } + AstNode* rightp() const { return thsp(); } }; class AstSelBit final : public AstNodePreSel { @@ -1899,6 +1936,7 @@ private: bool m_attrSFormat : 1; // User sformat attribute bool m_attrSplitVar : 1; // declared with split_var metacomment bool m_fileDescr : 1; // File descriptor + bool m_isRand : 1; // Random variable bool m_isConst : 1; // Table contains constant data bool m_isStatic : 1; // Static C variable (for Verilog see instead isAutomatic) bool m_isPulldown : 1; // Tri0 @@ -1911,6 +1949,7 @@ private: bool m_noSubst : 1; // Do not substitute out references bool m_overridenParam : 1; // Overridden parameter by #(...) or defparam bool m_trace : 1; // Trace this variable + bool m_isLatched : 1; // Not assigned in all control paths of combo always VLifetime m_lifetime; // Lifetime VVarAttrClocker m_attrClocker; MTaskIdSet m_mtaskIds; // MTaskID's that read or write this var @@ -1938,6 +1977,7 @@ private: m_attrSFormat = false; m_attrSplitVar = false; m_fileDescr = false; + m_isRand = false; m_isConst = false; m_isStatic = false; m_isPulldown = false; @@ -1950,6 +1990,7 @@ private: m_noSubst = false; m_overridenParam = false; m_trace = false; + m_isLatched = false; m_attrClocker = VVarAttrClocker::CLOCKER_UNKNOWN; } @@ -2088,6 +2129,7 @@ public: void sc(bool flag) { m_sc = flag; } void scSensitive(bool flag) { m_scSensitive = flag; } void primaryIO(bool flag) { m_primaryIO = flag; } + void isRand(bool flag) { m_isRand = flag; } void isConst(bool flag) { m_isConst = flag; } void isStatic(bool flag) { m_isStatic = flag; } void isIfaceParent(bool flag) { m_isIfaceParent = flag; } @@ -2106,6 +2148,7 @@ public: void overriddenParam(bool flag) { m_overridenParam = flag; } bool overriddenParam() const { return m_overridenParam; } void trace(bool flag) { m_trace = flag; } + void isLatched(bool flag) { m_isLatched = flag; } // METHODS virtual void name(const string& name) override { m_name = name; } virtual void tag(const string& text) override { m_tag = text; } @@ -2127,7 +2170,7 @@ public: return ((isIO() || isSignal()) && (isIO() || isBitLogic()) // Wrapper would otherwise duplicate wrapped module's coverage - && !isSc() && !isPrimaryIO() && !isConst()); + && !isSc() && !isPrimaryIO() && !isConst() && !isDouble()); } bool isClassMember() const { return varType() == AstVarType::MEMBER; } bool isStatementTemp() const { return (varType() == AstVarType::STMTTEMP); } @@ -2156,8 +2199,10 @@ public: bool isSigUserRdPublic() const { return m_sigUserRdPublic; } bool isSigUserRWPublic() const { return m_sigUserRWPublic; } bool isTrace() const { return m_trace; } + bool isRand() const { return m_isRand; } bool isConst() const { return m_isConst; } bool isStatic() const { return m_isStatic; } + bool isLatched() const { return m_isLatched; } bool isFuncLocal() const { return m_funcLocal; } bool isFuncReturn() const { return m_funcReturn; } bool isPullup() const { return m_isPullup; } @@ -2900,7 +2945,7 @@ public: AstBind(FileLine* fl, const string& name, AstNode* cellsp) : ASTGEN_SUPER(fl) , m_name{name} { - UASSERT_OBJ(VN_IS(cellsp, Cell), cellsp, "Only cells allowed to be bound"); + UASSERT_OBJ(VN_IS(cellsp, Cell), cellsp, "Only instances allowed to be bound"); addNOp1p(cellsp); } ASTNODE_NODE_FUNCS(Bind) @@ -2967,36 +3012,39 @@ public: class AstClassOrPackageRef final : public AstNode { private: string m_name; - AstNode* m_classOrPackagep; // Package hierarchy + // Node not NodeModule to appease some early parser usage + AstNode* m_classOrPackageNodep; // Package hierarchy public: - AstClassOrPackageRef(FileLine* fl, const string& name, AstNode* classOrPackagep, + AstClassOrPackageRef(FileLine* fl, const string& name, AstNode* classOrPackageNodep, AstNode* paramsp) : ASTGEN_SUPER(fl) , m_name{name} - , m_classOrPackagep{classOrPackagep} { + , m_classOrPackageNodep{classOrPackageNodep} { addNOp4p(paramsp); } ASTNODE_NODE_FUNCS(ClassOrPackageRef) // METHODS virtual const char* broken() const override { - BROKEN_RTN(m_classOrPackagep && !m_classOrPackagep->brokeExists()); + BROKEN_RTN(m_classOrPackageNodep && !m_classOrPackageNodep->brokeExists()); return nullptr; } virtual void cloneRelink() override { - if (m_classOrPackagep && m_classOrPackagep->clonep()) { - m_classOrPackagep = m_classOrPackagep->clonep(); + if (m_classOrPackageNodep && m_classOrPackageNodep->clonep()) { + m_classOrPackageNodep = m_classOrPackageNodep->clonep(); } } virtual bool same(const AstNode* samep) const override { - return (m_classOrPackagep - == static_cast(samep)->m_classOrPackagep); + return (m_classOrPackageNodep + == static_cast(samep)->m_classOrPackageNodep); } - virtual V3Hash sameHash() const override { return V3Hash(m_classOrPackagep); } + virtual V3Hash sameHash() const override { return V3Hash(m_classOrPackageNodep); } virtual void dump(std::ostream& str = std::cout) const override; virtual string name() const override { return m_name; } // * = Var name - AstNodeModule* classOrPackagep() const { return VN_CAST(m_classOrPackagep, NodeModule); } - AstPackage* packagep() const { return VN_CAST(classOrPackagep(), Package); } - void classOrPackagep(AstNode* nodep) { m_classOrPackagep = nodep; } + AstNode* classOrPackageNodep() const { return m_classOrPackageNodep; } + void classOrPackageNodep(AstNode* nodep) { m_classOrPackageNodep = nodep; } + AstNodeModule* classOrPackagep() const { return VN_CAST(m_classOrPackageNodep, NodeModule); } + AstPackage* packagep() const { return VN_CAST(classOrPackageNodep(), Package); } + void classOrPackagep(AstNodeModule* nodep) { m_classOrPackageNodep = nodep; } AstPin* paramsp() const { return VN_CAST(op4p(), Pin); } }; @@ -3450,6 +3498,30 @@ public: virtual bool brokeLhsMustBeLvalue() const override { return true; } }; +class AstExprStmt final : public AstNodeMath { + // Perform a statement, often assignment inside an expression/math node, + // the parent gets passed the 'resultp()'. + // resultp is evaluated AFTER the statement(s). +public: + AstExprStmt(FileLine* fl, AstNode* stmtsp, AstNode* resultp) + : ASTGEN_SUPER(fl) { + addOp1p(stmtsp); + setOp2p(resultp); // Possibly in future nullptr could mean return rhsp() + dtypeFrom(resultp); + } + ASTNODE_NODE_FUNCS(ExprStmt) + // ACCESSORS + AstNode* stmtsp() const { return op1p(); } + void addStmtsp(AstNode* nodep) { addOp1p(nodep); } + AstNode* resultp() const { return op2p(); } + // METHODS + virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { return false; } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode*) const override { return true; } +}; + class AstComment final : public AstNodeStmt { // Some comment to put into the output stream // Parents: {statement list} @@ -4521,7 +4593,7 @@ public: class AstDisableFork final : public AstNodeStmt { // A "disable fork" statement public: - AstDisableFork(FileLine* fl) + explicit AstDisableFork(FileLine* fl) : ASTGEN_SUPER(fl) {} ASTNODE_NODE_FUNCS(DisableFork) }; @@ -4529,7 +4601,7 @@ public: class AstWaitFork final : public AstNodeStmt { // A "wait fork" statement public: - AstWaitFork(FileLine* fl) + explicit AstWaitFork(FileLine* fl) : ASTGEN_SUPER(fl) {} ASTNODE_NODE_FUNCS(WaitFork) }; @@ -4582,7 +4654,7 @@ class AstJumpBlock final : public AstNodeStmt { // Parents: {statement list} // Children: {statement list, with JumpGo and JumpLabel below} private: - AstJumpLabel* m_labelp; // [After V3Jump] Pointer to declaration + AstJumpLabel* m_labelp = nullptr; // [After V3Jump] Pointer to declaration int m_labelNum = 0; // Set by V3EmitCSyms to tell final V3Emit what to increment public: // After construction must call ->labelp to associate with appropriate label @@ -4768,7 +4840,7 @@ class AstConsDynArray final : public AstNodeMath { // Parents: math // Children: expression (elements or other queues) public: - AstConsDynArray(FileLine* fl, AstNode* lhsp = nullptr, AstNode* rhsp = nullptr) + explicit AstConsDynArray(FileLine* fl, AstNode* lhsp = nullptr, AstNode* rhsp = nullptr) : ASTGEN_SUPER(fl) { setNOp1p(lhsp); setNOp2p(rhsp); @@ -4790,7 +4862,7 @@ class AstConsQueue final : public AstNodeMath { // Parents: math // Children: expression (elements or other queues) public: - AstConsQueue(FileLine* fl, AstNode* lhsp = nullptr, AstNode* rhsp = nullptr) + explicit AstConsQueue(FileLine* fl, AstNode* lhsp = nullptr, AstNode* rhsp = nullptr) : ASTGEN_SUPER(fl) { setNOp1p(lhsp); setNOp2p(rhsp); @@ -4953,7 +5025,7 @@ public: it->second->valuep(newp); } else { AstInitItem* itemp = new AstInitItem(fileline(), newp); - m_map.insert(it, make_pair(index, itemp)); + m_map.emplace(index, itemp); addOp2p(itemp); } return oldp; @@ -5054,7 +5126,7 @@ class AstPrintTimeScale final : public AstNodeStmt { string m_name; // Parent module name VTimescale m_timeunit; // Parent module time unit public: - AstPrintTimeScale(FileLine* fl) + explicit AstPrintTimeScale(FileLine* fl) : ASTGEN_SUPER(fl) {} ASTNODE_NODE_FUNCS(PrintTimeScale) virtual void name(const string& name) override { m_name = name; } @@ -5619,25 +5691,6 @@ public: virtual bool sizeMattersLhs() const override { return false; } virtual int instrCount() const override { return 1 + V3Number::log2b(width()); } }; -class AstRedXnor final : public AstNodeUniop { - // AstRedXnors are replaced with AstRedXors in V3Const. -public: - AstRedXnor(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER(fl, lhsp) { - dtypeSetBit(); - } - ASTNODE_NODE_FUNCS(RedXnor) - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opRedXnor(lhs); } - virtual string emitVerilog() override { return "%f(~^ %l)"; } - virtual string emitC() override { - v3fatalSrc("REDXNOR should have became REDXOR"); - return ""; - } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual int instrCount() const override { return 1 + V3Number::log2b(width()); } -}; class AstLenN final : public AstNodeUniop { // Length of a string @@ -6015,6 +6068,7 @@ public: virtual bool cleanLhs() const { return true; } virtual bool sizeMattersLhs() const { return false; } AstNode* lhsp() const { return op1p(); } + AstNode* fromp() const { return lhsp(); } void lhsp(AstNode* nodep) { setOp1p(nodep); } virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); } AstNodeDType* childDTypep() const { return VN_CAST(op2p(), NodeDType); } @@ -6026,6 +6080,9 @@ class AstCastDynamic final : public AstNodeBiop { // Task usage of $cast is converted during parse to assert($cast(...)) // Parents: MATH // Children: MATH + // lhsp() is value (we are converting FROM) to match AstCCast etc, this + // is opposite of $cast's order, because the first access is to the + // value reading from. Suggest use fromp()/top() instead of lhsp/rhsp(). public: AstCastDynamic(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) {} @@ -6037,8 +6094,7 @@ public: return new AstCastDynamic(this->fileline(), lhsp, rhsp); } virtual string emitVerilog() override { return "%f$cast(%r, %l)"; } - // Non-existent filehandle returns EOF - virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitC() override { return "VL_DYNAMIC_CAST(%r, %l)"; } virtual bool cleanOut() const override { return true; } virtual bool cleanLhs() const override { return true; } virtual bool cleanRhs() const override { return true; } @@ -6046,6 +6102,8 @@ public: virtual bool sizeMattersRhs() const override { return false; } virtual int instrCount() const override { return widthInstrs() * 20; } virtual bool isPure() const override { return true; } + AstNode* fromp() const { return lhsp(); } + AstNode* top() const { return rhsp(); } }; class AstCastParse final : public AstNode { @@ -6714,28 +6772,6 @@ public: virtual bool sizeMattersLhs() const override { return false; } virtual bool sizeMattersRhs() const override { return false; } }; -class AstXnor final : public AstNodeBiComAsv { -public: - AstXnor(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER(fl, lhsp, rhsp) { - dtypeFrom(lhsp); - } - ASTNODE_NODE_FUNCS(Xnor) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstXnor(this->fileline(), lhsp, rhsp); - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.opXnor(lhs, rhs); - } - virtual string emitVerilog() override { return "%k(%l %f^ ~ %r)"; } - virtual string emitC() override { return "VL_XNOR_%lq(%lW, %P, %li, %ri)"; } - virtual string emitSimpleOperator() override { return "^ ~"; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return true; } - virtual bool sizeMattersRhs() const override { return true; } -}; class AstEq final : public AstNodeBiCom { public: AstEq(FileLine* fl, AstNode* lhsp, AstNode* rhsp) @@ -8566,6 +8602,18 @@ public: AstNode* failsp() const { return op3p(); } // op3 = if assertion fails }; +class AstAssertIntrinsic final : public AstNodeCoverOrAssert { + // A $cast or other compiler inserted assert, that must run even without --assert option +public: + ASTNODE_NODE_FUNCS(AssertIntrinsic) + AstAssertIntrinsic(FileLine* fl, AstNode* propp, AstNode* passsp, AstNode* failsp, + bool immediate, const string& name = "") + : ASTGEN_SUPER(fl, propp, passsp, immediate, name) { + addNOp3p(failsp); + } + AstNode* failsp() const { return op3p(); } // op3 = if assertion fails +}; + class AstCover final : public AstNodeCoverOrAssert { public: ASTNODE_NODE_FUNCS(Cover) @@ -9166,6 +9214,7 @@ private: AstExecGraph* m_execGraphp = nullptr; // Execution MTask graph for threads>1 mode VTimescale m_timeunit; // Global time unit VTimescale m_timeprecision; // Global time precision + bool m_timescaleSpecified = false; // Input HDL specified timescale public: AstNetlist() : ASTGEN_SUPER(new FileLine(FileLine::builtInFilename())) {} @@ -9217,6 +9266,8 @@ public: m_timeprecision = v3Global.opt.timeDefaultPrec(); } void timeprecisionMerge(FileLine*, const VTimescale& value); + void timescaleSpecified(bool specified) { m_timescaleSpecified = specified; } + bool timescaleSpecified() const { return m_timescaleSpecified; } }; //###################################################################### diff --git a/src/V3Begin.cpp b/src/V3Begin.cpp index 3f92f8081..8a9f2943c 100644 --- a/src/V3Begin.cpp +++ b/src/V3Begin.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Begin.h b/src/V3Begin.h index fcd0a33f9..3962ce5e8 100644 --- a/src/V3Begin.h +++ b/src/V3Begin.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Branch.cpp b/src/V3Branch.cpp index 34901d20e..b4e6a2bf5 100644 --- a/src/V3Branch.cpp +++ b/src/V3Branch.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Branch.h b/src/V3Branch.h index d8ebed0f5..fd3a0736f 100644 --- a/src/V3Branch.h +++ b/src/V3Branch.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Broken.cpp b/src/V3Broken.cpp index 7ca71dfff..5df76d8e7 100644 --- a/src/V3Broken.cpp +++ b/src/V3Broken.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -73,7 +73,7 @@ public: "Newing AstNode object that is already allocated"); if (iter == s_nodes.end()) { int flags = FLAG_ALLOCATED; // This int needed to appease GCC 4.1.2 - s_nodes.insert(make_pair(nodep, flags)); + s_nodes.emplace(nodep, flags); } } static void setUnder(const AstNode* nodep, bool flag) { @@ -105,7 +105,7 @@ public: } int or_flags = FLAG_IN_TREE | (linkable ? FLAG_LINKABLE : 0); if (iter == s_nodes.end()) { - s_nodes.insert(make_pair(nodep, or_flags)); + s_nodes.emplace(nodep, or_flags); } else { iter->second |= or_flags; } @@ -329,3 +329,13 @@ void V3Broken::brokenAll(AstNetlist* nodep) { void V3Broken::addNewed(AstNode* nodep) { BrokenTable::addNewed(nodep); } void V3Broken::deleted(AstNode* nodep) { BrokenTable::deleted(nodep); } bool V3Broken::isAllocated(AstNode* nodep) { return BrokenTable::isAllocated(nodep); } +void V3Broken::selfTest() { + // Warmup addNewed and deleted for coverage, as otherwise only with VL_LEAK_CHECKS + FileLine* fl = new FileLine(FileLine::commandLineFilename()); + auto* newp = new AstBegin(fl, "[EditWrapper]", nullptr); +#ifndef VL_LEAK_CHECKS + addNewed(newp); + deleted(newp); +#endif + VL_DO_DANGLING(delete newp, newp); +} diff --git a/src/V3Broken.h b/src/V3Broken.h index ee7d718f6..88d87ce3e 100644 --- a/src/V3Broken.h +++ b/src/V3Broken.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -31,6 +31,7 @@ public: static void addNewed(AstNode* nodep); static void deleted(AstNode* nodep); static bool isAllocated(AstNode* nodep); + static void selfTest(); }; #endif // Guard diff --git a/src/V3CCtors.cpp b/src/V3CCtors.cpp index 65b98c3b1..49556d404 100644 --- a/src/V3CCtors.cpp +++ b/src/V3CCtors.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3CCtors.h b/src/V3CCtors.h index 533a0e819..c5590ae52 100644 --- a/src/V3CCtors.h +++ b/src/V3CCtors.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3CUse.cpp b/src/V3CUse.cpp index f9c835462..8aa7c1513 100644 --- a/src/V3CUse.cpp +++ b/src/V3CUse.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3CUse.h b/src/V3CUse.h index d3d0a44af..ec5028c37 100644 --- a/src/V3CUse.h +++ b/src/V3CUse.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Case.cpp b/src/V3Case.cpp index 06ece071c..d40c6eb0e 100644 --- a/src/V3Case.cpp +++ b/src/V3Case.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -127,6 +127,7 @@ private: // STATE VDouble0 m_statCaseFast; // Statistic tracking VDouble0 m_statCaseSlow; // Statistic tracking + AstNode* m_alwaysp = nullptr; // Always in which case is located // Per-CASE int m_caseWidth = 0; // Width of valueItems @@ -475,12 +476,17 @@ private: ++m_statCaseFast; VL_DO_DANGLING(replaceCaseFast(nodep), nodep); } else { + // If a case statement is whole, presume signals involved aren't forming a latch + if (m_alwaysp) m_alwaysp->fileline()->warnOff(V3ErrorCode::LATCH, true); ++m_statCaseSlow; VL_DO_DANGLING(replaceCaseComplicated(nodep), nodep); } } //-------------------- - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + virtual void visit(AstNode* nodep) override { + if (VN_IS(nodep, Always)) { m_alwaysp = nodep; } + iterateChildren(nodep); + } public: // CONSTRUCTORS diff --git a/src/V3Case.h b/src/V3Case.h index 35d4abbf7..001c063ea 100644 --- a/src/V3Case.h +++ b/src/V3Case.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Cast.cpp b/src/V3Cast.cpp index 355516acb..c8e5536cf 100644 --- a/src/V3Cast.cpp +++ b/src/V3Cast.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2004-2020 by Wilson Snyder. This program is free software; you +// Copyright 2004-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Cast.h b/src/V3Cast.h index ab9ad4dc0..8d35af3ef 100644 --- a/src/V3Cast.h +++ b/src/V3Cast.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2004-2020 by Wilson Snyder. This program is free software; you +// Copyright 2004-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Cdc.cpp b/src/V3Cdc.cpp index dfb70a833..95b44887f 100644 --- a/src/V3Cdc.cpp +++ b/src/V3Cdc.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Cdc.h b/src/V3Cdc.h index 9d59849f1..549474d30 100644 --- a/src/V3Cdc.h +++ b/src/V3Cdc.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Changed.cpp b/src/V3Changed.cpp index dbe1905b7..6bd904099 100644 --- a/src/V3Changed.cpp +++ b/src/V3Changed.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Changed.h b/src/V3Changed.h index 79c56cb27..2646a1084 100644 --- a/src/V3Changed.h +++ b/src/V3Changed.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Class.cpp b/src/V3Class.cpp index 83f99724a..7556bd19c 100644 --- a/src/V3Class.cpp +++ b/src/V3Class.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Class.h b/src/V3Class.h index a436bd9ed..d9da9dcb3 100644 --- a/src/V3Class.h +++ b/src/V3Class.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Clean.cpp b/src/V3Clean.cpp index 458e366fe..065f55197 100644 --- a/src/V3Clean.cpp +++ b/src/V3Clean.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Clean.h b/src/V3Clean.h index 76223d2ee..4ca00a58a 100644 --- a/src/V3Clean.h +++ b/src/V3Clean.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Clock.cpp b/src/V3Clock.cpp index e4a5da09f..04c174fa8 100644 --- a/src/V3Clock.cpp +++ b/src/V3Clock.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -294,31 +294,25 @@ private: m_scopep = nullptr; } virtual void visit(AstNodeProcedure* nodep) override { - AstNode* cmtp = new AstComment(nodep->fileline(), nodep->typeName(), true); - nodep->replaceWith(cmtp); if (AstNode* stmtsp = nodep->bodysp()) { stmtsp->unlinkFrBackWithNext(); - cmtp->addNextHere(stmtsp); + nodep->addNextHere(stmtsp); } - VL_DO_DANGLING(nodep->deleteTree(), nodep); + VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); } virtual void visit(AstAlwaysPost* nodep) override { - AstNode* cmtp = new AstComment(nodep->fileline(), nodep->typeName(), true); - nodep->replaceWith(cmtp); if (AstNode* stmtsp = nodep->bodysp()) { stmtsp->unlinkFrBackWithNext(); - cmtp->addNextHere(stmtsp); + nodep->addNextHere(stmtsp); } - VL_DO_DANGLING(nodep->deleteTree(), nodep); + VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); } virtual void visit(AstAlwaysPostponed* nodep) override { - AstNode* cmtp = new AstComment(nodep->fileline(), nodep->typeName(), true); - nodep->replaceWith(cmtp); if (AstNode* stmtsp = nodep->bodysp()) { stmtsp->unlinkFrBackWithNext(); - cmtp->addNextHere(stmtsp); + nodep->addNextHere(stmtsp); } - VL_DO_DANGLING(nodep->deleteTree(), nodep); + VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); } virtual void visit(AstCoverToggle* nodep) override { // nodep->dumpTree(cout, "ct:"); diff --git a/src/V3Clock.h b/src/V3Clock.h index de0ae9f2f..cdda29e18 100644 --- a/src/V3Clock.h +++ b/src/V3Clock.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Combine.cpp b/src/V3Combine.cpp index 795f1a8b1..687f8d602 100644 --- a/src/V3Combine.cpp +++ b/src/V3Combine.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -106,7 +106,7 @@ public: } } // METHODS - void addCall(AstCCall* nodep) { m_callMmap.insert(make_pair(nodep->funcp(), nodep)); } + void addCall(AstCCall* nodep) { m_callMmap.emplace(nodep->funcp(), nodep); } void deleteCall(AstCCall* nodep) { std::pair eqrange = m_callMmap.equal_range(nodep->funcp()); @@ -218,21 +218,27 @@ private: } } void walkDupFuncs() { - for (V3Hashed::iterator it = m_hashed.begin(); it != m_hashed.end(); ++it) { - V3Hash hashval = it->first; - AstNode* node1p = it->second; - if (!VN_IS(node1p, CFunc)) continue; - UASSERT_OBJ(!hashval.isIllegal(), node1p, "Illegal (unhashed) nodes"); - for (V3Hashed::iterator eqit = it; eqit != m_hashed.end(); ++eqit) { - AstNode* node2p = eqit->second; - if (!(eqit->first == hashval)) break; - if (node1p == node2p) continue; // Identical iterator - if (node1p->user3p() || node2p->user3p()) continue; // Already merged - if (node1p->sameTree(node2p)) { // walk of tree has same comparison - // Replace AstCCall's that point here - replaceFuncWFunc(VN_CAST(node2p, CFunc), VN_CAST(node1p, CFunc)); - // Replacement may promote a slow routine to fast path - if (!VN_CAST(node2p, CFunc)->slow()) VN_CAST(node1p, CFunc)->slow(false); + // Do non-slow first as then favors naming functions based on fast name + for (int slow = 0; slow < 2; ++slow) { + for (V3Hashed::iterator it = m_hashed.begin(); it != m_hashed.end(); ++it) { + AstNode* node1p = it->second; + AstCFunc* cfunc1p = VN_CAST(node1p, CFunc); + if (!cfunc1p) continue; + // cppcheck-suppress compareBoolExpressionWithInt + if (cfunc1p->slow() != slow) continue; + V3Hash hashval = it->first; + UASSERT_OBJ(!hashval.isIllegal(), node1p, "Illegal (unhashed) nodes"); + for (V3Hashed::iterator eqit = it; eqit != m_hashed.end(); ++eqit) { + AstNode* node2p = eqit->second; + if (!(eqit->first == hashval)) break; + if (node1p == node2p) continue; // Identical iterator + if (node1p->user3p() || node2p->user3p()) continue; // Already merged + if (node1p->sameTree(node2p)) { // walk of tree has same comparison + // Replace AstCCall's that point here + replaceFuncWFunc(VN_CAST(node2p, CFunc), cfunc1p); + // Replacement may promote a slow routine to fast path + if (!VN_CAST(node2p, CFunc)->slow()) cfunc1p->slow(false); + } } } } diff --git a/src/V3Combine.h b/src/V3Combine.h index aee53c2ae..fb2b99c07 100644 --- a/src/V3Combine.h +++ b/src/V3Combine.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Config.cpp b/src/V3Config.cpp index f552b766a..b0f035cd2 100644 --- a/src/V3Config.cpp +++ b/src/V3Config.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2010-2020 by Wilson Snyder. This program is free software; you +// Copyright 2010-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Config.h b/src/V3Config.h index dcf01427f..c86c60e83 100644 --- a/src/V3Config.h +++ b/src/V3Config.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2010-2020 by Wilson Snyder. This program is free software; you +// Copyright 2010-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Const.cpp b/src/V3Const.cpp index 1d0dccd64..8ef02f707 100644 --- a/src/V3Const.cpp +++ b/src/V3Const.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -94,6 +94,7 @@ private: bool m_wremove = true; // Inside scope, no assignw removal bool m_warn = false; // Output warnings bool m_doExpensive = false; // Enable computationally expensive optimizations + bool m_doCpp = false; // Enable late-stage C++ optimizations bool m_doNConst = false; // Enable non-constant-child simplifications bool m_doShort = true; // Remove expressions that short circuit bool m_doV = false; // Verilog, not C++ conversion @@ -509,7 +510,7 @@ private: return true; } bool ifConcatMergeableBiop(const AstNode* nodep) { - return (VN_IS(nodep, And) || VN_IS(nodep, Or) || VN_IS(nodep, Xor) || VN_IS(nodep, Xnor)); + return (VN_IS(nodep, And) || VN_IS(nodep, Or) || VN_IS(nodep, Xor)); } bool ifAdjacentSel(const AstSel* lhsp, const AstSel* rhsp) { if (!v3Global.opt.oAssemble()) return false; // opt disabled @@ -1967,7 +1968,6 @@ private: bool stmtDisplayDisplay(AstDisplay* nodep) { // DISPLAY(SFORMAT(text1)),DISPLAY(SFORMAT(text2)) -> DISPLAY(SFORMAT(text1+text2)) if (!m_modp) return false; // Don't optimize under single statement - if (!nodep->backp()) return false; AstDisplay* prevp = VN_CAST(nodep->backp(), Display); if (!prevp) return false; if (!((prevp->displayType() == nodep->displayType()) @@ -1981,12 +1981,21 @@ private: return false; if (!prevp->fmtp() || prevp->fmtp()->nextp() || !nodep->fmtp() || nodep->fmtp()->nextp()) return false; - // We don't merge scopeNames as might be different scopes (late in process) - // We don't merge arguments as might need to later print warnings with right line numbers AstSFormatF* pformatp = prevp->fmtp(); - if (!pformatp || pformatp->exprsp() || pformatp->scopeNamep()) return false; + if (!pformatp) return false; AstSFormatF* nformatp = nodep->fmtp(); - if (!nformatp || nformatp->exprsp() || nformatp->scopeNamep()) return false; + if (!nformatp) return false; + // We don't merge scopeNames as can have only one and might be different scopes (late in + // process) Also rare for real code to print %m multiple times in same message + if (nformatp->scopeNamep() && pformatp->scopeNamep()) return false; + // We don't early merge arguments as might need to later print warnings with + // right line numbers, nor scopeNames as might be different scopes (late in process) + if (!m_doCpp && pformatp->exprsp()) return false; + if (!m_doCpp && nformatp->exprsp()) return false; + // Avoid huge merges + static constexpr int DISPLAY_MAX_MERGE_LENGTH = 500; + if (pformatp->text().length() + nformatp->text().length() > DISPLAY_MAX_MERGE_LENGTH) + return false; // UINFO(9, "DISPLAY(SF({a})) DISPLAY(SF({b})) -> DISPLAY(SF({a}+{b}))" << endl); // Convert DT_DISPLAY to DT_WRITE as may allow later optimizations @@ -1998,9 +2007,10 @@ private: // So instead we edit the prev note itself. if (prevp->addNewline()) pformatp->text(pformatp->text() + "\n"); pformatp->text(pformatp->text() + nformatp->text()); - if (!prevp->addNewline() && nodep->addNewline()) { - pformatp->text(pformatp->text() + "\n"); - } + if (!prevp->addNewline() && nodep->addNewline()) pformatp->text(pformatp->text() + "\n"); + if (nformatp->exprsp()) pformatp->addExprsp(nformatp->exprsp()->unlinkFrBackWithNext()); + if (nformatp->scopeNamep()) + pformatp->scopeNamep(nformatp->scopeNamep()->unlinkFrBackWithNext()); VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); return true; } @@ -2248,7 +2258,6 @@ private: TREEOP ("AstShiftR{$lhsp.isZero, $rhsp}", "replaceZeroChkPure(nodep,$rhsp)"); TREEOP ("AstShiftRS{$lhsp.isZero, $rhsp}", "replaceZeroChkPure(nodep,$rhsp)"); TREEOP ("AstXor {$lhsp.isZero, $rhsp}", "replaceWRhs(nodep)"); - TREEOP ("AstXnor {$lhsp.isZero, $rhsp}", "AstNot{$rhsp}"); TREEOP ("AstSub {$lhsp.isZero, $rhsp}", "AstNegate{$rhsp}"); TREEOP ("AstAdd {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)"); TREEOP ("AstAnd {$lhsp, $rhsp.isZero}", "replaceZeroChkPure(nodep,$lhsp)"); @@ -2262,7 +2271,6 @@ private: TREEOP ("AstShiftRS{$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)"); TREEOP ("AstSub {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)"); TREEOP ("AstXor {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)"); - TREEOP ("AstXnor {$lhsp, $rhsp.isZero}", "AstNot{$lhsp}"); // Non-zero on one side or the other TREEOP ("AstAnd {$lhsp.isAllOnes, $rhsp}", "replaceWRhs(nodep)"); TREEOP ("AstLogAnd{$lhsp.isNeqZero, $rhsp}", "replaceWRhs(nodep)"); @@ -2273,7 +2281,6 @@ private: TREEOP ("AstOr {$lhsp, $rhsp.isAllOnes, isTPure($lhsp)}", "replaceWRhs(nodep)"); //->allOnes TREEOP ("AstLogOr {$lhsp, $rhsp.isNeqZero, isTPure($lhsp)}", "replaceNum(nodep,1)"); TREEOP ("AstXor {$lhsp.isAllOnes, $rhsp}", "AstNot{$rhsp}"); - TREEOP ("AstXnor {$lhsp.isAllOnes, $rhsp}", "replaceWRhs(nodep)"); TREEOP ("AstMul {$lhsp.isOne, $rhsp}", "replaceWRhs(nodep)"); TREEOP ("AstMulS {$lhsp.isOne, $rhsp}", "replaceWRhs(nodep)"); TREEOP ("AstDiv {$lhsp, $rhsp.isOne}", "replaceWLhs(nodep)"); @@ -2384,7 +2391,6 @@ private: TREEOP ("AstDivS {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); TREEOP ("AstOr {operandsSame($lhsp,,$rhsp)}", "replaceWLhs(nodep)"); TREEOP ("AstSub {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)"); - TREEOP ("AstXnor {operandsSame($lhsp,,$rhsp)}", "replaceAllOnes(nodep)"); TREEOP ("AstXor {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)"); TREEOP ("AstEq {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); // We let X==X -> 1, although in a true 4-state sim it's X. TREEOP ("AstEqD {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); // We let X==X -> 1, although in a true 4-state sim it's X. @@ -2461,8 +2467,6 @@ private: TREEOP ("AstAnd {operandShiftSame(nodep)}", "replaceShiftSame(nodep)"); TREEOP ("AstOr {operandShiftSame(nodep)}", "replaceShiftSame(nodep)"); TREEOP ("AstXor {operandShiftSame(nodep)}", "replaceShiftSame(nodep)"); - // "AstXnor{operandShiftSame(nodep)}", // Cannot ShiftSame as the shifted-in - // zeros might create a one // Note can't simplify a extend{extends}, extends{extend}, as the sign // bits end up in the wrong places TREEOPV("AstExtend {$lhsp.castExtend}", "replaceExtend(nodep, VN_CAST(nodep->lhsp(), Extend)->lhsp())"); @@ -2480,7 +2484,6 @@ private: TREEOPV("AstSel{$fromp.castAnd, operandSelBiLower(nodep)}", "DONE"); TREEOPV("AstSel{$fromp.castOr, operandSelBiLower(nodep)}", "DONE"); TREEOPV("AstSel{$fromp.castSub, operandSelBiLower(nodep)}", "DONE"); - TREEOPV("AstSel{$fromp.castXnor,operandSelBiLower(nodep)}", "DONE"); TREEOPV("AstSel{$fromp.castXor, operandSelBiLower(nodep)}", "DONE"); TREEOPV("AstSel{$fromp.castShiftR, operandSelShiftLower(nodep)}", "DONE"); TREEOPC("AstSel{$fromp.castConst, $lsbp.castConst, $widthp.castConst, }", "replaceConst(nodep)"); @@ -2494,9 +2497,6 @@ private: TREEOPV("AstSel{$fromp.castAnd,$lhsp.castConst}", "replaceSelIntoUniop(nodep)"); TREEOPV("AstSel{$fromp.castOr,$lhsp.castConst}", "replaceSelIntoUniop(nodep)"); TREEOPV("AstSel{$fromp.castXor,$lhsp.castConst}", "replaceSelIntoUniop(nodep)"); - TREEOPV("AstSel{$fromp.castXnor,$lhsp.castConst}", "replaceSelIntoUniop(nodep)"); - // Conversions - TREEOPV("AstRedXnor{$lhsp}", "AstNot{AstRedXor{$lhsp}}"); // Just eliminate XNOR's // This visit function here must allow for short-circuiting. TREEOPS("AstLogIf{$lhsp.isZero}", "replaceNum(nodep, 1)"); TREEOPV("AstLogIf{$lhsp, $rhsp}", "AstLogOr{AstLogNot{$lhsp},$rhsp}"); @@ -2559,7 +2559,7 @@ public: case PROC_V_WARN: m_doV = true; m_doNConst = true; m_warn = true; break; case PROC_V_NOWARN: m_doV = true; m_doNConst = true; break; case PROC_V_EXPENSIVE: m_doV = true; m_doNConst = true; m_doExpensive = true; break; - case PROC_CPP: m_doV = false; m_doNConst = true; break; + case PROC_CPP: m_doV = false; m_doNConst = true; m_doCpp = true; break; default: v3fatalSrc("Bad case"); break; } // clang-format on diff --git a/src/V3Const.h b/src/V3Const.h index f5b8732f3..6ccd67713 100644 --- a/src/V3Const.h +++ b/src/V3Const.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Coverage.cpp b/src/V3Coverage.cpp index 3a4c2f3d9..161839acf 100644 --- a/src/V3Coverage.cpp +++ b/src/V3Coverage.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -142,7 +142,7 @@ private: + cvtToStr(nodep->fileline()->lineno()) + "_" + type; const auto it = m_varnames.find(name); if (it == m_varnames.end()) { - m_varnames.insert(make_pair(name, 1)); + m_varnames.emplace(name, 1); } else { int suffix = (it->second)++; name += "_" + cvtToStr(suffix); @@ -210,6 +210,7 @@ private: // VISITORS - BOTH virtual void visit(AstNodeModule* nodep) override { AstNodeModule* origModp = m_modp; + VL_RESTORER(m_modp); VL_RESTORER(m_state); { createHandle(nodep); @@ -223,7 +224,6 @@ private: } iterateChildren(nodep); } - m_modp = origModp; } virtual void visit(AstNodeProcedure* nodep) override { iterateProcedure(nodep); } @@ -310,9 +310,9 @@ private: const ToggleEnt& above, AstVar* varp, AstVar* chgVarp) { // Constant if (const AstBasicDType* bdtypep = VN_CAST(dtypep, BasicDType)) { if (bdtypep->isRanged()) { - for (int index_docs = bdtypep->lsb(); index_docs < bdtypep->msb() + 1; - index_docs++) { - int index_code = index_docs - bdtypep->lsb(); + for (int index_docs = bdtypep->lo(); index_docs < bdtypep->hi() + 1; + ++index_docs) { + int index_code = index_docs - bdtypep->lo(); ToggleEnt newent(above.m_comment + string("[") + cvtToStr(index_docs) + "]", new AstSel(varp->fileline(), above.m_varRefp->cloneTree(true), index_code, 1), @@ -325,8 +325,8 @@ private: toggleVarBottom(above, varp); } } else if (AstUnpackArrayDType* adtypep = VN_CAST(dtypep, UnpackArrayDType)) { - for (int index_docs = adtypep->lsb(); index_docs <= adtypep->msb(); ++index_docs) { - int index_code = index_docs - adtypep->lsb(); + for (int index_docs = adtypep->lo(); index_docs <= adtypep->hi(); ++index_docs) { + int index_code = index_docs - adtypep->lo(); ToggleEnt newent(above.m_comment + string("[") + cvtToStr(index_docs) + "]", new AstArraySel(varp->fileline(), above.m_varRefp->cloneTree(true), index_code), @@ -337,9 +337,9 @@ private: newent.cleanup(); } } else if (AstPackArrayDType* adtypep = VN_CAST(dtypep, PackArrayDType)) { - for (int index_docs = adtypep->lsb(); index_docs <= adtypep->msb(); ++index_docs) { + for (int index_docs = adtypep->lo(); index_docs <= adtypep->hi(); ++index_docs) { AstNodeDType* subtypep = adtypep->subDTypep()->skipRefp(); - int index_code = index_docs - adtypep->lsb(); + int index_code = index_docs - adtypep->lo(); ToggleEnt newent(above.m_comment + string("[") + cvtToStr(index_docs) + "]", new AstSel(varp->fileline(), above.m_varRefp->cloneTree(true), index_code * subtypep->width(), subtypep->width()), diff --git a/src/V3Coverage.h b/src/V3Coverage.h index 37ebbacd5..12c20e76a 100644 --- a/src/V3Coverage.h +++ b/src/V3Coverage.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3CoverageJoin.cpp b/src/V3CoverageJoin.cpp index aebcc1f7f..7d382d59c 100644 --- a/src/V3CoverageJoin.cpp +++ b/src/V3CoverageJoin.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3CoverageJoin.h b/src/V3CoverageJoin.h index cdf2447e5..ef1a7fc7e 100644 --- a/src/V3CoverageJoin.h +++ b/src/V3CoverageJoin.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Dead.cpp b/src/V3Dead.cpp index d9602c913..f05ac9394 100644 --- a/src/V3Dead.cpp +++ b/src/V3Dead.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -285,7 +285,7 @@ private: AstVarRef* varrefp = VN_CAST(nodep->lhsp(), VarRef); if (varrefp && !m_sideEffect && varrefp->varScopep()) { // For simplicity, we only remove post-scoping - m_assignMap.insert(make_pair(varrefp->varScopep(), nodep)); + m_assignMap.emplace(varrefp->varScopep(), nodep); checkAll(varrefp); // Must track reference to dtype() checkVarRef(varrefp); } else { // Track like any other statement @@ -330,12 +330,6 @@ private: if (nodep->isSigPublic()) return false; // Can't elim publics! if (nodep->isIO() || nodep->isClassMember()) return false; if (nodep->isTemp() && !nodep->isTrace()) return true; - if (nodep->isParam()) { - const bool overriddenForHierBlock - = m_modp && m_modp->hierBlock() && nodep->overriddenParam(); - if (!nodep->isTrace() && !overriddenForHierBlock && !v3Global.opt.xmlOnly()) - return true; - } return m_elimUserVars; // Post-Trace can kill most anything } diff --git a/src/V3Dead.h b/src/V3Dead.h index 45da1943c..c0f656dee 100644 --- a/src/V3Dead.h +++ b/src/V3Dead.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Delayed.cpp b/src/V3Delayed.cpp index 60888600e..283b30923 100644 --- a/src/V3Delayed.cpp +++ b/src/V3Delayed.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -71,9 +71,10 @@ private: // AstVarScope::user2p() -> AstActive*. Points to activity block of signal // (valid when AstVarScope::user1p is valid) // AstVarScope::user4p() -> AstAlwaysPost*. Post block for this variable - // AstVarScope::user5() -> VarUsage. Tracks delayed vs non-delayed usage + // AstVarScope::user5p() -> AstVarRef*. Last blocking or non-blocking reference // AstVar::user2() -> bool. Set true if already made warning // AstVarRef::user2() -> bool. Set true if already processed + // AstVarRef::user5() -> bool. Set true if was blocking reference // AstAlwaysPost::user2() -> ActActive*. Points to activity block of signal // (valid when AstAlwaysPost::user4p is valid) // AstAlwaysPost::user4() -> AstIf*. Last IF (__Vdlyvset__) created under this AlwaysPost @@ -86,8 +87,6 @@ private: AstUser4InUse m_inuser4; AstUser5InUse m_inuser5; - enum VarUsage : uint8_t { VU_NONE = 0, VU_DLY = 1, VU_NONDLY = 2 }; - // STATE AstActive* m_activep = nullptr; // Current activate AstCFunc* m_cfuncp = nullptr; // Current public C Function @@ -104,13 +103,28 @@ private: // METHODS VL_DEBUG_FUNC; // Declare debug() - void markVarUsage(AstVarScope* nodep, uint32_t flags) { - // UINFO(4, " MVU " << flags << " " << nodep << endl); - nodep->user5(nodep->user5() | flags); - if ((nodep->user5() & VU_DLY) && (nodep->user5() & VU_NONDLY)) { - nodep->v3warn(BLKANDNBLK, - "Unsupported: Blocked and non-blocking assignments to same variable: " - << nodep->varp()->prettyNameQ()); + void markVarUsage(AstNodeVarRef* nodep, bool blocking) { + if (blocking) nodep->user5(true); + AstVarScope* vscp = nodep->varScopep(); + // UINFO(4, " MVU " << blocking << " " << nodep << endl); + AstNode* lastrefp = vscp->user5p(); + if (!lastrefp) { + vscp->user5p(nodep); + } else { + bool last_was_blocking = lastrefp->user5(); + if (last_was_blocking != blocking) { + AstNode* nonblockingp = blocking ? nodep : lastrefp; + AstNode* blockingp = blocking ? lastrefp : nodep; + vscp->v3warn( + BLKANDNBLK, + "Unsupported: Blocked and non-blocking assignments to same variable: " + << vscp->varp()->prettyNameQ() << '\n' + << vscp->warnContextPrimary() << '\n' + << blockingp->warnOther() << "... Location of blocking assignment\n" + << blockingp->warnContextSecondary() << '\n' + << nonblockingp->warnOther() << "... Location of nonblocking assignment\n" + << nonblockingp->warnContextSecondary()); + } } } AstVarScope* createVarSc(AstVarScope* oldvarscp, const string& name, @@ -136,7 +150,7 @@ private: VFlagBitPacked(), width); } addmodp->addStmtp(varp); - m_modVarMap.insert(make_pair(make_pair(addmodp, name), varp)); + m_modVarMap.emplace(make_pair(addmodp, name), varp); } AstVarScope* varscp = new AstVarScope(oldvarscp->fileline(), oldvarscp->scopep(), varp); @@ -398,9 +412,9 @@ private: if (newlhsp) { nodep->lhsp(newlhsp); } else { - VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); + VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep); } - VL_DO_DANGLING(lhsp->deleteTree(), lhsp); + VL_DO_DANGLING(pushDeletep(lhsp), lhsp); } else { iterateChildren(nodep); } @@ -412,7 +426,7 @@ private: if (!nodep->user2Inc()) { // Not done yet if (m_inDly && nodep->access().isWriteOrRW()) { UINFO(4, "AssignDlyVar: " << nodep << endl); - markVarUsage(nodep->varScopep(), VU_DLY); + markVarUsage(nodep, true); UASSERT_OBJ(m_activep, nodep, "<= not under sensitivity block"); UASSERT_OBJ(!nodep->access().isRW(), nodep, "<= on read+write method"); if (!m_activep->hasClocked()) { @@ -458,12 +472,12 @@ private: AstVarRef* newrefp = new AstVarRef(nodep->fileline(), dlyvscp, VAccess::WRITE); newrefp->user2(true); // No reason to do it again nodep->replaceWith(newrefp); - VL_DO_DANGLING(nodep->deleteTree(), nodep); + VL_DO_DANGLING(pushDeletep(nodep), nodep); } else if (!m_inDly && nodep->access().isWriteOrRW()) { // UINFO(9, "NBA " << nodep << endl); if (!m_inInitial) { UINFO(4, "AssignNDlyVar: " << nodep << endl); - markVarUsage(nodep->varScopep(), VU_NONDLY); + markVarUsage(nodep, false); } } } diff --git a/src/V3Delayed.h b/src/V3Delayed.h index eaa1e2650..4e8080bb5 100644 --- a/src/V3Delayed.h +++ b/src/V3Delayed.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Depth.cpp b/src/V3Depth.cpp index 6cc0bc5d7..4f8be0f75 100644 --- a/src/V3Depth.cpp +++ b/src/V3Depth.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -114,11 +114,12 @@ private: virtual void visit(AstNodeTermop* nodep) override {} virtual void visit(AstNodeMath* nodep) override { // We have some operator defines that use 2 parens, so += 2. - m_depth += 2; - if (m_depth > m_maxdepth) m_maxdepth = m_depth; - iterateChildren(nodep); - m_depth -= 2; - + { + VL_RESTORER(m_depth); + m_depth += 2; + if (m_depth > m_maxdepth) m_maxdepth = m_depth; + iterateChildren(nodep); + } if (m_stmtp && (v3Global.opt.compLimitParens() >= 1) // Else compiler doesn't need it && (m_maxdepth - m_depth) > v3Global.opt.compLimitParens() && !VN_IS(nodep->backp(), NodeStmt) // Not much point if we're about to use it diff --git a/src/V3Depth.h b/src/V3Depth.h index 9e1e4834f..355848da3 100644 --- a/src/V3Depth.h +++ b/src/V3Depth.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3DepthBlock.cpp b/src/V3DepthBlock.cpp index 19a3a0604..36924db42 100644 --- a/src/V3DepthBlock.cpp +++ b/src/V3DepthBlock.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3DepthBlock.h b/src/V3DepthBlock.h index 7233cd320..964c91234 100644 --- a/src/V3DepthBlock.h +++ b/src/V3DepthBlock.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Descope.cpp b/src/V3Descope.cpp index a23413e8c..237da3a1c 100644 --- a/src/V3Descope.cpp +++ b/src/V3Descope.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -123,7 +123,7 @@ private: hierUnprot = v3Global.opt.modPrefix() + "_"; // Prefix before protected part return scopep->modp()->name() + "::"; } else if (relativeRefOk && scopep->aboveScopep() && scopep->aboveScopep() == m_scopep) { - // Reference to scope of cell directly under this module, can just "cell->" + // Reference to scope of instance directly under this module, can just "cell->" string name = scopep->name(); string::size_type pos; if ((pos = name.rfind('.')) != string::npos) name.erase(0, pos + 1); @@ -296,7 +296,7 @@ private: if (nodep->funcPublic()) { // There may be multiple public functions by the same name; // record for later correction or making of shells - m_modFuncs.insert(make_pair(nodep->name(), nodep)); + m_modFuncs.emplace(nodep->name(), nodep); nodep->name(m_scopep->nameDotless() + "__" + nodep->name()); } } diff --git a/src/V3Descope.h b/src/V3Descope.h index 04093afd6..07896ce16 100644 --- a/src/V3Descope.h +++ b/src/V3Descope.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3EmitC.cpp b/src/V3EmitC.cpp index db5a803f5..95cb52af0 100644 --- a/src/V3EmitC.cpp +++ b/src/V3EmitC.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -166,8 +166,8 @@ public: sectionr = ""; } UASSERT_OBJ(varp->valuep(), nodep, "No init for a param?"); - // These should be static const values, however microsloth VC++ doesn't - // support them. They also cause problems with GDB under GCC2.95. + // These should be static const values, however older MSVC++ did't + // support them; should be ok now under C++11, need to refactor. if (varp->isWide()) { // Unsupported for output if (!init) { putsDecoration("// enum WData " + varp->nameProtect() + " //wide"); @@ -576,9 +576,9 @@ public: emitIQW(nodep->outp()); puts("("); puts(cvtToStr(nodep->outp()->widthMin())); - puts(","); + puts(", "); emitCvtPackStr(nodep->searchp()); - puts(","); + puts(", "); putbs(""); iterateAndNextNull(nodep->outp()); puts(")"); @@ -631,7 +631,7 @@ public: putbs(", "); // Need real storage width puts(cvtToStr(nodep->memp()->dtypep()->subDTypep()->widthMin())); - uint32_t array_lsb = 0; + uint32_t array_lo = 0; { const AstVarRef* varrefp = VN_CAST(nodep->memp(), VarRef); if (!varrefp) { @@ -642,9 +642,9 @@ public: = VN_CAST(varrefp->varp()->dtypeSkipRefp(), UnpackArrayDType)) { putbs(", "); puts(cvtToStr(varrefp->varp()->dtypep()->arrayUnpackedElements())); - array_lsb = adtypep->lsb(); + array_lo = adtypep->lo(); putbs(", "); - puts(cvtToStr(array_lsb)); + puts(cvtToStr(array_lo)); } else { nodep->v3error(nodep->verilogKwd() << " loading other than unpacked/associative-array variable"); @@ -658,7 +658,7 @@ public: if (nodep->lsbp()) { iterateAndNextNull(nodep->lsbp()); } else { - puts(cvtToStr(array_lsb)); + puts(cvtToStr(array_lo)); } putbs(", "); if (nodep->msbp()) { @@ -710,7 +710,7 @@ public: puts(cvtToStr(nodep->memp()->widthMin())); // Need real storage width putbs(","); bool memory = false; - uint32_t array_lsb = 0; + uint32_t array_lo = 0; uint32_t array_size = 0; { const AstVarRef* varrefp = VN_CAST(nodep->memp(), VarRef); @@ -720,14 +720,14 @@ public: } else if (const AstUnpackArrayDType* adtypep = VN_CAST(varrefp->varp()->dtypeSkipRefp(), UnpackArrayDType)) { memory = true; - array_lsb = adtypep->lsb(); + array_lo = adtypep->lo(); array_size = adtypep->elementsConst(); } else { nodep->v3error(nodep->verilogKwd() << " loading other than unpacked-array variable"); } } - puts(cvtToStr(array_lsb)); + puts(cvtToStr(array_lo)); putbs(","); puts(cvtToStr(array_size)); putbs(", "); @@ -740,7 +740,7 @@ public: if (nodep->startp()) { iterateAndNextNull(nodep->startp()); } else { - puts(cvtToStr(array_lsb)); + puts(cvtToStr(array_lo)); } putbs(", "); if (nodep->countp()) { @@ -818,6 +818,15 @@ public: } puts("}\n"); } + virtual void visit(AstExprStmt* nodep) override { + // GCC allows compound statements in expressions, but this is not standard. + // So we use an immediate-evaluation lambda and comma operator + putbs("([&]() {\n"); + iterateAndNextNull(nodep->stmtsp()); + puts("}(), "); + iterateAndNextNull(nodep->resultp()); + puts(")"); + } virtual void visit(AstStop* nodep) override { puts("VL_STOP_MT("); putsQuoted(protect(nodep->fileline()->filename())); @@ -1061,6 +1070,13 @@ public: emitOpName(nodep, "VL_STREAML_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)", nodep->lhsp(), nodep->rhsp(), nullptr); } + virtual void visit(AstCastDynamic* nodep) override { + putbs("VL_CAST_DYNAMIC("); + iterateAndNextNull(nodep->lhsp()); + puts(", "); + iterateAndNextNull(nodep->rhsp()); + puts(")"); + } virtual void visit(AstCountBits* nodep) override { putbs("VL_COUNTBITS_"); emitIQW(nodep->lhsp()); @@ -1773,7 +1789,7 @@ class EmitCImp final : EmitCStmts { return emitVarResetRecurse(varp, adtypep->subDTypep(), depth + 1, ".atDefault()" + cvtarray); } else if (AstUnpackArrayDType* adtypep = VN_CAST(dtypep, UnpackArrayDType)) { - UASSERT_OBJ(adtypep->msb() >= adtypep->lsb(), varp, + UASSERT_OBJ(adtypep->hi() >= adtypep->lo(), varp, "Should have swapped msb & lsb earlier."); string ivar = string("__Vi") + cvtToStr(depth); string pre = ("for (int " + ivar + "=" + cvtToStr(0) + "; " + ivar + "<" @@ -1905,7 +1921,7 @@ void EmitCStmts::emitVarDecl(const AstVar* nodep, const string& prefixIfImp) { emitDeclArrayBrackets(nodep); // If it's a packed struct/array then nodep->width is the whole // thing, msb/lsb is just lowest dimension - puts("," + cvtToStr(basicp->lsb() + nodep->width() - 1) + "," + cvtToStr(basicp->lsb())); + puts("," + cvtToStr(basicp->lo() + nodep->width() - 1) + "," + cvtToStr(basicp->lo())); if (nodep->isWide()) puts("," + cvtToStr(nodep->widthWords())); puts(");\n"); } else { @@ -2584,7 +2600,7 @@ void EmitCImp::emitSavableImp(AstNodeModule* modp) { for (AstUnpackArrayDType* arrayp = VN_CAST(elementp, UnpackArrayDType); arrayp; arrayp = VN_CAST(elementp, UnpackArrayDType)) { int vecnum = vects++; - UASSERT_OBJ(arrayp->msb() >= arrayp->lsb(), varp, + UASSERT_OBJ(arrayp->hi() >= arrayp->lo(), varp, "Should have swapped msb & lsb earlier."); string ivar = string("__Vi") + cvtToStr(vecnum); puts("for (int __Vi" + cvtToStr(vecnum) + "=" + cvtToStr(0)); @@ -2671,11 +2687,11 @@ void EmitCImp::emitSensitives() { arrayp; arrayp = VN_CAST(arrayp->subDTypep()->skipRefp(), UnpackArrayDType)) { int vecnum = vects++; - UASSERT_OBJ(arrayp->msb() >= arrayp->lsb(), varp, + UASSERT_OBJ(arrayp->hi() >= arrayp->lo(), varp, "Should have swapped msb & lsb earlier."); string ivar = string("__Vi") + cvtToStr(vecnum); - puts("for (int __Vi" + cvtToStr(vecnum) + "=" + cvtToStr(arrayp->lsb())); - puts("; " + ivar + "<=" + cvtToStr(arrayp->msb())); + puts("for (int __Vi" + cvtToStr(vecnum) + "=" + cvtToStr(arrayp->lo())); + puts("; " + ivar + "<=" + cvtToStr(arrayp->hi())); puts("; ++" + ivar + ") {\n"); } puts("sensitive << " + varp->nameProtect()); diff --git a/src/V3EmitC.h b/src/V3EmitC.h index e89b8f89a..fb75a1626 100644 --- a/src/V3EmitC.h +++ b/src/V3EmitC.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3EmitCBase.h b/src/V3EmitCBase.h index 731b8356e..cc75859f9 100644 --- a/src/V3EmitCBase.h +++ b/src/V3EmitCBase.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3EmitCInlines.cpp b/src/V3EmitCInlines.cpp index df7d20c88..0fd7450d9 100644 --- a/src/V3EmitCInlines.cpp +++ b/src/V3EmitCInlines.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3EmitCMain.cpp b/src/V3EmitCMain.cpp index f23cc7668..63e9abea6 100644 --- a/src/V3EmitCMain.cpp +++ b/src/V3EmitCMain.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3EmitCMain.h b/src/V3EmitCMain.h index c17449f50..d5232baaa 100644 --- a/src/V3EmitCMain.h +++ b/src/V3EmitCMain.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3EmitCMake.cpp b/src/V3EmitCMake.cpp index 4844f5ad6..ebf8c07c9 100644 --- a/src/V3EmitCMake.cpp +++ b/src/V3EmitCMake.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2004-2020 by Wilson Snyder. This program is free software; you +// Copyright 2004-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3EmitCMake.h b/src/V3EmitCMake.h index 144a22925..3401887f4 100644 --- a/src/V3EmitCMake.h +++ b/src/V3EmitCMake.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3EmitCSyms.cpp b/src/V3EmitCSyms.cpp index 168437852..d6392ef64 100644 --- a/src/V3EmitCSyms.cpp +++ b/src/V3EmitCSyms.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -116,6 +116,7 @@ class EmitCSyms final : EmitCBaseVisitor { void checkSplit(bool usesVfinal); void closeSplit(); void emitSymImpPreamble(); + void emitScopeHier(bool destroy); void emitSymImp(); void emitDpiHdr(); void emitDpiImp(); @@ -171,7 +172,7 @@ class EmitCSyms final : EmitCBaseVisitor { const auto scpit = m_vpiScopeCandidates.find(scp); if ((scpit != m_vpiScopeCandidates.end()) && (m_scopeNames.find(scp) == m_scopeNames.end())) { - m_scopeNames.insert(make_pair(scpit->second.m_symName, scpit->second)); + m_scopeNames.emplace(scpit->second.m_symName, scpit->second); } string::size_type pos = scp.rfind("__DOT__"); if (pos == string::npos) { @@ -312,8 +313,8 @@ class EmitCSyms final : EmitCBaseVisitor { // <<" ss"<timeunit().powerOfTen() : 0; if (m_scopeNames.find(name) == m_scopeNames.end()) { - m_scopeNames.insert(make_pair( - name, ScopeData(name, nodep->scopePrettySymName(), timeunit, "SCOPE_OTHER"))); + m_scopeNames.emplace( + name, ScopeData(name, nodep->scopePrettySymName(), timeunit, "SCOPE_OTHER")); } if (nodep->dpiExport()) { UASSERT_OBJ(m_cfuncp, nodep, "ScopeName not under DPI function"); @@ -467,7 +468,7 @@ void EmitCSyms::emitSymHdr() { puts("\n// CREATORS\n"); puts(symClassName() + "(" + topClassName() + "* topp, const char* namep);\n"); - puts(string("~") + symClassName() + "() = default;\n"); + puts(string("~") + symClassName() + "();\n"); for (const auto& i : m_usesVfinal) { puts("void " + symClassName() + "_" + cvtToStr(i.first) + "("); @@ -555,6 +556,40 @@ void EmitCSyms::emitSymImpPreamble() { } } +void EmitCSyms::emitScopeHier(bool destroy) { + if (v3Global.opt.vpi()) { + string verb = destroy ? "Tear down" : "Set up"; + string method = destroy ? "remove" : "add"; + puts("\n// " + verb + " scope hierarchy\n"); + for (ScopeNames::const_iterator it = m_scopeNames.begin(); it != m_scopeNames.end(); + ++it) { + string name = it->second.m_prettyName; + if (it->first == "TOP") continue; + if ((name.find('.') == string::npos) && (it->second.m_type == "SCOPE_MODULE")) { + puts("__Vhier." + method + "(0, &" + protect("__Vscope_" + it->second.m_symName) + + ");\n"); + } + } + + for (ScopeNameHierarchy::const_iterator it = m_vpiScopeHierarchy.begin(); + it != m_vpiScopeHierarchy.end(); ++it) { + for (ScopeNameList::const_iterator lit = it->second.begin(); lit != it->second.end(); + ++lit) { + string fromname = scopeSymString(it->first); + string toname = scopeSymString(*lit); + const auto from = vlstd::as_const(m_scopeNames).find(fromname); + const auto to = vlstd::as_const(m_scopeNames).find(toname); + UASSERT(from != m_scopeNames.end(), fromname + " not in m_scopeNames"); + UASSERT(to != m_scopeNames.end(), toname + " not in m_scopeNames"); + puts("__Vhier." + method + "("); + puts("&" + protect("__Vscope_" + from->second.m_symName) + ", "); + puts("&" + protect("__Vscope_" + to->second.m_symName) + ");\n"); + } + } + puts("\n"); + } +} + void EmitCSyms::emitSymImp() { UINFO(6, __FUNCTION__ << ": " << endl); string filename = v3Global.opt.makeDir() + "/" + symClassName() + ".cpp"; @@ -604,6 +639,10 @@ void EmitCSyms::emitSymImp() { puts("\n"); puts("\n// FUNCTIONS\n"); + puts(symClassName() + "::~" + symClassName() + "()\n"); + puts("{\n"); + emitScopeHier(true); + puts("}\n\n"); puts(symClassName() + "::" + symClassName() + "(" + topClassName() + "* topp, const char* namep)\n"); puts(" // Setup locals\n"); @@ -685,35 +724,7 @@ void EmitCSyms::emitSymImp() { } } - if (v3Global.opt.vpi()) { - puts("\n// Setup scope hierarchy\n"); - for (ScopeNames::const_iterator it = m_scopeNames.begin(); it != m_scopeNames.end(); - ++it) { - string name = it->second.m_prettyName; - if (it->first == "TOP") continue; - name = name.replace(0, 4, ""); // Remove the "TOP." - if ((name.find('.') == string::npos) && (it->second.m_type == "SCOPE_MODULE")) { - puts("__Vhier.add(0, &" + protect("__Vscope_" + it->second.m_symName) + ");\n"); - } - } - - for (ScopeNameHierarchy::const_iterator it = m_vpiScopeHierarchy.begin(); - it != m_vpiScopeHierarchy.end(); ++it) { - for (ScopeNameList::const_iterator lit = it->second.begin(); lit != it->second.end(); - ++lit) { - string fromname = scopeSymString(it->first); - string toname = scopeSymString(*lit); - const auto from = vlstd::as_const(m_scopeNames).find(fromname); - const auto to = vlstd::as_const(m_scopeNames).find(toname); - UASSERT(from != m_scopeNames.end(), fromname + " not in m_scopeNames"); - UASSERT(to != m_scopeNames.end(), toname + " not in m_scopeNames"); - puts("__Vhier.add("); - puts("&" + protect("__Vscope_" + from->second.m_symName) + ", "); - puts("&" + protect("__Vscope_" + to->second.m_symName) + ");\n"); - } - } - puts("\n"); - } + emitScopeHier(false); // Everything past here is in the __Vfinal loop, so start a new split file if needed closeSplit(); @@ -752,9 +763,9 @@ void EmitCSyms::emitSymImp() { // Range is always first, it's not in "C" order if (basicp->isRanged()) { bounds += " ,"; - bounds += cvtToStr(basicp->msb()); + bounds += cvtToStr(basicp->hi()); bounds += ","; - bounds += cvtToStr(basicp->lsb()); + bounds += cvtToStr(basicp->lo()); pdim++; } for (AstNodeDType* dtypep = varp->dtypep(); dtypep;) { @@ -762,9 +773,9 @@ void EmitCSyms::emitSymImp() { = dtypep->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node if (const AstNodeArrayDType* adtypep = VN_CAST(dtypep, NodeArrayDType)) { bounds += " ,"; - bounds += cvtToStr(adtypep->msb()); + bounds += cvtToStr(adtypep->left()); bounds += ","; - bounds += cvtToStr(adtypep->lsb()); + bounds += cvtToStr(adtypep->right()); if (VN_IS(dtypep, PackArrayDType)) { pdim++; } else { @@ -861,12 +872,14 @@ void EmitCSyms::emitDpiHdr() { for (AstCFunc* nodep : m_dpis) { if (nodep->dpiExportWrapper()) { if (!firstExp++) puts("\n// DPI EXPORTS\n"); - puts("// DPI export" + ifNoProtect(" at " + nodep->fileline()->ascii()) + "\n"); + putsDecoration("// DPI export" + ifNoProtect(" at " + nodep->fileline()->ascii()) + + "\n"); puts("extern " + nodep->rtnTypeVoid() + " " + nodep->nameProtect() + "(" + cFuncArgs(nodep) + ");\n"); } else if (nodep->dpiImport()) { if (!firstImp++) puts("\n// DPI IMPORTS\n"); - puts("// DPI import" + ifNoProtect(" at " + nodep->fileline()->ascii()) + "\n"); + putsDecoration("// DPI import" + ifNoProtect(" at " + nodep->fileline()->ascii()) + + "\n"); puts("extern " + nodep->rtnTypeVoid() + " " + nodep->nameProtect() + "(" + cFuncArgs(nodep) + ");\n"); } diff --git a/src/V3EmitMk.cpp b/src/V3EmitMk.cpp index cf50f1ea2..8464de0eb 100644 --- a/src/V3EmitMk.cpp +++ b/src/V3EmitMk.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2004-2020 by Wilson Snyder. This program is free software; you +// Copyright 2004-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -311,9 +311,6 @@ class EmitMkHierVerilation final { } of.puts("\n"); } - void emitOpts(V3OutMkFile& of, const V3StringList& opts) const { - for (const string& i : opts) { of.puts("\t\t" + i + " \\\n"); } - } void emitLaunchVerilator(V3OutMkFile& of, const string& argsFile) const { of.puts("\t@$(MAKE) -C $(VM_HIER_RUN_DIR) -f " + m_makefile + " hier_launch_verilator \\\n"); @@ -420,5 +417,5 @@ void V3EmitMk::emitmk() { void V3EmitMk::emitHierVerilation(const V3HierBlockPlan* planp) { UINFO(2, __FUNCTION__ << ": " << endl); - EmitMkHierVerilation emitter(planp); + EmitMkHierVerilation{planp}; } diff --git a/src/V3EmitMk.h b/src/V3EmitMk.h index bb329c3bd..c9208059d 100644 --- a/src/V3EmitMk.h +++ b/src/V3EmitMk.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3EmitV.cpp b/src/V3EmitV.cpp index 664f6ddbd..026d48d16 100644 --- a/src/V3EmitV.cpp +++ b/src/V3EmitV.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2004-2020 by Wilson Snyder. This program is free software; you +// Copyright 2004-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -513,11 +513,11 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor { } virtual void visit(AstRange* nodep) override { puts("["); - if (VN_IS(nodep->msbp(), Const) && VN_IS(nodep->lsbp(), Const)) { + if (VN_IS(nodep->leftp(), Const) && VN_IS(nodep->rightp(), Const)) { // Looks nicer if we print [1:0] rather than [32'sh1:32sh0] - puts(cvtToStr(VN_CAST(nodep->leftp(), Const)->toSInt())); + puts(cvtToStr(nodep->leftConst())); puts(":"); - puts(cvtToStr(VN_CAST(nodep->rightp(), Const)->toSInt())); + puts(cvtToStr(nodep->rightConst())); puts("]"); } else { iterateAndNextNull(nodep->leftp()); @@ -570,7 +570,7 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor { puts(" "); } else if (nodep->isRanged()) { puts(" ["); - puts(cvtToStr(nodep->msb())); + puts(cvtToStr(nodep->hi())); puts(":0] "); } } @@ -608,6 +608,11 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor { puts(")"); } virtual void visit(AstArg* nodep) override { iterateAndNextNull(nodep->exprp()); } + virtual void visit(AstPrintTimeScale* nodep) override { + puts(nodep->verilogKwd()); + puts(";\n"); + } + // Terminals virtual void visit(AstVarRef* nodep) override { if (nodep->varScopep()) { @@ -629,11 +634,31 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor { virtual void visit(AstTopScope* nodep) override { iterateChildren(nodep); } virtual void visit(AstScope* nodep) override { iterateChildren(nodep); } virtual void visit(AstVar* nodep) override { - putfs(nodep, nodep->verilogKwd()); - puts(" "); - iterate(nodep->dtypep()); - puts(" "); - puts(nodep->prettyName()); + if (nodep->isIO()) { + putfs(nodep, nodep->verilogKwd()); + puts(" "); + } + std::vector unpackps; + for (AstNodeDType* dtypep = nodep->dtypep(); dtypep;) { + dtypep = dtypep->skipRefp(); + if (AstUnpackArrayDType* unpackp = VN_CAST(dtypep, UnpackArrayDType)) { + unpackps.push_back(unpackp); + dtypep = unpackp->subDTypep(); + } else { + iterate(dtypep); + puts(" "); + puts(nodep->prettyName()); + dtypep = nullptr; + } + } + // If nodep is an unpacked array, append unpacked dimensions + for (const auto& unpackp : unpackps) { + puts("["); + puts(cvtToStr(unpackp->rangep()->leftConst())); + puts(":"); + puts(cvtToStr(unpackp->rangep()->rightConst())); + puts("]"); + } if (!m_suppressVarSemi) { puts(";\n"); } else { diff --git a/src/V3EmitV.h b/src/V3EmitV.h index 98f8b3cbb..17cb790ad 100644 --- a/src/V3EmitV.h +++ b/src/V3EmitV.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3EmitXml.cpp b/src/V3EmitXml.cpp index b39a30f43..27770caa5 100644 --- a/src/V3EmitXml.cpp +++ b/src/V3EmitXml.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2004-2020 by Wilson Snyder. This program is free software; you +// Copyright 2004-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -151,6 +151,7 @@ class EmitXmlFileVisitor final : public AstNVisitor { } if (nodep->attrClockEn()) puts(" clock_enable=\"true\""); if (nodep->attrIsolateAssign()) puts(" isolate_assignments=\"true\""); + if (nodep->isLatched()) puts(" latched=\"true\""); if (nodep->isSigPublic()) puts(" public=\"true\""); if (nodep->isSigUserRdPublic()) puts(" public_flat_rd=\"true\""); if (nodep->isSigUserRWPublic()) puts(" public_flat_rw=\"true\""); diff --git a/src/V3EmitXml.h b/src/V3EmitXml.h index 18555891f..e1b790736 100644 --- a/src/V3EmitXml.h +++ b/src/V3EmitXml.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Error.cpp b/src/V3Error.cpp index e8f8c6e18..95a34a7f0 100644 --- a/src/V3Error.cpp +++ b/src/V3Error.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Error.h b/src/V3Error.h index 5e88ba6c2..9f3b8daee 100644 --- a/src/V3Error.h +++ b/src/V3Error.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -71,6 +71,7 @@ public: CASEOVERLAP, // Case statements overlap CASEWITHX, // Case with X values CASEX, // Casex + CASTCONST, // Cast is constant CDCRSTLOGIC, // Logic in async reset path CLKDATA, // Clock used as data CMPCONST, // Comparison is constant due to limited range @@ -93,15 +94,18 @@ public: INFINITELOOP, // Infinite loop INITIALDLY, // Initial delayed statement INSECURE, // Insecure options + LATCH, // Latch detected outside of always_latch block LITENDIAN, // Little bit endian vector MODDUP, // Duplicate module MULTIDRIVEN, // Driven from multiple blocks MULTITOP, // Multiple top level modules + NOLATCH, // No latch detected in always_latch block PINMISSING, // Cell pin not specified PINNOCONNECT, // Cell pin not connected PINCONNECTEMPTY,// Cell pin connected by name with empty reference PKGNODECL, // Error: Package/class needs to be predeclared PROCASSWIRE, // Procedural assignment on wire + RANDC, // Unsupported: 'randc' converted to 'rand' REALCVT, // Real conversion REDEFMACRO, // Redefining existing define macro SELRANGE, // Selection index out of range @@ -153,17 +157,17 @@ public: " EC_FIRST_WARN", "ALWCOMBORDER", "ASSIGNDLY", "ASSIGNIN", "BLKANDNBLK", "BLKLOOPINIT", "BLKSEQ", "BSSPACE", - "CASEINCOMPLETE", "CASEOVERLAP", "CASEWITHX", "CASEX", "CDCRSTLOGIC", "CLKDATA", + "CASEINCOMPLETE", "CASEOVERLAP", "CASEWITHX", "CASEX", "CASTCONST", "CDCRSTLOGIC", "CLKDATA", "CMPCONST", "COLONPLUS", "COMBDLY", "CONTASSREG", "DEFPARAM", "DECLFILENAME", "DEPRECATED", "ENDLABEL", "GENCLK", "HIERBLOCK", "IFDEPTH", "IGNOREDRETURN", "IMPERFECTSCH", "IMPLICIT", "IMPORTSTAR", "IMPURE", "INCABSPATH", "INFINITELOOP", "INITIALDLY", "INSECURE", - "LITENDIAN", "MODDUP", - "MULTIDRIVEN", "MULTITOP", + "LATCH", "LITENDIAN", "MODDUP", + "MULTIDRIVEN", "MULTITOP","NOLATCH", "PINMISSING", "PINNOCONNECT", "PINCONNECTEMPTY", "PKGNODECL", "PROCASSWIRE", - "REALCVT", "REDEFMACRO", + "RANDC", "REALCVT", "REDEFMACRO", "SELRANGE", "SHORTREAL", "SPLITVAR", "STMTDLY", "SYMRSVDWORD", "SYNCASYNCNET", "TICKCOUNT", "TIMESCALEMOD", "UNDRIVEN", "UNOPT", "UNOPTFLAT", "UNOPTTHREADS", @@ -195,9 +199,10 @@ public: // Warnings that are lint only bool lintError() const { return (m_e == ALWCOMBORDER || m_e == BSSPACE || m_e == CASEINCOMPLETE - || m_e == CASEOVERLAP || m_e == CASEWITHX || m_e == CASEX || m_e == CMPCONST - || m_e == COLONPLUS || m_e == ENDLABEL || m_e == IMPLICIT || m_e == LITENDIAN - || m_e == PINMISSING || m_e == REALCVT || m_e == UNSIGNED || m_e == WIDTH); + || m_e == CASEOVERLAP || m_e == CASEWITHX || m_e == CASEX || m_e == CASTCONST + || m_e == CMPCONST || m_e == COLONPLUS || m_e == ENDLABEL || m_e == IMPLICIT + || m_e == LATCH || m_e == LITENDIAN || m_e == PINMISSING || m_e == REALCVT + || m_e == UNSIGNED || m_e == WIDTH); } // Warnings that are style only bool styleError() const { diff --git a/src/V3Expand.cpp b/src/V3Expand.cpp index f594434b2..541069ee4 100644 --- a/src/V3Expand.cpp +++ b/src/V3Expand.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2004-2020 by Wilson Snyder. This program is free software; you +// Copyright 2004-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -270,15 +270,6 @@ private: } return true; } - bool expandWide(AstNodeAssign* nodep, AstXnor* rhsp) { - UINFO(8, " Wordize ASSIGN(XNOR) " << nodep << endl); - for (int w = 0; w < nodep->widthWords(); w++) { - addWordAssign(nodep, w, - new AstXnor(nodep->fileline(), newAstWordSelClone(rhsp->lhsp(), w), - newAstWordSelClone(rhsp->rhsp(), w))); - } - return true; - } //-------- Triops bool expandWide(AstNodeAssign* nodep, AstNodeCond* rhsp) { UINFO(8, " Wordize ASSIGN(COND) " << nodep << endl); @@ -859,8 +850,6 @@ private: did = expandWide(nodep, rhsp); } else if (AstXor* rhsp = VN_CAST(nodep->rhsp(), Xor)) { did = expandWide(nodep, rhsp); - } else if (AstXnor* rhsp = VN_CAST(nodep->rhsp(), Xnor)) { - did = expandWide(nodep, rhsp); } else if (AstNodeCond* rhsp = VN_CAST(nodep->rhsp(), NodeCond)) { did = expandWide(nodep, rhsp); } diff --git a/src/V3Expand.h b/src/V3Expand.h index 7080ecbcd..d405479fa 100644 --- a/src/V3Expand.h +++ b/src/V3Expand.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3File.cpp b/src/V3File.cpp index 66f82abbb..d04a70b8e 100644 --- a/src/V3File.cpp +++ b/src/V3File.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -580,16 +580,16 @@ protected: // Cache small files (only to save space) // It's quite common to `include "timescale" thousands of times // This isn't so important if it's just an open(), but filtering can be slow - m_contentsMap.insert(make_pair(filename, listString(outl))); + m_contentsMap.emplace(filename, listString(outl)); } return true; } - static size_t listSize(StrList& sl) { + static size_t listSize(const StrList& sl) { size_t out = 0; for (const string& i : sl) out += i.length(); return out; } - static string listString(StrList& sl) { + static string listString(const StrList& sl) { string out; for (const string& i : sl) out += i; return out; @@ -980,7 +980,7 @@ public: UASSERT(old == it->second, "Passthru request for '" + old + "' after already --protect-ids of it."); } else { - m_nameMap.insert(make_pair(old, old)); + m_nameMap.emplace(old, old); m_newIdSet.insert(old); } return old; @@ -1011,7 +1011,7 @@ public: } } } - m_nameMap.insert(make_pair(old, out)); + m_nameMap.emplace(old, out); m_newIdSet.insert(out); return out; } diff --git a/src/V3File.h b/src/V3File.h index c4a176150..c94404224 100644 --- a/src/V3File.h +++ b/src/V3File.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3FileLine.cpp b/src/V3FileLine.cpp index a68d2348d..aabcea844 100644 --- a/src/V3FileLine.cpp +++ b/src/V3FileLine.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -63,7 +63,7 @@ int FileLineSingleton::nameToNumber(const string& filename) { int num = m_names.size(); m_names.push_back(filename); m_languages.push_back(V3LangCode::mostRecent()); - m_namemap.insert(make_pair(filename, num)); + m_namemap.emplace(filename, num); return num; } diff --git a/src/V3FileLine.h b/src/V3FileLine.h index 0e992d311..bbc0c2de2 100644 --- a/src/V3FileLine.h +++ b/src/V3FileLine.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Gate.cpp b/src/V3Gate.cpp index c14bb648d..e03443083 100644 --- a/src/V3Gate.cpp +++ b/src/V3Gate.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Gate.h b/src/V3Gate.h index 18ab97f16..1cc55cc9b 100644 --- a/src/V3Gate.h +++ b/src/V3Gate.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3GenClk.cpp b/src/V3GenClk.cpp index b8acc7430..dc6dc2ec9 100644 --- a/src/V3GenClk.cpp +++ b/src/V3GenClk.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3GenClk.h b/src/V3GenClk.h index 850f0cec0..031f76b3c 100644 --- a/src/V3GenClk.h +++ b/src/V3GenClk.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Global.cpp b/src/V3Global.cpp index bfdfc1311..73115a7b3 100644 --- a/src/V3Global.cpp +++ b/src/V3Global.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2004-2020 by Wilson Snyder. This program is free software; you +// Copyright 2004-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Global.h b/src/V3Global.h index f9fff4eb6..a8da68308 100644 --- a/src/V3Global.h +++ b/src/V3Global.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -52,7 +52,7 @@ template class VRestorer { const T m_saved; // Value saved, for later restore public: - VRestorer(T& permr) + explicit VRestorer(T& permr) : m_ref(permr) , m_saved(permr) {} ~VRestorer() { m_ref = m_saved; } @@ -97,10 +97,12 @@ class V3Global final { bool m_assertDTypesResolved = false; // Tree should have dtypep()'s bool m_assertScoped = false; // Tree is scoped bool m_constRemoveXs = false; // Const needs to strip any Xs - bool m_needHeavy = false; // Need verilated_heavy.h include + // Experimenting with always requiring heavy, see (#2701) + bool m_needHeavy = true; // Need verilated_heavy.h include bool m_needTraceDumper = false; // Need __Vm_dumperp in symbols bool m_dpi = false; // Need __Dpi include files bool m_useParallelBuild = false; // Use parallel build for model + bool m_useRandomizeMethods = false; // Need to define randomize() class methods // Memory address to short string mapping (for debug) typedef std::unordered_map PtrToIdMap; // The map type @@ -158,6 +160,8 @@ public: } void useParallelBuild(bool flag) { m_useParallelBuild = flag; } bool useParallelBuild() const { return m_useParallelBuild; } + void useRandomizeMethods(bool flag) { m_useRandomizeMethods = flag; } + bool useRandomizeMethods() const { return m_useRandomizeMethods; } const std::string& ptrToId(const void* p); }; diff --git a/src/V3Graph.cpp b/src/V3Graph.cpp index 518c1ce70..76ab948b1 100644 --- a/src/V3Graph.cpp +++ b/src/V3Graph.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -330,7 +330,7 @@ void V3Graph::dumpDotFile(const string& filename, bool colorAsSubgraph) const { for (V3GraphVertex* vertexp = verticesBeginp(); vertexp; vertexp = vertexp->verticesNextp()) { string vertexSubgraph = (colorAsSubgraph && vertexp->color()) ? cvtToStr(vertexp->color()) : ""; - subgraphs.insert(make_pair(vertexSubgraph, vertexp)); + subgraphs.emplace(vertexSubgraph, vertexp); } // We use a map here, as we don't want to corrupt anything (userp) in the graph, diff --git a/src/V3Graph.h b/src/V3Graph.h index 4ac788646..a12ce811f 100644 --- a/src/V3Graph.h +++ b/src/V3Graph.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -145,12 +145,6 @@ public: /// Make acyclical (into a tree) by breaking a minimal subset of cutable edges. void acyclic(V3EdgeFuncP edgeFuncp); - /// Delete any nodes with only outputs - void deleteCutableOnlyEdges(); - - /// Any cutable edges become non-cutable - void makeEdgesNonCutable(V3EdgeFuncP edgeFuncp); - /// Remove any redundant edges, weights become MAX of any other weight void removeRedundantEdges(V3EdgeFuncP edgeFuncp); diff --git a/src/V3GraphAcyc.cpp b/src/V3GraphAcyc.cpp index 858e4c22d..f18a432f7 100644 --- a/src/V3GraphAcyc.cpp +++ b/src/V3GraphAcyc.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3GraphAlg.cpp b/src/V3GraphAlg.cpp index e0046bd21..7cc32dd55 100644 --- a/src/V3GraphAlg.cpp +++ b/src/V3GraphAlg.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -26,45 +26,6 @@ #include #include -//###################################################################### -//###################################################################### -// Algorithms - delete - -void V3Graph::deleteCutableOnlyEdges() { - // Any vertices with only cutable edges will get deleted - - // Vertex::m_user begin: indicates can be deleted - // Pass 1, mark those. Don't delete now, as we don't want to rip out whole trees - for (V3GraphVertex* vertexp = verticesBeginp(); vertexp; vertexp = vertexp->verticesNextp()) { - vertexp->user(true); - for (V3GraphEdge* edgep = vertexp->inBeginp(); edgep; edgep = edgep->inNextp()) { - if (!edgep->cutable()) { - vertexp->user(false); // Can't delete it - break; - } - } - for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep = edgep->outNextp()) { - if (!edgep->cutable()) { - vertexp->user(false); // Can't delete it - break; - } - } - } - - // Pass 2, delete those marked - // Rather than doing a delete() we set the weight to 0 which disconnects the edge. - for (V3GraphVertex* vertexp = verticesBeginp(); vertexp; vertexp = vertexp->verticesNextp()) { - if (vertexp->user()) { - // UINFO(7, "Disconnect " << vertexp->name() << endl); - for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep = edgep->outNextp()) { - edgep->cut(); - } - } - } - - // Vertex::m_user end, now unused -} - //###################################################################### //###################################################################### // Algorithms - weakly connected components @@ -321,7 +282,7 @@ private: if (vertexp->user() == 1) { m_graphp->reportLoops(m_edgeFuncp, vertexp); m_graphp->loopsMessageCb(vertexp); - return; + return; // LCOV_EXCL_LINE // gcc gprof bug misses this return } if (vertexp->rank() >= currentRank) return; // Already processed it vertexp->user(1); @@ -449,21 +410,6 @@ void V3Graph::subtreeLoops(V3EdgeFuncP edgeFuncp, V3GraphVertex* vertexp, V3Grap GraphAlgSubtrees(this, loopGraphp, edgeFuncp, vertexp); } -//###################################################################### -//###################################################################### -// Algorithms - make non cutable - -void V3Graph::makeEdgesNonCutable(V3EdgeFuncP edgeFuncp) { - for (V3GraphVertex* vertexp = verticesBeginp(); vertexp; vertexp = vertexp->verticesNextp()) { - // Only need one direction, we'll always see the other at some point... - for (V3GraphEdge* edgep = vertexp->inBeginp(); edgep; edgep = edgep->inNextp()) { - if (edgep->cutable() && edgep->weight() && (edgeFuncp)(edgep)) { - edgep->cutable(false); - } - } - } -} - //###################################################################### //###################################################################### // Algorithms - sorting diff --git a/src/V3GraphAlg.h b/src/V3GraphAlg.h index b25b785f8..f3003f08a 100644 --- a/src/V3GraphAlg.h +++ b/src/V3GraphAlg.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3GraphDfa.cpp b/src/V3GraphDfa.cpp index 3d193aca3..ad77d1c60 100644 --- a/src/V3GraphDfa.cpp +++ b/src/V3GraphDfa.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2005-2020 by Wilson Snyder. This program is free software; you +// Copyright 2005-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -167,7 +167,7 @@ private: void insertDfaOrigins(DfaVertex* dfaStatep) { // Record the NFA states this dfa came from uint32_t hash = hashDfaOrigins(dfaStatep); - m_hashMap.insert(make_pair(hash, dfaStatep)); + m_hashMap.emplace(hash, dfaStatep); } DfaVertex* findDfaOrigins(const DfaStates& nfasWithInput) { diff --git a/src/V3GraphDfa.h b/src/V3GraphDfa.h index 3c726995d..26f31ef01 100644 --- a/src/V3GraphDfa.h +++ b/src/V3GraphDfa.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3GraphPathChecker.cpp b/src/V3GraphPathChecker.cpp index 8867d2cfa..ae7a474dd 100644 --- a/src/V3GraphPathChecker.cpp +++ b/src/V3GraphPathChecker.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3GraphPathChecker.h b/src/V3GraphPathChecker.h index 104aa719d..b239a1bca 100644 --- a/src/V3GraphPathChecker.h +++ b/src/V3GraphPathChecker.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3GraphStream.h b/src/V3GraphStream.h index f7bd78cb5..06e887699 100644 --- a/src/V3GraphStream.h +++ b/src/V3GraphStream.h @@ -7,7 +7,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -115,7 +115,7 @@ public: depCount++; } VxHolder newVx(vxp, pos++, depCount); - m_waitingVertices.insert(make_pair(vxp, newVx)); + m_waitingVertices.emplace(vxp, newVx); } } else { // REVERSE if (vxp->outEmpty()) { @@ -127,7 +127,7 @@ public: depCount++; } VxHolder newVx(vxp, pos++, depCount); - m_waitingVertices.insert(make_pair(vxp, newVx)); + m_waitingVertices.emplace(vxp, newVx); } } } diff --git a/src/V3GraphTest.cpp b/src/V3GraphTest.cpp index 67340c5ec..82c53d495 100644 --- a/src/V3GraphTest.cpp +++ b/src/V3GraphTest.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Hashed.cpp b/src/V3Hashed.cpp index a72e45106..acfe9ba94 100644 --- a/src/V3Hashed.cpp +++ b/src/V3Hashed.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -115,7 +115,7 @@ V3Hash V3Hashed::uncachedHash(const AstNode* nodep) { V3Hashed::iterator V3Hashed::hashAndInsert(AstNode* nodep) { hash(nodep); - return m_hashMmap.insert(make_pair(nodeHash(nodep), nodep)); + return m_hashMmap.emplace(nodeHash(nodep), nodep); } void V3Hashed::hash(AstNode* nodep) { @@ -162,7 +162,7 @@ void V3Hashed::dumpFile(const string& filename, bool tree) { if (it != end()) lasthash = it->first; if (num_in_bucket) { if (dist.find(num_in_bucket) == dist.end()) { - dist.insert(make_pair(num_in_bucket, 1)); + dist.emplace(num_in_bucket, 1); } else { ++dist[num_in_bucket]; } diff --git a/src/V3Hashed.h b/src/V3Hashed.h index e8d7b6fdc..bad5c246c 100644 --- a/src/V3Hashed.h +++ b/src/V3Hashed.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2005-2020 by Wilson Snyder. This program is free software; you +// Copyright 2005-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3HierBlock.cpp b/src/V3HierBlock.cpp index 41f647826..3f12fcfe4 100644 --- a/src/V3HierBlock.cpp +++ b/src/V3HierBlock.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -314,7 +314,7 @@ void V3HierBlockPlan::add(const AstNodeModule* modp, const std::vector& V3HierBlock* hblockp = new V3HierBlock(modp, gparams); UINFO(3, "Add " << modp->prettyNameQ() << " with " << gparams.size() << " parameters" << std::endl); - m_blocks.insert(std::make_pair(modp, hblockp)); + m_blocks.emplace(modp, hblockp); } } @@ -344,7 +344,7 @@ void V3HierBlockPlan::createPlan(AstNetlist* nodep) { } std::unique_ptr planp(new V3HierBlockPlan()); - { HierBlockUsageCollectVisitor visitor(planp.get(), nodep); } + { HierBlockUsageCollectVisitor{planp.get(), nodep}; } V3Stats::addStat("HierBlock, Hierarchical blocks", planp->m_blocks.size()); diff --git a/src/V3HierBlock.h b/src/V3HierBlock.h index 7ce652a74..e3dda62ae 100644 --- a/src/V3HierBlock.h +++ b/src/V3HierBlock.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you can +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you can // redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Inline.cpp b/src/V3Inline.cpp index c72990a3a..e81a28365 100644 --- a/src/V3Inline.cpp +++ b/src/V3Inline.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -614,7 +614,7 @@ public: // CONSTRUCTORS explicit InlineVisitor(AstNode* nodep) { iterate(nodep); } virtual ~InlineVisitor() override { // - V3Stats::addStat("Optimizations, Inlined cells", m_statCells); + V3Stats::addStat("Optimizations, Inlined instances", m_statCells); } }; diff --git a/src/V3Inline.h b/src/V3Inline.h index dd5b591f7..44bbfc327 100644 --- a/src/V3Inline.h +++ b/src/V3Inline.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Inst.cpp b/src/V3Inst.cpp index c9bb8acc8..fb950ae6c 100644 --- a/src/V3Inst.cpp +++ b/src/V3Inst.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -161,7 +161,7 @@ public: // METHODS void insert(AstVar* nodep) { UINFO(8, " dmINSERT " << nodep << endl); - m_modVarNameMap.insert(make_pair(nodep->name(), nodep)); + m_modVarNameMap.emplace(nodep->name(), nodep); } AstVar* find(const string& name) { const auto it = m_modVarNameMap.find(name); @@ -207,7 +207,7 @@ private: UINFO(8, " dv-vec-VAR " << nodep << endl); AstUnpackArrayDType* arrdtype = VN_CAST(nodep->dtypep(), UnpackArrayDType); AstNode* prevp = nullptr; - for (int i = arrdtype->lsb(); i <= arrdtype->msb(); ++i) { + for (int i = arrdtype->lo(); i <= arrdtype->hi(); ++i) { string varNewName = nodep->name() + "__BRA__" + cvtToStr(i) + "__KET__"; UINFO(8, "VAR name insert " << varNewName << " " << nodep << endl); if (!m_deModVars.find(varNewName)) { @@ -255,7 +255,7 @@ private: for (int i = 0; i < m_cellRangep->elementsConst(); i++) { m_instSelNum = m_cellRangep->littleEndian() ? (m_cellRangep->elementsConst() - 1 - i) : i; - int instNum = m_cellRangep->lsbConst() + i; + int instNum = m_cellRangep->loConst() + i; AstCell* newp = nodep->cloneTree(false); nodep->addNextHere(newp); @@ -341,17 +341,17 @@ private: // Arrayed instants: one bit for each of the instants (each // assign is 1 pinwidth wide) if (m_cellRangep->littleEndian()) { - nodep->exprp()->v3warn( - LITENDIAN, - "Little endian cell range connecting to vector: MSB < LSB of cell range: " - << m_cellRangep->lsbConst() << ":" << m_cellRangep->msbConst()); + nodep->exprp()->v3warn(LITENDIAN, "Little endian instance range connecting to " + "vector: left < right of instance range: [" + << m_cellRangep->leftConst() << ":" + << m_cellRangep->rightConst() << "]"); } AstNode* exprp = nodep->exprp()->unlinkFrBack(); bool inputPin = nodep->modVarp()->isNonOutput(); if (!inputPin && !VN_IS(exprp, VarRef) // V3Const will collapse the SEL with the one we're about to make - && !VN_IS(exprp, Concat) && !VN_IS(exprp, Sel)) { + && !VN_IS(exprp, Concat) && !VN_IS(exprp, Replicate) && !VN_IS(exprp, Sel)) { nodep->v3warn(E_UNSUPPORTED, "Unsupported: Per-bit array instantiations " "with output connections to non-wires."); // Note spec allows more complicated matches such as slices and such @@ -396,7 +396,7 @@ private: AstNode* prevPinp = nullptr; // Clone the var referenced by the pin, and clone each var referenced by the varref // Clone pin varp: - for (int i = pinArrp->lsb(); i <= pinArrp->msb(); ++i) { + for (int i = pinArrp->lo(); i <= pinArrp->hi(); ++i) { string varNewName = pinVarp->name() + "__BRA__" + cvtToStr(i) + "__KET__"; AstVar* varNewp = nullptr; @@ -529,7 +529,7 @@ public: && connectXRefp->varp()->isIfaceRef()) { } else if (!alwaysCvt && connBasicp && pinBasicp && connBasicp->width() == pinBasicp->width() - && connBasicp->lsb() == pinBasicp->lsb() + && connBasicp->lo() == pinBasicp->lo() && !connectRefp->varp() ->isSc() // Need the signal as a 'shell' to convert types && connBasicp->width() == pinVarp->width()) { diff --git a/src/V3Inst.h b/src/V3Inst.h index 5b68d0a31..3b7c4c333 100644 --- a/src/V3Inst.h +++ b/src/V3Inst.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3InstrCount.cpp b/src/V3InstrCount.cpp index 5da14c211..b26628cbf 100644 --- a/src/V3InstrCount.cpp +++ b/src/V3InstrCount.cpp @@ -7,7 +7,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3InstrCount.h b/src/V3InstrCount.h index 8e3d109f1..fa7c53086 100644 --- a/src/V3InstrCount.h +++ b/src/V3InstrCount.h @@ -7,7 +7,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3LangCode.h b/src/V3LangCode.h index cdb68b03e..ccb996836 100644 --- a/src/V3LangCode.h +++ b/src/V3LangCode.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3LanguageWords.h b/src/V3LanguageWords.h index 37cc5bee9..f9c3c92a1 100644 --- a/src/V3LanguageWords.h +++ b/src/V3LanguageWords.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2005-2020 by Wilson Snyder. This program is free software; you +// Copyright 2005-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -31,7 +31,7 @@ private: struct Singleton { KeywordMap s_kwdMap; // List of keywords, and what language applies Singleton() { init(); } - void addKwd(const string& kwd, const string& why) { s_kwdMap.insert(make_pair(kwd, why)); } + void addKwd(const string& kwd, const string& why) { s_kwdMap.emplace(kwd, why); } void init(); }; diff --git a/src/V3Life.cpp b/src/V3Life.cpp index daa9028f5..356d50ebd 100644 --- a/src/V3Life.cpp +++ b/src/V3Life.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -165,7 +165,7 @@ public: checkRemoveAssign(it); it->second.simpleAssign(assp); } else { - m_map.insert(make_pair(nodep, LifeVarEntry(LifeVarEntry::SIMPLEASSIGN(), assp))); + m_map.emplace(nodep, LifeVarEntry(LifeVarEntry::SIMPLEASSIGN(), assp)); } // lifeDump(); } @@ -175,7 +175,7 @@ public: if (it != m_map.end()) { it->second.complexAssign(); } else { - m_map.insert(make_pair(nodep, LifeVarEntry(LifeVarEntry::COMPLEXASSIGN()))); + m_map.emplace(nodep, LifeVarEntry(LifeVarEntry::COMPLEXASSIGN())); } } void varUsageReplace(AstVarScope* nodep, AstVarRef* varrefp) { @@ -196,7 +196,7 @@ public: UINFO(4, " usage: " << nodep << endl); it->second.consumed(); } else { - m_map.insert(make_pair(nodep, LifeVarEntry(LifeVarEntry::CONSUMED()))); + m_map.emplace(nodep, LifeVarEntry(LifeVarEntry::CONSUMED())); } } void complexAssignFind(AstVarScope* nodep) { @@ -205,7 +205,7 @@ public: UINFO(4, " casfind: " << it->first << endl); it->second.complexAssign(); } else { - m_map.insert(make_pair(nodep, LifeVarEntry(LifeVarEntry::COMPLEXASSIGN()))); + m_map.emplace(nodep, LifeVarEntry(LifeVarEntry::COMPLEXASSIGN())); } } void consumedFind(AstVarScope* nodep) { @@ -213,7 +213,7 @@ public: if (it != m_map.end()) { it->second.consumed(); } else { - m_map.insert(make_pair(nodep, LifeVarEntry(LifeVarEntry::CONSUMED()))); + m_map.emplace(nodep, LifeVarEntry(LifeVarEntry::CONSUMED())); } } void lifeToAbove() { diff --git a/src/V3Life.h b/src/V3Life.h index 7e8141329..5328503ed 100644 --- a/src/V3Life.h +++ b/src/V3Life.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3LifePost.cpp b/src/V3LifePost.cpp index b3bc39795..1dc7865d6 100644 --- a/src/V3LifePost.cpp +++ b/src/V3LifePost.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3LifePost.h b/src/V3LifePost.h index 426270a70..990f155ac 100644 --- a/src/V3LifePost.h +++ b/src/V3LifePost.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3LinkCells.cpp b/src/V3LinkCells.cpp index df9d24582..ef716e74f 100644 --- a/src/V3LinkCells.cpp +++ b/src/V3LinkCells.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -183,7 +183,7 @@ private: } v3error("Specified --top-module '" << v3Global.opt.topModule() - << "' isn't at the top level, it's under another cell '" + << "' isn't at the top level, it's under another instance '" << (abovep ? abovep->prettyName() : "UNKNOWN") << "'"); } } @@ -198,7 +198,7 @@ private: VL_RESTORER(m_modp); { m_modp = nodep; - UINFO(2, "Link Module: " << nodep << endl); + UINFO(4, "Link Module: " << nodep << endl); if (nodep->fileline()->filebasenameNoExt() != nodep->prettyName() && !v3Global.opt.isLibraryFile(nodep->fileline()->filename()) && !VN_IS(nodep, NotFoundModule) && !nodep->recursiveClone() @@ -363,7 +363,7 @@ private: for (AstPin *nextp, *pinp = nodep->pinsp(); pinp; pinp = nextp) { nextp = VN_CAST(pinp->nextp(), Pin); if (pinp->dotStar()) { - if (pinStar) pinp->v3error("Duplicate .* in a cell"); + if (pinStar) pinp->v3error("Duplicate .* in an instance"); pinStar = true; // Done with this fake pin VL_DO_DANGLING(pinp->unlinkFrBack()->deleteTree(), pinp); @@ -383,7 +383,7 @@ private: std::unordered_set ports; // Symbol table of all connected port names for (AstPin* pinp = nodep->pinsp(); pinp; pinp = VN_CAST(pinp->nextp(), Pin)) { if (pinp->name() == "") - pinp->v3error("Connect by position is illegal in .* connected cells"); + pinp->v3error("Connect by position is illegal in .* connected instances"); if (!pinp->exprp()) { if (pinp->name().substr(0, 11) == "__pinNumber") { pinp->v3warn(PINNOCONNECT, diff --git a/src/V3LinkCells.h b/src/V3LinkCells.h index c1cd4b817..7999147c8 100644 --- a/src/V3LinkCells.h +++ b/src/V3LinkCells.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index c82b3dba5..0c283904a 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -225,7 +225,7 @@ public: if (VN_IS(nodep, Var)) { return "variable"; } else if (VN_IS(nodep, Cell)) { - return "cell"; + return "instance"; } else if (VN_IS(nodep, Task)) { return "task"; } else if (VN_IS(nodep, Func)) { @@ -304,7 +304,7 @@ public: nodep->user1p(symp); checkDuplicate(rootEntp(), nodep, nodep->origName()); rootEntp()->insert(nodep->origName(), symp); - if (forScopeCreation()) m_nameScopeSymMap.insert(make_pair(scopename, symp)); + if (forScopeCreation()) m_nameScopeSymMap.emplace(scopename, symp); return symp; } VSymEnt* insertCell(VSymEnt* abovep, VSymEnt* modSymp, AstCell* nodep, @@ -326,11 +326,11 @@ public: // have 2 same cells under an if modSymp->reinsert(nodep->name(), symp); } - if (forScopeCreation()) m_nameScopeSymMap.insert(make_pair(scopename, symp)); + if (forScopeCreation()) m_nameScopeSymMap.emplace(scopename, symp); return symp; } void insertMap(VSymEnt* symp, const string& scopename) { - if (forScopeCreation()) m_nameScopeSymMap.insert(make_pair(scopename, symp)); + if (forScopeCreation()) m_nameScopeSymMap.emplace(scopename, symp); } VSymEnt* insertInline(VSymEnt* abovep, VSymEnt* modSymp, AstCellInline* nodep, @@ -409,9 +409,7 @@ public: // Mark the given variable name as being allowed to be implicitly declared if (nodep) { const auto it = m_implicitNameSet.find(make_pair(nodep, varname)); - if (it == m_implicitNameSet.end()) { - m_implicitNameSet.insert(make_pair(nodep, varname)); - } + if (it == m_implicitNameSet.end()) { m_implicitNameSet.emplace(nodep, varname); } } } bool implicitOk(AstNodeModule* nodep, const string& varname) { @@ -459,7 +457,7 @@ public: ifacerefp->v3fatalSrc("Unlinked interface"); } } else if (ifacerefp->ifaceViaCellp()->dead()) { - ifacerefp->v3error("Parent cell's interface is not found: " + ifacerefp->v3error("Parent instance's interface is not found: " << AstNode::prettyNameQ(ifacerefp->ifaceName())); continue; } @@ -501,7 +499,7 @@ public: UASSERT_OBJ( !(VN_IS(rhsp->nodep(), Cell) && !VN_IS(VN_CAST(rhsp->nodep(), Cell)->modp(), Iface)), rhsp->nodep(), "Got a non-IFACE alias RHS"); - m_scopeAliasMap[samn].insert(make_pair(lhsp, rhsp)); + m_scopeAliasMap[samn].emplace(lhsp, rhsp); } void computeScopeAliases() { UINFO(9, "computeIfaceAliases\n"); @@ -645,6 +643,10 @@ public: if (AstNodeModule* modp = cellp->modp()) { if (modp->hierBlock()) { refLocationp->v3error("Cannot access inside hierarchical block"); + } else if (VN_IS(modp, NotFoundModule)) { + refLocationp->v3error("Dotted reference to instance that refers to " + "missing module/interface: " + << modp->prettyNameQ()); } } } @@ -718,7 +720,6 @@ class LinkDotFindVisitor final : public AstNVisitor { AstNodeFTask* m_ftaskp = nullptr; // Current function/task bool m_inRecursion = false; // Inside a recursive module int m_paramNum = 0; // Parameter number, for position based connection - int m_blockNum = 0; // Begin block number, 0=none seen bool m_explicitNew = false; // Hit a "new" function int m_modBlockNum = 0; // Begin block number in module, 0=none seen int m_modWithNum = 0; // With block number, 0=none seen @@ -783,7 +784,6 @@ class LinkDotFindVisitor final : public AstNVisitor { VL_RESTORER(m_modSymp); VL_RESTORER(m_curSymp); VL_RESTORER(m_paramNum); - VL_RESTORER(m_blockNum); VL_RESTORER(m_modBlockNum); VL_RESTORER(m_modWithNum); if (doit && nodep->user2()) { @@ -793,7 +793,7 @@ class LinkDotFindVisitor final : public AstNVisitor { << AstNode::prettyNameQ(nodep->origName())); } else if (doit) { UINFO(4, " Link Module: " << nodep << endl); - UASSERT_OBJ(!nodep->dead(), nodep, "Module in cell tree mislabeled as dead?"); + UASSERT_OBJ(!nodep->dead(), nodep, "Module in instance tree mislabeled as dead?"); VSymEnt* upperSymp = m_curSymp ? m_curSymp : m_statep->rootEntp(); AstPackage* pkgp = VN_CAST(nodep, Package); m_classOrPackagep = pkgp; @@ -810,7 +810,6 @@ class LinkDotFindVisitor final : public AstNVisitor { } // m_paramNum = 0; - m_blockNum = 0; m_modBlockNum = 0; m_modWithNum = 0; // m_modSymp/m_curSymp for non-packages set by AstCell above this module @@ -845,7 +844,6 @@ class LinkDotFindVisitor final : public AstNVisitor { VL_RESTORER(m_modSymp); VL_RESTORER(m_curSymp); VL_RESTORER(m_paramNum); - VL_RESTORER(m_blockNum); VL_RESTORER(m_modBlockNum); VL_RESTORER(m_modWithNum); { @@ -859,7 +857,6 @@ class LinkDotFindVisitor final : public AstNVisitor { UINFO(9, "New module scope " << m_curSymp << endl); // m_paramNum = 0; - m_blockNum = 0; m_modBlockNum = 0; m_modWithNum = 0; m_explicitNew = false; @@ -899,8 +896,8 @@ class LinkDotFindVisitor final : public AstNVisitor { VSymEnt* okSymp; aboveSymp = m_statep->findDotted(nodep->fileline(), aboveSymp, scope, baddot, okSymp); UASSERT_OBJ(aboveSymp, nodep, - "Can't find cell insertion point at " << AstNode::prettyNameQ(baddot) - << " in: " << nodep->prettyNameQ()); + "Can't find instance insertion point at " + << AstNode::prettyNameQ(baddot) << " in: " << nodep->prettyNameQ()); } { m_scope = m_scope + "." + nodep->name(); @@ -937,14 +934,6 @@ class LinkDotFindVisitor final : public AstNVisitor { } virtual void visit(AstNodeBlock* nodep) override { UINFO(5, " " << nodep << endl); - // Rename "genblk"s to include a number - if (m_statep->forPrimary() && !nodep->user4SetOnce()) { - if (nodep->name() == "genblk") { - ++m_blockNum; - nodep->name(nodep->name() + cvtToStr(m_blockNum)); - } - } - // All blocks are numbered in the standard, IE we start with "genblk1" even if only one. if (nodep->name() == "" && nodep->unnamed()) { // Unnamed blocks are only important when they contain var // decls, so search for them. (Otherwise adding all the @@ -962,12 +951,10 @@ class LinkDotFindVisitor final : public AstNVisitor { if (nodep->name() == "") { iterateChildren(nodep); } else { - VL_RESTORER(m_blockNum); VL_RESTORER(m_blockp); VL_RESTORER(m_curSymp); VSymEnt* const oldCurSymp = m_curSymp; { - m_blockNum = 0; m_blockp = nodep; m_curSymp = m_statep->insertBlock(m_curSymp, nodep->name(), nodep, m_classOrPackagep); @@ -1161,7 +1148,7 @@ class LinkDotFindVisitor final : public AstNVisitor { VSymEnt* insp = m_statep->insertSym(m_curSymp, nodep->name(), nodep, m_classOrPackagep); if (m_statep->forPrimary() && nodep->isGParam()) { - m_paramNum++; + ++m_paramNum; VSymEnt* symp = m_statep->insertSym(m_curSymp, "__paramNumber" + cvtToStr(m_paramNum), nodep, m_classOrPackagep); @@ -1191,6 +1178,12 @@ class LinkDotFindVisitor final : public AstNVisitor { UASSERT_OBJ(m_curSymp, nodep, "Parameter type not under module/package/$unit"); iterateChildren(nodep); m_statep->insertSym(m_curSymp, nodep->name(), nodep, m_classOrPackagep); + if (m_statep->forPrimary() && nodep->isGParam()) { + ++m_paramNum; + VSymEnt* symp = m_statep->insertSym(m_curSymp, "__paramNumber" + cvtToStr(m_paramNum), + nodep, m_classOrPackagep); + symp->exported(false); + } } virtual void visit(AstCFunc* nodep) override { // For dotted resolution, ignore all AstVars under functions, otherwise shouldn't exist @@ -1290,9 +1283,9 @@ class LinkDotFindVisitor final : public AstNVisitor { VL_DO_DANGLING(argp->unlinkFrBackWithNext()->deleteTree(), argp); } // Type depends on the method used, let V3Width figure it out later - const auto indexArgRefp = new AstLambdaArgRef(argFl, name + "__DOT__index", true); - const auto valueArgRefp = new AstLambdaArgRef(argFl, name, false); if (nodep->exprp()) { // Else empty expression and pretend no "with" + const auto indexArgRefp = new AstLambdaArgRef(argFl, name + "__DOT__index", true); + const auto valueArgRefp = new AstLambdaArgRef(argFl, name, false); const auto newp = new AstWith(nodep->fileline(), indexArgRefp, valueArgRefp, nodep->exprp()->unlinkFrBackWithNext()); funcrefp->addPinsp(newp); @@ -1404,7 +1397,7 @@ private: VSymEnt* foundp = m_statep->getNodeSym(nodep)->findIdFallback(nodep->path()); AstCell* cellp = foundp ? VN_CAST(foundp->nodep(), Cell) : nullptr; if (!cellp) { - nodep->v3error("In defparam, cell " << nodep->path() << " never declared"); + nodep->v3error("In defparam, instance " << nodep->path() << " never declared"); } else { AstNode* exprp = nodep->rhsp()->unlinkFrBack(); UINFO(9, "Defparam cell " << nodep->path() << "." << nodep->name() << " attach-to " @@ -1470,6 +1463,28 @@ private: // We're done with implicit gates VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); } + virtual void visit(AstClassOrPackageRef* nodep) override { + if (auto* fwdp = VN_CAST(nodep->classOrPackageNodep(), TypedefFwd)) { + // Relink forward definitions to the "real" definition + VSymEnt* foundp = m_statep->getNodeSym(fwdp)->findIdFallback(fwdp->name()); + if (foundp && (VN_IS(foundp->nodep(), Class) || VN_IS(foundp->nodep(), Package))) { + nodep->classOrPackagep(VN_CAST(foundp->nodep(), NodeModule)); + } else if (foundp && VN_IS(foundp->nodep(), ParamTypeDType)) { + UASSERT(m_statep->forPrimary(), "Param types should have been resolved"); + nodep->classOrPackageNodep(foundp->nodep()); + } else { + if (foundp) UINFO(1, "found nodep = " << foundp->nodep() << endl); + nodep->v3error( + "Forward typedef used as class/package does not resolve to class/package: " + << nodep->prettyNameQ() << '\n' + << nodep->warnContextPrimary() << '\n' + << (foundp ? nodep->warnMore() + "... Object with matching name\n" + + foundp->nodep()->warnContextSecondary() + : "")); + } + } + iterateChildren(nodep); + } virtual void visit(AstTypedefFwd* nodep) override { VSymEnt* foundp = m_statep->getNodeSym(nodep)->findIdFallback(nodep->name()); if (!foundp && v3Global.opt.pedantic()) { @@ -1481,7 +1496,8 @@ private: << nodep->prettyNameQ()); } // We only needed the forward declaration in order to parse correctly. - VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); + // Delete later as may be ClassOrPackageRef's still pointing to it + VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep); } virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } @@ -1540,10 +1556,11 @@ class LinkDotScopeVisitor final : public AstNVisitor { VSymEnt* okSymp; VSymEnt* cellSymp = m_statep->findDotted(nodep->fileline(), m_modSymp, ifcellname, baddot, okSymp); - UASSERT_OBJ(cellSymp, nodep, - "No symbol for interface cell: " << nodep->prettyNameQ(ifcellname)); - UINFO(5, " Found interface cell: se" << cvtToHex(cellSymp) << " " - << cellSymp->nodep() << endl); + UASSERT_OBJ( + cellSymp, nodep, + "No symbol for interface instance: " << nodep->prettyNameQ(ifcellname)); + UINFO(5, " Found interface instance: se" << cvtToHex(cellSymp) << " " + << cellSymp->nodep() << endl); if (dtypep->modportName() != "") { VSymEnt* mpSymp = m_statep->findDotted(nodep->fileline(), m_modSymp, ifcellname, baddot, okSymp); @@ -1972,6 +1989,8 @@ private: checkNoDot(nodep); AstNode::user5ClearTree(); UASSERT_OBJ(nodep->classp(), nodep, "ClassRef has unlinked class"); + UASSERT_OBJ(m_statep->forPrimary() || !nodep->paramsp(), nodep, + "class reference parameter not removed by V3Param"); VL_RESTORER(m_pinSymp); { // ClassRef's have pins, so track @@ -1987,7 +2006,7 @@ private: checkNoDot(nodep); iterateChildren(nodep); if (!nodep->modVarp()) { - UASSERT_OBJ(m_pinSymp, nodep, "Pin not under cell?"); + UASSERT_OBJ(m_pinSymp, nodep, "Pin not under instance?"); VSymEnt* foundp = m_pinSymp->findIdFlat(nodep->name()); const char* whatp = nodep->param() ? "parameter pin" : "pin"; if (!foundp) { @@ -2068,9 +2087,9 @@ private: } else { auto cextp = VN_CAST(classp->extendsp(), ClassExtends); UASSERT_OBJ(cextp, nodep, "Bad super extends link"); - auto classp = cextp->classp(); - UASSERT_OBJ(classp, nodep, "Bad superclass"); - m_ds.m_dotSymp = m_statep->getNodeSym(classp); + auto sclassp = cextp->classp(); + UASSERT_OBJ(sclassp, nodep, "Bad superclass"); + m_ds.m_dotSymp = m_statep->getNodeSym(sclassp); UINFO(8, " super. " << m_ds.ascii() << endl); } } @@ -2325,7 +2344,7 @@ private: << modportp->prettyNameQ()); } else { AstCell* cellp = VN_CAST(m_ds.m_dotSymp->nodep(), Cell); - UASSERT_OBJ(cellp, nodep, "Modport not referenced from a cell"); + UASSERT_OBJ(cellp, nodep, "Modport not referenced from an instance"); VSymEnt* cellEntp = m_statep->getNodeSym(cellp); UASSERT_OBJ(cellEntp, nodep, "No interface sym entry"); VSymEnt* parentEntp = cellEntp->parentp(); // Container of the var; probably a @@ -2555,9 +2574,6 @@ private: nodep->v3warn(E_UNSUPPORTED, "Unsupported: " << AstNode::prettyNameQ(cpackagerefp->name())); } - if (cpackagerefp->paramsp()) { - nodep->v3warn(E_UNSUPPORTED, "Unsupported: parameterized packages for task calls"); - } UASSERT_OBJ(cpackagerefp->classOrPackagep(), m_ds.m_dotp->lhsp(), "Bad package link"); nodep->classOrPackagep(cpackagerefp->classOrPackagep()); m_ds.m_dotPos = DP_SCOPE; @@ -2703,7 +2719,7 @@ private: } virtual void visit(AstSelBit* nodep) override { if (nodep->user3SetOnce()) return; - iterateAndNextNull(nodep->lhsp()); + iterateAndNextNull(nodep->fromp()); if (m_ds.m_dotPos == DP_SCOPE) { // Already under dot, so this is {modulepart} DOT {modulepart} UINFO(9, " deferring until after a V3Param pass: " << nodep << endl); @@ -2734,12 +2750,12 @@ private: if (nodep->user3SetOnce()) return; if (m_ds.m_dotPos == DP_SCOPE) { // Already under dot, so this is {modulepart} DOT {modulepart} - nodep->v3error("Syntax Error: Range ':', '+:' etc are not allowed in the cell part of " - "a dotted reference"); + nodep->v3error("Syntax Error: Range ':', '+:' etc are not allowed in the instance " + "part of a dotted reference"); m_ds.m_dotErr = true; return; } - iterateAndNextNull(nodep->lhsp()); + iterateAndNextNull(nodep->fromp()); VL_RESTORER(m_ds); { m_ds.init(m_curSymp); @@ -2887,8 +2903,10 @@ private: if (!VN_IS(nodep->classOrPackagep(), Class) && !VN_IS(nodep->classOrPackagep(), Package)) { cpackagerefp->v3error( - "'::' expected to reference a class/package but referenced " - << nodep->classOrPackagep()->prettyTypeName() << '\n' + "'::' expected to reference a class/package but referenced '" + << (nodep->classOrPackagep() ? nodep->classOrPackagep()->prettyTypeName() + : "") + << "'\n" << cpackagerefp->warnMore() + "... Suggest '.' instead of '::'"); } } else { @@ -2896,16 +2914,13 @@ private: "Unsupported: Multiple '::' package/class reference"); } VL_DO_DANGLING(cpackagep->unlinkFrBack()->deleteTree(), cpackagep); - } else if (nodep->paramsp()) { - nodep->v3warn(E_UNSUPPORTED, "Unsupported: parameterized packages"); } if (m_ds.m_dotp && m_ds.m_dotPos == DP_PACKAGE) { UASSERT_OBJ(VN_IS(m_ds.m_dotp->lhsp(), ClassOrPackageRef), m_ds.m_dotp->lhsp(), "Bad package link"); - UASSERT_OBJ(VN_CAST(m_ds.m_dotp->lhsp(), ClassOrPackageRef)->classOrPackagep(), - m_ds.m_dotp->lhsp(), "Bad package link"); - nodep->classOrPackagep( - VN_CAST(m_ds.m_dotp->lhsp(), ClassOrPackageRef)->classOrPackagep()); + auto* cpackagerefp = VN_CAST(m_ds.m_dotp->lhsp(), ClassOrPackageRef); + UASSERT_OBJ(cpackagerefp->classOrPackagep(), m_ds.m_dotp->lhsp(), "Bad package link"); + nodep->classOrPackagep(cpackagerefp->classOrPackagep()); m_ds.m_dotPos = DP_SCOPE; m_ds.m_dotp = nullptr; } else { diff --git a/src/V3LinkDot.h b/src/V3LinkDot.h index 026ba0e2b..cfeaf100d 100644 --- a/src/V3LinkDot.h +++ b/src/V3LinkDot.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3LinkInc.cpp b/src/V3LinkInc.cpp index 89ea48649..44f3cde8f 100644 --- a/src/V3LinkInc.cpp +++ b/src/V3LinkInc.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3LinkInc.h b/src/V3LinkInc.h index ebb9194e7..051babbba 100644 --- a/src/V3LinkInc.h +++ b/src/V3LinkInc.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3LinkJump.cpp b/src/V3LinkJump.cpp index e4bbc3c0e..8308ffa1b 100644 --- a/src/V3LinkJump.cpp +++ b/src/V3LinkJump.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3LinkJump.h b/src/V3LinkJump.h index af1e88ba0..36a5d3742 100644 --- a/src/V3LinkJump.h +++ b/src/V3LinkJump.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3LinkLValue.cpp b/src/V3LinkLValue.cpp index b1e365f10..ae87110db 100644 --- a/src/V3LinkLValue.cpp +++ b/src/V3LinkLValue.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -79,10 +79,10 @@ private: virtual void visit(AstCastDynamic* nodep) override { VL_RESTORER(m_setRefLvalue); { - m_setRefLvalue = VAccess::WRITE; - iterateAndNextNull(nodep->lhsp()); m_setRefLvalue = VAccess::NOCHANGE; - iterateAndNextNull(nodep->rhsp()); + iterateAndNextNull(nodep->fromp()); + m_setRefLvalue = VAccess::WRITE; + iterateAndNextNull(nodep->top()); } } virtual void visit(AstFOpen* nodep) override { @@ -249,7 +249,7 @@ private: virtual void visit(AstNodePreSel* nodep) override { VL_RESTORER(m_setRefLvalue); { // Only set lvalues on the from - iterateAndNextNull(nodep->lhsp()); + iterateAndNextNull(nodep->fromp()); m_setRefLvalue = VAccess::NOCHANGE; iterateAndNextNull(nodep->rhsp()); iterateAndNextNull(nodep->thsp()); diff --git a/src/V3LinkLValue.h b/src/V3LinkLValue.h index 1a534d649..8c0327bd5 100644 --- a/src/V3LinkLValue.h +++ b/src/V3LinkLValue.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3LinkLevel.cpp b/src/V3LinkLevel.cpp index 4a5bc93b7..8572a25e9 100644 --- a/src/V3LinkLevel.cpp +++ b/src/V3LinkLevel.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -115,6 +115,8 @@ void V3LinkLevel::timescaling(const ModVec& mods) { } } + v3Global.rootp()->timescaleSpecified(modTimedp); // true if some module specifies timescale + if (v3Global.rootp()->timeprecision().isNone()) { v3Global.rootp()->timeprecisionMerge(v3Global.rootp()->fileline(), VTimescale(VTimescale::TS_DEFAULT)); diff --git a/src/V3LinkLevel.h b/src/V3LinkLevel.h index ca9a51a26..e141d0351 100644 --- a/src/V3LinkLevel.h +++ b/src/V3LinkLevel.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3LinkParse.cpp b/src/V3LinkParse.cpp index a3883b91c..60c73a5e5 100644 --- a/src/V3LinkParse.cpp +++ b/src/V3LinkParse.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -57,6 +57,8 @@ private: AstNodeModule* m_modp = nullptr; // Current module AstNodeFTask* m_ftaskp = nullptr; // Current task AstNodeDType* m_dtypep = nullptr; // Current data type + int m_genblkAbove = 0; // Begin block number of if/case/for above + int m_genblkNum = 0; // Begin block number, 0=none seen VLifetime m_lifetime = VLifetime::STATIC; // Propagating lifetime // METHODS @@ -96,10 +98,11 @@ private: void visitIterateNodeDType(AstNodeDType* nodep) { if (!nodep->user1SetOnce()) { // Process only once. cleanFileline(nodep); - AstNodeDType* upperDtypep = m_dtypep; - m_dtypep = nodep; - iterateChildren(nodep); - m_dtypep = upperDtypep; + { + VL_RESTORER(m_dtypep); + m_dtypep = nodep; + iterateChildren(nodep); + } } } @@ -125,10 +128,11 @@ private: if (!nodep->user1SetOnce()) { // Process only once. cleanFileline(nodep); UINFO(5, " " << nodep << endl); - AstNodeModule* upperValueModp = m_valueModp; - m_valueModp = nullptr; - iterateChildren(nodep); - m_valueModp = upperValueModp; + { + VL_RESTORER(m_valueModp); + m_valueModp = nullptr; + iterateChildren(nodep); + } } } virtual void visit(AstNodeDType* nodep) override { visitIterateNodeDType(nodep); } @@ -149,16 +153,17 @@ private: cleanFileline(nodep); iterateChildren(nodep); if (nodep->rangep()) { - if (!VN_IS(nodep->rangep()->msbp(), Const) // - || !VN_IS(nodep->rangep()->lsbp(), Const)) { + if (VL_UNCOVERABLE(!VN_IS(nodep->rangep()->leftp(), Const) // LCOV_EXCL_START + || !VN_IS(nodep->rangep()->rightp(), Const))) { + // We check this rule in the parser, so shouldn't fire nodep->v3error("Enum ranges must be integral, per spec"); - } - int msb = nodep->rangep()->msbConst(); - int lsb = nodep->rangep()->lsbConst(); - int increment = (msb > lsb) ? -1 : 1; + } // LCOV_EXCL_STOP + int left = nodep->rangep()->leftConst(); + int right = nodep->rangep()->rightConst(); + int increment = (left > right) ? -1 : 1; int offset_from_init = 0; AstNode* addp = nullptr; - for (int i = msb; i != (lsb + increment); i += increment, offset_from_init++) { + for (int i = left; i != (right + increment); i += increment, offset_from_init++) { string name = nodep->name() + cvtToStr(i); AstNode* valuep = nullptr; if (nodep->valuep()) { @@ -492,12 +497,16 @@ private: V3Config::applyModule(nodep); VL_RESTORER(m_modp); + VL_RESTORER(m_genblkAbove); + VL_RESTORER(m_genblkNum); VL_RESTORER(m_lifetime); { // Module: Create sim table for entire module and iterate cleanFileline(nodep); // m_modp = nodep; + m_genblkAbove = 0; + m_genblkNum = 0; m_valueModp = nodep; m_lifetime = nodep->lifetime(); if (m_lifetime.isNone()) { @@ -510,17 +519,17 @@ private: void visitIterateNoValueMod(AstNode* nodep) { // Iterate a node which shouldn't have any local variables moved to an Initial cleanFileline(nodep); - // - AstNodeModule* upperValueModp = m_valueModp; - m_valueModp = nullptr; - iterateChildren(nodep); - m_valueModp = upperValueModp; + { + VL_RESTORER(m_valueModp); + m_valueModp = nullptr; + iterateChildren(nodep); + } } virtual void visit(AstNodeProcedure* nodep) override { visitIterateNoValueMod(nodep); } virtual void visit(AstAlways* nodep) override { + VL_RESTORER(m_inAlways); m_inAlways = true; visitIterateNoValueMod(nodep); - m_inAlways = false; } virtual void visit(AstCover* nodep) override { visitIterateNoValueMod(nodep); } virtual void visit(AstRestrict* nodep) override { visitIterateNoValueMod(nodep); } @@ -535,13 +544,45 @@ private: || VN_IS(nodep->stmtsp(), GenCase)) // Has an if/case && !nodep->stmtsp()->nextp()); // Has only one item // It's not FOR(BEGIN(...)) but we earlier changed it to BEGIN(FOR(...)) - if (nodep->genforp() && nodep->name() == "") { - nodep->name("genblk"); - } else if (nodep->generate() && nodep->name() == "" - && (VN_IS(backp, CaseItem) || VN_IS(backp, GenIf)) && !nestedIf) { - nodep->name("genblk"); + if (nodep->genforp()) { + ++m_genblkNum; + if (nodep->name() == "") nodep->name("genblk" + cvtToStr(m_genblkNum)); + } + if (nodep->generate() && nodep->name() == "" + && (VN_IS(backp, CaseItem) || VN_IS(backp, GenIf)) && !nestedIf) { + nodep->name("genblk" + cvtToStr(m_genblkAbove)); + } + if (nodep->name() != "") { + VL_RESTORER(m_genblkAbove); + VL_RESTORER(m_genblkNum); + m_genblkAbove = 0; + m_genblkNum = 0; + iterateChildren(nodep); + } else { + iterateChildren(nodep); + } + } + virtual void visit(AstGenCase* nodep) override { + ++m_genblkNum; + cleanFileline(nodep); + { + VL_RESTORER(m_genblkAbove); + VL_RESTORER(m_genblkNum); + m_genblkAbove = m_genblkNum; + m_genblkNum = 0; + iterateChildren(nodep); + } + } + virtual void visit(AstGenIf* nodep) override { + ++m_genblkNum; + cleanFileline(nodep); + { + VL_RESTORER(m_genblkAbove); + VL_RESTORER(m_genblkNum); + m_genblkAbove = m_genblkNum; + m_genblkNum = 0; + iterateChildren(nodep); } - iterateChildren(nodep); } virtual void visit(AstCase* nodep) override { V3Config::applyCase(nodep); diff --git a/src/V3LinkParse.h b/src/V3LinkParse.h index bd600daab..0abf4e798 100644 --- a/src/V3LinkParse.h +++ b/src/V3LinkParse.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3LinkResolve.cpp b/src/V3LinkResolve.cpp index 9d8ba6828..f2d1dbb6a 100644 --- a/src/V3LinkResolve.cpp +++ b/src/V3LinkResolve.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -96,8 +96,6 @@ private: virtual void visit(AstVar* nodep) override { iterateChildren(nodep); if (m_classp && !nodep->isParam()) nodep->varType(AstVarType::MEMBER); - if (m_classp && nodep->isParam()) - nodep->v3warn(E_UNSUPPORTED, "Unsupported: class parameter"); if (m_ftaskp) nodep->funcLocal(true); if (nodep->isSigModPublic()) { nodep->sigModPublic(false); // We're done with this attribute @@ -107,14 +105,23 @@ private: virtual void visit(AstNodeVarRef* nodep) override { // VarRef: Resolve its reference - if (nodep->varp()) { nodep->varp()->usedParam(true); } + if (nodep->varp()) nodep->varp()->usedParam(true); iterateChildren(nodep); } virtual void visit(AstNodeFTask* nodep) override { // NodeTask: Remember its name for later resolution // Remember the existing symbol table scope - if (m_classp) nodep->classMethod(true); + if (m_classp) { + if (nodep->name() == "pre_randomize" || nodep->name() == "post_randomize") { + nodep->v3warn(E_UNSUPPORTED, "Unsupported: " << nodep->prettyNameQ()); + } else if (nodep->name() == "randomize") { + nodep->v3error(nodep->prettyNameQ() + << " is a predefined class method; redefinition not allowed (IEEE " + "1800-2017 18.6.3)"); + } + nodep->classMethod(true); + } // V3LinkDot moved the isExternDef into the class, the extern proto was // checked to exist, and now isn't needed nodep->isExternDef(false); @@ -189,7 +196,7 @@ private: did = true; } if (AstNodePreSel* selp = VN_CAST(nodep->sensp(), NodePreSel)) { - AstNode* fromp = selp->lhsp()->unlinkFrBack(); + AstNode* fromp = selp->fromp()->unlinkFrBack(); selp->replaceWith(fromp); VL_DO_DANGLING(selp->deleteTree(), selp); did = true; diff --git a/src/V3LinkResolve.h b/src/V3LinkResolve.h index a998c0500..92e351df1 100644 --- a/src/V3LinkResolve.h +++ b/src/V3LinkResolve.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3List.h b/src/V3List.h index 0b4bc399b..99090bc9e 100644 --- a/src/V3List.h +++ b/src/V3List.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Localize.cpp b/src/V3Localize.cpp index 372f4d188..42cf12d66 100644 --- a/src/V3Localize.cpp +++ b/src/V3Localize.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Localize.h b/src/V3Localize.h index 3db73dec4..9132145ce 100644 --- a/src/V3Localize.h +++ b/src/V3Localize.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3MergeCond.cpp b/src/V3MergeCond.cpp index 771096200..873048ee1 100644 --- a/src/V3MergeCond.cpp +++ b/src/V3MergeCond.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3MergeCond.h b/src/V3MergeCond.h index 3366963e7..47c88918d 100644 --- a/src/V3MergeCond.h +++ b/src/V3MergeCond.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Name.cpp b/src/V3Name.cpp index 9c3c745dc..2c7ad9e96 100644 --- a/src/V3Name.cpp +++ b/src/V3Name.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Name.h b/src/V3Name.h index 526858787..2c759178e 100644 --- a/src/V3Name.h +++ b/src/V3Name.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Number.cpp b/src/V3Number.cpp index a2073dff7..819e47339 100644 --- a/src/V3Number.cpp +++ b/src/V3Number.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -495,6 +495,7 @@ string V3Number::ascii(bool prefixed, bool cleanVerilog) const { out << "'"; if (bitIs0(0)) { out << '0'; + if (isNull()) out << "[null]"; } else if (bitIs1(0)) { out << '1'; } else if (bitIsZ(0)) { @@ -515,7 +516,8 @@ string V3Number::ascii(bool prefixed, bool cleanVerilog) const { bool binary = (isFourState() #ifdef V3NUMBER_ASCII_BINARY - || 1 + // cppcheck-suppress konwnConditionTrueFalse + || true #endif ); // out<<"-"<width(); bit++) { - if (lhs.bitIs1(bit) && rhs.bitIs1(bit)) { - setBit(bit, 1); - } else if (lhs.bitIs0(bit) && rhs.bitIs0(bit)) { - setBit(bit, 1); - } else if (lhs.bitIsXZ(bit) && rhs.bitIsXZ(bit)) { - setBit(bit, 'x'); - } - // else zero - } - return *this; -} - V3Number& V3Number::opConcat(const V3Number& lhs, const V3Number& rhs) { NUM_ASSERT_OP_ARGS2(lhs, rhs); NUM_ASSERT_LOGIC_ARGS2(lhs, rhs); @@ -1685,34 +1650,6 @@ V3Number& V3Number::opLte(const V3Number& lhs, const V3Number& rhs) { return opG V3Number& V3Number::opLtS(const V3Number& lhs, const V3Number& rhs) { return opGtS(rhs, lhs); } V3Number& V3Number::opLteS(const V3Number& lhs, const V3Number& rhs) { return opGteS(rhs, lhs); } -V3Number& V3Number::opRotR(const V3Number& lhs, const V3Number& rhs) { - // L(lhs) bit return - NUM_ASSERT_OP_ARGS2(lhs, rhs); - NUM_ASSERT_LOGIC_ARGS2(lhs, rhs); - if (rhs.isFourState()) return setAllBitsX(); - setZero(); - uint32_t rhsval = rhs.toUInt(); - for (int bit = 0; bit < this->width(); bit++) { - setBit(bit, lhs.bitIs((bit + rhsval) % this->width())); - } - return *this; -} - -V3Number& V3Number::opRotL(const V3Number& lhs, const V3Number& rhs) { - // L(lhs) bit return - NUM_ASSERT_OP_ARGS2(lhs, rhs); - NUM_ASSERT_LOGIC_ARGS2(lhs, rhs); - if (rhs.isFourState()) return setAllBitsX(); - setZero(); - uint32_t rhsval = rhs.toUInt(); - for (int bit = 0; bit < this->width(); bit++) { - if (bit >= static_cast(rhsval)) { - setBit(bit, lhs.bitIs((bit - rhsval) % this->width())); - } - } - return *this; -} - V3Number& V3Number::opShiftR(const V3Number& lhs, const V3Number& rhs) { // L(lhs) bit return NUM_ASSERT_OP_ARGS2(lhs, rhs); diff --git a/src/V3Number.h b/src/V3Number.h index 240858ea9..47ca60a11 100644 --- a/src/V3Number.h +++ b/src/V3Number.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -43,6 +43,7 @@ class V3Number final { bool m_sized : 1; // True if the user specified the width, else we track it. bool m_signed : 1; // True if signed value bool m_double : 1; // True if double real value + bool m_isNull : 1; // True if "null" versus normal 0 bool m_isString : 1; // True if string bool m_fromString : 1; // True if from string literal bool m_autoExtend : 1; // True if SystemVerilog extend-to-any-width @@ -176,6 +177,12 @@ public: init(nodep, 0); setString(value); } + class Null {}; + V3Number(Null, AstNode* nodep) { + init(nodep, 0); + m_isNull = true; + m_autoExtend = true; + } explicit V3Number(const V3Number* nump, int width = 1) { init(nullptr, width); m_fileline = nump->fileline(); @@ -191,13 +198,15 @@ private: void V3NumberCreate(AstNode* nodep, const char* sourcep, FileLine* fl); void init(AstNode* nodep, int swidth, bool sized = true) { setNames(nodep); + // dtype info does NOT from nodep's dtype; nodep only for error reporting m_signed = false; m_double = false; + m_isNull = false; m_isString = false; m_autoExtend = false; m_fromString = false; width(swidth, sized); - for (int i = 0; i < words(); i++) m_value[i] = m_valueX[i] = 0; + for (int i = 0; i < words(); ++i) m_value[i] = m_valueX[i] = 0; } void setNames(AstNode* nodep); static string displayPad(size_t fmtsize, char pad, bool left, const string& in); @@ -250,6 +259,7 @@ public: bool isString() const { return m_isString; } void isString(bool flag) { m_isString = flag; } bool isNegative() const { return bitIs1(width() - 1); } + bool isNull() const { return m_isNull; } bool isFourState() const; bool hasZ() const { for (int i = 0; i < words(); i++) { @@ -317,7 +327,6 @@ public: V3Number& opRedOr(const V3Number& lhs); V3Number& opRedAnd(const V3Number& lhs); V3Number& opRedXor(const V3Number& lhs); - V3Number& opRedXnor(const V3Number& lhs); V3Number& opCountBits(const V3Number& expr, const V3Number& ctrl1, const V3Number& ctrl2, const V3Number& ctrl3); V3Number& opCountOnes(const V3Number& lhs); @@ -366,10 +375,7 @@ public: V3Number& opAnd(const V3Number& lhs, const V3Number& rhs); V3Number& opChangeXor(const V3Number& lhs, const V3Number& rhs); V3Number& opXor(const V3Number& lhs, const V3Number& rhs); - V3Number& opXnor(const V3Number& lhs, const V3Number& rhs); V3Number& opOr(const V3Number& lhs, const V3Number& rhs); - V3Number& opRotR(const V3Number& lhs, const V3Number& rhs); - V3Number& opRotL(const V3Number& lhs, const V3Number& rhs); V3Number& opShiftR(const V3Number& lhs, const V3Number& rhs); V3Number& opShiftRS(const V3Number& lhs, const V3Number& rhs, // Arithmetic w/carry uint32_t lbits); diff --git a/src/V3Number_test.cpp b/src/V3Number_test.cpp index 894ba5228..74055f5c1 100644 --- a/src/V3Number_test.cpp +++ b/src/V3Number_test.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -47,8 +47,6 @@ void test(const string& lhss, const string& op, const string& rhss, const string gotnum.opRedAnd(lhnum); } else if (op == "redXor") { gotnum.opRedXor(lhnum); - } else if (op == "redXnor") { - gotnum.opRedXnor(lhnum); } else if (op == "concat") { gotnum.opConcat(lhnum, rhnum); } else if (op == "repl") { diff --git a/src/V3Options.cpp b/src/V3Options.cpp index 8ccbd5c56..fdc56aa08 100644 --- a/src/V3Options.cpp +++ b/src/V3Options.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -458,7 +458,7 @@ string V3Options::fileExists(const string& filename) { auto diriter = m_impp->m_dirMap.find(dir); if (diriter == m_impp->m_dirMap.end()) { // Read the listing - m_impp->m_dirMap.insert(std::make_pair(dir, std::set())); + m_impp->m_dirMap.emplace(dir, std::set()); diriter = m_impp->m_dirMap.find(dir); std::set* setp = &(diriter->second); @@ -1149,14 +1149,19 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char case 'c': m_oConst = flag; break; case 'd': m_oDedupe = flag; break; case 'e': m_oCase = flag; break; + // f case 'g': m_oGate = flag; break; + // h case 'i': m_oInline = flag; break; + // j case 'k': m_oSubstConst = flag; break; case 'l': m_oLife = flag; break; case 'm': m_oAssemble = flag; break; + // n o case 'p': m_public = !flag; break; // With -Op so flag=0, we want public on so few optimizations done + // q case 'r': m_oReorder = flag; break; case 's': m_oSplit = flag; break; case 't': m_oLifePost = flag; break; @@ -1229,7 +1234,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char } else if (!strcmp(sw, "-hierarchical-block") && (i + 1) < argc) { shift; V3HierarchicalBlockOption opt(argv[i]); - m_hierBlocks.insert(std::make_pair(opt.mangledName(), opt)); + m_hierBlocks.emplace(opt.mangledName(), opt); } else if (!strncmp(sw, "-I", 2)) { addIncDirUser(parseFileArg(optdir, string(sw + strlen("-I")))); } else if (!strcmp(sw, "-if-depth") && (i + 1) < argc) { @@ -1430,16 +1435,16 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char shift; parseOptsFile(fl, parseFileArg(optdir, argv[i]), false); } else if (!strcmp(sw, "-gdb")) { - // Used only in perl shell + // Processed only in bin/verilator shell } else if (!strcmp(sw, "-waiver-output") && (i + 1) < argc) { shift; m_waiverOutput = argv[i]; } else if (!strcmp(sw, "-rr")) { - // Used only in perl shell + // Processed only in bin/verilator shell } else if (!strcmp(sw, "-gdbbt")) { - // Used only in perl shell + // Processed only in bin/verilator shell } else if (!strcmp(sw, "-quiet-exit")) { - // Used only in perl shell + // Processed only in bin/verilator shell } else if (!strcmp(sw, "-mod-prefix") && (i + 1) < argc) { shift; m_modPrefix = argv[i]; @@ -1502,7 +1507,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char m_timeDefaultPrec = prec; m_timeOverridePrec = prec; } - } else if (!strcmp(sw, "-top-module") && (i + 1) < argc) { + } else if ((!strcmp(sw, "-top-module") || !strcmp(sw, "-top")) && (i + 1) < argc) { shift; m_topModule = argv[i]; } else if (!strcmp(sw, "-unused-regexp") && (i + 1) < argc) { @@ -1740,7 +1745,7 @@ void V3Options::showVersion(bool verbose) { if (!verbose) return; cout << endl; - cout << "Copyright 2003-2020 by Wilson Snyder. Verilator is free software; you can\n"; + cout << "Copyright 2003-2021 by Wilson Snyder. Verilator is free software; you can\n"; cout << "redistribute it and/or modify the Verilator internals under the terms of\n"; cout << "either the GNU Lesser General Public License Version 3 or the Perl Artistic\n"; cout << "License Version 2.0.\n"; @@ -1814,7 +1819,7 @@ void V3Options::setDebugSrcLevel(const string& srcfile, int level) { if (iter != m_debugSrcs.end()) { iter->second = level; } else { - m_debugSrcs.insert(make_pair(srcfile, level)); + m_debugSrcs.emplace(srcfile, level); } } @@ -1835,7 +1840,7 @@ void V3Options::setDumpTreeLevel(const string& srcfile, int level) { if (iter != m_dumpTrees.end()) { iter->second = level; } else { - m_dumpTrees.insert(make_pair(srcfile, level)); + m_dumpTrees.emplace(srcfile, level); } } diff --git a/src/V3Options.h b/src/V3Options.h index 1c5b05ad5..85d372a87 100644 --- a/src/V3Options.h +++ b/src/V3Options.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Order.cpp b/src/V3Order.cpp index 4060c3c54..c8509fa72 100644 --- a/src/V3Order.cpp +++ b/src/V3Order.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -164,7 +164,7 @@ public: return iter->second; } else { OrderMoveDomScope* domScopep = new OrderMoveDomScope(domainp, scopep); - s_dsMap.insert(make_pair(key, domScopep)); + s_dsMap.emplace(key, domScopep); return domScopep; } } @@ -184,7 +184,7 @@ inline std::ostream& operator<<(std::ostream& lhs, const OrderMoveDomScope& rhs) // Order information stored under each AstNode::user1p()... // Types of vertex we can create -enum WhichVertex : uint8_t { WV_STD, WV_PRE, WV_PORD, WV_POST, WV_SETL, WV_MAX }; +enum WhichVertex : uint8_t { WV_STD, WV_PRE, WV_PORD, WV_POST, WV_MAX }; class OrderUser final { // Stored in AstVarScope::user1p, a list of all the various vertices @@ -205,7 +205,6 @@ public: case WV_PRE: vertexp = new OrderVarPreVertex(graphp, scopep, varscp); break; case WV_PORD: vertexp = new OrderVarPordVertex(graphp, scopep, varscp); break; case WV_POST: vertexp = new OrderVarPostVertex(graphp, scopep, varscp); break; - case WV_SETL: vertexp = new OrderVarSettleVertex(graphp, scopep, varscp); break; default: varscp->v3fatalSrc("Bad case"); } m_vertexp[type] = vertexp; @@ -1569,8 +1568,6 @@ void OrderVisitor::processEdgeReport() { name += " {POST}"; } else if (dynamic_cast(itp)) { name += " {PORD}"; - } else if (dynamic_cast(itp)) { - name += " {STL}"; } std::ostringstream os; os.setf(std::ios::left); diff --git a/src/V3Order.h b/src/V3Order.h index 35c04cc57..1d55815aa 100644 --- a/src/V3Order.h +++ b/src/V3Order.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3OrderGraph.h b/src/V3OrderGraph.h index 579ea70bb..c235b8bb9 100644 --- a/src/V3OrderGraph.h +++ b/src/V3OrderGraph.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -26,7 +26,6 @@ // OrderVarPreVertex // OrderVarPostVertex // OrderVarPordVertex -// OrderVarSettleVertex // // V3GraphEdge // OrderEdge @@ -296,24 +295,6 @@ public: virtual string dotColor() const override { return "NavyBlue"; } virtual bool domainMatters() override { return false; } }; -class OrderVarSettleVertex final : public OrderVarVertex { - OrderVarSettleVertex(V3Graph* graphp, const OrderVarSettleVertex& old) - : OrderVarVertex{graphp, old} {} - -public: - OrderVarSettleVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varScp) - : OrderVarVertex{graphp, scopep, varScp} {} - virtual ~OrderVarSettleVertex() override = default; - virtual OrderVarSettleVertex* clone(V3Graph* graphp) const override { - return new OrderVarSettleVertex(graphp, *this); - } - virtual OrderVEdgeType type() const override { return OrderVEdgeType::VERTEX_VARSETTLE; } - virtual string name() const override { - return (cvtToHex(varScp()) + " STL\\n " + varScp()->name()); - } - virtual string dotColor() const override { return "PowderBlue"; } - virtual bool domainMatters() override { return false; } -}; //###################################################################### //--- Following only under the move graph, not the main graph diff --git a/src/V3Os.cpp b/src/V3Os.cpp index b6d7375e5..df66d97de 100644 --- a/src/V3Os.cpp +++ b/src/V3Os.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -53,8 +53,10 @@ # ifndef WIFEXITED # ifdef __MINGW32__ # define WIFEXITED(w) (((w) & 0xC0000000) == 0) +# define WEXITSTATUS(w) ((w) & ~0xC0000000) # else # define WIFEXITED(w) (((w) & 0377) == 0) +# define WEXITSTATUS(w) (((w) >> 8) & 0377) # endif # endif #else diff --git a/src/V3Os.h b/src/V3Os.h index a1eef9b86..6c519f8b2 100644 --- a/src/V3Os.h +++ b/src/V3Os.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Param.cpp b/src/V3Param.cpp index df9e60c1e..89df4b371 100644 --- a/src/V3Param.cpp +++ b/src/V3Param.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -60,7 +60,7 @@ #include #include -#include +#include #include //###################################################################### @@ -70,8 +70,10 @@ class ParameterizedHierBlocks final { typedef std::multimap HierBlockOptsByOrigName; typedef HierBlockOptsByOrigName::const_iterator HierMapIt; typedef std::map HierBlockModMap; - typedef std::map ParamConstMap; - typedef std::map ParamsMap; + typedef std::map> ParamConstMap; + typedef std::map GParamsMap; // key:parameter name value:parameter + typedef std::map HierParamsMap; + typedef std::map ModParamsMap; // key:module name // MEMBERS // key:Original module name, value:HiearchyBlockOption* @@ -81,10 +83,103 @@ class ParameterizedHierBlocks final { // key:mangled module name, value:AstNodeModule* HierBlockModMap m_hierBlockMod; // Overridden parameters of the hierarchical block - ParamsMap m_params; + HierParamsMap m_hierParams; + ModParamsMap m_modParams; // Parameter variables of hierarchical blocks // METHODS VL_DEBUG_FUNC; // Declare debug() + +public: + ParameterizedHierBlocks(const V3HierBlockOptSet& hierOpts, AstNetlist* nodep) { + for (const auto& hierOpt : hierOpts) { + m_hierBlockOptsByOrigName.insert( + std::make_pair(hierOpt.second.origName(), &hierOpt.second)); + const V3HierarchicalBlockOption::ParamStrMap& params = hierOpt.second.params(); + ParamConstMap& consts = m_hierParams[&hierOpt.second]; + for (V3HierarchicalBlockOption::ParamStrMap::const_iterator pIt = params.begin(); + pIt != params.end(); ++pIt) { + std::unique_ptr constp{AstConst::parseParamLiteral( + new FileLine(FileLine::EmptySecret()), pIt->second)}; + UASSERT(constp, pIt->second << " is not a valid parameter literal"); + const bool inserted = consts.emplace(pIt->first, std::move(constp)).second; + UASSERT(inserted, pIt->first << " is already added"); + } + // origName may be already registered, but it's fine. + m_modParams.insert({hierOpt.second.origName(), {}}); + } + for (AstNodeModule* modp = nodep->modulesp(); modp; + modp = VN_CAST(modp->nextp(), NodeModule)) { + if (hierOpts.find(modp->prettyName()) != hierOpts.end()) { + m_hierBlockMod.emplace(modp->name(), modp); + } + const auto defParamIt = m_modParams.find(modp->name()); + if (defParamIt != m_modParams.end()) { + // modp is the original of parameterized hierarchical block + for (AstNode* stmtp = modp->stmtsp(); stmtp; stmtp = stmtp->nextp()) { + if (AstVar* varp = VN_CAST(stmtp, Var)) { + if (varp->isGParam()) defParamIt->second.emplace(varp->name(), varp); + } + } + } + } + } + AstNodeModule* findByParams(const string& origName, AstPin* firstPinp, + const AstNodeModule* modp) { + if (m_hierBlockOptsByOrigName.find(origName) == m_hierBlockOptsByOrigName.end()) { + return nullptr; + } + // This module is a hierarchical block. Need to replace it by the protect-lib wrapper. + const std::pair candidates + = m_hierBlockOptsByOrigName.equal_range(origName); + const auto paramsIt = m_modParams.find(origName); + UASSERT_OBJ(paramsIt != m_modParams.end(), modp, origName << " must be registered"); + HierMapIt hierIt; + for (hierIt = candidates.first; hierIt != candidates.second; ++hierIt) { + bool found = true; + size_t paramIdx = 0; + const ParamConstMap& params = m_hierParams[hierIt->second]; + UASSERT(params.size() == hierIt->second->params().size(), "not match"); + for (AstPin* pinp = firstPinp; pinp; pinp = VN_CAST(pinp->nextp(), Pin)) { + if (!pinp->exprp()) continue; + UASSERT_OBJ(!pinp->modPTypep(), pinp, + "module with type parameter must not be a hierarchical block"); + if (AstVar* modvarp = pinp->modVarp()) { + AstConst* constp = VN_CAST(pinp->exprp(), Const); + UASSERT_OBJ(constp, pinp, + "parameter for a hierarchical block must have been constified"); + const auto paramIt = paramsIt->second.find(modvarp->name()); + UASSERT_OBJ(paramIt != paramsIt->second.end(), modvarp, "must be registered"); + AstConst* defValuep = VN_CAST(paramIt->second->valuep(), Const); + if (defValuep && areSame(constp, defValuep)) { + UINFO(5, "Setting default value of " << constp << " to " << modvarp + << std::endl); + continue; // Skip this parameter because setting the same value + } + const auto pIt = vlstd::as_const(params).find(modvarp->name()); + UINFO(5, "Comparing " << modvarp->name() << " " << constp << std::endl); + if (pIt == params.end() || paramIdx >= params.size() + || !areSame(constp, pIt->second.get())) { + found = false; + break; + } + UINFO(5, "Matched " << modvarp->name() << " " << constp << " and " + << pIt->second.get() << std::endl); + ++paramIdx; + } + } + if (found && paramIdx == hierIt->second->params().size()) break; + } + UASSERT_OBJ(hierIt != candidates.second, firstPinp, "No protect-lib wrapper found"); + // parameter settings will be removed in the bottom of caller visitCell(). + const HierBlockModMap::const_iterator modIt + = m_hierBlockMod.find(hierIt->second->mangledName()); + UASSERT_OBJ(modIt != m_hierBlockMod.end(), firstPinp, + hierIt->second->mangledName() << " is not found"); + + const auto it = vlstd::as_const(m_hierBlockMod).find(hierIt->second->mangledName()); + if (it == m_hierBlockMod.end()) return nullptr; + return it->second; + } static bool areSame(AstConst* pinValuep, AstConst* hierOptParamp) { if (pinValuep->isString()) { return pinValuep->num().toString() == hierOptParamp->num().toString(); @@ -117,82 +212,6 @@ class ParameterizedHierBlocks final { return isEq.isNeqZero(); } } - -public: - ParameterizedHierBlocks(const V3HierBlockOptSet& hierOpts, AstNetlist* nodep) { - for (const auto& hierOpt : hierOpts) { - m_hierBlockOptsByOrigName.insert( - std::make_pair(hierOpt.second.origName(), &hierOpt.second)); - const V3HierarchicalBlockOption::ParamStrMap& params = hierOpt.second.params(); - ParamConstMap& consts = m_params[&hierOpt.second]; - for (V3HierarchicalBlockOption::ParamStrMap::const_iterator pIt = params.begin(); - pIt != params.end(); ++pIt) { - AstConst* constp = AstConst::parseParamLiteral( - new FileLine(FileLine::EmptySecret()), pIt->second); - UASSERT(constp, pIt->second << " is not a valid parameter literal"); - const bool inserted = consts.insert(std::make_pair(pIt->first, constp)).second; - UASSERT(inserted, pIt->first << " is already added"); - } - } - for (AstNodeModule* modp = nodep->modulesp(); modp; - modp = VN_CAST(modp->nextp(), NodeModule)) { - if (hierOpts.find(modp->prettyName()) != hierOpts.end()) { - m_hierBlockMod.insert(std::make_pair(modp->name(), modp)); - } - } - } - ~ParameterizedHierBlocks() { - for (ParamsMap::const_iterator it = m_params.begin(); it != m_params.end(); ++it) { - for (const auto& pItr : it->second) { delete pItr.second; } - } - } - AstNodeModule* findByParams(const string& origName, AstPin* firstPinp, - const AstNodeModule* modp) { - if (m_hierBlockOptsByOrigName.find(origName) == m_hierBlockOptsByOrigName.end()) { - return nullptr; - } - // This module is a hierarchical block. Need to replace it by the protect-lib wrapper. - const std::pair candidates - = m_hierBlockOptsByOrigName.equal_range(origName); - HierMapIt hierIt; - for (hierIt = candidates.first; hierIt != candidates.second; ++hierIt) { - bool found = true; - size_t paramIdx = 0; - const ParamConstMap& params = m_params[hierIt->second]; - UASSERT(params.size() == hierIt->second->params().size(), "not match"); - for (AstPin* pinp = firstPinp; pinp; pinp = VN_CAST(pinp->nextp(), Pin)) { - if (!pinp->exprp()) continue; - UASSERT_OBJ(!pinp->modPTypep(), pinp, - "module with type parameter must not be a hierarchical block"); - if (AstVar* modvarp = pinp->modVarp()) { - AstConst* constp = VN_CAST(pinp->exprp(), Const); - UASSERT_OBJ(constp, pinp, - "parameter for a hierarchical block must have been constified"); - const auto pIt = vlstd::as_const(params).find(modvarp->name()); - UINFO(5, "Comparing " << modvarp->name() << " " << constp << std::endl); - if (pIt == params.end() || paramIdx >= params.size() - || !areSame(constp, pIt->second)) { - found = false; - break; - } - UINFO(5, "Matched " << modvarp->name() << " " << constp << " and " - << pIt->second << std::endl); - ++paramIdx; - } - } - if (found && paramIdx == hierIt->second->params().size()) break; - } - UASSERT_OBJ(hierIt != candidates.second, firstPinp, "No protect-lib wrapper found"); - // parameter settings will be removed in the bottom of caller visitCell(). - const HierBlockModMap::const_iterator modIt - = m_hierBlockMod.find(hierIt->second->mangledName()); - UASSERT_OBJ(modIt != m_hierBlockMod.end(), firstPinp, - hierIt->second->mangledName() << " is not found"); - - const auto it = vlstd::as_const(m_hierBlockMod).find(hierIt->second->mangledName()); - if (it == m_hierBlockMod.end()) return nullptr; - return it->second; - } }; //###################################################################### @@ -244,6 +263,10 @@ class ParamProcessor final { // Database to get protect-lib wrapper that matches parameters in hierarchical Verilation ParameterizedHierBlocks m_hierBlocks; + // Default parameter values key:parameter name, value:default value (can be nullptr) + typedef std::map DefaultValueMap; + // Default parameter values of hierarchical blocks + std::map m_defaultParameterValues; // METHODS VL_DEBUG_FUNC; // Declare debug() @@ -307,21 +330,17 @@ class ParamProcessor final { } return string("z") + cvtToStr(num); } - string moduleCalcName(AstNodeModule* srcModp, AstPin* paramsp, const string& longname) { + string moduleCalcName(AstNodeModule* srcModp, const string& longname) { string newname = longname; - if (longname.length() > 30 || srcModp->hierBlock()) { + if (longname.length() > 30) { const auto iter = m_longMap.find(longname); if (iter != m_longMap.end()) { newname = iter->second; } else { - if (srcModp->hierBlock()) { - newname = parametrizedHierBlockName(srcModp, paramsp); - } else { - newname = srcModp->name(); - // We use all upper case above, so lower here can't conflict - newname += "__pi" + cvtToStr(++m_longId); - } - m_longMap.insert(make_pair(longname, newname)); + newname = srcModp->name(); + // We use all upper case above, so lower here can't conflict + newname += "__pi" + cvtToStr(++m_longId); + m_longMap.emplace(longname, newname); } } UINFO(4, "Name: " << srcModp->name() << "->" << longname << "->" << newname << endl); @@ -349,12 +368,12 @@ class ParamProcessor final { AstVar* oldvarp = varp->clonep(); // UINFO(8,"Clone list 0x"< 0x"<<(uint32_t)varp<insert(make_pair(oldvarp, varp)); + clonemapp->emplace(oldvarp, varp); } } else if (AstParamTypeDType* ptp = VN_CAST(stmtp, ParamTypeDType)) { if (ptp->isGParam()) { AstParamTypeDType* oldptp = ptp->clonep(); - clonemapp->insert(make_pair(oldptp, ptp)); + clonemapp->emplace(oldptp, ptp); } } } @@ -383,7 +402,7 @@ class ParamProcessor final { for (AstNode* stmtp = modp->stmtsp(); stmtp; stmtp = stmtp->nextp()) { if (AstVar* varp = VN_CAST(stmtp, Var)) { if (varp->isIO() || varp->isGParam() || varp->isIfaceRef()) { - nameToPin.insert(make_pair(varp->name(), varp)); + nameToPin.emplace(varp->name(), varp); } } } @@ -421,17 +440,61 @@ class ParamProcessor final { return false; } - string parametrizedHierBlockName(const AstNodeModule* modp, AstPin* paramPinsp) const { - VHashSha256 hash; - // Calculate hash using module name, parameter name, and parameter value - // The hash is used as the module suffix to find a module name that is unique in the design - hash.insert(modp->name()); + string parameterizedHierBlockName(AstNodeModule* modp, AstPin* paramPinsp) { + // Create a unique name in the following steps + // - Make a long name that includes all parameters, that appear + // in the alphabetical order. + // - Hash the long name to get valid Verilog symbol + UASSERT_OBJ(modp->hierBlock(), modp, "should be used for hierarchical block"); + + std::map pins; for (AstPin* pinp = paramPinsp; pinp; pinp = VN_CAST(pinp->nextp(), Pin)) { - if (AstVar* varp = pinp->modVarp()) hash.insert(varp->name()); - if (AstConst* constp = VN_CAST(pinp->exprp(), Const)) { - hash.insert(constp->num().ascii(false)); + checkSupportedParam(modp, pinp); + if (AstVar* varp = pinp->modVarp()) { + if (!pinp->exprp()) continue; + if (varp->isGParam()) { + AstConst* constp = VN_CAST(pinp->exprp(), Const); + pins.emplace(varp->name(), constp); + } } } + + auto paramsIt = m_defaultParameterValues.find(modp); + if (paramsIt == m_defaultParameterValues.end()) { // Not cached yet, so check parameters + // Using map with key=string so that we can scan it in deterministic order + DefaultValueMap params; + for (AstNode* stmtp = modp->stmtsp(); stmtp; stmtp = stmtp->nextp()) { + if (AstVar* varp = VN_CAST(stmtp, Var)) { + if (varp->isGParam()) { + AstConst* constp = VN_CAST(varp->valuep(), Const); + // constp can be nullptr if the parameter is not used to instantiate sub + // module. varp->valuep() is not contified yet in the case. + // nullptr means that the parameter is using some default value. + params.emplace(varp->name(), constp); + } + } + } + paramsIt = m_defaultParameterValues.emplace(modp, std::move(params)).first; + } + if (paramsIt->second.empty()) return modp->name(); // modp has no parameter + + string longname = modp->name(); + for (auto&& defaultValue : paramsIt->second) { + auto pinIt = pins.find(defaultValue.first); + AstConst* constp = pinIt == pins.end() ? defaultValue.second : pinIt->second; + // This longname is not valid as verilog symbol, but ok, because it will be hashed + longname += "_" + defaultValue.first + "="; + // constp can be nullptr + if (constp) longname += constp->num().ascii(false); + } + + auto iter = m_longMap.find(longname); + if (iter != m_longMap.end()) return iter->second; // Already calculated + + VHashSha256 hash; + // Calculate hash using longname + // The hash is used as the module suffix to find a module name that is unique in the design + hash.insert(longname); while (true) { // Copy VHashSha256 just in case of hash collision VHashSha256 hashStrGen = hash; @@ -442,7 +505,10 @@ class ParamProcessor final { // Don't use '__' not to be encoded when this module is loaded later by Verilator if (newName.at(newName.size() - 1) != '_') newName += '_'; newName += hashStr.substr(0, i); - if (!moduleExists(newName)) return newName; + if (!moduleExists(newName)) { + m_longMap.emplace(longname, newName); + return newName; + } } // Hash collision. maybe just v3error is practically enough hash.insert(V3Os::trueRandom(64)); @@ -474,7 +540,7 @@ class ParamProcessor final { } insertp->addNextHere(newmodp); - m_modNameMap.insert(make_pair(newmodp->name(), ModInfo(newmodp))); + m_modNameMap.emplace(newmodp->name(), ModInfo(newmodp)); auto iter = m_modNameMap.find(newname); CloneMap* clonemapp = &(iter->second.m_cloneMap); UINFO(4, " De-parameterize to new: " << newmodp << endl); @@ -501,14 +567,18 @@ class ParamProcessor final { // DOES clone() so must be finished with module clonep() before here for (AstPin* pinp = paramsp; pinp; pinp = VN_CAST(pinp->nextp(), Pin)) { if (pinp->exprp()) { - if (newmodp->hierBlock()) checkSupportedParam(newmodp, pinp); if (AstVar* modvarp = pinp->modVarp()) { AstNode* newp = pinp->exprp(); // Const or InitArray + AstConst* exprp = VN_CAST(newp, Const); + AstConst* origp = VN_CAST(modvarp->valuep(), Const); + const bool overridden + = !(origp && ParameterizedHierBlocks::areSame(exprp, origp)); // Remove any existing parameter if (modvarp->valuep()) modvarp->valuep()->unlinkFrBack()->deleteTree(); // Set this parameter to value requested by cell + UINFO(9, " set param " << modvarp << " = " << newp << endl); modvarp->valuep(newp->cloneTree(false)); - modvarp->overriddenParam(true); + modvarp->overriddenParam(overridden); } else if (AstParamTypeDType* modptp = pinp->modPTypep()) { AstNodeDType* dtypep = VN_CAST(pinp->exprp(), NodeDType); UASSERT_OBJ(dtypep, pinp, "unlinked param dtype"); @@ -684,8 +754,13 @@ public: if (nodep->recursive()) any_overrides = true; if (debug() > 8) nodep->paramsp()->dumpTreeAndNext(cout, "-cellparams: "); - for (AstPin* pinp = nodep->paramsp(); pinp; pinp = VN_CAST(pinp->nextp(), Pin)) { - cellPinCleanup(nodep, pinp, srcModp, longname /*ref*/, any_overrides /*ref*/); + if (srcModp->hierBlock()) { + longname = parameterizedHierBlockName(srcModp, nodep->paramsp()); + any_overrides = longname != srcModp->name(); + } else { + for (AstPin* pinp = nodep->paramsp(); pinp; pinp = VN_CAST(pinp->nextp(), Pin)) { + cellPinCleanup(nodep, pinp, srcModp, longname /*ref*/, any_overrides /*ref*/); + } } IfaceRefRefs ifaceRefRefs; cellInterfaceCleanup(nodep, srcModp, longname /*ref*/, any_overrides /*ref*/, @@ -693,22 +768,22 @@ public: if (!any_overrides) { UINFO(8, "Cell parameters all match original values, skipping expansion.\n"); - } else if (AstNodeModule* modp + } else if (AstNodeModule* paramedModp = m_hierBlocks.findByParams(srcModp->name(), nodep->paramsp(), m_modp)) { - nodep->modp(modp); - nodep->modName(modp->name()); - modp->dead(false); + nodep->modp(paramedModp); + nodep->modName(paramedModp->name()); + paramedModp->dead(false); // We need to relink the pins to the new module - relinkPinsByName(nodep->pinsp(), modp); + relinkPinsByName(nodep->pinsp(), paramedModp); } else { - string newname = moduleCalcName(srcModp, nodep->paramsp(), longname); + string newname = srcModp->hierBlock() ? longname : moduleCalcName(srcModp, longname); const ModInfo* modInfop = moduleFindOrClone(srcModp, nodep, nodep->paramsp(), newname, ifaceRefRefs); // Have child use this module instead. nodep->modp(modInfop->m_modp); nodep->modName(newname); // We need to relink the pins to the new module - relinkPins(&(modInfop->m_cloneMap), nodep->pinsp()); + relinkPinsByName(nodep->pinsp(), modInfop->m_modp); UINFO(8, " Done with " << modInfop->m_modp << endl); } @@ -722,7 +797,7 @@ public: } // CONSTRUCTORS - ParamProcessor(AstNetlist* nodep) + explicit ParamProcessor(AstNetlist* nodep) : m_hierBlocks{v3Global.opt.hierBlocks(), nodep} { for (AstNodeModule* modp = nodep->modulesp(); modp; modp = VN_CAST(modp->nextp(), NodeModule)) { @@ -758,7 +833,7 @@ class ParamVisitor final : public AstNVisitor { UASSERT_OBJ(nodep->modp(), nodep, "Not linked?"); m_processor.cellDeparam(nodep, m_modp, hierName); // Remember to process the child module at the end of the module - m_todoModps.insert(make_pair(nodep->modp()->level(), nodep->modp())); + m_todoModps.emplace(nodep->modp()->level(), nodep->modp()); } void visitModules() { // Loop on all modules left to process @@ -784,12 +859,10 @@ class ParamVisitor final : public AstNVisitor { string fullName(m_modp->hierName()); if (const string* genHierNamep = (string*)cellp->user5p()) { fullName += *genHierNamep; - } - visitCellDeparam(cellp, fullName); - if (const string* genHierNamep = (string*)cellp->user5p()) { cellp->user5p(nullptr); VL_DO_DANGLING(delete genHierNamep, genHierNamep); } + VL_DO_DANGLING(visitCellDeparam(cellp, fullName), cellp); } } } @@ -804,16 +877,32 @@ class ParamVisitor final : public AstNVisitor { virtual void visit(AstNodeModule* nodep) override { if (nodep->dead()) { UINFO(4, " MOD-dead. " << nodep << endl); // Marked by LinkDot + return; } else if (nodep->recursiveClone()) { // Fake, made for recursive elimination UINFO(4, " MOD-recursive-dead. " << nodep << endl); nodep->dead(true); // So Dead checks won't count references to it - } else if (m_modp) { + return; + } + // + if (!nodep->dead() && VN_IS(nodep, Class)) { + for (AstNode* stmtp = nodep->stmtsp(); stmtp; stmtp = stmtp->nextp()) { + if (AstVar* varp = VN_CAST(stmtp, Var)) { + if (varp->isParam()) { + varp->v3warn(E_UNSUPPORTED, "Unsupported: class parameters"); + } + } + } + } + // + if (m_modp) { UINFO(4, " MOD-under-MOD. " << nodep << endl); + iterateChildren(nodep); } else if (nodep->level() <= 2 // Haven't added top yet, so level 2 is the top + || VN_IS(nodep, Class) // Nor moved classes || VN_IS(nodep, Package)) { // Likewise haven't done wrapTopPackages yet // Add request to END of modules left to process - m_todoModps.insert(make_pair(nodep->level(), nodep)); + m_todoModps.emplace(nodep->level(), nodep); m_generateHierName = ""; visitModules(); } else if (nodep->user5()) { @@ -830,6 +919,14 @@ class ParamVisitor final : public AstNVisitor { m_cellps.push_back(nodep); } + virtual void visit(AstClassRefDType* nodep) override { + if (nodep->paramsp()) { + nodep->paramsp()->v3warn(E_UNSUPPORTED, "Unsupported: parameterized classes"); + pushDeletep(nodep->paramsp()->unlinkFrBackWithNext()); + } + iterateChildren(nodep); + } + // Make sure all parameters are constantified virtual void visit(AstVar* nodep) override { if (nodep->user5SetOnce()) return; // Process once @@ -1026,10 +1123,9 @@ class ParamVisitor final : public AstNVisitor { // Note this clears nodep->genforp(), so begin is no longer special } } else { - string rootHierName(m_generateHierName); + VL_RESTORER(m_generateHierName); m_generateHierName += "." + nodep->prettyName(); iterateChildren(nodep); - m_generateHierName = rootHierName; } } virtual void visit(AstGenFor* nodep) override { // LCOV_EXCL_LINE diff --git a/src/V3Param.h b/src/V3Param.h index 750e4177c..a785602fb 100644 --- a/src/V3Param.h +++ b/src/V3Param.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Parse.h b/src/V3Parse.h index 198af1757..5fe39055d 100644 --- a/src/V3Parse.h +++ b/src/V3Parse.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3ParseGrammar.cpp b/src/V3ParseGrammar.cpp index e49b8f5d8..8b617181a 100644 --- a/src/V3ParseGrammar.cpp +++ b/src/V3ParseGrammar.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -95,14 +95,15 @@ AstRange* V3ParseGrammar::scrubRange(AstNodeRange* nrangep) { nextp = VN_CAST(nodep->nextp(), NodeRange); if (!VN_IS(nodep, Range)) { nodep->v3error( - "Unsupported or syntax error: Unsized range in cell or other declaration"); + "Unsupported or syntax error: Unsized range in instance or other declaration"); nodep->unlinkFrBack(); VL_DO_DANGLING(nodep->deleteTree(), nodep); } } if (nrangep && nrangep->nextp()) { // Not supported by at least 2 of big 3 - nrangep->nextp()->v3warn(E_UNSUPPORTED, "Unsupported: Multidimensional cells/interfaces."); + nrangep->nextp()->v3warn(E_UNSUPPORTED, + "Unsupported: Multidimensional instances/interfaces."); nrangep->nextp()->unlinkFrBackWithNext()->deleteTree(); } return VN_CAST(nrangep, Range); diff --git a/src/V3ParseImp.cpp b/src/V3ParseImp.cpp index e7800e0fd..e19325194 100644 --- a/src/V3ParseImp.cpp +++ b/src/V3ParseImp.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3ParseImp.h b/src/V3ParseImp.h index eb5dc8a6f..5b4bf7c48 100644 --- a/src/V3ParseImp.h +++ b/src/V3ParseImp.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2009-2020 by Wilson Snyder. This program is free software; you +// Copyright 2009-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -50,7 +50,7 @@ struct VMemberQualifiers { struct { uint32_t m_local : 1; // Local class item (ignored until warning implemented) uint32_t m_protected : 1; // Protected class item (ignored until warning implemented) - uint32_t m_rand : 1; // Rand property/member qualifier (ignored until supported) + uint32_t m_rand : 1; // Rand property/member qualifier uint32_t m_randc : 1; // Randc property/member qualifier (ignored until supported) uint32_t m_virtual : 1; // Virtual property/method qualifier uint32_t m_automatic : 1; // Automatic property/method qualifier @@ -83,8 +83,11 @@ struct VMemberQualifiers { } void applyToNodes(AstVar* nodesp) const { for (AstVar* nodep = nodesp; nodep; nodep = VN_CAST(nodep->nextp(), Var)) { - // Ignored for now: m_rand - // Ignored for now: m_randc + if (m_randc) { + nodep->v3warn(RANDC, "Unsupported: Converting 'randc' to 'rand'"); + nodep->isRand(true); + } + if (m_rand) nodep->isRand(true); if (m_local) nodep->isHideLocal(true); if (m_protected) nodep->isHideProtected(true); if (m_automatic) nodep->lifetime(VLifetime::AUTOMATIC); diff --git a/src/V3ParseLex.cpp b/src/V3ParseLex.cpp index 04bfa9b90..eedae87c1 100644 --- a/src/V3ParseLex.cpp +++ b/src/V3ParseLex.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3ParseSym.h b/src/V3ParseSym.h index 42045f273..80412379d 100644 --- a/src/V3ParseSym.h +++ b/src/V3ParseSym.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2009-2020 by Wilson Snyder. This program is free software; you +// Copyright 2009-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -111,7 +111,7 @@ public: m_symCurrentp = symp; } void popScope(AstNode* nodep) { - if (symCurrentp()->nodep() != nodep) { + if (VL_UNCOVERABLE(symCurrentp()->nodep() != nodep)) { // LCOV_EXCL_START if (debug()) { showUpward(); dump(cout, "-mism: "); @@ -120,19 +120,19 @@ public: << " but parser thinks ending " << nodep->prettyTypeName()); return; - } + } // LCOV_EXCL_STOP m_sympStack.pop_back(); UASSERT_OBJ(!m_sympStack.empty(), nodep, "symbol stack underflow"); m_symCurrentp = m_sympStack.back(); } - void showUpward() { + void showUpward() { // LCOV_EXCL_START UINFO(1, "ParseSym Stack:\n"); for (auto it = m_sympStack.rbegin(); it != m_sympStack.rend(); ++it) { VSymEnt* symp = *it; UINFO(1, " " << symp->nodep() << endl); } UINFO(1, "ParseSym Current: " << symCurrentp()->nodep() << endl); - } + } // LCOV_EXCL_STOP void dump(std::ostream& os, const string& indent = "") { m_syms.dump(os, indent); } AstNode* findEntUpward(const string& name) const { // Lookup the given string as an identifier, return type of the id, scanning upward diff --git a/src/V3Partition.cpp b/src/V3Partition.cpp index c48f8737a..bf3c0b410 100644 --- a/src/V3Partition.cpp +++ b/src/V3Partition.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Partition.h b/src/V3Partition.h index 0a91c6010..32006e89e 100644 --- a/src/V3Partition.h +++ b/src/V3Partition.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3PartitionGraph.h b/src/V3PartitionGraph.h index 74276c92d..0585f92f7 100644 --- a/src/V3PartitionGraph.h +++ b/src/V3PartitionGraph.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3PreLex.h b/src/V3PreLex.h index ee801421f..c72ea0592 100644 --- a/src/V3PreLex.h +++ b/src/V3PreLex.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2000-2020 by Wilson Snyder. This program is free software; you +// Copyright 2000-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3PreLex.l b/src/V3PreLex.l index aa331c629..dbe22e3f6 100644 --- a/src/V3PreLex.l +++ b/src/V3PreLex.l @@ -5,7 +5,7 @@ * ************************************************************************** * - * Copyright 2003-2020 by Wilson Snyder. This program is free software; you + * Copyright 2003-2021 by Wilson Snyder. This program is free software; you * can redistribute it and/or modify it under the terms of either the * GNU Lesser General Public License Version 3 or the Perl Artistic License * Version 2.0. @@ -55,7 +55,6 @@ void yyourtext(const char* textp, size_t size) { // Use this to break between tokens whereever not return'ing a token (e.g. skipping inside lexer) #define FL_BRK (LEXP->curFilelinep()->startToken()) -// Prevent conflicts from perl version static void linenoInc() { LEXP->linenoInc(); } static bool pedantic() { return LEXP->m_pedantic; } static void yyerror(char* msg) { LEXP->curFilelinep()->v3error(msg); } diff --git a/src/V3PreProc.cpp b/src/V3PreProc.cpp index 122385e8f..c62eb7ec1 100644 --- a/src/V3PreProc.cpp +++ b/src/V3PreProc.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2000-2020 by Wilson Snyder. This program is free software; you +// Copyright 2000-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -344,7 +344,7 @@ void V3PreProcImp::define(FileLine* fl, const string& name, const string& value, } undef(name); } - m_defines.insert(make_pair(name, VDefine(fl, value, params, cmdline))); + m_defines.emplace(name, VDefine(fl, value, params, cmdline)); } } @@ -1317,7 +1317,6 @@ int V3PreProcImp::getStateToken() { // Convert any newlines to spaces, so we don't get a // multiline "..." without \ escapes. // The spec is silent about this either way; simulators vary - string::size_type pos; std::replace(out.begin(), out.end(), '\n', ' '); unputString(string("\"") + out + "\""); statePop(); diff --git a/src/V3PreProc.h b/src/V3PreProc.h index 39c7dbb48..a51dab1bf 100644 --- a/src/V3PreProc.h +++ b/src/V3PreProc.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2000-2020 by Wilson Snyder. This program is free software; you +// Copyright 2000-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3PreShell.cpp b/src/V3PreShell.cpp index e2f1042dd..66b7d5f1c 100644 --- a/src/V3PreShell.cpp +++ b/src/V3PreShell.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2004-2020 by Wilson Snyder. This program is free software; you +// Copyright 2004-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3PreShell.h b/src/V3PreShell.h index 3428a8a88..b0f9986aa 100644 --- a/src/V3PreShell.h +++ b/src/V3PreShell.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2004-2020 by Wilson Snyder. This program is free software; you +// Copyright 2004-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Premit.cpp b/src/V3Premit.cpp index ac5582b4c..465bc93b5 100644 --- a/src/V3Premit.cpp +++ b/src/V3Premit.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Premit.h b/src/V3Premit.h index 8d798665c..d2ea432dd 100644 --- a/src/V3Premit.h +++ b/src/V3Premit.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3ProtectLib.cpp b/src/V3ProtectLib.cpp index 188a5e8f3..af6e08918 100644 --- a/src/V3ProtectLib.cpp +++ b/src/V3ProtectLib.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -135,20 +135,18 @@ private: "See instructions in your simulator for how" " to use DPI libraries\n"); - bool timescaleShown = false; - if (v3Global.opt.hierChild() && !modp->timeunit().isNone()) { - // Emit timescale for hierarhical verilation - timescaleShown = true; - txtp->addText(fl, string("`timescale ") + modp->timeunit().ascii() + "/" - + v3Global.rootp()->timeprecision().ascii() + "\n\n"); - } // Module declaration m_modPortsp = new AstTextBlock(fl, "module " + m_libName + " (\n", false, true); txtp->addNodep(m_modPortsp); txtp->addText(fl, ");\n\n"); // Timescale - if (!timescaleShown) { + if (v3Global.opt.hierChild() && v3Global.rootp()->timescaleSpecified()) { + // Emit timescale for hierarhical verilation if input HDL specifies timespec + txtp->addText(fl, string("timeunit ") + modp->timeunit().ascii() + ";\n"); + txtp->addText(fl, string("timeprecision ") + +v3Global.rootp()->timeprecision().ascii() + + ";\n"); + } else { addComment(txtp, fl, "Precision of submodule" " (commented out to avoid requiring timescale on all modules)"); @@ -388,10 +386,6 @@ private: virtual void visit(AstVar* nodep) override { if (!nodep->isIO()) return; - if (VN_IS(nodep->dtypep(), UnpackArrayDType)) { - nodep->v3warn(E_UNSUPPORTED, "Unsupported: unpacked arrays with protect-lib on " - << nodep->prettyNameQ()); - } if (nodep->direction() == VDirection::INPUT) { if (nodep->isUsedClock() || nodep->attrClocker() == VVarAttrClocker::CLOCKER_YES) { UASSERT_OBJ(m_hasClk, nodep, "checkIfClockExists() didn't find this clock"); @@ -410,13 +404,7 @@ private: virtual void visit(AstNode*) override {} string cInputConnection(AstVar* varp) { - string frstmt; - string ket; - bool useSetWSvlv = V3Task::dpiToInternalFrStmt(varp, varp->name(), frstmt, ket); - if (useSetWSvlv) { - return frstmt + ket + " handlep__V->" + varp->name() + ", " + varp->name() + ");\n"; - } - return "handlep__V->" + varp->name() + " = " + frstmt + ket + ";\n"; + return V3Task::assignDpiToInternal("handlep__V->" + varp->name(), varp); } void handleClock(AstVar* varp) { @@ -445,6 +433,13 @@ private: void handleInput(AstVar* varp) { m_modPortsp->addNodep(varp->cloneTree(false)); } + static void addLocalVariable(AstTextBlock* textp, AstVar* varp, const char* suffix) { + AstVar* newVarp + = new AstVar(varp->fileline(), AstVarType::VAR, varp->name() + suffix, varp->dtypep()); + textp->addNodep(newVarp); + textp->addText(varp->fileline(), ";\n"); + } + void handleOutput(AstVar* varp) { FileLine* fl = varp->fileline(); m_modPortsp->addNodep(varp->cloneTree(false)); @@ -455,18 +450,11 @@ private: m_seqParamsp->addText(fl, varp->name() + "_tmp__V\n"); } - AstNodeDType* comboDtypep = varp->dtypep()->cloneTree(false); - m_comboDeclsp->addNodep(comboDtypep); - m_comboDeclsp->addText(fl, " " + varp->name() + "_combo__V;\n"); + addLocalVariable(m_comboDeclsp, varp, "_combo__V"); if (m_hasClk) { - AstNodeDType* seqDtypep = varp->dtypep()->cloneTree(false); - m_seqDeclsp->addNodep(seqDtypep); - m_seqDeclsp->addText(fl, " " + varp->name() + "_seq__V;\n"); - - AstNodeDType* tmpDtypep = varp->dtypep()->cloneTree(false); - m_tmpDeclsp->addNodep(tmpDtypep); - m_tmpDeclsp->addText(fl, " " + varp->name() + "_tmp__V;\n"); + addLocalVariable(m_seqDeclsp, varp, "_seq__V"); + addLocalVariable(m_tmpDeclsp, varp, "_tmp__V"); m_nbAssignsp->addText(fl, varp->name() + "_seq__V <= " + varp->name() + "_tmp__V;\n"); m_seqAssignsp->addText(fl, varp->name() + " = " + varp->name() + "_seq__V;\n"); diff --git a/src/V3ProtectLib.h b/src/V3ProtectLib.h index 8bb167db3..39131d307 100644 --- a/src/V3ProtectLib.h +++ b/src/V3ProtectLib.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Randomize.cpp b/src/V3Randomize.cpp new file mode 100644 index 000000000..3fb49c16f --- /dev/null +++ b/src/V3Randomize.cpp @@ -0,0 +1,273 @@ +// -*- mode: C++; c-file-style: "cc-mode" -*- +//************************************************************************* +// DESCRIPTION: Verilator: Expression width calculations +// +// Code available from: https://verilator.org +// +//************************************************************************* +// +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you +// can redistribute it and/or modify it under the terms of either the GNU +// Lesser General Public License Version 3 or the Perl Artistic License +// Version 2.0. +// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 +// +//************************************************************************* +// V3Randomize's Transformations: +// +// Each randomize() method call: +// Mark class of object on which randomize() is called +// Mark all classes that inherit from previously marked classed +// Mark all classes whose instances are randomized member variables of marked classes +// Each marked class: +// define a virtual randomize() method that randomizes its random variables +// +//************************************************************************* + +#include "config_build.h" +#include "verilatedos.h" + +#include "V3Randomize.h" + +//###################################################################### +// Visitor that marks classes needing a randomize() method + +class RandomizeMarkVisitor final : public AstNVisitor { +private: + // NODE STATE + // Cleared on Netlist + // AstClass::user1() -> bool. Set true to indicate needs randomize processing + AstUser1InUse m_inuser1; + + typedef std::unordered_set DerivedSet; + typedef std::unordered_map BaseToDerivedMap; + + BaseToDerivedMap m_baseToDerivedMap; // Mapping from base classes to classes that extend them + + // METHODS + VL_DEBUG_FUNC; + + void markMembers(AstClass* nodep) { + for (auto* classp = nodep; classp; + classp = classp->extendsp() ? classp->extendsp()->classp() : nullptr) { + for (auto* memberp = classp->stmtsp(); memberp; memberp = memberp->nextp()) { + // If member is rand and of class type, mark its class + if (VN_IS(memberp, Var) && VN_CAST(memberp, Var)->isRand()) { + if (auto* classRefp = VN_CAST(memberp->dtypep(), ClassRefDType)) { + auto* rclassp = classRefp->classp(); + markMembers(rclassp); + markDerived(rclassp); + rclassp->user1(true); + } + } + } + } + } + void markDerived(AstClass* nodep) { + const auto it = m_baseToDerivedMap.find(nodep); + if (it != m_baseToDerivedMap.end()) { + for (auto* classp : it->second) { + classp->user1(true); + markMembers(classp); + markDerived(classp); + } + } + } + void markAllDerived() { + for (auto p : m_baseToDerivedMap) { + if (p.first->user1()) markDerived(p.first); + } + } + + // VISITORS + virtual void visit(AstClass* nodep) override { + iterateChildren(nodep); + if (nodep->extendsp()) { + // Save pointer to derived class + auto* basep = nodep->extendsp()->classp(); + m_baseToDerivedMap[basep].insert(nodep); + } + } + virtual void visit(AstMethodCall* nodep) override { + iterateChildren(nodep); + if (nodep->name() != "randomize") return; + if (AstClassRefDType* classRefp = VN_CAST(nodep->fromp()->dtypep(), ClassRefDType)) { + auto* classp = classRefp->classp(); + classp->user1(true); + markMembers(classp); + } + } + virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + +public: + // CONSTRUCTORS + explicit RandomizeMarkVisitor(AstNetlist* nodep) { + iterate(nodep); + markAllDerived(); + } + virtual ~RandomizeMarkVisitor() override = default; +}; + +//###################################################################### +// Visitor that defines a randomize method where needed + +class RandomizeVisitor final : public AstNVisitor { +private: + // NODE STATE + // Cleared on Netlist + // AstClass::user1() -> bool. Set true to indicate needs randomize processing + // AstEnumDType::user2() -> AstVar*. Pointer to table with enum values + // AstUser1InUse m_inuser1; (Allocated for use in RandomizeMarkVisitor) + AstUser2InUse m_inuser2; + + // STATE + size_t m_enumValueTabCount = 0; // Number of tables with enum values created + + // METHODS + VL_DEBUG_FUNC; + + AstVar* enumValueTabp(AstEnumDType* nodep) { + if (nodep->user2p()) return VN_CAST(nodep->user2p(), Var); + UINFO(9, "Construct Venumvaltab " << nodep << endl); + AstNodeArrayDType* vardtypep + = new AstUnpackArrayDType(nodep->fileline(), nodep->dtypep(), + new AstRange(nodep->fileline(), nodep->itemCount(), 0)); + AstInitArray* initp = new AstInitArray(nodep->fileline(), vardtypep, nullptr); + v3Global.rootp()->typeTablep()->addTypesp(vardtypep); + AstVar* varp = new AstVar(nodep->fileline(), AstVarType::MODULETEMP, + "__Venumvaltab_" + cvtToStr(m_enumValueTabCount++), vardtypep); + varp->isConst(true); + varp->isStatic(true); + varp->valuep(initp); + // Add to root, as don't know module we are in, and aids later structure sharing + v3Global.rootp()->dollarUnitPkgAddp()->addStmtp(varp); + UASSERT_OBJ(nodep->itemsp(), nodep, "Enum without items"); + for (AstEnumItem* itemp = nodep->itemsp(); itemp; + itemp = VN_CAST(itemp->nextp(), EnumItem)) { + AstConst* vconstp = VN_CAST(itemp->valuep(), Const); + UASSERT_OBJ(vconstp, nodep, "Enum item without constified value"); + initp->addValuep(vconstp->cloneTree(false)); + } + nodep->user2p(varp); + return varp; + } + AstNodeStmt* newRandStmtsp(FileLine* fl, AstNodeVarRef* varrefp, int offset = 0, + AstMemberDType* memberp = nullptr) { + if (auto* structDtp + = VN_CAST(memberp ? memberp->subDTypep()->skipRefp() : varrefp->dtypep()->skipRefp(), + StructDType)) { + AstNodeStmt* stmtsp = nullptr; + offset += memberp ? memberp->lsb() : 0; + for (auto* smemberp = structDtp->membersp(); smemberp; + smemberp = VN_CAST(smemberp->nextp(), MemberDType)) { + auto* randp = newRandStmtsp(fl, stmtsp ? varrefp->cloneTree(false) : varrefp, + offset, smemberp); + if (stmtsp) { + stmtsp->addNext(randp); + } else { + stmtsp = randp; + } + } + return stmtsp; + } else { + AstNodeMath* valp; + if (auto* enumDtp = VN_CAST(memberp ? memberp->subDTypep()->subDTypep() + : varrefp->dtypep()->subDTypep(), + EnumDType)) { + AstVarRef* tabRefp = new AstVarRef(fl, enumValueTabp(enumDtp), VAccess::READ); + tabRefp->classOrPackagep(v3Global.rootp()->dollarUnitPkgAddp()); + auto* randp = new AstRand(fl, nullptr, false); + auto* moddivp = new AstModDiv(fl, randp, new AstConst(fl, enumDtp->itemCount())); + randp->dtypep(varrefp->findBasicDType(AstBasicDTypeKwd::UINT32)); + moddivp->dtypep(enumDtp); + valp = new AstArraySel(fl, tabRefp, moddivp); + } else { + valp = new AstRand(fl, nullptr, false); + valp->dtypep(memberp ? memberp->dtypep() : varrefp->varp()->dtypep()); + } + return new AstAssign(fl, + new AstSel(fl, varrefp, offset + (memberp ? memberp->lsb() : 0), + memberp ? memberp->width() : varrefp->width()), + valp); + } + } + + // VISITORS + virtual void visit(AstClass* nodep) override { + iterateChildren(nodep); + if (!nodep->user1()) return; // Doesn't need randomize, or already processed + UINFO(9, "Define randomize() for " << nodep << endl); + auto* funcp = V3Randomize::newRandomizeFunc(nodep); + auto* fvarp = VN_CAST(funcp->fvarp(), Var); + funcp->addStmtsp(new AstAssign( + nodep->fileline(), new AstVarRef(nodep->fileline(), fvarp, VAccess::WRITE), + new AstConst(nodep->fileline(), AstConst::WidthedValue(), 32, 1))); + for (auto* classp = nodep; classp; + classp = classp->extendsp() ? classp->extendsp()->classp() : nullptr) { + for (auto* memberp = classp->stmtsp(); memberp; memberp = memberp->nextp()) { + auto* memberVarp = VN_CAST(memberp, Var); + if (!memberVarp || !memberVarp->isRand()) continue; + auto* dtypep = memberp->dtypep()->skipRefp(); + if (VN_IS(dtypep, BasicDType) || VN_IS(dtypep, StructDType)) { + auto* refp = new AstVarRef(nodep->fileline(), memberVarp, VAccess::WRITE); + auto* stmtp = newRandStmtsp(nodep->fileline(), refp); + funcp->addStmtsp(stmtp); + } else if (auto* classRefp = VN_CAST(dtypep, ClassRefDType)) { + auto* refp = new AstVarRef(nodep->fileline(), memberVarp, VAccess::WRITE); + auto* memberFuncp = V3Randomize::newRandomizeFunc(classRefp->classp()); + auto* callp = new AstMethodCall(nodep->fileline(), refp, "randomize", nullptr); + callp->taskp(memberFuncp); + callp->dtypeFrom(memberFuncp); + funcp->addStmtsp(new AstAssign( + nodep->fileline(), new AstVarRef(nodep->fileline(), fvarp, VAccess::WRITE), + new AstAnd(nodep->fileline(), + new AstVarRef(nodep->fileline(), fvarp, VAccess::READ), + callp))); + } else { + memberp->v3warn(E_UNSUPPORTED, + "Unsupported: random member variables with type " + << memberp->dtypep()->prettyDTypeNameQ()); + } + } + } + nodep->user1(false); + } + virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + +public: + // CONSTRUCTORS + explicit RandomizeVisitor(AstNetlist* nodep) { iterate(nodep); } + virtual ~RandomizeVisitor() override = default; +}; + +//###################################################################### +// Randomize method class functions + +void V3Randomize::randomizeNetlist(AstNetlist* nodep) { + UINFO(2, __FUNCTION__ << ": " << endl); + { + RandomizeMarkVisitor markVisitor(nodep); + RandomizeVisitor visitor(nodep); + } + V3Global::dumpCheckGlobalTree("randomize", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); +} + +AstFunc* V3Randomize::newRandomizeFunc(AstClass* nodep) { + auto* funcp = VN_CAST(nodep->findMember("randomize"), Func); + if (!funcp) { + auto* dtypep + = nodep->findBitDType(32, 32, VSigning::SIGNED); // IEEE says int return of 0/1 + auto* fvarp = new AstVar(nodep->fileline(), AstVarType::MEMBER, "randomize", dtypep); + fvarp->lifetime(VLifetime::AUTOMATIC); + fvarp->funcLocal(true); + fvarp->funcReturn(true); + fvarp->direction(VDirection::OUTPUT); + funcp = new AstFunc(nodep->fileline(), "randomize", nullptr, fvarp); + funcp->dtypep(dtypep); + funcp->classMethod(true); + funcp->isVirtual(nodep->isExtended()); + nodep->addMembersp(funcp); + nodep->repairCache(); + } + return funcp; +} diff --git a/src/V3Randomize.h b/src/V3Randomize.h new file mode 100644 index 000000000..53c74b182 --- /dev/null +++ b/src/V3Randomize.h @@ -0,0 +1,32 @@ +// -*- mode: C++; c-file-style: "cc-mode" -*- +//************************************************************************* +// DESCRIPTION: Verilator: Node attributes/ expression widths +// +// Code available from: https://verilator.org +// +//************************************************************************* +// +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you +// can redistribute it and/or modify it under the terms of either the GNU +// Lesser General Public License Version 3 or the Perl Artistic License +// Version 2.0. +// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 +// +//************************************************************************* + +#ifndef _V3RANDOMIZE_METHOD_H_ +#define _V3RANDOMIZE_METHOD_H_ 1 + +#include "config_build.h" +#include "verilatedos.h" + +#include "V3Ast.h" + +class V3Randomize final { +public: + static void randomizeNetlist(AstNetlist* nodep); + + static AstFunc* newRandomizeFunc(AstClass* nodep); +}; + +#endif // Guard diff --git a/src/V3Reloop.cpp b/src/V3Reloop.cpp index 71379aa05..5fb63111e 100644 --- a/src/V3Reloop.cpp +++ b/src/V3Reloop.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Reloop.h b/src/V3Reloop.h index fb0a748dc..64c17e50a 100644 --- a/src/V3Reloop.h +++ b/src/V3Reloop.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Scope.cpp b/src/V3Scope.cpp index cc11bdb40..042181ff8 100644 --- a/src/V3Scope.cpp +++ b/src/V3Scope.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -109,7 +109,7 @@ private: (m_aboveCellp ? static_cast(m_aboveCellp) : static_cast(nodep)) ->fileline(), nodep, scopename, m_aboveScopep, m_aboveCellp); - if (VN_IS(nodep, Package)) m_packageScopes.insert(make_pair(nodep, m_scopep)); + if (VN_IS(nodep, Package)) m_packageScopes.emplace(nodep, m_scopep); // Now for each child cell, iterate the module this cell points to for (AstNode* cellnextp = nodep->stmtsp(); cellnextp; cellnextp = cellnextp->nextp()) { @@ -169,7 +169,7 @@ private: : static_cast(nodep)); m_scopep = new AstScope(abovep->fileline(), m_modp, scopename, m_aboveScopep, m_aboveCellp); - m_packageScopes.insert(make_pair(nodep, m_scopep)); + m_packageScopes.emplace(nodep, m_scopep); // Create scope for the current usage of this cell AstNode::user1ClearTree(); @@ -272,7 +272,7 @@ private: nodep->attrClocker(VVarAttrClocker::CLOCKER_NO); } UASSERT_OBJ(m_scopep, nodep, "No scope for var"); - m_varScopes.insert(make_pair(make_pair(nodep, m_scopep), varscp)); + m_varScopes.emplace(make_pair(nodep, m_scopep), varscp); m_scopep->addVarp(varscp); } } @@ -287,7 +287,7 @@ private: // the var's referenced package etc might not be created yet. // So push to a list and post-correct. // No check here for nodep->classOrPackagep(), will check when walk list. - m_varRefScopes.insert(make_pair(nodep, m_scopep)); + m_varRefScopes.emplace(nodep, m_scopep); } } virtual void visit(AstScopeName* nodep) override { diff --git a/src/V3Scope.h b/src/V3Scope.h index ffce787f9..9589aa1e8 100644 --- a/src/V3Scope.h +++ b/src/V3Scope.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Scoreboard.cpp b/src/V3Scoreboard.cpp index 42df6dbd8..f265322ba 100644 --- a/src/V3Scoreboard.cpp +++ b/src/V3Scoreboard.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Scoreboard.h b/src/V3Scoreboard.h index d0a1ec3e7..44297978e 100644 --- a/src/V3Scoreboard.h +++ b/src/V3Scoreboard.h @@ -13,7 +13,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3SenTree.h b/src/V3SenTree.h index b64937081..22f212707 100644 --- a/src/V3SenTree.h +++ b/src/V3SenTree.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Simulate.h b/src/V3Simulate.h index edec6cffe..de00d6cb5 100644 --- a/src/V3Simulate.h +++ b/src/V3Simulate.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -152,7 +152,7 @@ private: int msb = lsb + width - 1; V3Number fieldNum(nump, width); fieldNum.opSel(*nump, msb, lsb); - int arrayElem = arrayp->lsb() + element; + int arrayElem = arrayp->lo() + element; out << arrayElem << " = " << prettyNumber(&fieldNum, childTypep); if (element < arrayElements - 1) out << ", "; } diff --git a/src/V3Slice.cpp b/src/V3Slice.cpp index 3c66b1648..de7a4b362 100644 --- a/src/V3Slice.cpp +++ b/src/V3Slice.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -106,7 +106,8 @@ class SliceVisitor final : public AstNVisitor { ? snodep->declRange().elements() - 1 - offset : offset)); newp = new AstArraySel(nodep->fileline(), snodep->fromp()->cloneTree(false), leOffset); - } else if (VN_IS(nodep, ArraySel) || VN_IS(nodep, NodeVarRef) || VN_IS(nodep, NodeSel)) { + } else if (VN_IS(nodep, ArraySel) || VN_IS(nodep, NodeVarRef) || VN_IS(nodep, NodeSel) + || VN_IS(nodep, CMethodHard)) { UINFO(9, " cloneSel(" << elements << "," << offset << ") " << nodep << endl); int leOffset = !arrayp->rangep()->littleEndian() ? arrayp->rangep()->elementsConst() - 1 - offset diff --git a/src/V3Slice.h b/src/V3Slice.h index ad711d0f2..40c94c04d 100644 --- a/src/V3Slice.h +++ b/src/V3Slice.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Split.cpp b/src/V3Split.cpp index 9b7e0cd85..801a6cef7 100644 --- a/src/V3Split.cpp +++ b/src/V3Split.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -528,7 +528,7 @@ protected: int currOrder = 0; // Existing sequence number of assignment for (AstNode* nextp = nodep; nextp; nextp = nextp->nextp()) { SplitLogicVertex* vvertexp = reinterpret_cast(nextp->user3p()); - rankMap.insert(make_pair(vvertexp->rank(), nextp)); + rankMap.emplace(vvertexp->rank(), nextp); nextp->user4(++currOrder); // Record current ordering } diff --git a/src/V3Split.h b/src/V3Split.h index bcabc01e3..9bf7ab68d 100644 --- a/src/V3Split.h +++ b/src/V3Split.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3SplitAs.cpp b/src/V3SplitAs.cpp index e40a87f42..43f794243 100644 --- a/src/V3SplitAs.cpp +++ b/src/V3SplitAs.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3SplitAs.h b/src/V3SplitAs.h index 82f9d4915..3c2886c3b 100644 --- a/src/V3SplitAs.h +++ b/src/V3SplitAs.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3SplitVar.cpp b/src/V3SplitVar.cpp index 83ae80e89..a3f0f4ef0 100644 --- a/src/V3SplitVar.cpp +++ b/src/V3SplitVar.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -405,7 +405,7 @@ class SplitUnpackedVarVisitor final : public AstNVisitor, public SplitVarImpl { static int outerMostSizeOfUnpackedArray(AstVar* nodep) { AstUnpackArrayDType* dtypep = VN_CAST(nodep->dtypep()->skipRefp(), UnpackArrayDType); UASSERT_OBJ(dtypep, nodep, "Must be unapcked array"); - return dtypep->msb() - dtypep->lsb() + 1; + return dtypep->elementsConst(); } void setContextAndIterateChildren(AstNode* nodep) { @@ -585,7 +585,7 @@ class SplitUnpackedVarVisitor final : public AstNVisitor, public SplitVarImpl { const VNumRange selRange{nodep->declRange().hi() + dtypep->declRange().lo(), nodep->declRange().lo() + dtypep->declRange().lo(), nodep->declRange().littleEndian()}; - UASSERT_OBJ(dtypep->lsb() <= selRange.lo() && selRange.hi() <= dtypep->msb(), nodep, + UASSERT_OBJ(dtypep->lo() <= selRange.lo() && selRange.hi() <= dtypep->hi(), nodep, "Range check for AstSliceSel must have been finished in V3Width.cpp"); UINFO(4, "add " << nodep << " for " << refp->varp()->prettyName() << "\n"); m_refs.tryAdd(m_contextp, refp, nodep, nodep->declRange().hi(), @@ -614,12 +614,12 @@ class SplitUnpackedVarVisitor final : public AstNVisitor, public SplitVarImpl { AstVar* varp = newVar(nodep->fileline(), AstVarType::VAR, name, dtypep); // Variable will be registered in the caller side. UINFO(3, varp->prettyNameQ() - << " is created lsb:" << dtypep->lsb() << " msb:" << dtypep->msb() << "\n"); + << " is created lsb:" << dtypep->lo() << " msb:" << dtypep->hi() << "\n"); // Use AstAssign if true, otherwise AstAssignW const bool use_simple_assign = (context && VN_IS(context, NodeFTaskRef)) || (assignp && VN_IS(assignp, Assign)); - for (int i = 0; i <= dtypep->msb() - dtypep->lsb(); ++i) { + for (int i = 0; i < dtypep->elementsConst(); ++i) { AstNode* lhsp = newVarRef(nodep->fileline(), vars.at(start_idx + i), lvalue ? VAccess::WRITE : VAccess::READ); AstNode* rhsp = new AstArraySel( @@ -689,10 +689,10 @@ class SplitUnpackedVarVisitor final : public AstNVisitor, public SplitVarImpl { const bool needNext = VN_IS(subTypep, UnpackArrayDType); // Still unpacked array. std::vector vars; // Add the split variables - for (vlsint32_t i = 0; i <= dtypep->msb() - dtypep->lsb(); ++i) { + for (vlsint32_t i = 0; i < dtypep->elementsConst(); ++i) { // Unpacked array is traced as var(idx), not var[idx]. const std::string name - = varp->name() + AstNode::encodeName('(' + cvtToStr(i + dtypep->lsb()) + ')'); + = varp->name() + AstNode::encodeName('(' + cvtToStr(i + dtypep->lo()) + ')'); AstVar* newp = newVar(varp->fileline(), AstVarType::VAR, name, subTypep); newp->propagateAttrFrom(varp); // If varp is an IO, varp will remain and will be traced. @@ -722,7 +722,7 @@ class SplitUnpackedVarVisitor final : public AstNVisitor, public SplitVarImpl { refp = VN_CAST(selp->fromp(), VarRef); UASSERT_OBJ(refp, selp, "Unexpected op is registered"); adtypep = VN_CAST(selp->dtypep()->skipRefp(), UnpackArrayDType); - lsb = adtypep->lsb(); + lsb = adtypep->lo(); } AstVarRef* newrefp = createTempVar(sit->context(), refp, adtypep, varp->name(), vars, lsb, refp->access(), sit->ftask()); @@ -873,9 +873,7 @@ class PackedVarRef final { // Use raw pointer to dedup typedef std::map NodeIndices; NodeIndices nodes; - for (size_t i = 0; i < refs.size(); ++i) { - nodes.insert(std::make_pair(refs[i].nodep(), i)); - } + for (size_t i = 0; i < refs.size(); ++i) { nodes.emplace(refs[i].nodep(), i); } std::vector vect; vect.reserve(nodes.size()); for (NodeIndices::const_iterator it = nodes.begin(), it_end = nodes.end(); it != it_end; @@ -922,8 +920,8 @@ public: points.emplace_back(std::make_pair(it->msb() + 1, true)); // End of a region } if (skipUnused && !m_rhs.empty()) { // Range to be read must be kept, so add points here - int lsb = m_basicp->msb() + 1; - int msb = m_basicp->lsb() - 1; + int lsb = m_basicp->hi() + 1; + int msb = m_basicp->lo() - 1; for (size_t i = 0; i < m_rhs.size(); ++i) { lsb = std::min(lsb, m_rhs[i].lsb()); msb = std::max(msb, m_rhs[i].msb()); @@ -933,8 +931,8 @@ public: points.emplace_back(std::make_pair(msb + 1, true)); } if (!skipUnused) { // All bits are necessary - points.emplace_back(std::make_pair(m_basicp->lsb(), false)); - points.emplace_back(std::make_pair(m_basicp->msb() + 1, true)); + points.emplace_back(std::make_pair(m_basicp->lo(), false)); + points.emplace_back(std::make_pair(m_basicp->hi() + 1, true)); } std::sort(points.begin(), points.end(), SortByFirst()); @@ -985,10 +983,10 @@ class SplitPackedVarVisitor final : public AstNVisitor, public SplitVarImpl { UASSERT_OBJ(!nodep->classOrPackagep(), nodep, "variable in package must have been dropped beforehand."); const AstBasicDType* basicp = refit->second.basicp(); - refit->second.append(PackedVarRefEntry(nodep, basicp->lsb(), varp->width()), + refit->second.append(PackedVarRefEntry(nodep, basicp->lo(), varp->width()), nodep->access()); UINFO(5, varp->prettyName() - << " Entire bit of [" << basicp->lsb() << ":+" << varp->width() << "] \n"); + << " Entire bit of [" << basicp->lo() << "+:" << varp->width() << "] \n"); } virtual void visit(AstSel* nodep) override { AstVarRef* vrefp = VN_CAST(nodep->fromp(), VarRef); @@ -1010,12 +1008,12 @@ class SplitPackedVarVisitor final : public AstNVisitor, public SplitVarImpl { VN_CAST(nodep->widthp(), Const)}}; // GCC 3.8.0 wants {{}} if (consts[0] && consts[1]) { // OK refit->second.append( - PackedVarRefEntry(nodep, consts[0]->toSInt() + refit->second.basicp()->lsb(), + PackedVarRefEntry(nodep, consts[0]->toSInt() + refit->second.basicp()->lo(), consts[1]->toUInt()), vrefp->access()); UINFO(5, varp->prettyName() << " [" << consts[0]->toSInt() << ":+" << consts[1]->toSInt() - << "] lsb:" << refit->second.basicp()->lsb() << "\n"); + << "] lsb:" << refit->second.basicp()->lo() << "\n"); } else { nodep->v3warn(SPLITVAR, vrefp->prettyNameQ() << notSplitMsg @@ -1081,7 +1079,8 @@ class SplitPackedVarVisitor final : public AstNVisitor, public SplitVarImpl { void createVars(AstVar* varp, const AstBasicDType* basicp, std::vector& vars) { for (size_t i = 0; i < vars.size(); ++i) { SplitNewVar* newvarp = &vars[i]; - int left = newvarp->msb(), right = newvarp->lsb(); + int left = newvarp->msb(); + int right = newvarp->lsb(); if (basicp->littleEndian()) std::swap(left, right); const std::string name = (left == right) @@ -1101,8 +1100,8 @@ class SplitPackedVarVisitor final : public AstNVisitor, public SplitVarImpl { break; default: UASSERT_OBJ(false, basicp, "Only bit and logic are allowed"); } - dtypep->rangep(new AstRange(varp->fileline(), newvarp->msb(), newvarp->lsb())); - dtypep->rangep()->littleEndian(basicp->littleEndian()); + dtypep->rangep(new AstRange{varp->fileline(), VNumRange{newvarp->msb(), newvarp->lsb(), + basicp->littleEndian()}}); newvarp->varp(new AstVar(varp->fileline(), AstVarType::VAR, name, dtypep)); newvarp->varp()->propagateAttrFrom(varp); newvarp->varp()->funcLocal(varp->isFuncLocal() || varp->isFuncReturn()); diff --git a/src/V3SplitVar.h b/src/V3SplitVar.h index 41195bc57..243120195 100644 --- a/src/V3SplitVar.h +++ b/src/V3SplitVar.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Stats.cpp b/src/V3Stats.cpp index 612ea0244..f155bba1d 100644 --- a/src/V3Stats.cpp +++ b/src/V3Stats.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2005-2020 by Wilson Snyder. This program is free software; you +// Copyright 2005-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -134,7 +134,7 @@ private: // Need to do even if !m_counting because maybe determining upstream if/else double ifInstrs = 0.0; double elseInstrs = 0.0; - if (nodep->branchPred() != VBranchPred::BP_UNLIKELY) { // Check if + if (!nodep->branchPred().unlikely()) { // Check if VL_RESTORER(m_instrs); VL_RESTORER(m_counting); { @@ -144,7 +144,7 @@ private: ifInstrs = m_instrs; } } - if (nodep->branchPred() != VBranchPred::BP_LIKELY) { // Check else + if (!nodep->branchPred().likely()) { // Check else VL_RESTORER(m_instrs); VL_RESTORER(m_counting); { diff --git a/src/V3Stats.h b/src/V3Stats.h index 7f9012238..9cebbd057 100644 --- a/src/V3Stats.h +++ b/src/V3Stats.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2005-2020 by Wilson Snyder. This program is free software; you +// Copyright 2005-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -24,6 +24,12 @@ class AstNetlist; +#define STAT_ADD_UINFO(level, text, value) \ + do { \ + UINFO((level), "addStat " << text << " " << value << endl); \ + V3Stats::addStat(text, value); \ + } while (0) + //============================================================================ class VDouble0 final { diff --git a/src/V3StatsReport.cpp b/src/V3StatsReport.cpp index 24c84932e..0eb3b9961 100644 --- a/src/V3StatsReport.cpp +++ b/src/V3StatsReport.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2005-2020 by Wilson Snyder. This program is free software; you +// Copyright 2005-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -54,7 +54,7 @@ class StatsReport final { // * is always first for (auto& itr : s_allStats) { V3Statistic* repp = &itr; - byName.insert(make_pair(repp->name(), repp)); + byName.emplace(repp->name(), repp); } // Process duplicates @@ -79,7 +79,7 @@ class StatsReport final { const V3Statistic* repp = &itr; if (repp->stage() == "*" && repp->printit()) { if (maxWidth < repp->name().length()) maxWidth = repp->name().length(); - byName.insert(make_pair(repp->name(), repp)); + byName.emplace(repp->name(), repp); } } @@ -123,10 +123,10 @@ class StatsReport final { if (repp->stage() != "*" && repp->printit()) { if (maxWidth < repp->name().length()) maxWidth = repp->name().length(); if (stageInt.find(repp->stage()) == stageInt.end()) { - stageInt.insert(make_pair(repp->stage(), stage++)); + stageInt.emplace(repp->stage(), stage++); stages.push_back(repp->stage()); } - byName.insert(make_pair(repp->name(), repp)); + byName.emplace(repp->name(), repp); } } diff --git a/src/V3String.cpp b/src/V3String.cpp index edf02a01d..2328f8cfc 100644 --- a/src/V3String.cpp +++ b/src/V3String.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3String.h b/src/V3String.h index 6bc0bd61f..71d811ec0 100644 --- a/src/V3String.h +++ b/src/V3String.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Subst.cpp b/src/V3Subst.cpp index 8a0bb483c..c15d7dd2e 100644 --- a/src/V3Subst.cpp +++ b/src/V3Subst.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2004-2020 by Wilson Snyder. This program is free software; you +// Copyright 2004-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Subst.h b/src/V3Subst.h index 9906f3487..a2dd17202 100644 --- a/src/V3Subst.h +++ b/src/V3Subst.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3SymTable.h b/src/V3SymTable.h index de63b816a..e1e11151a 100644 --- a/src/V3SymTable.h +++ b/src/V3SymTable.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -129,7 +129,7 @@ public: entp->nodep()->v3fatalSrc("Inserting two symbols with same name: " << name); } } else { - m_idNameMap.insert(make_pair(name, entp)); + m_idNameMap.emplace(name, entp); } } void reinsert(const string& name, VSymEnt* entp) { @@ -267,7 +267,7 @@ public: scopes += AstNode::prettyName(it->first); } } - if (scopes == "") scopes = ""; + if (scopes == "") scopes = ""; std::cerr << V3Error::warnMore() << "... Known scopes under '" << prettyName << "': " << scopes << endl; if (debug()) dump(std::cerr, " KnownScope: ", 1); diff --git a/src/V3TSP.cpp b/src/V3TSP.cpp index 95348cbbb..e9f2503c6 100644 --- a/src/V3TSP.cpp +++ b/src/V3TSP.cpp @@ -11,7 +11,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3TSP.h b/src/V3TSP.h index e44295150..ec81061ea 100644 --- a/src/V3TSP.h +++ b/src/V3TSP.h @@ -7,7 +7,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Table.cpp b/src/V3Table.cpp index 271c8c649..cc68dba7c 100644 --- a/src/V3Table.cpp +++ b/src/V3Table.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Table.h b/src/V3Table.h index 3ad3de773..471bc7f05 100644 --- a/src/V3Table.h +++ b/src/V3Table.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Task.cpp b/src/V3Task.cpp index 131129160..1ba20e2fd 100644 --- a/src/V3Task.cpp +++ b/src/V3Task.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -206,18 +206,19 @@ private: } virtual void visit(AstNodeFTask* nodep) override { UINFO(9, " TASK " << nodep << endl); - TaskBaseVertex* lastVxp = m_curVxp; - m_curVxp = getFTaskVertex(nodep); - if (nodep->dpiImport()) m_curVxp->noInline(true); - if (nodep->classMethod()) m_curVxp->noInline(true); // Until V3Task supports it - if (nodep->isConstructor()) { - m_curVxp->noInline(true); - m_ctorp = nodep; - UASSERT_OBJ(m_classp, nodep, "Ctor not under class"); - m_funcToClassMap[nodep] = m_classp; + { + VL_RESTORER(m_curVxp); + m_curVxp = getFTaskVertex(nodep); + if (nodep->dpiImport()) m_curVxp->noInline(true); + if (nodep->classMethod()) m_curVxp->noInline(true); // Until V3Task supports it + if (nodep->isConstructor()) { + m_curVxp->noInline(true); + m_ctorp = nodep; + UASSERT_OBJ(m_classp, nodep, "Ctor not under class"); + m_funcToClassMap[nodep] = m_classp; + } + iterateChildren(nodep); } - iterateChildren(nodep); - m_curVxp = lastVxp; } virtual void visit(AstPragma* nodep) override { if (nodep->pragType() == AstPragmaType::NO_INLINE_TASK) { @@ -320,6 +321,50 @@ public: virtual ~TaskRelinkVisitor() override = default; }; +//###################################################################### +// DPI related utility functions + +struct TaskDpiUtils { + static std::vector> + unpackDimsAndStrides(AstNodeDType* dtypep) { + std::vector> dimStrides; + if (AstUnpackArrayDType* unpackp = VN_CAST(dtypep->skipRefp(), UnpackArrayDType)) { + const std::vector dims = unpackp->unpackDimensions(); + dimStrides.resize(dims.size(), {nullptr, 0}); + dimStrides.back() = {dims.back(), 1}; + for (ssize_t i = dims.size() - 2; i >= 0; --i) { + dimStrides[i].first = dims[i]; + dimStrides[i].second = dimStrides[i + 1].second * dims[i + 1]->elementsConst(); + } + } + return dimStrides; + } + static bool dpiToInternalFrStmt(AstVar* portp, const string& frName, string& frstmt, + string& ket) { + ket.clear(); + if (portp->basicp() && portp->basicp()->keyword() == AstBasicDTypeKwd::CHANDLE) { + frstmt = "VL_CVT_VP_Q(" + frName; + ket = ")"; + } else if ((portp->basicp() && portp->basicp()->isDpiPrimitive())) { + frstmt = frName; + } else { + const string frSvType = portp->basicp()->isDpiBitVec() ? "SVBV" : "SVLV"; + if (portp->isWide()) { + // Need to convert to wide, using special function + frstmt = "VL_SET_W_" + frSvType + "(" + cvtToStr(portp->width()) + ","; + return true; + } else { + const AstNodeDType* dtypep = portp->dtypep()->skipRefp(); + frstmt = "VL_SET_" + string(dtypep->charIQWN()) + "_" + frSvType + "("; + if (VN_IS(dtypep, UnpackArrayDType)) frstmt += "&"; + frstmt += frName; + ket = ")"; + } + } + return false; + } +}; + //###################################################################### // Task state, as a visitor of each AstNode @@ -651,20 +696,6 @@ private: return new AstCStmt(portp->fileline(), stmt); } - static std::vector> unpackDimsAndStrides(AstVar* varp) { - std::vector> dimStrides; - if (AstUnpackArrayDType* dtypep = VN_CAST(varp->dtypep()->skipRefp(), UnpackArrayDType)) { - const std::vector dims = dtypep->unpackDimensions(); - dimStrides.resize(dims.size(), {nullptr, 0}); - dimStrides.back() = {dims.back(), 1}; - for (ssize_t i = dims.size() - 2; i >= 0; --i) { - dimStrides[i].first = dims[i]; - dimStrides[i].second = dimStrides[i + 1].second * dims[i + 1]->elementsConst(); - } - } - return dimStrides; - } - AstNode* createAssignDpiToInternal(AstVarScope* portvscp, const string& frName) { // Create assignment from DPI temporary into internal format // DPI temporary is scalar or 1D array (if unpacked array) @@ -672,7 +703,7 @@ private: AstVar* portp = portvscp->varp(); string frstmt; string ket; - const bool useSetWSvlv = V3Task::dpiToInternalFrStmt(portp, frName, frstmt, ket); + const bool useSetWSvlv = TaskDpiUtils::dpiToInternalFrStmt(portp, frName, frstmt, ket); // Use a AstCMath, as we want V3Clean to mask off bits that don't make sense. int cwidth = VL_IDATASIZE; if (!useSetWSvlv && portp->basicp()) { @@ -684,12 +715,12 @@ private: } const std::vector> dimStrides - = unpackDimsAndStrides(portvscp->varp()); + = TaskDpiUtils::unpackDimsAndStrides(portp->dtypep()); const int total = dimStrides.empty() ? 1 : dimStrides.front().first->elementsConst() * dimStrides.front().second; AstNode* newp = nullptr; - const int widthWords = portvscp->varp()->basicp()->widthWords(); + const int widthWords = portp->basicp()->widthWords(); for (int i = 0; i < total; ++i) { AstNode* srcp = new AstVarRef(portvscp->fileline(), portvscp, VAccess::WRITE); // extract a scalar from multi-dimensional array (internal format) @@ -710,7 +741,7 @@ private: string from = frstmt; if (!dimStrides.empty()) { // e.g. time is 64bit svLogicVector - const int coef = portvscp->varp()->basicp()->isDpiLogicVec() ? widthWords : 1; + const int coef = portp->basicp()->isDpiLogicVec() ? widthWords : 1; from += "[" + cvtToStr(i * coef) + "]"; } from += ket; @@ -881,7 +912,7 @@ private: // as it's legal for the user to attach multiple tasks to one dpi cname const auto iter = m_dpiNames.find(nodep->cname()); if (iter == m_dpiNames.end()) { - m_dpiNames.insert(make_pair(nodep->cname(), make_pair(nodep, dpiproto))); + m_dpiNames.emplace(nodep->cname(), make_pair(nodep, dpiproto)); return false; } else if (iter->second.second != dpiproto) { nodep->v3error( @@ -1645,29 +1676,45 @@ string V3Task::assignInternalToDpi(AstVar* portp, bool isPtr, const string& frSu return stmt; } -bool V3Task::dpiToInternalFrStmt(AstVar* portp, const string& frName, string& frstmt, - string& ket) { - ket.clear(); - if (portp->basicp() && portp->basicp()->keyword() == AstBasicDTypeKwd::CHANDLE) { - frstmt = "VL_CVT_VP_Q(" + frName; - ket = ")"; - } else if ((portp->basicp() && portp->basicp()->isDpiPrimitive())) { - frstmt = frName; - } else { - const string frSvType = portp->basicp()->isDpiBitVec() ? "SVBV" : "SVLV"; - if (portp->isWide()) { - // Need to convert to wide, using special function - frstmt = "VL_SET_W_" + frSvType + "(" + cvtToStr(portp->width()) + ","; - return true; +string V3Task::assignDpiToInternal(const string& lhsName, AstVar* varp) { + // Create assignment from DPI temporary into internal format + // DPI temporary is scalar or 1D array (if unpacked array) + // Internal representation is scalar, 1D, or multi-dimensional array (similar to SV) + const string frName = varp->name(); + string frstmt; + string ket; + const bool useSetWSvlv = TaskDpiUtils::dpiToInternalFrStmt(varp, frName, frstmt, ket); + + const std::vector> dimStrides + = TaskDpiUtils::unpackDimsAndStrides(varp->dtypep()); + const int total = dimStrides.empty() + ? 1 + : dimStrides.front().first->elementsConst() * dimStrides.front().second; + const int widthWords = varp->basicp()->widthWords(); + string statements; + for (int i = 0; i < total; ++i) { + string lhs = lhsName; + // extract a scalar from multi-dimensional array (internal format) + for (auto&& dimStride : dimStrides) { + const size_t dimIdx = (i / dimStride.second) % dimStride.first->elementsConst(); + lhs += "[" + cvtToStr(dimIdx) + "]"; + } + // extract a scalar from DPI temporary var that is scalar or 1D array + if (useSetWSvlv) { + statements += frstmt + ket + " " + lhs + ", " + frName + " + " + + cvtToStr(i * widthWords) + ");\n"; } else { - const AstNodeDType* dtypep = portp->dtypep()->skipRefp(); - frstmt = "VL_SET_" + string(dtypep->charIQWN()) + "_" + frSvType + "("; - if (VN_IS(dtypep, UnpackArrayDType)) frstmt += "&"; - frstmt += frName; - ket = ")"; + string rhs = frstmt; + if (!dimStrides.empty()) { + // e.g. time is 64bit svLogicVector + const int coef = varp->basicp()->isDpiLogicVec() ? widthWords : 1; + rhs += "[" + cvtToStr(i * coef) + "]"; + } + rhs += ket; + statements += lhs + " = " + rhs + ";\n"; } } - return false; + return statements; } const char* V3Task::dpiTemporaryVarSuffix() { diff --git a/src/V3Task.h b/src/V3Task.h index 78d7b0dde..9491d62fc 100644 --- a/src/V3Task.h +++ b/src/V3Task.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -39,8 +39,7 @@ public: static V3TaskConnects taskConnects(AstNodeFTaskRef* nodep, AstNode* taskStmtsp); static string assignInternalToDpi(AstVar* portp, bool isPtr, const string& frSuffix, const string& toSuffix, const string& frPrefix = ""); - static bool dpiToInternalFrStmt(AstVar* portp, const string& frName, string& frstmt, - string& ket); + static string assignDpiToInternal(const string& lhsName, AstVar* rhsp); static const char* dpiTemporaryVarSuffix(); }; diff --git a/src/V3Trace.cpp b/src/V3Trace.cpp index fcd5e7e03..4f6a7df98 100644 --- a/src/V3Trace.cpp +++ b/src/V3Trace.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -363,7 +363,7 @@ private: // make slow routines set all activity flags. actSet.erase(TraceActivityVertex::ACTIVITY_SLOW); } - traces.insert(make_pair(actSet, vtxp)); + traces.emplace(actSet, vtxp); } } } @@ -447,7 +447,8 @@ private: FileLine* const flp = m_topScopep->fileline(); AstNodeDType* const newScalarDtp = new AstBasicDType(flp, VFlagLogicPacked(), 1); v3Global.rootp()->typeTablep()->addTypesp(newScalarDtp); - AstRange* const newArange = new AstRange(flp, VNumRange(m_activityNumber - 1, 0, false)); + AstRange* const newArange + = new AstRange{flp, VNumRange{static_cast(m_activityNumber) - 1, 0}}; AstNodeDType* const newArrDtp = new AstUnpackArrayDType(flp, newScalarDtp, newArange); v3Global.rootp()->typeTablep()->addTypesp(newArrDtp); AstVar* const newvarp @@ -603,7 +604,8 @@ private: AstCFunc* topFuncp = nullptr; AstCFunc* subFuncp = nullptr; int subStmts = 0; - const uint32_t maxCodes = (nAllCodes + parallelism - 1) / parallelism; + uint32_t maxCodes = (nAllCodes + parallelism - 1) / parallelism; + if (maxCodes < 1) maxCodes = 1; uint32_t nCodes = 0; const ActCodeSet* prevActSet = nullptr; AstIf* ifp = nullptr; diff --git a/src/V3Trace.h b/src/V3Trace.h index c45922fe6..95691031b 100644 --- a/src/V3Trace.h +++ b/src/V3Trace.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3TraceDecl.cpp b/src/V3TraceDecl.cpp index ba248b720..0ed6572ce 100644 --- a/src/V3TraceDecl.cpp +++ b/src/V3TraceDecl.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -59,7 +59,7 @@ private: if (!varp->isTrace()) { return "Verilator trace_off"; } else if (!nodep->isTrace()) { - return "Verilator cell trace_off"; + return "Verilator instance trace_off"; } else if (!v3Global.opt.traceUnderscore()) { const string prettyName = varp->prettyName(); if (!prettyName.empty() && prettyName[0] == '_') return "Leading underscore"; @@ -99,7 +99,7 @@ private: // misreflects one element VNumRange bitRange; if (widthOverride) { - bitRange = VNumRange(widthOverride - 1, 0, false); + bitRange = VNumRange{widthOverride - 1, 0}; } else if (const AstBasicDType* const bdtypep = m_traValuep->dtypep()->basicp()) { bitRange = bdtypep->nrange(); } @@ -238,13 +238,13 @@ private: } else { // Unroll now, as have no other method to get right signal names AstNodeDType* const subtypep = nodep->subDTypep()->skipRefToEnump(); - for (int i = nodep->lsb(); i <= nodep->msb(); ++i) { + for (int i = nodep->lo(); i <= nodep->hi(); ++i) { VL_RESTORER(m_traShowname); VL_RESTORER(m_traValuep); { m_traShowname += string("(") + cvtToStr(i) + string(")"); m_traValuep = new AstArraySel( - nodep->fileline(), m_traValuep->cloneTree(true), i - nodep->lsb()); + nodep->fileline(), m_traValuep->cloneTree(true), i - nodep->lo()); m_traValuep->dtypep(subtypep); iterate(subtypep); @@ -263,14 +263,14 @@ private: addTraceDecl(VNumRange(), nodep->width()); } else { AstNodeDType* const subtypep = nodep->subDTypep()->skipRefToEnump(); - for (int i = nodep->lsb(); i <= nodep->msb(); ++i) { + for (int i = nodep->lo(); i <= nodep->hi(); ++i) { VL_RESTORER(m_traShowname); VL_RESTORER(m_traValuep); { m_traShowname += string("(") + cvtToStr(i) + string(")"); - m_traValuep = new AstSel(nodep->fileline(), m_traValuep->cloneTree(true), - (i - nodep->lsb()) * subtypep->width(), - subtypep->width()); + m_traValuep + = new AstSel(nodep->fileline(), m_traValuep->cloneTree(true), + (i - nodep->lo()) * subtypep->width(), subtypep->width()); m_traValuep->dtypep(subtypep); iterate(subtypep); VL_DO_CLEAR(m_traValuep->deleteTree(), m_traValuep = nullptr); diff --git a/src/V3TraceDecl.h b/src/V3TraceDecl.h index 024d284a7..2c0ec73eb 100644 --- a/src/V3TraceDecl.h +++ b/src/V3TraceDecl.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Tristate.cpp b/src/V3Tristate.cpp index cc192edd4..b834c47ff 100644 --- a/src/V3Tristate.cpp +++ b/src/V3Tristate.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -427,7 +427,7 @@ class TristateVisitor final : public TristateBaseVisitor { if (it == m_lhsmap.end()) { // Not found RefVec* refsp = new RefVec(); refsp->push_back(nodep); - m_lhsmap.insert(make_pair(key, refsp)); + m_lhsmap.emplace(key, refsp); } else { it->second->push_back(nodep); } diff --git a/src/V3Tristate.h b/src/V3Tristate.h index 5ea6c7d17..079c44a27 100644 --- a/src/V3Tristate.h +++ b/src/V3Tristate.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Undriven.cpp b/src/V3Undriven.cpp index 36077d610..158ffd2f1 100644 --- a/src/V3Undriven.cpp +++ b/src/V3Undriven.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2004-2020 by Wilson Snyder. This program is free software; you +// Copyright 2004-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -90,14 +90,14 @@ private: int lsb = bit + 1; if (bits != "") bits += ","; if (lsb == msb) { - bits += cvtToStr(lsb + bdtypep->lsb()); + bits += cvtToStr(lsb + bdtypep->lo()); } else { if (bdtypep->littleEndian()) { - bits += cvtToStr(lsb + bdtypep->lsb()) + ":" - + cvtToStr(msb + bdtypep->lsb()); + bits + += cvtToStr(lsb + bdtypep->lo()) + ":" + cvtToStr(msb + bdtypep->lo()); } else { - bits += cvtToStr(msb + bdtypep->lsb()) + ":" - + cvtToStr(lsb + bdtypep->lsb()); + bits + += cvtToStr(msb + bdtypep->lo()) + ":" + cvtToStr(lsb + bdtypep->lo()); } } prev = false; @@ -149,7 +149,7 @@ public: void reportViolations() { // Combine bits into overall state AstVar* nodep = m_varp; - if (!nodep->isParam() && !nodep->isGenVar()) { + { bool allU = true; bool allD = true; bool anyU = m_wholeFlags[FLAG_USED]; @@ -168,8 +168,12 @@ public: anyDnotU |= !used && driv; anynotDU |= !used && !driv; } + if ((nodep->isGenVar() || nodep->isParam()) && nodep->isUsedParam()) + allD = allU = true; if (allU) m_wholeFlags[FLAG_USED] = true; if (allD) m_wholeFlags[FLAG_DRIVEN] = true; + const char* const what + = nodep->isParam() ? "parameter" : nodep->isGenVar() ? "genvar" : "signal"; // Test results if (nodep->isIfaceRef()) { // For interface top level we don't do any tracking @@ -181,35 +185,39 @@ public: // UNDRIVEN is considered more serious - as is more likely a bug, // thus undriven+unused bits get UNUSED warnings, as they're not as buggy. if (!unusedMatch(nodep)) { - nodep->v3warn(UNUSED, - "Signal is not driven, nor used: " << nodep->prettyNameQ()); + nodep->v3warn(UNUSED, ucfirst(what) << " is not driven, nor used: " + << nodep->prettyNameQ()); nodep->fileline()->modifyWarnOff(V3ErrorCode::UNUSED, true); // Warn only once } } else if (allD && !anyU) { if (!unusedMatch(nodep)) { - nodep->v3warn(UNUSED, "Signal is not used: " << nodep->prettyNameQ()); + nodep->v3warn(UNUSED, ucfirst(what) + << " is not used: " << nodep->prettyNameQ()); nodep->fileline()->modifyWarnOff(V3ErrorCode::UNUSED, true); // Warn only once } } else if (!anyD && allU) { - nodep->v3warn(UNDRIVEN, "Signal is not driven: " << nodep->prettyNameQ()); + nodep->v3warn(UNDRIVEN, ucfirst(what) + << " is not driven: " << nodep->prettyNameQ()); nodep->fileline()->modifyWarnOff(V3ErrorCode::UNDRIVEN, true); // Warn only once } else { // Bits have different dispositions bool setU = false; bool setD = false; if (anynotDU && !unusedMatch(nodep)) { - nodep->v3warn(UNUSED, "Bits of signal are not driven, nor used: " - << nodep->prettyNameQ() << bitNames(BN_BOTH)); + nodep->v3warn(UNUSED, "Bits of " << what << " are not driven, nor used: " + << nodep->prettyNameQ() << bitNames(BN_BOTH)); setU = true; } if (anyDnotU && !unusedMatch(nodep)) { - nodep->v3warn(UNUSED, "Bits of signal are not used: " << nodep->prettyNameQ() - << bitNames(BN_UNUSED)); + nodep->v3warn(UNUSED, "Bits of " << what + << " are not used: " << nodep->prettyNameQ() + << bitNames(BN_UNUSED)); setU = true; } if (anyUnotD) { - nodep->v3warn(UNDRIVEN, "Bits of signal are not driven: " - << nodep->prettyNameQ() << bitNames(BN_UNDRIVEN)); + nodep->v3warn(UNDRIVEN, + "Bits of " << what << " are not driven: " << nodep->prettyNameQ() + << bitNames(BN_UNDRIVEN)); setD = true; } if (setU) { // Warn only once @@ -403,8 +411,8 @@ private: VL_RESTORER(m_alwaysCombp); { AstNode::user2ClearTree(); - if (nodep->keyword() == VAlwaysKwd::ALWAYS_COMB) UINFO(9, " " << nodep << endl); if (nodep->keyword() == VAlwaysKwd::ALWAYS_COMB) { + UINFO(9, " " << nodep << endl); m_alwaysCombp = nodep; } else { m_alwaysCombp = nullptr; diff --git a/src/V3Undriven.h b/src/V3Undriven.h index 2a4e5d18c..52d4361ce 100644 --- a/src/V3Undriven.h +++ b/src/V3Undriven.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Unknown.cpp b/src/V3Unknown.cpp index 0c2dcc553..51ed39b09 100644 --- a/src/V3Unknown.cpp +++ b/src/V3Unknown.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Unknown.h b/src/V3Unknown.h index 2139cf771..b203c7720 100644 --- a/src/V3Unknown.h +++ b/src/V3Unknown.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Unroll.cpp b/src/V3Unroll.cpp index 85b7d4484..28b96f230 100644 --- a/src/V3Unroll.cpp +++ b/src/V3Unroll.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -230,6 +230,7 @@ private: AstConst new_con(clonep->fileline(), *res); new_con.dtypeFrom(dtypep); outNum = new_con.num(); + outNum.isSigned(dtypep->isSigned()); VL_DO_DANGLING(clonep->deleteTree(), clonep); return true; } diff --git a/src/V3Unroll.h b/src/V3Unroll.h index 61b662f1b..e38658d97 100644 --- a/src/V3Unroll.h +++ b/src/V3Unroll.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Waiver.h b/src/V3Waiver.h index 7c93aa52c..165ae1f9f 100644 --- a/src/V3Waiver.h +++ b/src/V3Waiver.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 5fcac846d..e84c0f08a 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -70,6 +70,7 @@ #include "V3Width.h" #include "V3Number.h" #include "V3Const.h" +#include "V3Randomize.h" #include "V3String.h" #include "V3Task.h" @@ -100,6 +101,12 @@ std::ostream& operator<<(std::ostream& str, const Determ& rhs) { return str << s_det[rhs]; } +enum Castable : uint8_t { UNSUPPORTED, COMPATIBLE, DYNAMIC_ENUM, DYNAMIC_CLASS, INCOMPATIBLE }; +std::ostream& operator<<(std::ostream& str, const Castable& rhs) { + static const char* const s_det[] = {"UNSUP", "COMPAT", "DYN_ENUM", "DYN_CLS", "INCOMPAT"}; + return str << s_det[rhs]; +} + //###################################################################### // Width state, as a visitor of each AstNode @@ -247,7 +254,6 @@ private: // Widths: 1 bit out, Any width lhs virtual void visit(AstRedAnd* nodep) override { visit_red_and_or(nodep); } virtual void visit(AstRedOr* nodep) override { visit_red_and_or(nodep); } - virtual void visit(AstRedXnor* nodep) override { visit_red_and_or(nodep); } virtual void visit(AstRedXor* nodep) override { visit_red_and_or(nodep); } virtual void visit(AstOneHot* nodep) override { visit_red_and_or(nodep); } virtual void visit(AstOneHot0* nodep) override { visit_red_and_or(nodep); } @@ -293,7 +299,6 @@ private: // Real: Not allowed virtual void visit(AstAnd* nodep) override { visit_boolmath_and_or(nodep); } virtual void visit(AstOr* nodep) override { visit_boolmath_and_or(nodep); } - virtual void visit(AstXnor* nodep) override { visit_boolmath_and_or(nodep); } virtual void visit(AstXor* nodep) override { visit_boolmath_and_or(nodep); } virtual void visit(AstBufIf1* nodep) override { visit_boolmath_and_or(nodep); @@ -746,21 +751,10 @@ private: // Signed: unsigned output, input either // Convert all range values to constants UINFO(6, "RANGE " << nodep << endl); - V3Const::constifyParamsEdit(nodep->msbp()); // May relink pointed to node - V3Const::constifyParamsEdit(nodep->lsbp()); // May relink pointed to node - checkConstantOrReplace(nodep->msbp(), "MSB of bit range isn't a constant"); - checkConstantOrReplace(nodep->lsbp(), "LSB of bit range isn't a constant"); - int msb = nodep->msbConst(); - int lsb = nodep->lsbConst(); - if (msb < lsb) { - // Little endian bits are legal, just remember to swap - // Warning is in V3Width to avoid false warnings when in "off" generate if's - nodep->littleEndian(!nodep->littleEndian()); - // Internally we'll always have msb() be the greater number - // We only need to correct when doing [] AstSel extraction, - // and when tracing the vector. - nodep->msbp()->swapWith(nodep->lsbp()); - } + V3Const::constifyParamsEdit(nodep->leftp()); // May relink pointed to node + V3Const::constifyParamsEdit(nodep->rightp()); // May relink pointed to node + checkConstantOrReplace(nodep->leftp(), "left side of bit range isn't a constant"); + checkConstantOrReplace(nodep->rightp(), "right side of bit range isn't a constant"); if (m_vup->prelim()) { // Don't need to iterate because V3Const already constified int width = nodep->elementsConst(); @@ -771,8 +765,9 @@ private: // Note width() not set on range; use elementsConst() if (nodep->littleEndian() && !VN_IS(nodep->backp(), UnpackArrayDType) && !VN_IS(nodep->backp(), Cell)) { // For cells we warn in V3Inst - nodep->v3warn(LITENDIAN, "Little bit endian vector: MSB < LSB of bit range: " - << nodep->lsbConst() << ":" << nodep->msbConst()); + nodep->v3warn(LITENDIAN, "Little bit endian vector: left < right of bit range: [" + << nodep->leftConst() << ":" << nodep->rightConst() + << "]"); } } } @@ -800,7 +795,7 @@ private: int width = nodep->widthConst(); UASSERT_OBJ(nodep->dtypep(), nodep, "dtype wasn't set"); // by V3WidthSel if (VN_IS(nodep->lsbp(), Const) && nodep->msbConst() < nodep->lsbConst()) { - nodep->v3warn(E_UNSUPPORTED, "Unsupported: MSB < LSB of bit extract: " + nodep->v3warn(E_UNSUPPORTED, "Unsupported: left < right of bit extract: " << nodep->msbConst() << "<" << nodep->lsbConst()); width = (nodep->lsbConst() - nodep->msbConst() + 1); nodep->dtypeSetLogicSized(width, VSigning::UNSIGNED); @@ -896,8 +891,8 @@ private: int fromlsb; AstNodeDType* fromDtp = nodep->fromp()->dtypep()->skipRefp(); if (const AstUnpackArrayDType* adtypep = VN_CAST(fromDtp, UnpackArrayDType)) { - frommsb = adtypep->msb(); - fromlsb = adtypep->lsb(); + frommsb = adtypep->hi(); + fromlsb = adtypep->lo(); if (fromlsb > frommsb) { int t = frommsb; frommsb = fromlsb; @@ -1451,14 +1446,29 @@ private: // DTYPES virtual void visit(AstNodeArrayDType* nodep) override { if (nodep->didWidthAndSet()) return; // This node is a dtype & not both PRELIMed+FINALed + + if (nodep->subDTypep() == nodep->basicp()) { // Innermost dimension + AstBasicDType* basicp = nodep->basicp(); + // If basic dtype is LOGIC_IMPLICIT, it is actually 1 bit LOGIC + if (basicp->implicit()) { + UASSERT_OBJ(basicp->width() <= 1, basicp, + "must be 1 bit but actually " << basicp->width() << " bits"); + AstBasicDType* newp = new AstBasicDType( + basicp->fileline(), AstBasicDTypeKwd::LOGIC, basicp->numeric()); + newp->widthForce(1, 1); + basicp->replaceWith(newp); + VL_DO_DANGLING(pushDeletep(basicp), basicp); + } + } // Iterate into subDTypep() to resolve that type and update pointer. nodep->refDTypep(iterateEditMoveDTypep(nodep, nodep->subDTypep())); // Cleanup array size userIterateAndNext(nodep->rangep(), WidthVP(SELF, BOTH).p()); nodep->dtypep(nodep); // The array itself, not subDtype - if (VN_IS(nodep, UnpackArrayDType)) { + if (auto* adtypep = VN_CAST(nodep, UnpackArrayDType)) { // Historically array elements have width of the ref type not the full array nodep->widthFromSub(nodep->subDTypep()); + if (nodep->subDTypep()->skipRefp()->isCompound()) adtypep->isCompound(true); } else { int width = nodep->subDTypep()->width() * nodep->rangep()->elementsConst(); nodep->widthForce(width, width); @@ -1626,11 +1636,70 @@ private: } virtual void visit(AstCastDynamic* nodep) override { nodep->dtypeChgWidthSigned(32, 1, VSigning::SIGNED); // Spec says integer return - nodep->v3warn(E_UNSUPPORTED, "Unsupported: $cast. Suggest try static cast."); - AstNode* newp = new AstConst(nodep->fileline(), 1); + userIterateChildren(nodep, WidthVP(SELF, BOTH).p()); + AstNodeDType* toDtp = nodep->top()->dtypep()->skipRefToEnump(); + AstNodeDType* fromDtp = nodep->fromp()->dtypep()->skipRefToEnump(); + FileLine* fl = nodep->fileline(); + const auto castable = computeCastable(toDtp, fromDtp, nodep->fromp()); + AstNode* newp; + if (castable == DYNAMIC_CLASS) { + // Keep in place, will compute at runtime + return; + } else if (castable == DYNAMIC_ENUM) { + // TODO is from is a constant we could simplify, though normal constant + // elimination should do much the same + // Form: "( ((v > size) ? false : enum_valid[v[N:0]]) + // ? ExprStmt(ExprAssign(out, Cast(v, type)), 1) : 0)" + auto* enumDtp = VN_CAST(toDtp, EnumDType); + UASSERT_OBJ(enumDtp, nodep, "$cast determined as enum, but not enum type"); + uint64_t maxval = enumMaxValue(nodep, enumDtp); + int selwidth = V3Number::log2b(maxval) + 1; // Width to address a bit + AstVar* varp = enumVarp(enumDtp, AstAttrType::ENUM_VALID, (1ULL << selwidth) - 1); + AstVarRef* varrefp = new AstVarRef(fl, varp, VAccess::READ); + varrefp->classOrPackagep(v3Global.rootp()->dollarUnitPkgAddp()); + FileLine* fl_nowarn = new FileLine(fl); + fl_nowarn->warnOff(V3ErrorCode::WIDTH, true); + auto* testp = new AstCond{ + fl, + new AstGt{fl_nowarn, nodep->fromp()->cloneTree(false), + new AstConst{fl_nowarn, AstConst::Unsized64{}, maxval}}, + new AstConst{fl, AstConst::BitFalse{}}, + new AstArraySel{fl, varrefp, + new AstSel{fl, nodep->fromp()->cloneTree(false), 0, selwidth}}}; + newp = new AstCond{fl, testp, + new AstExprStmt{fl, + new AstAssign{fl, nodep->top()->unlinkFrBack(), + nodep->fromp()->unlinkFrBack()}, + new AstConst{fl, AstConst::Signed32(), 1}}, + new AstConst{fl, AstConst::Signed32(), 0}}; + } else if (castable == COMPATIBLE) { + nodep->v3warn(CASTCONST, "$cast will always return one as " + << toDtp->prettyDTypeNameQ() + << " is always castable from " + << fromDtp->prettyDTypeNameQ() << '\n' + << nodep->warnMore() << "... Suggest static cast"); + newp = new AstExprStmt{ + fl, + new AstAssign{fl, nodep->top()->unlinkFrBack(), + new AstCast{fl, nodep->fromp()->unlinkFrBack(), toDtp}}, + new AstConst{fl, AstConst::Signed32(), 1}}; + } else if (castable == INCOMPATIBLE) { + newp = new AstConst{fl, 0}; + nodep->v3warn(CASTCONST, "$cast will always return zero as " + << toDtp->prettyDTypeNameQ() << " is not castable from " + << fromDtp->prettyDTypeNameQ()); + } else { + newp = new AstConst{fl, 0}; + nodep->v3warn(E_UNSUPPORTED, "Unsupported: $cast to " + << toDtp->prettyDTypeNameQ() << " from " + << fromDtp->prettyDTypeNameQ() << '\n' + << nodep->warnMore() + << "... Suggest try static cast"); + } newp->dtypeFrom(nodep); nodep->replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep); + userIterate(newp, m_vup); } virtual void visit(AstCastParse* nodep) override { // nodep->dtp could be data type, or a primary_constant @@ -1651,53 +1720,86 @@ private: } virtual void visit(AstCast* nodep) override { nodep->dtypep(iterateEditMoveDTypep(nodep, nodep->subDTypep())); - // if (debug()) nodep->dumpTree(cout, " CastPre: "); - userIterateAndNext(nodep->lhsp(), WidthVP(SELF, PRELIM).p()); - - // When more general casts are supported, the cast elimination will be done later. - // For now, replace it ASAP, so widthing can propagate easily - // The cast may change signing, but we don't know the sign yet. Make it so. - // Note we don't sign lhsp() that would make the algorithm O(n^2) if lots of casting. - AstBasicDType* basicp = nodep->dtypep()->basicp(); - UASSERT_OBJ(basicp, nodep, "Unimplemented: Casting non-simple data type"); if (m_vup->prelim()) { - userIterateAndNext(nodep->lhsp(), WidthVP(SELF, PRELIM).p()); - // When implement more complicated types need to convert childDTypep to - // dtypep() not as a child - if (!basicp->isDouble() && !nodep->lhsp()->isDouble()) { - // Note castSized might modify nodep->lhsp() - int width = nodep->dtypep()->width(); - castSized(nodep, nodep->lhsp(), width); + // if (debug()) nodep->dumpTree(cout, " CastPre: "); + userIterateAndNext(nodep->fromp(), WidthVP(SELF, PRELIM).p()); + AstNodeDType* toDtp = nodep->dtypep()->skipRefToEnump(); + AstNodeDType* fromDtp = nodep->fromp()->dtypep()->skipRefToEnump(); + const auto castable = computeCastable(toDtp, fromDtp, nodep->fromp()); + bool bad = false; + if (castable == UNSUPPORTED) { + nodep->v3warn(E_UNSUPPORTED, "Unsupported: static cast to " + << toDtp->prettyDTypeNameQ() << " from " + << fromDtp->prettyDTypeNameQ()); + bad = true; + } else if (castable == COMPATIBLE || castable == DYNAMIC_ENUM) { + ; // Continue + } else if (castable == DYNAMIC_CLASS) { + nodep->v3error("Dynamic, not static cast, required to cast " + << toDtp->prettyDTypeNameQ() << " from " + << fromDtp->prettyDTypeNameQ() << '\n' + << nodep->warnMore() << "... Suggest dynamic $cast"); + bad = true; + } else if (castable == INCOMPATIBLE) { + nodep->v3error("Incompatible types to static cast to " + << toDtp->prettyDTypeNameQ() << " from " + << fromDtp->prettyDTypeNameQ() << '\n'); + bad = true; } else { - iterateCheck(nodep, "value", nodep->lhsp(), SELF, FINAL, nodep->lhsp()->dtypep(), - EXTEND_EXP, false); + nodep->v3fatalSrc("bad casting case"); } - AstNode* newp = nodep->lhsp()->unlinkFrBack(); - if (basicp->isDouble() && !newp->isDouble()) { - if (newp->isSigned()) { - newp = new AstISToRD(nodep->fileline(), newp); + // For now, replace it ASAP, so widthing can propagate easily + // The cast may change signing, but we don't know the sign yet. Make it so. + // Note we don't sign fromp() that would make the algorithm O(n^2) if lots of casting. + AstNode* newp = nullptr; + if (bad) { + } else if (AstBasicDType* basicp = toDtp->basicp()) { + if (!basicp->isDouble() && !fromDtp->isDouble()) { + int width = toDtp->width(); + castSized(nodep, nodep->fromp(), width); + // Note castSized might modify nodep->fromp() } else { - newp = new AstIToRD(nodep->fileline(), newp); + iterateCheck(nodep, "value", nodep->lhsp(), SELF, FINAL, fromDtp, EXTEND_EXP, + false); } - } else if (!basicp->isDouble() && newp->isDouble()) { - if (basicp->isSigned()) { - newp = new AstRToIRoundS(nodep->fileline(), newp); + if (basicp->isDouble() && !nodep->fromp()->isDouble()) { + if (nodep->fromp()->isSigned()) { + newp = new AstISToRD(nodep->fileline(), nodep->fromp()->unlinkFrBack()); + } else { + newp = new AstIToRD(nodep->fileline(), nodep->fromp()->unlinkFrBack()); + } + } else if (!basicp->isDouble() && nodep->fromp()->isDouble()) { + if (basicp->isSigned()) { + newp + = new AstRToIRoundS(nodep->fileline(), nodep->fromp()->unlinkFrBack()); + } else { + newp = new AstUnsigned( + nodep->fileline(), + new AstRToIS(nodep->fileline(), nodep->fromp()->unlinkFrBack())); + } + } else if (basicp->isSigned() && !nodep->fromp()->isSigned()) { + newp = new AstSigned(nodep->fileline(), nodep->fromp()->unlinkFrBack()); + } else if (!basicp->isSigned() && nodep->fromp()->isSigned()) { + newp = new AstUnsigned(nodep->fileline(), nodep->fromp()->unlinkFrBack()); } else { - newp = new AstUnsigned(nodep->fileline(), - new AstRToIS(nodep->fileline(), newp)); + // Can just remove cast } - } else if (basicp->isSigned() && !newp->isSigned()) { - newp = new AstSigned(nodep->fileline(), newp); - } else if (!basicp->isSigned() && newp->isSigned()) { - newp = new AstUnsigned(nodep->fileline(), newp); + } else if (VN_IS(toDtp, ClassRefDType)) { + // Can just remove cast } else { - // newp = newp; // Can just remove cast + nodep->v3fatalSrc("Unimplemented: Casting non-simple data type " + << toDtp->prettyDTypeNameQ()); } + if (!newp) newp = nodep->fromp()->unlinkFrBack(); nodep->lhsp(newp); - // if (debug()) nodep->dumpTree(cout, " CastOut: "); + if (debug()) nodep->dumpTree(cout, " CastOut: "); + if (debug()) nodep->backp()->dumpTree(cout, " CastOutUpUp: "); } if (m_vup->final()) { + iterateCheck(nodep, "value", nodep->lhsp(), SELF, FINAL, nodep->lhsp()->dtypep(), + EXTEND_EXP, false); AstNode* underp = nodep->lhsp()->unlinkFrBack(); + if (debug()) underp->dumpTree(cout, " CastRep: "); nodep->replaceWith(underp); VL_DO_DANGLING(pushDeletep(nodep), nodep); } @@ -1830,7 +1932,7 @@ private: // "foo[0]" from a parameter but not a wire nodep->dtypeChgWidthSigned(width, nodep->valuep()->widthMin(), VSigning::fromBool(issigned)); - nodep->dtypep(nodep->findLogicRangeDType(VNumRange(0, 0, false), + nodep->dtypep(nodep->findLogicRangeDType(VNumRange{0, 0}, nodep->valuep()->widthMin(), VSigning::fromBool(issigned))); } else { @@ -1958,7 +2060,7 @@ private: << otherp->warnOther() << "... Location of original declaration\n" << otherp->warnContextSecondary()); } else { - inits.insert(make_pair(num, itemp)); + inits.emplace(num, itemp); } num.opAdd(one, constp->num()); } @@ -2123,12 +2225,21 @@ private: for (AstNode *nextip, *itemp = nodep->itemsp(); itemp; itemp = nextip) { nextip = itemp->nextp(); // Will be unlinking AstNode* inewp; + AstNodeDType* itemDtp = itemp->dtypep()->skipRefp(); if (AstInsideRange* irangep = VN_CAST(itemp, InsideRange)) { // Similar logic in V3Case inewp = irangep->newAndFromInside(nodep->exprp(), irangep->lhsp()->unlinkFrBack(), irangep->rhsp()->unlinkFrBack()); - } else if (auto* irangep = VN_CAST(itemp->dtypep(), UnpackArrayDType)) { - irangep->v3error("Unsupported: inside on unpacked array"); + } else if (VN_IS(itemDtp, UnpackArrayDType)) { + nodep->v3error("Unsupported: inside (set membership operator) on unpacked array"); + // Need the AstInside type to persist, then + // for parameters, need V3Simulate support. + // For non-parameters, need runtime support. + continue; + } else if (VN_IS(itemDtp, AssocArrayDType) || VN_IS(itemDtp, DynArrayDType) + || VN_IS(itemDtp, QueueDType)) { + nodep->v3error( + "Inside operator not legal on non-unpacked arrays (IEEE 1800-2017 11.4.13)"); continue; } else { inewp = new AstEqWild(itemp->fileline(), nodep->exprp()->cloneTree(true), @@ -2849,6 +2960,10 @@ private: void methodCallClass(AstMethodCall* nodep, AstClassRefDType* adtypep) { // No need to width-resolve the class, as it was done when we did the child AstClass* first_classp = adtypep->classp(); + if (nodep->name() == "randomize") { + v3Global.useRandomizeMethods(true); + V3Randomize::newRandomizeFunc(first_classp); + } UASSERT_OBJ(first_classp, nodep, "Unlinked"); for (AstClass* classp = first_classp; classp;) { if (AstNodeFTask* ftaskp = VN_CAST(classp->findMember(nodep->name()), NodeFTask)) { @@ -3256,8 +3371,7 @@ private: patp = nullptr; break; } else { - std::pair ret - = patmap.insert(make_pair(memp, patp)); + std::pair ret = patmap.emplace(memp, patp); if (!ret.second) { patp->v3error("Assignment pattern contains duplicate entry: " << VN_CAST(patp->keyp(), Text)->text()); @@ -3603,6 +3717,12 @@ private: iterateCheckBool(nodep, "If", nodep->condp(), BOTH); // it's like an if() condition. // if (debug()) nodep->dumpTree(cout, " IfOut: "); } + virtual void visit(AstExprStmt* nodep) override { + userIterateAndNext(nodep->stmtsp(), nullptr); + // expected result is same as parent's expected result + userIterateAndNext(nodep->resultp(), m_vup); + nodep->dtypeFrom(nodep->resultp()); + } virtual void visit(AstNodeAssign* nodep) override { // IEEE-2012 10.7, 11.8.2, 11.8.3, 11.5: (Careful of 11.8.1 which is @@ -4001,6 +4121,12 @@ private: userIterateAndNext(nodep->passsp(), nullptr); userIterateAndNext(nodep->failsp(), nullptr); } + virtual void visit(AstAssertIntrinsic* nodep) override { + assertAtStatement(nodep); + iterateCheckBool(nodep, "Property", nodep->propp(), BOTH); // it's like an if() condition. + userIterateAndNext(nodep->passsp(), nullptr); + userIterateAndNext(nodep->failsp(), nullptr); + } virtual void visit(AstCover* nodep) override { assertAtStatement(nodep); iterateCheckBool(nodep, "Property", nodep->propp(), BOTH); // it's like an if() condition. @@ -4027,14 +4153,17 @@ private: // Very much like like an assignment, but which side is LH/RHS // depends on pin being a in/output/inout. userIterateAndNext(nodep->exprp(), WidthVP(nodep->modVarp()->dtypep(), PRELIM).p()); - AstNodeDType* pinDTypep = nodep->modVarp()->dtypep(); + AstNodeDType* modDTypep = nodep->modVarp()->dtypep(); AstNodeDType* conDTypep = nodep->exprp()->dtypep(); + if (!modDTypep) nodep->v3fatalSrc("Unlinked pin data type"); if (!conDTypep) nodep->v3fatalSrc("Unlinked pin data type"); - AstNodeDType* subDTypep = pinDTypep; - int pinwidth = pinDTypep->width(); + modDTypep = modDTypep->skipRefp(); + conDTypep = conDTypep->skipRefp(); + AstNodeDType* subDTypep = modDTypep; + int pinwidth = modDTypep->width(); int conwidth = conDTypep->width(); - if (conDTypep == pinDTypep // If match, we're golden - || similarDTypeRecurse(conDTypep, pinDTypep)) { + if (conDTypep == modDTypep // If match, we're golden + || similarDTypeRecurse(conDTypep, modDTypep)) { userIterateAndNext(nodep->exprp(), WidthVP(subDTypep, FINAL).p()); } else if (m_cellp->rangep()) { int numInsts = m_cellp->rangep()->elementsConst(); @@ -4062,11 +4191,13 @@ private: nodep->v3error("Ref connection " << nodep->modVarp()->prettyNameQ() << " requires matching types;" - << " ref requires " << pinDTypep->prettyDTypeNameQ() + << " ref requires " << modDTypep->prettyDTypeNameQ() << " data type but connection is " << conDTypep->prettyDTypeNameQ() << " data type."); } else if (nodep->modVarp()->isTristate()) { if (pinwidth != conwidth) { + // Ideally should call pinReconnectSimple which would tolerate this + // then have a conversion warning nodep->v3warn(E_UNSUPPORTED, "Unsupported: " << ucfirst(nodep->prettyOperatorName()) << " to inout signal requires " << pinwidth @@ -4075,26 +4206,30 @@ private: << " generates " << conwidth << " bits."); // otherwise would need some mess to force both sides to proper size } + } else if (nodep->modVarp()->direction().isWritable() + && ((conDTypep->isDouble() && !modDTypep->isDouble()) + || (!conDTypep->isDouble() && modDTypep->isDouble()))) { + nodep->v3warn(E_UNSUPPORTED, + "Unsupported: " << ucfirst(nodep->prettyOperatorName()) + << " connects real to non-real"); } + // Check if an interface is connected to a non-interface and vice versa - AstNodeDType* modDTypep = nodep->modVarp()->dtypep(); - AstNodeDType* exprDTypep = nodep->exprp()->dtypep(); - if ((VN_IS(modDTypep, IfaceRefDType) && !VN_IS(exprDTypep, IfaceRefDType)) - || (VN_IS(exprDTypep, IfaceRefDType) && !VN_IS(modDTypep, IfaceRefDType))) { + if ((VN_IS(modDTypep, IfaceRefDType) && !VN_IS(conDTypep, IfaceRefDType)) + || (VN_IS(conDTypep, IfaceRefDType) && !VN_IS(modDTypep, IfaceRefDType))) { nodep->v3error("Illegal " << nodep->prettyOperatorName() << "," << " mismatch between port which is" << (VN_CAST(modDTypep, IfaceRefDType) ? "" : " not") << " an interface," << " and expression which is" - << (VN_CAST(exprDTypep, IfaceRefDType) ? "" : " not") + << (VN_CAST(conDTypep, IfaceRefDType) ? "" : " not") << " an interface."); } // TODO Simple dtype checking, should be a more general check - AstNodeArrayDType* exprArrayp = VN_CAST(exprDTypep->skipRefp(), UnpackArrayDType); - AstNodeArrayDType* modArrayp = VN_CAST(modDTypep->skipRefp(), UnpackArrayDType); - if (exprArrayp && modArrayp - && VN_IS(exprArrayp->subDTypep()->skipRefp(), IfaceRefDType) + AstNodeArrayDType* exprArrayp = VN_CAST(conDTypep, UnpackArrayDType); + AstNodeArrayDType* modArrayp = VN_CAST(modDTypep, UnpackArrayDType); + if (exprArrayp && modArrayp && VN_IS(exprArrayp->subDTypep(), IfaceRefDType) && exprArrayp->declRange().elements() != modArrayp->declRange().elements()) { int exprSize = exprArrayp->declRange().elements(); int modSize = modArrayp->declRange().elements(); @@ -4104,8 +4239,8 @@ private: << modSize << "," << " and expression which is an interface array of size " << exprSize << "."); - UINFO(1, " Related lo: " << modDTypep->skipRefp() << endl); - UINFO(1, " Related hi: " << exprDTypep->skipRefp() << endl); + UINFO(1, " Related lo: " << modDTypep << endl); + UINFO(1, " Related hi: " << conDTypep << endl); } else if ((exprArrayp && !modArrayp) || (!exprArrayp && modArrayp)) { nodep->v3error("Illegal " << nodep->prettyOperatorName() << "," << " mismatch between port which is" @@ -4113,8 +4248,8 @@ private: << " and expression which is" << (exprArrayp ? "" : " not") << " an array. (IEEE 1800-2017 7.6)"); - UINFO(1, " Related lo: " << modDTypep->skipRefp() << endl); - UINFO(1, " Related hi: " << exprDTypep->skipRefp() << endl); + UINFO(1, " Related lo: " << modDTypep << endl); + UINFO(1, " Related hi: " << conDTypep << endl); } iterateCheckAssign(nodep, "pin connection", nodep->exprp(), FINAL, subDTypep); } @@ -4407,8 +4542,8 @@ private: virtual void visit(AstWith* nodep) override { // Should otherwise be underneath a method call AstNodeDType* vdtypep = m_vup->dtypeNullSkipRefp(); - VL_RESTORER(m_withp); { + VL_RESTORER(m_withp); m_withp = nodep; userIterateChildren(nodep->indexArgRefp(), nullptr); userIterateChildren(nodep->valueArgRefp(), nullptr); @@ -5444,7 +5579,9 @@ private: case AstType::atMulS: newp = new AstMul(fl, lhsp, rhsp); break; case AstType::atShiftR: newp = new AstShiftRS(fl, lhsp, rhsp); break; case AstType::atShiftRS: newp = new AstShiftR(fl, lhsp, rhsp); break; - default: nodep->v3fatalSrc("Node needs sign change, but bad case: " << nodep); break; + default: // LCOV_EXCL_LINE + nodep->v3fatalSrc("Node needs sign change, but bad case: " << nodep); + break; } UINFO(6, " ReplaceWithUOrSVersion: " << nodep << " w/ " << newp << endl); nodep->replaceWith(newp); @@ -5481,7 +5618,7 @@ private: case AstType::atDivS: newp = new AstDivD(fl, lhsp, rhsp); break; case AstType::atMul: case AstType::atMulS: newp = new AstMulD(fl, lhsp, rhsp); break; - default: + default: // LCOV_EXCL_LINE nodep->v3fatalSrc("Node needs conversion to double, but bad case: " << nodep); break; } @@ -5513,7 +5650,7 @@ private: case AstType::atLtS: newp = new AstLtN(fl, lhsp, rhsp); break; case AstType::atLte: case AstType::atLteS: newp = new AstLteN(fl, lhsp, rhsp); break; - default: + default: // LCOV_EXCL_LINE nodep->v3fatalSrc("Node needs conversion to string, but bad case: " << nodep); break; } @@ -5532,7 +5669,7 @@ private: AstNodeUniop* newp = nullptr; switch (nodep->type()) { case AstType::atNegate: newp = new AstNegateD(fl, lhsp); break; - default: + default: // LCOV_EXCL_LINE nodep->v3fatalSrc("Node needs conversion to double, but bad case: " << nodep); break; } @@ -5627,7 +5764,7 @@ private: if (adtypep->isRanged()) declRange = adtypep->declRange(); break; } - break; + break; // LCOV_EXCL_LINE } AstConst* valp = nullptr; // If nullptr, construct from val int val = 0; @@ -5657,7 +5794,7 @@ private: } else { val = bits; } - break; + break; // LCOV_EXCL_LINE } case AstAttrType::DIM_HIGH: val = !declRange.ranged() ? 0 : declRange.hi(); break; case AstAttrType::DIM_LEFT: val = !declRange.ranged() ? 0 : declRange.left(); break; @@ -5698,7 +5835,7 @@ private: initp->addValuep(dimensionValue(nodep->fileline(), nodep, attrType, i)); } userIterate(varp, nullptr); // May have already done $unit so must do this var - m_tableMap.insert(make_pair(make_pair(nodep, attrType), varp)); + m_tableMap.emplace(make_pair(nodep, attrType), varp); return varp; } uint64_t enumMaxValue(const AstNode* errNodep, const AstEnumDType* adtypep) { @@ -5730,6 +5867,12 @@ private: AstNodeDType* basep; if (attrType == AstAttrType::ENUM_NAME) { basep = nodep->findStringDType(); + } else if (attrType == AstAttrType::ENUM_VALID) { + // TODO in theory we could bit-pack the bits in the table, but + // would require additional operations to extract, so only + // would be worth it for larger tables which perhaps could be + // better handled with equation generation? + basep = nodep->findBitDType(); } else { basep = nodep->dtypep(); } @@ -5752,6 +5895,8 @@ private: initp->defaultp(new AstConst(nodep->fileline(), AstConst::String(), "")); } else if (attrType == AstAttrType::ENUM_NEXT || attrType == AstAttrType::ENUM_PREV) { initp->defaultp(new AstConst(nodep->fileline(), V3Number(nodep, nodep->width(), 0))); + } else if (attrType == AstAttrType::ENUM_VALID) { + initp->defaultp(new AstConst{nodep->fileline(), AstConst::BitFalse{}}); } else { nodep->v3fatalSrc("Bad case"); } @@ -5776,6 +5921,8 @@ private: values[i] = (nextp ? nextp : firstp)->valuep()->cloneTree(false); // A const } else if (attrType == AstAttrType::ENUM_PREV) { values[i] = prevp->valuep()->cloneTree(false); // A const + } else if (attrType == AstAttrType::ENUM_VALID) { + values[i] = new AstConst(nodep->fileline(), AstConst::BitTrue{}); } else { nodep->v3fatalSrc("Bad case"); } @@ -5785,11 +5932,10 @@ private: } // Add all specified values to table for (unsigned i = 0; i < (msbdim + 1); ++i) { - AstNode* valp = values[i]; - if (valp) initp->addIndexValuep(i, valp); + if (values[i]) initp->addIndexValuep(i, values[i]); } userIterate(varp, nullptr); // May have already done $unit so must do this var - m_tableMap.insert(make_pair(make_pair(nodep, attrType), varp)); + m_tableMap.emplace(make_pair(nodep, attrType), varp); return varp; } @@ -5809,7 +5955,7 @@ private: if (patmap.find(element) != patmap.end()) { patp->v3error("Assignment pattern key used multiple times: " << element); } else { - patmap.insert(make_pair(element, patp)); + patmap.emplace(element, patp); } element += range.leftToRightInc(); } @@ -5860,6 +6006,48 @@ private: return false; } + //---------------------------------------------------------------------- + // METHODS - casting + static Castable computeCastable(AstNodeDType* toDtp, AstNodeDType* fromDtp, + AstNode* fromConstp) { + const auto castable = computeCastableImp(toDtp, fromDtp, fromConstp); + UINFO(9, " castable=" << castable << " for " << toDtp << endl); + UINFO(9, " =?= " << fromDtp << endl); + UINFO(9, " const= " << fromConstp << endl); + return castable; + } + static Castable computeCastableImp(AstNodeDType* toDtp, AstNodeDType* fromDtp, + AstNode* fromConstp) { + Castable castable = UNSUPPORTED; + toDtp = toDtp->skipRefToEnump(); + fromDtp = fromDtp->skipRefToEnump(); + if (toDtp == fromDtp) return COMPATIBLE; + bool fromNumericable = VN_IS(fromDtp, BasicDType) || VN_IS(fromDtp, EnumDType) + || VN_IS(fromDtp, NodeUOrStructDType); + // UNSUP unpacked struct/unions (treated like BasicDType) + if (VN_IS(toDtp, BasicDType) || VN_IS(toDtp, NodeUOrStructDType)) { + if (fromNumericable) return COMPATIBLE; + } else if (VN_IS(toDtp, EnumDType)) { + if (fromNumericable) return DYNAMIC_ENUM; + } else if (VN_IS(toDtp, ClassRefDType) && VN_IS(fromConstp, Const)) { + if (VN_IS(fromConstp, Const) && VN_CAST(fromConstp, Const)->num().isNull()) + return COMPATIBLE; + } else if (VN_IS(toDtp, ClassRefDType) && VN_IS(fromDtp, ClassRefDType)) { + const auto toClassp = VN_CAST(toDtp, ClassRefDType)->classp(); + const auto fromClassp = VN_CAST(fromDtp, ClassRefDType)->classp(); + bool downcast = AstClass::isClassExtendedFrom(toClassp, fromClassp); + bool upcast = AstClass::isClassExtendedFrom(fromClassp, toClassp); + if (upcast) { + return COMPATIBLE; + } else if (downcast) { + return DYNAMIC_CLASS; + } else { + return INCOMPATIBLE; + } + } + return castable; + } + //---------------------------------------------------------------------- // METHODS - special type detection void assertAtStatement(AstNode* nodep) { @@ -5908,50 +6096,45 @@ private: AstNode* userIterateSubtreeReturnEdits(AstNode* nodep, WidthVP* vup) { if (!nodep) return nullptr; - WidthVP* saveVup = m_vup; AstNode* ret; { + VL_RESTORER(m_vup); m_vup = vup; ret = iterateSubtreeReturnEdits(nodep); } - m_vup = saveVup; return ret; } void userIterate(AstNode* nodep, WidthVP* vup) { if (!nodep) return; - WidthVP* saveVup = m_vup; { + VL_RESTORER(m_vup); m_vup = vup; iterate(nodep); } - m_vup = saveVup; } void userIterateAndNext(AstNode* nodep, WidthVP* vup) { if (!nodep) return; - WidthVP* saveVup = m_vup; { + VL_RESTORER(m_vup); m_vup = vup; iterateAndNextNull(nodep); } - m_vup = saveVup; } void userIterateChildren(AstNode* nodep, WidthVP* vup) { if (!nodep) return; - WidthVP* saveVup = m_vup; { + VL_RESTORER(m_vup); m_vup = vup; iterateChildren(nodep); } - m_vup = saveVup; } void userIterateChildrenBackwards(AstNode* nodep, WidthVP* vup) { if (!nodep) return; - WidthVP* saveVup = m_vup; { + VL_RESTORER(m_vup); m_vup = vup; iterateChildrenBackwards(nodep); } - m_vup = saveVup; } public: diff --git a/src/V3Width.h b/src/V3Width.h index 03e1fb037..db2d0cccc 100644 --- a/src/V3Width.h +++ b/src/V3Width.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3WidthCommit.h b/src/V3WidthCommit.h index b84b5a110..7ffb9fb8d 100644 --- a/src/V3WidthCommit.h +++ b/src/V3WidthCommit.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/V3WidthSel.cpp b/src/V3WidthSel.cpp index 37f5959ff..3769c1923 100644 --- a/src/V3WidthSel.cpp +++ b/src/V3WidthSel.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -96,8 +96,8 @@ private: } else if (adtypep->isRanged()) { UASSERT_OBJ( !(adtypep->rangep() - && (!VN_IS(adtypep->rangep()->msbp(), Const) - || !VN_IS(adtypep->rangep()->lsbp(), Const))), + && (!VN_IS(adtypep->rangep()->leftp(), Const) + || !VN_IS(adtypep->rangep()->rightp(), Const))), nodep, "Non-constant variable range; errored earlier"); // in constifyParam(bfdtypep) fromRange = adtypep->declRange(); @@ -204,7 +204,7 @@ private: UINFO(6, "SELBIT " << nodep << endl); if (debug() >= 9) nodep->backp()->dumpTree(cout, "--SELBT0: "); // lhsp/rhsp do not need to be constant - AstNode* fromp = nodep->lhsp()->unlinkFrBack(); + AstNode* fromp = nodep->fromp()->unlinkFrBack(); AstNode* rhsp = nodep->rhsp()->unlinkFrBack(); // bit we're extracting if (debug() >= 9) nodep->dumpTree(cout, "--SELBT2: "); FromData fromdata = fromDataForArray(nodep, fromp); @@ -225,12 +225,10 @@ private: } else if (AstPackArrayDType* adtypep = VN_CAST(ddtypep, PackArrayDType)) { // SELBIT(array, index) -> SEL(array, index*width-of-subindex, width-of-subindex) AstNode* subp = rhsp; - if (fromRange.lo() != 0 || fromRange.hi() < 0) { - if (fromRange.littleEndian()) { - subp = newSubNeg(fromRange.hi(), subp); - } else { - subp = newSubNeg(subp, fromRange.lo()); - } + if (fromRange.littleEndian()) { + subp = newSubNeg(fromRange.hi(), subp); + } else { + subp = newSubNeg(subp, fromRange.lo()); } UASSERT_OBJ(!(!fromRange.elements() || (adtypep->width() % fromRange.elements()) != 0), adtypep, @@ -324,14 +322,14 @@ private: UINFO(6, "SELEXTRACT " << nodep << endl); // if (debug() >= 9) nodep->dumpTree(cout, "--SELEX0: "); // Below 2 lines may change nodep->widthp() - V3Const::constifyParamsEdit(nodep->lsbp()); // May relink pointed to node - V3Const::constifyParamsEdit(nodep->msbp()); // May relink pointed to node + V3Const::constifyParamsEdit(nodep->leftp()); // May relink pointed to node + V3Const::constifyParamsEdit(nodep->rightp()); // May relink pointed to node // if (debug() >= 9) nodep->dumpTree(cout, "--SELEX3: "); - checkConstantOrReplace(nodep->lsbp(), + checkConstantOrReplace(nodep->leftp(), "First value of [a:b] isn't a constant, maybe you want +: or -:"); - checkConstantOrReplace(nodep->msbp(), + checkConstantOrReplace(nodep->rightp(), "Second value of [a:b] isn't a constant, maybe you want +: or -:"); - AstNode* fromp = nodep->lhsp()->unlinkFrBack(); + AstNode* fromp = nodep->fromp()->unlinkFrBack(); AstNode* msbp = nodep->rhsp()->unlinkFrBack(); AstNode* lsbp = nodep->thsp()->unlinkFrBack(); vlsint32_t msb = VN_CAST(msbp, Const)->toSInt(); @@ -351,9 +349,9 @@ private: nodep->replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep); } else { // Slice - AstSliceSel* newp = new AstSliceSel( - nodep->fileline(), fromp, - VNumRange(VNumRange::LeftRight(), msb - fromRange.lo(), lsb - fromRange.lo())); + AstSliceSel* newp + = new AstSliceSel{nodep->fileline(), fromp, + VNumRange{msb - fromRange.lo(), lsb - fromRange.lo()}}; nodep->replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep); } @@ -474,7 +472,7 @@ private: checkConstantOrReplace(nodep->thsp(), "Width of :+ or :- bit extract isn't a constant"); if (debug() >= 9) nodep->dumpTree(cout, "--SELPM3: "); // Now replace it with an AstSel - AstNode* fromp = nodep->lhsp()->unlinkFrBack(); + AstNode* fromp = nodep->fromp()->unlinkFrBack(); AstNode* rhsp = nodep->rhsp()->unlinkFrBack(); AstNode* widthp = nodep->thsp()->unlinkFrBack(); warnTri(rhsp); diff --git a/src/Verilator.cpp b/src/Verilator.cpp index a676082b5..342506342 100644 --- a/src/Verilator.cpp +++ b/src/Verilator.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -23,6 +23,7 @@ #include "V3AssertPre.h" #include "V3Begin.h" #include "V3Branch.h" +#include "V3Broken.h" #include "V3CCtors.h" #include "V3CUse.h" #include "V3Case.h" @@ -75,6 +76,7 @@ #include "V3PreShell.h" #include "V3Premit.h" #include "V3ProtectLib.h" +#include "V3Randomize.h" #include "V3Reloop.h" #include "V3Scope.h" #include "V3Scoreboard.h" @@ -179,6 +181,9 @@ static void process() { // Before we do dead code elimination and inlining, or we'll lose it. if (v3Global.opt.coverage()) V3Coverage::coverage(v3Global.rootp()); + // Add randomize() class methods if they are used by the design + if (v3Global.useRandomizeMethods()) V3Randomize::randomizeNetlist(v3Global.rootp()); + // Push constants, but only true constants preserving liveness // so V3Undriven sees variables to be eliminated, ie "if (0 && foo) ..." V3Const::constifyAllLive(v3Global.rootp()); @@ -570,6 +575,7 @@ static void verilate(const string& argString) { V3TSP::selfTest(); V3ScoreboardBase::selfTest(); V3Partition::selfTest(); + V3Broken::selfTest(); } // Read first filename diff --git a/src/VlcBucket.h b/src/VlcBucket.h index 4a2c30afc..b59f1d6c2 100644 --- a/src/VlcBucket.h +++ b/src/VlcBucket.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/VlcMain.cpp b/src/VlcMain.cpp index 6375c2a09..45be06f0c 100644 --- a/src/VlcMain.cpp +++ b/src/VlcMain.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -130,7 +130,7 @@ void VlcOptions::showVersion(bool verbose) { if (!verbose) return; cout << endl; - cout << "Copyright 2003-2020 by Wilson Snyder. Verilator is free software; you can\n"; + cout << "Copyright 2003-2021 by Wilson Snyder. Verilator is free software; you can\n"; cout << "redistribute it and/or modify the Verilator internals under the terms of\n"; cout << "either the GNU Lesser General Public License Version 3 or the Perl Artistic\n"; cout << "License Version 2.0.\n"; diff --git a/src/VlcOptions.h b/src/VlcOptions.h index 53940bbb9..fc999c7fb 100644 --- a/src/VlcOptions.h +++ b/src/VlcOptions.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/VlcPoint.h b/src/VlcPoint.h index 36eea2feb..e8b11d197 100644 --- a/src/VlcPoint.h +++ b/src/VlcPoint.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -130,7 +130,7 @@ public: VlcPoint point(name, pointnum); point.countInc(count); m_points.push_back(point); - m_nameMap.insert(make_pair(point.name(), point.pointNum())); + m_nameMap.emplace(point.name(), point.pointNum()); } return pointnum; } diff --git a/src/VlcSource.h b/src/VlcSource.h index 7874b9de0..18abda529 100644 --- a/src/VlcSource.h +++ b/src/VlcSource.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/VlcTest.h b/src/VlcTest.h index 5cc1c3ae2..71d8a8f52 100644 --- a/src/VlcTest.h +++ b/src/VlcTest.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/VlcTop.cpp b/src/VlcTop.cpp index cd87e5879..b4969ed53 100644 --- a/src/VlcTop.cpp +++ b/src/VlcTop.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/VlcTop.h b/src/VlcTop.h index 4284c69ed..28c6ce972 100644 --- a/src/VlcTop.h +++ b/src/VlcTop.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/astgen b/src/astgen index 60f20a283..c69a40417 100644 --- a/src/astgen +++ b/src/astgen @@ -769,7 +769,7 @@ Makes a report report. =head1 DISTRIBUTION -Copyright 2002-2020 by Wilson Snyder. This program is free software; you +Copyright 2002-2021 by Wilson Snyder. This program is free software; you can redistribute it and/or modify it under the terms of either the GNU Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. diff --git a/src/bisonpre b/src/bisonpre index 48cf26eb3..f4555c823 100755 --- a/src/bisonpre +++ b/src/bisonpre @@ -581,7 +581,7 @@ This is part of the L free Verilog EDA software tool suite. The latest version is available from CPAN and from L. -Copyright 2008-2020 by Wilson Snyder. This program is free software; you +Copyright 2008-2021 by Wilson Snyder. This program is free software; you can redistribute it and/or modify it under the terms of either the GNU Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. diff --git a/src/config_build.h.in b/src/config_build.h.in index f31046e03..a43093249 100644 --- a/src/config_build.h.in +++ b/src/config_build.h.in @@ -8,7 +8,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. diff --git a/src/config_rev b/src/config_rev new file mode 100755 index 000000000..a3dde7222 --- /dev/null +++ b/src/config_rev @@ -0,0 +1,42 @@ +#!/usr/bin/env python3 +###################################################################### +# +# Copyright 2005-2021 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 +# +###################################################################### +# DESCRIPTION: Query git to get version number + +import argparse +import os +import re +import sys + +parser = argparse.ArgumentParser() +parser.add_argument('directory') +Args = parser.parse_args() + +os.chdir(Args.directory) + +rev = 'UNKNOWN_REV' +data = os.popen('git describe').read() + +match = re.search(r'^(v[0-9].*)', data) +if match: + rev = match.group(1) +rev = re.sub('_', '.', rev) + +data = os.popen('git status').read() +if (re.search('Changed but not updated', data, flags=re.IGNORECASE) + or re.search('Changes to be committed', data, flags=re.IGNORECASE) + or re.search('Changes not staged', data, flags=re.IGNORECASE)): + rev += " (mod)" + +print("static const char* const DTVERSION_rev = \"" + rev + "\";") + +# Warn after the print, so at least the header has good contents +if re.search('UNKNOWN', rev): + print("%Warning: No git revision found in config_rev.py", file=sys.stderr) diff --git a/src/config_rev.pl b/src/config_rev.pl deleted file mode 100755 index b1de61379..000000000 --- a/src/config_rev.pl +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env perl -###################################################################### -# -# Copyright 2005-2020 by Wilson Snyder. This program is free software; you -# can redistribute it and/or modify it under the terms of either the GNU -# Lesser General Public License Version 3 or the Perl Artistic License -# Version 2.0. -# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 -# -###################################################################### -# DESCRIPTION: Query's subversion to get version number - -use warnings; - -my $dir = $ARGV[0]; defined $dir or die "%Error: No directory argument,"; -chdir $dir; - -my $rev = 'UNKNOWN_REV'; -my $data = `git describe`; -if ($data =~ /^(v[0-9].*)/i) { - $rev = $1; -} -elsif ($data =~ /verilator_?(.*)/i) { - $rev = "v".$1; - $rev =~ s/_/./g; -} - -$data = `git status`; -if ($data =~ /Changed but not updated/i - || $data =~ /Changes to be committed/i - || $data =~ /Changes not staged/i) { - $rev .= " (mod)"; -} - -print "static const char* const DTVERSION_rev = \"$rev\";\n"; - -# Die after the print, so at least the header has good contents -$rev =~ /UNKNOWN/ and warn "%Warning: No git revision found,"; diff --git a/src/cppcheck_filtered b/src/cppcheck_filtered index 461c042da..4e0f88128 100755 --- a/src/cppcheck_filtered +++ b/src/cppcheck_filtered @@ -1,245 +1,183 @@ -#!/usr/bin/env perl -# See copyright, etc in below POD section. +#!/usr/bin/env python3 ###################################################################### -use warnings; -use Getopt::Long; -use IO::File; -use Pod::Usage; -use strict; -use vars qw($Debug $VERSION); +import argparse +import os +import re +import sys -$VERSION = '3.881'; - -our %SuppressMap = ( - # New cpp check error Can suppress with old error - 'nullPointerRedundantCheck' => 'nullPointer', - ); - -#====================================================================== -# main - -our $Opt_Debug; - -autoflush STDOUT 1; -autoflush STDERR 1; -Getopt::Long::config("no_auto_abbrev","pass_through"); -our @Opt_Args = ("cppcheck", grep { $_ ne "--debug" } @ARGV); -if (! GetOptions( - # Local options - "debug!" => sub { $Debug = 9; }, - "help" => \&usage, - "version" => sub { print "Version $VERSION\n"; system("cppcheck","--version"); exit(0); }, - )) { - die "%Error: Bad usage, try 'cppcheck_filtered --help'\n"; +SuppressMap = { + # New cpp check error Can suppress with old error + 'nullPointerRedundantCheck': 'nullPointer' } -process(); +###################################################################### -#---------------------------------------------------------------------- -sub usage { - print "Version $VERSION\n"; - pod2usage(-verbose=>2, -exitval=>0, -output=>\*STDOUT, -noperldoc=>1); - exit(1); # Unreachable -} - -####################################################################### - -sub process { - my $cmd = join(' ', @Opt_Args); - print "\t$cmd\n" if $Debug; - my $fh = IO::File->new("$cmd 2>&1 |"); - $fh or die "%Error: '$cmd' failed: $!\n"; - my %uniq; - my %errs; - my $last_error = ""; - while (defined(my $line = $fh->getline())) { - print ">>>$line" if $Debug; - $line =~ s/^\s+//; - $line =~ s/Checking usage of global functions\.+//; # Sometimes tacked at end-of-line +def process(cppcheck_args): + cmd = " ".join(cppcheck_args) + " 2>&1" + if Args.debug: + print("\t" + cmd) + fh = os.popen(cmd) + uniq = {} + errs = False + last_error = "" + for line in fh: + line = line.rstrip() + if Args.debug: + print(">>>" + line) + line = re.sub(r'^\s+', '', line) + # Sometimes tacked at end-of-line + line = re.sub(r'Checking usage of global functions\.+', '', line) # General gunk - next if $uniq{$line}++; - next if $line =~ m!^<\?xml version!; - next if $line =~ m!^!; - next if $line =~ m!^!; - next if $line =~ m!^!; - next if $line =~ m!^', line): + continue + if re.search(r'^', line): + continue + if re.search(r'^', line): + continue + # --suppress=unmatchedSuppression doesn't work + if re.search(r'^error("Cppcheck errors:\n$all"); - #die "%Error: cppcheck_filtered found errors\n"; - exit(1); - } -} + if re.search(r'^cppcheck --', line): + if Args.debug: + print(line) + continue + if re.search(r'^\d+/\d+ files checked', line): + print(line) + continue + + suppress = False + # --xml-format=2 + if re.search(r'{verbose}; - return undef if $filename eq "*"; +def _suppress(filename, linenum, id): + if Args.debug: + print("-Suppression search %s %s %s" % (filename, linenum, id)) + + if filename == "*": + return False # Cleanup for e.g. ../V3AstNodes.h - $filename = "src/$1" if $filename =~ m!^\.\./(.*)!; + filename = re.sub(r'^\.\./(.*)', r'src/\1', filename) # Specific suppressions - return 1 if $id eq "missingInclude" && $filename =~ m!systemc.h!; - return 1 if $id eq "missingInclude" && $filename =~ m!svdpi.h!; - return 1 if $id eq "unusedFunction" && $filename =~ m!verilated_dpi.cpp!; - return 1 if $id eq "unusedFunction" && $filename =~ m!verilated_vpi.cpp!; - return 1 if $id eq "unreachableCode" && $filename =~ /V3ParseBison.c/; - return 1 if $id eq 'variableScope' && $filename =~ /fstapi.c/; + if id == 'missingInclude' and re.search(r'systemc.h', filename): + return True + if id == 'missingInclude' and re.search(r'svdpi.h', filename): + return True + if id == 'unusedFunction' and re.search(r'verilated_dpi.cpp', filename): + return True + if id == 'unusedFunction' and re.search(r'verilated_vpi.cpp', filename): + return True + if id == 'unreachableCode' and re.search(r'V3ParseBison.c', filename): + return True + if id == 'variableScope' and re.search(r'fstapi.c', filename): + return True - my $fh = IO::File->new("<$filename"); - if (!$fh) { - warn "%Warning: $! $filename,"; - return undef; - } - my $l = 0; - while (defined(my $line = $fh->getline())) { - ++$l; - if ($l+1 == $linenum) { - if ($line =~ /cppcheck-suppress((\s+\S+)+)/) { - my $supids = $1; - foreach my $supid (split /\s+/, $supids) { - if ($supid eq $id - || $supid eq ($SuppressMap{$id}||'')) { - return 1; - } - } - warn "%Warning: $filename: $l: Found suppress for ids='$supids', not expected id='$id'\n"; - } - } - if ($l == $linenum) { - if (0 && # We now use VL_DANGLING instead of this rule - $id eq "uselessAssignmentPtrArg" - && $line =~ /(delete|Delete|Edit).*p *= *(NULL|nullptr);/) { - # delete(nodep); nodep=NULL; # This is ok, it's how we prevent later using nodep - return 1; - } - } - } - return undef; -} + if not os.path.exists(filename): + print("%Warning: " + filename + " does not exist, ignored", + file=sys.stderr) + return False + + with open(filename) as fh: + l = 0 + for line in fh: + l += 1 + if (l + 1 == linenum): + match = re.search(r'cppcheck-suppress((\s+\S+)+)', line) + if match: + for supid in match.group(1).split(): + if (supid == id or + (id in SuppressMap and supid == SuppressMap[id])): + return True + return False -1; ####################################################################### -__END__ +####################################################################### -=pod +parser = argparse.ArgumentParser( + allow_abbrev=False, + formatter_class=argparse.RawDescriptionHelpFormatter, + description="""cppcheck_filtered passes all arguments to cppcheck, then +filters out unnecessary warnings related to Verilator. Run as: -=head1 NAME - -cppcheck_filtered - cppcheck wrapper with post-processing - -=head1 SYNOPSIS - - cppcheck_filtered ...normal cpp check flags... - - -=head1 DESCRIPTION - -Cppcheck_Filtered is a wrapper for cppcheck that filters out unnecessary -warnings related to Verilator. - -=head1 ARGUMENTS - -Most arguments are passed through to cppcheck - -=over 4 - -=item --help - -Displays this message and program version and exits. - -=item --version - -Print the version number and exit. - -=back - -=head1 DISTRIBUTION - -This is part of the L free Verilog EDA software -tool suite. The latest version is available from CPAN and from -L. - -Copyright 2014-2020 by Wilson Snyder. This program is free software; you + cd $VERILATOR_ROOT + make -k cppcheck""", + epilog= + """Copyright 2014-2021 by Wilson Snyder. This program is free software; you can redistribute it and/or modify it under the terms of either the GNU -Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. +Lesser General Public License Version 3 or the Perl Artistic License +Version 2.0. -SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 +SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0""") -=head1 AUTHORS +parser.add_argument('--debug', action='store_true', help='enable debug') -Wilson Snyder +Args, cppcheck_args = parser.parse_known_args() -=head1 SEE ALSO - -C - -=cut +process(cppcheck_args) ###################################################################### ### Local Variables: -### compile-command: "./cppcheck_filtered --xml V3Width.cpp" +### compile-command: "cd .. ; src/cppcheck_filtered cppcheck --xml --enable=all src/V3Width.cpp" ### End: diff --git a/src/flexfix b/src/flexfix index 616ddb5a1..c83cba61f 100755 --- a/src/flexfix +++ b/src/flexfix @@ -1,7 +1,7 @@ -#!/usr/bin/env perl +#!/usr/bin/env python3 ###################################################################### # -# Copyright 2002-2020 by Wilson Snyder. This program is free software; you +# Copyright 2002-2021 by Wilson Snyder. This program is free software; you # can redistribute it and/or modify it under the terms of either the GNU # Lesser General Public License Version 3 or the Perl Artistic License # Version 2.0. @@ -10,32 +10,42 @@ ###################################################################### # DESCRIPTION: Edits flex output to get around various broken flex issues. -use warnings; +import argparse +import re +import sys -my $Opt_Prefix = $ARGV[0] or die "%Error: No prefix specified,"; - -foreach my $line () { +for line in sys.stdin: # Fix flex 2.6.1 warning - $line =~ s/for \( i = 0; i < _yybytes_len; \+\+i \)/for ( i = 0; (yy_size_t)(i) < (yy_size_t)(_yybytes_len); ++i )/g; + line = re.sub( + r'for \( i = 0; i < _yybytes_len; \+\+i \)', + r'for ( i = 0; (yy_size_t)(i) < (yy_size_t)(_yybytes_len); ++i )', + line) # Fix flex 2.6.0 warning - $line =~ s/\(\(int\) \(\(yy_n_chars\) \+ number_to_move\) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size\)/((int) ((yy_n_chars) + number_to_move) > (int) YY_CURRENT_BUFFER_LVALUE->yy_buf_size)/g; - $line =~ s/ number_to_move == YY_MORE_ADJ / (int)number_to_move == (int)YY_MORE_ADJ /; + line = re.sub( + r'\(\(int\) \(\(yy_n_chars\) \+ number_to_move\) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size\)', + r'((int) ((yy_n_chars) + number_to_move) > (int) YY_CURRENT_BUFFER_LVALUE->yy_buf_size)', + line) + line = re.sub(r' number_to_move == YY_MORE_ADJ ', + r' (int)number_to_move == (int)YY_MORE_ADJ ', line) # Fix flex 2.5.4 namespace omission - $line =~ s/^class istream;/\#include \nusing namespace std;\n/; + line = re.sub(r'^class istream;', + '\#include \nusing namespace std;\n', line) # Fix flex 2.5.31 redefinition - $line =~ s!(\#define\s+yyFlexLexer\s+yyFlexLexer)!//flexfix: $1!g; + line = re.sub(r'(\#define\s+yyFlexLexer\s+yyFlexLexer)', r'//flexfix: \1', + line) # Fix flex 2.5.1 yytext_ptr undef - $line =~ s!(\#undef\s+yytext_ptr)!//flexfix: $1!g; + line = re.sub(r'(\#undef\s+yytext_ptr)', r'//flexfix: \1', line) # Fix flex 2.5.4 and GCC 4.1.0 warn_unused_result - $line =~ s!\(void\) *fwrite\((.*)\)!if (fwrite($1)) {}!g; + line = re.sub(r'\(void\) *fwrite\((.*)\)', r'if (fwrite(\1)) {}', line) # Fix flex 2.5.33 and GCC 4.1.2 "warning: comparison between signed and unsigned integer expressions" in YY_INPUT - $line =~ s!for \( n = 0; n < max_size && !for ( n = 0; ((size_t)n < (size_t)max_size) && !g; + line = re.sub(r'for \( n = 0; n < max_size && ', + r'for ( n = 0; ((size_t)n < (size_t)max_size) && ', line) # Fix flex 2.5.4 and GCC 4.0.2 under FLEX_DEBUG - $line =~ s!--accepting rule at line %d !--accepting rule at line %ld !g; + line = re.sub(r'--accepting rule at line %d ', + r'--accepting rule at line %ld ', line) # Fix compiler warning filenames - $line =~ s!(#line \d+ ".*)_pretmp!$1!; + line = re.sub(r'(#line \d+ ".*)_pretmp', r'\1', line) # Fix 'register' storage class specifier is deprecated and incompatible with C++17 - $line =~ s!register !!g; + line = re.sub(r'register ', '', line) - print "$line"; -} + print(line, end='') diff --git a/src/pod2latexfix b/src/pod2latexfix index 8e3b4e9d9..42e7a82a1 100755 --- a/src/pod2latexfix +++ b/src/pod2latexfix @@ -1,7 +1,7 @@ #!/usr/bin/env perl ###################################################################### # -# Copyright 2002-2020 by Wilson Snyder. This program is free software; you +# Copyright 2002-2021 by Wilson Snyder. This program is free software; you # can redistribute it and/or modify it under the terms of either the GNU # Lesser General Public License Version 3 or the Perl Artistic License # Version 2.0. diff --git a/src/verilog.l b/src/verilog.l index 422af9538..75739e32a 100644 --- a/src/verilog.l +++ b/src/verilog.l @@ -6,7 +6,7 @@ * ************************************************************************** * - * Copyright 2003-2020 by Wilson Snyder. Verilator is free software; you + * Copyright 2003-2021 by Wilson Snyder. Verilator is free software; you * can redistribute it and/or modify it under the terms of either the * GNU Lesser General Public License Version 3 or the Perl Artistic License * Version 2.0. @@ -78,7 +78,7 @@ static double lexParseDouble(FileLine* fl, const char* textp, size_t length) { %a 15000 %o 25000 -%s V95 V01 V05 S05 S09 S12 S17 +%s V95 V01NC V01C V05 S05 S09 S12 S17 %s STRING ATTRMODE TABLE %s VA5 SAX VLT %s SYSCHDR SYSCINT SYSCIMP SYSCIMPH SYSCCTOR SYSCDTOR @@ -155,7 +155,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5} /************************************************************************/ /* Verilog 1995 */ -{ +{ {ws} { FL_FWD; FL_BRK; } /* otherwise ignore white-space */ {crnl} { FL_FWD; FL_BRK; } /* Count line numbers */ /* Extensions to Verilog set, some specified by PSL */ @@ -395,7 +395,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5} } /* Verilog 2001 */ -{ +{ /* System Tasks */ "$signed" { FL; return yD_SIGNED; } "$unsigned" { FL; return yD_UNSIGNED; } @@ -412,6 +412,10 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5} "showcancelled" { FL; return yaTIMINGSPEC; } "signed" { FL; return ySIGNED; } "unsigned" { FL; return yUNSIGNED; } +} + + /* Verilog 2001 Config */ +{ /* Generic unsupported keywords */ "cell" { ERROR_RSVD_WORD("Verilog 2001-config"); } "config" { ERROR_RSVD_WORD("Verilog 2001-config"); } @@ -606,7 +610,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5} /* No new keywords */ /* Default PLI rule */ -{ +{ "$"[a-zA-Z_$][a-zA-Z0-9_$]* { string str (yytext, yyleng); yylval.strp = PARSEP->newString(AstNode::encodeName(str)); FL; return yaD_PLI; @@ -710,7 +714,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5} /* Meta comments */ /* Converted from //{cmt}verilator ...{cmt} by preprocessor */ -{ +{ "/*verilator"{ws}*"*/" { FL_FWD; FL_BRK; } /* Ignore empty comments, may be `endif // verilator */ "/*verilator clock_enable*/" { FL; return yVL_CLOCK_ENABLE; } "/*verilator clocker*/" { FL; return yVL_CLOCKER; } @@ -750,7 +754,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5} /************************************************************************/ /* Single character operator thingies */ -{ +{ "{" { FL; return yytext[0]; } "}" { FL; return yytext[0]; } "!" { FL; return yytext[0]; } @@ -784,7 +788,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5} /* Operators and multi-character symbols */ /* Verilog 1995 Operators */ -{ +{ "&&" { FL; return yP_ANDAND; } "||" { FL; return yP_OROR; } "<=" { FL; return yP_LTE; } @@ -806,7 +810,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5} } /* Verilog 2001 Operators */ -{ +{ "<<<" { FL; return yP_SLEFT; } ">>>" { FL; return yP_SSRIGHT; } "**" { FL; return yP_POW; } @@ -858,7 +862,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5} } /* Identifiers and numbers */ -{ +{ {escid} { FL; yylval.strp = PARSEP->newString (AstNode::encodeName(string(yytext+1))); // +1 to skip the backslash return yaID__LEX; @@ -936,7 +940,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5} /************************************************************************/ /* Attributes */ /* Note simulators vary in support for "(* /_*something*_/ foo*)" where _ doesn't exist */ -{ +{ "(*"({ws}|{crnl})*({id}|{escid}) { yymore(); yy_push_state(ATTRMODE); } /* Doesn't match (*), but (* attr_spec */ } @@ -956,7 +960,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5} /* Common for all SYSC header states */ /* OPTIMIZE: we return one per line, make it one for the entire block */ /* If add to this list also add to V3LanguageWords.h */ -{ +{ "`accelerate" { FL_FWD; FL_BRK; } // Verilog-XL compatibility "`autoexpand_vectornets" { FL_FWD; FL_BRK; } // Verilog-XL compatibility "`celldefine" { FL_FWD; PARSEP->lexFileline()->celldefineOn(true); FL_BRK; } @@ -1004,8 +1008,8 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5} /* See also setLanguage below */ "`begin_keywords"[ \t]*\"1364-1995\" { FL_FWD; yy_push_state(V95); PARSEP->lexPushKeywords(YY_START); FL_BRK; } - "`begin_keywords"[ \t]*\"1364-2001\" { FL_FWD; yy_push_state(V01); PARSEP->lexPushKeywords(YY_START); FL_BRK; } - "`begin_keywords"[ \t]*\"1364-2001-noconfig\" { FL_FWD; yy_push_state(V01); PARSEP->lexPushKeywords(YY_START); FL_BRK; } + "`begin_keywords"[ \t]*\"1364-2001\" { FL_FWD; yy_push_state(V01C); PARSEP->lexPushKeywords(YY_START); FL_BRK; } + "`begin_keywords"[ \t]*\"1364-2001-noconfig\" { FL_FWD; yy_push_state(V01NC); PARSEP->lexPushKeywords(YY_START); FL_BRK; } "`begin_keywords"[ \t]*\"1364-2005\" { FL_FWD; yy_push_state(V05); PARSEP->lexPushKeywords(YY_START); FL_BRK; } "`begin_keywords"[ \t]*\"VAMS[-0-9.]*\" { FL_FWD; yy_push_state(VA5); PARSEP->lexPushKeywords(YY_START); FL_BRK; } "`begin_keywords"[ \t]*\"1800-2005\" { FL_FWD; yy_push_state(S05); PARSEP->lexPushKeywords(YY_START); FL_BRK; } @@ -1052,7 +1056,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5} /************************************************************************/ /* Default rules - leave last */ -{ +{ "`"[a-zA-Z_0-9]+ { FL; V3ParseImp::lexErrorPreprocDirective(yylval.fl, yytext); FL_BRK; } "//"[^\n]* { FL_FWD; FL_BRK; } /* throw away single line comments */ . { FL; return yytext[0]; } /* return single char ops. */ diff --git a/src/verilog.y b/src/verilog.y index b6b54483f..bdf07ddb9 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2020 by Wilson Snyder. This program is free software; you +// Copyright 2003-2021 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -288,10 +288,7 @@ static void UNSUPREAL(FileLine* fileline) { //====================================================================== -void yyerror(const char* errmsg) { - PARSEP->bisonLastFileline()->v3error(errmsg); - static const char* const colonmsg = "syntax error, unexpected"; -} +void yyerror(const char* errmsg) { PARSEP->bisonLastFileline()->v3error(errmsg); } void yyerrorf(const char* format, ...) { const int maxlen = 2000; @@ -1403,7 +1400,7 @@ portSig: interface_declaration: // IEEE: interface_declaration + interface_nonansi_header + interface_ansi_header: // // timeunits_delcarationE is instead in interface_item - intFront parameter_port_listE portsStarE ';' + intFront importsAndParametersE portsStarE ';' interface_itemListE yENDINTERFACE endLabelE { if ($2) $1->addStmtp($2); if ($3) $1->addStmtp($3); @@ -2465,7 +2462,8 @@ loop_generate_construct: // ==IEEE: loop_generate_construct { // Convert BEGIN(...) to BEGIN(GENFOR(...)), as we need the BEGIN to hide the local genvar AstBegin* lowerBegp = VN_CAST($9, Begin); UASSERT_OBJ(!($9 && !lowerBegp), $9, "Child of GENFOR should have been begin"); - if (!lowerBegp) lowerBegp = new AstBegin($1, "genblk", nullptr, true, true); // Empty body + + if (!lowerBegp) lowerBegp = new AstBegin($1, "", nullptr, true, false); // Empty body AstNode* lowerNoBegp = lowerBegp->stmtsp(); if (lowerNoBegp) lowerNoBegp->unlinkFrBackWithNext(); // @@ -2479,7 +2477,7 @@ loop_generate_construct: // ==IEEE: loop_generate_construct } // Statements are under 'genforp' as cells under this // for loop won't get an extra layer of hierarchy tacked on - blkp->addGenforp(new AstGenFor($1,initp,$5,$7,lowerNoBegp)); + blkp->addGenforp(new AstGenFor($1, initp, $5, $7, lowerNoBegp)); $$ = blkp; VL_DO_DANGLING(lowerBegp->deleteTree(), lowerBegp); } @@ -3667,7 +3665,9 @@ system_t_call: // IEEE: system_tf_call (as task) | yD_WRITEMEMH '(' expr ',' idClassSel ',' expr ',' expr ')' { $$ = new AstWriteMem($1, true, $3, $5, $7, $9); } // | yD_CAST '(' expr ',' expr ')' - { $$ = new AstAssert($1, new AstCastDynamic($1, $3, $5), nullptr, nullptr, true); } + { FileLine* fl_nowarn = new FileLine($1); + fl_nowarn->warnOff(V3ErrorCode::WIDTH, true); + $$ = new AstAssertIntrinsic(fl_nowarn, new AstCastDynamic(fl_nowarn, $5, $3), nullptr, nullptr, true); } // // Any system function as a task | system_f_call_or_t { $$ = new AstSysFuncAsTask($1, $1); } @@ -3677,7 +3677,7 @@ system_f_call: // IEEE: system_tf_call (as func) yaD_PLI systemDpiArgsE { $$ = new AstFuncRef($1, *$1, $2); VN_CAST($$, FuncRef)->pli(true); } // | yD_C '(' cStrList ')' { $$ = (v3Global.opt.ignc() ? nullptr : new AstUCFunc($1,$3)); } - | yD_CAST '(' expr ',' expr ')' { $$ = new AstCastDynamic($1, $3, $5); } + | yD_CAST '(' expr ',' expr ')' { $$ = new AstCastDynamic($1, $5, $3); } | yD_SYSTEM '(' expr ')' { $$ = new AstSystemF($1,$3); } // | system_f_call_or_t { $$ = $1; } @@ -3783,6 +3783,7 @@ system_f_call_or_t: // IEEE: part of system_tf_call (can be task or func) | yD_UNSIGNED '(' expr ')' { $$ = new AstUnsigned($1, $3); } | yD_URANDOM '(' expr ')' { $$ = new AstRand($1, $3, true); } | yD_URANDOM parenE { $$ = new AstRand($1, nullptr, true); } + | yD_URANDOM_RANGE '(' expr ')' { $$ = new AstURandomRange($1, $3, new AstConst($1, 0)); } | yD_URANDOM_RANGE '(' expr ',' expr ')' { $$ = new AstURandomRange($1, $3, $5); } | yD_VALUEPLUSARGS '(' expr ',' expr ')' { $$ = new AstValuePlusArgs($1, $3, $5); } ; @@ -4146,7 +4147,7 @@ expr: // IEEE: part of expression/constant_expression/primary | '^' ~r~expr %prec prREDUCTION { $$ = new AstRedXor ($1,$2); } | yP_NAND ~r~expr %prec prREDUCTION { $$ = new AstLogNot($1, new AstRedAnd($1, $2)); } | yP_NOR ~r~expr %prec prREDUCTION { $$ = new AstLogNot($1, new AstRedOr($1, $2)); } - | yP_XNOR ~r~expr %prec prREDUCTION { $$ = new AstRedXnor ($1,$2); } + | yP_XNOR ~r~expr %prec prREDUCTION { $$ = new AstLogNot($1, new AstRedXor($1, $2)); } // // // IEEE: inc_or_dec_expression | ~l~inc_or_dec_expression { $$=$1; $$ = $1; } @@ -4187,9 +4188,9 @@ expr: // IEEE: part of expression/constant_expression/primary | ~l~expr '&' ~r~expr { $$ = new AstAnd ($2,$1,$3); } | ~l~expr '|' ~r~expr { $$ = new AstOr ($2,$1,$3); } | ~l~expr '^' ~r~expr { $$ = new AstXor ($2,$1,$3); } - | ~l~expr yP_XNOR ~r~expr { $$ = new AstXnor ($2,$1,$3); } - | ~l~expr yP_NOR ~r~expr { $$ = new AstNot($2,new AstOr ($2,$1,$3)); } - | ~l~expr yP_NAND ~r~expr { $$ = new AstNot($2,new AstAnd ($2,$1,$3)); } + | ~l~expr yP_XNOR ~r~expr { $$ = new AstNot{$2, new AstXor{$2, $1, $3}}; } + | ~l~expr yP_NOR ~r~expr { $$ = new AstNot{$2, new AstOr{$2, $1, $3}}; } + | ~l~expr yP_NAND ~r~expr { $$ = new AstNot{$2, new AstAnd{$2, $1, $3}}; } | ~l~expr yP_SLEFT ~r~expr { $$ = new AstShiftL ($2,$1,$3); } | ~l~expr yP_SRIGHT ~r~expr { $$ = new AstShiftR ($2,$1,$3); } | ~l~expr yP_SSRIGHT ~r~expr { $$ = new AstShiftRS ($2,$1,$3); } @@ -4264,7 +4265,7 @@ expr: // IEEE: part of expression/constant_expression/primary | yCONST__ETC yP_TICK '(' expr ')' { $$ = $4; } // Not linting const presently // // Spec only allows primary with addition of a type reference // // We'll be more general, and later assert LHS was a type. - | ~l~expr yP_TICK '(' expr ')' { $$ = new AstCastParse($2,$4,$1); } + | ~l~expr yP_TICK '(' expr ')' { $$ = new AstCastParse($2, $4, $1); } // // // IEEE: assignment_pattern_expression // // IEEE: streaming_concatenation @@ -4274,7 +4275,7 @@ expr: // IEEE: part of expression/constant_expression/primary // // Indistinguishable from function_subroutine_call:method_call // | '$' { $$ = new AstUnbounded($1); } - | yNULL { $$ = new AstConst($1, AstConst::StringToParse(), "'0"); } + | yNULL { $$ = new AstConst($1, AstConst::Null{}); } // // IEEE: yTHIS // // See exprScope // diff --git a/src/vlcovgen b/src/vlcovgen index c5a3e2a7f..a665e071c 100755 --- a/src/vlcovgen +++ b/src/vlcovgen @@ -1,169 +1,108 @@ -#!/usr/bin/env perl -# See copyright, etc in below POD section. +#!/usr/bin/env python3 ###################################################################### -use warnings; -use Getopt::Long; -use IO::File; -use Pod::Usage; -use strict; -use vars qw($Debug); +import argparse +import re +import os +import sys +from pprint import pprint -our @Items; +Items = [] -#====================================================================== -# main - -$Debug = 0; -my $Opt_Srcdir = "."; -Getopt::Long::config("pass_through", "no_auto_abbrev"); -if (! GetOptions( - "help" => \&usage, - "debug" => sub { $Debug = 1; }, - "srcdir=s" => \$Opt_Srcdir, - "<>" => sub { die "%Error: Unknown parameter: $_[0],"; }, - )) { - usage(); -} - -read_keys("$Opt_Srcdir/../include/verilated_cov_key.h"); -lint(); -write_keys("$Opt_Srcdir/../include/verilated_cov_key.h"); - -#---------------------------------------------------------------------- - -sub usage { - pod2usage(-verbose=>2, -exitval=>0, -output=>\*STDOUT); - exit(1); # Unreachable -} - -####################################################################### - -sub read_keys { - my $filename = shift; - - my $fh = IO::File->new("<$filename") or die "%Error: $! $filename,"; - while (defined (my $line = $fh->getline())) { - $line =~ s/\/\/.*$//; - next if $line =~ /^\s*$/; - if ($line =~ /^\s*VLCOVGEN_ITEM/) { - $line =~ /^\s*VLCOVGEN_ITEM *\( *"([^"]+)" *\)/ - or die "%Error: $filename:$.: Misformed VLCOVGEN_ITEM line,"; - my @data; - my $code = "\@data = ($1);"; - eval $code; - die "%Error: $filename:$.: Parsing '$code': $@," if $@; - push @Items, {@data}; - } - } -} - -####################################################################### - -sub lint { - my %shorts; - my $ok = 1; - foreach my $itemref (@Items) { - if ($shorts{$itemref->{short}}) { - die "%Error: Duplicate short code: $itemref->{short},"; - $ok = 0; - } - $shorts{$itemref->{short}} = 1; - } - return $ok; -} - -sub write_keys { - my $filename = shift; - - my $fh = IO::File->new("<$filename") or die "%Error: $! $filename\n"; - - my @in; - my @out; - my $deleting; - while (defined(my $line = $fh->getline)) { - push @in, $line; - if ($line =~ /VLCOVGEN_CIK_AUTO_EDIT_BEGIN/) { - $deleting = 1; - push @out, $line; - foreach my $keyref (sort {$a->{name} cmp $b->{name}} @Items) { - push @out, sprintf("#define VL_CIK_%s \"%s\"\n", - uc $keyref->{name}, $keyref->{short}); - } - } - elsif ($line =~ /VLCOVGEN_SHORT_AUTO_EDIT_BEGIN/) { - $deleting = 1; - push @out, $line; - foreach my $keyref (sort {$a->{name} cmp $b->{name}} @Items) { - push @out, sprintf(" if (key == \"%s\") return VL_CIK_%s;\n", - $keyref->{name}, uc $keyref->{name}); - } - } - elsif ($line =~ /VLCOVGEN_.*AUTO_EDIT_END/) { - $deleting = 0; - push @out, $line; - } - elsif ($deleting) { - } - else { - push @out, $line; - } - } - $fh->close; - - my $ok = join("", @out) eq join("", @in); - if (!$ok) { - my $fh = IO::File->new(">$filename") or die "%Error: $! writing $filename\n"; - $fh->print(join "", @out); - $fh->close; - } -} +###################################################################### -####################################################################### -__END__ +def read_keys(filename): + with open(filename) as fh: + for line in fh: + line = re.sub(r'\/\/.*$', '', line) + if re.match(r'^\s*$', line): + continue + if re.search(r'^\s*VLCOVGEN_ITEM', line): + match = re.search(r'^\s*VLCOVGEN_ITEM *\( *"([^"]+)" *\)', + line) + if not match: + sys.exit("%Error: " + filename + + ": vlcovgen misformed VLCOVGEN_ITEM line") + code = "{" + match.group(1) + "}" + data = eval(code) + # pprint(data) + Items.append(data) -=pod -=head1 NAME +###################################################################### -vlcovgen - Generate verilated_cov headers to reduce C++ code duplication -=head1 SYNOPSIS +def lint(): + shorts = {} + for item in Items: + if item['short'] in shorts: + sys.exit("%Error: vlcovgen duplicate short code: " + item['short']) + shorts[item['short']] = True - (called from make rules) - vlcovgen -=head1 DESCRIPTION +def write_keys(filename): + orig = [] + out = [] -Generates several files for Verilator compilations. + with open(filename) as fh: + deleting = False + for line in fh: + orig.append(line) + if re.search(r'VLCOVGEN_CIK_AUTO_EDIT_BEGIN', line): + deleting = True + out.append(line) + for keyref in sorted(Items, key=lambda a: a['name']): + out.append("#define VL_CIK_%s \"%s\"\n" % + (keyref['name'].upper(), keyref['short'])) + elif re.search(r'VLCOVGEN_SHORT_AUTO_EDIT_BEGIN', line): + deleting = True + out.append(line) + for keyref in sorted(Items, key=lambda a: a['name']): + out.append( + " if (key == \"%s\") return VL_CIK_%s;\n" % + (keyref['name'], keyref['name'].upper())) + elif re.search(r'VLCOVGEN_.*AUTO_EDIT_END', line): + deleting = False + out.append(line) + elif deleting: + None + else: + out.append(line) -=head1 ARGUMENTS + ok = "".join(out) == "".join(orig) + if not ok: + with open(filename, "w") as fhw: + fhw.write("".join(out)) -=over 4 -=item --help +###################################################################### +###################################################################### -Displays this message and program version and exits. - -=back - -=head1 DISTRIBUTION - -Copyright 2002-2020 by Wilson Snyder. This program is free software; you +parser = argparse.ArgumentParser( + allow_abbrev=False, + formatter_class=argparse.RawDescriptionHelpFormatter, + description= + """Generate verilated_cov headers to reduce C++ code duplication.""", + epilog= + """Copyright 2002-2021 by Wilson Snyder. This program is free software; you can redistribute it and/or modify it under the terms of either the GNU Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. -SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 +SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0""") -=head1 AUTHORS +parser.add_argument('--srcdir', + action='store', + help='directory containing Verilator sources') -Wilson Snyder +parser.set_defaults(srcdir=".") -=head1 SEE ALSO +Args = parser.parse_args() -=cut +read_keys(Args.srcdir + "/../include/verilated_cov_key.h") +lint() +write_keys(Args.srcdir + "/../include/verilated_cov_key.h") ###################################################################### ### Local Variables: diff --git a/test_regress/.gitignore b/test_regress/.gitignore index 541e080c1..9e5be0797 100644 --- a/test_regress/.gitignore +++ b/test_regress/.gitignore @@ -11,6 +11,7 @@ simx* ncverilog.* INCA_libs logs +transcript .vcsmx_rebuild vc_hdrs.h xsim.*/ diff --git a/test_regress/CMakeLists.txt b/test_regress/CMakeLists.txt index 0cb22c4b7..28a045961 100644 --- a/test_regress/CMakeLists.txt +++ b/test_regress/CMakeLists.txt @@ -4,7 +4,7 @@ # # This CMake file is meant to be consumed by regression tests. # -# Copyright 2003-2020 by Wilson Snyder. This program is free software; you +# Copyright 2003-2021 by Wilson Snyder. This program is free software; you # can redistribute it and/or modify it under the terms of either the GNU # Lesser General Public License Version 3 or the Perl Artistic License # Version 2.0. diff --git a/test_regress/Makefile b/test_regress/Makefile index f230222d8..747e756e0 100644 --- a/test_regress/Makefile +++ b/test_regress/Makefile @@ -5,7 +5,7 @@ # This calls the object directory makefile. That allows the objects to # be placed in the "current directory" which simplifies the Makefile. # -# Copyright 2003-2020 by Wilson Snyder. This program is free software; you +# Copyright 2003-2021 by Wilson Snyder. This program is free software; you # can redistribute it and/or modify it under the terms of either the GNU # Lesser General Public License Version 3 or the Perl Artistic License # Version 2.0. diff --git a/test_regress/Makefile_obj b/test_regress/Makefile_obj index 1678e3afb..6795aeed4 100644 --- a/test_regress/Makefile_obj +++ b/test_regress/Makefile_obj @@ -5,7 +5,7 @@ # # This is executed in the object directory, and called by ../Makefile # -# Copyright 2003-2020 by Wilson Snyder. This program is free software; you +# Copyright 2003-2021 by Wilson Snyder. This program is free software; you # can redistribute it and/or modify it under the terms of either the GNU # Lesser General Public License Version 3 or the Perl Artistic License # Version 2.0. diff --git a/test_regress/driver.pl b/test_regress/driver.pl index f2c23f8da..ff7c66fc1 100755 --- a/test_regress/driver.pl +++ b/test_regress/driver.pl @@ -80,6 +80,7 @@ my $opt_optimize; my $opt_quiet; my $opt_rerun; my $opt_rrsim; +my $opt_sanitize; my %opt_scenarios; my $opt_site; my $opt_stop; @@ -107,6 +108,7 @@ if (! GetOptions( "rerun!" => \$opt_rerun, "rr!" => \$opt_rr, "rrsim!" => \$opt_rrsim, + "sanitize!" => \$opt_sanitize, "site!" => \$opt_site, "stop!" => \$opt_stop, "trace!" => \$opt_trace, @@ -247,12 +249,17 @@ sub parameter { } } +our $_Max_Procs; sub max_procs { - my $ok = eval " - use Unix::Processors; - return Unix::Processors->new->max_online; - "; - return $ok; + if (!defined $_Max_Procs) { + $_Max_Procs = `python3 -c 'import multiprocessing\nprint(multiprocessing.cpu_count())'`; + chomp $_Max_Procs; + if ($_Max_Procs < 2) { + $_Max_Procs = 2; + warn "driver.pl: Python didn't find at least two CPUs\n"; + } + } + return $_Max_Procs; } sub calc_threads { @@ -768,7 +775,7 @@ sub _exit { if ($self->ok) { $self->oprint("Self PASSED\n"); } elsif ($self->skips && !$self->errors) { - $self->oprint("%Skip: $self->{skips}\n"); + $self->oprint("-Skip: $self->{skips}\n"); } elsif ($self->unsupporteds && !$self->errors) { $self->oprint("%Unsupported: $self->{unsupporteds}\n"); } else { @@ -866,6 +873,7 @@ sub compile_vlt_flags { || (!$self->{sc} && 'vcd-c')); $self->{savable} = 1 if ($checkflags =~ /-savable\b/); $self->{coverage} = 1 if ($checkflags =~ /-coverage\b/); + $self->{sanitize} = $opt_sanitize unless exists($self->{sanitize}); my @verilator_flags = @{$param{verilator_flags}}; unshift @verilator_flags, "--gdb" if $opt_gdb; @@ -878,6 +886,7 @@ sub compile_vlt_flags { unshift @verilator_flags, "--trace-threads 1" if $param{vltmt} && $checkflags =~ /-trace /; unshift @verilator_flags, "--trace-threads 2" if $param{vltmt} && $checkflags =~ /-trace-fst /; unshift @verilator_flags, "--debug-partition" if $param{vltmt}; + unshift @verilator_flags, "-CFLAGS -fsanitize=address -LDFLAGS -fsanitize=address" if $param{sanitize}; unshift @verilator_flags, "--make gmake" if $param{verilator_make_gmake}; unshift @verilator_flags, "--make cmake" if $param{verilator_make_cmake}; unshift @verilator_flags, "--exe" if @@ -1157,7 +1166,7 @@ sub compile { if ($param{make_pli}) { $self->oprint("Compile vpi\n") if $self->{verbose}; - my @cmd = ($ENV{CXX}, @{$param{pli_flags}}, "-DIS_VPI", + my @cmd = ($ENV{CXX}, @{$param{pli_flags}}, "-DIS_VPI", $ENV{CFLAGS}, "$self->{t_dir}/$self->{pli_filename}"); $self->_run(logfile=>"$self->{obj_dir}/pli_compile.log", @@ -1682,6 +1691,7 @@ sub _make_main { print $fh "// Test defines\n"; print $fh "#define MAIN_TIME_MULTIPLIER ".($self->{main_time_multiplier} || 1)."\n"; + print $fh "#include \n"; print $fh "// OS header\n"; print $fh "#include \"verilatedos.h\"\n"; @@ -1697,7 +1707,7 @@ sub _make_main { print $fh "#include \"verilated_vcd_sc.h\"\n" if $self->{trace} && $self->{trace_format} eq 'vcd-sc'; print $fh "#include \"verilated_save.h\"\n" if $self->{savable}; - print $fh "$VM_PREFIX* topp;\n"; + print $fh "std::unique_ptr<$VM_PREFIX> topp;\n"; if (!$self->sc) { if ($self->{vl_time_stamp64}) { print $fh "vluint64_t main_time = 0;\n"; @@ -1745,7 +1755,7 @@ sub _make_main { print $fh " Verilated::debug(".($self->{verilated_debug}?1:0).");\n"; print $fh " srand48(5);\n"; # Ensure determinism print $fh " Verilated::randReset(".$self->{verilated_randReset}.");\n" if defined $self->{verilated_randReset}; - print $fh " topp = new $VM_PREFIX(\"top\");\n"; + print $fh " topp.reset(new $VM_PREFIX(\"top\"));\n"; print $fh " Verilated::internalsDump()\n;" if $self->{verilated_debug}; my $set; @@ -1762,10 +1772,10 @@ sub _make_main { $fh->print("\n"); $fh->print("#if VM_TRACE\n"); $fh->print(" Verilated::traceEverOn(true);\n"); - $fh->print(" VerilatedFstC* tfp = new VerilatedFstC;\n") if $self->{trace_format} eq 'fst-c'; - $fh->print(" VerilatedVcdC* tfp = new VerilatedVcdC;\n") if $self->{trace_format} eq 'vcd-c'; - $fh->print(" VerilatedVcdSc* tfp = new VerilatedVcdSc;\n") if $self->{trace_format} eq 'vcd-sc'; - $fh->print(" topp->trace(tfp, 99);\n"); + $fh->print(" std::unique_ptr tfp{new VerilatedFstC};\n") if $self->{trace_format} eq 'fst-c'; + $fh->print(" std::unique_ptr tfp{new VerilatedVcdC};\n") if $self->{trace_format} eq 'vcd-c'; + $fh->print(" std::unique_ptr tfp{new VerilatedVcdSc};\n") if $self->{trace_format} eq 'vcd-sc'; + $fh->print(" topp->trace(tfp.get(), 99);\n"); $fh->print(" tfp->open(\"".$self->trace_filename."\");\n"); if ($self->{trace} && !$self->sc) { $fh->print(" if (tfp) tfp->dump(main_time);\n"); @@ -1827,11 +1837,12 @@ sub _make_main { if ($self->{trace}) { $fh->print("#if VM_TRACE\n"); $fh->print(" if (tfp) tfp->close();\n"); + $fh->print(" tfp.reset();\n"); $fh->print("#endif // VM_TRACE\n"); } $fh->print("\n"); - print $fh " VL_DO_DANGLING(delete topp, topp);\n"; + print $fh " topp.reset();\n"; print $fh " exit(0L);\n"; print $fh "}\n"; $fh->close(); @@ -2678,6 +2689,12 @@ Same as C: Run Verilator and record with rr. Run Verilator generated executable and record with rr. +=item --sanitize + +Enable address sanitizer to compile Verilated C++ code. +This may detect misuses of memory, such as out-of-bound accesses, use-after-free, +and memory leaks. + =item --site Run site specific tests also. @@ -2721,7 +2738,7 @@ Run simulator-agnostic distribution tests. Run GHDL simulator tests. -=item --iverilog +=item --iv Run Icarus Verilog simulator tests. @@ -2805,7 +2822,7 @@ Command to use to invoke XSim xvlog The latest version is available from L. -Copyright 2003-2020 by Wilson Snyder. This program is free software; you +Copyright 2003-2021 by Wilson Snyder. This program is free software; you can redistribute it and/or modify it under the terms of either the GNU Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. diff --git a/test_regress/t/TestSimulator.h b/test_regress/t/TestSimulator.h index 63d537eff..7c378e664 100644 --- a/test_regress/t/TestSimulator.h +++ b/test_regress/t/TestSimulator.h @@ -23,6 +23,7 @@ private: }; s_vpi_vlog_info m_info; SimTypes m_simulators; + public: TestSimulator() { vpi_get_vlog_info(&m_info); @@ -30,15 +31,16 @@ public: m_simulators.verilator = true; } else if (0 == strcmp(m_info.product, "Verilator")) { m_simulators.icarus = true; - } else if (0 == strncmp(m_info.product, "Chronologic Simulation VCS", - strlen("Chronologic Simulation VCS"))) { + } else if (0 + == strncmp(m_info.product, "Chronologic Simulation VCS", + strlen("Chronologic Simulation VCS"))) { m_simulators.vcs = true; } else { - printf("%%Warning: %s:%d: Unknown simulator in TestSimulator.h: %s\n", - __FILE__, __LINE__, m_info.product); + printf("%%Warning: %s:%d: Unknown simulator in TestSimulator.h: %s\n", __FILE__, + __LINE__, m_info.product); } } - ~TestSimulator() { } + ~TestSimulator() {} // METHORS private: static TestSimulator& singleton() { @@ -46,6 +48,7 @@ private: return s_singleton; } static const SimTypes& simulators() { return singleton().m_simulators; } + public: static const s_vpi_vlog_info& get_info() { return singleton().m_info; } // Simulator names @@ -69,7 +72,7 @@ public: static const char* rooted(const char* obj) { static std::string buf; std::ostringstream os; - os< 1); + +compile( + ); + +execute( + check_finished => 1, + ); + +ok(1); +1; diff --git a/test_regress/t/t_array_packed_endian.v b/test_regress/t/t_array_packed_endian.v new file mode 100644 index 000000000..6af307eea --- /dev/null +++ b/test_regress/t/t_array_packed_endian.v @@ -0,0 +1,71 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2020 Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +`define stop $stop +`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0) + +typedef struct packed { + logic [7:0] a; +} tb_t; + +typedef struct packed { + // verilator lint_off LITENDIAN + logic [0:7] a; + // verilator lint_on LITENDIAN +} tl_t; + +typedef struct packed { + logic [7:0] bb; + // verilator lint_off LITENDIAN + tb_t [0:1] cbl; + tb_t [1:0] cbb; + tl_t [0:1] cll; + tl_t [1:0] clb; + logic [0:7] dl; + // verilator lint_on LITENDIAN +} t2; + +module t; + t2 t; + initial begin + t = 80'hcd_1f2f3f4f_5f6f7f8f_c2; + `checkh(t.bb, 8'hcd); + `checkh(t.cbl[0].a, 8'h1f); + `checkh(t.cbl[1].a, 8'h2f); + `checkh(t.cbb[0].a, 8'h4f); + `checkh(t.cbb[1].a, 8'h3f); + `checkh(t.cll[0].a, 8'h5f); + `checkh(t.cll[1].a, 8'h6f); + `checkh(t.clb[0].a, 8'h8f); + `checkh(t.clb[1].a, 8'h7f); + `checkh(t.dl, 8'hc2); + + t = '0; + t.bb = 8'h13; + t.cbl[0].a = 8'hac; + t.cbl[1].a = 8'had; + t.cbb[0].a = 8'hae; + t.cbb[1].a = 8'haf; + t.cll[0].a = 8'hbc; + t.cll[1].a = 8'hbd; + t.clb[0].a = 8'hbe; + t.clb[1].a = 8'hbf; + t.dl = 8'h31; + `checkh(t, 80'h13_acadafae_bcbdbfbe_31); + + t = '0; + t.bb[7] = 1'b1; + t.cbl[1].a[1] = 1'b1; + t.cbb[1].a[2] = 1'b1; + t.cll[1].a[3] = 1'b1; + t.clb[1].a[4] = 1'b1; + t.dl[7] = 1'b1; + `checkh(t, 80'h80_0002040000100800_01); + + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule diff --git a/test_regress/t/t_case_huge_sub4.v b/test_regress/t/t_case_huge_sub4.v index b4eb77d28..221dafcc8 100644 --- a/test_regress/t/t_case_huge_sub4.v +++ b/test_regress/t/t_case_huge_sub4.v @@ -4,6 +4,8 @@ // any use, without warranty, 2005 by Wilson Snyder. // SPDX-License-Identifier: CC0-1.0 +// verilator lint_off LATCH + module t_case_huge_sub4 (/*AUTOARG*/ // Outputs outq, diff --git a/test_regress/t/t_cast.v b/test_regress/t/t_cast.v index baccee871..b41caa110 100644 --- a/test_regress/t/t_cast.v +++ b/test_regress/t/t_cast.v @@ -13,12 +13,18 @@ module t; logic [15:0] data; } packed_t; + typedef enum [15:0] { + ONE = 1 + } enum_t; + packed_t pdata; + packed_t pdata_reg; assign pdata.data = 16'h1234; logic [7:0] logic8bit; assign logic8bit = $bits(logic8bit)'(pdata >> 8); mc_t o; + enum_t e; logic [15:0] allones = 16'hffff; parameter FOUR = 4; @@ -55,6 +61,17 @@ module t; if ((FOUR+2)'(allones) !== 6'h3f) $stop; if (50 !== RESULT) $stop; + e = ONE; + if (e != 1) $stop; + if (e != ONE) $stop; + e = enum_t'(ONE); + if (e != ONE) $stop; + e = enum_t'(16'h1); + if (e != ONE) $stop; + pdata_reg.data = 1; + e = enum_t'(pdata_reg); + if (e != ONE) $stop; + o = tocast_t'(4'b1); if (o != 4'b1) $stop; diff --git a/test_regress/t/t_array_interface.pl b/test_regress/t/t_cast_class.pl similarity index 100% rename from test_regress/t/t_array_interface.pl rename to test_regress/t/t_cast_class.pl diff --git a/test_regress/t/t_cast_class.v b/test_regress/t/t_cast_class.v new file mode 100644 index 000000000..41112a868 --- /dev/null +++ b/test_regress/t/t_cast_class.v @@ -0,0 +1,39 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2011 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +class Base; + int b; +endclass +class BaseExtended extends Base; + int e; +endclass + +module t; + + Base v_cls_a; + BaseExtended v_cls_ab; + BaseExtended v_cls_ab1; + + initial begin + v_cls_a = Base'(null); + if (v_cls_a != null) $stop; + + v_cls_ab = new; + v_cls_ab.b = 10; + v_cls_ab.e = 20; + + v_cls_ab1 = BaseExtended'(v_cls_ab); + if (v_cls_ab1.b != 10) $stop; + if (v_cls_ab1.e != 20) $stop; + + v_cls_a = Base'(v_cls_ab); + if (v_cls_a.b != 10) $stop; + + $write("*-* All Finished *-*\n"); + $finish; + end + +endmodule diff --git a/test_regress/t/t_cast_class_incompat_bad.out b/test_regress/t/t_cast_class_incompat_bad.out new file mode 100644 index 000000000..2f214826d --- /dev/null +++ b/test_regress/t/t_cast_class_incompat_bad.out @@ -0,0 +1,10 @@ +%Error: t/t_cast_class_incompat_bad.v:26:16: Dynamic, not static cast, required to cast 'CLASSREFDTYPE 'BaseExtended'' from 'CLASSREFDTYPE 'Base'' + : ... In instance t + : ... Suggest dynamic $cast + 26 | cls_ab = BaseExtended'(cls_a); + | ^~~~~~~~~~~~ +%Error: t/t_cast_class_incompat_bad.v:27:15: Incompatible types to static cast to 'CLASSREFDTYPE 'Other'' from 'CLASSREFDTYPE 'BaseExtended'' + : ... In instance t + 27 | other = Other'(cls_ab); + | ^~~~~ +%Error: Exiting due to diff --git a/test_regress/t/t_cast_class_incompat_bad.pl b/test_regress/t/t_cast_class_incompat_bad.pl new file mode 100755 index 000000000..9c9fb65a0 --- /dev/null +++ b/test_regress/t/t_cast_class_incompat_bad.pl @@ -0,0 +1,19 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2010 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(linter => 1); + +lint( + fails => 1, + expect_filename => $Self->{golden_filename}, + ); + +ok(1); +1; diff --git a/test_regress/t/t_cast_class_incompat_bad.v b/test_regress/t/t_cast_class_incompat_bad.v new file mode 100644 index 000000000..d730af005 --- /dev/null +++ b/test_regress/t/t_cast_class_incompat_bad.v @@ -0,0 +1,30 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2011 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +class Base; +endclass +class BaseExtended extends Base; +endclass +class Other; +endclass + +typedef Base Base_t; +typedef BaseExtended BaseExtended_t; +typedef Other Other_t; + +module t; + + Base_t cls_a; + BaseExtended_t cls_ab; + Other_t other; + + initial begin + cls_a = new; + cls_ab = BaseExtended'(cls_a); // bad-need dyn + other = Other'(cls_ab); // bad-incompat + end + +endmodule diff --git a/test_regress/t/t_cast_types.pl b/test_regress/t/t_cast_types.pl new file mode 100755 index 000000000..aabcde63e --- /dev/null +++ b/test_regress/t/t_cast_types.pl @@ -0,0 +1,21 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2020 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(simulator => 1); + +compile( + ); + +execute( + check_finished => 1, + ); + +ok(1); +1; diff --git a/test_regress/t/t_cast_types.v b/test_regress/t/t_cast_types.v new file mode 100644 index 000000000..7867ec85d --- /dev/null +++ b/test_regress/t/t_cast_types.v @@ -0,0 +1,136 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2020 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +`define TRY_ASSIGN(a,b) a = b +`define TRY_CAST(a,b) a = type(a)'(b) +`ifdef VERILATOR +`define TRY_DYNAMIC(a,b) // UNSUP $cast +`define TRY_BAD(a,b) // UNSUP $cast +`else +`define TRY_DYNAMIC(a,b) if (1 != $cast(a, b)) $stop +`define TRY_BAD(a,b) if (0 != $cast(a, b)) $stop +`endif + +`define MATCHING(a,b) `TRY_ASSIGN(a,b) +`define EQUIVALENT(a,b) `TRY_ASSIGN(a,b) +`define COMPATIBLE(a,b) `TRY_ASSIGN(a,b) +`define CAST_COMPATIBLE(a,b) `TRY_CAST(a,b) +`define CAST_COMPATIBLE_ENUM(a,b) `TRY_CAST(a,b) +`define CAST_COMPATIBLE_DYNAMIC(a,b) `TRY_DYNAMIC(a,b) +`define INCOMPATIBLE(a,b) `TRY_BAD(a,b) + +`define STRING_LITERAL "literal" // IEEE 5.9 - to packed or unpacked per IEEE 6.24 + +class Base; +endclass +class BaseExtended extends Base; +endclass +class Other; +endclass + +typedef enum { A_ZERO, A_ONE } Enum_A_t; +typedef enum { B_ZERO, B_ONE } Enum_B_t; + +typedef int int_t; + +typedef struct packed { int a; int b; } stpack_t; + +typedef bit signed [7:0] simple_a_t; +typedef bit signed [7:0] simple_a1_t; + +module t (/*AUTOARG*/); + + real v_real; // IEEE 6.12.2 - by rounding + string v_string; + int v_int; + int_t v_int_t; + chandle v_chandle; + Enum_A_t v_enum_a; + Enum_A_t v_enum_a1; + Enum_B_t v_enum_b; + stpack_t v_stpack_a; + stpack_t v_stpack_a1; + simple_a_t v_simple_a; + simple_a1_t v_simple_a1; + int v_unpk_a[2][3]; + int v_unpk_a1[2][3]; + int v_assoc_a[string]; + int v_assoc_a1[string]; + int v_assoc_b[int]; + int v_assoc_c[bit[31:0]]; + + int v_q_a[$]; + int v_q_a1[$]; + real v_q_b[$]; + + bit [3:0][7:0] v_2thirtytwo_a; + bit [3:0][7:0] v_2thirtytwo_b; + logic [3:0][7:0] v_4thirtytwo_a; + logic [3:0][7:0] v_4thirtytwo_b; + + Base v_cls_a; + Base v_cls_a1; + BaseExtended v_cls_ab; + Other v_cls_b; + + // verilator lint_off REALCVT + + initial begin + // 6.22.1 + `MATCHING(v_real, v_real); + `MATCHING(v_string, v_string); + `MATCHING(v_int, v_int); + `MATCHING(v_chandle, v_chandle); + `MATCHING(v_int, v_int_t); + `MATCHING(v_stpack_a, v_stpack_a1); + `MATCHING(v_simple_a, v_simple_a1); + `MATCHING(v_unpk_a, v_unpk_a1); + `MATCHING(v_assoc_a, v_assoc_a1); + `MATCHING(v_q_a, v_q_a1); + `MATCHING(v_int, v_2thirtytwo_a); + `MATCHING(v_cls_a, v_cls_a1); + `MATCHING(v_cls_a, v_cls_ab); + // 6.22.2 + `EQUIVALENT(v_int, v_2thirtytwo_a); +`ifndef NC +`ifndef VCS + `EQUIVALENT(v_assoc_b, v_assoc_c); // Spec says equivalent, but simulators disagree +`endif +`endif + // 6.22.3 + `COMPATIBLE(v_string, `STRING_LITERAL); + `COMPATIBLE(v_int, v_enum_a); + `COMPATIBLE(v_int, v_real); + `COMPATIBLE(v_real, v_int); + // 6.22.4->5.9 +`ifndef NC + `CAST_COMPATIBLE(v_string, v_int); +`endif + // 6.22.4->6.19.3 +`ifndef NC + `CAST_COMPATIBLE_ENUM(v_enum_a, v_int); + `CAST_COMPATIBLE_ENUM(v_enum_a, v_enum_b); +`endif + `CAST_COMPATIBLE_DYNAMIC(v_cls_ab, v_cls_a); + // 6.22.5 incompatible + `INCOMPATIBLE(v_cls_ab, v_int); +`ifndef VCS + `INCOMPATIBLE(v_real, v_assoc_a); + `INCOMPATIBLE(v_real, v_q_a); +`endif +`ifndef VCS + `ifndef VERILATOR + `INCOMPATIBLE(v_chandle, v_int); + `endif +`endif +`ifndef NC + `INCOMPATIBLE(v_cls_a, v_cls_b); +`endif + + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule diff --git a/test_regress/t/t_castdyn.out b/test_regress/t/t_castdyn.out deleted file mode 100644 index 2e5c96249..000000000 --- a/test_regress/t/t_castdyn.out +++ /dev/null @@ -1,29 +0,0 @@ -%Error-UNSUPPORTED: t/t_castdyn.v:28:11: Unsupported: $cast. Suggest try static cast. - : ... In instance t - 28 | i = $cast(ao, a); - | ^~~~~ -%Error-UNSUPPORTED: t/t_castdyn.v:33:7: Unsupported: $cast. Suggest try static cast. - : ... In instance t - 33 | $cast(ao, a); - | ^~~~~ -%Error-UNSUPPORTED: t/t_castdyn.v:36:11: Unsupported: $cast. Suggest try static cast. - : ... In instance t - 36 | i = $cast(ao, 2.1 * 3.7); - | ^~~~~ -%Error-UNSUPPORTED: t/t_castdyn.v:40:11: Unsupported: $cast. Suggest try static cast. - : ... In instance t - 40 | i = $cast(bo, null); - | ^~~~~ -%Error-UNSUPPORTED: t/t_castdyn.v:46:11: Unsupported: $cast. Suggest try static cast. - : ... In instance t - 46 | i = $cast(bao, b); - | ^~~~~ -%Error-UNSUPPORTED: t/t_castdyn.v:52:11: Unsupported: $cast. Suggest try static cast. - : ... In instance t - 52 | i = $cast(bbo, b); - | ^~~~~ -%Error-UNSUPPORTED: t/t_castdyn.v:59:11: Unsupported: $cast. Suggest try static cast. - : ... In instance t - 59 | i = $cast(bao, b); - | ^~~~~ -%Error: Exiting due to diff --git a/test_regress/t/t_castdyn.pl b/test_regress/t/t_castdyn.pl index 2ad4a887d..aabcde63e 100755 --- a/test_regress/t/t_castdyn.pl +++ b/test_regress/t/t_castdyn.pl @@ -11,13 +11,11 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di scenarios(simulator => 1); compile( - fails => $Self->{vlt_all}, - expect_filename => $Self->{golden_filename}, ); execute( check_finished => 1, - ) if !$Self->{vlt_all}; + ); ok(1); 1; diff --git a/test_regress/t/t_castdyn.v b/test_regress/t/t_castdyn.v index 4c8761f96..9ccb19dc8 100644 --- a/test_regress/t/t_castdyn.v +++ b/test_regress/t/t_castdyn.v @@ -23,6 +23,8 @@ module t (/*AUTOARG*/); BasedB bb; BasedB bbo; + // verilator lint_off CASTCONST + initial begin a = 1234; i = $cast(ao, a); diff --git a/test_regress/t/t_castdyn_castconst_bad.out b/test_regress/t/t_castdyn_castconst_bad.out new file mode 100644 index 000000000..cb8251c49 --- /dev/null +++ b/test_regress/t/t_castdyn_castconst_bad.out @@ -0,0 +1,16 @@ +%Warning-CASTCONST: t/t_castdyn_castconst_bad.v:20:11: $cast will always return one as 'int' is always castable from 'logic[31:0]' + : ... In instance t + : ... Suggest static cast + 20 | i = $cast(v, 1); + | ^~~~~ + ... Use "/* verilator lint_off CASTCONST */" and lint_on around source to disable this message. +%Warning-CASTCONST: t/t_castdyn_castconst_bad.v:21:11: $cast will always return one as 'CLASSREFDTYPE 'Base'' is always castable from 'CLASSREFDTYPE 'Base'' + : ... In instance t + : ... Suggest static cast + 21 | i = $cast(b, b); + | ^~~~~ +%Warning-CASTCONST: t/t_castdyn_castconst_bad.v:22:11: $cast will always return zero as 'CLASSREFDTYPE 'Base'' is not castable from 'CLASSREFDTYPE 'Other'' + : ... In instance t + 22 | i = $cast(b, o); + | ^~~~~ +%Error: Exiting due to diff --git a/test_regress/t/t_castdyn_castconst_bad.pl b/test_regress/t/t_castdyn_castconst_bad.pl new file mode 100755 index 000000000..35d749208 --- /dev/null +++ b/test_regress/t/t_castdyn_castconst_bad.pl @@ -0,0 +1,19 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003-2009 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(linter => 1); + +lint( + fails => 1, + expect_filename => $Self->{golden_filename}, + ); + +ok(1); +1; diff --git a/test_regress/t/t_castdyn_castconst_bad.v b/test_regress/t/t_castdyn_castconst_bad.v new file mode 100644 index 000000000..3ec97778e --- /dev/null +++ b/test_regress/t/t_castdyn_castconst_bad.v @@ -0,0 +1,27 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2005-2007 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +class Base; +endclass +class Other; +endclass +enum { ZERO } e; + +module t (/*AUTOARG*/); + + int i; + int v; + Base b; + Other o; + initial begin + i = $cast(v, 1); // 1 + i = $cast(b, b); // 1 + i = $cast(b, o); // 0 + i = $cast(e, 0); // 1 + i = $cast(e, 10); // 0 + end + +endmodule diff --git a/test_regress/t/t_castdyn_enum.out b/test_regress/t/t_castdyn_enum.out deleted file mode 100644 index 893b3046b..000000000 --- a/test_regress/t/t_castdyn_enum.out +++ /dev/null @@ -1,5 +0,0 @@ -%Error-UNSUPPORTED: t/t_castdyn_enum.v:23:11: Unsupported: $cast. Suggest try static cast. - : ... In instance t - 23 | i = $cast(en, cyc); - | ^~~~~ -%Error: Exiting due to diff --git a/test_regress/t/t_castdyn_enum.pl b/test_regress/t/t_castdyn_enum.pl index 2ad4a887d..aabcde63e 100755 --- a/test_regress/t/t_castdyn_enum.pl +++ b/test_regress/t/t_castdyn_enum.pl @@ -11,13 +11,11 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di scenarios(simulator => 1); compile( - fails => $Self->{vlt_all}, - expect_filename => $Self->{golden_filename}, ); execute( check_finished => 1, - ) if !$Self->{vlt_all}; + ); ok(1); 1; diff --git a/test_regress/t/t_castdyn_enum.v b/test_regress/t/t_castdyn_enum.v index 44cf50098..47e61cf98 100644 --- a/test_regress/t/t_castdyn_enum.v +++ b/test_regress/t/t_castdyn_enum.v @@ -15,9 +15,23 @@ module t (/*AUTOARG*/ input clk; int i; + int i_const; int cyc; enum_t en; + // Constant propagation tests + initial begin + en = SIXTEEN; + i_const = $cast(en, 1); + if (i_const != 0) $stop; + if (en != SIXTEEN) $stop; + + en = SIXTEEN; + i_const = $cast(en, 10); + if (i_const != 1) $stop; + if (en != TEN) $stop; + end + // Test loop always @ (posedge clk) begin i = $cast(en, cyc); diff --git a/test_regress/t/t_castdyn_run_bad.out b/test_regress/t/t_castdyn_run_bad.out index bba531f0e..3df579223 100644 --- a/test_regress/t/t_castdyn_run_bad.out +++ b/test_regress/t/t_castdyn_run_bad.out @@ -1,9 +1,3 @@ -%Error-UNSUPPORTED: t/t_castdyn_run_bad.v:20:11: Unsupported: $cast. Suggest try static cast. - : ... In instance t - 20 | i = $cast(c, b); - | ^~~~~ -%Error-UNSUPPORTED: t/t_castdyn_run_bad.v:23:7: Unsupported: $cast. Suggest try static cast. - : ... In instance t - 23 | $cast(c, b); - | ^~~~~ -%Error: Exiting due to +[0] %Error: t_castdyn_run_bad.v:32: Assertion failed in top.t: 'assert' failed. +%Error: t/t_castdyn_run_bad.v:32: Verilog $stop +Aborting... diff --git a/test_regress/t/t_castdyn_run_bad.pl b/test_regress/t/t_castdyn_run_bad.pl index 2ad4a887d..8b1946a7b 100755 --- a/test_regress/t/t_castdyn_run_bad.pl +++ b/test_regress/t/t_castdyn_run_bad.pl @@ -11,13 +11,12 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di scenarios(simulator => 1); compile( - fails => $Self->{vlt_all}, - expect_filename => $Self->{golden_filename}, ); execute( - check_finished => 1, - ) if !$Self->{vlt_all}; + fails => 1, + expect_filename => $Self->{golden_filename}, + ); ok(1); 1; diff --git a/test_regress/t/t_castdyn_run_bad.v b/test_regress/t/t_castdyn_run_bad.v index 37fe1ec74..9e8a5260b 100644 --- a/test_regress/t/t_castdyn_run_bad.v +++ b/test_regress/t/t_castdyn_run_bad.v @@ -6,21 +6,30 @@ class Base; endclass -class C; +class ExbaseA extends Base; +endclass +class ExbaseB extends Base; endclass module t (/*AUTOARG*/); int i; Base b; - C c; + ExbaseA ba, ba1; + ExbaseB bb, bb1; initial begin - b = new; - i = $cast(c, b); - if (i != 0) $stop; + ba = new; + b = ba; + i = $cast(ba1, b); + if (i != 1) $stop; + $cast(ba1, b); // ok at runtime - $cast(c, b); // Bad at runtime + bb = new; + b = bb; + i = $cast(ba1, b); + if (i != 0) $stop; + $cast(ba1, b); $write("*-* All Finished *-*\n"); $finish; diff --git a/test_regress/t/t_castdyn_unsup_bad.out b/test_regress/t/t_castdyn_unsup_bad.out new file mode 100644 index 000000000..bb045d2d7 --- /dev/null +++ b/test_regress/t/t_castdyn_unsup_bad.out @@ -0,0 +1,6 @@ +%Error-UNSUPPORTED: t/t_castdyn_unsup_bad.v:13:7: Unsupported: $cast to 'string[$]' from 'int[string]' + : ... In instance t + : ... Suggest try static cast + 13 | $cast(q, aarray); + | ^~~~~ +%Error: Exiting due to diff --git a/test_regress/t/t_castdyn_unsup_bad.pl b/test_regress/t/t_castdyn_unsup_bad.pl new file mode 100755 index 000000000..35d749208 --- /dev/null +++ b/test_regress/t/t_castdyn_unsup_bad.pl @@ -0,0 +1,19 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003-2009 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(linter => 1); + +lint( + fails => 1, + expect_filename => $Self->{golden_filename}, + ); + +ok(1); +1; diff --git a/test_regress/t/t_castdyn_unsup_bad.v b/test_regress/t/t_castdyn_unsup_bad.v new file mode 100644 index 000000000..26cd436bd --- /dev/null +++ b/test_regress/t/t_castdyn_unsup_bad.v @@ -0,0 +1,16 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2020 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +module t (/*AUTOARG*/); + + string q[$]; + int aarray[string]; + + initial begin + $cast(q, aarray); + end + +endmodule diff --git a/test_regress/t/t_class_fwd_cc.pl b/test_regress/t/t_class_fwd_cc.pl new file mode 100755 index 000000000..7314796b8 --- /dev/null +++ b/test_regress/t/t_class_fwd_cc.pl @@ -0,0 +1,13 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(vlt => 1); + +lint( + ); + +ok(1); +1; diff --git a/test_regress/t/t_class_fwd_cc.v b/test_regress/t/t_class_fwd_cc.v new file mode 100644 index 000000000..dce477fdf --- /dev/null +++ b/test_regress/t/t_class_fwd_cc.v @@ -0,0 +1,22 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2020 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +package Pkg; + typedef class Fwd; + virtual class Virt; + pure virtual function Fwd get_root(); + endclass + class Ext extends Virt; + virtual function Fwd get_root(); + return Fwd::m_uvm_get_root(); + endfunction + endclass + class Fwd; + function Fwd m_uvm_get_root(); + return null; + endfunction + endclass +endpackage diff --git a/test_regress/t/t_class_mod_bad.out b/test_regress/t/t_class_mod_bad.out index 8a24ba164..08ae3c20d 100644 --- a/test_regress/t/t_class_mod_bad.out +++ b/test_regress/t/t_class_mod_bad.out @@ -1,4 +1,4 @@ -%Error: t/t_class_mod_bad.v:21:7: '::' expected to reference a class/package but referenced MODULE 'M' +%Error: t/t_class_mod_bad.v:21:7: '::' expected to reference a class/package but referenced 'MODULE 'M'' : ... Suggest '.' instead of '::' 21 | M::Cls p; | ^ diff --git a/test_regress/t/t_class_param.out b/test_regress/t/t_class_param.out index 53cdad86a..1a041787c 100644 --- a/test_regress/t/t_class_param.out +++ b/test_regress/t/t_class_param.out @@ -1,7 +1,9 @@ -%Error-UNSUPPORTED: t/t_class_param.v:20:4: Unsupported: parameterized packages - 20 | Cls #(.P(4)) c4; - | ^~~ -%Error-UNSUPPORTED: t/t_class_param.v:9:23: Unsupported: class parameter +%Error-UNSUPPORTED: t/t_class_param.v:9:23: Unsupported: class parameters + : ... In instance t 9 | class Cls #(parameter P = 12); | ^ +%Error-UNSUPPORTED: t/t_class_param.v:20:11: Unsupported: parameterized classes + : ... In instance t + 20 | Cls #(.P(4)) c4; + | ^ %Error: Exiting due to diff --git a/test_regress/t/t_class_param_bad.out b/test_regress/t/t_class_param_bad.out index d7a071bf0..20b89cfa7 100644 --- a/test_regress/t/t_class_param_bad.out +++ b/test_regress/t/t_class_param_bad.out @@ -1,17 +1,8 @@ -%Error-UNSUPPORTED: t/t_class_param_bad.v:12:4: Unsupported: parameterized packages - 12 | Cls #(.PARAMBAD(1)) c; - | ^~~ %Error: t/t_class_param_bad.v:12:11: Parameter pin not found: 'PARAMBAD' : ... Suggested alternative: 'PARAMB' 12 | Cls #(.PARAMBAD(1)) c; | ^~~~~~~~ -%Error-UNSUPPORTED: t/t_class_param_bad.v:13:4: Unsupported: parameterized packages - 13 | Cls #(13, 1) cd; - | ^~~ %Error: t/t_class_param_bad.v:13:14: Parameter pin not found: '__paramNumber2' 13 | Cls #(13, 1) cd; | ^ -%Error-UNSUPPORTED: t/t_class_param_bad.v:7:23: Unsupported: class parameter - 7 | class Cls #(parameter PARAMB = 12); - | ^~~~~~ %Error: Exiting due to diff --git a/test_regress/t/t_class_unsup_bad.pl b/test_regress/t/t_class_unsup_bad.pl index 009248fc5..33a7f3beb 100755 --- a/test_regress/t/t_class_unsup_bad.pl +++ b/test_regress/t/t_class_unsup_bad.pl @@ -12,6 +12,7 @@ scenarios(vlt => 1); lint( fails => 1, + verilator_flags2 => ['-Wno-RANDC'], expect_filename => $Self->{golden_filename}, ); diff --git a/test_regress/t/t_class_vparam.out b/test_regress/t/t_class_vparam.out index 1816089b8..798dea2ca 100644 --- a/test_regress/t/t_class_vparam.out +++ b/test_regress/t/t_class_vparam.out @@ -1,7 +1,17 @@ -%Error-UNSUPPORTED: t/t_class_vparam.v:13:40: Unsupported: parameterized packages - 13 | pure virtual function void funcname(paramed_class_t #(CTYPE_t) v); - | ^~~~~~~~~~~~~~~ -%Error: t/t_class_vparam.v:13:58: Parameter pin not found: '__paramNumber1' - 13 | pure virtual function void funcname(paramed_class_t #(CTYPE_t) v); +%Error-UNSUPPORTED: t/t_class_vparam.v:11:26: Unsupported: parameterized classes + : ... In instance t + 11 | typedef paramed_class_t#(real, 1) paramed_class_double_t; + | ^~~~ +%Error-UNSUPPORTED: t/t_class_vparam.v:13:56: Unsupported: class parameters + : ... In instance t + 13 | virtual class vclass #(type CTYPE_t = arg_class_t, int I = 0); + | ^ +%Error-UNSUPPORTED: t/t_class_vparam.v:14:58: Unsupported: parameterized classes + : ... In instance t + 14 | pure virtual function void funcname(paramed_class_t #(CTYPE_t) v); | ^~~~~~~ +%Error-UNSUPPORTED: t/t_class_vparam.v:17:46: Unsupported: class parameters + : ... In instance t + 17 | class paramed_class_t #(type TYPE = int, int I = 0); + | ^ %Error: Exiting due to diff --git a/test_regress/t/t_class_vparam.v b/test_regress/t/t_class_vparam.v index d19d0988e..9f19c609a 100644 --- a/test_regress/t/t_class_vparam.v +++ b/test_regress/t/t_class_vparam.v @@ -8,12 +8,13 @@ typedef class paramed_class_t; typedef class arg_class_t; +typedef paramed_class_t#(real, 1) paramed_class_double_t; -virtual class vclass #(type CTYPE_t = arg_class_t); +virtual class vclass #(type CTYPE_t = arg_class_t, int I = 0); pure virtual function void funcname(paramed_class_t #(CTYPE_t) v); endclass -class paramed_class_t #(type TYPE=int); +class paramed_class_t #(type TYPE = int, int I = 0); endclass class arg_class_t; diff --git a/test_regress/t/t_clk_condflop.v b/test_regress/t/t_clk_condflop.v index 7cc4e1b69..98852229a 100644 --- a/test_regress/t/t_clk_condflop.v +++ b/test_regress/t/t_clk_condflop.v @@ -112,6 +112,7 @@ module clockgate (clk, sen, ena, gatedclk); wire gatedclk = clk & ena_b; // verilator lint_off COMBDLY + // verilator lint_off LATCH always @(clk or ena or sen) begin if (~clk) begin ena_b <= ena | sen; @@ -120,6 +121,7 @@ module clockgate (clk, sen, ena, gatedclk); if ((clk^sen)===1'bX) ena_b <= 1'bX; end end + // verilator lint_on LATCH // verilator lint_on COMBDLY endmodule diff --git a/test_regress/t/t_clk_condflop_nord.v b/test_regress/t/t_clk_condflop_nord.v index 7cc4e1b69..98852229a 100644 --- a/test_regress/t/t_clk_condflop_nord.v +++ b/test_regress/t/t_clk_condflop_nord.v @@ -112,6 +112,7 @@ module clockgate (clk, sen, ena, gatedclk); wire gatedclk = clk & ena_b; // verilator lint_off COMBDLY + // verilator lint_off LATCH always @(clk or ena or sen) begin if (~clk) begin ena_b <= ena | sen; @@ -120,6 +121,7 @@ module clockgate (clk, sen, ena, gatedclk); if ((clk^sen)===1'bX) ena_b <= 1'bX; end end + // verilator lint_on LATCH // verilator lint_on COMBDLY endmodule diff --git a/test_regress/t/t_clk_latch.v b/test_regress/t/t_clk_latch.v index 7fc4e96ea..caf25288c 100644 --- a/test_regress/t/t_clk_latch.v +++ b/test_regress/t/t_clk_latch.v @@ -53,6 +53,7 @@ module t (/*AUTOARG*/ end // verilator lint_off COMBDLY + // verilator lint_off LATCH always @ (`posstyle clk /*AS*/ or data) begin if (clk) begin data_a <= data + 8'd1; diff --git a/test_regress/t/t_clk_latchgate.v b/test_regress/t/t_clk_latchgate.v index bf43d7c06..120db757f 100644 --- a/test_regress/t/t_clk_latchgate.v +++ b/test_regress/t/t_clk_latchgate.v @@ -111,11 +111,13 @@ module llq (clk, d, q); reg [WIDTH-1:0] qr; /* verilator lint_off COMBDLY */ + /* verilator lint_off LATCH */ always @(clk or d) if (clk == 1'b0) qr <= d; + /* verilator lint_on LATCH */ /* verilator lint_on COMBDLY */ assign q = qr; diff --git a/test_regress/t/t_const_opt_red.v b/test_regress/t/t_const_opt_red.v index 0afb42832..d36faf72b 100644 --- a/test_regress/t/t_const_opt_red.v +++ b/test_regress/t/t_const_opt_red.v @@ -34,6 +34,9 @@ module t(/*AUTOARG*/ logic x3; // From test of Test.v logic x4; // From test of Test.v logic x5; // From test of Test.v + logic z1; // From test of Test.v + logic z2; // From test of Test.v + logic z3; // From test of Test.v // End of automatics wire [31:0] i = crc[31:0]; @@ -55,6 +58,9 @@ module t(/*AUTOARG*/ .x3 (x3), .x4 (x4), .x5 (x5), + .z1 (z1), + .z2 (z2), + .z3 (z3), // Inputs .clk (clk), .i (i[31:0])); @@ -98,6 +104,9 @@ module t(/*AUTOARG*/ if (x1 != x3) $stop; if (x1 != x4) $stop; if (x1 != x5) $stop; + if (z1 != '0) $stop; + if (z2 != '1) $stop; + if (z3 != '0) $stop; end else begin $write("[%0t] cyc==%0d crc=%x sum=%x\n",$time, cyc, crc, sum); @@ -114,7 +123,7 @@ endmodule module Test(/*AUTOARG*/ // Outputs - a1, a2, a3, a4, a5, o1, o2, o3, o4, o5, x1, x2, x3, x4, x5, + a1, a2, a3, a4, a5, o1, o2, o3, o4, o5, x1, x2, x3, x4, x5, z1, z2, z3, // Inputs clk, i ); @@ -125,6 +134,7 @@ module Test(/*AUTOARG*/ output logic a1, a2, a3, a4, a5; output logic o1, o2, o3, o4, o5; output logic x1, x2, x3, x4, x5; + output logic z1, z2, z3; always_ff @(posedge clk) begin a1 <= (i[5] & ~i[3] & i[1]); @@ -144,6 +154,11 @@ module Test(/*AUTOARG*/ x3 <= ^{i[5], ~i[3], i[1]}; x4 <= ^((i & 32'b101010) ^ 32'b001000); x5 <= ^((i & 32'b001010) ^ 32'b001000) ^ i[5]; + // + // All zero/all one cases + z1 <= (i[5] & ~i[3] & ~i[5]); + z2 <= (~i[5] | i[3] | i[5]); + z3 <= (i[5] ^ ~i[3] ^ ~i[5] ^ i[3]); end endmodule diff --git a/test_regress/t/t_cover_lib_1.out b/test_regress/t/t_cover_lib_1.out index d757bf25a..71fdbee4b 100644 --- a/test_regress/t/t_cover_lib_1.out +++ b/test_regress/t/t_cover_lib_1.out @@ -1,4 +1,4 @@ # SystemC::Coverage-3 -C 'f../../t/t_cover_lib_c.cppl44pagesp_user/t_cover_lib_cokept_onehmain' 100 -C 'f../../t/t_cover_lib_c.cppl45pagesp_user/t_cover_lib_cokept_twohmain' 210 -C 'f../../t/t_cover_lib_c.cppl46pagesp_user/t_cover_lib_colost_threehmain' 220 +C 'f../../t/t_cover_lib_c.cppl35pagesp_user/t_cover_lib_cokept_onehmain' 100 +C 'f../../t/t_cover_lib_c.cppl36pagesp_user/t_cover_lib_cokept_twohmain' 210 +C 'f../../t/t_cover_lib_c.cppl37pagesp_user/t_cover_lib_colost_threehmain' 220 diff --git a/test_regress/t/t_cover_lib_2.out b/test_regress/t/t_cover_lib_2.out index 42ec9a18e..445668d78 100644 --- a/test_regress/t/t_cover_lib_2.out +++ b/test_regress/t/t_cover_lib_2.out @@ -1,3 +1,3 @@ # SystemC::Coverage-3 -C 'f../../t/t_cover_lib_c.cppl44pagesp_user/t_cover_lib_cokept_onehmain' 100 -C 'f../../t/t_cover_lib_c.cppl45pagesp_user/t_cover_lib_cokept_twohmain' 210 +C 'f../../t/t_cover_lib_c.cppl35pagesp_user/t_cover_lib_cokept_onehmain' 100 +C 'f../../t/t_cover_lib_c.cppl36pagesp_user/t_cover_lib_cokept_twohmain' 210 diff --git a/test_regress/t/t_cover_lib_3.out b/test_regress/t/t_cover_lib_3.out index 78bddf206..e04cf5d1c 100644 --- a/test_regress/t/t_cover_lib_3.out +++ b/test_regress/t/t_cover_lib_3.out @@ -1,3 +1,3 @@ # SystemC::Coverage-3 -C 'f../../t/t_cover_lib_c.cppl44pagesp_user/t_cover_lib_cokept_onehmain' 0 -C 'f../../t/t_cover_lib_c.cppl45pagesp_user/t_cover_lib_cokept_twohmain' 0 +C 'f../../t/t_cover_lib_c.cppl35pagesp_user/t_cover_lib_cokept_onehmain' 0 +C 'f../../t/t_cover_lib_c.cppl36pagesp_user/t_cover_lib_cokept_twohmain' 0 diff --git a/test_regress/t/t_cover_lib_c.cpp b/test_regress/t/t_cover_lib_c.cpp index 8b288fad9..a9168e483 100644 --- a/test_regress/t/t_cover_lib_c.cpp +++ b/test_regress/t/t_cover_lib_c.cpp @@ -24,15 +24,6 @@ double sc_time_stamp() { return 0; } int failure = 0; -#define CHECK_RESULT_HEX(got, exp) \ - do { \ - if ((got) != (exp)) { \ - std::cout << std::dec << "%Error: " << __FILE__ << ":" << __LINE__ << std::hex \ - << ": GOT=" << (got) << " EXP=" << (exp) << std::endl; \ - failure = __LINE__; \ - } \ - } while (0) - //====================================================================== const char* name() { return "main"; } diff --git a/test_regress/t/t_cover_toggle.v b/test_regress/t/t_cover_toggle.v index e069a3382..1c4008c3b 100644 --- a/test_regress/t/t_cover_toggle.v +++ b/test_regress/t/t_cover_toggle.v @@ -6,10 +6,12 @@ module t (/*AUTOARG*/ // Inputs - clk + clk, + check_real ); input clk; + input real check_real; // Check issue #2741 typedef struct packed { union packed { diff --git a/test_regress/t/t_debug_emitv.out b/test_regress/t/t_debug_emitv.out index dc1d81c5a..50ed186bf 100644 --- a/test_regress/t/t_debug_emitv.out +++ b/test_regress/t/t_debug_emitv.out @@ -1,18 +1,18 @@ module Vt_debug_emitv; input logic clk; input logic in; - signed int [31:0] [0:2] t.array; - logic logic [15:0] t.pubflat; - logic logic [15:0] t.pubflat_r; - int signed int [31:0] t.fd; - int signed int [31:0] t.i; - int signed int [31:0] t.cyc; - int signed int [31:0] t.fo; - int signed int [31:0] t.sum; - string string t.str; - int signed int [31:0] t._Vpast_0_0; - int signed int [31:0] t._Vpast_1_0; - int signed int [31:0] t.unnamedblk3.i; + signed int [31:0] t.array[0:2]; + logic [15:0] t.pubflat; + logic [15:0] t.pubflat_r; + signed int [31:0] t.fd; + signed int [31:0] t.i; + signed int [31:0] t.cyc; + signed int [31:0] t.fo; + signed int [31:0] t.sum; + string t.str; + signed int [31:0] t._Vpast_0_0; + signed int [31:0] t._Vpast_1_0; + signed int [31:0] t.unnamedblk3.i; @(*)@([settle])@([initial])@(posedge clk)@(negedge clk)always @( *)@( @@ -48,7 +48,6 @@ module Vt_debug_emitv; ???? // CFUNC '_final_TOP' $_CSTMT(Vt_debug_emitv* const __restrict vlTOPp VL_ATTR_UNUSED = vlSymsp->TOPp; ); - // FINAL $display("stmt"); always @(posedge clk)@(negedge clk) begin $display("posedge clk"); @@ -78,8 +77,8 @@ module Vt_debug_emitv; end t.sum = __Vfunc_t.sub.f__3__Vfuncout; $display("[%0t] sum = %~", $timet.sum, t.sum); - $display("a?= $d%d", ($c(32'sh1) ? $c(32'sh14) - : $c(32'sh1e))); + $display("a?= %d", ($c(32'sh1) ? $c(32'sh14) + : $c(32'sh1e))); $c(;); $display("%d", $c(0)); $fopen(72'h2f6465762f6e756c6c); @@ -172,6 +171,7 @@ module Vt_debug_emitv; $time, $time); $sscanf(40'h666f6f3d35, "foo=%d", t.i); ; + $printtimescale; if ((32'sh5 != t.i)) begin $stop; end @@ -198,12 +198,32 @@ module Vt_debug_emitv; always @(negedge clk) begin $display("negedge clk, pfr = %x", t.pubflat_r); end - int signed int [31:0] __Vtask_t.sub.inc__2__i; - int signed int [31:0] __Vtask_t.sub.inc__2__o; - int signed int [31:0] __Vfunc_t.sub.f__3__Vfuncout; - int signed int [31:0] __Vfunc_t.sub.f__3__v; - logic logic [15:0] __Vdly__t.pubflat_r; - int signed int [31:0] __Vdly__t.cyc; - int signed int [31:0] __Vdly__t._Vpast_0_0; - int signed int [31:0] __Vdly__t._Vpast_1_0; + signed int [31:0] __Vtask_t.sub.inc__2__i; + signed int [31:0] __Vtask_t.sub.inc__2__o; + signed int [31:0] __Vfunc_t.sub.f__3__Vfuncout; + signed int [31:0] __Vfunc_t.sub.f__3__v; + logic [15:0] __Vdly__t.pubflat_r; + signed int [31:0] __Vdly__t.cyc; + signed int [31:0] __Vdly__t._Vpast_0_0; + signed int [31:0] __Vdly__t._Vpast_1_0; endmodule +package Vt_debug_emitv___024unit; +endpackage +package Vt_debug_emitv_Pkg; +endpackage +class Vt_debug_emitv___024unit__03a__03aCls; +signed int [31:0] member; + +???? // CFUNC '__VnoInFunc_method' +$_CSTMT(Vt_debug_emitv* const __restrict vlTOPp VL_ATTR_UNUSED = vlSymsp->TOPp; +); + +???? // CFUNC 'new' +$_CSTMT(_ctor_var_reset(vlSymsp); +); +$_CSTMT(Vt_debug_emitv* const __restrict vlTOPp VL_ATTR_UNUSED = vlSymsp->TOPp; +); +$unit::Cls.member = 32'sh1; +endclass +/*class*/package Vt_debug_emitv___024unit__03a__03aCls__Vclpkg; +end/*class*/package diff --git a/test_regress/t/t_debug_emitv.v b/test_regress/t/t_debug_emitv.v index 5764cedcf..9ab85d288 100644 --- a/test_regress/t/t_debug_emitv.v +++ b/test_regress/t/t_debug_emitv.v @@ -5,6 +5,25 @@ // without warranty, 2020 by Wilson Snyder. // SPDX-License-Identifier: CC0-1.0 +package Pkg; + localparam PKG_PARAM = 1; +endpackage +package PkgImp; + import Pkg::*; + export Pkg::*; +endpackage + +class Cls; + int member = 1; + function void method; + endfunction +endclass + +interface Iface; + logic ifsig; + modport mp(input ifsig); +endinterface + module t (/*AUTOARG*/ // Inputs clk, in @@ -43,6 +62,10 @@ module t (/*AUTOARG*/ int fd; int i; + int q[$]; + int assoc[string]; + int dyn[]; + task t; $display("stmt"); endtask @@ -91,7 +114,7 @@ module t (/*AUTOARG*/ sub.inc(fo, sum); sum = sub.f(sum); $display("[%0t] sum = %d", $time, sum); - $display("a?= $d", $c(1) ? $c32(20) : $c32(30)); + $display("a?= %d", $c(1) ? $c32(20) : $c32(30)); $c(";"); $display("%d", $c("0")); @@ -143,12 +166,16 @@ module t (/*AUTOARG*/ $display("str = %s", str); $display("%% [%t] [%t] to=%o td=%d", $time, $realtime, $time, $time); $sscanf("foo=5", "foo=%d", i); + $printtimescale; if (i != 5) $stop; sum = $random; sum = $random(10); sum = $urandom; sum = $urandom(10); + + if (Pkg::PKG_PARAM != 1) $stop; + sub.r = 62.0; end endmodule diff --git a/test_regress/t/t_debug_graph_test.pl b/test_regress/t/t_debug_graph_test.pl index 5ae25d7f3..961994545 100755 --- a/test_regress/t/t_debug_graph_test.pl +++ b/test_regress/t/t_debug_graph_test.pl @@ -13,7 +13,7 @@ $ENV{VERILATOR_TEST_NO_GDB} and skip("Skipping due to VERILATOR_TEST_NO_GDB"); lint( # Check we can call dump() on graph, and other things - v_flags => ["--lint-only --debug --debugi-V3GraphTest 9 --debugi-V3GraphDfa 9"], + v_flags => ["--lint-only --debug --debugi-V3GraphTest 9 --debugi-V3GraphDfa 9 --debug-self-test"], ); ok(1); diff --git a/test_regress/t/t_debug_sigsegv_bad.pl b/test_regress/t/t_debug_sigsegv_bad.pl index 07e71bd60..631892fd9 100755 --- a/test_regress/t/t_debug_sigsegv_bad.pl +++ b/test_regress/t/t_debug_sigsegv_bad.pl @@ -14,6 +14,7 @@ $ENV{VERILATOR_TEST_NO_GDB} and skip("Skipping due to VERILATOR_TEST_NO_GDB"); lint( v_flags => ["--debug-sigsegv"], fails => 1, + sanitize => 0, expect => '%Error: Verilator internal fault, sorry. Suggest trying --debug --gdbbt %Error: Command Failed.*', diff --git a/test_regress/t/t_debug_sigsegv_bt_bad.pl b/test_regress/t/t_debug_sigsegv_bt_bad.pl index 1b1ca012c..fcee4ee37 100755 --- a/test_regress/t/t_debug_sigsegv_bt_bad.pl +++ b/test_regress/t/t_debug_sigsegv_bt_bad.pl @@ -13,6 +13,7 @@ $ENV{VERILATOR_TEST_NO_GDB} and skip("Skipping due to VERILATOR_TEST_NO_GDB"); lint( verilator_flags2 => ["--lint-only --debug --gdbbt --debug-sigsegv"], + sanitize => 0, fails => $Self->{vlt_all}, expect => '.* diff --git a/test_regress/t/t_dedupe_clk_gate.pl b/test_regress/t/t_dedupe_clk_gate.pl index 229d1186d..631bd3480 100755 --- a/test_regress/t/t_dedupe_clk_gate.pl +++ b/test_regress/t/t_dedupe_clk_gate.pl @@ -17,7 +17,7 @@ compile( ); if ($Self->{vlt_all}) { - file_grep("$out_filename", qr/\/i); + file_grep("$out_filename", qr/\/i); file_grep($Self->{stats}, qr/Optimizations, Gate sigs deduped\s+(\d+)/i, 4); } diff --git a/test_regress/t/t_dedupe_clk_gate.v b/test_regress/t/t_dedupe_clk_gate.v index 1cfcec315..af6331196 100644 --- a/test_regress/t/t_dedupe_clk_gate.v +++ b/test_regress/t/t_dedupe_clk_gate.v @@ -45,7 +45,7 @@ module clock_gate_latch (gated_clk, clk, clken); assign gated_clk = clk & clken_latched ; wire clkb = ~clk; - always @(clkb or clken) + always_latch @(clkb or clken) if(clkb) clken_latched = clken; endmodule diff --git a/test_regress/t/t_delay.v b/test_regress/t/t_delay.v index 7434c1841..c391c5b61 100644 --- a/test_regress/t/t_delay.v +++ b/test_regress/t/t_delay.v @@ -8,7 +8,6 @@ module t (/*AUTOARG*/ // Inputs clk ); - parameter PAR = 3; input clk; integer cyc=1; diff --git a/test_regress/t/t_delay_stmtdly_bad.out b/test_regress/t/t_delay_stmtdly_bad.out index 9a680e713..a5beee6c4 100644 --- a/test_regress/t/t_delay_stmtdly_bad.out +++ b/test_regress/t/t_delay_stmtdly_bad.out @@ -1,26 +1,26 @@ -%Warning-ASSIGNDLY: t/t_delay.v:23:13: Unsupported: Ignoring delay on this assignment/primitive. - 23 | assign #(1.2000000000000000) dly1 = dly0 + 32'h1; +%Warning-ASSIGNDLY: t/t_delay.v:22:13: Unsupported: Ignoring delay on this assignment/primitive. + 22 | assign #(1.2000000000000000) dly1 = dly0 + 32'h1; | ^~~~~~~~~~~~~~~~~~ ... Use "/* verilator lint_off ASSIGNDLY */" and lint_on around source to disable this message. -%Warning-ASSIGNDLY: t/t_delay.v:28:19: Unsupported: Ignoring delay on this assignment/primitive. - 28 | dly0 <= #0 32'h11; +%Warning-ASSIGNDLY: t/t_delay.v:27:19: Unsupported: Ignoring delay on this assignment/primitive. + 27 | dly0 <= #0 32'h11; | ^ -%Warning-ASSIGNDLY: t/t_delay.v:31:19: Unsupported: Ignoring delay on this assignment/primitive. - 31 | dly0 <= #0.12 dly0 + 32'h12; +%Warning-ASSIGNDLY: t/t_delay.v:30:19: Unsupported: Ignoring delay on this assignment/primitive. + 30 | dly0 <= #0.12 dly0 + 32'h12; | ^~~~ -%Warning-ASSIGNDLY: t/t_delay.v:39:25: Unsupported: Ignoring delay on this assignment/primitive. - 39 | dly0 <= #(dly_s.dly) 32'h55; +%Warning-ASSIGNDLY: t/t_delay.v:38:25: Unsupported: Ignoring delay on this assignment/primitive. + 38 | dly0 <= #(dly_s.dly) 32'h55; | ^ -%Warning-STMTDLY: t/t_delay.v:44:11: Unsupported: Ignoring delay on this delayed statement. +%Warning-STMTDLY: t/t_delay.v:43:11: Unsupported: Ignoring delay on this delayed statement. : ... In instance t - 44 | #100 $finish; + 43 | #100 $finish; | ^~~ -%Warning-UNUSED: t/t_delay.v:21:12: Signal is not used: 'dly_s' +%Warning-UNUSED: t/t_delay.v:20:12: Signal is not used: 'dly_s' : ... In instance t - 21 | dly_s_t dly_s; + 20 | dly_s_t dly_s; | ^~~~~ -%Warning-BLKSEQ: t/t_delay.v:38:20: Blocking assignments (=) in sequential (flop or latch) block +%Warning-BLKSEQ: t/t_delay.v:37:20: Blocking assignments (=) in sequential (flop or latch) block : ... Suggest delayed assignments (<=) - 38 | dly_s.dly = 55; + 37 | dly_s.dly = 55; | ^ %Error: Exiting due to diff --git a/test_regress/t/t_display_merge.out b/test_regress/t/t_display_merge.out index 7ab198f50..358455d76 100644 --- a/test_regress/t/t_display_merge.out +++ b/test_regress/t/t_display_merge.out @@ -1,8 +1,7 @@ Merge: This should merge f - a=top.t - b=top.t + 1=1 a=top.t 1=1 1=1 b=top.t 1=1 pre t=0 t2=0 @@ -15,5 +14,14 @@ m mm f a=top.t b=top.t pre t=0 t2=0 post t3=0 t4=0 t5=0 0m t=0 t2=0 t3=0 t4=0 t5=0 t=0 t2=0 t3=0 t4=0 t5=0mm +very very very very very very very very very very very very very very very very very very very very very very +very very very very very very very very very very very very very very very very very very very very very very +very very very very very very very very very very very very very very very very very very very very very very +very very very very very very very very very very very very very very very very very very very very very very +very very very very very very very very very very very very very very very very very very very very very very +very very very very very very very very very very very very very very very very very very very very very very +very very very very very very very very very very very very very very very very very very very very very very +11111 11111 +11111 11111 *-* All Finished *-* diff --git a/test_regress/t/t_display_merge.pl b/test_regress/t/t_display_merge.pl index 67b3d10f3..66642748d 100755 --- a/test_regress/t/t_display_merge.pl +++ b/test_regress/t/t_display_merge.pl @@ -20,7 +20,7 @@ execute( ); file_grep("$Self->{obj_dir}/$Self->{VM_PREFIX}__stats.txt", - qr/Node count, DISPLAY \s+ 32 \s+ 25 \s+ 25 \s+ 25/); + qr/Node count, DISPLAY \s+ 41 \s+ 27 \s+ 27 \s+ 6/); ok(1); 1; diff --git a/test_regress/t/t_display_merge.v b/test_regress/t/t_display_merge.v index cdf8ea8cc..9d5b1e3ec 100644 --- a/test_regress/t/t_display_merge.v +++ b/test_regress/t/t_display_merge.v @@ -5,6 +5,14 @@ // SPDX-License-Identifier: CC0-1.0 module t (/*AUTOARG*/); + int one = +`ifdef verilator + $c32(1) +`else + 1 +`endif + ; + initial begin $display("Merge:"); $write("This "); @@ -12,8 +20,8 @@ module t (/*AUTOARG*/); $display("merge"); $display("f"); - $display(" a=%m"); - $display(" b=%m"); + $write(" 1=%0d a=%m 1=%0d", one, one); + $display(" 1=%0d b=%m 1=%0d", one, one); $display(" pre"); $display(" t=%0d",$time); $display(" t2=%0d",$time); @@ -40,6 +48,19 @@ module t (/*AUTOARG*/); $write(" t=%0d t2=%0d t3=%0d t4=%0d t5=%0d",$time,$time,$time,$time,$time); $display("mm"); + $display("very very very very very very very very very very very very very very very very very very very very very very"); + $display("very very very very very very very very very very very very very very very very very very very very very very"); + $display("very very very very very very very very very very very very very very very very very very very very very very"); + $display("very very very very very very very very very very very very very very very very very very very very very very"); + $display("very very very very very very very very very very very very very very very very very very very very very very"); + $display("very very very very very very very very very very very very very very very very very very very very very very"); + $display("very very very very very very very very very very very very very very very very very very very very very very"); + $display("%0d%0d%0d%0d%0d %0d%0d%0d%0d%0d", + one, one, one, one, one, + one, one, one, one, one); + $display("%0d%0d%0d%0d%0d %0d%0d%0d%0d%0d", + one, one, one, one, one, + one, one, one, one, one); $write("\n*-* All Finished *-*\n"); $finish; end diff --git a/test_regress/t/t_dist_contributors.pl b/test_regress/t/t_dist_contributors.pl index 7f2764f91..527d3e157 100755 --- a/test_regress/t/t_dist_contributors.pl +++ b/test_regress/t/t_dist_contributors.pl @@ -16,10 +16,12 @@ scenarios(dist => 1); my $root = ".."; my $Debug; -my %Contributors; +my %Contributors = ('github action' => 1); my %Authors; -if (!-r "$root/.git") { +if ($ENV{VERILATOR_TEST_NO_CONTRIBUTORS}) { + skip("Skipping due to VERILATOR_TEST_NO_CONTRIBUTORS"); +} elsif (!-r "$root/.git") { skip("Not in a git repository"); } else { check(); diff --git a/test_regress/t/t_dpi_arg_inout_type.pl b/test_regress/t/t_dpi_arg_inout_type.pl index 68d9c487c..c885022e4 100755 --- a/test_regress/t/t_dpi_arg_inout_type.pl +++ b/test_regress/t/t_dpi_arg_inout_type.pl @@ -20,7 +20,8 @@ if ($Self->{nc}) { compile( v_flags2 => ["t/t_dpi_arg_inout_type.cpp"], - verilator_flags2 => ["-Wall -Wno-DECLFILENAME"], + # --no-decoration so .out file doesn't comment on source lines + verilator_flags2 => ["-Wall -Wno-DECLFILENAME --no-decoration"], # NC: Gdd the obj_dir to the C include path nc_flags2 => ["+ncscargs+-I$Self->{obj_dir}"], # ModelSim: Generate DPI header, add obj_dir to the C include path diff --git a/test_regress/t/t_dpi_arg_inout_type__Dpi.out b/test_regress/t/t_dpi_arg_inout_type__Dpi.out index 36221d574..3f0f7e242 100644 --- a/test_regress/t/t_dpi_arg_inout_type__Dpi.out +++ b/test_regress/t/t_dpi_arg_inout_type__Dpi.out @@ -10,278 +10,145 @@ #ifdef __cplusplus extern "C" { #endif - - - // DPI EXPORTS - // DPI export at t/t_dpi_arg_inout_type.v:571:18 - extern void e_array_2_state_1(svBitVecVal* x); - // DPI export at t/t_dpi_arg_inout_type.v:611:18 - extern void e_array_2_state_128(svBitVecVal* x); - // DPI export at t/t_dpi_arg_inout_type.v:579:18 - extern void e_array_2_state_32(svBitVecVal* x); - // DPI export at t/t_dpi_arg_inout_type.v:587:18 - extern void e_array_2_state_33(svBitVecVal* x); - // DPI export at t/t_dpi_arg_inout_type.v:595:18 - extern void e_array_2_state_64(svBitVecVal* x); - // DPI export at t/t_dpi_arg_inout_type.v:603:18 - extern void e_array_2_state_65(svBitVecVal* x); - // DPI export at t/t_dpi_arg_inout_type.v:718:18 - extern void e_array_4_state_1(svLogicVecVal* x); - // DPI export at t/t_dpi_arg_inout_type.v:758:18 - extern void e_array_4_state_128(svLogicVecVal* x); - // DPI export at t/t_dpi_arg_inout_type.v:726:18 - extern void e_array_4_state_32(svLogicVecVal* x); - // DPI export at t/t_dpi_arg_inout_type.v:734:18 - extern void e_array_4_state_33(svLogicVecVal* x); - // DPI export at t/t_dpi_arg_inout_type.v:742:18 - extern void e_array_4_state_64(svLogicVecVal* x); - // DPI export at t/t_dpi_arg_inout_type.v:750:18 - extern void e_array_4_state_65(svLogicVecVal* x); - // DPI export at t/t_dpi_arg_inout_type.v:422:18 - extern void e_bit(svBit* x); - // DPI export at t/t_dpi_arg_inout_type.v:554:18 - extern void e_bit_t(svBit* x); - // DPI export at t/t_dpi_arg_inout_type.v:307:18 - extern void e_byte(char* x); - // DPI export at t/t_dpi_arg_inout_type.v:439:18 - extern void e_byte_t(char* x); - // DPI export at t/t_dpi_arg_inout_type.v:314:18 - extern void e_byte_unsigned(unsigned char* x); - // DPI export at t/t_dpi_arg_inout_type.v:446:18 - extern void e_byte_unsigned_t(unsigned char* x); - // DPI export at t/t_dpi_arg_inout_type.v:397:18 - extern void e_chandle(void** x); - // DPI export at t/t_dpi_arg_inout_type.v:529:18 - extern void e_chandle_t(void** x); - // DPI export at t/t_dpi_arg_inout_type.v:335:18 - extern void e_int(int* x); - // DPI export at t/t_dpi_arg_inout_type.v:467:18 - extern void e_int_t(int* x); - // DPI export at t/t_dpi_arg_inout_type.v:342:18 - extern void e_int_unsigned(unsigned int* x); - // DPI export at t/t_dpi_arg_inout_type.v:474:18 - extern void e_int_unsigned_t(unsigned int* x); - // DPI export at t/t_dpi_arg_inout_type.v:373:18 - extern void e_integer(svLogicVecVal* x); - // DPI export at t/t_dpi_arg_inout_type.v:505:18 - extern void e_integer_t(svLogicVecVal* x); - // DPI export at t/t_dpi_arg_inout_type.v:430:18 - extern void e_logic(svLogic* x); - // DPI export at t/t_dpi_arg_inout_type.v:562:18 - extern void e_logic_t(svLogic* x); - // DPI export at t/t_dpi_arg_inout_type.v:349:18 - extern void e_longint(long long* x); - // DPI export at t/t_dpi_arg_inout_type.v:481:18 - extern void e_longint_t(long long* x); - // DPI export at t/t_dpi_arg_inout_type.v:356:18 - extern void e_longint_unsigned(unsigned long long* x); - // DPI export at t/t_dpi_arg_inout_type.v:488:18 - extern void e_longint_unsigned_t(unsigned long long* x); - // DPI export at t/t_dpi_arg_inout_type.v:381:18 - extern void e_real(double* x); - // DPI export at t/t_dpi_arg_inout_type.v:513:18 - extern void e_real_t(double* x); - // DPI export at t/t_dpi_arg_inout_type.v:321:18 - extern void e_shortint(short* x); - // DPI export at t/t_dpi_arg_inout_type.v:453:18 - extern void e_shortint_t(short* x); - // DPI export at t/t_dpi_arg_inout_type.v:328:18 - extern void e_shortint_unsigned(unsigned short* x); - // DPI export at t/t_dpi_arg_inout_type.v:460:18 - extern void e_shortint_unsigned_t(unsigned short* x); - // DPI export at t/t_dpi_arg_inout_type.v:409:18 - extern void e_string(const char** x); - // DPI export at t/t_dpi_arg_inout_type.v:541:18 - extern void e_string_t(const char** x); - // DPI export at t/t_dpi_arg_inout_type.v:620:18 - extern void e_struct_2_state_1(svBitVecVal* x); - // DPI export at t/t_dpi_arg_inout_type.v:660:18 - extern void e_struct_2_state_128(svBitVecVal* x); - // DPI export at t/t_dpi_arg_inout_type.v:628:18 - extern void e_struct_2_state_32(svBitVecVal* x); - // DPI export at t/t_dpi_arg_inout_type.v:636:18 - extern void e_struct_2_state_33(svBitVecVal* x); - // DPI export at t/t_dpi_arg_inout_type.v:644:18 - extern void e_struct_2_state_64(svBitVecVal* x); - // DPI export at t/t_dpi_arg_inout_type.v:652:18 - extern void e_struct_2_state_65(svBitVecVal* x); - // DPI export at t/t_dpi_arg_inout_type.v:767:18 - extern void e_struct_4_state_1(svLogicVecVal* x); - // DPI export at t/t_dpi_arg_inout_type.v:807:18 - extern void e_struct_4_state_128(svLogicVecVal* x); - // DPI export at t/t_dpi_arg_inout_type.v:775:18 - extern void e_struct_4_state_32(svLogicVecVal* x); - // DPI export at t/t_dpi_arg_inout_type.v:783:18 - extern void e_struct_4_state_33(svLogicVecVal* x); - // DPI export at t/t_dpi_arg_inout_type.v:791:18 - extern void e_struct_4_state_64(svLogicVecVal* x); - // DPI export at t/t_dpi_arg_inout_type.v:799:18 - extern void e_struct_4_state_65(svLogicVecVal* x); - // DPI export at t/t_dpi_arg_inout_type.v:364:18 - extern void e_time(svLogicVecVal* x); - // DPI export at t/t_dpi_arg_inout_type.v:496:18 - extern void e_time_t(svLogicVecVal* x); - // DPI export at t/t_dpi_arg_inout_type.v:669:18 - extern void e_union_2_state_1(svBitVecVal* x); - // DPI export at t/t_dpi_arg_inout_type.v:709:18 - extern void e_union_2_state_128(svBitVecVal* x); - // DPI export at t/t_dpi_arg_inout_type.v:677:18 - extern void e_union_2_state_32(svBitVecVal* x); - // DPI export at t/t_dpi_arg_inout_type.v:685:18 - extern void e_union_2_state_33(svBitVecVal* x); - // DPI export at t/t_dpi_arg_inout_type.v:693:18 - extern void e_union_2_state_64(svBitVecVal* x); - // DPI export at t/t_dpi_arg_inout_type.v:701:18 - extern void e_union_2_state_65(svBitVecVal* x); - // DPI export at t/t_dpi_arg_inout_type.v:816:18 - extern void e_union_4_state_1(svLogicVecVal* x); - // DPI export at t/t_dpi_arg_inout_type.v:856:18 - extern void e_union_4_state_128(svLogicVecVal* x); - // DPI export at t/t_dpi_arg_inout_type.v:824:18 - extern void e_union_4_state_32(svLogicVecVal* x); - // DPI export at t/t_dpi_arg_inout_type.v:832:18 - extern void e_union_4_state_33(svLogicVecVal* x); - // DPI export at t/t_dpi_arg_inout_type.v:840:18 - extern void e_union_4_state_64(svLogicVecVal* x); - // DPI export at t/t_dpi_arg_inout_type.v:848:18 - extern void e_union_4_state_65(svLogicVecVal* x); - - // DPI IMPORTS - // DPI import at t/t_dpi_arg_inout_type.v:867:41 - extern void check_exports(); - // DPI import at t/t_dpi_arg_inout_type.v:154:33 - extern void i_array_2_state_1(svBitVecVal* x); - // DPI import at t/t_dpi_arg_inout_type.v:159:33 - extern void i_array_2_state_128(svBitVecVal* x); - // DPI import at t/t_dpi_arg_inout_type.v:155:33 - extern void i_array_2_state_32(svBitVecVal* x); - // DPI import at t/t_dpi_arg_inout_type.v:156:33 - extern void i_array_2_state_33(svBitVecVal* x); - // DPI import at t/t_dpi_arg_inout_type.v:157:33 - extern void i_array_2_state_64(svBitVecVal* x); - // DPI import at t/t_dpi_arg_inout_type.v:158:33 - extern void i_array_2_state_65(svBitVecVal* x); - // DPI import at t/t_dpi_arg_inout_type.v:178:33 - extern void i_array_4_state_1(svLogicVecVal* x); - // DPI import at t/t_dpi_arg_inout_type.v:183:33 - extern void i_array_4_state_128(svLogicVecVal* x); - // DPI import at t/t_dpi_arg_inout_type.v:179:33 - extern void i_array_4_state_32(svLogicVecVal* x); - // DPI import at t/t_dpi_arg_inout_type.v:180:33 - extern void i_array_4_state_33(svLogicVecVal* x); - // DPI import at t/t_dpi_arg_inout_type.v:181:33 - extern void i_array_4_state_64(svLogicVecVal* x); - // DPI import at t/t_dpi_arg_inout_type.v:182:33 - extern void i_array_4_state_65(svLogicVecVal* x); - // DPI import at t/t_dpi_arg_inout_type.v:126:33 - extern void i_bit(svBit* x); - // DPI import at t/t_dpi_arg_inout_type.v:150:33 - extern void i_bit_t(svBit* x); - // DPI import at t/t_dpi_arg_inout_type.v:106:33 - extern void i_byte(char* x); - // DPI import at t/t_dpi_arg_inout_type.v:130:33 - extern void i_byte_t(char* x); - // DPI import at t/t_dpi_arg_inout_type.v:107:33 - extern void i_byte_unsigned(unsigned char* x); - // DPI import at t/t_dpi_arg_inout_type.v:131:33 - extern void i_byte_unsigned_t(unsigned char* x); - // DPI import at t/t_dpi_arg_inout_type.v:124:33 - extern void i_chandle(void** x); - // DPI import at t/t_dpi_arg_inout_type.v:148:33 - extern void i_chandle_t(void** x); - // DPI import at t/t_dpi_arg_inout_type.v:110:33 - extern void i_int(int* x); - // DPI import at t/t_dpi_arg_inout_type.v:134:33 - extern void i_int_t(int* x); - // DPI import at t/t_dpi_arg_inout_type.v:111:33 - extern void i_int_unsigned(unsigned int* x); - // DPI import at t/t_dpi_arg_inout_type.v:135:33 - extern void i_int_unsigned_t(unsigned int* x); - // DPI import at t/t_dpi_arg_inout_type.v:118:33 - extern void i_integer(svLogicVecVal* x); - // DPI import at t/t_dpi_arg_inout_type.v:142:33 - extern void i_integer_t(svLogicVecVal* x); - // DPI import at t/t_dpi_arg_inout_type.v:127:33 - extern void i_logic(svLogic* x); - // DPI import at t/t_dpi_arg_inout_type.v:151:33 - extern void i_logic_t(svLogic* x); - // DPI import at t/t_dpi_arg_inout_type.v:112:33 - extern void i_longint(long long* x); - // DPI import at t/t_dpi_arg_inout_type.v:136:33 - extern void i_longint_t(long long* x); - // DPI import at t/t_dpi_arg_inout_type.v:113:33 - extern void i_longint_unsigned(unsigned long long* x); - // DPI import at t/t_dpi_arg_inout_type.v:137:33 - extern void i_longint_unsigned_t(unsigned long long* x); - // DPI import at t/t_dpi_arg_inout_type.v:120:33 - extern void i_real(double* x); - // DPI import at t/t_dpi_arg_inout_type.v:144:33 - extern void i_real_t(double* x); - // DPI import at t/t_dpi_arg_inout_type.v:108:33 - extern void i_shortint(short* x); - // DPI import at t/t_dpi_arg_inout_type.v:132:33 - extern void i_shortint_t(short* x); - // DPI import at t/t_dpi_arg_inout_type.v:109:33 - extern void i_shortint_unsigned(unsigned short* x); - // DPI import at t/t_dpi_arg_inout_type.v:133:33 - extern void i_shortint_unsigned_t(unsigned short* x); - // DPI import at t/t_dpi_arg_inout_type.v:125:33 - extern void i_string(const char** x); - // DPI import at t/t_dpi_arg_inout_type.v:149:33 - extern void i_string_t(const char** x); - // DPI import at t/t_dpi_arg_inout_type.v:162:33 - extern void i_struct_2_state_1(svBitVecVal* x); - // DPI import at t/t_dpi_arg_inout_type.v:167:33 - extern void i_struct_2_state_128(svBitVecVal* x); - // DPI import at t/t_dpi_arg_inout_type.v:163:33 - extern void i_struct_2_state_32(svBitVecVal* x); - // DPI import at t/t_dpi_arg_inout_type.v:164:33 - extern void i_struct_2_state_33(svBitVecVal* x); - // DPI import at t/t_dpi_arg_inout_type.v:165:33 - extern void i_struct_2_state_64(svBitVecVal* x); - // DPI import at t/t_dpi_arg_inout_type.v:166:33 - extern void i_struct_2_state_65(svBitVecVal* x); - // DPI import at t/t_dpi_arg_inout_type.v:186:33 - extern void i_struct_4_state_1(svLogicVecVal* x); - // DPI import at t/t_dpi_arg_inout_type.v:191:33 - extern void i_struct_4_state_128(svLogicVecVal* x); - // DPI import at t/t_dpi_arg_inout_type.v:187:33 - extern void i_struct_4_state_32(svLogicVecVal* x); - // DPI import at t/t_dpi_arg_inout_type.v:188:33 - extern void i_struct_4_state_33(svLogicVecVal* x); - // DPI import at t/t_dpi_arg_inout_type.v:189:33 - extern void i_struct_4_state_64(svLogicVecVal* x); - // DPI import at t/t_dpi_arg_inout_type.v:190:33 - extern void i_struct_4_state_65(svLogicVecVal* x); - // DPI import at t/t_dpi_arg_inout_type.v:115:33 - extern void i_time(svLogicVecVal* x); - // DPI import at t/t_dpi_arg_inout_type.v:139:33 - extern void i_time_t(svLogicVecVal* x); - // DPI import at t/t_dpi_arg_inout_type.v:170:33 - extern void i_union_2_state_1(svBitVecVal* x); - // DPI import at t/t_dpi_arg_inout_type.v:175:33 - extern void i_union_2_state_128(svBitVecVal* x); - // DPI import at t/t_dpi_arg_inout_type.v:171:33 - extern void i_union_2_state_32(svBitVecVal* x); - // DPI import at t/t_dpi_arg_inout_type.v:172:33 - extern void i_union_2_state_33(svBitVecVal* x); - // DPI import at t/t_dpi_arg_inout_type.v:173:33 - extern void i_union_2_state_64(svBitVecVal* x); - // DPI import at t/t_dpi_arg_inout_type.v:174:33 - extern void i_union_2_state_65(svBitVecVal* x); - // DPI import at t/t_dpi_arg_inout_type.v:194:33 - extern void i_union_4_state_1(svLogicVecVal* x); - // DPI import at t/t_dpi_arg_inout_type.v:199:33 - extern void i_union_4_state_128(svLogicVecVal* x); - // DPI import at t/t_dpi_arg_inout_type.v:195:33 - extern void i_union_4_state_32(svLogicVecVal* x); - // DPI import at t/t_dpi_arg_inout_type.v:196:33 - extern void i_union_4_state_33(svLogicVecVal* x); - // DPI import at t/t_dpi_arg_inout_type.v:197:33 - extern void i_union_4_state_64(svLogicVecVal* x); - // DPI import at t/t_dpi_arg_inout_type.v:198:33 - extern void i_union_4_state_65(svLogicVecVal* x); - + + + // DPI EXPORTS + extern void e_array_2_state_1(svBitVecVal* x); + extern void e_array_2_state_128(svBitVecVal* x); + extern void e_array_2_state_32(svBitVecVal* x); + extern void e_array_2_state_33(svBitVecVal* x); + extern void e_array_2_state_64(svBitVecVal* x); + extern void e_array_2_state_65(svBitVecVal* x); + extern void e_array_4_state_1(svLogicVecVal* x); + extern void e_array_4_state_128(svLogicVecVal* x); + extern void e_array_4_state_32(svLogicVecVal* x); + extern void e_array_4_state_33(svLogicVecVal* x); + extern void e_array_4_state_64(svLogicVecVal* x); + extern void e_array_4_state_65(svLogicVecVal* x); + extern void e_bit(svBit* x); + extern void e_bit_t(svBit* x); + extern void e_byte(char* x); + extern void e_byte_t(char* x); + extern void e_byte_unsigned(unsigned char* x); + extern void e_byte_unsigned_t(unsigned char* x); + extern void e_chandle(void** x); + extern void e_chandle_t(void** x); + extern void e_int(int* x); + extern void e_int_t(int* x); + extern void e_int_unsigned(unsigned int* x); + extern void e_int_unsigned_t(unsigned int* x); + extern void e_integer(svLogicVecVal* x); + extern void e_integer_t(svLogicVecVal* x); + extern void e_logic(svLogic* x); + extern void e_logic_t(svLogic* x); + extern void e_longint(long long* x); + extern void e_longint_t(long long* x); + extern void e_longint_unsigned(unsigned long long* x); + extern void e_longint_unsigned_t(unsigned long long* x); + extern void e_real(double* x); + extern void e_real_t(double* x); + extern void e_shortint(short* x); + extern void e_shortint_t(short* x); + extern void e_shortint_unsigned(unsigned short* x); + extern void e_shortint_unsigned_t(unsigned short* x); + extern void e_string(const char** x); + extern void e_string_t(const char** x); + extern void e_struct_2_state_1(svBitVecVal* x); + extern void e_struct_2_state_128(svBitVecVal* x); + extern void e_struct_2_state_32(svBitVecVal* x); + extern void e_struct_2_state_33(svBitVecVal* x); + extern void e_struct_2_state_64(svBitVecVal* x); + extern void e_struct_2_state_65(svBitVecVal* x); + extern void e_struct_4_state_1(svLogicVecVal* x); + extern void e_struct_4_state_128(svLogicVecVal* x); + extern void e_struct_4_state_32(svLogicVecVal* x); + extern void e_struct_4_state_33(svLogicVecVal* x); + extern void e_struct_4_state_64(svLogicVecVal* x); + extern void e_struct_4_state_65(svLogicVecVal* x); + extern void e_time(svLogicVecVal* x); + extern void e_time_t(svLogicVecVal* x); + extern void e_union_2_state_1(svBitVecVal* x); + extern void e_union_2_state_128(svBitVecVal* x); + extern void e_union_2_state_32(svBitVecVal* x); + extern void e_union_2_state_33(svBitVecVal* x); + extern void e_union_2_state_64(svBitVecVal* x); + extern void e_union_2_state_65(svBitVecVal* x); + extern void e_union_4_state_1(svLogicVecVal* x); + extern void e_union_4_state_128(svLogicVecVal* x); + extern void e_union_4_state_32(svLogicVecVal* x); + extern void e_union_4_state_33(svLogicVecVal* x); + extern void e_union_4_state_64(svLogicVecVal* x); + extern void e_union_4_state_65(svLogicVecVal* x); + + // DPI IMPORTS + extern void check_exports(); + extern void i_array_2_state_1(svBitVecVal* x); + extern void i_array_2_state_128(svBitVecVal* x); + extern void i_array_2_state_32(svBitVecVal* x); + extern void i_array_2_state_33(svBitVecVal* x); + extern void i_array_2_state_64(svBitVecVal* x); + extern void i_array_2_state_65(svBitVecVal* x); + extern void i_array_4_state_1(svLogicVecVal* x); + extern void i_array_4_state_128(svLogicVecVal* x); + extern void i_array_4_state_32(svLogicVecVal* x); + extern void i_array_4_state_33(svLogicVecVal* x); + extern void i_array_4_state_64(svLogicVecVal* x); + extern void i_array_4_state_65(svLogicVecVal* x); + extern void i_bit(svBit* x); + extern void i_bit_t(svBit* x); + extern void i_byte(char* x); + extern void i_byte_t(char* x); + extern void i_byte_unsigned(unsigned char* x); + extern void i_byte_unsigned_t(unsigned char* x); + extern void i_chandle(void** x); + extern void i_chandle_t(void** x); + extern void i_int(int* x); + extern void i_int_t(int* x); + extern void i_int_unsigned(unsigned int* x); + extern void i_int_unsigned_t(unsigned int* x); + extern void i_integer(svLogicVecVal* x); + extern void i_integer_t(svLogicVecVal* x); + extern void i_logic(svLogic* x); + extern void i_logic_t(svLogic* x); + extern void i_longint(long long* x); + extern void i_longint_t(long long* x); + extern void i_longint_unsigned(unsigned long long* x); + extern void i_longint_unsigned_t(unsigned long long* x); + extern void i_real(double* x); + extern void i_real_t(double* x); + extern void i_shortint(short* x); + extern void i_shortint_t(short* x); + extern void i_shortint_unsigned(unsigned short* x); + extern void i_shortint_unsigned_t(unsigned short* x); + extern void i_string(const char** x); + extern void i_string_t(const char** x); + extern void i_struct_2_state_1(svBitVecVal* x); + extern void i_struct_2_state_128(svBitVecVal* x); + extern void i_struct_2_state_32(svBitVecVal* x); + extern void i_struct_2_state_33(svBitVecVal* x); + extern void i_struct_2_state_64(svBitVecVal* x); + extern void i_struct_2_state_65(svBitVecVal* x); + extern void i_struct_4_state_1(svLogicVecVal* x); + extern void i_struct_4_state_128(svLogicVecVal* x); + extern void i_struct_4_state_32(svLogicVecVal* x); + extern void i_struct_4_state_33(svLogicVecVal* x); + extern void i_struct_4_state_64(svLogicVecVal* x); + extern void i_struct_4_state_65(svLogicVecVal* x); + extern void i_time(svLogicVecVal* x); + extern void i_time_t(svLogicVecVal* x); + extern void i_union_2_state_1(svBitVecVal* x); + extern void i_union_2_state_128(svBitVecVal* x); + extern void i_union_2_state_32(svBitVecVal* x); + extern void i_union_2_state_33(svBitVecVal* x); + extern void i_union_2_state_64(svBitVecVal* x); + extern void i_union_2_state_65(svBitVecVal* x); + extern void i_union_4_state_1(svLogicVecVal* x); + extern void i_union_4_state_128(svLogicVecVal* x); + extern void i_union_4_state_32(svLogicVecVal* x); + extern void i_union_4_state_33(svLogicVecVal* x); + extern void i_union_4_state_64(svLogicVecVal* x); + extern void i_union_4_state_65(svLogicVecVal* x); + #ifdef __cplusplus } #endif diff --git a/test_regress/t/t_dpi_arg_inout_unpack.cpp b/test_regress/t/t_dpi_arg_inout_unpack.cpp index 9b029bfbd..3e0b62d80 100644 --- a/test_regress/t/t_dpi_arg_inout_unpack.cpp +++ b/test_regress/t/t_dpi_arg_inout_unpack.cpp @@ -99,6 +99,17 @@ template bool compare(const T& act, const T& exp) { } } +bool compare_scalar(const svScalar v0, sv_longint_unsigned_t val) { + const bool act_bit = v0 == sv_1; + const bool exp_bit = val & 1; + if (act_bit != exp_bit) { + std::cout << "Mismatch at bit:" << 0 << " exp:" << exp_bit << " act:" << act_bit; + return false; + } + if (VERBOSE_MESSAGE) { std::cout << "OK " << val << " as expected " << std::endl; } + return true; +} + bool compare(const svLogicVecVal* v0, sv_longint_unsigned_t val, int bitwidth) { for (int i = 0; i < bitwidth; ++i) { const bool act_bit = svGetBitselLogic(v0, i); @@ -165,6 +176,39 @@ template bool update_3d(T* v) { return true; } +bool update_0d_scalar(svScalar* v) { + if (!compare_scalar(v[0], sv_0)) return false; + v[0] = sv_1; + return true; +} +bool update_1d_scalar(svScalar* v) { + if (!compare_scalar(v[0], sv_1)) return false; + v[0] = sv_0; + if (!compare_scalar(v[1], sv_0)) return false; + v[1] = sv_1; + return true; +} +bool update_2d_scalar(svScalar* v) { + if (!compare_scalar(v[(0 * 2) + 1], sv_1)) return false; + v[(0 * 2) + 1] = sv_0; + if (!compare_scalar(v[(1 * 2) + 1], sv_0)) return false; + v[(1 * 2) + 1] = sv_1; + if (!compare_scalar(v[(2 * 2) + 1], sv_1)) return false; + v[(2 * 2) + 1] = sv_0; + return true; +} +bool update_3d_scalar(svScalar* v) { + if (!compare_scalar(v[((0 * 3) + 0) * 2 + 0], sv_0)) return false; + v[(0 * 3 + 0) * 2 + 0] = sv_1; + if (!compare_scalar(v[((1 * 3) + 0) * 2 + 0], sv_1)) return false; + v[(1 * 3 + 0) * 2 + 0] = sv_0; + if (!compare_scalar(v[((2 * 3) + 0) * 2 + 0], sv_0)) return false; + v[(2 * 3 + 0) * 2 + 0] = sv_1; + if (!compare_scalar(v[((3 * 3) + 0) * 2 + 0], sv_1)) return false; + v[(3 * 3 + 0) * 2 + 0] = sv_0; + return true; +} + template bool update_0d(T* v, int bitwidth) { if (!compare(v, 42, bitwidth)) return false; set_uint(v, 43, bitwidth); @@ -481,6 +525,11 @@ void i_string_3d(const char** v) { v[(3 * 3 + 0) * 2 + 0] = s3; } +void i_bit1_0d(svBit* v) { update_0d_scalar(v); } +void i_bit1_1d(svBit* v) { update_1d_scalar(v); } +void i_bit1_2d(svBit* v) { update_2d_scalar(v); } +void i_bit1_3d(svBit* v) { update_3d_scalar(v); } + void i_bit7_0d(svBitVecVal* v) { update_0d(v, 7); } void i_bit7_1d(svBitVecVal* v) { update_1d(v, 7); } void i_bit7_2d(svBitVecVal* v) { update_2d(v, 7); } @@ -491,6 +540,11 @@ void i_bit121_1d(svBitVecVal* v) { update_1d(v, 121); } void i_bit121_2d(svBitVecVal* v) { update_2d(v, 121); } void i_bit121_3d(svBitVecVal* v) { update_3d(v, 121); } +void i_logic1_0d(svLogic* v) { update_0d_scalar(v); } +void i_logic1_1d(svLogic* v) { update_1d_scalar(v); } +void i_logic1_2d(svLogic* v) { update_2d_scalar(v); } +void i_logic1_3d(svLogic* v) { update_3d_scalar(v); } + void i_logic7_0d(svLogicVecVal* v) { update_0d(v, 7); } void i_logic7_1d(svLogicVecVal* v) { update_1d(v, 7); } void i_logic7_2d(svLogicVecVal* v) { update_2d(v, 7); } diff --git a/test_regress/t/t_dpi_arg_inout_unpack.pl b/test_regress/t/t_dpi_arg_inout_unpack.pl index 59dfe0252..b46d023f8 100755 --- a/test_regress/t/t_dpi_arg_inout_unpack.pl +++ b/test_regress/t/t_dpi_arg_inout_unpack.pl @@ -20,7 +20,8 @@ if ($Self->{nc}) { compile( v_flags2 => ["t/t_dpi_arg_inout_unpack.cpp"], - verilator_flags2 => ["-Wall -Wno-DECLFILENAME"], + # --no-decoration so .out file doesn't comment on source lines + verilator_flags2 => ["-Wall -Wno-DECLFILENAME --no-decoration"], # NC: Gdd the obj_dir to the C include path nc_flags2 => ["+ncscargs+-I$Self->{obj_dir}"], # ModelSim: Generate DPI header, add obj_dir to the C include path diff --git a/test_regress/t/t_dpi_arg_inout_unpack.v b/test_regress/t/t_dpi_arg_inout_unpack.v index a37a24cc2..9306f90f4 100644 --- a/test_regress/t/t_dpi_arg_inout_unpack.v +++ b/test_regress/t/t_dpi_arg_inout_unpack.v @@ -17,6 +17,7 @@ `endif `ifdef MS + `define NO_BITS_TO_SCALAR `endif `ifdef VERILATOR @@ -24,10 +25,15 @@ `define NO_UNPACK_STRUCT //%Error-TASKNSVAR: Unsupported: Function/task input argument is not simple variable `define NO_INOUT_COMPLEX_TYPE -`else `endif -`define CHECK_VAL(act, exp) if ((act) == (exp)) begin \ +`ifdef NO_BITS_TO_SCALAR + `define ARE_SAME(act, exp) ($bits((act)) == 1 ? (act) == ((exp) & 1) : (act) == (exp)) +`else + `define ARE_SAME(act, exp) ((act) == (($bits(act))'(exp))) +`endif + +`define CHECK_VAL(act, exp) if (`ARE_SAME(act, exp)) begin \ if (ENABLE_VERBOSE_MESSAGE)$display(`"act`", ":", (act), " as expected"); \ end else begin \ $display("Mismatch %s expected:%d actual:%d at %d", `"act`", int'(exp), int'(act), `__LINE__); \ @@ -90,14 +96,25 @@ `CHECK_DOUBLE_VAL(val[2][0][0], 51.0); \ `CHECK_DOUBLE_VAL(val[3][0][0], 52.0) -`define SET_VALUE_0D(val) val = 42 -`define SET_VALUE_1D(val) val[0] = 43; val[1] = 44 -`define SET_VALUE_2D(val) val[0][1] = 45; val[1][1] = 46; val[2][1] = 47 +`define SET_VALUE_0D(val) \ +/*verilator lint_off WIDTH */ \ +val = 42 +/*verilator lint_on WIDTH */ +`define SET_VALUE_1D(val) \ +/*verilator lint_off WIDTH */ \ +val[0] = 43; val[1] = 44 \ +/*verilator lint_on WIDTH */ +`define SET_VALUE_2D(val) \ +/*verilator lint_off WIDTH */ \ +val[0][1] = 45; val[1][1] = 46; val[2][1] = 47 \ +/*verilator lint_on WIDTH */ `define SET_VALUES(val) \ +/*verilator lint_off WIDTH */ \ val[3][2][1] = 42; \ val[2][1][0] = 43; val[2][1][1] = 44; \ val[1][0][1] = 45; val[1][1][1] = 46; val[1][2][1] = 47; \ -val[0][0][0] = 48; val[1][0][0] = 49; val[2][0][0] = 50; val[3][0][0] = 51 +val[0][0][0] = 48; val[1][0][0] = 49; val[2][0][0] = 50; val[3][0][0] = 51 \ +/*verilator lint_on WIDTH */ module t; @@ -143,10 +160,14 @@ module t; typedef chandle_t chandle_array_t[4][3][2]; typedef string string_t; typedef string_t string_array_t[4][3][2]; + typedef bit bit1_t; + typedef bit1_t bit1_array_t[4][3][2]; typedef bit [6:0] bit7_t; typedef bit7_t bit7_array_t[4][3][2]; typedef bit [120:0] bit121_t; typedef bit121_t bit121_array_t[4][3][2]; + typedef logic logic1_t; + typedef logic1_t logic1_array_t[4][3][2]; typedef logic [6:0] logic7_t; typedef logic7_t logic7_array_t[4][3][2]; typedef logic [120:0] logic121_t; @@ -246,6 +267,11 @@ module t; import "DPI-C" function void i_string_2d(inout string val[3][2]); import "DPI-C" function void i_string_3d(inout string_array_t val); + import "DPI-C" function void i_bit1_0d(inout bit val); + import "DPI-C" function void i_bit1_1d(inout bit val[2]); + import "DPI-C" function void i_bit1_2d(inout bit val[3][2]); + import "DPI-C" function void i_bit1_3d(inout bit1_array_t val); + import "DPI-C" function void i_bit7_0d(inout bit[6:0] val); import "DPI-C" function void i_bit7_1d(inout bit[6:0] val[2]); import "DPI-C" function void i_bit7_2d(inout bit[6:0] val[3][2]); @@ -256,6 +282,11 @@ module t; import "DPI-C" function void i_bit121_2d(inout bit[120:0] val[3][2]); import "DPI-C" function void i_bit121_3d(inout bit121_array_t val); + import "DPI-C" function void i_logic1_0d(inout logic val); + import "DPI-C" function void i_logic1_1d(inout logic val[2]); + import "DPI-C" function void i_logic1_2d(inout logic val[3][2]); + import "DPI-C" function void i_logic1_3d(inout logic1_array_t val); + import "DPI-C" function void i_logic7_0d(inout logic[6:0] val); import "DPI-C" function void i_logic7_1d(inout logic[6:0] val[2]); import "DPI-C" function void i_logic7_2d(inout logic[6:0] val[3][2]); @@ -357,6 +388,11 @@ module t; export "DPI-C" function e_string_2d; export "DPI-C" function e_string_3d; + export "DPI-C" function e_bit1_0d; + export "DPI-C" function e_bit1_1d; + export "DPI-C" function e_bit1_2d; + export "DPI-C" function e_bit1_3d; + export "DPI-C" function e_bit7_0d; export "DPI-C" function e_bit7_1d; export "DPI-C" function e_bit7_2d; @@ -367,6 +403,11 @@ module t; export "DPI-C" function e_bit121_2d; export "DPI-C" function e_bit121_3d; + export "DPI-C" function e_logic1_0d; + export "DPI-C" function e_logic1_1d; + export "DPI-C" function e_logic1_2d; + export "DPI-C" function e_logic1_3d; + export "DPI-C" function e_logic7_0d; export "DPI-C" function e_logic7_1d; export "DPI-C" function e_logic7_2d; @@ -521,6 +562,11 @@ module t; val[3][0][0] = "52"; endfunction + function void e_bit1_0d(inout bit val); `UPDATE_0D(val); endfunction + function void e_bit1_1d(inout bit val[2]); `UPDATE_1D(val); endfunction + function void e_bit1_2d(inout bit val[3][2]); `UPDATE_2D(val); endfunction + function void e_bit1_3d(inout bit1_array_t val); `UPDATE_3D(val); endfunction + function void e_bit7_0d(inout bit[6:0] val); `UPDATE_0D(val); endfunction function void e_bit7_1d(inout bit[6:0] val[2]); `UPDATE_1D(val); endfunction function void e_bit7_2d(inout bit[6:0] val[3][2]); `UPDATE_2D(val); endfunction @@ -531,6 +577,11 @@ module t; function void e_bit121_2d(inout bit[120:0] val[3][2]); `UPDATE_2D(val); endfunction function void e_bit121_3d(inout bit121_array_t val); `UPDATE_3D(val); endfunction + function void e_logic1_0d(inout logic val); `UPDATE_0D(val); endfunction + function void e_logic1_1d(inout logic val[2]); `UPDATE_1D(val); endfunction + function void e_logic1_2d(inout logic val[3][2]); `UPDATE_2D(val); endfunction + function void e_logic1_3d(inout logic1_array_t val); `UPDATE_3D(val); endfunction + function void e_logic7_0d(inout logic[6:0] val); `UPDATE_0D(val); endfunction function void e_logic7_1d(inout logic[6:0] val[2]); `UPDATE_1D(val); endfunction function void e_logic7_2d(inout logic[6:0] val[3][2]); `UPDATE_2D(val); endfunction @@ -647,6 +698,11 @@ module t; string_t string_array_2d[3][2]; string_array_t string_array; + bit1_t bit1_array_0d; + bit1_t bit1_array_1d[2]; + bit1_t bit1_array_2d[3][2]; + bit1_array_t bit1_array; + bit7_t bit7_array_0d; bit7_t bit7_array_1d[2]; bit7_t bit7_array_2d[3][2]; @@ -657,6 +713,11 @@ module t; bit121_t bit121_array_2d[3][2]; bit121_array_t bit121_array; + logic1_t logic1_array_0d; + logic1_t logic1_array_1d[2]; + logic1_t logic1_array_2d[3][2]; + logic1_array_t logic1_array; + logic7_t logic7_array_0d; logic7_t logic7_array_1d[2]; logic7_t logic7_array_2d[3][2]; @@ -1019,6 +1080,27 @@ module t; `CHECK_STRING_VAL(string_array[2][0][0], "51"); `CHECK_STRING_VAL(string_array[3][0][0], "52"); + `SET_VALUES(bit1_array); + `SET_VALUE_0D(bit1_array_0d); + `SET_VALUE_1D(bit1_array_1d); + `SET_VALUE_2D(bit1_array_2d); +`ifndef NO_INOUT_COMPLEX_TYPE + i_bit1_0d(bit1_array[3][2][1]); + `CHECK_0D(bit1_array[3][2][1]); + i_bit1_1d(bit1_array[2][1]); + `CHECK_1D(bit1_array[2][1]); + i_bit1_2d(bit1_array[1]); + `CHECK_2D(bit1_array[1]); +`endif + i_bit1_0d(bit1_array_0d); + `CHECK_0D(bit1_array_0d); + i_bit1_1d(bit1_array_1d); + `CHECK_1D(bit1_array_1d); + i_bit1_2d(bit1_array_2d); + `CHECK_2D(bit1_array_2d); + i_bit1_3d(bit1_array); + `CHECK_3D(bit1_array); + `SET_VALUES(bit7_array); `SET_VALUE_0D(bit7_array_0d); `SET_VALUE_1D(bit7_array_1d); @@ -1061,6 +1143,27 @@ module t; i_bit121_3d(bit121_array); `CHECK_3D(bit121_array); + `SET_VALUES(logic1_array); + `SET_VALUE_0D(logic1_array_0d); + `SET_VALUE_1D(logic1_array_1d); + `SET_VALUE_2D(logic1_array_2d); +`ifndef NO_INOUT_COMPLEX_TYPE + i_logic1_0d(logic1_array[3][2][1]); + `CHECK_0D(logic1_array[3][2][1]); + i_logic1_1d(logic1_array[2][1]); + `CHECK_1D(logic1_array[2][1]); + i_logic1_2d(logic1_array[1]); + `CHECK_2D(logic1_array[1]); +`endif + i_logic1_0d(logic1_array_0d); + `CHECK_0D(logic1_array_0d); + i_logic1_1d(logic1_array_1d); + `CHECK_1D(logic1_array_1d); + i_logic1_2d(logic1_array_2d); + `CHECK_2D(logic1_array_2d); + i_logic1_3d(logic1_array); + `CHECK_3D(logic1_array); + `SET_VALUES(logic7_array); `SET_VALUE_0D(logic7_array_0d); `SET_VALUE_1D(logic7_array_1d); diff --git a/test_regress/t/t_dpi_arg_inout_unpack__Dpi.out b/test_regress/t/t_dpi_arg_inout_unpack__Dpi.out index c525fa429..918872073 100644 --- a/test_regress/t/t_dpi_arg_inout_unpack__Dpi.out +++ b/test_regress/t/t_dpi_arg_inout_unpack__Dpi.out @@ -10,304 +10,174 @@ #ifdef __cplusplus extern "C" { #endif - - - // DPI EXPORTS - // DPI export at t/t_dpi_arg_inout_unpack.v:529:18 - extern void e_bit121_0d(svBitVecVal* val); - // DPI export at t/t_dpi_arg_inout_unpack.v:530:18 - extern void e_bit121_1d(svBitVecVal* val); - // DPI export at t/t_dpi_arg_inout_unpack.v:531:18 - extern void e_bit121_2d(svBitVecVal* val); - // DPI export at t/t_dpi_arg_inout_unpack.v:532:18 - extern void e_bit121_3d(svBitVecVal* val); - // DPI export at t/t_dpi_arg_inout_unpack.v:524:18 - extern void e_bit7_0d(svBitVecVal* val); - // DPI export at t/t_dpi_arg_inout_unpack.v:525:18 - extern void e_bit7_1d(svBitVecVal* val); - // DPI export at t/t_dpi_arg_inout_unpack.v:526:18 - extern void e_bit7_2d(svBitVecVal* val); - // DPI export at t/t_dpi_arg_inout_unpack.v:527:18 - extern void e_bit7_3d(svBitVecVal* val); - // DPI export at t/t_dpi_arg_inout_unpack.v:395:18 - extern void e_byte_0d(char* val); - // DPI export at t/t_dpi_arg_inout_unpack.v:396:18 - extern void e_byte_1d(char* val); - // DPI export at t/t_dpi_arg_inout_unpack.v:397:18 - extern void e_byte_2d(char* val); - // DPI export at t/t_dpi_arg_inout_unpack.v:398:18 - extern void e_byte_3d(char* val); - // DPI export at t/t_dpi_arg_inout_unpack.v:400:18 - extern void e_byte_unsigned_0d(unsigned char* val); - // DPI export at t/t_dpi_arg_inout_unpack.v:401:18 - extern void e_byte_unsigned_1d(unsigned char* val); - // DPI export at t/t_dpi_arg_inout_unpack.v:402:18 - extern void e_byte_unsigned_2d(unsigned char* val); - // DPI export at t/t_dpi_arg_inout_unpack.v:403:18 - extern void e_byte_unsigned_3d(unsigned char* val); - // DPI export at t/t_dpi_arg_inout_unpack.v:465:18 - extern void e_chandle_0d(void** val); - // DPI export at t/t_dpi_arg_inout_unpack.v:469:18 - extern void e_chandle_1d(void** val); - // DPI export at t/t_dpi_arg_inout_unpack.v:475:18 - extern void e_chandle_2d(void** val); - // DPI export at t/t_dpi_arg_inout_unpack.v:483:18 - extern void e_chandle_3d(void** val); - // DPI export at t/t_dpi_arg_inout_unpack.v:416:18 - extern void e_int_0d(int* val); - // DPI export at t/t_dpi_arg_inout_unpack.v:417:18 - extern void e_int_1d(int* val); - // DPI export at t/t_dpi_arg_inout_unpack.v:418:18 - extern void e_int_2d(int* val); - // DPI export at t/t_dpi_arg_inout_unpack.v:419:18 - extern void e_int_3d(int* val); - // DPI export at t/t_dpi_arg_inout_unpack.v:421:18 - extern void e_int_unsigned_0d(unsigned int* val); - // DPI export at t/t_dpi_arg_inout_unpack.v:422:18 - extern void e_int_unsigned_1d(unsigned int* val); - // DPI export at t/t_dpi_arg_inout_unpack.v:423:18 - extern void e_int_unsigned_2d(unsigned int* val); - // DPI export at t/t_dpi_arg_inout_unpack.v:424:18 - extern void e_int_unsigned_3d(unsigned int* val); - // DPI export at t/t_dpi_arg_inout_unpack.v:446:18 - extern void e_integer_0d(svLogicVecVal* val); - // DPI export at t/t_dpi_arg_inout_unpack.v:447:18 - extern void e_integer_1d(svLogicVecVal* val); - // DPI export at t/t_dpi_arg_inout_unpack.v:448:18 - extern void e_integer_2d(svLogicVecVal* val); - // DPI export at t/t_dpi_arg_inout_unpack.v:449:18 - extern void e_integer_3d(svLogicVecVal* val); - // DPI export at t/t_dpi_arg_inout_unpack.v:539:18 - extern void e_logic121_0d(svLogicVecVal* val); - // DPI export at t/t_dpi_arg_inout_unpack.v:540:18 - extern void e_logic121_1d(svLogicVecVal* val); - // DPI export at t/t_dpi_arg_inout_unpack.v:541:18 - extern void e_logic121_2d(svLogicVecVal* val); - // DPI export at t/t_dpi_arg_inout_unpack.v:542:18 - extern void e_logic121_3d(svLogicVecVal* val); - // DPI export at t/t_dpi_arg_inout_unpack.v:534:18 - extern void e_logic7_0d(svLogicVecVal* val); - // DPI export at t/t_dpi_arg_inout_unpack.v:535:18 - extern void e_logic7_1d(svLogicVecVal* val); - // DPI export at t/t_dpi_arg_inout_unpack.v:536:18 - extern void e_logic7_2d(svLogicVecVal* val); - // DPI export at t/t_dpi_arg_inout_unpack.v:537:18 - extern void e_logic7_3d(svLogicVecVal* val); - // DPI export at t/t_dpi_arg_inout_unpack.v:428:18 - extern void e_longint_0d(long long* val); - // DPI export at t/t_dpi_arg_inout_unpack.v:429:18 - extern void e_longint_1d(long long* val); - // DPI export at t/t_dpi_arg_inout_unpack.v:430:18 - extern void e_longint_2d(long long* val); - // DPI export at t/t_dpi_arg_inout_unpack.v:431:18 - extern void e_longint_3d(long long* val); - // DPI export at t/t_dpi_arg_inout_unpack.v:433:18 - extern void e_longint_unsigned_0d(unsigned long long* val); - // DPI export at t/t_dpi_arg_inout_unpack.v:434:18 - extern void e_longint_unsigned_1d(unsigned long long* val); - // DPI export at t/t_dpi_arg_inout_unpack.v:435:18 - extern void e_longint_unsigned_2d(unsigned long long* val); - // DPI export at t/t_dpi_arg_inout_unpack.v:436:18 - extern void e_longint_unsigned_3d(unsigned long long* val); - // DPI export at t/t_dpi_arg_inout_unpack.v:544:18 - extern void e_pack_struct_0d(svLogicVecVal* val); - // DPI export at t/t_dpi_arg_inout_unpack.v:545:18 - extern void e_pack_struct_1d(svLogicVecVal* val); - // DPI export at t/t_dpi_arg_inout_unpack.v:546:18 - extern void e_pack_struct_2d(svLogicVecVal* val); - // DPI export at t/t_dpi_arg_inout_unpack.v:547:18 - extern void e_pack_struct_3d(svLogicVecVal* val); - // DPI export at t/t_dpi_arg_inout_unpack.v:452:18 - extern void e_real_0d(double* val); - // DPI export at t/t_dpi_arg_inout_unpack.v:453:18 - extern void e_real_1d(double* val); - // DPI export at t/t_dpi_arg_inout_unpack.v:454:18 - extern void e_real_2d(double* val); - // DPI export at t/t_dpi_arg_inout_unpack.v:455:18 - extern void e_real_3d(double* val); - // DPI export at t/t_dpi_arg_inout_unpack.v:405:18 - extern void e_shortint_0d(short* val); - // DPI export at t/t_dpi_arg_inout_unpack.v:406:18 - extern void e_shortint_1d(short* val); - // DPI export at t/t_dpi_arg_inout_unpack.v:407:18 - extern void e_shortint_2d(short* val); - // DPI export at t/t_dpi_arg_inout_unpack.v:408:18 - extern void e_shortint_3d(short* val); - // DPI export at t/t_dpi_arg_inout_unpack.v:410:18 - extern void e_shortint_unsigned_0d(unsigned short* val); - // DPI export at t/t_dpi_arg_inout_unpack.v:411:18 - extern void e_shortint_unsigned_1d(unsigned short* val); - // DPI export at t/t_dpi_arg_inout_unpack.v:412:18 - extern void e_shortint_unsigned_2d(unsigned short* val); - // DPI export at t/t_dpi_arg_inout_unpack.v:413:18 - extern void e_shortint_unsigned_3d(unsigned short* val); - // DPI export at t/t_dpi_arg_inout_unpack.v:495:18 - extern void e_string_0d(const char** val); - // DPI export at t/t_dpi_arg_inout_unpack.v:499:18 - extern void e_string_1d(const char** val); - // DPI export at t/t_dpi_arg_inout_unpack.v:505:18 - extern void e_string_2d(const char** val); - // DPI export at t/t_dpi_arg_inout_unpack.v:513:18 - extern void e_string_3d(const char** val); - // DPI export at t/t_dpi_arg_inout_unpack.v:439:18 - extern void e_time_0d(svLogicVecVal* val); - // DPI export at t/t_dpi_arg_inout_unpack.v:440:18 - extern void e_time_1d(svLogicVecVal* val); - // DPI export at t/t_dpi_arg_inout_unpack.v:441:18 - extern void e_time_2d(svLogicVecVal* val); - // DPI export at t/t_dpi_arg_inout_unpack.v:442:18 - extern void e_time_3d(svLogicVecVal* val); - - // DPI IMPORTS - // DPI import at t/t_dpi_arg_inout_unpack.v:584:41 - extern void check_exports(); - // DPI import at t/t_dpi_arg_inout_unpack.v:171:36 - extern void* get_non_null(); - // DPI import at t/t_dpi_arg_inout_unpack.v:254:33 - extern void i_bit121_0d(svBitVecVal* val); - // DPI import at t/t_dpi_arg_inout_unpack.v:255:33 - extern void i_bit121_1d(svBitVecVal* val); - // DPI import at t/t_dpi_arg_inout_unpack.v:256:33 - extern void i_bit121_2d(svBitVecVal* val); - // DPI import at t/t_dpi_arg_inout_unpack.v:257:33 - extern void i_bit121_3d(svBitVecVal* val); - // DPI import at t/t_dpi_arg_inout_unpack.v:249:33 - extern void i_bit7_0d(svBitVecVal* val); - // DPI import at t/t_dpi_arg_inout_unpack.v:250:33 - extern void i_bit7_1d(svBitVecVal* val); - // DPI import at t/t_dpi_arg_inout_unpack.v:251:33 - extern void i_bit7_2d(svBitVecVal* val); - // DPI import at t/t_dpi_arg_inout_unpack.v:252:33 - extern void i_bit7_3d(svBitVecVal* val); - // DPI import at t/t_dpi_arg_inout_unpack.v:173:33 - extern void i_byte_0d(char* val); - // DPI import at t/t_dpi_arg_inout_unpack.v:174:33 - extern void i_byte_1d(char* val); - // DPI import at t/t_dpi_arg_inout_unpack.v:175:33 - extern void i_byte_2d(char* val); - // DPI import at t/t_dpi_arg_inout_unpack.v:176:33 - extern void i_byte_3d(char* val); - // DPI import at t/t_dpi_arg_inout_unpack.v:178:33 - extern void i_byte_unsigned_0d(unsigned char* val); - // DPI import at t/t_dpi_arg_inout_unpack.v:179:33 - extern void i_byte_unsigned_1d(unsigned char* val); - // DPI import at t/t_dpi_arg_inout_unpack.v:180:33 - extern void i_byte_unsigned_2d(unsigned char* val); - // DPI import at t/t_dpi_arg_inout_unpack.v:181:33 - extern void i_byte_unsigned_3d(unsigned char* val); - // DPI import at t/t_dpi_arg_inout_unpack.v:239:33 - extern void i_chandle_0d(void** val); - // DPI import at t/t_dpi_arg_inout_unpack.v:240:33 - extern void i_chandle_1d(void** val); - // DPI import at t/t_dpi_arg_inout_unpack.v:241:33 - extern void i_chandle_2d(void** val); - // DPI import at t/t_dpi_arg_inout_unpack.v:242:33 - extern void i_chandle_3d(void** val); - // DPI import at t/t_dpi_arg_inout_unpack.v:193:33 - extern void i_int_0d(int* val); - // DPI import at t/t_dpi_arg_inout_unpack.v:194:33 - extern void i_int_1d(int* val); - // DPI import at t/t_dpi_arg_inout_unpack.v:195:33 - extern void i_int_2d(int* val); - // DPI import at t/t_dpi_arg_inout_unpack.v:196:33 - extern void i_int_3d(int* val); - // DPI import at t/t_dpi_arg_inout_unpack.v:198:33 - extern void i_int_unsigned_0d(unsigned int* val); - // DPI import at t/t_dpi_arg_inout_unpack.v:199:33 - extern void i_int_unsigned_1d(unsigned int* val); - // DPI import at t/t_dpi_arg_inout_unpack.v:200:33 - extern void i_int_unsigned_2d(unsigned int* val); - // DPI import at t/t_dpi_arg_inout_unpack.v:201:33 - extern void i_int_unsigned_3d(unsigned int* val); - // DPI import at t/t_dpi_arg_inout_unpack.v:221:33 - extern void i_integer_0d(svLogicVecVal* val); - // DPI import at t/t_dpi_arg_inout_unpack.v:222:33 - extern void i_integer_1d(svLogicVecVal* val); - // DPI import at t/t_dpi_arg_inout_unpack.v:223:33 - extern void i_integer_2d(svLogicVecVal* val); - // DPI import at t/t_dpi_arg_inout_unpack.v:224:33 - extern void i_integer_3d(svLogicVecVal* val); - // DPI import at t/t_dpi_arg_inout_unpack.v:264:33 - extern void i_logic121_0d(svLogicVecVal* val); - // DPI import at t/t_dpi_arg_inout_unpack.v:265:33 - extern void i_logic121_1d(svLogicVecVal* val); - // DPI import at t/t_dpi_arg_inout_unpack.v:266:33 - extern void i_logic121_2d(svLogicVecVal* val); - // DPI import at t/t_dpi_arg_inout_unpack.v:267:33 - extern void i_logic121_3d(svLogicVecVal* val); - // DPI import at t/t_dpi_arg_inout_unpack.v:259:33 - extern void i_logic7_0d(svLogicVecVal* val); - // DPI import at t/t_dpi_arg_inout_unpack.v:260:33 - extern void i_logic7_1d(svLogicVecVal* val); - // DPI import at t/t_dpi_arg_inout_unpack.v:261:33 - extern void i_logic7_2d(svLogicVecVal* val); - // DPI import at t/t_dpi_arg_inout_unpack.v:262:33 - extern void i_logic7_3d(svLogicVecVal* val); - // DPI import at t/t_dpi_arg_inout_unpack.v:203:33 - extern void i_longint_0d(long long* val); - // DPI import at t/t_dpi_arg_inout_unpack.v:204:33 - extern void i_longint_1d(long long* val); - // DPI import at t/t_dpi_arg_inout_unpack.v:205:33 - extern void i_longint_2d(long long* val); - // DPI import at t/t_dpi_arg_inout_unpack.v:206:33 - extern void i_longint_3d(long long* val); - // DPI import at t/t_dpi_arg_inout_unpack.v:208:33 - extern void i_longint_unsigned_0d(unsigned long long* val); - // DPI import at t/t_dpi_arg_inout_unpack.v:209:33 - extern void i_longint_unsigned_1d(unsigned long long* val); - // DPI import at t/t_dpi_arg_inout_unpack.v:210:33 - extern void i_longint_unsigned_2d(unsigned long long* val); - // DPI import at t/t_dpi_arg_inout_unpack.v:211:33 - extern void i_longint_unsigned_3d(unsigned long long* val); - // DPI import at t/t_dpi_arg_inout_unpack.v:269:33 - extern void i_pack_struct_0d(svLogicVecVal* val); - // DPI import at t/t_dpi_arg_inout_unpack.v:270:33 - extern void i_pack_struct_1d(svLogicVecVal* val); - // DPI import at t/t_dpi_arg_inout_unpack.v:271:33 - extern void i_pack_struct_2d(svLogicVecVal* val); - // DPI import at t/t_dpi_arg_inout_unpack.v:272:33 - extern void i_pack_struct_3d(svLogicVecVal* val); - // DPI import at t/t_dpi_arg_inout_unpack.v:227:33 - extern void i_real_0d(double* val); - // DPI import at t/t_dpi_arg_inout_unpack.v:228:33 - extern void i_real_1d(double* val); - // DPI import at t/t_dpi_arg_inout_unpack.v:229:33 - extern void i_real_2d(double* val); - // DPI import at t/t_dpi_arg_inout_unpack.v:230:33 - extern void i_real_3d(double* val); - // DPI import at t/t_dpi_arg_inout_unpack.v:183:33 - extern void i_shortint_0d(short* val); - // DPI import at t/t_dpi_arg_inout_unpack.v:184:33 - extern void i_shortint_1d(short* val); - // DPI import at t/t_dpi_arg_inout_unpack.v:185:33 - extern void i_shortint_2d(short* val); - // DPI import at t/t_dpi_arg_inout_unpack.v:186:33 - extern void i_shortint_3d(short* val); - // DPI import at t/t_dpi_arg_inout_unpack.v:188:33 - extern void i_shortint_unsigned_0d(unsigned short* val); - // DPI import at t/t_dpi_arg_inout_unpack.v:189:33 - extern void i_shortint_unsigned_1d(unsigned short* val); - // DPI import at t/t_dpi_arg_inout_unpack.v:190:33 - extern void i_shortint_unsigned_2d(unsigned short* val); - // DPI import at t/t_dpi_arg_inout_unpack.v:191:33 - extern void i_shortint_unsigned_3d(unsigned short* val); - // DPI import at t/t_dpi_arg_inout_unpack.v:244:33 - extern void i_string_0d(const char** val); - // DPI import at t/t_dpi_arg_inout_unpack.v:245:33 - extern void i_string_1d(const char** val); - // DPI import at t/t_dpi_arg_inout_unpack.v:246:33 - extern void i_string_2d(const char** val); - // DPI import at t/t_dpi_arg_inout_unpack.v:247:33 - extern void i_string_3d(const char** val); - // DPI import at t/t_dpi_arg_inout_unpack.v:214:33 - extern void i_time_0d(svLogicVecVal* val); - // DPI import at t/t_dpi_arg_inout_unpack.v:215:33 - extern void i_time_1d(svLogicVecVal* val); - // DPI import at t/t_dpi_arg_inout_unpack.v:216:33 - extern void i_time_2d(svLogicVecVal* val); - // DPI import at t/t_dpi_arg_inout_unpack.v:217:33 - extern void i_time_3d(svLogicVecVal* val); - + + + // DPI EXPORTS + extern void e_bit121_0d(svBitVecVal* val); + extern void e_bit121_1d(svBitVecVal* val); + extern void e_bit121_2d(svBitVecVal* val); + extern void e_bit121_3d(svBitVecVal* val); + extern void e_bit1_0d(svBit* val); + extern void e_bit1_1d(svBit* val); + extern void e_bit1_2d(svBit* val); + extern void e_bit1_3d(svBit* val); + extern void e_bit7_0d(svBitVecVal* val); + extern void e_bit7_1d(svBitVecVal* val); + extern void e_bit7_2d(svBitVecVal* val); + extern void e_bit7_3d(svBitVecVal* val); + extern void e_byte_0d(char* val); + extern void e_byte_1d(char* val); + extern void e_byte_2d(char* val); + extern void e_byte_3d(char* val); + extern void e_byte_unsigned_0d(unsigned char* val); + extern void e_byte_unsigned_1d(unsigned char* val); + extern void e_byte_unsigned_2d(unsigned char* val); + extern void e_byte_unsigned_3d(unsigned char* val); + extern void e_chandle_0d(void** val); + extern void e_chandle_1d(void** val); + extern void e_chandle_2d(void** val); + extern void e_chandle_3d(void** val); + extern void e_int_0d(int* val); + extern void e_int_1d(int* val); + extern void e_int_2d(int* val); + extern void e_int_3d(int* val); + extern void e_int_unsigned_0d(unsigned int* val); + extern void e_int_unsigned_1d(unsigned int* val); + extern void e_int_unsigned_2d(unsigned int* val); + extern void e_int_unsigned_3d(unsigned int* val); + extern void e_integer_0d(svLogicVecVal* val); + extern void e_integer_1d(svLogicVecVal* val); + extern void e_integer_2d(svLogicVecVal* val); + extern void e_integer_3d(svLogicVecVal* val); + extern void e_logic121_0d(svLogicVecVal* val); + extern void e_logic121_1d(svLogicVecVal* val); + extern void e_logic121_2d(svLogicVecVal* val); + extern void e_logic121_3d(svLogicVecVal* val); + extern void e_logic1_0d(svLogic* val); + extern void e_logic1_1d(svLogic* val); + extern void e_logic1_2d(svLogic* val); + extern void e_logic1_3d(svLogic* val); + extern void e_logic7_0d(svLogicVecVal* val); + extern void e_logic7_1d(svLogicVecVal* val); + extern void e_logic7_2d(svLogicVecVal* val); + extern void e_logic7_3d(svLogicVecVal* val); + extern void e_longint_0d(long long* val); + extern void e_longint_1d(long long* val); + extern void e_longint_2d(long long* val); + extern void e_longint_3d(long long* val); + extern void e_longint_unsigned_0d(unsigned long long* val); + extern void e_longint_unsigned_1d(unsigned long long* val); + extern void e_longint_unsigned_2d(unsigned long long* val); + extern void e_longint_unsigned_3d(unsigned long long* val); + extern void e_pack_struct_0d(svLogicVecVal* val); + extern void e_pack_struct_1d(svLogicVecVal* val); + extern void e_pack_struct_2d(svLogicVecVal* val); + extern void e_pack_struct_3d(svLogicVecVal* val); + extern void e_real_0d(double* val); + extern void e_real_1d(double* val); + extern void e_real_2d(double* val); + extern void e_real_3d(double* val); + extern void e_shortint_0d(short* val); + extern void e_shortint_1d(short* val); + extern void e_shortint_2d(short* val); + extern void e_shortint_3d(short* val); + extern void e_shortint_unsigned_0d(unsigned short* val); + extern void e_shortint_unsigned_1d(unsigned short* val); + extern void e_shortint_unsigned_2d(unsigned short* val); + extern void e_shortint_unsigned_3d(unsigned short* val); + extern void e_string_0d(const char** val); + extern void e_string_1d(const char** val); + extern void e_string_2d(const char** val); + extern void e_string_3d(const char** val); + extern void e_time_0d(svLogicVecVal* val); + extern void e_time_1d(svLogicVecVal* val); + extern void e_time_2d(svLogicVecVal* val); + extern void e_time_3d(svLogicVecVal* val); + + // DPI IMPORTS + extern void check_exports(); + extern void* get_non_null(); + extern void i_bit121_0d(svBitVecVal* val); + extern void i_bit121_1d(svBitVecVal* val); + extern void i_bit121_2d(svBitVecVal* val); + extern void i_bit121_3d(svBitVecVal* val); + extern void i_bit1_0d(svBit* val); + extern void i_bit1_1d(svBit* val); + extern void i_bit1_2d(svBit* val); + extern void i_bit1_3d(svBit* val); + extern void i_bit7_0d(svBitVecVal* val); + extern void i_bit7_1d(svBitVecVal* val); + extern void i_bit7_2d(svBitVecVal* val); + extern void i_bit7_3d(svBitVecVal* val); + extern void i_byte_0d(char* val); + extern void i_byte_1d(char* val); + extern void i_byte_2d(char* val); + extern void i_byte_3d(char* val); + extern void i_byte_unsigned_0d(unsigned char* val); + extern void i_byte_unsigned_1d(unsigned char* val); + extern void i_byte_unsigned_2d(unsigned char* val); + extern void i_byte_unsigned_3d(unsigned char* val); + extern void i_chandle_0d(void** val); + extern void i_chandle_1d(void** val); + extern void i_chandle_2d(void** val); + extern void i_chandle_3d(void** val); + extern void i_int_0d(int* val); + extern void i_int_1d(int* val); + extern void i_int_2d(int* val); + extern void i_int_3d(int* val); + extern void i_int_unsigned_0d(unsigned int* val); + extern void i_int_unsigned_1d(unsigned int* val); + extern void i_int_unsigned_2d(unsigned int* val); + extern void i_int_unsigned_3d(unsigned int* val); + extern void i_integer_0d(svLogicVecVal* val); + extern void i_integer_1d(svLogicVecVal* val); + extern void i_integer_2d(svLogicVecVal* val); + extern void i_integer_3d(svLogicVecVal* val); + extern void i_logic121_0d(svLogicVecVal* val); + extern void i_logic121_1d(svLogicVecVal* val); + extern void i_logic121_2d(svLogicVecVal* val); + extern void i_logic121_3d(svLogicVecVal* val); + extern void i_logic1_0d(svLogic* val); + extern void i_logic1_1d(svLogic* val); + extern void i_logic1_2d(svLogic* val); + extern void i_logic1_3d(svLogic* val); + extern void i_logic7_0d(svLogicVecVal* val); + extern void i_logic7_1d(svLogicVecVal* val); + extern void i_logic7_2d(svLogicVecVal* val); + extern void i_logic7_3d(svLogicVecVal* val); + extern void i_longint_0d(long long* val); + extern void i_longint_1d(long long* val); + extern void i_longint_2d(long long* val); + extern void i_longint_3d(long long* val); + extern void i_longint_unsigned_0d(unsigned long long* val); + extern void i_longint_unsigned_1d(unsigned long long* val); + extern void i_longint_unsigned_2d(unsigned long long* val); + extern void i_longint_unsigned_3d(unsigned long long* val); + extern void i_pack_struct_0d(svLogicVecVal* val); + extern void i_pack_struct_1d(svLogicVecVal* val); + extern void i_pack_struct_2d(svLogicVecVal* val); + extern void i_pack_struct_3d(svLogicVecVal* val); + extern void i_real_0d(double* val); + extern void i_real_1d(double* val); + extern void i_real_2d(double* val); + extern void i_real_3d(double* val); + extern void i_shortint_0d(short* val); + extern void i_shortint_1d(short* val); + extern void i_shortint_2d(short* val); + extern void i_shortint_3d(short* val); + extern void i_shortint_unsigned_0d(unsigned short* val); + extern void i_shortint_unsigned_1d(unsigned short* val); + extern void i_shortint_unsigned_2d(unsigned short* val); + extern void i_shortint_unsigned_3d(unsigned short* val); + extern void i_string_0d(const char** val); + extern void i_string_1d(const char** val); + extern void i_string_2d(const char** val); + extern void i_string_3d(const char** val); + extern void i_time_0d(svLogicVecVal* val); + extern void i_time_1d(svLogicVecVal* val); + extern void i_time_2d(svLogicVecVal* val); + extern void i_time_3d(svLogicVecVal* val); + #ifdef __cplusplus } #endif diff --git a/test_regress/t/t_dpi_arg_input_type.pl b/test_regress/t/t_dpi_arg_input_type.pl index 16fc1abc3..8c609be40 100755 --- a/test_regress/t/t_dpi_arg_input_type.pl +++ b/test_regress/t/t_dpi_arg_input_type.pl @@ -20,7 +20,8 @@ if ($Self->{nc}) { compile( v_flags2 => ["t/t_dpi_arg_input_type.cpp"], - verilator_flags2 => ["-Wall -Wno-DECLFILENAME"], + # --no-decoration so .out file doesn't comment on source lines + verilator_flags2 => ["-Wall -Wno-DECLFILENAME --no-decoration"], # NC: Gdd the obj_dir to the C include path nc_flags2 => ["+ncscargs+-I$Self->{obj_dir}"], # ModelSim: Generate DPI header, add obj_dir to the C include path diff --git a/test_regress/t/t_dpi_arg_input_type__Dpi.out b/test_regress/t/t_dpi_arg_input_type__Dpi.out index 26a75f7ee..ea56ffe00 100644 --- a/test_regress/t/t_dpi_arg_input_type__Dpi.out +++ b/test_regress/t/t_dpi_arg_input_type__Dpi.out @@ -10,278 +10,145 @@ #ifdef __cplusplus extern "C" { #endif - - - // DPI EXPORTS - // DPI export at t/t_dpi_arg_input_type.v:537:18 - extern void e_array_2_state_1(const svBitVecVal* i); - // DPI export at t/t_dpi_arg_input_type.v:572:18 - extern void e_array_2_state_128(const svBitVecVal* i); - // DPI export at t/t_dpi_arg_input_type.v:544:18 - extern void e_array_2_state_32(const svBitVecVal* i); - // DPI export at t/t_dpi_arg_input_type.v:551:18 - extern void e_array_2_state_33(const svBitVecVal* i); - // DPI export at t/t_dpi_arg_input_type.v:558:18 - extern void e_array_2_state_64(const svBitVecVal* i); - // DPI export at t/t_dpi_arg_input_type.v:565:18 - extern void e_array_2_state_65(const svBitVecVal* i); - // DPI export at t/t_dpi_arg_input_type.v:666:18 - extern void e_array_4_state_1(const svLogicVecVal* i); - // DPI export at t/t_dpi_arg_input_type.v:701:18 - extern void e_array_4_state_128(const svLogicVecVal* i); - // DPI export at t/t_dpi_arg_input_type.v:673:18 - extern void e_array_4_state_32(const svLogicVecVal* i); - // DPI export at t/t_dpi_arg_input_type.v:680:18 - extern void e_array_4_state_33(const svLogicVecVal* i); - // DPI export at t/t_dpi_arg_input_type.v:687:18 - extern void e_array_4_state_64(const svLogicVecVal* i); - // DPI export at t/t_dpi_arg_input_type.v:694:18 - extern void e_array_4_state_65(const svLogicVecVal* i); - // DPI export at t/t_dpi_arg_input_type.v:407:18 - extern void e_bit(svBit i); - // DPI export at t/t_dpi_arg_input_type.v:522:18 - extern void e_bit_t(svBit i); - // DPI export at t/t_dpi_arg_input_type.v:307:18 - extern void e_byte(char i); - // DPI export at t/t_dpi_arg_input_type.v:422:18 - extern void e_byte_t(char i); - // DPI export at t/t_dpi_arg_input_type.v:313:18 - extern void e_byte_unsigned(unsigned char i); - // DPI export at t/t_dpi_arg_input_type.v:428:18 - extern void e_byte_unsigned_t(unsigned char i); - // DPI export at t/t_dpi_arg_input_type.v:385:18 - extern void e_chandle(void* i); - // DPI export at t/t_dpi_arg_input_type.v:500:18 - extern void e_chandle_t(void* i); - // DPI export at t/t_dpi_arg_input_type.v:331:18 - extern void e_int(int i); - // DPI export at t/t_dpi_arg_input_type.v:446:18 - extern void e_int_t(int i); - // DPI export at t/t_dpi_arg_input_type.v:337:18 - extern void e_int_unsigned(unsigned int i); - // DPI export at t/t_dpi_arg_input_type.v:452:18 - extern void e_int_unsigned_t(unsigned int i); - // DPI export at t/t_dpi_arg_input_type.v:364:18 - extern void e_integer(const svLogicVecVal* i); - // DPI export at t/t_dpi_arg_input_type.v:479:18 - extern void e_integer_t(const svLogicVecVal* i); - // DPI export at t/t_dpi_arg_input_type.v:414:18 - extern void e_logic(svLogic i); - // DPI export at t/t_dpi_arg_input_type.v:529:18 - extern void e_logic_t(svLogic i); - // DPI export at t/t_dpi_arg_input_type.v:343:18 - extern void e_longint(long long i); - // DPI export at t/t_dpi_arg_input_type.v:458:18 - extern void e_longint_t(long long i); - // DPI export at t/t_dpi_arg_input_type.v:349:18 - extern void e_longint_unsigned(unsigned long long i); - // DPI export at t/t_dpi_arg_input_type.v:464:18 - extern void e_longint_unsigned_t(unsigned long long i); - // DPI export at t/t_dpi_arg_input_type.v:371:18 - extern void e_real(double i); - // DPI export at t/t_dpi_arg_input_type.v:486:18 - extern void e_real_t(double i); - // DPI export at t/t_dpi_arg_input_type.v:319:18 - extern void e_shortint(short i); - // DPI export at t/t_dpi_arg_input_type.v:434:18 - extern void e_shortint_t(short i); - // DPI export at t/t_dpi_arg_input_type.v:325:18 - extern void e_shortint_unsigned(unsigned short i); - // DPI export at t/t_dpi_arg_input_type.v:440:18 - extern void e_shortint_unsigned_t(unsigned short i); - // DPI export at t/t_dpi_arg_input_type.v:396:18 - extern void e_string(const char* i); - // DPI export at t/t_dpi_arg_input_type.v:511:18 - extern void e_string_t(const char* i); - // DPI export at t/t_dpi_arg_input_type.v:580:18 - extern void e_struct_2_state_1(const svBitVecVal* i); - // DPI export at t/t_dpi_arg_input_type.v:615:18 - extern void e_struct_2_state_128(const svBitVecVal* i); - // DPI export at t/t_dpi_arg_input_type.v:587:18 - extern void e_struct_2_state_32(const svBitVecVal* i); - // DPI export at t/t_dpi_arg_input_type.v:594:18 - extern void e_struct_2_state_33(const svBitVecVal* i); - // DPI export at t/t_dpi_arg_input_type.v:601:18 - extern void e_struct_2_state_64(const svBitVecVal* i); - // DPI export at t/t_dpi_arg_input_type.v:608:18 - extern void e_struct_2_state_65(const svBitVecVal* i); - // DPI export at t/t_dpi_arg_input_type.v:709:18 - extern void e_struct_4_state_1(const svLogicVecVal* i); - // DPI export at t/t_dpi_arg_input_type.v:744:18 - extern void e_struct_4_state_128(const svLogicVecVal* i); - // DPI export at t/t_dpi_arg_input_type.v:716:18 - extern void e_struct_4_state_32(const svLogicVecVal* i); - // DPI export at t/t_dpi_arg_input_type.v:723:18 - extern void e_struct_4_state_33(const svLogicVecVal* i); - // DPI export at t/t_dpi_arg_input_type.v:730:18 - extern void e_struct_4_state_64(const svLogicVecVal* i); - // DPI export at t/t_dpi_arg_input_type.v:737:18 - extern void e_struct_4_state_65(const svLogicVecVal* i); - // DPI export at t/t_dpi_arg_input_type.v:356:18 - extern void e_time(const svLogicVecVal* i); - // DPI export at t/t_dpi_arg_input_type.v:471:18 - extern void e_time_t(const svLogicVecVal* i); - // DPI export at t/t_dpi_arg_input_type.v:623:18 - extern void e_union_2_state_1(const svBitVecVal* i); - // DPI export at t/t_dpi_arg_input_type.v:658:18 - extern void e_union_2_state_128(const svBitVecVal* i); - // DPI export at t/t_dpi_arg_input_type.v:630:18 - extern void e_union_2_state_32(const svBitVecVal* i); - // DPI export at t/t_dpi_arg_input_type.v:637:18 - extern void e_union_2_state_33(const svBitVecVal* i); - // DPI export at t/t_dpi_arg_input_type.v:644:18 - extern void e_union_2_state_64(const svBitVecVal* i); - // DPI export at t/t_dpi_arg_input_type.v:651:18 - extern void e_union_2_state_65(const svBitVecVal* i); - // DPI export at t/t_dpi_arg_input_type.v:752:18 - extern void e_union_4_state_1(const svLogicVecVal* i); - // DPI export at t/t_dpi_arg_input_type.v:787:18 - extern void e_union_4_state_128(const svLogicVecVal* i); - // DPI export at t/t_dpi_arg_input_type.v:759:18 - extern void e_union_4_state_32(const svLogicVecVal* i); - // DPI export at t/t_dpi_arg_input_type.v:766:18 - extern void e_union_4_state_33(const svLogicVecVal* i); - // DPI export at t/t_dpi_arg_input_type.v:773:18 - extern void e_union_4_state_64(const svLogicVecVal* i); - // DPI export at t/t_dpi_arg_input_type.v:780:18 - extern void e_union_4_state_65(const svLogicVecVal* i); - - // DPI IMPORTS - // DPI import at t/t_dpi_arg_input_type.v:797:41 - extern void check_exports(); - // DPI import at t/t_dpi_arg_input_type.v:154:33 - extern void i_array_2_state_1(const svBitVecVal* i); - // DPI import at t/t_dpi_arg_input_type.v:159:33 - extern void i_array_2_state_128(const svBitVecVal* i); - // DPI import at t/t_dpi_arg_input_type.v:155:33 - extern void i_array_2_state_32(const svBitVecVal* i); - // DPI import at t/t_dpi_arg_input_type.v:156:33 - extern void i_array_2_state_33(const svBitVecVal* i); - // DPI import at t/t_dpi_arg_input_type.v:157:33 - extern void i_array_2_state_64(const svBitVecVal* i); - // DPI import at t/t_dpi_arg_input_type.v:158:33 - extern void i_array_2_state_65(const svBitVecVal* i); - // DPI import at t/t_dpi_arg_input_type.v:178:33 - extern void i_array_4_state_1(const svLogicVecVal* i); - // DPI import at t/t_dpi_arg_input_type.v:183:33 - extern void i_array_4_state_128(const svLogicVecVal* i); - // DPI import at t/t_dpi_arg_input_type.v:179:33 - extern void i_array_4_state_32(const svLogicVecVal* i); - // DPI import at t/t_dpi_arg_input_type.v:180:33 - extern void i_array_4_state_33(const svLogicVecVal* i); - // DPI import at t/t_dpi_arg_input_type.v:181:33 - extern void i_array_4_state_64(const svLogicVecVal* i); - // DPI import at t/t_dpi_arg_input_type.v:182:33 - extern void i_array_4_state_65(const svLogicVecVal* i); - // DPI import at t/t_dpi_arg_input_type.v:126:33 - extern void i_bit(svBit i); - // DPI import at t/t_dpi_arg_input_type.v:150:33 - extern void i_bit_t(svBit i); - // DPI import at t/t_dpi_arg_input_type.v:106:33 - extern void i_byte(char i); - // DPI import at t/t_dpi_arg_input_type.v:130:33 - extern void i_byte_t(char i); - // DPI import at t/t_dpi_arg_input_type.v:107:33 - extern void i_byte_unsigned(unsigned char i); - // DPI import at t/t_dpi_arg_input_type.v:131:33 - extern void i_byte_unsigned_t(unsigned char i); - // DPI import at t/t_dpi_arg_input_type.v:124:33 - extern void i_chandle(void* i); - // DPI import at t/t_dpi_arg_input_type.v:148:33 - extern void i_chandle_t(void* i); - // DPI import at t/t_dpi_arg_input_type.v:110:33 - extern void i_int(int i); - // DPI import at t/t_dpi_arg_input_type.v:134:33 - extern void i_int_t(int i); - // DPI import at t/t_dpi_arg_input_type.v:111:33 - extern void i_int_unsigned(unsigned int i); - // DPI import at t/t_dpi_arg_input_type.v:135:33 - extern void i_int_unsigned_t(unsigned int i); - // DPI import at t/t_dpi_arg_input_type.v:118:33 - extern void i_integer(const svLogicVecVal* i); - // DPI import at t/t_dpi_arg_input_type.v:142:33 - extern void i_integer_t(const svLogicVecVal* i); - // DPI import at t/t_dpi_arg_input_type.v:127:33 - extern void i_logic(svLogic i); - // DPI import at t/t_dpi_arg_input_type.v:151:33 - extern void i_logic_t(svLogic i); - // DPI import at t/t_dpi_arg_input_type.v:112:33 - extern void i_longint(long long i); - // DPI import at t/t_dpi_arg_input_type.v:136:33 - extern void i_longint_t(long long i); - // DPI import at t/t_dpi_arg_input_type.v:113:33 - extern void i_longint_unsigned(unsigned long long i); - // DPI import at t/t_dpi_arg_input_type.v:137:33 - extern void i_longint_unsigned_t(unsigned long long i); - // DPI import at t/t_dpi_arg_input_type.v:120:33 - extern void i_real(double i); - // DPI import at t/t_dpi_arg_input_type.v:144:33 - extern void i_real_t(double i); - // DPI import at t/t_dpi_arg_input_type.v:108:33 - extern void i_shortint(short i); - // DPI import at t/t_dpi_arg_input_type.v:132:33 - extern void i_shortint_t(short i); - // DPI import at t/t_dpi_arg_input_type.v:109:33 - extern void i_shortint_unsigned(unsigned short i); - // DPI import at t/t_dpi_arg_input_type.v:133:33 - extern void i_shortint_unsigned_t(unsigned short i); - // DPI import at t/t_dpi_arg_input_type.v:125:33 - extern void i_string(const char* i); - // DPI import at t/t_dpi_arg_input_type.v:149:33 - extern void i_string_t(const char* i); - // DPI import at t/t_dpi_arg_input_type.v:162:33 - extern void i_struct_2_state_1(const svBitVecVal* i); - // DPI import at t/t_dpi_arg_input_type.v:167:33 - extern void i_struct_2_state_128(const svBitVecVal* i); - // DPI import at t/t_dpi_arg_input_type.v:163:33 - extern void i_struct_2_state_32(const svBitVecVal* i); - // DPI import at t/t_dpi_arg_input_type.v:164:33 - extern void i_struct_2_state_33(const svBitVecVal* i); - // DPI import at t/t_dpi_arg_input_type.v:165:33 - extern void i_struct_2_state_64(const svBitVecVal* i); - // DPI import at t/t_dpi_arg_input_type.v:166:33 - extern void i_struct_2_state_65(const svBitVecVal* i); - // DPI import at t/t_dpi_arg_input_type.v:186:33 - extern void i_struct_4_state_1(const svLogicVecVal* i); - // DPI import at t/t_dpi_arg_input_type.v:191:33 - extern void i_struct_4_state_128(const svLogicVecVal* i); - // DPI import at t/t_dpi_arg_input_type.v:187:33 - extern void i_struct_4_state_32(const svLogicVecVal* i); - // DPI import at t/t_dpi_arg_input_type.v:188:33 - extern void i_struct_4_state_33(const svLogicVecVal* i); - // DPI import at t/t_dpi_arg_input_type.v:189:33 - extern void i_struct_4_state_64(const svLogicVecVal* i); - // DPI import at t/t_dpi_arg_input_type.v:190:33 - extern void i_struct_4_state_65(const svLogicVecVal* i); - // DPI import at t/t_dpi_arg_input_type.v:115:33 - extern void i_time(const svLogicVecVal* i); - // DPI import at t/t_dpi_arg_input_type.v:139:33 - extern void i_time_t(const svLogicVecVal* i); - // DPI import at t/t_dpi_arg_input_type.v:170:33 - extern void i_union_2_state_1(const svBitVecVal* i); - // DPI import at t/t_dpi_arg_input_type.v:175:33 - extern void i_union_2_state_128(const svBitVecVal* i); - // DPI import at t/t_dpi_arg_input_type.v:171:33 - extern void i_union_2_state_32(const svBitVecVal* i); - // DPI import at t/t_dpi_arg_input_type.v:172:33 - extern void i_union_2_state_33(const svBitVecVal* i); - // DPI import at t/t_dpi_arg_input_type.v:173:33 - extern void i_union_2_state_64(const svBitVecVal* i); - // DPI import at t/t_dpi_arg_input_type.v:174:33 - extern void i_union_2_state_65(const svBitVecVal* i); - // DPI import at t/t_dpi_arg_input_type.v:194:33 - extern void i_union_4_state_1(const svLogicVecVal* i); - // DPI import at t/t_dpi_arg_input_type.v:199:33 - extern void i_union_4_state_128(const svLogicVecVal* i); - // DPI import at t/t_dpi_arg_input_type.v:195:33 - extern void i_union_4_state_32(const svLogicVecVal* i); - // DPI import at t/t_dpi_arg_input_type.v:196:33 - extern void i_union_4_state_33(const svLogicVecVal* i); - // DPI import at t/t_dpi_arg_input_type.v:197:33 - extern void i_union_4_state_64(const svLogicVecVal* i); - // DPI import at t/t_dpi_arg_input_type.v:198:33 - extern void i_union_4_state_65(const svLogicVecVal* i); - + + + // DPI EXPORTS + extern void e_array_2_state_1(const svBitVecVal* i); + extern void e_array_2_state_128(const svBitVecVal* i); + extern void e_array_2_state_32(const svBitVecVal* i); + extern void e_array_2_state_33(const svBitVecVal* i); + extern void e_array_2_state_64(const svBitVecVal* i); + extern void e_array_2_state_65(const svBitVecVal* i); + extern void e_array_4_state_1(const svLogicVecVal* i); + extern void e_array_4_state_128(const svLogicVecVal* i); + extern void e_array_4_state_32(const svLogicVecVal* i); + extern void e_array_4_state_33(const svLogicVecVal* i); + extern void e_array_4_state_64(const svLogicVecVal* i); + extern void e_array_4_state_65(const svLogicVecVal* i); + extern void e_bit(svBit i); + extern void e_bit_t(svBit i); + extern void e_byte(char i); + extern void e_byte_t(char i); + extern void e_byte_unsigned(unsigned char i); + extern void e_byte_unsigned_t(unsigned char i); + extern void e_chandle(void* i); + extern void e_chandle_t(void* i); + extern void e_int(int i); + extern void e_int_t(int i); + extern void e_int_unsigned(unsigned int i); + extern void e_int_unsigned_t(unsigned int i); + extern void e_integer(const svLogicVecVal* i); + extern void e_integer_t(const svLogicVecVal* i); + extern void e_logic(svLogic i); + extern void e_logic_t(svLogic i); + extern void e_longint(long long i); + extern void e_longint_t(long long i); + extern void e_longint_unsigned(unsigned long long i); + extern void e_longint_unsigned_t(unsigned long long i); + extern void e_real(double i); + extern void e_real_t(double i); + extern void e_shortint(short i); + extern void e_shortint_t(short i); + extern void e_shortint_unsigned(unsigned short i); + extern void e_shortint_unsigned_t(unsigned short i); + extern void e_string(const char* i); + extern void e_string_t(const char* i); + extern void e_struct_2_state_1(const svBitVecVal* i); + extern void e_struct_2_state_128(const svBitVecVal* i); + extern void e_struct_2_state_32(const svBitVecVal* i); + extern void e_struct_2_state_33(const svBitVecVal* i); + extern void e_struct_2_state_64(const svBitVecVal* i); + extern void e_struct_2_state_65(const svBitVecVal* i); + extern void e_struct_4_state_1(const svLogicVecVal* i); + extern void e_struct_4_state_128(const svLogicVecVal* i); + extern void e_struct_4_state_32(const svLogicVecVal* i); + extern void e_struct_4_state_33(const svLogicVecVal* i); + extern void e_struct_4_state_64(const svLogicVecVal* i); + extern void e_struct_4_state_65(const svLogicVecVal* i); + extern void e_time(const svLogicVecVal* i); + extern void e_time_t(const svLogicVecVal* i); + extern void e_union_2_state_1(const svBitVecVal* i); + extern void e_union_2_state_128(const svBitVecVal* i); + extern void e_union_2_state_32(const svBitVecVal* i); + extern void e_union_2_state_33(const svBitVecVal* i); + extern void e_union_2_state_64(const svBitVecVal* i); + extern void e_union_2_state_65(const svBitVecVal* i); + extern void e_union_4_state_1(const svLogicVecVal* i); + extern void e_union_4_state_128(const svLogicVecVal* i); + extern void e_union_4_state_32(const svLogicVecVal* i); + extern void e_union_4_state_33(const svLogicVecVal* i); + extern void e_union_4_state_64(const svLogicVecVal* i); + extern void e_union_4_state_65(const svLogicVecVal* i); + + // DPI IMPORTS + extern void check_exports(); + extern void i_array_2_state_1(const svBitVecVal* i); + extern void i_array_2_state_128(const svBitVecVal* i); + extern void i_array_2_state_32(const svBitVecVal* i); + extern void i_array_2_state_33(const svBitVecVal* i); + extern void i_array_2_state_64(const svBitVecVal* i); + extern void i_array_2_state_65(const svBitVecVal* i); + extern void i_array_4_state_1(const svLogicVecVal* i); + extern void i_array_4_state_128(const svLogicVecVal* i); + extern void i_array_4_state_32(const svLogicVecVal* i); + extern void i_array_4_state_33(const svLogicVecVal* i); + extern void i_array_4_state_64(const svLogicVecVal* i); + extern void i_array_4_state_65(const svLogicVecVal* i); + extern void i_bit(svBit i); + extern void i_bit_t(svBit i); + extern void i_byte(char i); + extern void i_byte_t(char i); + extern void i_byte_unsigned(unsigned char i); + extern void i_byte_unsigned_t(unsigned char i); + extern void i_chandle(void* i); + extern void i_chandle_t(void* i); + extern void i_int(int i); + extern void i_int_t(int i); + extern void i_int_unsigned(unsigned int i); + extern void i_int_unsigned_t(unsigned int i); + extern void i_integer(const svLogicVecVal* i); + extern void i_integer_t(const svLogicVecVal* i); + extern void i_logic(svLogic i); + extern void i_logic_t(svLogic i); + extern void i_longint(long long i); + extern void i_longint_t(long long i); + extern void i_longint_unsigned(unsigned long long i); + extern void i_longint_unsigned_t(unsigned long long i); + extern void i_real(double i); + extern void i_real_t(double i); + extern void i_shortint(short i); + extern void i_shortint_t(short i); + extern void i_shortint_unsigned(unsigned short i); + extern void i_shortint_unsigned_t(unsigned short i); + extern void i_string(const char* i); + extern void i_string_t(const char* i); + extern void i_struct_2_state_1(const svBitVecVal* i); + extern void i_struct_2_state_128(const svBitVecVal* i); + extern void i_struct_2_state_32(const svBitVecVal* i); + extern void i_struct_2_state_33(const svBitVecVal* i); + extern void i_struct_2_state_64(const svBitVecVal* i); + extern void i_struct_2_state_65(const svBitVecVal* i); + extern void i_struct_4_state_1(const svLogicVecVal* i); + extern void i_struct_4_state_128(const svLogicVecVal* i); + extern void i_struct_4_state_32(const svLogicVecVal* i); + extern void i_struct_4_state_33(const svLogicVecVal* i); + extern void i_struct_4_state_64(const svLogicVecVal* i); + extern void i_struct_4_state_65(const svLogicVecVal* i); + extern void i_time(const svLogicVecVal* i); + extern void i_time_t(const svLogicVecVal* i); + extern void i_union_2_state_1(const svBitVecVal* i); + extern void i_union_2_state_128(const svBitVecVal* i); + extern void i_union_2_state_32(const svBitVecVal* i); + extern void i_union_2_state_33(const svBitVecVal* i); + extern void i_union_2_state_64(const svBitVecVal* i); + extern void i_union_2_state_65(const svBitVecVal* i); + extern void i_union_4_state_1(const svLogicVecVal* i); + extern void i_union_4_state_128(const svLogicVecVal* i); + extern void i_union_4_state_32(const svLogicVecVal* i); + extern void i_union_4_state_33(const svLogicVecVal* i); + extern void i_union_4_state_64(const svLogicVecVal* i); + extern void i_union_4_state_65(const svLogicVecVal* i); + #ifdef __cplusplus } #endif diff --git a/test_regress/t/t_dpi_arg_input_unpack.cpp b/test_regress/t/t_dpi_arg_input_unpack.cpp index 695cedc6c..08084ae57 100644 --- a/test_regress/t/t_dpi_arg_input_unpack.cpp +++ b/test_regress/t/t_dpi_arg_input_unpack.cpp @@ -458,6 +458,25 @@ void i_string_3d(CONSTARG char** v) { if (!check_3d(v)) stop(); } +void i_bit1_0d(CONSTARG svBit v) { + if (!compare(v, sv_0)) stop(); +} +void i_bit1_1d(CONSTARG svBit* v) { + if (!compare(v[0], sv_1)) stop(); + if (!compare(v[1], sv_0)) stop(); +} +void i_bit1_2d(CONSTARG svBit* v) { + if (!compare(v[0 * 2 + 1], sv_1)) stop(); + if (!compare(v[1 * 2 + 1], sv_0)) stop(); + if (!compare(v[2 * 2 + 1], sv_1)) stop(); +} +void i_bit1_3d(CONSTARG svBit* v) { + if (!compare(v[(0 * 3 + 0) * 2 + 0], sv_0)) stop(); + if (!compare(v[(1 * 3 + 0) * 2 + 0], sv_1)) stop(); + if (!compare(v[(2 * 3 + 0) * 2 + 0], sv_0)) stop(); + if (!compare(v[(3 * 3 + 0) * 2 + 0], sv_1)) stop(); +} + void i_bit7_0d(CONSTARG svBitVecVal* v) { if (!check_0d(v, 7)) stop(); } @@ -484,6 +503,25 @@ void i_bit121_3d(CONSTARG svBitVecVal* v) { if (!check_3d(v, 121)) stop(); } +void i_logic1_0d(CONSTARG svLogic v) { + if (!compare(v, sv_0)) stop(); +} +void i_logic1_1d(CONSTARG svLogic* v) { + if (!compare(v[0], sv_1)) stop(); + if (!compare(v[1], sv_0)) stop(); +} +void i_logic1_2d(CONSTARG svLogic* v) { + if (!compare(v[0 * 2 + 1], sv_1)) stop(); + if (!compare(v[1 * 2 + 1], sv_0)) stop(); + if (!compare(v[2 * 2 + 1], sv_1)) stop(); +} +void i_logic1_3d(CONSTARG svLogic* v) { + if (!compare(v[(0 * 3 + 0) * 2 + 0], sv_0)) stop(); + if (!compare(v[(1 * 3 + 0) * 2 + 0], sv_1)) stop(); + if (!compare(v[(2 * 3 + 0) * 2 + 0], sv_0)) stop(); + if (!compare(v[(3 * 3 + 0) * 2 + 0], sv_1)) stop(); +} + void i_logic7_0d(CONSTARG svLogicVecVal* v) { if (!check_0d(v, 7)) stop(); } diff --git a/test_regress/t/t_dpi_arg_input_unpack.pl b/test_regress/t/t_dpi_arg_input_unpack.pl index 364897b82..f6772ebcc 100755 --- a/test_regress/t/t_dpi_arg_input_unpack.pl +++ b/test_regress/t/t_dpi_arg_input_unpack.pl @@ -20,7 +20,8 @@ if ($Self->{nc}) { compile( v_flags2 => ["t/t_dpi_arg_input_unpack.cpp"], - verilator_flags2 => ["-Wall -Wno-DECLFILENAME"], + # --no-decoration so .out file doesn't comment on source lines + verilator_flags2 => ["-Wall -Wno-DECLFILENAME --no-decoration"], # NC: Gdd the obj_dir to the C include path nc_flags2 => ["+ncscargs+-I$Self->{obj_dir}"], # ModelSim: Generate DPI header, add obj_dir to the C include path diff --git a/test_regress/t/t_dpi_arg_input_unpack.v b/test_regress/t/t_dpi_arg_input_unpack.v index 0a698e905..432e1925a 100644 --- a/test_regress/t/t_dpi_arg_input_unpack.v +++ b/test_regress/t/t_dpi_arg_input_unpack.v @@ -17,17 +17,22 @@ `endif `ifdef MS + `define NO_BITS_TO_SCALAR `endif `ifdef VERILATOR `define NO_SHORTREAL `define NO_UNPACK_STRUCT - `define NULL 64'd0 `else - `define NULL null `endif -`define CHECK_VAL(act, exp) if ((act) == (exp)) begin \ +`ifdef NO_BITS_TO_SCALAR + `define ARE_SAME(act, exp) ((act) == (exp)) +`else + `define ARE_SAME(act, exp) ((act) == (($bits(act))'(exp))) +`endif + +`define CHECK_VAL(act, exp) if (`ARE_SAME(act, exp)) begin \ if (ENABLE_VERBOSE_MESSAGE)$display(`"act`", ":", (act), " as expected"); \ end else begin \ $display("Mismatch %s expected:%d actual:%d at %d", `"act`", \ @@ -47,10 +52,12 @@ `CHECK_VAL(val[3][0][0], 51) `define SET_VALUES(val) \ +/* verilator lint_off WIDTH */ \ val[3][2][1] = 42; \ val[2][1][0] = 43; val[2][1][1] = 44; \ val[1][0][1] = 45; val[1][1][1] = 46; val[1][2][1] = 47; \ -val[0][0][0] = 48; val[1][0][0] = 49; val[2][0][0] = 50; val[3][0][0] = 51 +val[0][0][0] = 48; val[1][0][0] = 49; val[2][0][0] = 50; val[3][0][0] = 51 \ +/* verilator lint_on WIDTH */ module t; @@ -82,8 +89,10 @@ module t; `endif typedef chandle chandle_array_t[4][3][2]; typedef string string_array_t[4][3][2]; + typedef bit bit1_array_t[4][3][2]; typedef bit [6:0] bit7_array_t[4][3][2]; typedef bit [120:0] bit121_array_t[4][3][2]; + typedef logic logic1_array_t[4][3][2]; typedef logic [6:0] logic7_array_t[4][3][2]; typedef logic [120:0] logic121_array_t[4][3][2]; @@ -181,6 +190,11 @@ module t; import "DPI-C" function void i_string_2d(input string val[3][2]); import "DPI-C" function void i_string_3d(input string_array_t val); + import "DPI-C" function void i_bit1_0d(input bit val); + import "DPI-C" function void i_bit1_1d(input bit val[2]); + import "DPI-C" function void i_bit1_2d(input bit val[3][2]); + import "DPI-C" function void i_bit1_3d(input bit1_array_t val); + import "DPI-C" function void i_bit7_0d(input bit[6:0] val); import "DPI-C" function void i_bit7_1d(input bit[6:0] val[2]); import "DPI-C" function void i_bit7_2d(input bit[6:0] val[3][2]); @@ -191,6 +205,11 @@ module t; import "DPI-C" function void i_bit121_2d(input bit[120:0] val[3][2]); import "DPI-C" function void i_bit121_3d(input bit121_array_t val); + import "DPI-C" function void i_logic1_0d(input logic val); + import "DPI-C" function void i_logic1_1d(input logic val[2]); + import "DPI-C" function void i_logic1_2d(input logic val[3][2]); + import "DPI-C" function void i_logic1_3d(input logic1_array_t val); + import "DPI-C" function void i_logic7_0d(input logic[6:0] val); import "DPI-C" function void i_logic7_1d(input logic[6:0] val[2]); import "DPI-C" function void i_logic7_2d(input logic[6:0] val[3][2]); @@ -294,6 +313,11 @@ module t; export "DPI-C" function e_string_2d; export "DPI-C" function e_string_3d; + export "DPI-C" function e_bit1_0d; + export "DPI-C" function e_bit1_1d; + export "DPI-C" function e_bit1_2d; + export "DPI-C" function e_bit1_3d; + export "DPI-C" function e_bit7_0d; export "DPI-C" function e_bit7_1d; export "DPI-C" function e_bit7_2d; @@ -304,6 +328,11 @@ module t; export "DPI-C" function e_bit121_2d; export "DPI-C" function e_bit121_3d; + export "DPI-C" function e_logic1_0d; + export "DPI-C" function e_logic1_1d; + export "DPI-C" function e_logic1_2d; + export "DPI-C" function e_logic1_3d; + export "DPI-C" function e_logic7_0d; export "DPI-C" function e_logic7_1d; export "DPI-C" function e_logic7_2d; @@ -493,6 +522,11 @@ module t; end endfunction + function void e_bit1_0d(input bit val); `CHECK_0D(val); endfunction + function void e_bit1_1d(input bit val[2]); `CHECK_1D(val); endfunction + function void e_bit1_2d(input bit val[3][2]); `CHECK_2D(val); endfunction + function void e_bit1_3d(input bit1_array_t val); `CHECK_3D(val); endfunction + function void e_bit7_0d(input bit[6:0] val); `CHECK_0D(val); endfunction function void e_bit7_1d(input bit[6:0] val[2]); `CHECK_1D(val); endfunction function void e_bit7_2d(input bit[6:0] val[3][2]); `CHECK_2D(val); endfunction @@ -503,6 +537,11 @@ module t; function void e_bit121_2d(input bit[120:0] val[3][2]); `CHECK_2D(val); endfunction function void e_bit121_3d(input bit121_array_t val); `CHECK_3D(val); endfunction + function void e_logic1_0d(input logic val); `CHECK_0D(val); endfunction + function void e_logic1_1d(input logic val[2]); `CHECK_1D(val); endfunction + function void e_logic1_2d(input logic val[3][2]); `CHECK_2D(val); endfunction + function void e_logic1_3d(input logic1_array_t val); `CHECK_3D(val); endfunction + function void e_logic7_0d(input logic[6:0] val); `CHECK_0D(val); endfunction function void e_logic7_1d(input logic[6:0] val[2]); `CHECK_1D(val); endfunction function void e_logic7_2d(input logic[6:0] val[3][2]); `CHECK_2D(val); endfunction @@ -596,8 +635,10 @@ module t; `endif chandle_array_t chandle_array; string_array_t string_array; + bit1_array_t bit1_array; bit7_array_t bit7_array; bit121_array_t bit121_array; + logic1_array_t logic1_array; logic7_array_t logic7_array; logic121_array_t logic121_array; pack_struct_array_t pack_struct_array; @@ -712,6 +753,13 @@ module t; i_string_2d(string_array[1]); i_string_3d(string_array); + `SET_VALUES(bit1_array); + i_bit1_0d(bit1_array[3][2][1]); + i_bit1_1d(bit1_array[2][1]); + i_bit1_2d(bit1_array[1]); + i_bit1_3d(bit1_array); + + `SET_VALUES(bit7_array); i_bit7_0d(bit7_array[3][2][1]); i_bit7_1d(bit7_array[2][1]); @@ -724,6 +772,12 @@ module t; i_bit121_2d(bit121_array[1]); i_bit121_3d(bit121_array); + `SET_VALUES(logic1_array); + i_logic1_0d(logic1_array[3][2][1]); + i_logic1_1d(logic1_array[2][1]); + i_logic1_2d(logic1_array[1]); + i_logic1_3d(logic1_array); + `SET_VALUES(logic7_array); i_logic7_0d(logic7_array[3][2][1]); i_logic7_1d(logic7_array[2][1]); diff --git a/test_regress/t/t_dpi_arg_input_unpack__Dpi.out b/test_regress/t/t_dpi_arg_input_unpack__Dpi.out index dd53f2061..f6eee80e8 100644 --- a/test_regress/t/t_dpi_arg_input_unpack__Dpi.out +++ b/test_regress/t/t_dpi_arg_input_unpack__Dpi.out @@ -10,304 +10,174 @@ #ifdef __cplusplus extern "C" { #endif - - - // DPI EXPORTS - // DPI export at t/t_dpi_arg_input_unpack.v:501:18 - extern void e_bit121_0d(const svBitVecVal* val); - // DPI export at t/t_dpi_arg_input_unpack.v:502:18 - extern void e_bit121_1d(const svBitVecVal* val); - // DPI export at t/t_dpi_arg_input_unpack.v:503:18 - extern void e_bit121_2d(const svBitVecVal* val); - // DPI export at t/t_dpi_arg_input_unpack.v:504:18 - extern void e_bit121_3d(const svBitVecVal* val); - // DPI export at t/t_dpi_arg_input_unpack.v:496:18 - extern void e_bit7_0d(const svBitVecVal* val); - // DPI export at t/t_dpi_arg_input_unpack.v:497:18 - extern void e_bit7_1d(const svBitVecVal* val); - // DPI export at t/t_dpi_arg_input_unpack.v:498:18 - extern void e_bit7_2d(const svBitVecVal* val); - // DPI export at t/t_dpi_arg_input_unpack.v:499:18 - extern void e_bit7_3d(const svBitVecVal* val); - // DPI export at t/t_dpi_arg_input_unpack.v:332:18 - extern void e_byte_0d(char val); - // DPI export at t/t_dpi_arg_input_unpack.v:333:18 - extern void e_byte_1d(const char* val); - // DPI export at t/t_dpi_arg_input_unpack.v:334:18 - extern void e_byte_2d(const char* val); - // DPI export at t/t_dpi_arg_input_unpack.v:335:18 - extern void e_byte_3d(const char* val); - // DPI export at t/t_dpi_arg_input_unpack.v:337:18 - extern void e_byte_unsigned_0d(unsigned char val); - // DPI export at t/t_dpi_arg_input_unpack.v:338:18 - extern void e_byte_unsigned_1d(const unsigned char* val); - // DPI export at t/t_dpi_arg_input_unpack.v:339:18 - extern void e_byte_unsigned_2d(const unsigned char* val); - // DPI export at t/t_dpi_arg_input_unpack.v:340:18 - extern void e_byte_unsigned_3d(const unsigned char* val); - // DPI export at t/t_dpi_arg_input_unpack.v:398:18 - extern void e_chandle_0d(void* val); - // DPI export at t/t_dpi_arg_input_unpack.v:404:18 - extern void e_chandle_1d(const void** val); - // DPI export at t/t_dpi_arg_input_unpack.v:414:18 - extern void e_chandle_2d(const void** val); - // DPI export at t/t_dpi_arg_input_unpack.v:428:18 - extern void e_chandle_3d(const void** val); - // DPI export at t/t_dpi_arg_input_unpack.v:352:18 - extern void e_int_0d(int val); - // DPI export at t/t_dpi_arg_input_unpack.v:353:18 - extern void e_int_1d(const int* val); - // DPI export at t/t_dpi_arg_input_unpack.v:354:18 - extern void e_int_2d(const int* val); - // DPI export at t/t_dpi_arg_input_unpack.v:355:18 - extern void e_int_3d(const int* val); - // DPI export at t/t_dpi_arg_input_unpack.v:357:18 - extern void e_int_unsigned_0d(unsigned int val); - // DPI export at t/t_dpi_arg_input_unpack.v:358:18 - extern void e_int_unsigned_1d(const unsigned int* val); - // DPI export at t/t_dpi_arg_input_unpack.v:359:18 - extern void e_int_unsigned_2d(const unsigned int* val); - // DPI export at t/t_dpi_arg_input_unpack.v:360:18 - extern void e_int_unsigned_3d(const unsigned int* val); - // DPI export at t/t_dpi_arg_input_unpack.v:380:18 - extern void e_integer_0d(const svLogicVecVal* val); - // DPI export at t/t_dpi_arg_input_unpack.v:381:18 - extern void e_integer_1d(const svLogicVecVal* val); - // DPI export at t/t_dpi_arg_input_unpack.v:382:18 - extern void e_integer_2d(const svLogicVecVal* val); - // DPI export at t/t_dpi_arg_input_unpack.v:383:18 - extern void e_integer_3d(const svLogicVecVal* val); - // DPI export at t/t_dpi_arg_input_unpack.v:511:18 - extern void e_logic121_0d(const svLogicVecVal* val); - // DPI export at t/t_dpi_arg_input_unpack.v:512:18 - extern void e_logic121_1d(const svLogicVecVal* val); - // DPI export at t/t_dpi_arg_input_unpack.v:513:18 - extern void e_logic121_2d(const svLogicVecVal* val); - // DPI export at t/t_dpi_arg_input_unpack.v:514:18 - extern void e_logic121_3d(const svLogicVecVal* val); - // DPI export at t/t_dpi_arg_input_unpack.v:506:18 - extern void e_logic7_0d(const svLogicVecVal* val); - // DPI export at t/t_dpi_arg_input_unpack.v:507:18 - extern void e_logic7_1d(const svLogicVecVal* val); - // DPI export at t/t_dpi_arg_input_unpack.v:508:18 - extern void e_logic7_2d(const svLogicVecVal* val); - // DPI export at t/t_dpi_arg_input_unpack.v:509:18 - extern void e_logic7_3d(const svLogicVecVal* val); - // DPI export at t/t_dpi_arg_input_unpack.v:362:18 - extern void e_longint_0d(long long val); - // DPI export at t/t_dpi_arg_input_unpack.v:363:18 - extern void e_longint_1d(const long long* val); - // DPI export at t/t_dpi_arg_input_unpack.v:364:18 - extern void e_longint_2d(const long long* val); - // DPI export at t/t_dpi_arg_input_unpack.v:365:18 - extern void e_longint_3d(const long long* val); - // DPI export at t/t_dpi_arg_input_unpack.v:367:18 - extern void e_longint_unsigned_0d(unsigned long long val); - // DPI export at t/t_dpi_arg_input_unpack.v:368:18 - extern void e_longint_unsigned_1d(const unsigned long long* val); - // DPI export at t/t_dpi_arg_input_unpack.v:369:18 - extern void e_longint_unsigned_2d(const unsigned long long* val); - // DPI export at t/t_dpi_arg_input_unpack.v:370:18 - extern void e_longint_unsigned_3d(const unsigned long long* val); - // DPI export at t/t_dpi_arg_input_unpack.v:516:18 - extern void e_pack_struct_0d(const svLogicVecVal* val); - // DPI export at t/t_dpi_arg_input_unpack.v:517:18 - extern void e_pack_struct_1d(const svLogicVecVal* val); - // DPI export at t/t_dpi_arg_input_unpack.v:518:18 - extern void e_pack_struct_2d(const svLogicVecVal* val); - // DPI export at t/t_dpi_arg_input_unpack.v:519:18 - extern void e_pack_struct_3d(const svLogicVecVal* val); - // DPI export at t/t_dpi_arg_input_unpack.v:386:18 - extern void e_real_0d(double val); - // DPI export at t/t_dpi_arg_input_unpack.v:387:18 - extern void e_real_1d(const double* val); - // DPI export at t/t_dpi_arg_input_unpack.v:388:18 - extern void e_real_2d(const double* val); - // DPI export at t/t_dpi_arg_input_unpack.v:389:18 - extern void e_real_3d(const double* val); - // DPI export at t/t_dpi_arg_input_unpack.v:342:18 - extern void e_shortint_0d(short val); - // DPI export at t/t_dpi_arg_input_unpack.v:343:18 - extern void e_shortint_1d(const short* val); - // DPI export at t/t_dpi_arg_input_unpack.v:344:18 - extern void e_shortint_2d(const short* val); - // DPI export at t/t_dpi_arg_input_unpack.v:345:18 - extern void e_shortint_3d(const short* val); - // DPI export at t/t_dpi_arg_input_unpack.v:347:18 - extern void e_shortint_unsigned_0d(unsigned short val); - // DPI export at t/t_dpi_arg_input_unpack.v:348:18 - extern void e_shortint_unsigned_1d(const unsigned short* val); - // DPI export at t/t_dpi_arg_input_unpack.v:349:18 - extern void e_shortint_unsigned_2d(const unsigned short* val); - // DPI export at t/t_dpi_arg_input_unpack.v:350:18 - extern void e_shortint_unsigned_3d(const unsigned short* val); - // DPI export at t/t_dpi_arg_input_unpack.v:447:18 - extern void e_string_0d(const char* val); - // DPI export at t/t_dpi_arg_input_unpack.v:453:18 - extern void e_string_1d(const char** val); - // DPI export at t/t_dpi_arg_input_unpack.v:463:18 - extern void e_string_2d(const char** val); - // DPI export at t/t_dpi_arg_input_unpack.v:477:18 - extern void e_string_3d(const char** val); - // DPI export at t/t_dpi_arg_input_unpack.v:373:18 - extern void e_time_0d(const svLogicVecVal* val); - // DPI export at t/t_dpi_arg_input_unpack.v:374:18 - extern void e_time_1d(const svLogicVecVal* val); - // DPI export at t/t_dpi_arg_input_unpack.v:375:18 - extern void e_time_2d(const svLogicVecVal* val); - // DPI export at t/t_dpi_arg_input_unpack.v:376:18 - extern void e_time_3d(const svLogicVecVal* val); - - // DPI IMPORTS - // DPI import at t/t_dpi_arg_input_unpack.v:576:41 - extern void check_exports(); - // DPI import at t/t_dpi_arg_input_unpack.v:106:36 - extern void* get_non_null(); - // DPI import at t/t_dpi_arg_input_unpack.v:189:33 - extern void i_bit121_0d(const svBitVecVal* val); - // DPI import at t/t_dpi_arg_input_unpack.v:190:33 - extern void i_bit121_1d(const svBitVecVal* val); - // DPI import at t/t_dpi_arg_input_unpack.v:191:33 - extern void i_bit121_2d(const svBitVecVal* val); - // DPI import at t/t_dpi_arg_input_unpack.v:192:33 - extern void i_bit121_3d(const svBitVecVal* val); - // DPI import at t/t_dpi_arg_input_unpack.v:184:33 - extern void i_bit7_0d(const svBitVecVal* val); - // DPI import at t/t_dpi_arg_input_unpack.v:185:33 - extern void i_bit7_1d(const svBitVecVal* val); - // DPI import at t/t_dpi_arg_input_unpack.v:186:33 - extern void i_bit7_2d(const svBitVecVal* val); - // DPI import at t/t_dpi_arg_input_unpack.v:187:33 - extern void i_bit7_3d(const svBitVecVal* val); - // DPI import at t/t_dpi_arg_input_unpack.v:108:33 - extern void i_byte_0d(char val); - // DPI import at t/t_dpi_arg_input_unpack.v:109:33 - extern void i_byte_1d(const char* val); - // DPI import at t/t_dpi_arg_input_unpack.v:110:33 - extern void i_byte_2d(const char* val); - // DPI import at t/t_dpi_arg_input_unpack.v:111:33 - extern void i_byte_3d(const char* val); - // DPI import at t/t_dpi_arg_input_unpack.v:113:33 - extern void i_byte_unsigned_0d(unsigned char val); - // DPI import at t/t_dpi_arg_input_unpack.v:114:33 - extern void i_byte_unsigned_1d(const unsigned char* val); - // DPI import at t/t_dpi_arg_input_unpack.v:115:33 - extern void i_byte_unsigned_2d(const unsigned char* val); - // DPI import at t/t_dpi_arg_input_unpack.v:116:33 - extern void i_byte_unsigned_3d(const unsigned char* val); - // DPI import at t/t_dpi_arg_input_unpack.v:174:33 - extern void i_chandle_0d(void* val); - // DPI import at t/t_dpi_arg_input_unpack.v:175:33 - extern void i_chandle_1d(const void** val); - // DPI import at t/t_dpi_arg_input_unpack.v:176:33 - extern void i_chandle_2d(const void** val); - // DPI import at t/t_dpi_arg_input_unpack.v:177:33 - extern void i_chandle_3d(const void** val); - // DPI import at t/t_dpi_arg_input_unpack.v:128:33 - extern void i_int_0d(int val); - // DPI import at t/t_dpi_arg_input_unpack.v:129:33 - extern void i_int_1d(const int* val); - // DPI import at t/t_dpi_arg_input_unpack.v:130:33 - extern void i_int_2d(const int* val); - // DPI import at t/t_dpi_arg_input_unpack.v:131:33 - extern void i_int_3d(const int* val); - // DPI import at t/t_dpi_arg_input_unpack.v:133:33 - extern void i_int_unsigned_0d(unsigned int val); - // DPI import at t/t_dpi_arg_input_unpack.v:134:33 - extern void i_int_unsigned_1d(const unsigned int* val); - // DPI import at t/t_dpi_arg_input_unpack.v:135:33 - extern void i_int_unsigned_2d(const unsigned int* val); - // DPI import at t/t_dpi_arg_input_unpack.v:136:33 - extern void i_int_unsigned_3d(const unsigned int* val); - // DPI import at t/t_dpi_arg_input_unpack.v:156:33 - extern void i_integer_0d(const svLogicVecVal* val); - // DPI import at t/t_dpi_arg_input_unpack.v:157:33 - extern void i_integer_1d(const svLogicVecVal* val); - // DPI import at t/t_dpi_arg_input_unpack.v:158:33 - extern void i_integer_2d(const svLogicVecVal* val); - // DPI import at t/t_dpi_arg_input_unpack.v:159:33 - extern void i_integer_3d(const svLogicVecVal* val); - // DPI import at t/t_dpi_arg_input_unpack.v:199:33 - extern void i_logic121_0d(const svLogicVecVal* val); - // DPI import at t/t_dpi_arg_input_unpack.v:200:33 - extern void i_logic121_1d(const svLogicVecVal* val); - // DPI import at t/t_dpi_arg_input_unpack.v:201:33 - extern void i_logic121_2d(const svLogicVecVal* val); - // DPI import at t/t_dpi_arg_input_unpack.v:202:33 - extern void i_logic121_3d(const svLogicVecVal* val); - // DPI import at t/t_dpi_arg_input_unpack.v:194:33 - extern void i_logic7_0d(const svLogicVecVal* val); - // DPI import at t/t_dpi_arg_input_unpack.v:195:33 - extern void i_logic7_1d(const svLogicVecVal* val); - // DPI import at t/t_dpi_arg_input_unpack.v:196:33 - extern void i_logic7_2d(const svLogicVecVal* val); - // DPI import at t/t_dpi_arg_input_unpack.v:197:33 - extern void i_logic7_3d(const svLogicVecVal* val); - // DPI import at t/t_dpi_arg_input_unpack.v:138:33 - extern void i_longint_0d(long long val); - // DPI import at t/t_dpi_arg_input_unpack.v:139:33 - extern void i_longint_1d(const long long* val); - // DPI import at t/t_dpi_arg_input_unpack.v:140:33 - extern void i_longint_2d(const long long* val); - // DPI import at t/t_dpi_arg_input_unpack.v:141:33 - extern void i_longint_3d(const long long* val); - // DPI import at t/t_dpi_arg_input_unpack.v:143:33 - extern void i_longint_unsigned_0d(unsigned long long val); - // DPI import at t/t_dpi_arg_input_unpack.v:144:33 - extern void i_longint_unsigned_1d(const unsigned long long* val); - // DPI import at t/t_dpi_arg_input_unpack.v:145:33 - extern void i_longint_unsigned_2d(const unsigned long long* val); - // DPI import at t/t_dpi_arg_input_unpack.v:146:33 - extern void i_longint_unsigned_3d(const unsigned long long* val); - // DPI import at t/t_dpi_arg_input_unpack.v:204:33 - extern void i_pack_struct_0d(const svLogicVecVal* val); - // DPI import at t/t_dpi_arg_input_unpack.v:205:33 - extern void i_pack_struct_1d(const svLogicVecVal* val); - // DPI import at t/t_dpi_arg_input_unpack.v:206:33 - extern void i_pack_struct_2d(const svLogicVecVal* val); - // DPI import at t/t_dpi_arg_input_unpack.v:207:33 - extern void i_pack_struct_3d(const svLogicVecVal* val); - // DPI import at t/t_dpi_arg_input_unpack.v:162:33 - extern void i_real_0d(double val); - // DPI import at t/t_dpi_arg_input_unpack.v:163:33 - extern void i_real_1d(const double* val); - // DPI import at t/t_dpi_arg_input_unpack.v:164:33 - extern void i_real_2d(const double* val); - // DPI import at t/t_dpi_arg_input_unpack.v:165:33 - extern void i_real_3d(const double* val); - // DPI import at t/t_dpi_arg_input_unpack.v:118:33 - extern void i_shortint_0d(short val); - // DPI import at t/t_dpi_arg_input_unpack.v:119:33 - extern void i_shortint_1d(const short* val); - // DPI import at t/t_dpi_arg_input_unpack.v:120:33 - extern void i_shortint_2d(const short* val); - // DPI import at t/t_dpi_arg_input_unpack.v:121:33 - extern void i_shortint_3d(const short* val); - // DPI import at t/t_dpi_arg_input_unpack.v:123:33 - extern void i_shortint_unsigned_0d(unsigned short val); - // DPI import at t/t_dpi_arg_input_unpack.v:124:33 - extern void i_shortint_unsigned_1d(const unsigned short* val); - // DPI import at t/t_dpi_arg_input_unpack.v:125:33 - extern void i_shortint_unsigned_2d(const unsigned short* val); - // DPI import at t/t_dpi_arg_input_unpack.v:126:33 - extern void i_shortint_unsigned_3d(const unsigned short* val); - // DPI import at t/t_dpi_arg_input_unpack.v:179:33 - extern void i_string_0d(const char* val); - // DPI import at t/t_dpi_arg_input_unpack.v:180:33 - extern void i_string_1d(const char** val); - // DPI import at t/t_dpi_arg_input_unpack.v:181:33 - extern void i_string_2d(const char** val); - // DPI import at t/t_dpi_arg_input_unpack.v:182:33 - extern void i_string_3d(const char** val); - // DPI import at t/t_dpi_arg_input_unpack.v:149:33 - extern void i_time_0d(const svLogicVecVal* val); - // DPI import at t/t_dpi_arg_input_unpack.v:150:33 - extern void i_time_1d(const svLogicVecVal* val); - // DPI import at t/t_dpi_arg_input_unpack.v:151:33 - extern void i_time_2d(const svLogicVecVal* val); - // DPI import at t/t_dpi_arg_input_unpack.v:152:33 - extern void i_time_3d(const svLogicVecVal* val); - + + + // DPI EXPORTS + extern void e_bit121_0d(const svBitVecVal* val); + extern void e_bit121_1d(const svBitVecVal* val); + extern void e_bit121_2d(const svBitVecVal* val); + extern void e_bit121_3d(const svBitVecVal* val); + extern void e_bit1_0d(svBit val); + extern void e_bit1_1d(const svBit* val); + extern void e_bit1_2d(const svBit* val); + extern void e_bit1_3d(const svBit* val); + extern void e_bit7_0d(const svBitVecVal* val); + extern void e_bit7_1d(const svBitVecVal* val); + extern void e_bit7_2d(const svBitVecVal* val); + extern void e_bit7_3d(const svBitVecVal* val); + extern void e_byte_0d(char val); + extern void e_byte_1d(const char* val); + extern void e_byte_2d(const char* val); + extern void e_byte_3d(const char* val); + extern void e_byte_unsigned_0d(unsigned char val); + extern void e_byte_unsigned_1d(const unsigned char* val); + extern void e_byte_unsigned_2d(const unsigned char* val); + extern void e_byte_unsigned_3d(const unsigned char* val); + extern void e_chandle_0d(void* val); + extern void e_chandle_1d(const void** val); + extern void e_chandle_2d(const void** val); + extern void e_chandle_3d(const void** val); + extern void e_int_0d(int val); + extern void e_int_1d(const int* val); + extern void e_int_2d(const int* val); + extern void e_int_3d(const int* val); + extern void e_int_unsigned_0d(unsigned int val); + extern void e_int_unsigned_1d(const unsigned int* val); + extern void e_int_unsigned_2d(const unsigned int* val); + extern void e_int_unsigned_3d(const unsigned int* val); + extern void e_integer_0d(const svLogicVecVal* val); + extern void e_integer_1d(const svLogicVecVal* val); + extern void e_integer_2d(const svLogicVecVal* val); + extern void e_integer_3d(const svLogicVecVal* val); + extern void e_logic121_0d(const svLogicVecVal* val); + extern void e_logic121_1d(const svLogicVecVal* val); + extern void e_logic121_2d(const svLogicVecVal* val); + extern void e_logic121_3d(const svLogicVecVal* val); + extern void e_logic1_0d(svLogic val); + extern void e_logic1_1d(const svLogic* val); + extern void e_logic1_2d(const svLogic* val); + extern void e_logic1_3d(const svLogic* val); + extern void e_logic7_0d(const svLogicVecVal* val); + extern void e_logic7_1d(const svLogicVecVal* val); + extern void e_logic7_2d(const svLogicVecVal* val); + extern void e_logic7_3d(const svLogicVecVal* val); + extern void e_longint_0d(long long val); + extern void e_longint_1d(const long long* val); + extern void e_longint_2d(const long long* val); + extern void e_longint_3d(const long long* val); + extern void e_longint_unsigned_0d(unsigned long long val); + extern void e_longint_unsigned_1d(const unsigned long long* val); + extern void e_longint_unsigned_2d(const unsigned long long* val); + extern void e_longint_unsigned_3d(const unsigned long long* val); + extern void e_pack_struct_0d(const svLogicVecVal* val); + extern void e_pack_struct_1d(const svLogicVecVal* val); + extern void e_pack_struct_2d(const svLogicVecVal* val); + extern void e_pack_struct_3d(const svLogicVecVal* val); + extern void e_real_0d(double val); + extern void e_real_1d(const double* val); + extern void e_real_2d(const double* val); + extern void e_real_3d(const double* val); + extern void e_shortint_0d(short val); + extern void e_shortint_1d(const short* val); + extern void e_shortint_2d(const short* val); + extern void e_shortint_3d(const short* val); + extern void e_shortint_unsigned_0d(unsigned short val); + extern void e_shortint_unsigned_1d(const unsigned short* val); + extern void e_shortint_unsigned_2d(const unsigned short* val); + extern void e_shortint_unsigned_3d(const unsigned short* val); + extern void e_string_0d(const char* val); + extern void e_string_1d(const char** val); + extern void e_string_2d(const char** val); + extern void e_string_3d(const char** val); + extern void e_time_0d(const svLogicVecVal* val); + extern void e_time_1d(const svLogicVecVal* val); + extern void e_time_2d(const svLogicVecVal* val); + extern void e_time_3d(const svLogicVecVal* val); + + // DPI IMPORTS + extern void check_exports(); + extern void* get_non_null(); + extern void i_bit121_0d(const svBitVecVal* val); + extern void i_bit121_1d(const svBitVecVal* val); + extern void i_bit121_2d(const svBitVecVal* val); + extern void i_bit121_3d(const svBitVecVal* val); + extern void i_bit1_0d(svBit val); + extern void i_bit1_1d(const svBit* val); + extern void i_bit1_2d(const svBit* val); + extern void i_bit1_3d(const svBit* val); + extern void i_bit7_0d(const svBitVecVal* val); + extern void i_bit7_1d(const svBitVecVal* val); + extern void i_bit7_2d(const svBitVecVal* val); + extern void i_bit7_3d(const svBitVecVal* val); + extern void i_byte_0d(char val); + extern void i_byte_1d(const char* val); + extern void i_byte_2d(const char* val); + extern void i_byte_3d(const char* val); + extern void i_byte_unsigned_0d(unsigned char val); + extern void i_byte_unsigned_1d(const unsigned char* val); + extern void i_byte_unsigned_2d(const unsigned char* val); + extern void i_byte_unsigned_3d(const unsigned char* val); + extern void i_chandle_0d(void* val); + extern void i_chandle_1d(const void** val); + extern void i_chandle_2d(const void** val); + extern void i_chandle_3d(const void** val); + extern void i_int_0d(int val); + extern void i_int_1d(const int* val); + extern void i_int_2d(const int* val); + extern void i_int_3d(const int* val); + extern void i_int_unsigned_0d(unsigned int val); + extern void i_int_unsigned_1d(const unsigned int* val); + extern void i_int_unsigned_2d(const unsigned int* val); + extern void i_int_unsigned_3d(const unsigned int* val); + extern void i_integer_0d(const svLogicVecVal* val); + extern void i_integer_1d(const svLogicVecVal* val); + extern void i_integer_2d(const svLogicVecVal* val); + extern void i_integer_3d(const svLogicVecVal* val); + extern void i_logic121_0d(const svLogicVecVal* val); + extern void i_logic121_1d(const svLogicVecVal* val); + extern void i_logic121_2d(const svLogicVecVal* val); + extern void i_logic121_3d(const svLogicVecVal* val); + extern void i_logic1_0d(svLogic val); + extern void i_logic1_1d(const svLogic* val); + extern void i_logic1_2d(const svLogic* val); + extern void i_logic1_3d(const svLogic* val); + extern void i_logic7_0d(const svLogicVecVal* val); + extern void i_logic7_1d(const svLogicVecVal* val); + extern void i_logic7_2d(const svLogicVecVal* val); + extern void i_logic7_3d(const svLogicVecVal* val); + extern void i_longint_0d(long long val); + extern void i_longint_1d(const long long* val); + extern void i_longint_2d(const long long* val); + extern void i_longint_3d(const long long* val); + extern void i_longint_unsigned_0d(unsigned long long val); + extern void i_longint_unsigned_1d(const unsigned long long* val); + extern void i_longint_unsigned_2d(const unsigned long long* val); + extern void i_longint_unsigned_3d(const unsigned long long* val); + extern void i_pack_struct_0d(const svLogicVecVal* val); + extern void i_pack_struct_1d(const svLogicVecVal* val); + extern void i_pack_struct_2d(const svLogicVecVal* val); + extern void i_pack_struct_3d(const svLogicVecVal* val); + extern void i_real_0d(double val); + extern void i_real_1d(const double* val); + extern void i_real_2d(const double* val); + extern void i_real_3d(const double* val); + extern void i_shortint_0d(short val); + extern void i_shortint_1d(const short* val); + extern void i_shortint_2d(const short* val); + extern void i_shortint_3d(const short* val); + extern void i_shortint_unsigned_0d(unsigned short val); + extern void i_shortint_unsigned_1d(const unsigned short* val); + extern void i_shortint_unsigned_2d(const unsigned short* val); + extern void i_shortint_unsigned_3d(const unsigned short* val); + extern void i_string_0d(const char* val); + extern void i_string_1d(const char** val); + extern void i_string_2d(const char** val); + extern void i_string_3d(const char** val); + extern void i_time_0d(const svLogicVecVal* val); + extern void i_time_1d(const svLogicVecVal* val); + extern void i_time_2d(const svLogicVecVal* val); + extern void i_time_3d(const svLogicVecVal* val); + #ifdef __cplusplus } #endif diff --git a/test_regress/t/t_dpi_arg_output_type.pl b/test_regress/t/t_dpi_arg_output_type.pl index b611513a8..d469bfc8a 100755 --- a/test_regress/t/t_dpi_arg_output_type.pl +++ b/test_regress/t/t_dpi_arg_output_type.pl @@ -20,7 +20,8 @@ if ($Self->{nc}) { compile( v_flags2 => ["t/t_dpi_arg_output_type.cpp"], - verilator_flags2 => ["-Wall -Wno-DECLFILENAME"], + # --no-decoration so .out file doesn't comment on source lines + verilator_flags2 => ["-Wall -Wno-DECLFILENAME --no-decoration"], # NC: Gdd the obj_dir to the C include path nc_flags2 => ["+ncscargs+-I$Self->{obj_dir}"], # ModelSim: Generate DPI header, add obj_dir to the C include path diff --git a/test_regress/t/t_dpi_arg_output_type__Dpi.out b/test_regress/t/t_dpi_arg_output_type__Dpi.out index 5f24130ff..f2bc7f4c6 100644 --- a/test_regress/t/t_dpi_arg_output_type__Dpi.out +++ b/test_regress/t/t_dpi_arg_output_type__Dpi.out @@ -10,278 +10,145 @@ #ifdef __cplusplus extern "C" { #endif - - - // DPI EXPORTS - // DPI export at t/t_dpi_arg_output_type.v:521:18 - extern void e_array_2_state_1(svBitVecVal* o); - // DPI export at t/t_dpi_arg_output_type.v:556:18 - extern void e_array_2_state_128(svBitVecVal* o); - // DPI export at t/t_dpi_arg_output_type.v:528:18 - extern void e_array_2_state_32(svBitVecVal* o); - // DPI export at t/t_dpi_arg_output_type.v:535:18 - extern void e_array_2_state_33(svBitVecVal* o); - // DPI export at t/t_dpi_arg_output_type.v:542:18 - extern void e_array_2_state_64(svBitVecVal* o); - // DPI export at t/t_dpi_arg_output_type.v:549:18 - extern void e_array_2_state_65(svBitVecVal* o); - // DPI export at t/t_dpi_arg_output_type.v:650:18 - extern void e_array_4_state_1(svLogicVecVal* o); - // DPI export at t/t_dpi_arg_output_type.v:685:18 - extern void e_array_4_state_128(svLogicVecVal* o); - // DPI export at t/t_dpi_arg_output_type.v:657:18 - extern void e_array_4_state_32(svLogicVecVal* o); - // DPI export at t/t_dpi_arg_output_type.v:664:18 - extern void e_array_4_state_33(svLogicVecVal* o); - // DPI export at t/t_dpi_arg_output_type.v:671:18 - extern void e_array_4_state_64(svLogicVecVal* o); - // DPI export at t/t_dpi_arg_output_type.v:678:18 - extern void e_array_4_state_65(svLogicVecVal* o); - // DPI export at t/t_dpi_arg_output_type.v:399:18 - extern void e_bit(svBit* o); - // DPI export at t/t_dpi_arg_output_type.v:506:18 - extern void e_bit_t(svBit* o); - // DPI export at t/t_dpi_arg_output_type.v:307:18 - extern void e_byte(char* o); - // DPI export at t/t_dpi_arg_output_type.v:414:18 - extern void e_byte_t(char* o); - // DPI export at t/t_dpi_arg_output_type.v:313:18 - extern void e_byte_unsigned(unsigned char* o); - // DPI export at t/t_dpi_arg_output_type.v:420:18 - extern void e_byte_unsigned_t(unsigned char* o); - // DPI export at t/t_dpi_arg_output_type.v:385:18 - extern void e_chandle(void** o); - // DPI export at t/t_dpi_arg_output_type.v:492:18 - extern void e_chandle_t(void** o); - // DPI export at t/t_dpi_arg_output_type.v:331:18 - extern void e_int(int* o); - // DPI export at t/t_dpi_arg_output_type.v:438:18 - extern void e_int_t(int* o); - // DPI export at t/t_dpi_arg_output_type.v:337:18 - extern void e_int_unsigned(unsigned int* o); - // DPI export at t/t_dpi_arg_output_type.v:444:18 - extern void e_int_unsigned_t(unsigned int* o); - // DPI export at t/t_dpi_arg_output_type.v:364:18 - extern void e_integer(svLogicVecVal* o); - // DPI export at t/t_dpi_arg_output_type.v:471:18 - extern void e_integer_t(svLogicVecVal* o); - // DPI export at t/t_dpi_arg_output_type.v:406:18 - extern void e_logic(svLogic* o); - // DPI export at t/t_dpi_arg_output_type.v:513:18 - extern void e_logic_t(svLogic* o); - // DPI export at t/t_dpi_arg_output_type.v:343:18 - extern void e_longint(long long* o); - // DPI export at t/t_dpi_arg_output_type.v:450:18 - extern void e_longint_t(long long* o); - // DPI export at t/t_dpi_arg_output_type.v:349:18 - extern void e_longint_unsigned(unsigned long long* o); - // DPI export at t/t_dpi_arg_output_type.v:456:18 - extern void e_longint_unsigned_t(unsigned long long* o); - // DPI export at t/t_dpi_arg_output_type.v:371:18 - extern void e_real(double* o); - // DPI export at t/t_dpi_arg_output_type.v:478:18 - extern void e_real_t(double* o); - // DPI export at t/t_dpi_arg_output_type.v:319:18 - extern void e_shortint(short* o); - // DPI export at t/t_dpi_arg_output_type.v:426:18 - extern void e_shortint_t(short* o); - // DPI export at t/t_dpi_arg_output_type.v:325:18 - extern void e_shortint_unsigned(unsigned short* o); - // DPI export at t/t_dpi_arg_output_type.v:432:18 - extern void e_shortint_unsigned_t(unsigned short* o); - // DPI export at t/t_dpi_arg_output_type.v:392:18 - extern void e_string(const char** o); - // DPI export at t/t_dpi_arg_output_type.v:499:18 - extern void e_string_t(const char** o); - // DPI export at t/t_dpi_arg_output_type.v:564:18 - extern void e_struct_2_state_1(svBitVecVal* o); - // DPI export at t/t_dpi_arg_output_type.v:599:18 - extern void e_struct_2_state_128(svBitVecVal* o); - // DPI export at t/t_dpi_arg_output_type.v:571:18 - extern void e_struct_2_state_32(svBitVecVal* o); - // DPI export at t/t_dpi_arg_output_type.v:578:18 - extern void e_struct_2_state_33(svBitVecVal* o); - // DPI export at t/t_dpi_arg_output_type.v:585:18 - extern void e_struct_2_state_64(svBitVecVal* o); - // DPI export at t/t_dpi_arg_output_type.v:592:18 - extern void e_struct_2_state_65(svBitVecVal* o); - // DPI export at t/t_dpi_arg_output_type.v:693:18 - extern void e_struct_4_state_1(svLogicVecVal* o); - // DPI export at t/t_dpi_arg_output_type.v:728:18 - extern void e_struct_4_state_128(svLogicVecVal* o); - // DPI export at t/t_dpi_arg_output_type.v:700:18 - extern void e_struct_4_state_32(svLogicVecVal* o); - // DPI export at t/t_dpi_arg_output_type.v:707:18 - extern void e_struct_4_state_33(svLogicVecVal* o); - // DPI export at t/t_dpi_arg_output_type.v:714:18 - extern void e_struct_4_state_64(svLogicVecVal* o); - // DPI export at t/t_dpi_arg_output_type.v:721:18 - extern void e_struct_4_state_65(svLogicVecVal* o); - // DPI export at t/t_dpi_arg_output_type.v:356:18 - extern void e_time(svLogicVecVal* o); - // DPI export at t/t_dpi_arg_output_type.v:463:18 - extern void e_time_t(svLogicVecVal* o); - // DPI export at t/t_dpi_arg_output_type.v:607:18 - extern void e_union_2_state_1(svBitVecVal* o); - // DPI export at t/t_dpi_arg_output_type.v:642:18 - extern void e_union_2_state_128(svBitVecVal* o); - // DPI export at t/t_dpi_arg_output_type.v:614:18 - extern void e_union_2_state_32(svBitVecVal* o); - // DPI export at t/t_dpi_arg_output_type.v:621:18 - extern void e_union_2_state_33(svBitVecVal* o); - // DPI export at t/t_dpi_arg_output_type.v:628:18 - extern void e_union_2_state_64(svBitVecVal* o); - // DPI export at t/t_dpi_arg_output_type.v:635:18 - extern void e_union_2_state_65(svBitVecVal* o); - // DPI export at t/t_dpi_arg_output_type.v:736:18 - extern void e_union_4_state_1(svLogicVecVal* o); - // DPI export at t/t_dpi_arg_output_type.v:771:18 - extern void e_union_4_state_128(svLogicVecVal* o); - // DPI export at t/t_dpi_arg_output_type.v:743:18 - extern void e_union_4_state_32(svLogicVecVal* o); - // DPI export at t/t_dpi_arg_output_type.v:750:18 - extern void e_union_4_state_33(svLogicVecVal* o); - // DPI export at t/t_dpi_arg_output_type.v:757:18 - extern void e_union_4_state_64(svLogicVecVal* o); - // DPI export at t/t_dpi_arg_output_type.v:764:18 - extern void e_union_4_state_65(svLogicVecVal* o); - - // DPI IMPORTS - // DPI import at t/t_dpi_arg_output_type.v:781:41 - extern void check_exports(); - // DPI import at t/t_dpi_arg_output_type.v:154:33 - extern void i_array_2_state_1(svBitVecVal* o); - // DPI import at t/t_dpi_arg_output_type.v:159:33 - extern void i_array_2_state_128(svBitVecVal* o); - // DPI import at t/t_dpi_arg_output_type.v:155:33 - extern void i_array_2_state_32(svBitVecVal* o); - // DPI import at t/t_dpi_arg_output_type.v:156:33 - extern void i_array_2_state_33(svBitVecVal* o); - // DPI import at t/t_dpi_arg_output_type.v:157:33 - extern void i_array_2_state_64(svBitVecVal* o); - // DPI import at t/t_dpi_arg_output_type.v:158:33 - extern void i_array_2_state_65(svBitVecVal* o); - // DPI import at t/t_dpi_arg_output_type.v:178:33 - extern void i_array_4_state_1(svLogicVecVal* o); - // DPI import at t/t_dpi_arg_output_type.v:183:33 - extern void i_array_4_state_128(svLogicVecVal* o); - // DPI import at t/t_dpi_arg_output_type.v:179:33 - extern void i_array_4_state_32(svLogicVecVal* o); - // DPI import at t/t_dpi_arg_output_type.v:180:33 - extern void i_array_4_state_33(svLogicVecVal* o); - // DPI import at t/t_dpi_arg_output_type.v:181:33 - extern void i_array_4_state_64(svLogicVecVal* o); - // DPI import at t/t_dpi_arg_output_type.v:182:33 - extern void i_array_4_state_65(svLogicVecVal* o); - // DPI import at t/t_dpi_arg_output_type.v:126:33 - extern void i_bit(svBit* o); - // DPI import at t/t_dpi_arg_output_type.v:150:33 - extern void i_bit_t(svBit* o); - // DPI import at t/t_dpi_arg_output_type.v:106:33 - extern void i_byte(char* o); - // DPI import at t/t_dpi_arg_output_type.v:130:33 - extern void i_byte_t(char* o); - // DPI import at t/t_dpi_arg_output_type.v:107:33 - extern void i_byte_unsigned(unsigned char* o); - // DPI import at t/t_dpi_arg_output_type.v:131:33 - extern void i_byte_unsigned_t(unsigned char* o); - // DPI import at t/t_dpi_arg_output_type.v:124:33 - extern void i_chandle(void** o); - // DPI import at t/t_dpi_arg_output_type.v:148:33 - extern void i_chandle_t(void** o); - // DPI import at t/t_dpi_arg_output_type.v:110:33 - extern void i_int(int* o); - // DPI import at t/t_dpi_arg_output_type.v:134:33 - extern void i_int_t(int* o); - // DPI import at t/t_dpi_arg_output_type.v:111:33 - extern void i_int_unsigned(unsigned int* o); - // DPI import at t/t_dpi_arg_output_type.v:135:33 - extern void i_int_unsigned_t(unsigned int* o); - // DPI import at t/t_dpi_arg_output_type.v:118:33 - extern void i_integer(svLogicVecVal* o); - // DPI import at t/t_dpi_arg_output_type.v:142:33 - extern void i_integer_t(svLogicVecVal* o); - // DPI import at t/t_dpi_arg_output_type.v:127:33 - extern void i_logic(svLogic* o); - // DPI import at t/t_dpi_arg_output_type.v:151:33 - extern void i_logic_t(svLogic* o); - // DPI import at t/t_dpi_arg_output_type.v:112:33 - extern void i_longint(long long* o); - // DPI import at t/t_dpi_arg_output_type.v:136:33 - extern void i_longint_t(long long* o); - // DPI import at t/t_dpi_arg_output_type.v:113:33 - extern void i_longint_unsigned(unsigned long long* o); - // DPI import at t/t_dpi_arg_output_type.v:137:33 - extern void i_longint_unsigned_t(unsigned long long* o); - // DPI import at t/t_dpi_arg_output_type.v:120:33 - extern void i_real(double* o); - // DPI import at t/t_dpi_arg_output_type.v:144:33 - extern void i_real_t(double* o); - // DPI import at t/t_dpi_arg_output_type.v:108:33 - extern void i_shortint(short* o); - // DPI import at t/t_dpi_arg_output_type.v:132:33 - extern void i_shortint_t(short* o); - // DPI import at t/t_dpi_arg_output_type.v:109:33 - extern void i_shortint_unsigned(unsigned short* o); - // DPI import at t/t_dpi_arg_output_type.v:133:33 - extern void i_shortint_unsigned_t(unsigned short* o); - // DPI import at t/t_dpi_arg_output_type.v:125:33 - extern void i_string(const char** o); - // DPI import at t/t_dpi_arg_output_type.v:149:33 - extern void i_string_t(const char** o); - // DPI import at t/t_dpi_arg_output_type.v:162:33 - extern void i_struct_2_state_1(svBitVecVal* o); - // DPI import at t/t_dpi_arg_output_type.v:167:33 - extern void i_struct_2_state_128(svBitVecVal* o); - // DPI import at t/t_dpi_arg_output_type.v:163:33 - extern void i_struct_2_state_32(svBitVecVal* o); - // DPI import at t/t_dpi_arg_output_type.v:164:33 - extern void i_struct_2_state_33(svBitVecVal* o); - // DPI import at t/t_dpi_arg_output_type.v:165:33 - extern void i_struct_2_state_64(svBitVecVal* o); - // DPI import at t/t_dpi_arg_output_type.v:166:33 - extern void i_struct_2_state_65(svBitVecVal* o); - // DPI import at t/t_dpi_arg_output_type.v:186:33 - extern void i_struct_4_state_1(svLogicVecVal* o); - // DPI import at t/t_dpi_arg_output_type.v:191:33 - extern void i_struct_4_state_128(svLogicVecVal* o); - // DPI import at t/t_dpi_arg_output_type.v:187:33 - extern void i_struct_4_state_32(svLogicVecVal* o); - // DPI import at t/t_dpi_arg_output_type.v:188:33 - extern void i_struct_4_state_33(svLogicVecVal* o); - // DPI import at t/t_dpi_arg_output_type.v:189:33 - extern void i_struct_4_state_64(svLogicVecVal* o); - // DPI import at t/t_dpi_arg_output_type.v:190:33 - extern void i_struct_4_state_65(svLogicVecVal* o); - // DPI import at t/t_dpi_arg_output_type.v:115:33 - extern void i_time(svLogicVecVal* o); - // DPI import at t/t_dpi_arg_output_type.v:139:33 - extern void i_time_t(svLogicVecVal* o); - // DPI import at t/t_dpi_arg_output_type.v:170:33 - extern void i_union_2_state_1(svBitVecVal* o); - // DPI import at t/t_dpi_arg_output_type.v:175:33 - extern void i_union_2_state_128(svBitVecVal* o); - // DPI import at t/t_dpi_arg_output_type.v:171:33 - extern void i_union_2_state_32(svBitVecVal* o); - // DPI import at t/t_dpi_arg_output_type.v:172:33 - extern void i_union_2_state_33(svBitVecVal* o); - // DPI import at t/t_dpi_arg_output_type.v:173:33 - extern void i_union_2_state_64(svBitVecVal* o); - // DPI import at t/t_dpi_arg_output_type.v:174:33 - extern void i_union_2_state_65(svBitVecVal* o); - // DPI import at t/t_dpi_arg_output_type.v:194:33 - extern void i_union_4_state_1(svLogicVecVal* o); - // DPI import at t/t_dpi_arg_output_type.v:199:33 - extern void i_union_4_state_128(svLogicVecVal* o); - // DPI import at t/t_dpi_arg_output_type.v:195:33 - extern void i_union_4_state_32(svLogicVecVal* o); - // DPI import at t/t_dpi_arg_output_type.v:196:33 - extern void i_union_4_state_33(svLogicVecVal* o); - // DPI import at t/t_dpi_arg_output_type.v:197:33 - extern void i_union_4_state_64(svLogicVecVal* o); - // DPI import at t/t_dpi_arg_output_type.v:198:33 - extern void i_union_4_state_65(svLogicVecVal* o); - + + + // DPI EXPORTS + extern void e_array_2_state_1(svBitVecVal* o); + extern void e_array_2_state_128(svBitVecVal* o); + extern void e_array_2_state_32(svBitVecVal* o); + extern void e_array_2_state_33(svBitVecVal* o); + extern void e_array_2_state_64(svBitVecVal* o); + extern void e_array_2_state_65(svBitVecVal* o); + extern void e_array_4_state_1(svLogicVecVal* o); + extern void e_array_4_state_128(svLogicVecVal* o); + extern void e_array_4_state_32(svLogicVecVal* o); + extern void e_array_4_state_33(svLogicVecVal* o); + extern void e_array_4_state_64(svLogicVecVal* o); + extern void e_array_4_state_65(svLogicVecVal* o); + extern void e_bit(svBit* o); + extern void e_bit_t(svBit* o); + extern void e_byte(char* o); + extern void e_byte_t(char* o); + extern void e_byte_unsigned(unsigned char* o); + extern void e_byte_unsigned_t(unsigned char* o); + extern void e_chandle(void** o); + extern void e_chandle_t(void** o); + extern void e_int(int* o); + extern void e_int_t(int* o); + extern void e_int_unsigned(unsigned int* o); + extern void e_int_unsigned_t(unsigned int* o); + extern void e_integer(svLogicVecVal* o); + extern void e_integer_t(svLogicVecVal* o); + extern void e_logic(svLogic* o); + extern void e_logic_t(svLogic* o); + extern void e_longint(long long* o); + extern void e_longint_t(long long* o); + extern void e_longint_unsigned(unsigned long long* o); + extern void e_longint_unsigned_t(unsigned long long* o); + extern void e_real(double* o); + extern void e_real_t(double* o); + extern void e_shortint(short* o); + extern void e_shortint_t(short* o); + extern void e_shortint_unsigned(unsigned short* o); + extern void e_shortint_unsigned_t(unsigned short* o); + extern void e_string(const char** o); + extern void e_string_t(const char** o); + extern void e_struct_2_state_1(svBitVecVal* o); + extern void e_struct_2_state_128(svBitVecVal* o); + extern void e_struct_2_state_32(svBitVecVal* o); + extern void e_struct_2_state_33(svBitVecVal* o); + extern void e_struct_2_state_64(svBitVecVal* o); + extern void e_struct_2_state_65(svBitVecVal* o); + extern void e_struct_4_state_1(svLogicVecVal* o); + extern void e_struct_4_state_128(svLogicVecVal* o); + extern void e_struct_4_state_32(svLogicVecVal* o); + extern void e_struct_4_state_33(svLogicVecVal* o); + extern void e_struct_4_state_64(svLogicVecVal* o); + extern void e_struct_4_state_65(svLogicVecVal* o); + extern void e_time(svLogicVecVal* o); + extern void e_time_t(svLogicVecVal* o); + extern void e_union_2_state_1(svBitVecVal* o); + extern void e_union_2_state_128(svBitVecVal* o); + extern void e_union_2_state_32(svBitVecVal* o); + extern void e_union_2_state_33(svBitVecVal* o); + extern void e_union_2_state_64(svBitVecVal* o); + extern void e_union_2_state_65(svBitVecVal* o); + extern void e_union_4_state_1(svLogicVecVal* o); + extern void e_union_4_state_128(svLogicVecVal* o); + extern void e_union_4_state_32(svLogicVecVal* o); + extern void e_union_4_state_33(svLogicVecVal* o); + extern void e_union_4_state_64(svLogicVecVal* o); + extern void e_union_4_state_65(svLogicVecVal* o); + + // DPI IMPORTS + extern void check_exports(); + extern void i_array_2_state_1(svBitVecVal* o); + extern void i_array_2_state_128(svBitVecVal* o); + extern void i_array_2_state_32(svBitVecVal* o); + extern void i_array_2_state_33(svBitVecVal* o); + extern void i_array_2_state_64(svBitVecVal* o); + extern void i_array_2_state_65(svBitVecVal* o); + extern void i_array_4_state_1(svLogicVecVal* o); + extern void i_array_4_state_128(svLogicVecVal* o); + extern void i_array_4_state_32(svLogicVecVal* o); + extern void i_array_4_state_33(svLogicVecVal* o); + extern void i_array_4_state_64(svLogicVecVal* o); + extern void i_array_4_state_65(svLogicVecVal* o); + extern void i_bit(svBit* o); + extern void i_bit_t(svBit* o); + extern void i_byte(char* o); + extern void i_byte_t(char* o); + extern void i_byte_unsigned(unsigned char* o); + extern void i_byte_unsigned_t(unsigned char* o); + extern void i_chandle(void** o); + extern void i_chandle_t(void** o); + extern void i_int(int* o); + extern void i_int_t(int* o); + extern void i_int_unsigned(unsigned int* o); + extern void i_int_unsigned_t(unsigned int* o); + extern void i_integer(svLogicVecVal* o); + extern void i_integer_t(svLogicVecVal* o); + extern void i_logic(svLogic* o); + extern void i_logic_t(svLogic* o); + extern void i_longint(long long* o); + extern void i_longint_t(long long* o); + extern void i_longint_unsigned(unsigned long long* o); + extern void i_longint_unsigned_t(unsigned long long* o); + extern void i_real(double* o); + extern void i_real_t(double* o); + extern void i_shortint(short* o); + extern void i_shortint_t(short* o); + extern void i_shortint_unsigned(unsigned short* o); + extern void i_shortint_unsigned_t(unsigned short* o); + extern void i_string(const char** o); + extern void i_string_t(const char** o); + extern void i_struct_2_state_1(svBitVecVal* o); + extern void i_struct_2_state_128(svBitVecVal* o); + extern void i_struct_2_state_32(svBitVecVal* o); + extern void i_struct_2_state_33(svBitVecVal* o); + extern void i_struct_2_state_64(svBitVecVal* o); + extern void i_struct_2_state_65(svBitVecVal* o); + extern void i_struct_4_state_1(svLogicVecVal* o); + extern void i_struct_4_state_128(svLogicVecVal* o); + extern void i_struct_4_state_32(svLogicVecVal* o); + extern void i_struct_4_state_33(svLogicVecVal* o); + extern void i_struct_4_state_64(svLogicVecVal* o); + extern void i_struct_4_state_65(svLogicVecVal* o); + extern void i_time(svLogicVecVal* o); + extern void i_time_t(svLogicVecVal* o); + extern void i_union_2_state_1(svBitVecVal* o); + extern void i_union_2_state_128(svBitVecVal* o); + extern void i_union_2_state_32(svBitVecVal* o); + extern void i_union_2_state_33(svBitVecVal* o); + extern void i_union_2_state_64(svBitVecVal* o); + extern void i_union_2_state_65(svBitVecVal* o); + extern void i_union_4_state_1(svLogicVecVal* o); + extern void i_union_4_state_128(svLogicVecVal* o); + extern void i_union_4_state_32(svLogicVecVal* o); + extern void i_union_4_state_33(svLogicVecVal* o); + extern void i_union_4_state_64(svLogicVecVal* o); + extern void i_union_4_state_65(svLogicVecVal* o); + #ifdef __cplusplus } #endif diff --git a/test_regress/t/t_dpi_arg_output_unpack.cpp b/test_regress/t/t_dpi_arg_output_unpack.cpp index 417e29cb1..70fb6f542 100644 --- a/test_regress/t/t_dpi_arg_output_unpack.cpp +++ b/test_regress/t/t_dpi_arg_output_unpack.cpp @@ -130,6 +130,26 @@ void set_3d(svLogicVecVal* v, int bitwidth) { set_uint(v + ((3 * 3 + 0) * 2 + 0) * unit, 51, bitwidth); } +void set_0d_scalar(svScalar* v) { *v = sv_0; } + +void set_1d_scalar(svScalar* v) { + v[0] = sv_1; + v[1] = sv_0; +} + +void set_2d_scalar(svScalar* v) { + v[0 * 2 + 1] = sv_1; + v[1 * 2 + 1] = sv_0; + v[2 * 2 + 1] = sv_1; +} + +void set_3d_scalar(svScalar* v) { + v[(0 * 3 + 0) * 2 + 0] = sv_0; + v[(1 * 3 + 0) * 2 + 0] = sv_1; + v[(2 * 3 + 0) * 2 + 0] = sv_0; + v[(3 * 3 + 0) * 2 + 0] = sv_1; +} + void set_0d(svBitVecVal* v, int bitwidth) { set_uint(v, 42, bitwidth); } void set_1d(svBitVecVal* v, int bitwidth) { @@ -343,6 +363,11 @@ void i_string_3d(const char** v) { v[(3 * 3 + 0) * 2 + 0] = s3; } +void i_bit1_0d(svBit* v) { set_0d_scalar(v); } +void i_bit1_1d(svBit* v) { set_1d_scalar(v); } +void i_bit1_2d(svBit* v) { set_2d_scalar(v); } +void i_bit1_3d(svBit* v) { set_3d_scalar(v); } + void i_bit7_0d(svBitVecVal* v) { set_0d(v, 7); } void i_bit7_1d(svBitVecVal* v) { set_1d(v, 7); } void i_bit7_2d(svBitVecVal* v) { set_2d(v, 7); } @@ -353,6 +378,11 @@ void i_bit121_1d(svBitVecVal* v) { set_1d(v, 121); } void i_bit121_2d(svBitVecVal* v) { set_2d(v, 121); } void i_bit121_3d(svBitVecVal* v) { set_3d(v, 121); } +void i_logic1_0d(svLogic* v) { set_0d_scalar(v); } +void i_logic1_1d(svLogic* v) { set_1d_scalar(v); } +void i_logic1_2d(svLogic* v) { set_2d_scalar(v); } +void i_logic1_3d(svLogic* v) { set_3d_scalar(v); } + void i_logic7_0d(svLogicVecVal* v) { set_0d(v, 7); } void i_logic7_1d(svLogicVecVal* v) { set_1d(v, 7); } void i_logic7_2d(svLogicVecVal* v) { set_2d(v, 7); } diff --git a/test_regress/t/t_dpi_arg_output_unpack.pl b/test_regress/t/t_dpi_arg_output_unpack.pl index 4a2f325ab..c4b0c26de 100755 --- a/test_regress/t/t_dpi_arg_output_unpack.pl +++ b/test_regress/t/t_dpi_arg_output_unpack.pl @@ -20,7 +20,8 @@ if ($Self->{nc}) { compile( v_flags2 => ["t/t_dpi_arg_output_unpack.cpp"], - verilator_flags2 => ["-Wall -Wno-DECLFILENAME"], + # --no-decoration so .out file doesn't comment on source lines + verilator_flags2 => ["-Wall -Wno-DECLFILENAME --no-decoration"], # NC: Gdd the obj_dir to the C include path nc_flags2 => ["+ncscargs+-I$Self->{obj_dir}"], # ModelSim: Generate DPI header, add obj_dir to the C include path diff --git a/test_regress/t/t_dpi_arg_output_unpack.v b/test_regress/t/t_dpi_arg_output_unpack.v index f2fbcd7ee..fc9c96f64 100644 --- a/test_regress/t/t_dpi_arg_output_unpack.v +++ b/test_regress/t/t_dpi_arg_output_unpack.v @@ -17,17 +17,21 @@ `endif `ifdef MS + `define NO_BITS_TO_SCALAR `endif `ifdef VERILATOR `define NO_SHORTREAL `define NO_UNPACK_STRUCT - `define NULL 64'd0 -`else - `define NULL null `endif -`define CHECK_VAL(act, exp) if ((act) == (exp)) begin \ +`ifdef NO_BITS_TO_SCALAR + `define ARE_SAME(act, exp) ($bits((act)) == 1 ? (act) == ((exp) & 1) : (act) == (exp)) +`else + `define ARE_SAME(act, exp) ((act) == (($bits(act))'(exp))) +`endif + +`define CHECK_VAL(act, exp) if (`ARE_SAME(act, exp)) begin \ if (ENABLE_VERBOSE_MESSAGE)$display(`"act`", ":", (act), " as expected"); \ end else begin \ $display("Mismatch %s expected:%d actual:%d at %d", `"act`", \ @@ -99,8 +103,10 @@ module t; `endif typedef chandle chandle_array_t[4][3][2]; typedef string string_array_t[4][3][2]; + typedef bit bit1_array_t[4][3][2]; typedef bit [6:0] bit7_array_t[4][3][2]; typedef bit [120:0] bit121_array_t[4][3][2]; + typedef logic logic1_array_t[4][3][2]; typedef logic [6:0] logic7_array_t[4][3][2]; typedef logic [120:0] logic121_array_t[4][3][2]; @@ -198,6 +204,11 @@ module t; import "DPI-C" function void i_string_2d(output string val[3][2]); import "DPI-C" function void i_string_3d(output string_array_t val); + import "DPI-C" function void i_bit1_0d(output bit val); + import "DPI-C" function void i_bit1_1d(output bit val[2]); + import "DPI-C" function void i_bit1_2d(output bit val[3][2]); + import "DPI-C" function void i_bit1_3d(output bit1_array_t val); + import "DPI-C" function void i_bit7_0d(output bit[6:0] val); import "DPI-C" function void i_bit7_1d(output bit[6:0] val[2]); import "DPI-C" function void i_bit7_2d(output bit[6:0] val[3][2]); @@ -208,6 +219,11 @@ module t; import "DPI-C" function void i_bit121_2d(output bit[120:0] val[3][2]); import "DPI-C" function void i_bit121_3d(output bit121_array_t val); + import "DPI-C" function void i_logic1_0d(output logic val); + import "DPI-C" function void i_logic1_1d(output logic val[2]); + import "DPI-C" function void i_logic1_2d(output logic val[3][2]); + import "DPI-C" function void i_logic1_3d(output logic1_array_t val); + import "DPI-C" function void i_logic7_0d(output logic[6:0] val); import "DPI-C" function void i_logic7_1d(output logic[6:0] val[2]); import "DPI-C" function void i_logic7_2d(output logic[6:0] val[3][2]); @@ -309,6 +325,11 @@ module t; export "DPI-C" function e_string_2d; export "DPI-C" function e_string_3d; + export "DPI-C" function e_bit1_0d; + export "DPI-C" function e_bit1_1d; + export "DPI-C" function e_bit1_2d; + export "DPI-C" function e_bit1_3d; + export "DPI-C" function e_bit7_0d; export "DPI-C" function e_bit7_1d; export "DPI-C" function e_bit7_2d; @@ -319,6 +340,11 @@ module t; export "DPI-C" function e_bit121_2d; export "DPI-C" function e_bit121_3d; + export "DPI-C" function e_logic1_0d; + export "DPI-C" function e_logic1_1d; + export "DPI-C" function e_logic1_2d; + export "DPI-C" function e_logic1_3d; + export "DPI-C" function e_logic7_0d; export "DPI-C" function e_logic7_1d; export "DPI-C" function e_logic7_2d; @@ -343,10 +369,22 @@ module t; //====================================================================== // Definitions of exported functions //====================================================================== -`define SET_0D(val) val = 42 -`define SET_1D(val) val[0] = 43; val[1] = 44 -`define SET_2D(val) val[0][1] = 45; val[1][1] = 46; val[2][1] = 47 -`define SET_3D(val) val[0][0][0] = 48; val[1][0][0] = 49; val[2][0][0] = 50; val[3][0][0] = 51 +`define SET_0D(val) \ + /* verilator lint_off WIDTH */ \ + val = 42 \ + /* verilator lint_on WIDTH */ +`define SET_1D(val) \ + /* verilator lint_off WIDTH */ \ + val[0] = 43; val[1] = 44 \ + /* verilator lint_on WIDTH */ +`define SET_2D(val) \ + /* verilator lint_off WIDTH */ \ + val[0][1] = 45; val[1][1] = 46; val[2][1] = 47 \ + /* verilator lint_on WIDTH */ +`define SET_3D(val) \ + /* verilator lint_off WIDTH */ \ + val[0][0][0] = 48; val[1][0][0] = 49; val[2][0][0] = 50; val[3][0][0] = 51 \ + /* verilator lint_on WIDTH */ function void e_byte_0d(output byte val); `SET_0D(val); endfunction function void e_byte_1d(output byte val[2]); `SET_1D(val); endfunction @@ -452,6 +490,11 @@ module t; val[3][0][0] = "51"; endfunction + function void e_bit1_0d(output bit val); `SET_0D(val); endfunction + function void e_bit1_1d(output bit val[2]); `SET_1D(val); endfunction + function void e_bit1_2d(output bit val[3][2]); `SET_2D(val); endfunction + function void e_bit1_3d(output bit7_array_t val); `SET_3D(val); endfunction + function void e_bit7_0d(output bit[6:0] val); `SET_0D(val); endfunction function void e_bit7_1d(output bit[6:0] val[2]); `SET_1D(val); endfunction function void e_bit7_2d(output bit[6:0] val[3][2]); `SET_2D(val); endfunction @@ -462,6 +505,11 @@ module t; function void e_bit121_2d(output bit[120:0] val[3][2]); `SET_2D(val); endfunction function void e_bit121_3d(output bit121_array_t val); `SET_3D(val); endfunction + function void e_logic1_0d(output logic val); `SET_0D(val); endfunction + function void e_logic1_1d(output logic val[2]); `SET_1D(val); endfunction + function void e_logic1_2d(output logic val[3][2]); `SET_2D(val); endfunction + function void e_logic1_3d(output logic7_array_t val); `SET_3D(val); endfunction + function void e_logic7_0d(output logic[6:0] val); `SET_0D(val); endfunction function void e_logic7_1d(output logic[6:0] val[2]); `SET_1D(val); endfunction function void e_logic7_2d(output logic[6:0] val[3][2]); `SET_2D(val); endfunction @@ -525,8 +573,10 @@ module t; `endif chandle_array_t chandle_array; string_array_t string_array; + bit1_array_t bit1_array; bit7_array_t bit7_array; bit121_array_t bit121_array; + logic1_array_t logic1_array; logic7_array_t logic7_array; logic121_array_t logic121_array; pack_struct_array_t pack_struct_array; @@ -682,6 +732,15 @@ module t; `CHECK_STRING_VAL(string_array[2][0][0], "50"); `CHECK_STRING_VAL(string_array[3][0][0], "51"); + i_bit1_0d(bit1_array[3][2][1]); + `CHECK_0D(bit1_array[3][2][1]); + i_bit1_1d(bit1_array[2][1]); + `CHECK_1D(bit1_array[2][1]); + i_bit1_2d(bit1_array[1]); + `CHECK_2D(bit1_array[1]); + i_bit1_3d(bit1_array); + `CHECK_3D(bit1_array); + i_bit7_0d(bit7_array[3][2][1]); `CHECK_0D(bit7_array[3][2][1]); i_bit7_1d(bit7_array[2][1]); @@ -700,6 +759,15 @@ module t; i_bit121_3d(bit121_array); `CHECK_3D(bit121_array); + i_logic1_0d(logic1_array[3][2][1]); + `CHECK_0D(logic1_array[3][2][1]); + i_logic1_1d(logic1_array[2][1]); + `CHECK_1D(logic1_array[2][1]); + i_logic1_2d(logic1_array[1]); + `CHECK_2D(logic1_array[1]); + i_logic1_3d(logic1_array); + `CHECK_3D(logic1_array); + i_logic7_0d(logic7_array[3][2][1]); `CHECK_0D(logic7_array[3][2][1]); i_logic7_1d(logic7_array[2][1]); diff --git a/test_regress/t/t_dpi_arg_output_unpack__Dpi.out b/test_regress/t/t_dpi_arg_output_unpack__Dpi.out index 0c038cb14..e3a2729a4 100644 --- a/test_regress/t/t_dpi_arg_output_unpack__Dpi.out +++ b/test_regress/t/t_dpi_arg_output_unpack__Dpi.out @@ -10,304 +10,174 @@ #ifdef __cplusplus extern "C" { #endif - - - // DPI EXPORTS - // DPI export at t/t_dpi_arg_output_unpack.v:460:18 - extern void e_bit121_0d(svBitVecVal* val); - // DPI export at t/t_dpi_arg_output_unpack.v:461:18 - extern void e_bit121_1d(svBitVecVal* val); - // DPI export at t/t_dpi_arg_output_unpack.v:462:18 - extern void e_bit121_2d(svBitVecVal* val); - // DPI export at t/t_dpi_arg_output_unpack.v:463:18 - extern void e_bit121_3d(svBitVecVal* val); - // DPI export at t/t_dpi_arg_output_unpack.v:455:18 - extern void e_bit7_0d(svBitVecVal* val); - // DPI export at t/t_dpi_arg_output_unpack.v:456:18 - extern void e_bit7_1d(svBitVecVal* val); - // DPI export at t/t_dpi_arg_output_unpack.v:457:18 - extern void e_bit7_2d(svBitVecVal* val); - // DPI export at t/t_dpi_arg_output_unpack.v:458:18 - extern void e_bit7_3d(svBitVecVal* val); - // DPI export at t/t_dpi_arg_output_unpack.v:351:18 - extern void e_byte_0d(char* val); - // DPI export at t/t_dpi_arg_output_unpack.v:352:18 - extern void e_byte_1d(char* val); - // DPI export at t/t_dpi_arg_output_unpack.v:353:18 - extern void e_byte_2d(char* val); - // DPI export at t/t_dpi_arg_output_unpack.v:354:18 - extern void e_byte_3d(char* val); - // DPI export at t/t_dpi_arg_output_unpack.v:356:18 - extern void e_byte_unsigned_0d(unsigned char* val); - // DPI export at t/t_dpi_arg_output_unpack.v:357:18 - extern void e_byte_unsigned_1d(unsigned char* val); - // DPI export at t/t_dpi_arg_output_unpack.v:358:18 - extern void e_byte_unsigned_2d(unsigned char* val); - // DPI export at t/t_dpi_arg_output_unpack.v:359:18 - extern void e_byte_unsigned_3d(unsigned char* val); - // DPI export at t/t_dpi_arg_output_unpack.v:417:18 - extern void e_chandle_0d(void** val); - // DPI export at t/t_dpi_arg_output_unpack.v:420:18 - extern void e_chandle_1d(void** val); - // DPI export at t/t_dpi_arg_output_unpack.v:424:18 - extern void e_chandle_2d(void** val); - // DPI export at t/t_dpi_arg_output_unpack.v:429:18 - extern void e_chandle_3d(void** val); - // DPI export at t/t_dpi_arg_output_unpack.v:371:18 - extern void e_int_0d(int* val); - // DPI export at t/t_dpi_arg_output_unpack.v:372:18 - extern void e_int_1d(int* val); - // DPI export at t/t_dpi_arg_output_unpack.v:373:18 - extern void e_int_2d(int* val); - // DPI export at t/t_dpi_arg_output_unpack.v:374:18 - extern void e_int_3d(int* val); - // DPI export at t/t_dpi_arg_output_unpack.v:376:18 - extern void e_int_unsigned_0d(unsigned int* val); - // DPI export at t/t_dpi_arg_output_unpack.v:377:18 - extern void e_int_unsigned_1d(unsigned int* val); - // DPI export at t/t_dpi_arg_output_unpack.v:378:18 - extern void e_int_unsigned_2d(unsigned int* val); - // DPI export at t/t_dpi_arg_output_unpack.v:379:18 - extern void e_int_unsigned_3d(unsigned int* val); - // DPI export at t/t_dpi_arg_output_unpack.v:399:18 - extern void e_integer_0d(svLogicVecVal* val); - // DPI export at t/t_dpi_arg_output_unpack.v:400:18 - extern void e_integer_1d(svLogicVecVal* val); - // DPI export at t/t_dpi_arg_output_unpack.v:401:18 - extern void e_integer_2d(svLogicVecVal* val); - // DPI export at t/t_dpi_arg_output_unpack.v:402:18 - extern void e_integer_3d(svLogicVecVal* val); - // DPI export at t/t_dpi_arg_output_unpack.v:470:18 - extern void e_logic121_0d(svLogicVecVal* val); - // DPI export at t/t_dpi_arg_output_unpack.v:471:18 - extern void e_logic121_1d(svLogicVecVal* val); - // DPI export at t/t_dpi_arg_output_unpack.v:472:18 - extern void e_logic121_2d(svLogicVecVal* val); - // DPI export at t/t_dpi_arg_output_unpack.v:473:18 - extern void e_logic121_3d(svLogicVecVal* val); - // DPI export at t/t_dpi_arg_output_unpack.v:465:18 - extern void e_logic7_0d(svLogicVecVal* val); - // DPI export at t/t_dpi_arg_output_unpack.v:466:18 - extern void e_logic7_1d(svLogicVecVal* val); - // DPI export at t/t_dpi_arg_output_unpack.v:467:18 - extern void e_logic7_2d(svLogicVecVal* val); - // DPI export at t/t_dpi_arg_output_unpack.v:468:18 - extern void e_logic7_3d(svLogicVecVal* val); - // DPI export at t/t_dpi_arg_output_unpack.v:381:18 - extern void e_longint_0d(long long* val); - // DPI export at t/t_dpi_arg_output_unpack.v:382:18 - extern void e_longint_1d(long long* val); - // DPI export at t/t_dpi_arg_output_unpack.v:383:18 - extern void e_longint_2d(long long* val); - // DPI export at t/t_dpi_arg_output_unpack.v:384:18 - extern void e_longint_3d(long long* val); - // DPI export at t/t_dpi_arg_output_unpack.v:386:18 - extern void e_longint_unsigned_0d(unsigned long long* val); - // DPI export at t/t_dpi_arg_output_unpack.v:387:18 - extern void e_longint_unsigned_1d(unsigned long long* val); - // DPI export at t/t_dpi_arg_output_unpack.v:388:18 - extern void e_longint_unsigned_2d(unsigned long long* val); - // DPI export at t/t_dpi_arg_output_unpack.v:389:18 - extern void e_longint_unsigned_3d(unsigned long long* val); - // DPI export at t/t_dpi_arg_output_unpack.v:475:18 - extern void e_pack_struct_0d(svLogicVecVal* val); - // DPI export at t/t_dpi_arg_output_unpack.v:476:18 - extern void e_pack_struct_1d(svLogicVecVal* val); - // DPI export at t/t_dpi_arg_output_unpack.v:477:18 - extern void e_pack_struct_2d(svLogicVecVal* val); - // DPI export at t/t_dpi_arg_output_unpack.v:478:18 - extern void e_pack_struct_3d(svLogicVecVal* val); - // DPI export at t/t_dpi_arg_output_unpack.v:405:18 - extern void e_real_0d(double* val); - // DPI export at t/t_dpi_arg_output_unpack.v:406:18 - extern void e_real_1d(double* val); - // DPI export at t/t_dpi_arg_output_unpack.v:407:18 - extern void e_real_2d(double* val); - // DPI export at t/t_dpi_arg_output_unpack.v:408:18 - extern void e_real_3d(double* val); - // DPI export at t/t_dpi_arg_output_unpack.v:361:18 - extern void e_shortint_0d(short* val); - // DPI export at t/t_dpi_arg_output_unpack.v:362:18 - extern void e_shortint_1d(short* val); - // DPI export at t/t_dpi_arg_output_unpack.v:363:18 - extern void e_shortint_2d(short* val); - // DPI export at t/t_dpi_arg_output_unpack.v:364:18 - extern void e_shortint_3d(short* val); - // DPI export at t/t_dpi_arg_output_unpack.v:366:18 - extern void e_shortint_unsigned_0d(unsigned short* val); - // DPI export at t/t_dpi_arg_output_unpack.v:367:18 - extern void e_shortint_unsigned_1d(unsigned short* val); - // DPI export at t/t_dpi_arg_output_unpack.v:368:18 - extern void e_shortint_unsigned_2d(unsigned short* val); - // DPI export at t/t_dpi_arg_output_unpack.v:369:18 - extern void e_shortint_unsigned_3d(unsigned short* val); - // DPI export at t/t_dpi_arg_output_unpack.v:436:18 - extern void e_string_0d(const char** val); - // DPI export at t/t_dpi_arg_output_unpack.v:439:18 - extern void e_string_1d(const char** val); - // DPI export at t/t_dpi_arg_output_unpack.v:443:18 - extern void e_string_2d(const char** val); - // DPI export at t/t_dpi_arg_output_unpack.v:448:18 - extern void e_string_3d(const char** val); - // DPI export at t/t_dpi_arg_output_unpack.v:392:18 - extern void e_time_0d(svLogicVecVal* val); - // DPI export at t/t_dpi_arg_output_unpack.v:393:18 - extern void e_time_1d(svLogicVecVal* val); - // DPI export at t/t_dpi_arg_output_unpack.v:394:18 - extern void e_time_2d(svLogicVecVal* val); - // DPI export at t/t_dpi_arg_output_unpack.v:395:18 - extern void e_time_3d(svLogicVecVal* val); - - // DPI IMPORTS - // DPI import at t/t_dpi_arg_output_unpack.v:505:41 - extern void check_exports(); - // DPI import at t/t_dpi_arg_output_unpack.v:123:36 - extern void* get_non_null(); - // DPI import at t/t_dpi_arg_output_unpack.v:206:33 - extern void i_bit121_0d(svBitVecVal* val); - // DPI import at t/t_dpi_arg_output_unpack.v:207:33 - extern void i_bit121_1d(svBitVecVal* val); - // DPI import at t/t_dpi_arg_output_unpack.v:208:33 - extern void i_bit121_2d(svBitVecVal* val); - // DPI import at t/t_dpi_arg_output_unpack.v:209:33 - extern void i_bit121_3d(svBitVecVal* val); - // DPI import at t/t_dpi_arg_output_unpack.v:201:33 - extern void i_bit7_0d(svBitVecVal* val); - // DPI import at t/t_dpi_arg_output_unpack.v:202:33 - extern void i_bit7_1d(svBitVecVal* val); - // DPI import at t/t_dpi_arg_output_unpack.v:203:33 - extern void i_bit7_2d(svBitVecVal* val); - // DPI import at t/t_dpi_arg_output_unpack.v:204:33 - extern void i_bit7_3d(svBitVecVal* val); - // DPI import at t/t_dpi_arg_output_unpack.v:125:33 - extern void i_byte_0d(char* val); - // DPI import at t/t_dpi_arg_output_unpack.v:126:33 - extern void i_byte_1d(char* val); - // DPI import at t/t_dpi_arg_output_unpack.v:127:33 - extern void i_byte_2d(char* val); - // DPI import at t/t_dpi_arg_output_unpack.v:128:33 - extern void i_byte_3d(char* val); - // DPI import at t/t_dpi_arg_output_unpack.v:130:33 - extern void i_byte_unsigned_0d(unsigned char* val); - // DPI import at t/t_dpi_arg_output_unpack.v:131:33 - extern void i_byte_unsigned_1d(unsigned char* val); - // DPI import at t/t_dpi_arg_output_unpack.v:132:33 - extern void i_byte_unsigned_2d(unsigned char* val); - // DPI import at t/t_dpi_arg_output_unpack.v:133:33 - extern void i_byte_unsigned_3d(unsigned char* val); - // DPI import at t/t_dpi_arg_output_unpack.v:191:33 - extern void i_chandle_0d(void** val); - // DPI import at t/t_dpi_arg_output_unpack.v:192:33 - extern void i_chandle_1d(void** val); - // DPI import at t/t_dpi_arg_output_unpack.v:193:33 - extern void i_chandle_2d(void** val); - // DPI import at t/t_dpi_arg_output_unpack.v:194:33 - extern void i_chandle_3d(void** val); - // DPI import at t/t_dpi_arg_output_unpack.v:145:33 - extern void i_int_0d(int* val); - // DPI import at t/t_dpi_arg_output_unpack.v:146:33 - extern void i_int_1d(int* val); - // DPI import at t/t_dpi_arg_output_unpack.v:147:33 - extern void i_int_2d(int* val); - // DPI import at t/t_dpi_arg_output_unpack.v:148:33 - extern void i_int_3d(int* val); - // DPI import at t/t_dpi_arg_output_unpack.v:150:33 - extern void i_int_unsigned_0d(unsigned int* val); - // DPI import at t/t_dpi_arg_output_unpack.v:151:33 - extern void i_int_unsigned_1d(unsigned int* val); - // DPI import at t/t_dpi_arg_output_unpack.v:152:33 - extern void i_int_unsigned_2d(unsigned int* val); - // DPI import at t/t_dpi_arg_output_unpack.v:153:33 - extern void i_int_unsigned_3d(unsigned int* val); - // DPI import at t/t_dpi_arg_output_unpack.v:173:33 - extern void i_integer_0d(svLogicVecVal* val); - // DPI import at t/t_dpi_arg_output_unpack.v:174:33 - extern void i_integer_1d(svLogicVecVal* val); - // DPI import at t/t_dpi_arg_output_unpack.v:175:33 - extern void i_integer_2d(svLogicVecVal* val); - // DPI import at t/t_dpi_arg_output_unpack.v:176:33 - extern void i_integer_3d(svLogicVecVal* val); - // DPI import at t/t_dpi_arg_output_unpack.v:216:33 - extern void i_logic121_0d(svLogicVecVal* val); - // DPI import at t/t_dpi_arg_output_unpack.v:217:33 - extern void i_logic121_1d(svLogicVecVal* val); - // DPI import at t/t_dpi_arg_output_unpack.v:218:33 - extern void i_logic121_2d(svLogicVecVal* val); - // DPI import at t/t_dpi_arg_output_unpack.v:219:33 - extern void i_logic121_3d(svLogicVecVal* val); - // DPI import at t/t_dpi_arg_output_unpack.v:211:33 - extern void i_logic7_0d(svLogicVecVal* val); - // DPI import at t/t_dpi_arg_output_unpack.v:212:33 - extern void i_logic7_1d(svLogicVecVal* val); - // DPI import at t/t_dpi_arg_output_unpack.v:213:33 - extern void i_logic7_2d(svLogicVecVal* val); - // DPI import at t/t_dpi_arg_output_unpack.v:214:33 - extern void i_logic7_3d(svLogicVecVal* val); - // DPI import at t/t_dpi_arg_output_unpack.v:155:33 - extern void i_longint_0d(long long* val); - // DPI import at t/t_dpi_arg_output_unpack.v:156:33 - extern void i_longint_1d(long long* val); - // DPI import at t/t_dpi_arg_output_unpack.v:157:33 - extern void i_longint_2d(long long* val); - // DPI import at t/t_dpi_arg_output_unpack.v:158:33 - extern void i_longint_3d(long long* val); - // DPI import at t/t_dpi_arg_output_unpack.v:160:33 - extern void i_longint_unsigned_0d(unsigned long long* val); - // DPI import at t/t_dpi_arg_output_unpack.v:161:33 - extern void i_longint_unsigned_1d(unsigned long long* val); - // DPI import at t/t_dpi_arg_output_unpack.v:162:33 - extern void i_longint_unsigned_2d(unsigned long long* val); - // DPI import at t/t_dpi_arg_output_unpack.v:163:33 - extern void i_longint_unsigned_3d(unsigned long long* val); - // DPI import at t/t_dpi_arg_output_unpack.v:221:33 - extern void i_pack_struct_0d(svLogicVecVal* val); - // DPI import at t/t_dpi_arg_output_unpack.v:222:33 - extern void i_pack_struct_1d(svLogicVecVal* val); - // DPI import at t/t_dpi_arg_output_unpack.v:223:33 - extern void i_pack_struct_2d(svLogicVecVal* val); - // DPI import at t/t_dpi_arg_output_unpack.v:224:33 - extern void i_pack_struct_3d(svLogicVecVal* val); - // DPI import at t/t_dpi_arg_output_unpack.v:179:33 - extern void i_real_0d(double* val); - // DPI import at t/t_dpi_arg_output_unpack.v:180:33 - extern void i_real_1d(double* val); - // DPI import at t/t_dpi_arg_output_unpack.v:181:33 - extern void i_real_2d(double* val); - // DPI import at t/t_dpi_arg_output_unpack.v:182:33 - extern void i_real_3d(double* val); - // DPI import at t/t_dpi_arg_output_unpack.v:135:33 - extern void i_shortint_0d(short* val); - // DPI import at t/t_dpi_arg_output_unpack.v:136:33 - extern void i_shortint_1d(short* val); - // DPI import at t/t_dpi_arg_output_unpack.v:137:33 - extern void i_shortint_2d(short* val); - // DPI import at t/t_dpi_arg_output_unpack.v:138:33 - extern void i_shortint_3d(short* val); - // DPI import at t/t_dpi_arg_output_unpack.v:140:33 - extern void i_shortint_unsigned_0d(unsigned short* val); - // DPI import at t/t_dpi_arg_output_unpack.v:141:33 - extern void i_shortint_unsigned_1d(unsigned short* val); - // DPI import at t/t_dpi_arg_output_unpack.v:142:33 - extern void i_shortint_unsigned_2d(unsigned short* val); - // DPI import at t/t_dpi_arg_output_unpack.v:143:33 - extern void i_shortint_unsigned_3d(unsigned short* val); - // DPI import at t/t_dpi_arg_output_unpack.v:196:33 - extern void i_string_0d(const char** val); - // DPI import at t/t_dpi_arg_output_unpack.v:197:33 - extern void i_string_1d(const char** val); - // DPI import at t/t_dpi_arg_output_unpack.v:198:33 - extern void i_string_2d(const char** val); - // DPI import at t/t_dpi_arg_output_unpack.v:199:33 - extern void i_string_3d(const char** val); - // DPI import at t/t_dpi_arg_output_unpack.v:166:33 - extern void i_time_0d(svLogicVecVal* val); - // DPI import at t/t_dpi_arg_output_unpack.v:167:33 - extern void i_time_1d(svLogicVecVal* val); - // DPI import at t/t_dpi_arg_output_unpack.v:168:33 - extern void i_time_2d(svLogicVecVal* val); - // DPI import at t/t_dpi_arg_output_unpack.v:169:33 - extern void i_time_3d(svLogicVecVal* val); - + + + // DPI EXPORTS + extern void e_bit121_0d(svBitVecVal* val); + extern void e_bit121_1d(svBitVecVal* val); + extern void e_bit121_2d(svBitVecVal* val); + extern void e_bit121_3d(svBitVecVal* val); + extern void e_bit1_0d(svBit* val); + extern void e_bit1_1d(svBit* val); + extern void e_bit1_2d(svBit* val); + extern void e_bit1_3d(svBitVecVal* val); + extern void e_bit7_0d(svBitVecVal* val); + extern void e_bit7_1d(svBitVecVal* val); + extern void e_bit7_2d(svBitVecVal* val); + extern void e_bit7_3d(svBitVecVal* val); + extern void e_byte_0d(char* val); + extern void e_byte_1d(char* val); + extern void e_byte_2d(char* val); + extern void e_byte_3d(char* val); + extern void e_byte_unsigned_0d(unsigned char* val); + extern void e_byte_unsigned_1d(unsigned char* val); + extern void e_byte_unsigned_2d(unsigned char* val); + extern void e_byte_unsigned_3d(unsigned char* val); + extern void e_chandle_0d(void** val); + extern void e_chandle_1d(void** val); + extern void e_chandle_2d(void** val); + extern void e_chandle_3d(void** val); + extern void e_int_0d(int* val); + extern void e_int_1d(int* val); + extern void e_int_2d(int* val); + extern void e_int_3d(int* val); + extern void e_int_unsigned_0d(unsigned int* val); + extern void e_int_unsigned_1d(unsigned int* val); + extern void e_int_unsigned_2d(unsigned int* val); + extern void e_int_unsigned_3d(unsigned int* val); + extern void e_integer_0d(svLogicVecVal* val); + extern void e_integer_1d(svLogicVecVal* val); + extern void e_integer_2d(svLogicVecVal* val); + extern void e_integer_3d(svLogicVecVal* val); + extern void e_logic121_0d(svLogicVecVal* val); + extern void e_logic121_1d(svLogicVecVal* val); + extern void e_logic121_2d(svLogicVecVal* val); + extern void e_logic121_3d(svLogicVecVal* val); + extern void e_logic1_0d(svLogic* val); + extern void e_logic1_1d(svLogic* val); + extern void e_logic1_2d(svLogic* val); + extern void e_logic1_3d(svLogicVecVal* val); + extern void e_logic7_0d(svLogicVecVal* val); + extern void e_logic7_1d(svLogicVecVal* val); + extern void e_logic7_2d(svLogicVecVal* val); + extern void e_logic7_3d(svLogicVecVal* val); + extern void e_longint_0d(long long* val); + extern void e_longint_1d(long long* val); + extern void e_longint_2d(long long* val); + extern void e_longint_3d(long long* val); + extern void e_longint_unsigned_0d(unsigned long long* val); + extern void e_longint_unsigned_1d(unsigned long long* val); + extern void e_longint_unsigned_2d(unsigned long long* val); + extern void e_longint_unsigned_3d(unsigned long long* val); + extern void e_pack_struct_0d(svLogicVecVal* val); + extern void e_pack_struct_1d(svLogicVecVal* val); + extern void e_pack_struct_2d(svLogicVecVal* val); + extern void e_pack_struct_3d(svLogicVecVal* val); + extern void e_real_0d(double* val); + extern void e_real_1d(double* val); + extern void e_real_2d(double* val); + extern void e_real_3d(double* val); + extern void e_shortint_0d(short* val); + extern void e_shortint_1d(short* val); + extern void e_shortint_2d(short* val); + extern void e_shortint_3d(short* val); + extern void e_shortint_unsigned_0d(unsigned short* val); + extern void e_shortint_unsigned_1d(unsigned short* val); + extern void e_shortint_unsigned_2d(unsigned short* val); + extern void e_shortint_unsigned_3d(unsigned short* val); + extern void e_string_0d(const char** val); + extern void e_string_1d(const char** val); + extern void e_string_2d(const char** val); + extern void e_string_3d(const char** val); + extern void e_time_0d(svLogicVecVal* val); + extern void e_time_1d(svLogicVecVal* val); + extern void e_time_2d(svLogicVecVal* val); + extern void e_time_3d(svLogicVecVal* val); + + // DPI IMPORTS + extern void check_exports(); + extern void* get_non_null(); + extern void i_bit121_0d(svBitVecVal* val); + extern void i_bit121_1d(svBitVecVal* val); + extern void i_bit121_2d(svBitVecVal* val); + extern void i_bit121_3d(svBitVecVal* val); + extern void i_bit1_0d(svBit* val); + extern void i_bit1_1d(svBit* val); + extern void i_bit1_2d(svBit* val); + extern void i_bit1_3d(svBit* val); + extern void i_bit7_0d(svBitVecVal* val); + extern void i_bit7_1d(svBitVecVal* val); + extern void i_bit7_2d(svBitVecVal* val); + extern void i_bit7_3d(svBitVecVal* val); + extern void i_byte_0d(char* val); + extern void i_byte_1d(char* val); + extern void i_byte_2d(char* val); + extern void i_byte_3d(char* val); + extern void i_byte_unsigned_0d(unsigned char* val); + extern void i_byte_unsigned_1d(unsigned char* val); + extern void i_byte_unsigned_2d(unsigned char* val); + extern void i_byte_unsigned_3d(unsigned char* val); + extern void i_chandle_0d(void** val); + extern void i_chandle_1d(void** val); + extern void i_chandle_2d(void** val); + extern void i_chandle_3d(void** val); + extern void i_int_0d(int* val); + extern void i_int_1d(int* val); + extern void i_int_2d(int* val); + extern void i_int_3d(int* val); + extern void i_int_unsigned_0d(unsigned int* val); + extern void i_int_unsigned_1d(unsigned int* val); + extern void i_int_unsigned_2d(unsigned int* val); + extern void i_int_unsigned_3d(unsigned int* val); + extern void i_integer_0d(svLogicVecVal* val); + extern void i_integer_1d(svLogicVecVal* val); + extern void i_integer_2d(svLogicVecVal* val); + extern void i_integer_3d(svLogicVecVal* val); + extern void i_logic121_0d(svLogicVecVal* val); + extern void i_logic121_1d(svLogicVecVal* val); + extern void i_logic121_2d(svLogicVecVal* val); + extern void i_logic121_3d(svLogicVecVal* val); + extern void i_logic1_0d(svLogic* val); + extern void i_logic1_1d(svLogic* val); + extern void i_logic1_2d(svLogic* val); + extern void i_logic1_3d(svLogic* val); + extern void i_logic7_0d(svLogicVecVal* val); + extern void i_logic7_1d(svLogicVecVal* val); + extern void i_logic7_2d(svLogicVecVal* val); + extern void i_logic7_3d(svLogicVecVal* val); + extern void i_longint_0d(long long* val); + extern void i_longint_1d(long long* val); + extern void i_longint_2d(long long* val); + extern void i_longint_3d(long long* val); + extern void i_longint_unsigned_0d(unsigned long long* val); + extern void i_longint_unsigned_1d(unsigned long long* val); + extern void i_longint_unsigned_2d(unsigned long long* val); + extern void i_longint_unsigned_3d(unsigned long long* val); + extern void i_pack_struct_0d(svLogicVecVal* val); + extern void i_pack_struct_1d(svLogicVecVal* val); + extern void i_pack_struct_2d(svLogicVecVal* val); + extern void i_pack_struct_3d(svLogicVecVal* val); + extern void i_real_0d(double* val); + extern void i_real_1d(double* val); + extern void i_real_2d(double* val); + extern void i_real_3d(double* val); + extern void i_shortint_0d(short* val); + extern void i_shortint_1d(short* val); + extern void i_shortint_2d(short* val); + extern void i_shortint_3d(short* val); + extern void i_shortint_unsigned_0d(unsigned short* val); + extern void i_shortint_unsigned_1d(unsigned short* val); + extern void i_shortint_unsigned_2d(unsigned short* val); + extern void i_shortint_unsigned_3d(unsigned short* val); + extern void i_string_0d(const char** val); + extern void i_string_1d(const char** val); + extern void i_string_2d(const char** val); + extern void i_string_3d(const char** val); + extern void i_time_0d(svLogicVecVal* val); + extern void i_time_1d(svLogicVecVal* val); + extern void i_time_2d(svLogicVecVal* val); + extern void i_time_3d(svLogicVecVal* val); + #ifdef __cplusplus } #endif diff --git a/test_regress/t/t_dpi_context.v b/test_regress/t/t_dpi_context.v index 70838b473..b0e11a23f 100644 --- a/test_regress/t/t_dpi_context.v +++ b/test_regress/t/t_dpi_context.v @@ -21,6 +21,9 @@ module t (); $finish; end + import "DPI-C" context function void dpic_final(); + final dpic_final(); + endmodule module sub (input integer inst); @@ -32,6 +35,15 @@ module sub (input integer inst); int result; + // Exports here are only to cover the export dumper of Verilated::internalsDump + export "DPI-C" function dpix_void; + function void dpix_void; + endfunction + export "DPI-C" function dpix_result; + function int dpix_result; + return result; + endfunction + task test1; // Check line numbering `ifndef verilator // Not all sims support SV2009 `__LINE__, and some that do fail the specific-line test diff --git a/test_regress/t/t_dpi_context_c.cpp b/test_regress/t/t_dpi_context_c.cpp index 50534b8e9..359aa05b2 100644 --- a/test_regress/t/t_dpi_context_c.cpp +++ b/test_regress/t/t_dpi_context_c.cpp @@ -82,6 +82,8 @@ int dpic_line() { extern int Dpic_Unique; int Dpic_Unique = 0; // Address used for uniqueness +extern int Dpic_Value; +int Dpic_Value = 0; // Address used for testing int dpic_save(int value) { svScope scope = svGetScope(); @@ -96,6 +98,21 @@ int dpic_save(int value) { int i; } vp; + // Load the value here, and below, to test we can reinsert correctly + if (svPutUserData(scope, &Dpic_Unique, &Dpic_Value)) { + printf("%%Warning: svPutUserData failed (initial)\n"); + return 0; + } + if (void* userp = svGetUserData(scope, &Dpic_Unique)) { + if (userp != &Dpic_Value) { + printf("%%Warning: svGetUserData failed (initial wrong data)\n"); + return 0; + } + } else { + printf("%%Warning: svGetUserData failed (initial)\n"); + return 0; + } + vp.i = value; if (vp.i) {} if (svPutUserData(scope, &Dpic_Unique, vp.ptr)) { @@ -132,3 +149,13 @@ unsigned dpic_getcontext() { scope, svGetNameFromScope(scope)); return (unsigned)(uintptr_t)scope; } + +void dpic_final() { + static int s_once = 0; + if (s_once++) return; + printf("%s:\n", __func__); +#ifdef VERILATOR + // Cover VerilatedImp::userDump + Verilated::internalsDump(); +#endif +} diff --git a/test_regress/t/t_dpi_import_c.cpp b/test_regress/t/t_dpi_import_c.cpp index 2771b70f1..c28c58d0e 100644 --- a/test_regress/t/t_dpi_import_c.cpp +++ b/test_regress/t/t_dpi_import_c.cpp @@ -124,7 +124,7 @@ void dpii_v_ushort(unsigned short i, unsigned short* o) { *o = ~i; } void dpii_v_longint(long long i, long long* o) { *o = ~i; } void dpii_v_ulong(unsigned long long i, unsigned long long* o) { *o = ~i; } void dpii_v_chandle(void* i, void** o) { *o = i; } -void dpii_v_string(const char* i, const char** o) { *o = strdup(i); } // Leaks +void dpii_v_string(const char* i, const char** o) { *o = i; } void dpii_v_real(double i, double* o) { *o = i + 1.5; } void dpii_v_shortreal(float i, float* o) { *o = i + 1.5f; } diff --git a/test_regress/t/t_dpi_open.v b/test_regress/t/t_dpi_open.v index 09bce4338..e78d01b3b 100644 --- a/test_regress/t/t_dpi_open.v +++ b/test_regress/t/t_dpi_open.v @@ -6,11 +6,11 @@ // Version 2.0. // SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 -`ifdef VERILATOR +//`ifdef VERILATOR `define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0) -`else - `define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); end while(0) -`endif +//`else +// `define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); end while(0) +//`endif module t (/*AUTOARG*/); @@ -48,11 +48,8 @@ module t (/*AUTOARG*/); logic o_logic [1:0]; byte i_byte [1:0]; byte o_byte [1:0]; - int i_int [1:0]; - int o_int [1:0]; integer i_integer [1:0]; integer o_integer [1:0]; - // verilator lint_on UNUSED import "DPI-C" function int dpii_failure(); @@ -60,6 +57,7 @@ module t (/*AUTOARG*/); // [] on packed arrays is unsupported in VCS & NC, so not supporting this + // p is number of packed dimensions, u is number of unpacked dimensions import "DPI-C" function void dpii_open_p0_u1(input int c,p,u, input reg i [], output reg o []); import "DPI-C" function void dpii_open_p1_u1(input int c,p,u, input reg [1:-1] i [], output reg [1:-1] o []); import "DPI-C" function void dpii_open_p1_u2(input int c,p,u, input reg [1:-1] i [] [], output reg [1:-1] o [] []); @@ -72,10 +70,19 @@ module t (/*AUTOARG*/); import "DPI-C" function void dpii_open_bit(input bit i [], output bit o []); import "DPI-C" function void dpii_open_logic(input logic i [], output logic o []); import "DPI-C" function void dpii_open_byte(input byte i [], output byte o []); - import "DPI-C" function void dpii_open_int(input int i [], output int o []); import "DPI-C" function void dpii_open_integer(input integer i [], output integer o []); - import "DPI-C" function int dpii_failed(); + int i_int_u1 [2:-2]; + int o_int_u1 [2:-2]; + int i_int_u2 [2:-2] [-3:3]; + int o_int_u2 [2:-2] [-3:3]; + int i_int_u3 [2:-2] [-3:3] [4:-4]; + int o_int_u3 [2:-2] [-3:3] [4:-4]; + import "DPI-C" function void dpii_open_int_u1(int u, input int i [], output int o []); + import "DPI-C" function void dpii_open_int_u2(int u, input int i [] [], output int o [] []); + import "DPI-C" function void dpii_open_int_u3(int u, input int i [] [] [], output int o [] [] []); + + // verilator lint_on UNUSED reg [95:0] crc; @@ -86,7 +93,6 @@ module t (/*AUTOARG*/); i_bit[a] = crc[0]; i_logic[a] = crc[0]; i_byte[a] = crc[7:0]; - i_int[a] = crc[31:0]; i_integer[a] = crc[31:0]; crc = {crc[94:0], crc[95]^crc[2]^crc[0]}; end @@ -94,7 +100,6 @@ module t (/*AUTOARG*/); dpii_open_bit(i_bit, o_bit); dpii_open_logic(i_logic, o_logic); dpii_open_byte(i_byte, o_byte); - dpii_open_int(i_int, o_int); dpii_open_integer(i_integer, o_integer); for (int a=-2; a<=2; a=a+1) begin @@ -104,14 +109,17 @@ module t (/*AUTOARG*/); i_rl_p1_u1[a] = crc[2:0]; i_rb_p1_u1[a] = crc[2:0]; i_rw_p1_u1[a] = crc[94:0]; + i_int_u1[a] = crc[31:0]; for (int b=-3; b<=3; b=b+1) begin i_rl_p1_u2[a][b] = crc[2:0]; i_rb_p1_u2[a][b] = crc[2:0]; i_rw_p1_u2[a][b] = crc[94:0]; + i_int_u2[a][b] = crc[31:0]; for (int c=-4; c<=4; c=c+1) begin i_rl_p1_u3[a][b][c] = crc[2:0]; i_rb_p1_u3[a][b][c] = crc[2:0]; i_rw_p1_u3[a][b][c] = crc[94:0]; + i_int_u3[a][b][c] = crc[31:0]; crc = {crc[94:0], crc[95]^crc[2]^crc[0]}; end end @@ -138,6 +146,19 @@ module t (/*AUTOARG*/); end end + dpii_open_int_u1(1, i_int_u1, o_int_u1); + dpii_open_int_u2(2, i_int_u2, o_int_u2); + dpii_open_int_u3(3, i_int_u3, o_int_u3); + for (int a=-2; a<=2; a=a+1) begin + `checkh(o_int_u1[a], ~i_int_u1[a]); + for (int b=-3; b<=3; b=b+1) begin + `checkh(o_int_u2[a][b], ~i_int_u2[a][b]); + for (int c=-4; c<=4; c=c+1) begin + `checkh(o_int_u3[a][b][c], ~i_int_u3[a][b][c]); + end + end + end + if (dpii_failure()!=0) begin $write("%%Error: Failure in DPI tests\n"); $stop; diff --git a/test_regress/t/t_dpi_open_c.cpp b/test_regress/t/t_dpi_open_c.cpp index b4aa42c56..cff5d506a 100644 --- a/test_regress/t/t_dpi_open_c.cpp +++ b/test_regress/t/t_dpi_open_c.cpp @@ -62,44 +62,17 @@ extern void dpii_open_int(const svOpenArrayHandle i, const svOpenArrayHandle o); extern void dpii_open_integer(const svOpenArrayHandle i, const svOpenArrayHandle o); extern void dpii_open_logic(const svOpenArrayHandle i, const svOpenArrayHandle o); +extern void dpii_open_int_u1(int u, const svOpenArrayHandle i, const svOpenArrayHandle o); +extern void dpii_open_int_u2(int u, const svOpenArrayHandle i, const svOpenArrayHandle o); +extern void dpii_open_int_u3(int u, const svOpenArrayHandle i, const svOpenArrayHandle o); + extern int dpii_failure(); } #endif -//====================================================================== - -// Untested: -// void *svGetArrElemPtr(const svOpenArrayHandle, int indx1, ...); -// void svPutBitArrElemVecVal(const svOpenArrayHandle d, const svBitVecVal* s, int indx1, ...); -// void svPutBitArrElem1VecVal(const svOpenArrayHandle d, const svBitVecVal* s, int indx1); -// void svPutLogicArrElemVecVal(const svOpenArrayHandle d, const svLogicVecVal* s, int indx1, ...); -// void svPutLogicArrElem1VecVal(const svOpenArrayHandle d, const svLogicVecVal* s, int indx1); -// void svGetBitArrElemVecVal(svBitVecVal* d, const svOpenArrayHandle s, int indx1, ...); -// void svGetBitArrElem1VecVal(svBitVecVal* d, const svOpenArrayHandle s, int indx1); -// void svGetLogicArrElemVecVal(svLogicVecVal* d, const svOpenArrayHandle s, int indx1, ...); -// void svGetLogicArrElem1VecVal(svLogicVecVal* d, const svOpenArrayHandle s, int indx1); -// svBit svGetBitArrElem(const svOpenArrayHandle s, int indx1, ...); -// svBit svGetBitArrElem1(const svOpenArrayHandle s, int indx1); -// svLogic svGetLogicArrElem(const svOpenArrayHandle s, int indx1, ...); -// svLogic svGetLogicArrElem1(const svOpenArrayHandle s, int indx1); -// void svPutBitArrElem(const svOpenArrayHandle d, svBit value, int indx1, ...); -// void svPutBitArrElem1(const svOpenArrayHandle d, svBit value, int indx1); -// void svPutLogicArrElem(const svOpenArrayHandle d, svLogic value, int indx1, ...); -// void svPutLogicArrElem1(const svOpenArrayHandle d, svLogic value, int indx1); - -//====================================================================== - int failure = 0; int dpii_failure() { return failure; } -// clang-format off -#ifdef _WIN32 -# define T_PRI64 "I64" -#else // Linux or compliant Unix flavors -# define T_PRI64 "ll" -#endif -// clang-format on - #define CHECK_RESULT_HEX(got, exp) \ do { \ if ((got) != (exp)) { \ @@ -122,8 +95,8 @@ void dpii_unused(const svOpenArrayHandle u) {} void _dpii_all(int c, int p, int u, const svOpenArrayHandle i, const svOpenArrayHandle o) { #ifdef TEST_VERBOSE - printf("-:%s:%d: For case c=%d p=%d u=%d data=%p\n", // - __FILE__, __LINE__, c, p, u, svGetArrayPtr(i)); + fprintf(stderr, "-:%s:%d: For case c=%d p=%d u=%d data=%p\n", // + __FILE__, __LINE__, c, p, u, svGetArrayPtr(i)); #endif (void)svGetArrayPtr(i); #ifndef NC @@ -260,18 +233,63 @@ void dpii_open_byte(const svOpenArrayHandle i, const svOpenArrayHandle o) { #endif } -void dpii_open_int(const svOpenArrayHandle i, const svOpenArrayHandle o) { +void dpii_open_integer(const svOpenArrayHandle i, const svOpenArrayHandle o) {} +void dpii_open_logic(const svOpenArrayHandle i, const svOpenArrayHandle o) {} + +static void _dpii_open_int_ux(int u, const svOpenArrayHandle i, const svOpenArrayHandle o) { intptr_t arrPtr = (intptr_t)svGetArrayPtr(i); CHECK_RESULT_HEX_NE(arrPtr, 0); // All the arrays should actually exist #ifndef NC // NC always returns zero and warns int sizeInputOfArray = svSizeOfArray(i); CHECK_RESULT_HEX_NE(sizeInputOfArray, 0); // None of the test cases have zero size - CHECK_RESULT_HEX_NE(svDimensions(i), 0); // All the test cases are unpacked arrays + CHECK_RESULT_HEX(svDimensions(i), u); #endif + + int dim = svDimensions(i); + + for (int a = svLow(i, 1); a <= svHigh(i, 1); ++a) { + if (dim == 1) { + intptr_t ip = (intptr_t)svGetArrElemPtr(i, a); + intptr_t i2p = (intptr_t)svGetArrElemPtr1(i, a); + CHECK_RESULT_HEX(ip, i2p); + CHECK_RESULT_HEX_NE(ip, 0); + intptr_t op = (intptr_t)svGetArrElemPtr(o, a); + CHECK_RESULT_HEX_NE(op, 0); + *reinterpret_cast(op) = ~*reinterpret_cast(ip); + } else { + for (int b = svLow(i, 2); b <= svHigh(i, 2); ++b) { + if (dim == 2) { + intptr_t ip = (intptr_t)svGetArrElemPtr(i, a, b); + intptr_t i2p = (intptr_t)svGetArrElemPtr2(i, a, b); + CHECK_RESULT_HEX(ip, i2p); + CHECK_RESULT_HEX_NE(ip, 0); + intptr_t op = (intptr_t)svGetArrElemPtr(o, a, b); + CHECK_RESULT_HEX_NE(op, 0); + *reinterpret_cast(op) = ~*reinterpret_cast(ip); + } else { + for (int c = svLow(i, 3); c <= svHigh(i, 3); ++c) { + if (dim == 3) { + intptr_t ip = (intptr_t)svGetArrElemPtr(i, a, b, c); + intptr_t i2p = (intptr_t)svGetArrElemPtr3(i, a, b, c); + CHECK_RESULT_HEX(ip, i2p); + CHECK_RESULT_HEX_NE(ip, 0); + intptr_t op = (intptr_t)svGetArrElemPtr(o, a, b, c); + CHECK_RESULT_HEX_NE(op, 0); + *reinterpret_cast(op) = ~*reinterpret_cast(ip); + } + } + } + } + } + } +} +void dpii_open_int_u1(int u, const svOpenArrayHandle i, const svOpenArrayHandle o) { + _dpii_open_int_ux(u, i, o); +} +void dpii_open_int_u2(int u, const svOpenArrayHandle i, const svOpenArrayHandle o) { + _dpii_open_int_ux(u, i, o); +} +void dpii_open_int_u3(int u, const svOpenArrayHandle i, const svOpenArrayHandle o) { + _dpii_open_int_ux(u, i, o); } - -void dpii_open_integer(const svOpenArrayHandle i, const svOpenArrayHandle o) {} -void dpii_open_logic(const svOpenArrayHandle i, const svOpenArrayHandle o) {} - -int dpii_failed() { return failure; } diff --git a/test_regress/t/t_dpi_open_elem.pl b/test_regress/t/t_dpi_open_elem.pl new file mode 100755 index 000000000..ab9367bf0 --- /dev/null +++ b/test_regress/t/t_dpi_open_elem.pl @@ -0,0 +1,23 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(simulator => 1); + +compile( + v_flags2 => ["t/t_dpi_open_elem_c.cpp"], + verilator_flags2 => ["-Wall -Wno-DECLFILENAME -unroll-count 1"], + ); + +execute( + check_finished => 1, + ); + +ok(1); +1; diff --git a/test_regress/t/t_dpi_open_elem.v b/test_regress/t/t_dpi_open_elem.v new file mode 100644 index 000000000..c2b38f00a --- /dev/null +++ b/test_regress/t/t_dpi_open_elem.v @@ -0,0 +1,118 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// Copyright 2017 by Wilson Snyder. This program is free software; you can +// redistribute it and/or modify it under the terms of either the GNU +// Lesser General Public License Version 3 or the Perl Artistic License +// Version 2.0. +// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + + `define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0) + +module t (/*AUTOARG*/); + + bit i_bit_p0_u1 [2:-2]; + bit o_bit_p0_u1 [2:-2]; + bit q_bit_p0_u1 [2:-2]; + bit i_bit_p0_u2 [2:-2] [-3:3]; + bit o_bit_p0_u2 [2:-2] [-3:3]; + bit q_bit_p0_u2 [2:-2] [-3:3]; + bit i_bit_p0_u3 [2:-2] [-3:3] [4:-4]; + bit o_bit_p0_u3 [2:-2] [-3:3] [4:-4]; + bit q_bit_p0_u3 [2:-2] [-3:3] [4:-4]; + import "DPI-C" function void dpii_bit_elem_p0_u1 + (int p, int u, input bit i [], output bit o [], output bit q []); + import "DPI-C" function void dpii_bit_elem_p0_u2 + (int p, int u, input bit i [] [], output bit o [] [], output bit q [] []); + import "DPI-C" function void dpii_bit_elem_p0_u3 + (int p, int u, input bit i [] [] [], output bit o [] [] [], output bit q [] [] []); + + logic i_logic_p0_u1 [2:-2]; + logic o_logic_p0_u1 [2:-2]; + logic q_logic_p0_u1 [2:-2]; + logic i_logic_p0_u2 [2:-2] [-3:3]; + logic o_logic_p0_u2 [2:-2] [-3:3]; + logic q_logic_p0_u2 [2:-2] [-3:3]; + logic i_logic_p0_u3 [2:-2] [-3:3] [4:-4]; + logic o_logic_p0_u3 [2:-2] [-3:3] [4:-4]; + logic q_logic_p0_u3 [2:-2] [-3:3] [4:-4]; + import "DPI-C" function void dpii_logic_elem_p0_u1(int p, int u, input logic i [], + output logic o [], output logic q []); + import "DPI-C" function void dpii_logic_elem_p0_u2(int p, int u, input logic i [] [], + output logic o [] [], output logic q [] []); + import "DPI-C" function void dpii_logic_elem_p0_u3(int p, int u, input logic i [] [] [], + output logic o [] [] [], output logic q [] [] []); + + import "DPI-C" function int dpii_failure(); + + reg [95:0] crc; + + initial begin + crc = 96'h8a10a572_5aef0c8d_d70a4497; + + begin + for (int a=-2; a<=2; a=a+1) begin + i_bit_p0_u1[a] = crc[0]; + for (int b=-3; b<=3; b=b+1) begin + i_bit_p0_u2[a][b] = crc[0]; + for (int c=-4; c<=4; c=c+1) begin + i_bit_p0_u3[a][b][c] = crc[0]; + crc = {crc[94:0], crc[95]^crc[2]^crc[0]}; + end + end + end + dpii_bit_elem_p0_u1(0, 1, i_bit_p0_u1, o_bit_p0_u1, q_bit_p0_u1); + dpii_bit_elem_p0_u2(0, 2, i_bit_p0_u2, o_bit_p0_u2, q_bit_p0_u2); + dpii_bit_elem_p0_u3(0, 3, i_bit_p0_u3, o_bit_p0_u3, q_bit_p0_u3); + for (int a=-2; a<=2; a=a+1) begin + `checkh(o_bit_p0_u1[a], ~i_bit_p0_u1[a]); + `checkh(q_bit_p0_u1[a], ~i_bit_p0_u1[a]); + for (int b=-3; b<=3; b=b+1) begin + `checkh(o_bit_p0_u2[a][b], ~i_bit_p0_u2[a][b]); + `checkh(q_bit_p0_u2[a][b], ~i_bit_p0_u2[a][b]); + for (int c=-4; c<=4; c=c+1) begin + `checkh(o_bit_p0_u3[a][b][c], ~i_bit_p0_u3[a][b][c]); + `checkh(q_bit_p0_u3[a][b][c], ~i_bit_p0_u3[a][b][c]); + end + end + end + end + + begin + for (int a=-2; a<=2; a=a+1) begin + i_logic_p0_u1[a] = crc[0]; + for (int b=-3; b<=3; b=b+1) begin + i_logic_p0_u2[a][b] = crc[0]; + for (int c=-4; c<=4; c=c+1) begin + i_logic_p0_u3[a][b][c] = crc[0]; + crc = {crc[94:0], crc[95]^crc[2]^crc[0]}; + end + end + end + dpii_logic_elem_p0_u1(0, 1, i_logic_p0_u1, o_logic_p0_u1, q_logic_p0_u1); + dpii_logic_elem_p0_u2(0, 2, i_logic_p0_u2, o_logic_p0_u2, q_logic_p0_u2); + dpii_logic_elem_p0_u3(0, 3, i_logic_p0_u3, o_logic_p0_u3, q_logic_p0_u3); + for (int a=-2; a<=2; a=a+1) begin + `checkh(o_logic_p0_u1[a], ~i_logic_p0_u1[a]); + `checkh(q_logic_p0_u1[a], ~i_logic_p0_u1[a]); + for (int b=-3; b<=3; b=b+1) begin + `checkh(o_logic_p0_u2[a][b], ~i_logic_p0_u2[a][b]); + `checkh(q_logic_p0_u2[a][b], ~i_logic_p0_u2[a][b]); + for (int c=-4; c<=4; c=c+1) begin + `checkh(o_logic_p0_u3[a][b][c], ~i_logic_p0_u3[a][b][c]); + `checkh(q_logic_p0_u3[a][b][c], ~i_logic_p0_u3[a][b][c]); + end + end + end + end + + if (dpii_failure()!=0) begin + $write("%%Error: Failure in DPI tests\n"); + $stop; + end + else begin + $write("*-* All Finished *-*\n"); + $finish; + end + end + +endmodule diff --git a/test_regress/t/t_dpi_open_elem_c.cpp b/test_regress/t/t_dpi_open_elem_c.cpp new file mode 100644 index 000000000..72a8793a4 --- /dev/null +++ b/test_regress/t/t_dpi_open_elem_c.cpp @@ -0,0 +1,188 @@ +// -*- mode: C++; c-file-style: "cc-mode" -*- +//************************************************************************* +// +// Copyright 2009-2017 by Wilson Snyder. This program is free software; you can +// redistribute it and/or modify it under the terms of either the GNU +// Lesser General Public License Version 3 or the Perl Artistic License +// Version 2.0. +// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 +// +//************************************************************************* + +#include +#include +#include +#include "svdpi.h" + +//====================================================================== + +// clang-format off +#if defined(VERILATOR) +# include "Vt_dpi_open_elem__Dpi.h" +#elif defined(VCS) +# include "../vc_hdrs.h" +#elif defined(NC) +# define NEED_EXTERNS +// #elif defined(MS) +// # define NEED_EXTERNS +#else +# error "Unknown simulator for DPI test" +#endif +// clang-format on + +#ifdef NEED_EXTERNS +extern "C" { +// If get ncsim: *F,NOFDPI: Function {foo} not found in default libdpi. +// Then probably forgot to list a function here. + +void dpii_bit_elem_p0_u1(int p, int u, const svOpenArrayHandle i, const svOpenArrayHandle o, + const svOpenArrayHandle q); +void dpii_bit_elem_p0_u2(int p, int u, const svOpenArrayHandle i, const svOpenArrayHandle o, + const svOpenArrayHandle q); +void dpii_bit_elem_p0_u3(int p, int u, const svOpenArrayHandle i, const svOpenArrayHandle o, + const svOpenArrayHandle q); +void dpii_logic_elem_p0_u1(int p, int u, const svOpenArrayHandle i, const svOpenArrayHandle o, + const svOpenArrayHandle q); +void dpii_logic_elem_p0_u2(int p, int u, const svOpenArrayHandle i, const svOpenArrayHandle o, + const svOpenArrayHandle q); +void dpii_logic_elem_p0_u3(int p, int u, const svOpenArrayHandle i, const svOpenArrayHandle o, + const svOpenArrayHandle q); + +extern int dpii_failure(); +} +#endif + +int failure = 0; +int dpii_failure() { return failure; } + +#define CHECK_RESULT_HEX(got, exp) \ + do { \ + if ((got) != (exp)) { \ + std::cout << std::dec << "%Error: " << __FILE__ << ":" << __LINE__ << std::hex \ + << ": GOT=" << (got) << " EXP=" << (exp) << std::endl; \ + failure = __LINE__; \ + } \ + } while (0) + +#define CHECK_RESULT_HEX_NE(got, exp) \ + do { \ + if ((got) == (exp)) { \ + std::cout << std::dec << "%Error: " << __FILE__ << ":" << __LINE__ << std::hex \ + << ": GOT=" << (got) << " EXP!=" << (exp) << std::endl; \ + failure = __LINE__; \ + } \ + } while (0) + +void dpii_unused(const svOpenArrayHandle u) {} + +//====================================================================== + +static void _dpii_bit_elem_ux(int p, int u, const svOpenArrayHandle i, const svOpenArrayHandle o, + const svOpenArrayHandle q) { + int dim = svDimensions(i); +#ifndef NC + // NC always returns zero and warns + CHECK_RESULT_HEX(dim, u); + // svSizeOfArray(i) undeterministic as not in C representation +#endif + + for (int a = svLow(i, 1); a <= svHigh(i, 1); ++a) { + fflush(stdout); + if (dim == 1) { + svBit v = svGetBitArrElem(i, a); + svBit v2 = svGetBitArrElem1(i, a); + CHECK_RESULT_HEX(v, v2); + svPutBitArrElem(o, v ? 0 : 1, a); + svPutBitArrElem1(q, v ? 0 : 1, a); + } else { + for (int b = svLow(i, 2); b <= svHigh(i, 2); ++b) { + if (dim == 2) { + svBit v = svGetBitArrElem(i, a, b); + svBit v2 = svGetBitArrElem2(i, a, b); + CHECK_RESULT_HEX(v, v2); + svPutBitArrElem(o, v ? 0 : 1, a, b); + svPutBitArrElem2(q, v ? 0 : 1, a, b); + } else { + for (int c = svLow(i, 3); c <= svHigh(i, 3); ++c) { + if (dim == 3) { + svBit v = svGetBitArrElem(i, a, b, c); + svBit v2 = svGetBitArrElem3(i, a, b, c); + CHECK_RESULT_HEX(v, v2); + svPutBitArrElem(o, v ? 0 : 1, a, b, c); + svPutBitArrElem3(q, v ? 0 : 1, a, b, c); + } + } + } + } + } + } + fflush(stdout); +} +void dpii_bit_elem_p0_u1(int p, int u, const svOpenArrayHandle i, const svOpenArrayHandle o, + const svOpenArrayHandle q) { + _dpii_bit_elem_ux(p, u, i, o, q); +} +void dpii_bit_elem_p0_u2(int p, int u, const svOpenArrayHandle i, const svOpenArrayHandle o, + const svOpenArrayHandle q) { + _dpii_bit_elem_ux(p, u, i, o, q); +} +void dpii_bit_elem_p0_u3(int p, int u, const svOpenArrayHandle i, const svOpenArrayHandle o, + const svOpenArrayHandle q) { + _dpii_bit_elem_ux(p, u, i, o, q); +} + +//====================================================================== + +static void _dpii_logic_elem_ux(int p, int u, const svOpenArrayHandle i, const svOpenArrayHandle o, + const svOpenArrayHandle q) { + int sizeInputOfArray = svSizeOfArray(i); + int dim = svDimensions(i); +#ifndef NC + // NC always returns zero and warns + CHECK_RESULT_HEX(dim, u); + // svSizeOfArray(i) undeterministic as not in C representation +#endif + + for (int a = svLow(i, 1); a <= svHigh(i, 1); ++a) { + if (dim == 1) { + svLogic v = svGetLogicArrElem(i, a); + svLogic v2 = svGetLogicArrElem1(i, a); + CHECK_RESULT_HEX(v, v2); + svPutLogicArrElem(o, v ? 0 : 1, a); + svPutLogicArrElem1(q, v ? 0 : 1, a); + } else { + for (int b = svLow(i, 2); b <= svHigh(i, 2); ++b) { + if (dim == 2) { + svLogic v = svGetLogicArrElem(i, a, b); + svLogic v2 = svGetLogicArrElem2(i, a, b); + CHECK_RESULT_HEX(v, v2); + svPutLogicArrElem(o, v ? 0 : 1, a, b); + svPutLogicArrElem2(q, v ? 0 : 1, a, b); + } else { + for (int c = svLow(i, 3); c <= svHigh(i, 3); ++c) { + if (dim == 3) { + svLogic v = svGetLogicArrElem(i, a, b, c); + svLogic v2 = svGetLogicArrElem3(i, a, b, c); + CHECK_RESULT_HEX(v, v2); + svPutLogicArrElem(o, v ? 0 : 1, a, b, c); + svPutLogicArrElem3(q, v ? 0 : 1, a, b, c); + } + } + } + } + } + } + fflush(stdout); +} +void dpii_logic_elem_p0_u1(int p, int u, const svOpenArrayHandle i, const svOpenArrayHandle o, + const svOpenArrayHandle q) { + _dpii_logic_elem_ux(p, u, i, o, q); +} +void dpii_logic_elem_p0_u2(int p, int u, const svOpenArrayHandle i, const svOpenArrayHandle o, + const svOpenArrayHandle q) { + _dpii_logic_elem_ux(p, u, i, o, q); +} +void dpii_logic_elem_p0_u3(int p, int u, const svOpenArrayHandle i, const svOpenArrayHandle o, + const svOpenArrayHandle q) { + _dpii_logic_elem_ux(p, u, i, o, q); +} diff --git a/test_regress/t/t_dpi_open_oob_bad.out b/test_regress/t/t_dpi_open_oob_bad.out new file mode 100644 index 000000000..a40343874 --- /dev/null +++ b/test_regress/t/t_dpi_open_oob_bad.out @@ -0,0 +1,27 @@ +dpii_nullptr: +dpii_int_u3: +%Warning: DPI svOpenArrayHandle function index 3 out of bounds; 1 outside [4:-4]. +%Warning: DPI svOpenArrayHandle function index 2 out of bounds; 20 outside [-3:3]. +%Warning: DPI svOpenArrayHandle function index 1 out of bounds; 10 outside [2:-2]. +%Warning: DPI svOpenArrayHandle function called on 3 dimensional array using 1 dimensional function. +dpii_real_u1: +%Warning: DPI svOpenArrayHandle function unsupported datatype (5). +%Warning: DPI svOpenArrayHandle function unsupported datatype (5). +%Warning: DPI svOpenArrayHandle function unsupported datatype (5). +%Warning: DPI svOpenArrayHandle function unsupported datatype (5). +%Warning: DPI svOpenArrayHandle function unsupported datatype (5). +%Warning: DPI svOpenArrayHandle function unsupported datatype (5). +%Warning: DPI svOpenArrayHandle function unsupported datatype (5). +%Warning: DPI svOpenArrayHandle function unsupported datatype (5). +dpii_bit_u6: +%Warning: DPI svOpenArrayHandle function called on 6 dimensional array using -1 dimensional function. +%Warning: DPI svOpenArrayHandle function called on 6 dimensional array using -1 dimensional function. +%Warning: DPI svOpenArrayHandle function called on 6 dimensional array using -1 dimensional function. +%Warning: DPI svOpenArrayHandle function called on 6 dimensional array using -1 dimensional function. +%Warning: DPI svOpenArrayHandle function called on 6 dimensional array using -1 dimensional function. +%Warning: DPI svOpenArrayHandle function called on 6 dimensional array using -1 dimensional function. +%Warning: DPI svOpenArrayHandle function called on 6 dimensional array using -1 dimensional function. +%Warning: DPI svOpenArrayHandle function called on 6 dimensional array using -1 dimensional function. +dpii_real_u6: +%Warning: DPI svOpenArrayHandle function called on 6 dimensional array using -1 dimensional function. +*-* All Finished *-* diff --git a/test_regress/t/t_dpi_open_oob_bad.pl b/test_regress/t/t_dpi_open_oob_bad.pl new file mode 100755 index 000000000..8f02d74a8 --- /dev/null +++ b/test_regress/t/t_dpi_open_oob_bad.pl @@ -0,0 +1,24 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(vlt => 1); + +compile( + v_flags2 => ["t/t_dpi_open_oob_bad_c.cpp"], + verilator_flags2 => ["-Wall -Wno-DECLFILENAME -unroll-count 1"], + ); + +execute( + fails => 0, # DPI warnings are not errors + expect_filename => $Self->{golden_filename}, + ); + +ok(1); +1; diff --git a/test_regress/t/t_dpi_open_oob_bad.v b/test_regress/t/t_dpi_open_oob_bad.v new file mode 100644 index 000000000..579ac523e --- /dev/null +++ b/test_regress/t/t_dpi_open_oob_bad.v @@ -0,0 +1,40 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// Copyright 2020 by Wilson Snyder. This program is free software; you can +// redistribute it and/or modify it under the terms of either the GNU +// Lesser General Public License Version 3 or the Perl Artistic License +// Version 2.0. +// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +module t (/*AUTOARG*/); + + import "DPI-C" function void dpii_nullptr(); + + // verilator lint_off UNDRIVEN + int i_int_u3 [2:-2] [-3:3] [4:-4]; + import "DPI-C" function void dpii_int_u3(input int i [] [] []); + + real i_real_u1 [1:0]; + import "DPI-C" function void dpii_real_u1(input real i []); + + bit i_u6 [2][2][2][2][2][2]; + import "DPI-C" function void dpii_bit_u6(input bit i [][][][][][]); + + real i_real_u6 [2][2][2][2][2][2]; + import "DPI-C" function void dpii_real_u6(input real i [][][][][][]); + + initial begin + i_int_u3[0][0][0] = 32'hbad; + i_real_u1[0] = 1.1; + i_u6[0][0][0][0][0][0] = 1'b1; + + dpii_nullptr(); + dpii_int_u3(i_int_u3); + dpii_real_u1(i_real_u1); + dpii_bit_u6(i_u6); + dpii_real_u6(i_real_u6); + $write("*-* All Finished *-*\n"); + $finish; + end + +endmodule diff --git a/test_regress/t/t_dpi_open_oob_bad_c.cpp b/test_regress/t/t_dpi_open_oob_bad_c.cpp new file mode 100644 index 000000000..5ed9853c0 --- /dev/null +++ b/test_regress/t/t_dpi_open_oob_bad_c.cpp @@ -0,0 +1,156 @@ +// -*- mode: C++; c-file-style: "cc-mode" -*- +//************************************************************************* +// +// Copyright 2009-2020 by Wilson Snyder. This program is free software; you can +// redistribute it and/or modify it under the terms of either the GNU +// Lesser General Public License Version 3 or the Perl Artistic License +// Version 2.0. +// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 +// +//************************************************************************* + +#include +#include +#include +#include "svdpi.h" + +//====================================================================== + +// clang-format off +#if defined(VERILATOR) +# include "Vt_dpi_open_oob_bad__Dpi.h" +#else +# error "Unknown simulator for DPI test" +#endif +// clang-format on + +#define CHECK_RESULT_HEX(got, exp) \ + do { \ + if ((got) != (exp)) { \ + std::cout << std::dec << "%Error: " << __FILE__ << ":" << __LINE__ << std::hex \ + << ": GOT=" << (got) << " EXP=" << (exp) << std::endl; \ + failure = __LINE__; \ + } \ + } while (0) + +#define CHECK_RESULT_HEX_NE(got, exp) \ + do { \ + if ((got) == (exp)) { \ + std::cout << std::dec << "%Error: " << __FILE__ << ":" << __LINE__ << std::hex \ + << ": GOT=" << (got) << " EXP!=" << (exp) << std::endl; \ + failure = __LINE__; \ + } \ + } while (0) + +//====================================================================== + +int failure = 0; + +void dpii_nullptr() { + printf("%s:\n", __func__); + // These cause fatal errors, so each would need a separate run + // svOpenArrayHandle h = nullptr; + // svBitVecVal bit_vec_val[2]; + // svLogicVecVal logic_vec_val[2]; + // svDimensions(h); + // svGetArrayPtr(h); + // svHigh(h, 0); + // svIncrement(h, 0); + // svLeft(h, 0); + // svLow(h, 0); + // svRight(h, 0); + // svSize(h, 0); + // svSizeOfArray(h); + // + // svGetArrElemPtr(h, 0); + // svGetArrElemPtr1(h, 0); + // svGetArrElemPtr2(h, 0, 0); + // svGetArrElemPtr3(h, 0, 0, 0); + // svGetBitArrElem(h, 0); + // svGetBitArrElem1(h, 0); + // svGetBitArrElem1VecVal(bit_vec_val, h, 0); + // svGetBitArrElem2(h, 0, 0); + // svGetBitArrElem2VecVal(bit_vec_val, h, 0, 0); + // svGetBitArrElem3(h, 0, 0, 0); + // svGetBitArrElem3VecVal(bit_vec_val, h, 0, 0, 0); + // svGetBitArrElemVecVal(bit_vec_val, h, 0); + // svGetLogicArrElem(h, 0); + // svGetLogicArrElem1(h, 0); + // svGetLogicArrElem1VecVal(logic_vec_val, h, 0); + // svGetLogicArrElem2(h, 0, 0); + // svGetLogicArrElem2VecVal(logic_vec_val, h, 0, 0); + // svGetLogicArrElem3(h, 0, 0, 0); + // svGetLogicArrElem3VecVal(logic_vec_val, h, 0, 0, 0); + // svGetLogicArrElemVecVal(logic_vec_val, h, 0); + // svPutBitArrElem(h, 0, 0); + // svPutBitArrElem1(h, 0, 0); + // svPutBitArrElem1VecVal(h, bit_vec_val, 0); + // svPutBitArrElem2(h, 0, 0, 0); + // svPutBitArrElem2VecVal(h, bit_vec_val, 0, 0); + // svPutBitArrElem3(h, 0, 0, 0, 0); + // svPutBitArrElem3VecVal(h, bit_vec_val, 0, 0, 0); + // svPutBitArrElemVecVal(h, bit_vec_val, 0); + // svPutLogicArrElem(h, 0, 0); + // svPutLogicArrElem1(h, 0, 0); + // svPutLogicArrElem1VecVal(h, logic_vec_val, 0); + // svPutLogicArrElem2(h, 0, 0, 0); + // svPutLogicArrElem2VecVal(h, logic_vec_val, 0, 0); + // svPutLogicArrElem3(h, 0, 0, 0, 0); + // svPutLogicArrElem3VecVal(h, logic_vec_val, 0, 0, 0); + // svPutLogicArrElemVecVal(h, logic_vec_val, 0); +} + +void dpii_int_u3(const svOpenArrayHandle i) { + printf("%s:\n", __func__); + // Correct usage + intptr_t ip = (intptr_t)svGetArrElemPtr3(i, 1, 2, 3); + CHECK_RESULT_HEX_NE(ip, 0); + // Out of bounds + ip = (intptr_t)svGetArrElemPtr3(i, 1, 2, 30); + ip = (intptr_t)svGetArrElemPtr3(i, 1, 20, 3); + ip = (intptr_t)svGetArrElemPtr3(i, 10, 2, 3); + ip = (intptr_t)svGetArrElemPtr1(i, 30); +} + +void dpii_real_u1(const svOpenArrayHandle i) { + printf("%s:\n", __func__); + svBitVecVal bit_vec_val[4]; + svLogicVecVal logic_vec_val[4]; + + svGetBitArrElem(i, 0); + svGetBitArrElem1(i, 0); + svGetBitArrElem1VecVal(bit_vec_val, i, 0); + svGetBitArrElemVecVal(bit_vec_val, i, 0); + svGetLogicArrElem(i, 0); + svGetLogicArrElem1(i, 0); + svGetLogicArrElem1VecVal(logic_vec_val, i, 0); + svGetLogicArrElemVecVal(logic_vec_val, i, 0); + svPutBitArrElem(i, 0, 0); + svPutBitArrElem1(i, 0, 0); + svPutBitArrElem1VecVal(i, bit_vec_val, 0); + svPutBitArrElemVecVal(i, bit_vec_val, 0); + svPutLogicArrElem(i, 0, 0); + svPutLogicArrElem1(i, 0, 0); + svPutLogicArrElem1VecVal(i, logic_vec_val, 0); + svPutLogicArrElemVecVal(i, logic_vec_val, 0); +} + +void dpii_bit_u6(const svOpenArrayHandle i) { + printf("%s:\n", __func__); + svBitVecVal bit_vec_val[4]; + svLogicVecVal logic_vec_val[4]; + + svGetBitArrElem(i, 0, 0, 0, 0, 0, 0); + svGetBitArrElemVecVal(bit_vec_val, i, 0, 0, 0, 0, 0, 0); + svGetLogicArrElem(i, 0, 0, 0, 0, 0, 0); + svGetLogicArrElemVecVal(logic_vec_val, i, 0, 0, 0, 0, 0, 0); + svPutBitArrElem(i, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + svPutBitArrElemVecVal(i, bit_vec_val, 0, 0, 0, 0, 0, 0); + svPutLogicArrElem(i, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + svPutLogicArrElemVecVal(i, logic_vec_val, 0, 0, 0, 0, 0, 0); +} + +void dpii_real_u6(const svOpenArrayHandle i) { + printf("%s:\n", __func__); + svGetArrElemPtr(i, 0, 0, 0, 0, 0, 0); +} diff --git a/test_regress/t/t_dpi_open_vecval.pl b/test_regress/t/t_dpi_open_vecval.pl new file mode 100755 index 000000000..542b88469 --- /dev/null +++ b/test_regress/t/t_dpi_open_vecval.pl @@ -0,0 +1,23 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(simulator => 1); + +compile( + v_flags2 => ["t/t_dpi_open_vecval_c.cpp"], + verilator_flags2 => ["-Wall -Wno-DECLFILENAME -unroll-count 1"], + ); + +execute( + check_finished => 1, + ); + +ok(1); +1; diff --git a/test_regress/t/t_dpi_open_vecval.v b/test_regress/t/t_dpi_open_vecval.v new file mode 100644 index 000000000..8954f872a --- /dev/null +++ b/test_regress/t/t_dpi_open_vecval.v @@ -0,0 +1,156 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// Copyright 2017 by Wilson Snyder. This program is free software; you can +// redistribute it and/or modify it under the terms of either the GNU +// Lesser General Public License Version 3 or the Perl Artistic License +// Version 2.0. +// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + + `define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0) + +module t (/*AUTOARG*/); + + // Note that a packed array is required, otherwise some simulators will return bad + // results using *ElemVecVal() routines instead of scalar *Elem() routines. + bit [0:0] i_bit_p1_u1 [2:-2]; + bit [0:0] o_bit_p1_u1 [2:-2]; + bit [0:0] q_bit_p1_u1 [2:-2]; + bit [60:0] i_bit61_p1_u1 [2:-2]; + bit [60:0] o_bit61_p1_u1 [2:-2]; + bit [60:0] q_bit61_p1_u1 [2:-2]; + bit [91:0] i_bit92_p1_u1 [2:-2]; + bit [91:0] o_bit92_p1_u1 [2:-2]; + bit [91:0] q_bit92_p1_u1 [2:-2]; + bit [11:0] i_bit12_p1_u2 [2:-2] [-3:3]; + bit [11:0] o_bit12_p1_u2 [2:-2] [-3:3]; + bit [11:0] q_bit12_p1_u2 [2:-2] [-3:3]; + bit [29:1] i_bit29_p1_u3 [2:-2] [-3:3] [4:-4]; + bit [29:1] o_bit29_p1_u3 [2:-2] [-3:3] [4:-4]; + bit [29:1] q_bit29_p1_u3 [2:-2] [-3:3] [4:-4]; + import "DPI-C" function void dpii_bit_vecval_p1_u1 + (int bits, int p, int u, input bit [0:0] i [], output bit [0:0] o [], output bit [0:0] q []); + import "DPI-C" function void dpii_bit61_vecval_p1_u1 + (int bits, int p, int u, input bit [60:0] i [], output bit [60:0] o [], output bit [60:0] q []); + import "DPI-C" function void dpii_bit92_vecval_p1_u1 + (int bits, int p, int u, input bit [91:0] i [], output bit [91:0] o [], output bit [91:0] q []); + import "DPI-C" function void dpii_bit12_vecval_p1_u2 + (int bits, int p, int u, input bit [11:0] i [] [], output bit [11:0] o [] [], output bit [11:0] q [] []); + import "DPI-C" function void dpii_bit29_vecval_p1_u3 + (int bits, int p, int u, input bit [29:1] i [] [] [], output bit [29:1] o [] [] [], output bit [29:1] q [] [] []); + + logic [0:0] i_logic_p1_u1 [2:-2]; + logic [0:0] o_logic_p1_u1 [2:-2]; + logic [0:0] q_logic_p1_u1 [2:-2]; + logic [60:0] i_logic61_p1_u1 [2:-2]; + logic [60:0] o_logic61_p1_u1 [2:-2]; + logic [60:0] q_logic61_p1_u1 [2:-2]; + logic [91:0] i_logic92_p1_u1 [2:-2]; + logic [91:0] o_logic92_p1_u1 [2:-2]; + logic [91:0] q_logic92_p1_u1 [2:-2]; + logic [11:0] i_logic12_p1_u2 [2:-2] [-3:3]; + logic [11:0] o_logic12_p1_u2 [2:-2] [-3:3]; + logic [11:0] q_logic12_p1_u2 [2:-2] [-3:3]; + logic [29:1] i_logic29_p1_u3 [2:-2] [-3:3] [4:-4]; + logic [29:1] o_logic29_p1_u3 [2:-2] [-3:3] [4:-4]; + logic [29:1] q_logic29_p1_u3 [2:-2] [-3:3] [4:-4]; + import "DPI-C" function void dpii_logic_vecval_p1_u1 + (int logics, int p, int u, input logic [0:0] i [], output logic [0:0] o [], output logic [0:0] q []); + import "DPI-C" function void dpii_logic61_vecval_p1_u1 + (int logics, int p, int u, input logic [60:0] i [], output logic [60:0] o [], output logic [60:0] q []); + import "DPI-C" function void dpii_logic92_vecval_p1_u1 + (int logics, int p, int u, input logic [91:0] i [], output logic [91:0] o [], output logic [91:0] q []); + import "DPI-C" function void dpii_logic12_vecval_p1_u2 + (int logics, int p, int u, input logic [11:0] i [] [], output logic [11:0] o [] [], output logic [11:0] q [] []); + import "DPI-C" function void dpii_logic29_vecval_p1_u3 + (int logics, int p, int u, input logic [29:1] i [] [] [], output logic [29:1] o [] [] [], output logic [29:1] q [] [] []); + + import "DPI-C" function int dpii_failure(); + + reg [95:0] crc; + + initial begin + crc = 96'h8a10a572_5aef0c8d_d70a4497; + + begin + for (int a=-2; a<=2; a=a+1) begin + i_bit_p1_u1[a] = crc[0]; + i_bit61_p1_u1[a] = crc[60:0]; + i_bit92_p1_u1[a] = crc[91:0]; + for (int b=-3; b<=3; b=b+1) begin + i_bit12_p1_u2[a][b] = crc[11:0]; + for (int c=-4; c<=4; c=c+1) begin + i_bit29_p1_u3[a][b][c] = crc[29:1]; + crc = {crc[94:0], crc[95]^crc[2]^crc[0]}; + end + end + end + dpii_bit_vecval_p1_u1(1, 1, 1, i_bit_p1_u1, o_bit_p1_u1, q_bit_p1_u1); + dpii_bit61_vecval_p1_u1(61, 1, 1, i_bit61_p1_u1, o_bit61_p1_u1, q_bit61_p1_u1); + dpii_bit92_vecval_p1_u1(92, 1, 1, i_bit92_p1_u1, o_bit92_p1_u1, q_bit92_p1_u1); + dpii_bit12_vecval_p1_u2(12, 1, 2, i_bit12_p1_u2, o_bit12_p1_u2, q_bit12_p1_u2); + dpii_bit29_vecval_p1_u3(29, 1, 3, i_bit29_p1_u3, o_bit29_p1_u3, q_bit29_p1_u3); + for (int a=-2; a<=2; a=a+1) begin + `checkh(o_bit_p1_u1[a], ~i_bit_p1_u1[a]); + `checkh(q_bit_p1_u1[a], ~i_bit_p1_u1[a]); + `checkh(o_bit61_p1_u1[a], ~i_bit61_p1_u1[a]); + `checkh(q_bit61_p1_u1[a], ~i_bit61_p1_u1[a]); + `checkh(o_bit92_p1_u1[a], ~i_bit92_p1_u1[a]); + `checkh(q_bit92_p1_u1[a], ~i_bit92_p1_u1[a]); + for (int b=-3; b<=3; b=b+1) begin + `checkh(o_bit12_p1_u2[a][b], ~i_bit12_p1_u2[a][b]); + `checkh(q_bit12_p1_u2[a][b], ~i_bit12_p1_u2[a][b]); + for (int c=-4; c<=4; c=c+1) begin + `checkh(o_bit29_p1_u3[a][b][c], ~i_bit29_p1_u3[a][b][c]); + `checkh(q_bit29_p1_u3[a][b][c], ~i_bit29_p1_u3[a][b][c]); + end + end + end + end + + begin + for (int a=-2; a<=2; a=a+1) begin + i_logic_p1_u1[a] = crc[0]; + i_logic61_p1_u1[a] = crc[60:0]; + i_logic92_p1_u1[a] = crc[91:0]; + for (int b=-3; b<=3; b=b+1) begin + i_logic12_p1_u2[a][b] = crc[11:0]; + for (int c=-4; c<=4; c=c+1) begin + i_logic29_p1_u3[a][b][c] = crc[29:1]; + crc = {crc[94:0], crc[95]^crc[2]^crc[0]}; + end + end + end + dpii_logic_vecval_p1_u1(1, 1, 1, i_logic_p1_u1, o_logic_p1_u1, q_logic_p1_u1); + dpii_logic61_vecval_p1_u1(61, 1, 1, i_logic61_p1_u1, o_logic61_p1_u1, q_logic61_p1_u1); + dpii_logic92_vecval_p1_u1(92, 1, 1, i_logic92_p1_u1, o_logic92_p1_u1, q_logic92_p1_u1); + dpii_logic12_vecval_p1_u2(12, 1, 2, i_logic12_p1_u2, o_logic12_p1_u2, q_logic12_p1_u2); + dpii_logic29_vecval_p1_u3(29, 1, 3, i_logic29_p1_u3, o_logic29_p1_u3, q_logic29_p1_u3); + for (int a=-2; a<=2; a=a+1) begin + `checkh(o_logic_p1_u1[a], ~i_logic_p1_u1[a]); + `checkh(q_logic_p1_u1[a], ~i_logic_p1_u1[a]); + `checkh(o_logic61_p1_u1[a], ~i_logic61_p1_u1[a]); + `checkh(q_logic61_p1_u1[a], ~i_logic61_p1_u1[a]); + `checkh(o_logic92_p1_u1[a], ~i_logic92_p1_u1[a]); + `checkh(q_logic92_p1_u1[a], ~i_logic92_p1_u1[a]); + for (int b=-3; b<=3; b=b+1) begin + `checkh(o_logic12_p1_u2[a][b], ~i_logic12_p1_u2[a][b]); + `checkh(q_logic12_p1_u2[a][b], ~i_logic12_p1_u2[a][b]); + for (int c=-4; c<=4; c=c+1) begin + `checkh(o_logic29_p1_u3[a][b][c], ~i_logic29_p1_u3[a][b][c]); + `checkh(q_logic29_p1_u3[a][b][c], ~i_logic29_p1_u3[a][b][c]); + end + end + end + end + + if (dpii_failure()!=0) begin + $write("%%Error: Failure in DPI tests\n"); + $stop; + end + else begin + $write("*-* All Finished *-*\n"); + $finish; + end + end + +endmodule diff --git a/test_regress/t/t_dpi_open_vecval_c.cpp b/test_regress/t/t_dpi_open_vecval_c.cpp new file mode 100644 index 000000000..e8b49163c --- /dev/null +++ b/test_regress/t/t_dpi_open_vecval_c.cpp @@ -0,0 +1,236 @@ +// -*- mode: C++; c-file-style: "cc-mode" -*- +//************************************************************************* +// +// Copyright 2009-2020 by Wilson Snyder. This program is free software; you can +// redistribute it and/or modify it under the terms of either the GNU +// Lesser General Public License Version 3 or the Perl Artistic License +// Version 2.0. +// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 +// +//************************************************************************* + +#include +#include +#include +#include "svdpi.h" + +//====================================================================== + +// clang-format off +#if defined(VERILATOR) +# include "Vt_dpi_open_vecval__Dpi.h" +#elif defined(VCS) +# include "../vc_hdrs.h" +#elif defined(NC) +# define NEED_EXTERNS +// #elif defined(MS) +// # define NEED_EXTERNS +#else +# error "Unknown simulator for DPI test" +#endif +// clang-format on + +#ifdef NEED_EXTERNS +extern "C" { +// If get ncsim: *F,NOFDPI: Function {foo} not found in default libdpi. +// Then probably forgot to list a function here. + +extern int dpii_failure(); +} +#endif + +int failure = 0; +int dpii_failure() { return failure; } + +#define CHECK_RESULT_HEX(got, exp) \ + do { \ + if ((got) != (exp)) { \ + std::cout << std::dec << "%Error: " << __FILE__ << ":" << __LINE__ << std::hex \ + << ": GOT=" << (got) << " EXP=" << (exp) << std::endl; \ + failure = __LINE__; \ + } \ + } while (0) + +#define CHECK_RESULT_HEX_NE(got, exp) \ + do { \ + if ((got) == (exp)) { \ + std::cout << std::dec << "%Error: " << __FILE__ << ":" << __LINE__ << std::hex \ + << ": GOT=" << (got) << " EXP!=" << (exp) << std::endl; \ + failure = __LINE__; \ + } \ + } while (0) + +static void _invert(int bits, svBitVecVal o[], const svBitVecVal i[]) { + for (int w = 0; w < SV_PACKED_DATA_NELEMS(bits); ++w) o[w] = ~i[w]; + o[SV_PACKED_DATA_NELEMS(bits) - 1] &= SV_MASK(bits & 31); +} +static void _invert(int bits, svLogicVecVal o[], const svLogicVecVal i[]) { + for (int w = 0; w < SV_PACKED_DATA_NELEMS(bits); ++w) { + o[w].aval = ~i[w].aval; + o[w].bval = 0; + } + o[SV_PACKED_DATA_NELEMS(bits) - 1].aval &= SV_MASK(bits & 31); + o[SV_PACKED_DATA_NELEMS(bits) - 1].bval &= SV_MASK(bits & 31); +} + +static bool _same(int bits, const svBitVecVal o[], const svBitVecVal i[]) { + for (int w = 0; w < SV_PACKED_DATA_NELEMS(bits); ++w) { + svBitVecVal mask = 0xffffffff; + if (w == SV_PACKED_DATA_NELEMS(bits) - 1) mask = SV_MASK(bits & 31); + if ((o[w] & mask) != (i[w] & mask)) return false; + } + return true; +} +static bool _same(int bits, const svLogicVecVal o[], const svLogicVecVal i[]) { + for (int w = 0; w < SV_PACKED_DATA_NELEMS(bits); ++w) { + svBitVecVal mask = 0xffffffff; + if (w == SV_PACKED_DATA_NELEMS(bits) - 1) mask = SV_MASK(bits & 31); + if ((o[w].aval & mask) != (i[w].aval & mask)) return false; + if ((o[w].bval & mask) != (i[w].bval & mask)) return false; + } + return true; +} + +void dpii_unused(const svOpenArrayHandle u) {} + +//====================================================================== + +static void _dpii_bit_vecval_ux(int bits, int p, int u, const svOpenArrayHandle i, + const svOpenArrayHandle o, const svOpenArrayHandle q) { + printf("%s: bits=%d p=%d u=%d\n", __func__, bits, p, u); + + int dim = svDimensions(i); +#ifndef NC + // NC always returns zero and warns + CHECK_RESULT_HEX(dim, u); +#endif + + svBitVecVal vv[SV_PACKED_DATA_NELEMS(bits)]; + svBitVecVal vv2[SV_PACKED_DATA_NELEMS(bits)]; + svBitVecVal vo[SV_PACKED_DATA_NELEMS(bits)]; + for (int a = svLow(i, 1); a <= svHigh(i, 1); ++a) { + fflush(stdout); + if (dim == 1) { + svGetBitArrElemVecVal(vv, i, a); + svGetBitArrElem1VecVal(vv2, i, a); + CHECK_RESULT_HEX(_same(bits, vv, vv2), true); + _invert(bits, vo, vv); + svPutBitArrElemVecVal(o, vo, a); + svPutBitArrElem1VecVal(q, vo, a); + } else { + for (int b = svLow(i, 2); b <= svHigh(i, 2); ++b) { + if (dim == 2) { + svGetBitArrElemVecVal(vv, i, a, b); + svGetBitArrElem2VecVal(vv2, i, a, b); + CHECK_RESULT_HEX(_same(bits, vv, vv2), true); + _invert(bits, vo, vv); + svPutBitArrElemVecVal(o, vo, a, b); + svPutBitArrElem2VecVal(q, vo, a, b); + } else { + for (int c = svLow(i, 3); c <= svHigh(i, 3); ++c) { + if (dim == 3) { + svGetBitArrElemVecVal(vv, i, a, b, c); + svGetBitArrElem3VecVal(vv2, i, a, b, c); + CHECK_RESULT_HEX(_same(bits, vv, vv2), true); + _invert(bits, vo, vv); + svPutBitArrElemVecVal(o, vo, a, b, c); + svPutBitArrElem3VecVal(q, vo, a, b, c); + } + } + } + } + } + } + fflush(stdout); +} +void dpii_bit_vecval_p1_u1(int bits, int p, int u, const svOpenArrayHandle i, + const svOpenArrayHandle o, const svOpenArrayHandle q) { + _dpii_bit_vecval_ux(bits, p, u, i, o, q); +} +void dpii_bit61_vecval_p1_u1(int bits, int p, int u, const svOpenArrayHandle i, + const svOpenArrayHandle o, const svOpenArrayHandle q) { + _dpii_bit_vecval_ux(bits, p, u, i, o, q); +} +void dpii_bit92_vecval_p1_u1(int bits, int p, int u, const svOpenArrayHandle i, + const svOpenArrayHandle o, const svOpenArrayHandle q) { + _dpii_bit_vecval_ux(bits, p, u, i, o, q); +} +void dpii_bit12_vecval_p1_u2(int bits, int p, int u, const svOpenArrayHandle i, + const svOpenArrayHandle o, const svOpenArrayHandle q) { + _dpii_bit_vecval_ux(bits, p, u, i, o, q); +} +void dpii_bit29_vecval_p1_u3(int bits, int p, int u, const svOpenArrayHandle i, + const svOpenArrayHandle o, const svOpenArrayHandle q) { + _dpii_bit_vecval_ux(bits, p, u, i, o, q); +} + +//====================================================================== + +static void _dpii_logic_vecval_ux(int bits, int p, int u, const svOpenArrayHandle i, + const svOpenArrayHandle o, const svOpenArrayHandle q) { + printf("%s: bits=%d p=%d u=%d\n", __func__, bits, p, u); + + int dim = svDimensions(i); +#ifndef NC + // NC always returns zero and warns + CHECK_RESULT_HEX(dim, u); +#endif + + svLogicVecVal vv[SV_PACKED_DATA_NELEMS(bits)]; + svLogicVecVal vv2[SV_PACKED_DATA_NELEMS(bits)]; + svLogicVecVal vo[SV_PACKED_DATA_NELEMS(bits)]; + for (int a = svLow(i, 1); a <= svHigh(i, 1); ++a) { + fflush(stdout); + if (dim == 1) { + svGetLogicArrElemVecVal(vv, i, a); + svGetLogicArrElem1VecVal(vv2, i, a); + CHECK_RESULT_HEX(_same(bits, vv, vv2), true); + _invert(bits, vo, vv); + svPutLogicArrElemVecVal(o, vo, a); + svPutLogicArrElem1VecVal(q, vo, a); + } else { + for (int b = svLow(i, 2); b <= svHigh(i, 2); ++b) { + if (dim == 2) { + svGetLogicArrElemVecVal(vv, i, a, b); + svGetLogicArrElem2VecVal(vv2, i, a, b); + CHECK_RESULT_HEX(_same(bits, vv, vv2), true); + _invert(bits, vo, vv); + svPutLogicArrElemVecVal(o, vo, a, b); + svPutLogicArrElem2VecVal(q, vo, a, b); + } else { + for (int c = svLow(i, 3); c <= svHigh(i, 3); ++c) { + if (dim == 3) { + svGetLogicArrElemVecVal(vv, i, a, b, c); + svGetLogicArrElem3VecVal(vv2, i, a, b, c); + CHECK_RESULT_HEX(_same(bits, vv, vv2), true); + _invert(bits, vo, vv); + svPutLogicArrElemVecVal(o, vo, a, b, c); + svPutLogicArrElem3VecVal(q, vo, a, b, c); + } + } + } + } + } + } + fflush(stdout); +} +void dpii_logic_vecval_p1_u1(int bits, int p, int u, const svOpenArrayHandle i, + const svOpenArrayHandle o, const svOpenArrayHandle q) { + _dpii_logic_vecval_ux(bits, p, u, i, o, q); +} +void dpii_logic61_vecval_p1_u1(int bits, int p, int u, const svOpenArrayHandle i, + const svOpenArrayHandle o, const svOpenArrayHandle q) { + _dpii_logic_vecval_ux(bits, p, u, i, o, q); +} +void dpii_logic92_vecval_p1_u1(int bits, int p, int u, const svOpenArrayHandle i, + const svOpenArrayHandle o, const svOpenArrayHandle q) { + _dpii_logic_vecval_ux(bits, p, u, i, o, q); +} +void dpii_logic12_vecval_p1_u2(int bits, int p, int u, const svOpenArrayHandle i, + const svOpenArrayHandle o, const svOpenArrayHandle q) { + _dpii_logic_vecval_ux(bits, p, u, i, o, q); +} +void dpii_logic29_vecval_p1_u3(int bits, int p, int u, const svOpenArrayHandle i, + const svOpenArrayHandle o, const svOpenArrayHandle q) { + _dpii_logic_vecval_ux(bits, p, u, i, o, q); +} diff --git a/test_regress/t/t_dpi_result_type.pl b/test_regress/t/t_dpi_result_type.pl index 76761b85a..7796879c7 100755 --- a/test_regress/t/t_dpi_result_type.pl +++ b/test_regress/t/t_dpi_result_type.pl @@ -20,7 +20,8 @@ if ($Self->{nc}) { compile( v_flags2 => ["t/t_dpi_result_type.cpp"], - verilator_flags2 => ["-Wall -Wno-DECLFILENAME"], + # --no-decoration so .out file doesn't comment on source lines + verilator_flags2 => ["-Wall -Wno-DECLFILENAME --no-decoration"], # NC: Gdd the obj_dir to the C include path nc_flags2 => ["+ncscargs+-I$Self->{obj_dir}"], # ModelSim: Generate DPI header, add obj_dir to the C include path diff --git a/test_regress/t/t_dpi_result_type__Dpi.out b/test_regress/t/t_dpi_result_type__Dpi.out index 680a6d05c..e5d541f43 100644 --- a/test_regress/t/t_dpi_result_type__Dpi.out +++ b/test_regress/t/t_dpi_result_type__Dpi.out @@ -10,146 +10,79 @@ #ifdef __cplusplus extern "C" { #endif - - - // DPI EXPORTS - // DPI export at t/t_dpi_result_type.v:393:24 - extern svBitVecVal e_array_2_state_1(); - // DPI export at t/t_dpi_result_type.v:400:24 - extern svBitVecVal e_array_2_state_32(); - // DPI export at t/t_dpi_result_type.v:284:17 - extern svBit e_bit(); - // DPI export at t/t_dpi_result_type.v:377:19 - extern svBit e_bit_t(); - // DPI export at t/t_dpi_result_type.v:206:18 - extern char e_byte(); - // DPI export at t/t_dpi_result_type.v:299:20 - extern char e_byte_t(); - // DPI export at t/t_dpi_result_type.v:212:27 - extern unsigned char e_byte_unsigned(); - // DPI export at t/t_dpi_result_type.v:305:29 - extern unsigned char e_byte_unsigned_t(); - // DPI export at t/t_dpi_result_type.v:270:21 - extern void* e_chandle(); - // DPI export at t/t_dpi_result_type.v:363:23 - extern void* e_chandle_t(); - // DPI export at t/t_dpi_result_type.v:230:17 - extern int e_int(); - // DPI export at t/t_dpi_result_type.v:323:19 - extern int e_int_t(); - // DPI export at t/t_dpi_result_type.v:236:26 - extern unsigned int e_int_unsigned(); - // DPI export at t/t_dpi_result_type.v:329:28 - extern unsigned int e_int_unsigned_t(); - // DPI export at t/t_dpi_result_type.v:291:19 - extern svLogic e_logic(); - // DPI export at t/t_dpi_result_type.v:384:21 - extern svLogic e_logic_t(); - // DPI export at t/t_dpi_result_type.v:242:21 - extern long long e_longint(); - // DPI export at t/t_dpi_result_type.v:335:23 - extern long long e_longint_t(); - // DPI export at t/t_dpi_result_type.v:248:30 - extern unsigned long long e_longint_unsigned(); - // DPI export at t/t_dpi_result_type.v:341:32 - extern unsigned long long e_longint_unsigned_t(); - // DPI export at t/t_dpi_result_type.v:255:18 - extern double e_real(); - // DPI export at t/t_dpi_result_type.v:348:20 - extern double e_real_t(); - // DPI export at t/t_dpi_result_type.v:218:22 - extern short e_shortint(); - // DPI export at t/t_dpi_result_type.v:311:24 - extern short e_shortint_t(); - // DPI export at t/t_dpi_result_type.v:224:31 - extern unsigned short e_shortint_unsigned(); - // DPI export at t/t_dpi_result_type.v:317:33 - extern unsigned short e_shortint_unsigned_t(); - // DPI export at t/t_dpi_result_type.v:277:20 - extern const char* e_string(); - // DPI export at t/t_dpi_result_type.v:370:22 - extern const char* e_string_t(); - // DPI export at t/t_dpi_result_type.v:410:30 - extern svBitVecVal e_struct_2_state_1(); - // DPI export at t/t_dpi_result_type.v:417:32 - extern svBitVecVal e_struct_2_state_32(); - // DPI export at t/t_dpi_result_type.v:425:29 - extern svBitVecVal e_union_2_state_1(); - // DPI export at t/t_dpi_result_type.v:432:30 - extern svBitVecVal e_union_2_state_32(); - // DPI export at t/t_dpi_result_type.v:200:18 - extern void e_void(); - - // DPI IMPORTS - // DPI import at t/t_dpi_result_type.v:443:41 - extern void check_exports(); - // DPI import at t/t_dpi_result_type.v:115:39 - extern svBitVecVal i_array_2_state_1(); - // DPI import at t/t_dpi_result_type.v:116:39 - extern svBitVecVal i_array_2_state_32(); - // DPI import at t/t_dpi_result_type.v:92:46 - extern svBit i_bit(); - // DPI import at t/t_dpi_result_type.v:110:48 - extern svBit i_bit_t(); - // DPI import at t/t_dpi_result_type.v:78:46 - extern char i_byte(); - // DPI import at t/t_dpi_result_type.v:96:48 - extern char i_byte_t(); - // DPI import at t/t_dpi_result_type.v:79:46 - extern unsigned char i_byte_unsigned(); - // DPI import at t/t_dpi_result_type.v:97:48 - extern unsigned char i_byte_unsigned_t(); - // DPI import at t/t_dpi_result_type.v:90:46 - extern void* i_chandle(); - // DPI import at t/t_dpi_result_type.v:108:48 - extern void* i_chandle_t(); - // DPI import at t/t_dpi_result_type.v:82:46 - extern int i_int(); - // DPI import at t/t_dpi_result_type.v:100:48 - extern int i_int_t(); - // DPI import at t/t_dpi_result_type.v:83:46 - extern unsigned int i_int_unsigned(); - // DPI import at t/t_dpi_result_type.v:101:48 - extern unsigned int i_int_unsigned_t(); - // DPI import at t/t_dpi_result_type.v:93:46 - extern svLogic i_logic(); - // DPI import at t/t_dpi_result_type.v:111:48 - extern svLogic i_logic_t(); - // DPI import at t/t_dpi_result_type.v:84:46 - extern long long i_longint(); - // DPI import at t/t_dpi_result_type.v:102:48 - extern long long i_longint_t(); - // DPI import at t/t_dpi_result_type.v:85:46 - extern unsigned long long i_longint_unsigned(); - // DPI import at t/t_dpi_result_type.v:103:48 - extern unsigned long long i_longint_unsigned_t(); - // DPI import at t/t_dpi_result_type.v:86:46 - extern double i_real(); - // DPI import at t/t_dpi_result_type.v:104:48 - extern double i_real_t(); - // DPI import at t/t_dpi_result_type.v:80:46 - extern short i_shortint(); - // DPI import at t/t_dpi_result_type.v:98:48 - extern short i_shortint_t(); - // DPI import at t/t_dpi_result_type.v:81:46 - extern unsigned short i_shortint_unsigned(); - // DPI import at t/t_dpi_result_type.v:99:48 - extern unsigned short i_shortint_unsigned_t(); - // DPI import at t/t_dpi_result_type.v:91:46 - extern const char* i_string(); - // DPI import at t/t_dpi_result_type.v:109:48 - extern const char* i_string_t(); - // DPI import at t/t_dpi_result_type.v:121:47 - extern svBitVecVal i_struct_2_state_1(); - // DPI import at t/t_dpi_result_type.v:122:47 - extern svBitVecVal i_struct_2_state_32(); - // DPI import at t/t_dpi_result_type.v:125:46 - extern svBitVecVal i_union_2_state_1(); - // DPI import at t/t_dpi_result_type.v:126:46 - extern svBitVecVal i_union_2_state_32(); - // DPI import at t/t_dpi_result_type.v:77:46 - extern void i_void(); - + + + // DPI EXPORTS + extern svBitVecVal e_array_2_state_1(); + extern svBitVecVal e_array_2_state_32(); + extern svBit e_bit(); + extern svBit e_bit_t(); + extern char e_byte(); + extern char e_byte_t(); + extern unsigned char e_byte_unsigned(); + extern unsigned char e_byte_unsigned_t(); + extern void* e_chandle(); + extern void* e_chandle_t(); + extern int e_int(); + extern int e_int_t(); + extern unsigned int e_int_unsigned(); + extern unsigned int e_int_unsigned_t(); + extern svLogic e_logic(); + extern svLogic e_logic_t(); + extern long long e_longint(); + extern long long e_longint_t(); + extern unsigned long long e_longint_unsigned(); + extern unsigned long long e_longint_unsigned_t(); + extern double e_real(); + extern double e_real_t(); + extern short e_shortint(); + extern short e_shortint_t(); + extern unsigned short e_shortint_unsigned(); + extern unsigned short e_shortint_unsigned_t(); + extern const char* e_string(); + extern const char* e_string_t(); + extern svBitVecVal e_struct_2_state_1(); + extern svBitVecVal e_struct_2_state_32(); + extern svBitVecVal e_union_2_state_1(); + extern svBitVecVal e_union_2_state_32(); + extern void e_void(); + + // DPI IMPORTS + extern void check_exports(); + extern svBitVecVal i_array_2_state_1(); + extern svBitVecVal i_array_2_state_32(); + extern svBit i_bit(); + extern svBit i_bit_t(); + extern char i_byte(); + extern char i_byte_t(); + extern unsigned char i_byte_unsigned(); + extern unsigned char i_byte_unsigned_t(); + extern void* i_chandle(); + extern void* i_chandle_t(); + extern int i_int(); + extern int i_int_t(); + extern unsigned int i_int_unsigned(); + extern unsigned int i_int_unsigned_t(); + extern svLogic i_logic(); + extern svLogic i_logic_t(); + extern long long i_longint(); + extern long long i_longint_t(); + extern unsigned long long i_longint_unsigned(); + extern unsigned long long i_longint_unsigned_t(); + extern double i_real(); + extern double i_real_t(); + extern short i_shortint(); + extern short i_shortint_t(); + extern unsigned short i_shortint_unsigned(); + extern unsigned short i_shortint_unsigned_t(); + extern const char* i_string(); + extern const char* i_string_t(); + extern svBitVecVal i_struct_2_state_1(); + extern svBitVecVal i_struct_2_state_32(); + extern svBitVecVal i_union_2_state_1(); + extern svBitVecVal i_union_2_state_32(); + extern void i_void(); + #ifdef __cplusplus } #endif diff --git a/test_regress/t/t_dynarray_unpacked.pl b/test_regress/t/t_dynarray_unpacked.pl new file mode 100755 index 000000000..9a15dd2cc --- /dev/null +++ b/test_regress/t/t_dynarray_unpacked.pl @@ -0,0 +1,21 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2019 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(simulator => 1); + +compile( + ); + +execute( + check_finished => 1, + ); + +ok(1); +1; diff --git a/test_regress/t/t_dynarray_unpacked.v b/test_regress/t/t_dynarray_unpacked.v new file mode 100644 index 000000000..530a6cbc3 --- /dev/null +++ b/test_regress/t/t_dynarray_unpacked.v @@ -0,0 +1,34 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2020 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +`define stop $stop +`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0) + +module t (/*AUTOARG*/); + + byte dyn [][1:0]; + + initial begin + begin + dyn = new [3]; + dyn[0] = '{101, 100}; + dyn[1] = '{111, 110}; + dyn[2] = '{121, 120}; +`ifndef verilator // bug2314 + `checkh(dyn[0][0], 100); + `checkh(dyn[0][1], 101); + `checkh(dyn[1][0], 110); + `checkh(dyn[1][1], 111); + `checkh(dyn[2][0], 120); + `checkh(dyn[2][1], 121); +`endif + end + + $write("*-* All Finished *-*\n"); + $finish; + end + +endmodule diff --git a/test_regress/t/t_embed1_c.cpp b/test_regress/t/t_embed1_c.cpp index 51ffbe375..e9deda818 100644 --- a/test_regress/t/t_embed1_c.cpp +++ b/test_regress/t/t_embed1_c.cpp @@ -61,7 +61,23 @@ Vt_embed1_child* __get_modelp() { vl_fatal(__FILE__, __LINE__, __FILE__, "svPutUserData failed"); } } - return (Vt_embed1_child*)(__modelp); + return reinterpret_cast(__modelp); +} + +void __delete_modelp() { + svScope scope = svGetScope(); + if (!scope) { + vl_fatal(__FILE__, __LINE__, __FILE__, "svGetScope failed"); + return; + } + void* __modelp = svGetUserData(scope, &T_Embed_Child_Unique); + if (__modelp) { + delete reinterpret_cast(__modelp); + __modelp = nullptr; + if (svPutUserData(scope, &T_Embed_Child_Unique, __modelp)) { + vl_fatal(__FILE__, __LINE__, __FILE__, "svPutUserData failed"); + } + } } void t_embed_child_initial() { @@ -74,6 +90,7 @@ void t_embed_child_final() { VL_DEBUG_IF(VL_PRINTF(" t_embed1_child_final\n");); Vt_embed1_child* __modelp = __get_modelp(); __modelp->final(); + __delete_modelp(); } void t_embed_child_eval() { diff --git a/test_regress/t/t_flag_stats.v b/test_regress/t/t_flag_stats.v index 319e410ff..1026d969b 100644 --- a/test_regress/t/t_flag_stats.v +++ b/test_regress/t/t_flag_stats.v @@ -4,10 +4,12 @@ // any use, without warranty, 2014 by Wilson Snyder. // SPDX-License-Identifier: CC0-1.0 -module t (b); +module t (b, b2); output reg [31:0] b; + output reg [31:0] b2; // Need 2 vars of same width to cover V3Stats initial begin - b = 22; + b = 11; + b2 = 22; $write("*-* All Finished *-*\n"); $finish; end diff --git a/test_regress/t/t_flag_topmod2_bad.out b/test_regress/t/t_flag_topmod2_bad.out index 79a337a4a..a3680a2c6 100644 --- a/test_regress/t/t_flag_topmod2_bad.out +++ b/test_regress/t/t_flag_topmod2_bad.out @@ -1,2 +1,2 @@ -%Error: Specified --top-module 'a' isn't at the top level, it's under another cell 'a_top' +%Error: Specified --top-module 'a' isn't at the top level, it's under another instance 'a_top' %Error: Exiting due to diff --git a/test_regress/t/t_flag_topmodule_inline.pl b/test_regress/t/t_flag_topmodule_inline.pl index aab9ba97c..b6bfb1af9 100755 --- a/test_regress/t/t_flag_topmodule_inline.pl +++ b/test_regress/t/t_flag_topmodule_inline.pl @@ -11,7 +11,8 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di scenarios(vlt => 1); compile( - v_flags2 => ["--top-module b"], + # This also tests --top as opposed to --top-module + v_flags2 => ["--top b"], ); execute( diff --git a/test_regress/t/t_func_impure_bad.out b/test_regress/t/t_func_impure_bad.out new file mode 100644 index 000000000..17a896993 --- /dev/null +++ b/test_regress/t/t_func_impure_bad.out @@ -0,0 +1,7 @@ +%Error-IMPURE: t/t_func_impure_bad.v:11:9: Unsupported: External variable referenced by non-inlined function/task: 't.foo' + 11 | task foo; + | ^~~ + t/t_func_impure_bad.v:13:7: ... Location of the external reference: 't.sig' + 13 | sig = '1; + | ^~~ +%Error: Exiting due to diff --git a/test_regress/t/t_func_impure_bad.pl b/test_regress/t/t_func_impure_bad.pl new file mode 100755 index 000000000..a5846c699 --- /dev/null +++ b/test_regress/t/t_func_impure_bad.pl @@ -0,0 +1,19 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(vlt => 1); + +lint( + fails => 1, + expect_filename => $Self->{golden_filename}, + ); + +ok(1); +1; diff --git a/test_regress/t/t_func_impure_bad.v b/test_regress/t/t_func_impure_bad.v new file mode 100644 index 000000000..fdbffde8a --- /dev/null +++ b/test_regress/t/t_func_impure_bad.v @@ -0,0 +1,20 @@ +// DESCRIPTION: Verilator: Test of select from constant +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2020 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +module t (/*AUTOARG*/); + + int sig; + + task foo; + // verilator no_inline_task + sig = '1; + endtask + + initial begin + foo(); + end + +endmodule diff --git a/test_regress/t/t_func_tasknsvar_bad.out b/test_regress/t/t_func_tasknsvar_bad.out new file mode 100644 index 000000000..d7bb3f57c --- /dev/null +++ b/test_regress/t/t_func_tasknsvar_bad.out @@ -0,0 +1,7 @@ +%Error-TASKNSVAR: t/t_func_tasknsvar_bad.v:16:29: Unsupported: Function/task input argument is not simple variable + 16 | foo(bus_we_select_from[2]); + | ^ +%Error: Internal Error: t/t_func_tasknsvar_bad.v:10:7: ../V3Broken.cpp:#: Broken link in node (or something without maybePointedTo): m_varScopep && !m_varScopep->brokeExists() + 10 | sig = '1; + | ^~~ + ... See the manual and https://verilator.org for more assistance. diff --git a/test_regress/t/t_func_tasknsvar_bad.pl b/test_regress/t/t_func_tasknsvar_bad.pl new file mode 100755 index 000000000..a5846c699 --- /dev/null +++ b/test_regress/t/t_func_tasknsvar_bad.pl @@ -0,0 +1,19 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(vlt => 1); + +lint( + fails => 1, + expect_filename => $Self->{golden_filename}, + ); + +ok(1); +1; diff --git a/test_regress/t/t_func_tasknsvar_bad.v b/test_regress/t/t_func_tasknsvar_bad.v new file mode 100644 index 000000000..7f4a62308 --- /dev/null +++ b/test_regress/t/t_func_tasknsvar_bad.v @@ -0,0 +1,19 @@ +// DESCRIPTION: Verilator: Test of select from constant +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2020 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +module t (/*AUTOARG*/); + + task foo(inout sig); + sig = '1; + endtask + + reg [3:0] bus_we_select_from; + + initial begin + foo(bus_we_select_from[2]); // Will get TASKNSVAR error + end + +endmodule diff --git a/test_regress/t/t_gen_for2.pl b/test_regress/t/t_gen_for_interface.pl similarity index 100% rename from test_regress/t/t_gen_for2.pl rename to test_regress/t/t_gen_for_interface.pl diff --git a/test_regress/t/t_gen_for2.v b/test_regress/t/t_gen_for_interface.v similarity index 100% rename from test_regress/t/t_gen_for2.v rename to test_regress/t/t_gen_for_interface.v diff --git a/test_regress/t/t_gen_genblk.out b/test_regress/t/t_gen_genblk.out index 4eb73f9a4..9a6cb52a4 100644 --- a/test_regress/t/t_gen_genblk.out +++ b/test_regress/t/t_gen_genblk.out @@ -1,6 +1,50 @@ -015: exp=top.t.show0 got=top.t.show0 -019: exp=top.t.genblk1.show1 got=top.t.genblk1.show1 -023: exp=top.t.genblk2.show2 got=top.t.genblk2.show2 -028: exp=top.t.genblk3.genblk1.show3 got=top.t.genblk3.genblk1.show3 -034: exp=top.t.x1.x3.show4 got=top.t.x1.x3.show4 +021: got=top.t.direct_ignored.show1 +023: got=top.t.direct_ignored.genblk1.show2 exp=1 gennum=1 + +030: got=top.t.empty_DISAGREE.genblk1.show2 exp=0 gennum=1 + +037: got=top.t.empty_named_DISAGREE.genblk1.show2 exp=0 gennum=1 + +043: got=top.t.unnamed_counts.show1 +046: got=top.t.unnamed_counts.genblk1.show2 exp=0 gennum=1 + +052: got=top.t.named_counts.named.show1 +055: got=top.t.named_counts.genblk1.show2 exp=0 gennum=1 + +061: got=top.t.if_direct_counts.genblk1.show1 +063: got=top.t.if_direct_counts.genblk2.show2 exp=2 gennum=2 + +069: got=top.t.if_begin_counts.genblk1.show1 +071: got=top.t.if_begin_counts.genblk2.show2 exp=2 gennum=2 + +076: got=top.t.if_named_counts.named.show1 +078: got=top.t.if_named_counts.named.subnamed.show1s +082: got=top.t.if_named_counts.genblk2.show2 exp=2 gennum=2 + +089: got=top.t.begin_if_counts.genblk1.show1 +092: got=top.t.begin_if_counts.genblk2.show2 exp=2 gennum=2 + +099: got=top.t.for_empty_counts.genblk2.show2 exp=0 gennum=2 + +104: got=top.t.for_direct_counts.genblk1[0].show1 +106: got=top.t.for_direct_counts.genblk2.show2 exp=2 gennum=2 + +111: got=top.t.for_named_counts.fornamed[0].show1 +114: got=top.t.for_named_counts.genblk2.show2 exp=2 gennum=2 + +119: got=top.t.for_begin_counts.genblk1[0].show1 +122: got=top.t.for_begin_counts.genblk2.show2 exp=2 gennum=2 + +132: got=top.t.if_if.genblk1.genblk1.show1 +136: got=top.t.if_if.genblk2.show2 exp=2 gennum=2 + +142: got=top.t.case_direct.genblk1.show1 +146: got=top.t.case_direct.genblk2.show2 exp=2 gennum=2 + +152: got=top.t.case_begin_counts.genblk1.show1 +156: got=top.t.case_begin_counts.genblk2.show2 exp=2 gennum=2 + +162: got=top.t.case_named_counts.subnamed.show1 +166: got=top.t.case_named_counts.genblk2.show2 exp=2 gennum=2 + *-* All Finished *-* diff --git a/test_regress/t/t_gen_genblk.pl b/test_regress/t/t_gen_genblk.pl index 56cc415df..e86489964 100755 --- a/test_regress/t/t_gen_genblk.pl +++ b/test_regress/t/t_gen_genblk.pl @@ -10,6 +10,8 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di scenarios(simulator => 1); +$Self->{sim_time} = 11000; + compile( ); diff --git a/test_regress/t/t_gen_genblk.v b/test_regress/t/t_gen_genblk.v index ee2dd3ea4..0a9b85582 100644 --- a/test_regress/t/t_gen_genblk.v +++ b/test_regress/t/t_gen_genblk.v @@ -3,6 +3,11 @@ // any use, without warranty, 2020 by Wilson Snyder. // SPDX-License-Identifier: CC0-1.0 +`define CONCAT(a,b) a``b +`define SHOW_LINED `CONCAT(show, `__LINE__) + +bit fails; + module t (/*AUTOARG*/ // Inputs clk, reset_l @@ -12,45 +17,209 @@ module t (/*AUTOARG*/ input reset_l; generate - show #(`__LINE__, "top.t.show0") show0(); + begin : direct_ignored + show #(`__LINE__) show1(); - if (0) ; - else if (0) ; - else if (1) show #(`__LINE__, "top.t.genblk1.show1") show1(); + if (1) begin check #(`__LINE__, 1) show2(); end + end - if (0) begin end - else if (0) begin end - else if (1) begin show #(`__LINE__, "top.t.genblk2.show2") show2(); end + begin : empty_DISAGREE + // DISAGREEMENT: if empty unnamed begin/end counts + begin end - if (0) ; - else begin + if (1) begin check #(`__LINE__, 0) show2(); end + end + + begin : empty_named_DISAGREE + // DISAGREEMENT: if empty named begin/end counts + begin : empty_inside_named end + + if (1) begin check #(`__LINE__, 0) show2(); end + end + + begin : unnamed_counts + // DISAGREEMENT: if unnamed begin/end counts + begin + show #(`__LINE__) show1(); + end + + if (1) begin check #(`__LINE__, 0) show2(); end + end + + begin : named_counts + // DISAGREEMENT: if named begin/end counts + begin : named + show #(`__LINE__) show1(); + end + + if (1) begin check #(`__LINE__, 0) show2(); end + end + + begin : if_direct_counts + if (0) ; + else if (0) ; + else if (1) show #(`__LINE__) show1(); + + if (1) begin check #(`__LINE__, 2) show2(); end + end + + begin : if_begin_counts if (0) begin end - else if (1) begin show #(`__LINE__, "top.t.genblk3.genblk1.show3") show3(); end + else if (0) begin show #(`__LINE__) show1_NOT(); end + else if (1) begin show #(`__LINE__) show1(); end + + if (1) begin check #(`__LINE__, 2) show2(); end end - if (0) ; - else begin : x1 - if (0) begin : x2 end - else if (1) begin : x3 show #(`__LINE__, "top.t.x1.x3.show4") show4(); end + begin : if_named_counts + if (1) begin : named + show #(`__LINE__) show1(); + if (1) begin : subnamed + show #(`__LINE__) show1s(); + end + end + + if (1) begin check #(`__LINE__, 2) show2(); end end + + begin : begin_if_counts + begin + if (0) begin end + else if (0) begin show #(`__LINE__) show1_NOT(); end + else if (1) begin show #(`__LINE__) show1(); end + end + // DISAGREEMENT: this could be genblk01 + if (1) begin check #(`__LINE__, 2) show2(); end + end + + begin : for_empty_counts + // DISAGREEMENT: if empty genfor counts + for (genvar g = 0; g < 1; ++g) ; + + if (1) begin check #(`__LINE__, 0) show2(); end + end + + begin : for_direct_counts + for (genvar g = 0; g < 1; ++g) + show #(`__LINE__) show1(); + + if (1) begin check #(`__LINE__, 2) show2(); end + end + + begin : for_named_counts + for (genvar g = 0; g < 1; ++g) begin : fornamed + show #(`__LINE__) show1(); + end + + if (1) begin check #(`__LINE__, 2) show2(); end + end + + begin : for_begin_counts + for (genvar g = 0; g < 1; ++g) begin + show #(`__LINE__) show1(); + end + + if (1) begin check #(`__LINE__, 2) show2(); end + end + + begin : if_if + if (0) ; + else if (0) begin : namedb + end + else begin + if (0) begin end + else if (1) begin + show #(`__LINE__) show1(); + end + end + + if (1) begin check #(`__LINE__, 2) show2(); end + end + + begin : case_direct + case (1) + 0 : show #(`__LINE__) show1a_NOT(); + 1 : show #(`__LINE__) show1(); + 2 : show #(`__LINE__) show1c_NOT(); + endcase + + if (1) begin check #(`__LINE__, 2) show2(); end + end + + begin : case_begin_counts + case (1) + 0 : begin show #(`__LINE__) show1a_NOT(); end + 1 : begin show #(`__LINE__) show1(); end + 2 : begin show #(`__LINE__) show1c_NOT(); end + endcase + + if (1) begin check #(`__LINE__, 2) show2(); end + end + + begin : case_named_counts + case (1) + 0 : begin : subnamed show #(`__LINE__) show1a_NOT(); end + 1 : begin : subnamed show #(`__LINE__) show1(); end + 2 : begin : subnamed show #(`__LINE__) show1c_NOT(); end + endcase + + if (1) begin check #(`__LINE__, 2) show2(); end + end + endgenerate int cyc; always @ (posedge clk) begin cyc <= cyc + 1; - if (cyc == 99) begin - $write("*-* All Finished *-*\n"); + if (cyc == 999) begin + if (fails) $stop; + else $write("*-* All Finished *-*\n"); $finish; end end endmodule -module show #(parameter LINE=0, parameter string EXPT) (); +module show #(parameter LINE=0) (); + // Each instance compares on unique cycle based on line number + // so we get deterministic ordering (versus using an initial) always @ (posedge t.clk) begin if (t.cyc == LINE) begin - $display("%03d: exp=%s got=%m", LINE, EXPT); + $display("%03d: got=%m", LINE); + end + end +endmodule + +module check #(parameter LINE=0, parameter EXP=0) (); + string mod; + int gennum; + int pos; + + always @ (posedge t.clk) begin + if (t.cyc == LINE) begin + mod = $sformatf("%m"); + + gennum = 0; + for (int pos = 0; pos < mod.len(); ++pos) begin + if (mod.substr(pos, pos+5) == "genblk") begin + pos += 6; + // verilator lint_off WIDTH + gennum = mod[pos] - "0"; + // verilator lint_on WIDTH + break; + end + end + + $write("%03d: got=%s exp=%0d gennum=%0d ", LINE, mod, EXP, gennum); + if (EXP == 0) $display(" "); + else if (gennum != EXP) begin + $display (" %%Error"); + fails = 1; + end + else $display; + + $display; end end endmodule diff --git a/test_regress/t/t_gen_genblk_noinl.pl b/test_regress/t/t_gen_genblk_noinl.pl index 08623e342..86adb4a8e 100755 --- a/test_regress/t/t_gen_genblk_noinl.pl +++ b/test_regress/t/t_gen_genblk_noinl.pl @@ -12,6 +12,8 @@ top_filename("t_gen_genblk.v"); scenarios(simulator => 1); +$Self->{sim_time} = 11000; + compile( v_flags2 => ["-Oi"], ); diff --git a/test_regress/t/t_gen_intdot2.v b/test_regress/t/t_gen_intdot2.v index d405a9d47..a2f3886ca 100644 --- a/test_regress/t/t_gen_intdot2.v +++ b/test_regress/t/t_gen_intdot2.v @@ -64,11 +64,8 @@ module Genit ( else One ifcell1(); // genblk1.ifcell1 endgenerate - // On compliant simulators "Implicit name" not allowed here; IE we can't use "genblk1" etc -`ifdef verilator + // DISAGREEMENT on this naming always @ (posedge clk) if (genblk1.ifcell1.one !== 1'b1) $stop; -//`else // NOT SUPPORTED accoring to spec - generic block references -`endif generate begin : namedif2 @@ -76,10 +73,8 @@ module Genit ( One ifcell2(); // namedif2.genblk1.ifcell2 end endgenerate -`ifdef verilator + // DISAGREEMENT on this naming always @ (posedge clk) if (namedif2.genblk1.ifcell2.one !== 1'b1) $stop; -//`else // NOT SUPPORTED accoring to spec - generic block references -`endif generate if (1'b1) @@ -91,15 +86,15 @@ module Genit ( // CASE generate - case (1'b1) - 1'b1 : - One casecell10(); // genblk3.casecell10 - endcase + begin : casecheck + case (1'b1) + 1'b1 : + One casecell10(); // genblk4.casecell10 + endcase + end endgenerate -`ifdef verilator - always @ (posedge clk) if (genblk3.casecell10.one !== 1'b1) $stop; -//`else // NOT SUPPORTED accoring to spec - generic block references -`endif + // DISAGREEMENT on this naming + always @ (posedge clk) if (casecheck.genblk1.casecell10.one !== 1'b1) $stop; generate case (1'b1) @@ -113,16 +108,15 @@ module Genit ( genvar i; genvar j; - // IF generate - for (i = 0; i < 2; i = i + 1) - One cellfor20 (); // genblk4[0..1].cellfor20 + begin : genfor + for (i = 0; i < 2; i = i + 1) + One cellfor20 (); // genfor.genblk1[0..1].cellfor20 + end endgenerate -`ifdef verilator - always @ (posedge clk) if (genblk4[0].cellfor20.one !== 1'b1) $stop; - always @ (posedge clk) if (genblk4[1].cellfor20.one !== 1'b1) $stop; -//`else // NOT SUPPORTED accoring to spec - generic block references -`endif + // DISAGREEMENT on this naming + always @ (posedge clk) if (genfor.genblk1[0].cellfor20.one !== 1'b1) $stop; + always @ (posedge clk) if (genfor.genblk1[1].cellfor20.one !== 1'b1) $stop; // COMBO generate diff --git a/test_regress/t/t_generate_fatal_bad.out b/test_regress/t/t_generate_fatal_bad.out index 1e3d4e2b1..c23052748 100644 --- a/test_regress/t/t_generate_fatal_bad.out +++ b/test_regress/t/t_generate_fatal_bad.out @@ -1,7 +1,7 @@ %Warning-USERFATAL: "boom" ... Use "/* verilator lint_off USERFATAL */" and lint_on around source to disable this message. %Error: t/t_generate_fatal_bad.v:13:29: Expecting expression to be constant, but can't determine constant for FUNCREF 'get_baz' - : ... In instance t.genloop[0].foo_inst + : ... In instance t.nested_loop[10].foo2_inst.foo2_loop[1].foo_in_foo2_inst t/t_generate_fatal_bad.v:9:4: ... Location of non-constant STOP: $stop executed during function constification; maybe indicates assertion firing t/t_generate_fatal_bad.v:13:29: ... Called from get_baz() with parameters: bar = ?32?h0 @@ -50,7 +50,7 @@ 13 | localparam integer BAZ = get_baz(BAR); | ^~~~~~~ %Error: t/t_generate_fatal_bad.v:13:29: Expecting expression to be constant, but can't determine constant for FUNCREF 'get_baz' - : ... In instance t.genblk1.foo_inst4 + : ... In instance t.genblk4.foo_inst4 t/t_generate_fatal_bad.v:9:4: ... Location of non-constant STOP: $stop executed during function constification; maybe indicates assertion firing t/t_generate_fatal_bad.v:13:29: ... Called from get_baz() with parameters: bar = ?32?h7 diff --git a/test_regress/t/t_genfor_signed.out b/test_regress/t/t_genfor_signed.out new file mode 100644 index 000000000..7f921d5a9 --- /dev/null +++ b/test_regress/t/t_genfor_signed.out @@ -0,0 +1,9 @@ +top.t.u_sub1.unnamedblk1 1..1 i=1 +top.t.u_sub0.unnamedblk1 1..0 i=1 +top.t.u_sub0.unnamedblk1 1..0 i=0 +top.t.SUB_PIPE[-1].u_sub.unnamedblk1 1..-1 i=1 +top.t.SUB_PIPE[-1].u_sub.unnamedblk1 1..-1 i=0 +top.t.SUB_PIPE[-1].u_sub.unnamedblk1 1..-1 i=-1 +top.t.SUB_PIPE[0].u_sub.unnamedblk1 1..0 i=1 +top.t.SUB_PIPE[0].u_sub.unnamedblk1 1..0 i=0 +*-* All Finished *-* diff --git a/test_regress/t/t_genfor_signed.pl b/test_regress/t/t_genfor_signed.pl new file mode 100755 index 000000000..c6a015747 --- /dev/null +++ b/test_regress/t/t_genfor_signed.pl @@ -0,0 +1,22 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2019 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(simulator => 1); + +compile( + ); + +execute( + check_finished => 1, + expect_filename => $Self->{golden_filename}, + ); + +ok(1); +1; diff --git a/test_regress/t/t_genfor_signed.v b/test_regress/t/t_genfor_signed.v new file mode 100644 index 000000000..e79d64bac --- /dev/null +++ b/test_regress/t/t_genfor_signed.v @@ -0,0 +1,64 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// Use this file as a template for submitting bugs, etc. +// This module takes a single clock input, and should either +// $write("*-* All Finished *-*\n"); +// $finish; +// on success, or $stop. +// +// The code as shown applies a random vector to the Test +// module, then calculates a CRC on the Test module's outputs. +// +// **If you do not wish for your code to be released to the public +// please note it here, otherwise:** +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2020 by ____YOUR_NAME_HERE____. +// SPDX-License-Identifier: CC0-1.0 + +module t # + ( + parameter PIPE = 4 + )(/*AUTOARG*/ + // Inputs + clk + ); + + input clk; + + // These are ok + sub #( + .P_STOP (1) + ) u_sub1 (); + sub #( + .P_STOP (0) + ) u_sub0 (); + + genvar i; + for (i = -1; i < 1; i++) begin: SUB_PIPE + sub #( + .P_STOP (i) + ) u_sub (); + end + + always @ (posedge clk) begin + $write("*-* All Finished *-*\n"); + $finish; + end + +endmodule + +module sub # + ( + parameter P_START = 1, + parameter P_STOP = 0 + )( + ); + + initial begin + for (int i = P_START; i >= P_STOP; --i) begin + $display("%m %0d..%0d i=%0d", P_START, P_STOP, i); + end + end + +endmodule diff --git a/test_regress/t/t_hier_block.pl b/test_regress/t/t_hier_block.pl index e856d3cd8..fe743cb94 100755 --- a/test_regress/t/t_hier_block.pl +++ b/test_regress/t/t_hier_block.pl @@ -28,10 +28,11 @@ execute( check_finished => 1, ); +file_grep($Self->{obj_dir} . "/Vsub0/sub0.sv", qr/^\s+\/\/\s+timeprecision\s+(\d+)ps;/mi, 1); file_grep($Self->{obj_dir} . "/Vsub0/sub0.sv", /^module\s+(\S+)\s+/, "sub0"); file_grep($Self->{obj_dir} . "/Vsub1/sub1.sv", /^module\s+(\S+)\s+/, "sub1"); file_grep($Self->{obj_dir} . "/Vsub2/sub2.sv", /^module\s+(\S+)\s+/, "sub2"); -file_grep($Self->{stats}, qr/HierBlock,\s+Hierarchical blocks\s+(\d+)/i, 10); +file_grep($Self->{stats}, qr/HierBlock,\s+Hierarchical blocks\s+(\d+)/i, 13); file_grep($Self->{run_log_filename}, qr/MACRO:(\S+) is defined/i, "cplusplus"); ok(1); diff --git a/test_regress/t/t_hier_block.v b/test_regress/t/t_hier_block.v index 26c722cb6..7c8ee9e15 100644 --- a/test_regress/t/t_hier_block.v +++ b/test_regress/t/t_hier_block.v @@ -9,7 +9,7 @@ `define HIER_BLOCK /*verilator hier_block*/ `endif -`ifndef PROTLIB_TOP +`ifdef SHOW_TIMESCALE `timescale 1ns/1ps `endif @@ -215,6 +215,102 @@ module sub4 #( reg [7:0] ff; always_ff @(posedge clk) ff <= in + 8'(P0); assign out = ff; + + logic [127:0] sub5_in[2][3]; + wire [7:0] sub5_out[2][3]; + sub5 i_sub5(.clk(clk), .in(sub5_in), .out(sub5_out)); + + int count = 0; + always @(posedge clk) begin + if (!count[0]) begin + sub5_in[0][0] <= 128'd0; + sub5_in[0][1] <= 128'd1; + sub5_in[0][2] <= 128'd2; + sub5_in[1][0] <= 128'd3; + sub5_in[1][1] <= 128'd4; + sub5_in[1][2] <= 128'd5; + end else begin + sub5_in[0][0] <= 128'd0; + sub5_in[0][1] <= 128'd0; + sub5_in[0][2] <= 128'd0; + sub5_in[1][0] <= 128'd0; + sub5_in[1][1] <= 128'd0; + sub5_in[1][2] <= 128'd0; + end + end + + always @(posedge clk) begin + count <= count + 1; + if (count > 0) begin + for (int i = 0; i < 2; ++i) begin + for (int j = 0; j < 3; ++j) begin + automatic byte exp = !count[0] ? 8'(3 * (1 - i) + (2- j) + 1) : 8'b0; + if (sub5_out[i][j] != exp) begin + $display("in[%d][%d] act:%d exp:%d", i, j, sub5_out[i][j], exp); + $stop; + end + end + end + end + end +endmodule + +module sub5 (input wire clk, input wire [127:0] in[2][3], output logic [7:0] out[2][3]); `HIER_BLOCK + + int count = 0; + always @(posedge clk) begin + count <= count + 1; + if (count > 0) begin + for (int i = 0; i < 2; ++i) begin + for (int j = 0; j < 3; ++j) begin + automatic bit [127:0] exp = count[0] ? 128'(3 * i + 128'(j)) : 128'd0; + if (in[i][j] != exp) begin + $display("in[%d][%d] act:%d exp:%d", i, j, in[i][j], exp); + $stop; + end + end + end + end + end + + always @(posedge clk) begin + if (count[0]) begin + out[0][0] <= 8'd6; + out[0][1] <= 8'd5; + out[0][2] <= 8'd4; + out[1][0] <= 8'd3; + out[1][1] <= 8'd2; + out[1][2] <= 8'd1; + end else begin + out[0][0] <= 8'd0; + out[0][1] <= 8'd0; + out[0][2] <= 8'd0; + out[1][0] <= 8'd0; + out[1][1] <= 8'd0; + out[1][2] <= 8'd0; + end + end + + wire [7:0] val0[2]; + wire [7:0] val1[2]; + wire [7:0] val2[2]; + wire [7:0] val3[2]; + sub6 i_sub0(.out(val0)); + sub6 #(.P0(1)) i_sub1(.out(val1)); // Setting the default value + sub6 #(.P0(1), .P1(2)) i_sub2(.out(val2)); // Setting the default value + sub6 #(.P0(1), .P1(3)) i_sub3(.out(val3)); + + always @(posedge clk) begin + if (val0[0] != 1 || val0[1] != 2) $stop; + if (val1[0] != 1 || val1[1] != 2) $stop; + if (val2[0] != 1 || val2[1] != 2) $stop; + if (val3[0] != 1 || val3[1] != 3) $stop; + end +endmodule + +module sub6 #(parameter P0 = 1, parameter P1 = 2) (output wire [7:0] out[2]); `HIER_BLOCK + assign out[0] = 8'(P0); + assign out[1] = 8'(P1); endmodule module delay #( diff --git a/test_regress/t/t_hier_block_cmake.pl b/test_regress/t/t_hier_block_cmake.pl index 7f7c28cba..0517b3a3b 100755 --- a/test_regress/t/t_hier_block_cmake.pl +++ b/test_regress/t/t_hier_block_cmake.pl @@ -33,7 +33,7 @@ if (!$Self->have_cmake) { file_grep($target_dir . 'Vsub0/sub0.sv', /^module\s+(\S+)\s+/, "sub0"); file_grep($target_dir . 'Vsub1/sub1.sv', /^module\s+(\S+)\s+/, "sub1"); file_grep($target_dir . 'Vsub2/sub2.sv', /^module\s+(\S+)\s+/, "sub2"); - file_grep($target_dir . 'Vt_hier_block__stats.txt', qr/HierBlock,\s+Hierarchical blocks\s+(\d+)/i, 10); + file_grep($target_dir . 'Vt_hier_block__stats.txt', qr/HierBlock,\s+Hierarchical blocks\s+(\d+)/i, 13); file_grep($Self->{obj_dir} . '/run.log', qr/MACRO:(\S+) is defined/i, "cplusplus"); } diff --git a/test_regress/t/t_hier_block_sc.pl b/test_regress/t/t_hier_block_sc.pl index 7b85fedd8..139b280b9 100755 --- a/test_regress/t/t_hier_block_sc.pl +++ b/test_regress/t/t_hier_block_sc.pl @@ -34,7 +34,7 @@ execute( file_grep($Self->{obj_dir} . "/Vsub0/sub0.sv", /^module\s+(\S+)\s+/, "sub0"); file_grep($Self->{obj_dir} . "/Vsub1/sub1.sv", /^module\s+(\S+)\s+/, "sub1"); file_grep($Self->{obj_dir} . "/Vsub2/sub2.sv", /^module\s+(\S+)\s+/, "sub2"); -file_grep($Self->{stats}, qr/HierBlock,\s+Hierarchical blocks\s+(\d+)/i, 10); +file_grep($Self->{stats}, qr/HierBlock,\s+Hierarchical blocks\s+(\d+)/i, 13); file_grep($Self->{run_log_filename}, qr/MACRO:(\S+) is defined/i, "cplusplus"); ok(1); diff --git a/test_regress/t/t_hier_block_vlt.pl b/test_regress/t/t_hier_block_vlt.pl index f5231113b..904182717 100755 --- a/test_regress/t/t_hier_block_vlt.pl +++ b/test_regress/t/t_hier_block_vlt.pl @@ -20,6 +20,7 @@ compile( v_flags2 => ['t/t_hier_block.cpp'], verilator_flags2 => ['--stats', '--hierarchical', + '+define+SHOW_TIMESCALE', '+define+USE_VLT', 't/t_hier_block_vlt.vlt', '--CFLAGS', '"-pipe -DCPP_MACRO=cplusplus"', ($Self->{vltmt} ? ' --threads 6' : '')], @@ -29,10 +30,11 @@ execute( check_finished => 1, ); +file_grep($Self->{obj_dir} . "/Vsub0/sub0.sv", qr/^\s+timeprecision\s+(\d+)ps;/mi, 1); file_grep($Self->{obj_dir} . "/Vsub0/sub0.sv", /^module\s+(\S+)\s+/, "sub0"); file_grep($Self->{obj_dir} . "/Vsub1/sub1.sv", /^module\s+(\S+)\s+/, "sub1"); file_grep($Self->{obj_dir} . "/Vsub2/sub2.sv", /^module\s+(\S+)\s+/, "sub2"); -file_grep($Self->{stats}, qr/HierBlock,\s+Hierarchical blocks\s+(\d+)/i, 10); +file_grep($Self->{stats}, qr/HierBlock,\s+Hierarchical blocks\s+(\d+)/i, 13); file_grep($Self->{run_log_filename}, qr/MACRO:(\S+) is defined/i, "cplusplus"); ok(1); diff --git a/test_regress/t/t_inside_queue_bad.out b/test_regress/t/t_inside_queue_bad.out new file mode 100644 index 000000000..ad0b436c9 --- /dev/null +++ b/test_regress/t/t_inside_queue_bad.out @@ -0,0 +1,13 @@ +%Error: t/t_inside_queue_bad.v:15:15: Inside operator not legal on non-unpacked arrays (IEEE 1800-2017 11.4.13) + : ... In instance t + 15 | m = (10 inside {q}); + | ^~~~~~ +%Error: t/t_inside_queue_bad.v:16:15: Inside operator not legal on non-unpacked arrays (IEEE 1800-2017 11.4.13) + : ... In instance t + 16 | m = (10 inside {assoc}); + | ^~~~~~ +%Error: t/t_inside_queue_bad.v:17:15: Inside operator not legal on non-unpacked arrays (IEEE 1800-2017 11.4.13) + : ... In instance t + 17 | m = (10 inside {dyn}); + | ^~~~~~ +%Error: Exiting due to diff --git a/test_regress/t/t_inside_queue_bad.pl b/test_regress/t/t_inside_queue_bad.pl new file mode 100755 index 000000000..ffb804e48 --- /dev/null +++ b/test_regress/t/t_inside_queue_bad.pl @@ -0,0 +1,19 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2019 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(linter => 1); + +compile( + fails => 1, + expect_filename => $Self->{golden_filename}, + ); + +ok(1); +1; diff --git a/test_regress/t/t_inside_queue_bad.v b/test_regress/t/t_inside_queue_bad.v new file mode 100644 index 000000000..4e3e0c9a8 --- /dev/null +++ b/test_regress/t/t_inside_queue_bad.v @@ -0,0 +1,20 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2020 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +module t(/*AUTOARG*/); + + int q[$]; + int assoc[int]; + int dyn[]; + bit m; + + initial begin + m = (10 inside {q}); + m = (10 inside {assoc}); + m = (10 inside {dyn}); + end + +endmodule diff --git a/test_regress/t/t_inside_unpack.out b/test_regress/t/t_inside_unpack.out deleted file mode 100644 index e7037fc4a..000000000 --- a/test_regress/t/t_inside_unpack.out +++ /dev/null @@ -1,4 +0,0 @@ -%Error: t/t_inside_unpack.v:13:31: Unsupported: inside on unpacked array - 13 | localparam int CHECKLIST_P [2:0] = '{0, 1, 2}; - | ^ -%Error: Exiting due to diff --git a/test_regress/t/t_inside_unpacked.out b/test_regress/t/t_inside_unpacked.out new file mode 100644 index 000000000..608d0f49b --- /dev/null +++ b/test_regress/t/t_inside_unpacked.out @@ -0,0 +1,9 @@ +%Error: t/t_inside_unpacked.v:17:35: Unsupported: inside (set membership operator) on unpacked array + : ... In instance t + 17 | localparam HIT_INSIDE = HIT_LP inside {CHECKLIST_P}; + | ^~~~~~ +%Error: t/t_inside_unpacked.v:18:37: Unsupported: inside (set membership operator) on unpacked array + : ... In instance t + 18 | localparam MISS_INSIDE = MISS_LP inside {CHECKLIST_P}; + | ^~~~~~ +%Error: Exiting due to diff --git a/test_regress/t/t_inside_unpack.pl b/test_regress/t/t_inside_unpacked.pl similarity index 100% rename from test_regress/t/t_inside_unpack.pl rename to test_regress/t/t_inside_unpacked.pl diff --git a/test_regress/t/t_inside_unpack.v b/test_regress/t/t_inside_unpacked.v similarity index 100% rename from test_regress/t/t_inside_unpack.v rename to test_regress/t/t_inside_unpacked.v diff --git a/test_regress/t/t_inst_missing_dot_bad.out b/test_regress/t/t_inst_missing_dot_bad.out new file mode 100644 index 000000000..025688ecb --- /dev/null +++ b/test_regress/t/t_inst_missing_dot_bad.out @@ -0,0 +1,7 @@ +%Error: t/t_inst_missing_dot_bad.v:9:22: Dotted reference to instance that refers to missing module/interface: 'missing' + 9 | $display("a=", missing.a); + | ^~~~~~~ +%Error: t/t_inst_missing_dot_bad.v:9:30: Can't find definition of 'a' in dotted variable: 'missing.a' + 9 | $display("a=", missing.a); + | ^ +%Error: Exiting due to diff --git a/test_regress/t/t_inst_missing_dot_bad.pl b/test_regress/t/t_inst_missing_dot_bad.pl new file mode 100755 index 000000000..a60503a1f --- /dev/null +++ b/test_regress/t/t_inst_missing_dot_bad.pl @@ -0,0 +1,19 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(linter => 1); + +lint( + fails => 1, + expect_filename => $Self->{golden_filename}, + ); + +ok(1); +1; diff --git a/test_regress/t/t_inst_missing_dot_bad.v b/test_regress/t/t_inst_missing_dot_bad.v new file mode 100644 index 000000000..e2570bd5f --- /dev/null +++ b/test_regress/t/t_inst_missing_dot_bad.v @@ -0,0 +1,12 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2019 by Stefan Wallentowitz. +// SPDX-License-Identifier: CC0-1.0 + +module t; + initial begin + $display("a=", missing.a); + end + missing missing(); // Intentionally missing +endmodule diff --git a/test_regress/t/t_inst_pin_realnreal.out b/test_regress/t/t_inst_pin_realnreal.out new file mode 100755 index 000000000..34eade000 --- /dev/null +++ b/test_regress/t/t_inst_pin_realnreal.out @@ -0,0 +1,5 @@ +%Error-UNSUPPORTED: t/t_inst_pin_realnreal.v:51:32: Unsupported: Output port connection 'out' connects real to non-real + : ... In instance t.netlist + 51 | pga_model pga0(.in, .gain, .out(pga_out)); + | ^~~ +%Error: Exiting due to diff --git a/test_regress/t/t_inst_pin_realnreal.pl b/test_regress/t/t_inst_pin_realnreal.pl new file mode 100755 index 000000000..40f69d41d --- /dev/null +++ b/test_regress/t/t_inst_pin_realnreal.pl @@ -0,0 +1,23 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2019 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(simulator => 1); + +compile( + fails => $Self->{vlt_all}, + expect_filename => $Self->{golden_filename}, + ); + +execute( + check_finished => 1, + ) if !$Self->{vlt_all}; + +ok(1); +1; diff --git a/test_regress/t/t_inst_pin_realnreal.v b/test_regress/t/t_inst_pin_realnreal.v new file mode 100644 index 000000000..5c5539661 --- /dev/null +++ b/test_regress/t/t_inst_pin_realnreal.v @@ -0,0 +1,76 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2020 by Peter Monsson. +// SPDX-License-Identifier: CC0-1.0 + +module t (/*AUTOARG*/ + // Inputs + clk + ); + + input clk; + integer cyc; initial cyc=1; + + wire gain = 1'b0; + real in; + always_comb in = (cyc-4) * 1.0; + wire cmp; + + adc_netlist netlist(.clk, .in, .gain, .cmp); + + always @ (posedge clk) begin + if (cyc!=0) begin + cyc <= cyc + 1; + $display("cyc=%0d cmp=%d", cyc, cmp); + if (cyc == 3) begin + if (cmp != 0) $stop; + end + else if (cyc == 4) begin + if (cmp != 1) $stop; + end + else if (cyc == 5) begin + if (cmp != 0) $stop; + end + else if (cyc == 10) begin + $write("*-* All Finished *-*\n"); + $finish; + end + end + end + +endmodule + +module adc_netlist(clk, in, gain, cmp); + input clk; + input real in; + input gain; + output cmp; + + wire pga_out; //TODO: convert to real or support real + pga_model pga0(.in, .gain, .out(pga_out)); + comparator_model cmp0(.clk, .in(pga_out), .cmp); + +endmodule + +module pga_model(in, gain, out); + input real in; + input gain; + output real out; + + always_comb begin + out = in * 3.0; + end + +endmodule + +module comparator_model(clk, in, cmp); + input clk; + input real in; + output logic cmp; + + always_ff @(posedge clk) begin + cmp <= in > 0.0; + end + +endmodule diff --git a/test_regress/t/t_interface_array2.pl b/test_regress/t/t_interface_array2.pl new file mode 100755 index 000000000..b46d46042 --- /dev/null +++ b/test_regress/t/t_interface_array2.pl @@ -0,0 +1,21 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(simulator => 1); + +compile( + ); + +execute( + check_finished => 1, + ); + +ok(1); +1; diff --git a/test_regress/t/t_array_interface.v b/test_regress/t/t_interface_array2.v similarity index 100% rename from test_regress/t/t_array_interface.v rename to test_regress/t/t_interface_array2.v diff --git a/test_regress/t/t_array_interface_noinl.pl b/test_regress/t/t_interface_array2_noinl.pl similarity index 93% rename from test_regress/t/t_array_interface_noinl.pl rename to test_regress/t/t_interface_array2_noinl.pl index 3b2379a98..ad389d0fb 100755 --- a/test_regress/t/t_array_interface_noinl.pl +++ b/test_regress/t/t_interface_array2_noinl.pl @@ -10,7 +10,7 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di scenarios(simulator => 1); -top_filename("t/t_array_interface.v"); +top_filename("t/t_interface_array2.v"); compile( v_flags2 => ["-Oi"], diff --git a/test_regress/t/t_interface_array_nocolon_bad.out b/test_regress/t/t_interface_array_nocolon_bad.out index 6d528dd58..546031d0c 100644 --- a/test_regress/t/t_interface_array_nocolon_bad.out +++ b/test_regress/t/t_interface_array_nocolon_bad.out @@ -1,17 +1,17 @@ -%Warning-LITENDIAN: t/t_interface_array_nocolon_bad.v:26:26: Little endian cell range connecting to vector: MSB < LSB of cell range: 0:2 +%Warning-LITENDIAN: t/t_interface_array_nocolon_bad.v:26:26: Little endian instance range connecting to vector: left < right of instance range: [0:2] : ... In instance t 26 | foo_intf foos [N] (.x(X)); | ^ ... Use "/* verilator lint_off LITENDIAN */" and lint_on around source to disable this message. -%Warning-LITENDIAN: t/t_interface_array_nocolon_bad.v:27:28: Little endian cell range connecting to vector: MSB < LSB of cell range: 1:3 +%Warning-LITENDIAN: t/t_interface_array_nocolon_bad.v:27:28: Little endian instance range connecting to vector: left < right of instance range: [1:3] : ... In instance t 27 | foo_intf fool [1:3] (.x(X)); | ^ -%Warning-LITENDIAN: t/t_interface_array_nocolon_bad.v:30:26: Little endian cell range connecting to vector: MSB < LSB of cell range: 0:2 +%Warning-LITENDIAN: t/t_interface_array_nocolon_bad.v:30:26: Little endian instance range connecting to vector: left < right of instance range: [0:2] : ... In instance t 30 | foo_subm subs [N] (.x(X)); | ^ -%Warning-LITENDIAN: t/t_interface_array_nocolon_bad.v:31:28: Little endian cell range connecting to vector: MSB < LSB of cell range: 1:3 +%Warning-LITENDIAN: t/t_interface_array_nocolon_bad.v:31:28: Little endian instance range connecting to vector: left < right of instance range: [1:3] : ... In instance t 31 | foo_subm subl [1:3] (.x(X)); | ^ diff --git a/test_regress/t/t_interface_import_param.pl b/test_regress/t/t_interface_import_param.pl new file mode 100755 index 000000000..b46d46042 --- /dev/null +++ b/test_regress/t/t_interface_import_param.pl @@ -0,0 +1,21 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(simulator => 1); + +compile( + ); + +execute( + check_finished => 1, + ); + +ok(1); +1; diff --git a/test_regress/t/t_interface_import_param.v b/test_regress/t/t_interface_import_param.v new file mode 100644 index 000000000..82969649d --- /dev/null +++ b/test_regress/t/t_interface_import_param.v @@ -0,0 +1,47 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// A test that a package import declaration can preceed a parameter port list +// in an interface declaration. See 25.3 of the 1800-2017 LRM. +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2013 by Jeremy Bennett. +// SPDX-License-Identifier: CC0-1.0 + +package bus_pkg; + parameter WIDTH = 8; +endpackage + +interface simple_bus + import bus_pkg::*; // Import preceding parameters. + #(p_width = WIDTH) + (input logic clk); + + logic req, gnt; + logic [p_width-1:0] addr; + logic [p_width-1:0] data; + + modport slave(input req, addr, clk, + output gnt, + input data); + + modport master(input gnt, clk, + output req, addr, + output data); + +endinterface + +module mem(simple_bus a); + logic avail; + always @(posedge a.clk) + a.gnt <= a.req & avail; + initial begin + if ($bits(a.data) != 8) $stop; + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule + +module t (input clk); + simple_bus sb(clk); + mem mem(sb.slave); +endmodule diff --git a/test_regress/t/t_interface_mismodport_bad.out b/test_regress/t/t_interface_mismodport_bad.out index 20e79489d..a46bee788 100644 --- a/test_regress/t/t_interface_mismodport_bad.out +++ b/test_regress/t/t_interface_mismodport_bad.out @@ -1,5 +1,5 @@ %Error: t/t_interface_mismodport_bad.v:36:12: Can't find definition of 'bad' in dotted signal: 'isub.bad' 36 | isub.bad = i_value; | ^~~ - ... Known scopes under 'bad': + ... Known scopes under 'bad': %Error: Exiting due to diff --git a/test_regress/t/t_interface_top_bad.out b/test_regress/t/t_interface_top_bad.out index 6947f5dea..9ff12283c 100644 --- a/test_regress/t/t_interface_top_bad.out +++ b/test_regress/t/t_interface_top_bad.out @@ -1,7 +1,7 @@ %Error-UNSUPPORTED: t/t_interface_top_bad.v:17:19: Unsupported: Interfaced port on top level module 17 | ifc.counter_mp c_data | ^~~~~~ -%Error: t/t_interface_top_bad.v:17:4: Parent cell's interface is not found: 'ifc' +%Error: t/t_interface_top_bad.v:17:4: Parent instance's interface is not found: 'ifc' 17 | ifc.counter_mp c_data | ^~~ %Error: Exiting due to diff --git a/test_regress/t/t_interface_typo_bad.out b/test_regress/t/t_interface_typo_bad.out index c509e157d..3f80ecf61 100644 --- a/test_regress/t/t_interface_typo_bad.out +++ b/test_regress/t/t_interface_typo_bad.out @@ -1,4 +1,4 @@ -%Error: t/t_interface_typo_bad.v:14:4: Parent cell's interface is not found: 'foo_intf' +%Error: t/t_interface_typo_bad.v:14:4: Parent instance's interface is not found: 'foo_intf' 14 | foo_intf foo | ^~~~~~~~ %Error: t/t_interface_typo_bad.v:22:4: Cannot find file containing interface: 'fo_intf' diff --git a/test_regress/t/t_lint_caseincomplete_bad.out b/test_regress/t/t_lint_caseincomplete_bad.out new file mode 100644 index 000000000..ab527489b --- /dev/null +++ b/test_regress/t/t_lint_caseincomplete_bad.out @@ -0,0 +1,5 @@ +%Warning-CASEINCOMPLETE: t/t_lint_caseincomplete_bad.v:15:7: Case values incompletely covered (example pattern 0x1) + 15 | case (i) + | ^~~~ + ... Use "/* verilator lint_off CASEINCOMPLETE */" and lint_on around source to disable this message. +%Error: Exiting due to diff --git a/test_regress/t/t_lint_caseincomplete_bad.pl b/test_regress/t/t_lint_caseincomplete_bad.pl new file mode 100755 index 000000000..a60503a1f --- /dev/null +++ b/test_regress/t/t_lint_caseincomplete_bad.pl @@ -0,0 +1,19 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(linter => 1); + +lint( + fails => 1, + expect_filename => $Self->{golden_filename}, + ); + +ok(1); +1; diff --git a/test_regress/t/t_lint_caseincomplete_bad.v b/test_regress/t/t_lint_caseincomplete_bad.v new file mode 100644 index 000000000..c2b25973f --- /dev/null +++ b/test_regress/t/t_lint_caseincomplete_bad.v @@ -0,0 +1,21 @@ +// DESCRIPTION: Verilator: Test of select from constant +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2020 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +module t (/*AUTOARG*/ + // Inputs + i + ); + + input [1:0] i; + + always_comb begin + case (i) + 2'b00: ; + 2'b10: ; + 2'b11: ; + endcase + end +endmodule diff --git a/test_regress/t/t_lint_cmpconst_bad.out b/test_regress/t/t_lint_cmpconst_bad.out new file mode 100644 index 000000000..a2c156ebf --- /dev/null +++ b/test_regress/t/t_lint_cmpconst_bad.out @@ -0,0 +1,6 @@ +%Warning-CMPCONST: t/t_lint_cmpconst_bad.v:13:15: Comparison is constant due to limited range + : ... In instance t + 13 | if (uns > 3'b111) $stop; + | ^ + ... Use "/* verilator lint_off CMPCONST */" and lint_on around source to disable this message. +%Error: Exiting due to diff --git a/test_regress/t/t_lint_cmpconst_bad.pl b/test_regress/t/t_lint_cmpconst_bad.pl new file mode 100755 index 000000000..a60503a1f --- /dev/null +++ b/test_regress/t/t_lint_cmpconst_bad.pl @@ -0,0 +1,19 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(linter => 1); + +lint( + fails => 1, + expect_filename => $Self->{golden_filename}, + ); + +ok(1); +1; diff --git a/test_regress/t/t_lint_cmpconst_bad.v b/test_regress/t/t_lint_cmpconst_bad.v new file mode 100644 index 000000000..07b736171 --- /dev/null +++ b/test_regress/t/t_lint_cmpconst_bad.v @@ -0,0 +1,15 @@ +// DESCRIPTION: Verilator: Test of select from constant +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2020 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +module t (/*AUTOARG*/); + + bit [2:0] uns; + + initial begin + uns = 1; + if (uns > 3'b111) $stop; + end +endmodule diff --git a/test_regress/t/t_lint_defparam.v b/test_regress/t/t_lint_defparam.v index 05bd79f41..a2b70f76e 100644 --- a/test_regress/t/t_lint_defparam.v +++ b/test_regress/t/t_lint_defparam.v @@ -13,4 +13,5 @@ endmodule module sub; parameter P = 6; + if (P != 0) ; // Prevent unused endmodule diff --git a/test_regress/t/t_lint_latch_1.pl b/test_regress/t/t_lint_latch_1.pl new file mode 100755 index 000000000..629a44bbb --- /dev/null +++ b/test_regress/t/t_lint_latch_1.pl @@ -0,0 +1,17 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003-2009 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(vlt => 1); + +lint( + ); + +ok(1); +1; diff --git a/test_regress/t/t_lint_latch_1.v b/test_regress/t/t_lint_latch_1.v new file mode 100644 index 000000000..95ae861c2 --- /dev/null +++ b/test_regress/t/t_lint_latch_1.v @@ -0,0 +1,16 @@ +// DESCRIPTION: Verilator: Verilog Test module for Issue#1609 +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2020 by Julien Margetts. + +module t (/*AUTOARG*/ a, b, o); + input a; + input b; + output reg o; + + // verilator lint_off LATCH + always @(a or b) + if (a) + o <= b; + +endmodule diff --git a/test_regress/t/t_lint_latch_2.pl b/test_regress/t/t_lint_latch_2.pl new file mode 100755 index 000000000..629a44bbb --- /dev/null +++ b/test_regress/t/t_lint_latch_2.pl @@ -0,0 +1,17 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003-2009 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(vlt => 1); + +lint( + ); + +ok(1); +1; diff --git a/test_regress/t/t_lint_latch_2.v b/test_regress/t/t_lint_latch_2.v new file mode 100644 index 000000000..d3c93d9d0 --- /dev/null +++ b/test_regress/t/t_lint_latch_2.v @@ -0,0 +1,20 @@ +// DESCRIPTION: Verilator: Verilog Test module for Issue#1609 +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2020 by Julien Margetts. + +module t (/*AUTOARG*/ i, o); + + input [1:0] i; + output reg [1:0] o; + + // This should not detect a latch as all options are covered + always @* begin + if (i==2'b00) o = 2'b11; + else if (i==2'b01) o = 2'b10; + else if (i==2'b10) o = 2'b01; + else if (i==2'b11) o = 2'b00; + else o = 2'b00; // Without this else a latch is (falsely) detected + end + +endmodule diff --git a/test_regress/t/t_lint_latch_3.pl b/test_regress/t/t_lint_latch_3.pl new file mode 100755 index 000000000..629a44bbb --- /dev/null +++ b/test_regress/t/t_lint_latch_3.pl @@ -0,0 +1,17 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003-2009 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(vlt => 1); + +lint( + ); + +ok(1); +1; diff --git a/test_regress/t/t_lint_latch_3.v b/test_regress/t/t_lint_latch_3.v new file mode 100644 index 000000000..6ba537f89 --- /dev/null +++ b/test_regress/t/t_lint_latch_3.v @@ -0,0 +1,50 @@ +// DESCRIPTION: Verilator: Verilog Test module for Issue#1609 +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2020 by Julien Margetts. + +module t (/*AUTOARG*/ out, out2, in ); + + input [9:0] in; + output reg [3:0] out; + output reg [3:0] out2; + + // Should be no latch here since the input space is fully covered + + always @* begin + casez (in) + 10'b0000000000 : out = 4'h0; + 10'b?????????1 : out = 4'h0; + 10'b????????10 : out = 4'h1; + 10'b???????100 : out = 4'h2; + 10'b??????1000 : out = 4'h3; + 10'b?????10000 : out = 4'h4; + 10'b????100000 : out = 4'h5; + 10'b???1000000 : out = 4'h6; + 10'b??10000000 : out = 4'h7; + 10'b?100000000 : out = 4'h8; + 10'b1000000000 : out = 4'h9; + endcase + end + + // Should detect a latch here since not all paths assign + // BUT we don't because warnOff(LATCH) is set for any always containing a + // complex case statement + + always @* begin + casez (in) + 10'b0000000000 : out2 = 4'h0; + 10'b?????????1 : out2 = 4'h0; + 10'b????????10 : out2 = 4'h1; + 10'b???????100 : out2 = 4'h2; + 10'b??????1000 : out2 = 4'h3; + 10'b?????10000 : /* No assignement */ ; + 10'b????100000 : out2 = 4'h5; + 10'b???1000000 : out2 = 4'h6; + 10'b??10000000 : out2 = 4'h7; + 10'b?100000000 : out2 = 4'h8; + 10'b1000000000 : out2 = 4'h9; + endcase + end + +endmodule diff --git a/test_regress/t/t_lint_latch_bad.out b/test_regress/t/t_lint_latch_bad.out index 751a7516f..eeeb70548 100644 --- a/test_regress/t/t_lint_latch_bad.out +++ b/test_regress/t/t_lint_latch_bad.out @@ -1,8 +1,11 @@ +%Warning-NOLATCH: t/t_lint_latch_bad.v:17:4: No latches detected in always_latch block + 17 | always_latch begin + | ^~~~~~~~~~~~ + ... Use "/* verilator lint_off NOLATCH */" and lint_on around source to disable this message. %Warning-COMBDLY: t/t_lint_latch_bad.v:25:10: Delayed assignments (<=) in non-clocked (non flop or latch) block : ... Suggest blocking assignments (=) 25 | bc <= a; | ^~ - ... Use "/* verilator lint_off COMBDLY */" and lint_on around source to disable this message. *** See the manual before disabling this, else you may end up with different sim results. %Error: Exiting due to diff --git a/test_regress/t/t_lint_latch_bad_2.out b/test_regress/t/t_lint_latch_bad_2.out new file mode 100644 index 000000000..ea37dddf6 --- /dev/null +++ b/test_regress/t/t_lint_latch_bad_2.out @@ -0,0 +1,6 @@ +%Warning-LATCH: t/t_lint_latch_bad_2.v:11:4: Latch inferred for signal 'o' (not all control paths of combinational always assign a value) + : ... Suggest use of always_latch for intentional latches + 11 | always @(a or b) + | ^~~~~~ + ... Use "/* verilator lint_off LATCH */" and lint_on around source to disable this message. +%Error: Exiting due to diff --git a/test_regress/t/t_lint_latch_bad_2.pl b/test_regress/t/t_lint_latch_bad_2.pl new file mode 100755 index 000000000..34ebfdc61 --- /dev/null +++ b/test_regress/t/t_lint_latch_bad_2.pl @@ -0,0 +1,18 @@ +#!/usr/bin/perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2020 by Wilson Snyder. This program is free software; you can +# redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. + +scenarios(linter => 1); + +lint( + fails => 1, + expect_filename => $Self->{golden_filename}, + ); + +ok(1); +1; diff --git a/test_regress/t/t_lint_latch_bad_2.v b/test_regress/t/t_lint_latch_bad_2.v new file mode 100644 index 000000000..e4719d0e0 --- /dev/null +++ b/test_regress/t/t_lint_latch_bad_2.v @@ -0,0 +1,15 @@ +// DESCRIPTION: Verilator: Verilog Test module for Issue#1609 +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2020 by Julien Margetts. + +module t (/*AUTOARG*/ a, b, o); + input a; + input b; + output reg o; + + always @(a or b) + if (a) + o <= b; + +endmodule diff --git a/test_regress/t/t_lint_latch_bad_3.out b/test_regress/t/t_lint_latch_bad_3.out new file mode 100644 index 000000000..9b132b899 --- /dev/null +++ b/test_regress/t/t_lint_latch_bad_3.out @@ -0,0 +1,12 @@ +%Warning-LATCH: t/t_lint_latch_bad_3.v:18:1: Latch inferred for signal 'o5' (not all control paths of combinational always assign a value) + : ... Suggest use of always_latch for intentional latches + 18 | always @(reset or en or a or b) + | ^~~~~~ + ... Use "/* verilator lint_off LATCH */" and lint_on around source to disable this message. +%Warning-COMBDLY: t/t_lint_latch_bad_3.v:70:12: Delayed assignments (<=) in non-clocked (non flop or latch) block + : ... Suggest blocking assignments (=) + 70 | o4 <= 1'b0; + | ^~ + *** See the manual before disabling this, + else you may end up with different sim results. +%Error: Exiting due to diff --git a/test_regress/t/t_lint_latch_bad_3.pl b/test_regress/t/t_lint_latch_bad_3.pl new file mode 100755 index 000000000..34ebfdc61 --- /dev/null +++ b/test_regress/t/t_lint_latch_bad_3.pl @@ -0,0 +1,18 @@ +#!/usr/bin/perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2020 by Wilson Snyder. This program is free software; you can +# redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. + +scenarios(linter => 1); + +lint( + fails => 1, + expect_filename => $Self->{golden_filename}, + ); + +ok(1); +1; diff --git a/test_regress/t/t_lint_latch_bad_3.v b/test_regress/t/t_lint_latch_bad_3.v new file mode 100644 index 000000000..90890e1c8 --- /dev/null +++ b/test_regress/t/t_lint_latch_bad_3.v @@ -0,0 +1,74 @@ +// DESCRIPTION: Verilator: Verilog Test module for Issue#1609 +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2020 by Julien Margetts. + +module t (/*AUTOARG*/ reset, a, b, c, en, o1, o2, o3, o4, o5); + input reset; + input a; + input b; + input c; + input en; + output reg o1; // Always assigned + output reg o2; // " + output reg o3; // " + output reg o4; // " + output reg o5; // Latch + +always @(reset or en or a or b) +if (reset) +begin + o1 = 1'b0; + o2 = 1'b0; + o3 = 1'b0; + o4 = 1'b0; + o5 <= 1'b0; // Do NOT expect Warning-COMBDLY +end +else +begin + o1 = 1'b1; + if (en) + begin + o2 = 1'b0; + + if (a) + begin + o3 = a; + o5 <= 1'b1; // Do NOT expect Warning-COMBDLY + end + else + begin + o3 = ~a; + o5 <= a; // Do NOT expect Warning-COMBDLY + end + + // o3 is not assigned in either path of this if/else + // but no latch because always assigned above + if (c) + begin + o2 = a ^ b; + o4 = 1'b1; + end + else + o4 = ~a ^ b; + + o2 = 1'b1; + end + else + begin + o2 = 1'b1; + if (b) + begin + o3 = ~a | b; + o5 <= ~b; // Do NOT expect Warning-COMBDLY + end + else + begin + o3 = a & ~b; + // No assignment to o5, expect Warning-LATCH + end + o4 <= 1'b0; // expect Warning-COMBDLY + end +end + +endmodule diff --git a/test_regress/t/t_lint_nolatch_bad.out b/test_regress/t/t_lint_nolatch_bad.out new file mode 100644 index 000000000..2cdc19da9 --- /dev/null +++ b/test_regress/t/t_lint_nolatch_bad.out @@ -0,0 +1,5 @@ +%Warning-NOLATCH: t/t_lint_nolatch_bad.v:11:4: No latches detected in always_latch block + 11 | always_latch @(a or b) + | ^~~~~~~~~~~~ + ... Use "/* verilator lint_off NOLATCH */" and lint_on around source to disable this message. +%Error: Exiting due to diff --git a/test_regress/t/t_lint_nolatch_bad.pl b/test_regress/t/t_lint_nolatch_bad.pl new file mode 100755 index 000000000..0b13642c9 --- /dev/null +++ b/test_regress/t/t_lint_nolatch_bad.pl @@ -0,0 +1,18 @@ +#!/usr/bin/perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2020 by Wilson Snyder. This program is free software; you can +# redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. + +scenarios(linter => 1); + +lint( + fails => 1, + expect_filename => $Self->{golden_filename} + ); + +ok(1); +1; diff --git a/test_regress/t/t_lint_nolatch_bad.v b/test_regress/t/t_lint_nolatch_bad.v new file mode 100644 index 000000000..517f57f94 --- /dev/null +++ b/test_regress/t/t_lint_nolatch_bad.v @@ -0,0 +1,17 @@ +// DESCRIPTION: Verilator: Verilog Test module for Issue#1609 +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2020 by Julien Margetts. + +module t (/*AUTOARG*/ a, b, o); + input a; + input b; + output reg o; + + always_latch @(a or b) + if (a) + o <= b; + else + o <= ~b; + +endmodule diff --git a/test_regress/t/t_lint_unsigned_bad.out b/test_regress/t/t_lint_unsigned_bad.out new file mode 100644 index 000000000..861d13a58 --- /dev/null +++ b/test_regress/t/t_lint_unsigned_bad.out @@ -0,0 +1,6 @@ +%Warning-UNSIGNED: t/t_lint_unsigned_bad.v:13:15: Comparison is constant due to unsigned arithmetic + : ... In instance t + 13 | if (uns < 0) $stop; + | ^ + ... Use "/* verilator lint_off UNSIGNED */" and lint_on around source to disable this message. +%Error: Exiting due to diff --git a/test_regress/t/t_lint_unsigned_bad.pl b/test_regress/t/t_lint_unsigned_bad.pl new file mode 100755 index 000000000..a60503a1f --- /dev/null +++ b/test_regress/t/t_lint_unsigned_bad.pl @@ -0,0 +1,19 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(linter => 1); + +lint( + fails => 1, + expect_filename => $Self->{golden_filename}, + ); + +ok(1); +1; diff --git a/test_regress/t/t_lint_unsigned_bad.v b/test_regress/t/t_lint_unsigned_bad.v new file mode 100644 index 000000000..d81366e43 --- /dev/null +++ b/test_regress/t/t_lint_unsigned_bad.v @@ -0,0 +1,15 @@ +// DESCRIPTION: Verilator: Test of select from constant +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2020 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +module t (/*AUTOARG*/); + + bit [2:0] uns; + + initial begin + uns = 1; + if (uns < 0) $stop; + end +endmodule diff --git a/test_regress/t/t_lint_unsup_deassign.v b/test_regress/t/t_lint_unsup_deassign.v index 05454d438..77c1f2f1d 100644 --- a/test_regress/t/t_lint_unsup_deassign.v +++ b/test_regress/t/t_lint_unsup_deassign.v @@ -11,10 +11,12 @@ module t integer q; + // verilator lint_off LATCH always @(*) if (rst) assign q = 0; else deassign q; + // verilator lint_on LATCH endmodule diff --git a/test_regress/t/t_lint_unused.v b/test_regress/t/t_lint_unused.v index 3042c127e..697706563 100644 --- a/test_regress/t/t_lint_unused.v +++ b/test_regress/t/t_lint_unused.v @@ -44,8 +44,6 @@ module sub; wire pub /*verilator public*/; // Ignore publics - localparam THREE = 3; - endmodule primitive udp_mux2 (q, a, b, s); diff --git a/test_regress/t/t_lint_unused_bad.out b/test_regress/t/t_lint_unused_bad.out index 9e888314f..745ca8336 100644 --- a/test_regress/t/t_lint_unused_bad.out +++ b/test_regress/t/t_lint_unused_bad.out @@ -23,4 +23,16 @@ : ... In instance t.sub 28 | wire [3:0] mixed; | ^~~~~ +%Warning-UNUSED: t/t_lint_unused_bad.v:37:14: Parameter is not used: 'UNUSED_P' + : ... In instance t.sub + 37 | parameter UNUSED_P = 1; + | ^~~~~~~~ +%Warning-UNUSED: t/t_lint_unused_bad.v:38:15: Parameter is not used: 'UNUSED_LP' + : ... In instance t.sub + 38 | localparam UNUSED_LP = 2; + | ^~~~~~~~~ +%Warning-UNUSED: t/t_lint_unused_bad.v:40:15: Genvar is not driven, nor used: 'unused_gv' + : ... In instance t.sub + 40 | genvar unused_gv; + | ^~~~~~~~~ %Error: Exiting due to diff --git a/test_regress/t/t_lint_unused_bad.v b/test_regress/t/t_lint_unused_bad.v index 839527590..ade5152d3 100644 --- a/test_regress/t/t_lint_unused_bad.v +++ b/test_regress/t/t_lint_unused_bad.v @@ -34,9 +34,21 @@ module sub; localparam THREE = 3; + parameter UNUSED_P = 1; + localparam UNUSED_LP = 2; + + genvar unused_gv; + genvar ok_gv; + initial begin if (0 && assunu1[0] != 0 && udrb2 != 0) begin end if (0 && assunub2[THREE] && assunub2[1:0]!=0) begin end if (0 && mixed[1:0] != 0) begin end end + + generate + if (0) + for (ok_gv = 0; ok_gv < 1; ++ok_gv) begin end + endgenerate + endmodule diff --git a/test_regress/t/t_lint_width_genfor_bad.out b/test_regress/t/t_lint_width_genfor_bad.out index 5e344a696..a814e38a8 100644 --- a/test_regress/t/t_lint_width_genfor_bad.out +++ b/test_regress/t/t_lint_width_genfor_bad.out @@ -1,4 +1,4 @@ -%Warning-WIDTH: t/t_lint_width_genfor_bad.v:25:13: Operator ASSIGN expects 4 bits on the Assign RHS, but Assign RHS's CONST '?32?h10' generates 32 or 5 bits. +%Warning-WIDTH: t/t_lint_width_genfor_bad.v:25:13: Operator ASSIGN expects 4 bits on the Assign RHS, but Assign RHS's CONST '?32?sh10' generates 32 or 5 bits. : ... In instance t 25 | rg = g; | ^ diff --git a/test_regress/t/t_math_cmp.v b/test_regress/t/t_math_cmp.v index 6df08388a..bf5dc80e4 100644 --- a/test_regress/t/t_math_cmp.v +++ b/test_regress/t/t_math_cmp.v @@ -82,6 +82,7 @@ module prover ( reg signed [WIDTH-1:0] bs; wire [WIDTH-1:0] b = bs; + // verilator lint_off LATCH always @* begin casez (index_a) 3'd0: as = {(WIDTH){1'd0}}; // 0 @@ -100,6 +101,7 @@ module prover ( default: $stop; endcase end + // verilator lint_on LATCH reg [7:0] results[4:0][4:0]; diff --git a/test_regress/t/t_metacmt_onoff.out b/test_regress/t/t_metacmt_onoff.out index 5de179f75..7001223a5 100644 --- a/test_regress/t/t_metacmt_onoff.out +++ b/test_regress/t/t_metacmt_onoff.out @@ -1,9 +1,9 @@ -%Warning-LITENDIAN: t/t_metacmt_onoff.v:8:8: Little bit endian vector: MSB < LSB of bit range: 0:1 +%Warning-LITENDIAN: t/t_metacmt_onoff.v:8:8: Little bit endian vector: left < right of bit range: [0:1] : ... In instance t 8 | reg [0:1] show1; /*verilator lint_off LITENDIAN*/ reg [0:2] ign2; /*verilator lint_on LITENDIAN*/ reg [0:3] show3; | ^ ... Use "/* verilator lint_off LITENDIAN */" and lint_on around source to disable this message. -%Warning-LITENDIAN: t/t_metacmt_onoff.v:8:109: Little bit endian vector: MSB < LSB of bit range: 0:3 +%Warning-LITENDIAN: t/t_metacmt_onoff.v:8:109: Little bit endian vector: left < right of bit range: [0:3] : ... In instance t 8 | reg [0:1] show1; /*verilator lint_off LITENDIAN*/ reg [0:2] ign2; /*verilator lint_on LITENDIAN*/ reg [0:3] show3; | ^ diff --git a/test_regress/t/t_mod_interface_array3.out b/test_regress/t/t_mod_interface_array3.out index f0fd8215e..34ca8e708 100644 --- a/test_regress/t/t_mod_interface_array3.out +++ b/test_regress/t/t_mod_interface_array3.out @@ -1,7 +1,7 @@ -%Error-UNSUPPORTED: t/t_mod_interface_array3.v:25:20: Unsupported: Multidimensional cells/interfaces. +%Error-UNSUPPORTED: t/t_mod_interface_array3.v:25:20: Unsupported: Multidimensional instances/interfaces. 25 | a_if iface [2:0][1:0]; | ^ -%Error-UNSUPPORTED: t/t_mod_interface_array3.v:27:18: Unsupported: Multidimensional cells/interfaces. +%Error-UNSUPPORTED: t/t_mod_interface_array3.v:27:18: Unsupported: Multidimensional instances/interfaces. 27 | sub i_sub[2:0][1:0] (.s(str)); | ^ %Error: Exiting due to diff --git a/test_regress/t/t_optm_if_cond.pl b/test_regress/t/t_optm_if_cond.pl new file mode 100755 index 000000000..3c5833594 --- /dev/null +++ b/test_regress/t/t_optm_if_cond.pl @@ -0,0 +1,22 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2019 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(vlt => 1); + +compile( + verilator_flags2 => ['--stats'], + ); + +if ($Self->{vlt_all}) { + file_grep($Self->{stats}, qr/Node count, IF +\d+ +\d+ +\d+ +\d+ +(\d+)/, 11); +} + +ok(1); +1; diff --git a/test_regress/t/t_optm_if_cond.v b/test_regress/t/t_optm_if_cond.v new file mode 100644 index 000000000..f9509efad --- /dev/null +++ b/test_regress/t/t_optm_if_cond.v @@ -0,0 +1,57 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2020 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +module t(/*AUTOARG*/ + // Outputs + q0, q1, q2, q3, q4, + // Inputs + clk, rst, en, i0, i1, i2, i3, i4 + ); + input clk; + + input rst; + input en; + output int q0; input int i0; + output int q1; input int i1; + output int q2; input int i2; + output int q3; input int i3; + output int q4; input int i4; + + always @ (posedge clk) begin + if (rst) begin + if (en) q0 <= i0; + end + else q0 <= 0; + + if (rst) begin + if (en) q1 <= i1; + end + else q1 <= 0; + + if (rst) begin + if (en) q2 <= i2; + end + else q2 <= 0; + + if (rst) begin + if (en) q3 <= i3; + end + else q3 <= 0; + end + + always_comb begin + q4 = i4; + if (q4 == 0) begin + // Conflicts with condition + q4 = 1; + end + if (q4 == 0) begin + // Conflicts with condition + q4 = 2; + end + end + +endmodule diff --git a/test_regress/t/t_order_blkandnblk_bad.out b/test_regress/t/t_order_blkandnblk_bad.out new file mode 100644 index 000000000..67d333e77 --- /dev/null +++ b/test_regress/t/t_order_blkandnblk_bad.out @@ -0,0 +1,10 @@ +%Error-BLKANDNBLK: t/t_order_blkandnblk_bad.v:17:21: Unsupported: Blocked and non-blocking assignments to same variable: 't.array' + 17 | logic [1:0][3:0] array; + | ^~~~~ + t/t_order_blkandnblk_bad.v:19:16: ... Location of blocking assignment + 19 | always_comb array[0] = i; + | ^~~~~ + t/t_order_blkandnblk_bad.v:22:6: ... Location of nonblocking assignment + 22 | array[1] <= array[0]; + | ^~~~~ +%Error: Exiting due to diff --git a/test_regress/t/t_order_blkandnblk_bad.pl b/test_regress/t/t_order_blkandnblk_bad.pl new file mode 100755 index 000000000..a5846c699 --- /dev/null +++ b/test_regress/t/t_order_blkandnblk_bad.pl @@ -0,0 +1,19 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(vlt => 1); + +lint( + fails => 1, + expect_filename => $Self->{golden_filename}, + ); + +ok(1); +1; diff --git a/test_regress/t/t_order_blkandnblk_bad.v b/test_regress/t/t_order_blkandnblk_bad.v new file mode 100644 index 000000000..2b4dbcd4d --- /dev/null +++ b/test_regress/t/t_order_blkandnblk_bad.v @@ -0,0 +1,26 @@ +// DESCRIPTION: Verilator: Test of select from constant +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2020 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +module t (/*AUTOARG*/ + // Outputs + o, + // Inputs + clk, i + ); + input clk; + input [3:0] i; + output [3:0] o; + + logic [1:0][3:0] array; + + always_comb array[0] = i; + + always @ (posedge clk) + array[1] <= array[0]; + + assign o = array[1]; + +endmodule diff --git a/test_regress/t/t_order_blkloopinit_bad.out b/test_regress/t/t_order_blkloopinit_bad.out new file mode 100644 index 000000000..ec6d432f5 --- /dev/null +++ b/test_regress/t/t_order_blkloopinit_bad.out @@ -0,0 +1,4 @@ +%Error-BLKLOOPINIT: t/t_order_blkloopinit_bad.v:21:19: Unsupported: Delayed assignment to array inside for loops (non-delayed is ok - see docs) + 21 | array[i] <= 0; + | ^~ +%Error: Exiting due to diff --git a/test_regress/t/t_order_blkloopinit_bad.pl b/test_regress/t/t_order_blkloopinit_bad.pl new file mode 100755 index 000000000..a5846c699 --- /dev/null +++ b/test_regress/t/t_order_blkloopinit_bad.pl @@ -0,0 +1,19 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(vlt => 1); + +lint( + fails => 1, + expect_filename => $Self->{golden_filename}, + ); + +ok(1); +1; diff --git a/test_regress/t/t_order_blkloopinit_bad.v b/test_regress/t/t_order_blkloopinit_bad.v new file mode 100644 index 000000000..d2cef2b31 --- /dev/null +++ b/test_regress/t/t_order_blkloopinit_bad.v @@ -0,0 +1,26 @@ +// DESCRIPTION: Verilator: Test of select from constant +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2020 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +module t (/*AUTOARG*/ + // Outputs + o, + // Inputs + clk + ); + input clk; + output int o; + + localparam SIZE = 65536; + int array [SIZE]; + + always @ (posedge clk) begin + for (int i=0; i 0 && sig``_in != sig``_out) begin \ end module t #(parameter GATED_CLK = 0) (/*AUTOARG*/ - // Inputs - clk - ); + // Inputs + clk + ); input clk; localparam last_cyc = `ifdef TEST_BENCHMARK - `TEST_BENCHMARK; + `TEST_BENCHMARK; `else 10; `endif - genvar x; + genvar x; generate for (x = 0; x < 2; x = x + 1) begin: gen_loop integer cyc = 0; @@ -41,6 +41,8 @@ module t #(parameter GATED_CLK = 0) (/*AUTOARG*/ logic [31:0] accum_bypass_out_expect; logic s1_in; logic s1_out; + logic s1up_in[2]; + logic s1up_out[2]; logic [1:0] s2_in; logic [1:0] s2_out; logic [7:0] s8_in; @@ -55,6 +57,14 @@ module t #(parameter GATED_CLK = 0) (/*AUTOARG*/ logic [128:0] s129_out; logic [3:0] [31:0] s4x32_in; logic [3:0] [31:0] s4x32_out; + /*verilator lint_off LITENDIAN*/ + logic [0:15] s6x16up_in[0:1][2:0]; + logic [0:15] s6x16up_out[0:1][2:0]; + /*verilator lint_on LITENDIAN*/ + logic [15:0] s8x16up_in[1:0][0:3]; + logic [15:0] s8x16up_out[1:0][0:3]; + logic [15:0] s8x16up_3d_in[1:0][0:1][0:1]; + logic [15:0] s8x16up_3d_out[1:0][0:1][0:1]; wire clk_en = crc[0]; @@ -66,6 +76,8 @@ module t #(parameter GATED_CLK = 0) (/*AUTOARG*/ .accum_bypass_out, .s1_in, .s1_out, + .s1up_in, + .s1up_out, .s2_in, .s2_out, .s8_in, @@ -80,6 +92,12 @@ module t #(parameter GATED_CLK = 0) (/*AUTOARG*/ .s129_out, .s4x32_in, .s4x32_out, + .s6x16up_in, + .s6x16up_out, + .s8x16up_in, + .s8x16up_out, + .s8x16up_3d_in, + .s8x16up_3d_out, .clk_en, .clk); @@ -99,6 +117,15 @@ module t #(parameter GATED_CLK = 0) (/*AUTOARG*/ `DRIVE(s65) `DRIVE(s129) `DRIVE(s4x32) + {s1up_in[1], s1up_in[0]} <= {^crc, ~(^crc)}; + {s6x16up_in[0][0], s6x16up_in[0][1], s6x16up_in[0][2]} <= crc[47:0]; + {s6x16up_in[1][0], s6x16up_in[1][1], s6x16up_in[1][2]} <= ~crc[63:16]; + {s8x16up_in[0][0], s8x16up_in[0][1], s8x16up_in[0][2], s8x16up_in[0][3]} <= crc; + {s8x16up_in[1][0], s8x16up_in[1][1], s8x16up_in[1][2], s8x16up_in[1][3]} <= ~crc; + {s8x16up_3d_in[0][0][0], s8x16up_3d_in[0][0][1]} <= ~crc[31:0]; + {s8x16up_3d_in[0][1][0], s8x16up_3d_in[0][1][1]} <= ~crc[63:32]; + {s8x16up_3d_in[1][0][0], s8x16up_3d_in[1][0][1]} <= crc[31:0]; + {s8x16up_3d_in[1][1][0], s8x16up_3d_in[1][1][1]} <= crc[63:32]; if (cyc == 0) begin accum_in <= x*100; accum_bypass <= '0; @@ -128,7 +155,9 @@ module t #(parameter GATED_CLK = 0) (/*AUTOARG*/ if (GATED_CLK != 0) begin: yes_gated_clock logic clk_en_latch /*verilator clock_enable*/; /* verilator lint_off COMBDLY */ + /* verilator lint_off LATCH */ always_comb if (clk == '0) clk_en_latch <= clk_en; + /* verilator lint_on LATCH */ /* verilator lint_on COMBDLY */ assign possibly_gated_clk = clk & clk_en_latch; end else begin: no_gated_clock @@ -148,6 +177,7 @@ module t #(parameter GATED_CLK = 0) (/*AUTOARG*/ #1; /* verilator lint_on STMTDLY */ `CHECK(s1) + `CHECK(s1up) `CHECK(s2) `CHECK(s8) `CHECK(s33) @@ -155,6 +185,9 @@ module t #(parameter GATED_CLK = 0) (/*AUTOARG*/ `CHECK(s65) `CHECK(s129) `CHECK(s4x32) + `CHECK(s6x16up) + `CHECK(s8x16up) + `CHECK(s8x16up_3d) end assign accum_bypass_out_expect = accum_bypass ? accum_in : diff --git a/test_regress/t/t_prot_lib_secret.v b/test_regress/t/t_prot_lib_secret.v index e959c8e42..c01d0f48e 100644 --- a/test_regress/t/t_prot_lib_secret.v +++ b/test_regress/t/t_prot_lib_secret.v @@ -5,31 +5,41 @@ module secret #(parameter GATED_CLK = 0) ( - input [31:0] accum_in, - output wire [31:0] accum_out, - input accum_bypass, - output [31:0] accum_bypass_out, - input s1_in, - output logic s1_out, - input [1:0] s2_in, - output logic [1:0] s2_out, - input [7:0] s8_in, - output logic [7:0] s8_out, - input [32:0] s33_in, + input [31:0] accum_in, + output wire [31:0] accum_out, + input accum_bypass, + output [31:0] accum_bypass_out, + input s1_in, + output logic s1_out, + input s1up_in[2], + output logic s1up_out[2], + input [1:0] s2_in, + output logic [1:0] s2_out, + input [7:0] s8_in, + output logic [7:0] s8_out, + input [32:0] s33_in, output logic [32:0] s33_out, - input [63:0] s64_in, + input [63:0] s64_in, output logic [63:0] s64_out, - input [64:0] s65_in, + input [64:0] s65_in, output logic [64:0] s65_out, - input [128:0] s129_in, + input [128:0] s129_in, output logic [128:0] s129_out, - input [3:0] [31:0] s4x32_in, + input [3:0] [31:0] s4x32_in, output logic [3:0] [31:0] s4x32_out, - input clk_en, - input clk /*verilator clocker*/); + /*verilator lint_off LITENDIAN*/ + input [0:15] s6x16up_in[0:1][2:0], + output logic [0:15] s6x16up_out[0:1][2:0], + /*verilator lint_on LITENDIAN*/ + input [15:0] s8x16up_in[1:0][0:3], + output logic [15:0] s8x16up_out[1:0][0:3], + input [15:0] s8x16up_3d_in[1:0][0:1][0:1], + output logic [15:0] s8x16up_3d_out[1:0][0:1][0:1], + input clk_en, + input clk /*verilator clocker*/); - logic [31:0] secret_accum_q = 0; - logic [31:0] secret_value = 7; + logic [31:0] secret_accum_q = 0; + logic [31:0] secret_value = 7; initial $display("created %m"); @@ -38,7 +48,9 @@ module secret #(parameter GATED_CLK = 0) if (GATED_CLK != 0) begin: yes_gated_clock logic clk_en_latch /*verilator clock_enable*/; /* verilator lint_off COMBDLY */ + /* verilator lint_off LATCH */ always_comb if (clk == '0) clk_en_latch <= clk_en; + /* verilator lint_on LATCH */ /* verilator lint_on COMBDLY */ assign the_clk = clk & clk_en_latch; end else begin: no_gated_clock @@ -53,6 +65,7 @@ module secret #(parameter GATED_CLK = 0) // Test combinatorial paths of different sizes always @(*) begin s1_out = s1_in; + s1up_out = s1up_in; s2_out = s2_in; s8_out = s8_in; s64_out = s64_in; @@ -61,6 +74,19 @@ module secret #(parameter GATED_CLK = 0) s4x32_out = s4x32_in; end + for (genvar i = 0; i < 3; ++i) begin + assign s6x16up_out[0][i] = s6x16up_in[0][i]; + assign s6x16up_out[1][i] = s6x16up_in[1][i]; + end + for (genvar i = 0; i < 4; ++i) begin + assign s8x16up_out[0][i] = s8x16up_in[0][i]; + assign s8x16up_out[1][i] = s8x16up_in[1][i]; + end + for (genvar i = 0; i < 8; ++i) begin + assign s8x16up_3d_out[i[2]][i[1]][i[0]] = s8x16up_3d_in[i[2]][i[1]][i[0]]; + end + + sub sub (.sub_in(s33_in), .sub_out(s33_out)); // Test sequential path diff --git a/test_regress/t/t_prot_lib_unpacked_bad.out b/test_regress/t/t_prot_lib_unpacked_bad.out deleted file mode 100644 index f48917027..000000000 --- a/test_regress/t/t_prot_lib_unpacked_bad.out +++ /dev/null @@ -1,7 +0,0 @@ -%Error-UNSUPPORTED: t/t_prot_lib_unpacked_bad.v:7:28: Unsupported: unpacked arrays with protect-lib on 'unpacked_in' - 7 | input unpacked_in [7:0], - | ^~~~~~~~~~~ -%Error-UNSUPPORTED: t/t_prot_lib_unpacked_bad.v:8:28: Unsupported: unpacked arrays with protect-lib on 'unpacked_out' - 8 | output unpacked_out [7:0]); - | ^~~~~~~~~~~~ -%Error: Exiting due to diff --git a/test_regress/t/t_prot_lib_unpacked_bad.v b/test_regress/t/t_prot_lib_unpacked_bad.v deleted file mode 100644 index 91cfcdffb..000000000 --- a/test_regress/t/t_prot_lib_unpacked_bad.v +++ /dev/null @@ -1,17 +0,0 @@ -// DESCRIPTION: Verilator: Verilog Test module -// This file ONLY is placed into the Public Domain, for any use, -// without warranty, 2019 by Todd Strader. -// SPDX-License-Identifier: CC0-1.0 - -module secret_impl ( - input unpacked_in [7:0], - output unpacked_out [7:0]); - - genvar i; - generate - for (i = 0; i < 8; i = i + 1) begin - assign unpacked_out[i] = unpacked_in[i]; - end - endgenerate - -endmodule diff --git a/test_regress/t/t_protect_ids_debug.pl b/test_regress/t/t_protect_ids_debug.pl new file mode 100755 index 000000000..d1da5019c --- /dev/null +++ b/test_regress/t/t_protect_ids_debug.pl @@ -0,0 +1,26 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(vlt => 1); + +top_filename("t/t_protect_ids.v"); + +compile( + verilator_flags2 => ["--protect-ids", + "--protect-key SECRET_KEY", + "--trace", + "--debug-protect", + "--coverage", + "-Wno-INSECURE",], + verilator_make_gmake => 0, + ); + +ok(1); +1; diff --git a/test_regress/t/t_queue_unpacked.pl b/test_regress/t/t_queue_unpacked.pl new file mode 100755 index 000000000..9a15dd2cc --- /dev/null +++ b/test_regress/t/t_queue_unpacked.pl @@ -0,0 +1,21 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2019 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(simulator => 1); + +compile( + ); + +execute( + check_finished => 1, + ); + +ok(1); +1; diff --git a/test_regress/t/t_queue_unpacked.v b/test_regress/t/t_queue_unpacked.v new file mode 100644 index 000000000..566de16b6 --- /dev/null +++ b/test_regress/t/t_queue_unpacked.v @@ -0,0 +1,66 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2020 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +`define stop $stop +`define checks(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='%s' exp='%s'\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0); + +module t (/*AUTOARG*/); + + typedef string sarray_t[2]; + typedef sarray_t q_sarray_t[$]; + + typedef bit [95:0] wide_t; + typedef wide_t warray_t[2]; + typedef warray_t q_warray_t[$]; + + initial begin + begin + q_sarray_t iq; + sarray_t a; + sarray_t b0; + sarray_t b1; + + a[0] = "hello"; + a[1] = "world"; + iq.push_back(a); + a[0] = "bye"; + a[1] = "world"; + iq.push_back(a); + + b0 = iq[0]; + b1 = iq[1]; + `checks(b0[0], "hello"); + `checks(b0[1], "world"); + `checks(b1[0], "bye"); + `checks(b1[1], "world"); + end + +`ifndef verilator + // Need wide conversion into VlUnpacked types + + // If we convert all arrays to VlUnpacked it works, so we need to track + // data types and insert conversions perhaps in V3Cast, but we currently + // don't know the output datatypes, so work needed. + begin + q_warray_t iq; + warray_t a; + warray_t b0; + + a[0] = "abcdefg_ijkl"; + a[1] = "012123123128"; + iq.push_back(a); + + b0 = iq[0]; + `checks(b0[0], "abcdefg_ijkl"); + `checks(b0[1], "012123123128"); + end +`endif + + $write("*-* All Finished *-*\n"); + $finish; + end + +endmodule diff --git a/test_regress/t/t_randc_ignore_unsup.pl b/test_regress/t/t_randc_ignore_unsup.pl new file mode 100755 index 000000000..a161852b1 --- /dev/null +++ b/test_regress/t/t_randc_ignore_unsup.pl @@ -0,0 +1,22 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2020 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(vlt => 1); + +compile( + verilator_flags2 => ['-Wno-RANDC'], + ); + +execute( + check_finished => 1, + ); + +ok(1); +1; diff --git a/test_regress/t/t_randc_ignore_unsup.v b/test_regress/t/t_randc_ignore_unsup.v new file mode 100644 index 000000000..a2087e6b0 --- /dev/null +++ b/test_regress/t/t_randc_ignore_unsup.v @@ -0,0 +1,38 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2019 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +class Cls; + randc int i; + + function new; + i = 0; + endfunction + +endclass + +module t (/*AUTOARG*/); + bit ok = 0; + + Cls obj; + + initial begin + int rand_result; + int prev_i; + for (int i = 0; i < 10; i++) begin + obj = new; + rand_result = obj.randomize(); + if (i > 0 && obj.i != prev_i) begin + ok = 1; + end + prev_i = obj.i; + end + if (ok) begin + $write("*-* All Finished *-*\n"); + $finish; + end + else $stop; + end +endmodule diff --git a/test_regress/t/t_randc_unsup.out b/test_regress/t/t_randc_unsup.out new file mode 100644 index 000000000..4ca619d14 --- /dev/null +++ b/test_regress/t/t_randc_unsup.out @@ -0,0 +1,5 @@ +%Warning-RANDC: t/t_randc_unsup.v:8:14: Unsupported: Converting 'randc' to 'rand' + 8 | randc int i; + | ^ + ... Use "/* verilator lint_off RANDC */" and lint_on around source to disable this message. +%Error: Exiting due to diff --git a/test_regress/t/t_randc_unsup.pl b/test_regress/t/t_randc_unsup.pl new file mode 100755 index 000000000..009248fc5 --- /dev/null +++ b/test_regress/t/t_randc_unsup.pl @@ -0,0 +1,19 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2020 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(vlt => 1); + +lint( + fails => 1, + expect_filename => $Self->{golden_filename}, + ); + +ok(1); +1; diff --git a/test_regress/t/t_randc_unsup.v b/test_regress/t/t_randc_unsup.v new file mode 100644 index 000000000..1a966261a --- /dev/null +++ b/test_regress/t/t_randc_unsup.v @@ -0,0 +1,12 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2019 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +class Cls; + randc int i; +endclass + +module t (/*AUTOARG*/); +endmodule diff --git a/test_regress/t/t_randomize_method.pl b/test_regress/t/t_randomize_method.pl new file mode 100644 index 000000000..aabcde63e --- /dev/null +++ b/test_regress/t/t_randomize_method.pl @@ -0,0 +1,21 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2020 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(simulator => 1); + +compile( + ); + +execute( + check_finished => 1, + ); + +ok(1); +1; diff --git a/test_regress/t/t_randomize_method.v b/test_regress/t/t_randomize_method.v new file mode 100644 index 000000000..126f0785e --- /dev/null +++ b/test_regress/t/t_randomize_method.v @@ -0,0 +1,136 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2020 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +typedef enum bit[15:0] { + ONE = 3, + TWO = 5, + THREE = 8, + FOUR = 13 +} Enum; + +typedef struct packed { + int a; + bit b; + Enum c; +} StructInner; + +typedef struct packed { + bit x; + StructInner s; + Enum y; + longint z; +} StructOuter; + +class BaseCls; +endclass + +class Inner; + rand logic[7:0] a; + rand logic[15:0] b; + rand logic[3:0] c; + rand logic[11:0] d; + int e; + + function new; + a = 0; + b = 0; + c = 0; + d = 0; + e = 0; + endfunction + +endclass + +class DerivedCls extends BaseCls; + rand Inner i; + rand int j; + int k; + rand Enum l; + + function new; + i = new; + j = 0; + k = 0; + l = ONE; + endfunction + +endclass + +class OtherCls; + logic[63:0] v; + rand logic[63:0] w; + rand logic[47:0] x; + rand logic[31:0] y; + rand logic[23:0] z; + rand StructOuter str; + + function new; + v = 0; + w = 0; + x = 0; + y = 0; + z = 0; + str = '{x: 1'b0, y: ONE, z: 64'd0, s: '{a: 32'd0, b: 1'b0, c: ONE}}; + endfunction + +endclass + +module t (/*AUTOARG*/); + bit ok = 0; + longint checksum; + + task checksum_next(longint x); + checksum = x ^ {checksum[62:0],checksum[63]^checksum[2]^checksum[0]}; + endtask; + + DerivedCls derived; + OtherCls other; + BaseCls base; + + initial begin + int rand_result; + longint prev_checksum; + for (int i = 0; i < 10; i++) begin + derived = new; + other = new; + base = derived; + rand_result = base.randomize(); + rand_result = other.randomize(); + if (!(derived.l inside {ONE, TWO, THREE, FOUR})) $stop; + if (!(other.str.s.c inside {ONE, TWO, THREE, FOUR})) $stop; + if (!(other.str.y inside {ONE, TWO, THREE, FOUR})) $stop; + if (derived.i.e != 0) $stop; + if (derived.k != 0) $stop; + if (other.v != 0) $stop; + checksum = 0; + checksum_next(longint'(derived.i.a)); + checksum_next(longint'(derived.i.b)); + checksum_next(longint'(derived.i.c)); + checksum_next(longint'(derived.j)); + checksum_next(longint'(derived.l)); + checksum_next(longint'(other.w)); + checksum_next(longint'(other.x)); + checksum_next(longint'(other.y)); + checksum_next(longint'(other.z)); + checksum_next(longint'(other.str.x)); + checksum_next(longint'(other.str.y)); + checksum_next(longint'(other.str.z)); + checksum_next(longint'(other.str.s.a)); + checksum_next(longint'(other.str.s.b)); + checksum_next(longint'(other.str.s.c)); + $write("checksum: %d\n", checksum); + if (i > 0 && checksum != prev_checksum) begin + ok = 1; + end + prev_checksum = checksum; + end + if (ok) begin + $write("*-* All Finished *-*\n"); + $finish; + end + else $stop; + end +endmodule diff --git a/test_regress/t/t_randomize_method_bad.out b/test_regress/t/t_randomize_method_bad.out new file mode 100644 index 000000000..80f06eb60 --- /dev/null +++ b/test_regress/t/t_randomize_method_bad.out @@ -0,0 +1,7 @@ +%Error: t/t_randomize_method_bad.v:8:17: 'randomize' is a predefined class method; redefinition not allowed (IEEE 1800-2017 18.6.3) + 8 | function int randomize; + | ^~~~~~~~~ +%Error: t/t_randomize_method_bad.v:14:18: 'randomize' is a predefined class method; redefinition not allowed (IEEE 1800-2017 18.6.3) + 14 | function void randomize(int x); + | ^~~~~~~~~ +%Error: Exiting due to diff --git a/test_regress/t/t_randomize_method_bad.pl b/test_regress/t/t_randomize_method_bad.pl new file mode 100644 index 000000000..6ad7137de --- /dev/null +++ b/test_regress/t/t_randomize_method_bad.pl @@ -0,0 +1,19 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2020 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(simulator => 1); + +compile( + fails => $Self->{vlt_all}, + expect_filename => $Self->{golden_filename}, + ); + +ok(1); +1; diff --git a/test_regress/t/t_randomize_method_bad.v b/test_regress/t/t_randomize_method_bad.v new file mode 100644 index 000000000..72da52529 --- /dev/null +++ b/test_regress/t/t_randomize_method_bad.v @@ -0,0 +1,19 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2020 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +class Cls1; + function int randomize; + return 1; + endfunction +endclass + +class Cls2; + function void randomize(int x); + endfunction +endclass + +module t (/*AUTOARG*/); +endmodule diff --git a/test_regress/t/t_randomize_method_types_unsup.out b/test_regress/t/t_randomize_method_types_unsup.out new file mode 100644 index 000000000..a84c9ae0e --- /dev/null +++ b/test_regress/t/t_randomize_method_types_unsup.out @@ -0,0 +1,17 @@ +%Error-UNSUPPORTED: t/t_randomize_method_types_unsup.v:12:13: Unsupported: random member variables with type 'int[string]' + : ... In instance t + 12 | rand int assocarr[string]; + | ^~~~~~~~ +%Error-UNSUPPORTED: t/t_randomize_method_types_unsup.v:13:13: Unsupported: random member variables with type 'int[]' + : ... In instance t + 13 | rand int dynarr[]; + | ^~~~~~ +%Error-UNSUPPORTED: t/t_randomize_method_types_unsup.v:14:13: Unsupported: random member variables with type 'int$[0:4]' + : ... In instance t + 14 | rand int unpackarr[5]; + | ^~~~~~~~~ +%Error-UNSUPPORTED: t/t_randomize_method_types_unsup.v:15:15: Unsupported: random member variables with type '__024unit::Union' + : ... In instance t + 15 | rand Union uni; + | ^~~ +%Error: Exiting due to diff --git a/test_regress/t/t_randomize_method_types_unsup.pl b/test_regress/t/t_randomize_method_types_unsup.pl new file mode 100644 index 000000000..6ad7137de --- /dev/null +++ b/test_regress/t/t_randomize_method_types_unsup.pl @@ -0,0 +1,19 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2020 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(simulator => 1); + +compile( + fails => $Self->{vlt_all}, + expect_filename => $Self->{golden_filename}, + ); + +ok(1); +1; diff --git a/test_regress/t/t_randomize_method_types_unsup.v b/test_regress/t/t_randomize_method_types_unsup.v new file mode 100644 index 000000000..1595a6c07 --- /dev/null +++ b/test_regress/t/t_randomize_method_types_unsup.v @@ -0,0 +1,25 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2020 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +typedef union packed { + int x; +} Union; + +class Cls; + rand int assocarr[string]; + rand int dynarr[]; + rand int unpackarr[5]; + rand Union uni; +endclass + +module t (/*AUTOARG*/); + Cls obj; + + initial begin + obj = new; + obj.randomize(); + end +endmodule diff --git a/test_regress/t/t_randomize_method_unsup.out b/test_regress/t/t_randomize_method_unsup.out new file mode 100644 index 000000000..5012993da --- /dev/null +++ b/test_regress/t/t_randomize_method_unsup.out @@ -0,0 +1,7 @@ +%Error-UNSUPPORTED: t/t_randomize_method_unsup.v:8:18: Unsupported: 'pre_randomize' + 8 | function void pre_randomize; + | ^~~~~~~~~~~~~ +%Error-UNSUPPORTED: t/t_randomize_method_unsup.v:11:18: Unsupported: 'post_randomize' + 11 | function void post_randomize; + | ^~~~~~~~~~~~~~ +%Error: Exiting due to diff --git a/test_regress/t/t_randomize_method_unsup.pl b/test_regress/t/t_randomize_method_unsup.pl new file mode 100644 index 000000000..6ad7137de --- /dev/null +++ b/test_regress/t/t_randomize_method_unsup.pl @@ -0,0 +1,19 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2020 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(simulator => 1); + +compile( + fails => $Self->{vlt_all}, + expect_filename => $Self->{golden_filename}, + ); + +ok(1); +1; diff --git a/test_regress/t/t_randomize_method_unsup.v b/test_regress/t/t_randomize_method_unsup.v new file mode 100644 index 000000000..898bf9fff --- /dev/null +++ b/test_regress/t/t_randomize_method_unsup.v @@ -0,0 +1,16 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2020 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +class Cls; + function void pre_randomize; + endfunction; + + function void post_randomize; + endfunction; +endclass + +module t (/*AUTOARG*/); +endmodule diff --git a/test_regress/t/t_runflag_uninit_bad.cpp b/test_regress/t/t_runflag_uninit_bad.cpp new file mode 100644 index 000000000..2a389c6e1 --- /dev/null +++ b/test_regress/t/t_runflag_uninit_bad.cpp @@ -0,0 +1,28 @@ +// -*- mode: C++; c-file-style: "cc-mode" -*- +// +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2010 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +#include + +#include +#include +#include VM_PREFIX_INCLUDE + +//====================================================================== + +unsigned int main_time = 0; + +double sc_time_stamp() { return main_time; } + +int main(int argc, char* argv[]) { + auto topp = new VM_PREFIX; + + // We aren't calling Verilated::commandArgs(argc, argv) + topp->eval(); + + exit(0); +} diff --git a/test_regress/t/t_runflag_uninit_bad.out b/test_regress/t/t_runflag_uninit_bad.out new file mode 100644 index 000000000..f11c79dba --- /dev/null +++ b/test_regress/t/t_runflag_uninit_bad.out @@ -0,0 +1,2 @@ +%Error: unknown:0: %Error: Verilog called $test$plusargs or $value$plusargs without testbench C first calling Verilated::commandArgs(argc,argv). +Aborting... diff --git a/test_regress/t/t_prot_lib_unpacked_bad.pl b/test_regress/t/t_runflag_uninit_bad.pl similarity index 61% rename from test_regress/t/t_prot_lib_unpacked_bad.pl rename to test_regress/t/t_runflag_uninit_bad.pl index 955f6793e..dada1b80d 100755 --- a/test_regress/t/t_prot_lib_unpacked_bad.pl +++ b/test_regress/t/t_runflag_uninit_bad.pl @@ -2,7 +2,7 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } # DESCRIPTION: Verilator: Verilog Test driver/expect definition # -# Copyright 2019 by Todd Strader. This program is free software; you +# Copyright 2003 by Wilson Snyder. This program is free software; you # can redistribute it and/or modify it under the terms of either the GNU # Lesser General Public License Version 3 or the Perl Artistic License # Version 2.0. @@ -10,19 +10,15 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di scenarios(vlt => 1); -compile ( - verilator_flags2 => ["--protect-lib", - "secret"], - verilator_make_gcc => 0, +compile( + v_flags2 => ["--savable --exe $Self->{t_dir}/t_runflag_uninit_bad.cpp"], + make_main => 0, + ); + +execute( fails => 1, expect_filename => $Self->{golden_filename}, ); -#run(cmd=>["make", -# "-C", -# "$Self->{obj_dir}", -# "-f", -# "V$Self->{name}.mk"]); - ok(1); 1; diff --git a/test_regress/t/t_runflag_uninit_bad.v b/test_regress/t/t_runflag_uninit_bad.v new file mode 100644 index 000000000..0f4e48ff9 --- /dev/null +++ b/test_regress/t/t_runflag_uninit_bad.v @@ -0,0 +1,11 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// Copyright 2020 by Wilson Snyder. This program is free software; you can +// redistribute it and/or modify it under the terms of either the GNU +// Lesser General Public License Version 3 or the Perl Artistic License +// Version 2.0. +// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +module t; + initial $display($test$plusargs("MYFLAG")); +endmodule diff --git a/test_regress/t/t_savable_open_bad2.cpp b/test_regress/t/t_savable_open_bad2.cpp new file mode 100644 index 000000000..0e4c383cc --- /dev/null +++ b/test_regress/t/t_savable_open_bad2.cpp @@ -0,0 +1,48 @@ +// -*- mode: C++; c-file-style: "cc-mode" -*- +// +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2010 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +#include + +#include +#include +#include VM_PREFIX_INCLUDE + +//====================================================================== + +#define CHECK_RESULT_HEX(got, exp) \ + do { \ + if ((got) != (exp)) { \ + std::cout << std::dec << "%Error: " << __FILE__ << ":" << __LINE__ << std::hex \ + << ": GOT=" << (got) << " EXP=" << (exp) << std::endl; \ + exit(10); \ + } \ + } while (0) + +//====================================================================== + +unsigned int main_time = 0; + +double sc_time_stamp() { return main_time; } + +int main(int argc, char* argv[]) { + // No need to make a model: topp = new VM_PREFIX; + + Verilated::debug(0); + { + VerilatedSave os; + os.open("/No_such_file_as_this"); + CHECK_RESULT_HEX(os.isOpen(), false); + } + { + VerilatedRestore os; + os.open("/No_such_file_as_this"); + CHECK_RESULT_HEX(os.isOpen(), false); + } + + exit(0); +} diff --git a/test_regress/t/t_savable_open_bad2.out b/test_regress/t/t_savable_open_bad2.out new file mode 100644 index 000000000..dc2091af3 --- /dev/null +++ b/test_regress/t/t_savable_open_bad2.out @@ -0,0 +1,2 @@ +%Error: unknown:0: Testbench C called 'dpix_task' but scope wasn't set, perhaps due to dpi import call without 'context', or missing svSetScope. See IEEE 1800-2017 35.5.3. +Aborting... diff --git a/test_regress/t/t_savable_open_bad2.pl b/test_regress/t/t_savable_open_bad2.pl new file mode 100755 index 000000000..f7e08a422 --- /dev/null +++ b/test_regress/t/t_savable_open_bad2.pl @@ -0,0 +1,22 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(vlt => 1); + +compile( + v_flags2 => ["--savable --exe $Self->{t_dir}/t_savable_open_bad2.cpp"], + make_main => 0, + ); + +execute( + ); + +ok(1); +1; diff --git a/test_regress/t/t_savable_open_bad2.v b/test_regress/t/t_savable_open_bad2.v new file mode 100644 index 000000000..c473152e5 --- /dev/null +++ b/test_regress/t/t_savable_open_bad2.v @@ -0,0 +1,10 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// Copyright 2020 by Wilson Snyder. This program is free software; you can +// redistribute it and/or modify it under the terms of either the GNU +// Lesser General Public License Version 3 or the Perl Artistic License +// Version 2.0. +// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +module t; +endmodule diff --git a/test_regress/t/t_scope_map.cpp b/test_regress/t/t_scope_map.cpp index 020bee9d4..b27cb4c97 100644 --- a/test_regress/t/t_scope_map.cpp +++ b/test_regress/t/t_scope_map.cpp @@ -161,6 +161,7 @@ int main(int argc, char** argv, char** env) { tfp->close(); top->final(); + VL_DO_DANGLING(delete tfp, tfp); VL_DO_DANGLING(delete top, top); VL_PRINTF("*-* All Finished *-*\n"); diff --git a/test_regress/t/t_select_bad_msb.out b/test_regress/t/t_select_bad_msb.out index f31c7e096..69147264b 100644 --- a/test_regress/t/t_select_bad_msb.out +++ b/test_regress/t/t_select_bad_msb.out @@ -1,4 +1,4 @@ -%Warning-LITENDIAN: t/t_select_bad_msb.v:12:8: Little bit endian vector: MSB < LSB of bit range: 0:22 +%Warning-LITENDIAN: t/t_select_bad_msb.v:12:8: Little bit endian vector: left < right of bit range: [0:22] : ... In instance t 12 | reg [0:22] backwd; | ^ diff --git a/test_regress/t/t_sys_fstrobe.pl b/test_regress/t/t_sys_fstrobe.pl index 6bbedacab..55224d3d6 100755 --- a/test_regress/t/t_sys_fstrobe.pl +++ b/test_regress/t/t_sys_fstrobe.pl @@ -8,7 +8,7 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di # Version 2.0. # SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 -scenarios(simulator => 1); +scenarios(vlt => 1); # Not vltmt due to possible race compile( ); diff --git a/test_regress/t/t_sys_sformat.v b/test_regress/t/t_sys_sformat.v index d4da7ac54..bce43cb5e 100644 --- a/test_regress/t/t_sys_sformat.v +++ b/test_regress/t/t_sys_sformat.v @@ -65,9 +65,12 @@ module t; `ifdef TEST_VERBOSE $display("chku %s", str3); `endif if (str3 !== "u=dcba") $stop; - str3 = $sformatf("v=%v", {"a","b","c","d"}); // Value selected so is printable + str3 = $sformatf("v=%v", 4'b01xz); // Value selected so is printable `ifdef TEST_VERBOSE $display("chkv %s", str3); `endif + str3 = $sformatf("z=%z", {"a","b","c","d"}); // Value selected so is printable +`ifdef TEST_VERBOSE $display("chkz %s", str3); `endif + $sformat(ochar,"%s","c"); if (ochar != "c") $stop; diff --git a/test_regress/t/t_threads_crazy.pl b/test_regress/t/t_threads_crazy.pl new file mode 100755 index 000000000..1d54c9e0a --- /dev/null +++ b/test_regress/t/t_threads_crazy.pl @@ -0,0 +1,24 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003-2009 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(vltmt => 1); + +compile( + verilator_flags2 => ['--cc --threads 1024'], + ); + +execute( + check_finished => 1, + ); + +file_grep($Self->{run_log_filename}, qr/System has .* CPUs but.*--threads 1024/); + +ok(1); +1; diff --git a/test_regress/t/t_threads_crazy.v b/test_regress/t/t_threads_crazy.v new file mode 100644 index 000000000..fad058267 --- /dev/null +++ b/test_regress/t/t_threads_crazy.v @@ -0,0 +1,25 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2017 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +module t (/*AUTOARG*/ + // Inputs + clk + ); + + input clk; + + integer cyc; + + always @ (posedge clk) begin + cyc <= cyc + 1; + if (cyc!=0) begin + if (cyc==10) begin + $write("*-* All Finished *-*\n"); + $finish; + end + end + end +endmodule diff --git a/test_regress/t/t_time_vpi_c.cpp b/test_regress/t/t_time_vpi_c.cpp index da3eb7f98..901de71cd 100644 --- a/test_regress/t/t_time_vpi_c.cpp +++ b/test_regress/t/t_time_vpi_c.cpp @@ -12,6 +12,7 @@ #include #include "svdpi.h" #include "vpi_user.h" +#include "TestVpi.h" //====================================================================== @@ -53,7 +54,7 @@ void show(vpiHandle obj) { void dpii_check() { show(0); - vpiHandle mod = vpi_handle_by_name((PLI_BYTE8*)"top.t", NULL); + TestVpiHandle mod = vpi_handle_by_name((PLI_BYTE8*)"top.t", NULL); if (!mod) { vpi_printf(const_cast("-- Cannot vpi_find module\n")); } else { diff --git a/test_regress/t/t_trace_cat.cpp b/test_regress/t/t_trace_cat.cpp index c0374121d..8f851daf7 100644 --- a/test_regress/t/t_trace_cat.cpp +++ b/test_regress/t/t_trace_cat.cpp @@ -6,6 +6,7 @@ // any use, without warranty, 2008 by Wilson Snyder. // SPDX-License-Identifier: CC0-1.0 +#include #include #include @@ -21,13 +22,13 @@ const char* trace_name() { } int main(int argc, char** argv, char** env) { - VM_PREFIX* top = new VM_PREFIX("top"); + std::unique_ptr top{new VM_PREFIX("top")}; Verilated::debug(0); Verilated::traceEverOn(true); - VerilatedVcdC* tfp = new VerilatedVcdC; - top->trace(tfp, 99); + std::unique_ptr tfp{new VerilatedVcdC}; + top->trace(tfp.get(), 99); tfp->open(trace_name()); @@ -45,9 +46,8 @@ int main(int argc, char** argv, char** env) { tfp->open(trace_name()); #elif defined(T_TRACE_CAT_RENEW) tfp->close(); - delete tfp; - tfp = new VerilatedVcdC; - top->trace(tfp, 99); + tfp.reset(new VerilatedVcdC); + top->trace(tfp.get(), 99); tfp->open(trace_name()); #else #error "Unknown test" @@ -58,7 +58,8 @@ int main(int argc, char** argv, char** env) { } tfp->close(); top->final(); - VL_DO_DANGLING(delete top, top); + tfp.reset(); + top.reset(); printf("*-* All Finished *-*\n"); return 0; } diff --git a/test_regress/t/t_trace_public_func.cpp b/test_regress/t/t_trace_public_func.cpp index b77045813..b17540c2d 100644 --- a/test_regress/t/t_trace_public_func.cpp +++ b/test_regress/t/t_trace_public_func.cpp @@ -6,6 +6,7 @@ // any use, without warranty, 2008 by Wilson Snyder. // SPDX-License-Identifier: CC0-1.0 +#include #include #include @@ -26,13 +27,13 @@ double sc_time_stamp() { return (double)main_time; } const unsigned long long dt_2 = 3; int main(int argc, char** argv, char** env) { - VM_PREFIX* top = new VM_PREFIX("top"); + std::unique_ptr top{new VM_PREFIX("top")}; Verilated::debug(0); Verilated::traceEverOn(true); - VerilatedVcdC* tfp = new VerilatedVcdC; - top->trace(tfp, 99); + std::unique_ptr tfp{new VerilatedVcdC}; + top->trace(tfp.get(), 99); tfp->open(VL_STRINGIFY(TEST_OBJ_DIR) "/simx.vcd"); while (main_time <= 20) { @@ -46,7 +47,8 @@ int main(int argc, char** argv, char** env) { } tfp->close(); top->final(); - VL_DO_DANGLING(delete top, top); + tfp.reset(); + top.reset(); printf("*-* All Finished *-*\n"); return 0; } diff --git a/test_regress/t/t_trace_public_sig.cpp b/test_regress/t/t_trace_public_sig.cpp index c77db8584..8cf387097 100644 --- a/test_regress/t/t_trace_public_sig.cpp +++ b/test_regress/t/t_trace_public_sig.cpp @@ -47,6 +47,7 @@ int main(int argc, char** argv, char** env) { tfp->close(); top->final(); VL_DO_DANGLING(delete top, top); + VL_DO_DANGLING(delete tfp, tfp); printf("*-* All Finished *-*\n"); return 0; } diff --git a/test_regress/t/t_trace_sc_empty.pl b/test_regress/t/t_trace_sc_empty.pl new file mode 100755 index 000000000..e8d7ccc84 --- /dev/null +++ b/test_regress/t/t_trace_sc_empty.pl @@ -0,0 +1,18 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2019 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(simulator => 1); + +compile( + verilator_flags2 => ['-sc', '--trace'], + ); + +ok(1); +1; diff --git a/test_regress/t/t_trace_sc_empty.v b/test_regress/t/t_trace_sc_empty.v new file mode 100644 index 000000000..4136b8663 --- /dev/null +++ b/test_regress/t/t_trace_sc_empty.v @@ -0,0 +1,14 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2020 by Wilsn Snyder. +// SPDX-License-Identifier: CC0-1.0 + +module t + ( + output id0 + ); + + assign id0 = 0; + +endmodule diff --git a/test_regress/t/t_urandom.v b/test_regress/t/t_urandom.v index f20529134..fcb6b7b9d 100644 --- a/test_regress/t/t_urandom.v +++ b/test_regress/t/t_urandom.v @@ -34,12 +34,17 @@ module t(/*AUTOARG*/); if (v1 == v2 && v1 == v3) $stop; // Possible, but 2^-64 // Range + v2 = $urandom_range(v1, v1); + if (v1 != v2) $stop; + for (int test = 0; test < 20; ++test) begin v1 = 2; v1 = $urandom_range(0, v1); - if (v1 != 0 && v1 != 1) $stop; + if (v1 != 0 && v1 != 1 && v1 != 2) $stop; v1 = $urandom_range(2, 0); - if (v1 != 0 && v1 != 1) $stop; + if (v1 != 0 && v1 != 1 && v1 !=2) $stop; + v1 = $urandom_range(3); + if (v1 != 0 && v1 != 1 && v1 != 2 && v1 != 3) $stop; end // Seed stability diff --git a/test_regress/t/t_var_bad_sameas.out b/test_regress/t/t_var_bad_sameas.out index e2a345466..046cd6955 100644 --- a/test_regress/t/t_var_bad_sameas.out +++ b/test_regress/t/t_var_bad_sameas.out @@ -1,19 +1,19 @@ -%Error: t/t_var_bad_sameas.v:10:8: Unsupported in C: Cell has the same name as variable: 'varfirst' +%Error: t/t_var_bad_sameas.v:10:8: Unsupported in C: Instance has the same name as variable: 'varfirst' 10 | sub varfirst (); | ^~~~~~~~ t/t_var_bad_sameas.v:9:12: ... Location of original declaration 9 | integer varfirst; | ^~~~~~~~ -%Error: t/t_var_bad_sameas.v:11:9: Unsupported in C: Task has the same name as cell: 'varfirst' +%Error: t/t_var_bad_sameas.v:11:9: Unsupported in C: Task has the same name as instance: 'varfirst' 11 | task varfirst; begin end endtask | ^~~~~~~~ t/t_var_bad_sameas.v:10:8: ... Location of original declaration 10 | sub varfirst (); | ^~~~~~~~ -%Error: t/t_var_bad_sameas.v:14:12: Unsupported in C: Variable has same name as cell: 'cellfirst' +%Error: t/t_var_bad_sameas.v:14:12: Unsupported in C: Variable has same name as instance: 'cellfirst' 14 | integer cellfirst; | ^~~~~~~~~ -%Error: t/t_var_bad_sameas.v:15:9: Unsupported in C: Task has the same name as cell: 'cellfirst' +%Error: t/t_var_bad_sameas.v:15:9: Unsupported in C: Task has the same name as instance: 'cellfirst' 15 | task cellfirst; begin end endtask | ^~~~~~~~~ t/t_var_bad_sameas.v:13:8: ... Location of original declaration @@ -22,7 +22,7 @@ %Error: t/t_var_bad_sameas.v:18:12: Unsupported in C: Variable has same name as task: 'taskfirst' 18 | integer taskfirst; | ^~~~~~~~~ -%Error: t/t_var_bad_sameas.v:19:8: Unsupported in C: Cell has the same name as task: 'taskfirst' +%Error: t/t_var_bad_sameas.v:19:8: Unsupported in C: Instance has the same name as task: 'taskfirst' 19 | sub taskfirst (); | ^~~~~~~~~ t/t_var_bad_sameas.v:17:9: ... Location of original declaration diff --git a/test_regress/t/t_var_dotted_dup_bad.out b/test_regress/t/t_var_dotted_dup_bad.out index 8bdda3bde..2a4eaaa17 100644 --- a/test_regress/t/t_var_dotted_dup_bad.out +++ b/test_regress/t/t_var_dotted_dup_bad.out @@ -1,4 +1,4 @@ -%Error: t/t_var_dotted_dup_bad.v:14:18: Duplicate declaration of cell: 'dccm_bank' +%Error: t/t_var_dotted_dup_bad.v:14:18: Duplicate declaration of instance: 'dccm_bank' 14 | eh2_ram dccm_bank (.*); | ^~~~~~~~~ t/t_var_dotted_dup_bad.v:11:18: ... Location of original declaration diff --git a/test_regress/t/t_vpi_cb_iter.cpp b/test_regress/t/t_vpi_cb_iter.cpp index f9dd322d4..a4a6641cb 100644 --- a/test_regress/t/t_vpi_cb_iter.cpp +++ b/test_regress/t/t_vpi_cb_iter.cpp @@ -26,8 +26,8 @@ bool got_error = false; -vpiHandle vh_value_cb = 0; -vpiHandle vh_rw_cb = 0; +TestVpiHandle vh_value_cb; +TestVpiHandle vh_rw_cb; unsigned int last_value_cb_time = 0; unsigned int last_rw_cb_time = 0; @@ -78,6 +78,7 @@ static void reregister_value_cb() { if (vh_value_cb) { if (verbose) { vpi_printf(const_cast("- Removing cbValueChange callback\n")); } int ret = vpi_remove_cb(vh_value_cb); + vh_value_cb.freed(); CHECK_RESULT(ret, 1); if (verbose) { @@ -93,7 +94,7 @@ static void reregister_value_cb() { cb_data_testcase.cb_rtn = the_value_callback; cb_data_testcase.reason = cbValueChange; - vpiHandle vh1 = VPI_HANDLE("count"); + TestVpiHandle vh1 = VPI_HANDLE("count"); CHECK_RESULT_NZ(vh1); s_vpi_value v; @@ -110,6 +111,7 @@ static void reregister_rw_cb() { if (vh_rw_cb) { if (verbose) { vpi_printf(const_cast("- Removing cbReadWriteSynch callback\n")); } int ret = vpi_remove_cb(vh_rw_cb); + vh_rw_cb.freed(); CHECK_RESULT(ret, 1); if (verbose) { @@ -140,8 +142,8 @@ static void register_filler_cb() { cb_data_1.cb_rtn = the_filler_callback; cb_data_1.reason = cbReadWriteSynch; - vpiHandle vh1 = vpi_register_cb(&cb_data_1); - CHECK_RESULT_NZ(vh1); + TestVpiHandle cb_data_1_h = vpi_register_cb(&cb_data_1); + CHECK_RESULT_NZ(cb_data_1_h); if (verbose) { vpi_printf(const_cast("- Registering filler cbValueChange callback\n")); @@ -151,7 +153,7 @@ static void register_filler_cb() { cb_data_2.cb_rtn = the_filler_callback; cb_data_2.reason = cbValueChange; - vpiHandle vh2 = VPI_HANDLE("count"); + TestVpiHandle vh2 = VPI_HANDLE("count"); CHECK_RESULT_NZ(vh2); s_vpi_value v; @@ -160,8 +162,8 @@ static void register_filler_cb() { cb_data_2.obj = vh2; cb_data_2.value = &v; - vpiHandle vh3 = vpi_register_cb(&cb_data_2); - CHECK_RESULT_NZ(vh3); + TestVpiHandle cb_data_2_h = vpi_register_cb(&cb_data_2); + CHECK_RESULT_NZ(cb_data_2_h); } double sc_time_stamp() { return main_time; } diff --git a/test_regress/t/t_vpi_cbs_called.cpp b/test_regress/t/t_vpi_cbs_called.cpp index c5ac031b6..8a8b929d3 100644 --- a/test_regress/t/t_vpi_cbs_called.cpp +++ b/test_regress/t/t_vpi_cbs_called.cpp @@ -32,7 +32,7 @@ const std::vector cb_states{PRE_REGISTER, ACTIVE, ACTIVE_AGAIN, R POST_REMOVE}; #define CB_COUNT cbAtEndOfSimTime + 1 -vpiHandle vh_registered_cbs[CB_COUNT] = {0}; +TestVpiHandle vh_registered_cbs[CB_COUNT] = {0}; unsigned int callback_counts[CB_COUNT] = {0}; unsigned int callback_expected_counts[CB_COUNT] = {0}; @@ -43,7 +43,6 @@ bool callbacks_expected_called[CB_COUNT] = {false}; std::vector::const_iterator cb_iter; std::vector::const_iterator state_iter; -vpiHandle vh_test_cb = 0; unsigned int main_time = 0; bool got_error = false; @@ -94,18 +93,17 @@ static int the_callback(p_cb_data cb_data) { static int register_cb(const int next_state) { int cb = *cb_iter; t_cb_data cb_data_testcase; + s_vpi_value v; // Needed in this scope as is in cb_data bzero(&cb_data_testcase, sizeof(cb_data_testcase)); cb_data_testcase.cb_rtn = the_callback; cb_data_testcase.reason = cb; + TestVpiHandle count_h = VPI_HANDLE("count"); // Needed in this scope as is in cb_data + CHECK_RESULT_NZ(count_h); if (cb == cbValueChange) { - vpiHandle vh1 = VPI_HANDLE("count"); - CHECK_RESULT_NZ(vh1); - - s_vpi_value v; v.format = vpiSuppressVal; - cb_data_testcase.obj = vh1; + cb_data_testcase.obj = count_h; cb_data_testcase.value = &v; } @@ -117,6 +115,7 @@ static int register_cb(const int next_state) { vpi_printf(const_cast(" - Registering callback %s\n"), cb_reason_to_string(cb)); } + vh_registered_cbs[cb].release(); vh_registered_cbs[cb] = vpi_register_cb(&cb_data_testcase); break; } @@ -126,6 +125,7 @@ static int register_cb(const int next_state) { cb_reason_to_string(cb)); } int ret = vpi_remove_cb(vh_registered_cbs[cb]); + vh_registered_cbs[cb].freed(); CHECK_RESULT(ret, 1); vh_registered_cbs[cb] = vpi_register_cb(&cb_data_testcase); break; @@ -136,6 +136,7 @@ static int register_cb(const int next_state) { cb_reason_to_string(cb)); } int ret = vpi_remove_cb(vh_registered_cbs[cb]); + vh_registered_cbs[cb].freed(); CHECK_RESULT(ret, 1); break; } @@ -215,7 +216,7 @@ static int test_callbacks(p_cb_data cb_data) { t1.low = 1; cb_data_n.time = &t1; cb_data_n.cb_rtn = test_callbacks; - vh_test_cb = vpi_register_cb(&cb_data_n); + TestVpiHandle vh_test_cb = vpi_register_cb(&cb_data_n); CHECK_RESULT_NZ(vh_test_cb); } @@ -235,7 +236,7 @@ static int register_test_callback() { t1.low = 1; cb_data.time = &t1; cb_data.cb_rtn = test_callbacks; - vh_test_cb = vpi_register_cb(&cb_data); + TestVpiHandle vh_test_cb = vpi_register_cb(&cb_data); CHECK_RESULT_NZ(vh_test_cb); cb_iter = cbs_to_test.cbegin(); @@ -250,7 +251,6 @@ int main(int argc, char** argv, char** env) { double sim_time = 100; bool cbs_called; Verilated::commandArgs(argc, argv); - Verilated::debug(0); VM_PREFIX* topp = new VM_PREFIX(""); // Note null name - we're flattening it out diff --git a/test_regress/t/t_vpi_get.cpp b/test_regress/t/t_vpi_get.cpp index 90741ef73..2fde87c6b 100644 --- a/test_regress/t/t_vpi_get.cpp +++ b/test_regress/t/t_vpi_get.cpp @@ -180,7 +180,7 @@ int mon_check_props() { if (value->children.size) { int size = 0; TestVpiHandle iter_h = vpi_iterate(vpiMemoryWord, h); - while (TestVpiHandle word_h = vpi_scan(iter_h.nofree())) { + while (TestVpiHandle word_h = vpi_scan(iter_h)) { // check size and range if (int status = _mon_check_props(word_h, value->children.size, value->children.direction, @@ -188,6 +188,7 @@ int mon_check_props() { return status; size++; } + iter_h.freed(); // IEEE 37.2.2 vpi_scan at end does a vpi_release_handle CHECK_RESULT(size, value->attributes.size); } value++; @@ -206,7 +207,7 @@ int mon_check() { #ifdef IS_VPI static int mon_check_vpi() { - vpiHandle href = vpi_handle(vpiSysTfCall, 0); + TestVpiHandle href = vpi_handle(vpiSysTfCall, 0); s_vpi_value vpi_value; vpi_value.format = vpiIntVal; diff --git a/test_regress/t/t_vpi_memory.cpp b/test_regress/t/t_vpi_memory.cpp index 6cfaebdaf..6478c4b58 100644 --- a/test_regress/t/t_vpi_memory.cpp +++ b/test_regress/t/t_vpi_memory.cpp @@ -80,26 +80,32 @@ unsigned int main_time = 0; #define CHECK_RESULT_CSTR_STRIP(got, exp) CHECK_RESULT_CSTR(got + strspn(got, " "), exp) -int _mon_check_range(TestVpiHandle& handle, int size, int left, int right) { - TestVpiHandle iter_h, left_h, right_h; +int _mon_check_range(const TestVpiHandle& handle, int size, int left, int right) { s_vpi_value value; value.format = vpiIntVal; value.value.integer = 0; // check size of object - int vpisize = vpi_get(vpiSize, handle); - CHECK_RESULT(vpisize, size); - // check left hand side of range - left_h = vpi_handle(vpiLeftRange, handle); - CHECK_RESULT_NZ(left_h); - vpi_get_value(left_h, &value); - CHECK_RESULT(value.value.integer, left); - int coherency = value.value.integer; - // check right hand side of range - right_h = vpi_handle(vpiRightRange, handle); - CHECK_RESULT_NZ(right_h); - vpi_get_value(right_h, &value); - CHECK_RESULT(value.value.integer, right); - coherency -= value.value.integer; + { + int vpisize = vpi_get(vpiSize, handle); + CHECK_RESULT(vpisize, size); + } + int coherency; + { + // check left hand side of range + TestVpiHandle left_h = vpi_handle(vpiLeftRange, handle); + CHECK_RESULT_NZ(left_h); + vpi_get_value(left_h, &value); + CHECK_RESULT(value.value.integer, left); + coherency = value.value.integer; + } + { + // check right hand side of range + TestVpiHandle right_h = vpi_handle(vpiRightRange, handle); + CHECK_RESULT_NZ(right_h); + vpi_get_value(right_h, &value); + CHECK_RESULT(value.value.integer, right); + coherency -= value.value.integer; + } // calculate size & check coherency = abs(coherency) + 1; CHECK_RESULT(coherency, size); @@ -107,40 +113,46 @@ int _mon_check_range(TestVpiHandle& handle, int size, int left, int right) { } int _mon_check_memory() { - int cnt; - TestVpiHandle mem_h, lcl_h, side_h; - vpiHandle iter_h; // Icarus does not like auto free of iterator handles s_vpi_value value; value.format = vpiIntVal; value.value.integer = 0; s_vpi_error_info e; vpi_printf((PLI_BYTE8*)"Check memory vpi ...\n"); - mem_h = vpi_handle_by_name((PLI_BYTE8*)TestSimulator::rooted("mem0"), NULL); + TestVpiHandle mem_h = vpi_handle_by_name((PLI_BYTE8*)TestSimulator::rooted("mem0"), NULL); CHECK_RESULT_NZ(mem_h); - // check type - int vpitype = vpi_get(vpiType, mem_h); - CHECK_RESULT(vpitype, vpiMemory); + { + // check type + int vpitype = vpi_get(vpiType, mem_h); + CHECK_RESULT(vpitype, vpiMemory); + } if (int status = _mon_check_range(mem_h, 16, 16, 1)) return status; // iterate and store - iter_h = vpi_iterate(vpiMemoryWord, mem_h); - cnt = 0; - while ((lcl_h = vpi_scan(iter_h))) { - value.value.integer = ++cnt; - vpi_put_value(lcl_h, &value, NULL, vpiNoDelay); - // check size and range - if (int status = _mon_check_range(lcl_h, 32, 31, 0)) return status; + { + TestVpiHandle iter_h = vpi_iterate(vpiMemoryWord, mem_h); + int cnt = 0; + while (TestVpiHandle lcl_h = vpi_scan(iter_h)) { + value.value.integer = ++cnt; + vpi_put_value(lcl_h, &value, NULL, vpiNoDelay); + // check size and range + if (int status = _mon_check_range(lcl_h, 32, 31, 0)) return status; + } + iter_h.freed(); // IEEE 37.2.2 vpi_scan at end does a vpi_release_handle + CHECK_RESULT(cnt, 16); // should be 16 addresses } - CHECK_RESULT(cnt, 16); // should be 16 addresses - // iterate and accumulate - iter_h = vpi_iterate(vpiMemoryWord, mem_h); - cnt = 0; - while ((lcl_h = vpi_scan(iter_h))) { - ++cnt; - vpi_get_value(lcl_h, &value); - CHECK_RESULT(value.value.integer, cnt); + { + // iterate and accumulate + TestVpiHandle iter_h = vpi_iterate(vpiMemoryWord, mem_h); + int cnt = 0; + while (TestVpiHandle lcl_h = vpi_scan(iter_h)) { + ++cnt; + vpi_get_value(lcl_h, &value); + CHECK_RESULT(value.value.integer, cnt); + } + iter_h.freed(); // IEEE 37.2.2 vpi_scan at end does a vpi_release_handle + CHECK_RESULT(cnt, 16); // should be 16 addresses } - CHECK_RESULT(cnt, 16); // should be 16 addresses + // don't care for non verilator // (crashes on Icarus) if (TestSimulator::is_icarus()) { @@ -148,37 +160,49 @@ int _mon_check_memory() { TestSimulator::get_info().product); return 0; // Ok } - // make sure trying to get properties that don't exist - // doesn't crash - int should_be_0 = vpi_get(vpiSize, iter_h); - CHECK_RESULT(should_be_0, 0); - should_be_0 = vpi_get(vpiIndex, iter_h); - CHECK_RESULT(should_be_0, 0); - vpiHandle should_be_NULL = vpi_handle(vpiLeftRange, iter_h); - CHECK_RESULT(should_be_NULL, 0); - should_be_NULL = vpi_handle(vpiRightRange, iter_h); - CHECK_RESULT(should_be_NULL, 0); - should_be_NULL = vpi_handle(vpiScope, iter_h); - CHECK_RESULT(should_be_NULL, 0); - - // check vpiRange - iter_h = vpi_iterate(vpiRange, mem_h); - CHECK_RESULT_NZ(iter_h); - lcl_h = vpi_scan(iter_h); - CHECK_RESULT_NZ(lcl_h); - side_h = vpi_handle(vpiLeftRange, lcl_h); - CHECK_RESULT_NZ(side_h); - vpi_get_value(side_h, &value); - CHECK_RESULT(value.value.integer, 16); - side_h = vpi_handle(vpiRightRange, lcl_h); - CHECK_RESULT_NZ(side_h); - vpi_get_value(side_h, &value); - CHECK_RESULT(value.value.integer, 1); - - // check writing to vpiConstant - vpi_put_value(side_h, &value, NULL, vpiNoDelay); - CHECK_RESULT_NZ(vpi_chk_error(&e)); - + { + // make sure trying to get properties that don't exist + // doesn't crash + TestVpiHandle iter_h = vpi_iterate(vpiMemoryWord, mem_h); + int should_be_0 = vpi_get(vpiSize, iter_h); + CHECK_RESULT(should_be_0, 0); + should_be_0 = vpi_get(vpiIndex, iter_h); + CHECK_RESULT(should_be_0, 0); + vpiHandle should_be_NULL = vpi_handle(vpiLeftRange, iter_h); + CHECK_RESULT(should_be_NULL, 0); + should_be_NULL = vpi_handle(vpiRightRange, iter_h); + CHECK_RESULT(should_be_NULL, 0); + should_be_NULL = vpi_handle(vpiScope, iter_h); + CHECK_RESULT(should_be_NULL, 0); + } + { + // check vpiRange + TestVpiHandle iter_h = vpi_iterate(vpiRange, mem_h); + CHECK_RESULT_NZ(iter_h); + TestVpiHandle lcl_h = vpi_scan(iter_h); + CHECK_RESULT_NZ(lcl_h); + { + TestVpiHandle side_h = vpi_handle(vpiLeftRange, lcl_h); + CHECK_RESULT_NZ(side_h); + vpi_get_value(side_h, &value); + CHECK_RESULT(value.value.integer, 16); + } + { + TestVpiHandle side_h = vpi_handle(vpiRightRange, lcl_h); + CHECK_RESULT_NZ(side_h); + vpi_get_value(side_h, &value); + CHECK_RESULT(value.value.integer, 1); + // check writing to vpiConstant + vpi_put_value(side_h, &value, NULL, vpiNoDelay); + CHECK_RESULT_NZ(vpi_chk_error(&e)); + } + { + // iterator should exhaust after 1 dimension + TestVpiHandle zero_h = vpi_scan(iter_h); + iter_h.freed(); // IEEE 37.2.2 vpi_scan at end does a vpi_release_handle + CHECK_RESULT(zero_h, 0); + } + } return 0; // Ok } @@ -193,7 +217,7 @@ int mon_check() { #ifdef IS_VPI static int mon_check_vpi() { - vpiHandle href = vpi_handle(vpiSysTfCall, 0); + TestVpiHandle href = vpi_handle(vpiSysTfCall, 0); s_vpi_value vpi_value; vpi_value.format = vpiIntVal; diff --git a/test_regress/t/t_vpi_module.cpp b/test_regress/t/t_vpi_module.cpp index dc5929f86..0d9922f51 100644 --- a/test_regress/t/t_vpi_module.cpp +++ b/test_regress/t/t_vpi_module.cpp @@ -48,6 +48,19 @@ unsigned int main_time = 0; return __LINE__; \ } +#define CHECK_RESULT_Z(got) \ + if (got) { \ + printf("%%Error: %s:%d: GOT = !NULL EXP = NULL\n", FILENM, __LINE__); \ + return __LINE__; \ + } + +#define CHECK_RESULT(got, exp) \ + if ((got) != (exp)) { \ + std::cout << std::dec << "%Error: " << FILENM << ":" << __LINE__ << ": GOT = " << (got) \ + << " EXP = " << (exp) << std::endl; \ + return __LINE__; \ + } + #define CHECK_RESULT_CSTR(got, exp) \ if (strcmp((got), (exp))) { \ printf("%%Error: %s:%d: GOT = '%s' EXP = '%s'\n", FILENM, __LINE__, \ @@ -55,41 +68,68 @@ unsigned int main_time = 0; return __LINE__; \ } +void modDump(const TestVpiHandle& it, int n) { + while (TestVpiHandle hndl = vpi_scan(it)) { + const char* nm = vpi_get_str(vpiName, hndl); + for (int i = 0; i < n; i++) printf(" "); + printf("%s\n", nm); + TestVpiHandle subIt = vpi_iterate(vpiModule, hndl); + if (subIt) modDump(subIt, n + 1); + } +} + extern "C" { int mon_check() { - vpiHandle it = vpi_iterate(vpiModule, NULL); + TestVpiHandle it = vpi_iterate(vpiModule, NULL); CHECK_RESULT_NZ(it); + // Uncomment to see what other simulators return + // modDump(it, 0); + // return 1; - vpiHandle topmod = vpi_scan(it); + TestVpiHandle topmod = vpi_scan(it); CHECK_RESULT_NZ(topmod); + CHECK_RESULT(vpi_get(vpiType, topmod), vpiModule); - char* name = vpi_get_str(vpiName, topmod); - CHECK_RESULT_NZ(name); - CHECK_RESULT_CSTR(name, "t"); + const char* t_name = vpi_get_str(vpiName, topmod); + CHECK_RESULT_NZ(t_name); - it = vpi_iterate(vpiModule, topmod); - CHECK_RESULT_NZ(it); - - vpiHandle mod = vpi_scan(it); - CHECK_RESULT_NZ(mod); - - name = vpi_get_str(vpiName, mod); - CHECK_RESULT_CSTR(name, "mod_a"); - - it = vpi_iterate(vpiModule, mod); - CHECK_RESULT_NZ(it); - - mod = vpi_scan(it); - CHECK_RESULT_NZ(mod); - - name = vpi_get_str(vpiName, mod); - if (strcmp(name, "mod_b") == 0) { - // Full visibility in other simulators, skip mod_b - mod = vpi_scan(it); - CHECK_RESULT_NZ(mod); - name = vpi_get_str(vpiName, mod); + // Icarus reports the top most module as "top" + if (strcmp(t_name, "top") == 0) { + it = vpi_iterate(vpiModule, topmod); + CHECK_RESULT_NZ(it); + CHECK_RESULT(vpi_get(vpiType, it), vpiModule); + topmod = vpi_scan(it); + t_name = vpi_get_str(vpiName, topmod); + CHECK_RESULT_NZ(t_name); } - CHECK_RESULT_CSTR(name, "mod_c."); + CHECK_RESULT_CSTR(t_name, "t"); + TestVpiHandle topmod_done_should_be_0 = (vpi_scan(it)); + it.freed(); // IEEE 37.2.2 vpi_scan at end does a vpi_release_handle + CHECK_RESULT_Z(topmod_done_should_be_0); + + TestVpiHandle it2 = vpi_iterate(vpiModule, topmod); + CHECK_RESULT_NZ(it2); + + TestVpiHandle mod2 = vpi_scan(it2); + CHECK_RESULT_NZ(mod2); + + const char* mod_a_name = vpi_get_str(vpiName, mod2); + CHECK_RESULT_CSTR(mod_a_name, "mod_a"); + + TestVpiHandle it3 = vpi_iterate(vpiModule, mod2); + CHECK_RESULT_NZ(it3); + + TestVpiHandle mod3 = vpi_scan(it3); + CHECK_RESULT_NZ(mod3); + + const char* mod_c_name = vpi_get_str(vpiName, mod3); + if (strcmp(mod_c_name, "mod_b") == 0) { + // Full visibility in other simulators, skip mod_b + TestVpiHandle mod4 = vpi_scan(it3); + CHECK_RESULT_NZ(mod4); + mod_c_name = vpi_get_str(vpiName, mod4); + } + CHECK_RESULT_CSTR(mod_c_name, "mod_c."); return 0; // Ok } @@ -99,7 +139,7 @@ int mon_check() { #ifdef IS_VPI static int mon_check_vpi() { - vpiHandle href = vpi_handle(vpiSysTfCall, 0); + TestVpiHandle href = vpi_handle(vpiSysTfCall, 0); s_vpi_value vpi_value; vpi_value.format = vpiIntVal; @@ -134,6 +174,9 @@ int main(int argc, char** argv, char** env) { Verilated::fatalOnVpiError(0); VM_PREFIX* topp = new VM_PREFIX(""); // Note null name - we're flattening it out + // Test second construction + delete topp; + topp = new VM_PREFIX(""); #ifdef VERILATOR #ifdef TEST_VERBOSE diff --git a/test_regress/t/t_vpi_param.cpp b/test_regress/t/t_vpi_param.cpp index bfba20a21..64e54b36f 100644 --- a/test_regress/t/t_vpi_param.cpp +++ b/test_regress/t/t_vpi_param.cpp @@ -214,7 +214,7 @@ int mon_check() { #ifdef IS_VPI static int mon_check_vpi() { - vpiHandle href = vpi_handle(vpiSysTfCall, 0); + TestVpiHandle href = vpi_handle(vpiSysTfCall, 0); s_vpi_value vpi_value; vpi_value.format = vpiIntVal; diff --git a/test_regress/t/t_vpi_release_dup_bad.pl b/test_regress/t/t_vpi_release_dup_bad.pl new file mode 100755 index 000000000..2fa1154c0 --- /dev/null +++ b/test_regress/t/t_vpi_release_dup_bad.pl @@ -0,0 +1,26 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(vlt => 1); + +compile( + v_flags2 => ["t/$Self->{name}_c.cpp"], + verilator_flags2 => ['--vpi'], + ); + +execute( + fails => 1, + ); + +file_grep($Self->{run_log_filename}, qr/vpi_release_handle.*called on same object twice/i); + +ok(1); + +1; diff --git a/test_regress/t/t_vpi_release_dup_bad.v b/test_regress/t/t_vpi_release_dup_bad.v new file mode 100644 index 000000000..1ba1097e0 --- /dev/null +++ b/test_regress/t/t_vpi_release_dup_bad.v @@ -0,0 +1,15 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under The Creative Commons Public Domain, for +// any use, without warranty, 2020 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +import "DPI-C" context function void dpii_check(); + +module t (/*AUTOARG*/); + initial begin + dpii_check(); + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule diff --git a/test_regress/t/t_vpi_release_dup_bad_c.cpp b/test_regress/t/t_vpi_release_dup_bad_c.cpp new file mode 100644 index 000000000..2d05cb61d --- /dev/null +++ b/test_regress/t/t_vpi_release_dup_bad_c.cpp @@ -0,0 +1,28 @@ +// -*- mode: C++; c-file-style: "cc-mode" -*- +//************************************************************************* +// +// Copyright 2009-2011 by Wilson Snyder. This program is free software; you +// can redistribute it and/or modify it under the terms of either the GNU +// Lesser General Public License Version 3 or the Perl Artistic License +// Version 2.0. +// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 +// +//************************************************************************* + +#include +#include "svdpi.h" +#include "vpi_user.h" +//#include "verilated.h" + +#include "Vt_vpi_release_dup_bad__Dpi.h" + +//====================================================================== + +void dpii_check() { + vpiHandle mod; // Not TestVpiHandle as testing double free + // Verilated::scopesDump(); + mod = vpi_handle_by_name((PLI_BYTE8*)"top.t", NULL); + if (!mod) vpi_printf(const_cast("-- Cannot vpi_find module\n")); + vpi_free_object(mod); // using vpi_free_object instead of vpi_release_handle for coverage + vpi_free_object(mod); // error: double free +} diff --git a/test_regress/t/t_vpi_time_cb.cpp b/test_regress/t/t_vpi_time_cb.cpp index 210abb609..54d61a4a1 100644 --- a/test_regress/t/t_vpi_time_cb.cpp +++ b/test_regress/t/t_vpi_time_cb.cpp @@ -89,6 +89,10 @@ unsigned int callback_count_start_of_sim = 0; #ifdef IS_VPI +static int _never_cb(p_cb_data cb_data) { + CHECK_RESULT(0, 1); // Should never get called +} + static int _time_cb1(p_cb_data cb_data) { s_vpi_time t; t.type = vpiSimTime; @@ -99,14 +103,28 @@ static int _time_cb1(p_cb_data cb_data) { t_cb_data cb_data_n; bzero(&cb_data_n, sizeof(cb_data_n)); - - cb_data_n.reason = cbAfterDelay; - t.type = vpiSimTime; - t.high = 0; - t.low = 1; - cb_data_n.time = &t; - cb_data_n.cb_rtn = _time_cb1; - vpi_register_cb(&cb_data_n); + { + cb_data_n.reason = cbAfterDelay; + t.type = vpiSimTime; + t.high = 0; + t.low = 1; + cb_data_n.time = &t; + cb_data_n.cb_rtn = _time_cb1; + TestVpiHandle cb_data_n1_h = vpi_register_cb(&cb_data_n); + CHECK_RESULT(vpi_get(vpiType, cb_data_n1_h), vpiCallback); + } + { + // Test cancelling a callback + cb_data_n.reason = cbAfterDelay; + t.type = vpiSimTime; + t.high = 0; + t.low = 1; + cb_data_n.time = &t; + cb_data_n.cb_rtn = _never_cb; + TestVpiHandle cb_h = vpi_register_cb(&cb_data_n); + vpi_remove_cb(cb_h); + cb_h.freed(); + } return 0; } @@ -127,7 +145,8 @@ static int _time_cb2(p_cb_data cb_data) { t.low = 1; cb_data_n.time = &t; cb_data_n.cb_rtn = _time_cb2; - vpi_register_cb(&cb_data_n); + TestVpiHandle cb_data_n2_h = vpi_register_cb(&cb_data_n); + CHECK_RESULT(vpi_get(vpiType, cb_data_n2_h), vpiCallback); return 0; } @@ -143,7 +162,8 @@ static int _start_of_sim_cb(p_cb_data cb_data) { t1.low = 3; cb_data_n1.time = &t1; cb_data_n1.cb_rtn = _time_cb1; - vpi_register_cb(&cb_data_n1); + TestVpiHandle cb_data_n1_h = vpi_register_cb(&cb_data_n1); + CHECK_RESULT(vpi_get(vpiType, cb_data_n1_h), vpiCallback); cb_data_n2.reason = cbAfterDelay; t2.type = vpiSimTime; @@ -151,7 +171,7 @@ static int _start_of_sim_cb(p_cb_data cb_data) { t2.low = 4; cb_data_n2.time = &t2; cb_data_n2.cb_rtn = _time_cb2; - vpi_register_cb(&cb_data_n2); + TestVpiHandle cb_data_n2_h = vpi_register_cb(&cb_data_n2); callback_count_start_of_sim++; return 0; } @@ -172,17 +192,28 @@ void vpi_compat_bootstrap(void) { // clang-format on t_cb_data cb_data; bzero(&cb_data, sizeof(cb_data)); - - // VL_PRINTF("register start-of-sim callback\n"); - cb_data.reason = cbStartOfSimulation; - cb_data.time = 0; - cb_data.cb_rtn = _start_of_sim_cb; - vpi_register_cb(&cb_data); - - cb_data.reason = cbEndOfSimulation; - cb_data.time = 0; - cb_data.cb_rtn = _end_of_sim_cb; - vpi_register_cb(&cb_data); + { + // VL_PRINTF("register start-of-sim callback\n"); + cb_data.reason = cbStartOfSimulation; + cb_data.time = 0; + cb_data.cb_rtn = _start_of_sim_cb; + TestVpiHandle _start_of_sim_cb_h = vpi_register_cb(&cb_data); + } + { + cb_data.reason = cbEndOfSimulation; + cb_data.time = 0; + cb_data.cb_rtn = _end_of_sim_cb; + TestVpiHandle _end_of_sim_cb_h = vpi_register_cb(&cb_data); + } + { + // Test cancelling a callback + cb_data.reason = cbStartOfSimulation; + cb_data.time = 0; + cb_data.cb_rtn = _never_cb; + TestVpiHandle cb_h = vpi_register_cb(&cb_data); + vpi_remove_cb(cb_h); + cb_h.freed(); + } } // icarus entry diff --git a/test_regress/t/t_vpi_unimpl.cpp b/test_regress/t/t_vpi_unimpl.cpp index 53cdde2c5..9c7e1ec3a 100644 --- a/test_regress/t/t_vpi_unimpl.cpp +++ b/test_regress/t/t_vpi_unimpl.cpp @@ -45,6 +45,12 @@ unsigned int callback_count = 0; return __LINE__; \ } +#define CHECK_RESULT_Z(got) \ + if (got) { \ + printf("%%Error: %s:%d: GOT = !NULL EXP = NULL\n", FILENM, __LINE__); \ + return __LINE__; \ + } + // Use cout to avoid issues with %d/%lx etc #define CHECK_RESULT(got, exp) \ if ((got) != (exp)) { \ @@ -72,6 +78,7 @@ unsigned int callback_count = 0; int _mon_check_unimpl(p_cb_data cb_data) { static TestVpiHandle cb, clk_h; vpiHandle handle; + const char* cp = nullptr; if (cb_data) { // this is the callback s_vpi_error_info info; @@ -151,6 +158,20 @@ int _mon_check_unimpl(p_cb_data cb_data) { handle = vpi_register_cb(&cb_data_s); CHECK_RESULT(callback_count, 24); CHECK_RESULT(handle, 0); + + (void)vpi_get_str(vpiRange, clk_h); // Bad type + CHECK_RESULT(callback_count, 25); + + // Supported but illegal tests: + // Various checks that guarded passing NULL handles + handle = vpi_scan(NULL); + CHECK_RESULT(handle, 0); + (void)vpi_get(vpiType, NULL); + (void)vpi_get(vpiDirection, NULL); + (void)vpi_get(vpiVector, NULL); + cp = vpi_get_str(vpiType, NULL); + CHECK_RESULT_Z(cp); + vpi_release_handle(NULL); } return 0; // Ok } diff --git a/test_regress/t/t_vpi_var.cpp b/test_regress/t/t_vpi_var.cpp index 93802d6a7..b8af76d23 100644 --- a/test_regress/t/t_vpi_var.cpp +++ b/test_regress/t/t_vpi_var.cpp @@ -49,6 +49,12 @@ unsigned int callback_count_strs_max = 500; //====================================================================== +#ifdef TEST_VERBOSE +bool verbose = true; +#else +bool verbose = false; +#endif + #define CHECK_RESULT_VH(got, exp) \ if ((got) != (exp)) { \ printf("%%Error: %s:%d: GOT = %p EXP = %p\n", FILENM, __LINE__, (got), (exp)); \ @@ -138,17 +144,18 @@ int _mon_check_callbacks() { cb_data.value = NULL; cb_data.time = NULL; - vpiHandle vh = vpi_register_cb(&cb_data); + TestVpiHandle vh = vpi_register_cb(&cb_data); CHECK_RESULT_NZ(vh); PLI_INT32 status = vpi_remove_cb(vh); + vh.freed(); CHECK_RESULT_NZ(status); return 0; } int _value_callback(p_cb_data cb_data) { - + if (verbose) vpi_printf(const_cast(" _value_callback:\n")); if (TestSimulator::is_verilator()) { // this check only makes sense in Verilator CHECK_RESULT(cb_data->value->value.integer + 10, main_time); @@ -178,50 +185,59 @@ int _value_callback_quad(p_cb_data cb_data) { } int _mon_check_value_callbacks() { - vpiHandle vh1 = VPI_HANDLE("count"); - CHECK_RESULT_NZ(vh1); - s_vpi_value v; v.format = vpiIntVal; - vpi_get_value(vh1, &v); t_cb_data cb_data; cb_data.reason = cbValueChange; - cb_data.cb_rtn = _value_callback; - cb_data.obj = vh1; - cb_data.value = &v; cb_data.time = NULL; - vpiHandle vh = vpi_register_cb(&cb_data); - CHECK_RESULT_NZ(vh); + { + TestVpiHandle vh1 = VPI_HANDLE("count"); + CHECK_RESULT_NZ(vh1); - vh1 = VPI_HANDLE("half_count"); - CHECK_RESULT_NZ(vh1); + vpi_get_value(vh1, &v); + cb_data.value = &v; + cb_data.obj = vh1; + cb_data.cb_rtn = _value_callback; - cb_data.obj = vh1; - cb_data.cb_rtn = _value_callback_half; + if (verbose) vpi_printf(const_cast(" vpi_register_cb(_value_callback):\n")); + TestVpiHandle callback_h = vpi_register_cb(&cb_data); + CHECK_RESULT_NZ(callback_h); + } + { + TestVpiHandle vh1 = VPI_HANDLE("half_count"); + CHECK_RESULT_NZ(vh1); - vh = vpi_register_cb(&cb_data); - CHECK_RESULT_NZ(vh); + cb_data.obj = vh1; + cb_data.cb_rtn = _value_callback_half; - vh1 = VPI_HANDLE("quads"); - CHECK_RESULT_NZ(vh1); + TestVpiHandle callback_h = vpi_register_cb(&cb_data); + CHECK_RESULT_NZ(callback_h); + } + { + TestVpiHandle vh1 = VPI_HANDLE("quads"); + CHECK_RESULT_NZ(vh1); - v.format = vpiVectorVal; - cb_data.obj = vh1; - cb_data.cb_rtn = _value_callback_quad; + v.format = vpiVectorVal; + cb_data.obj = vh1; + cb_data.cb_rtn = _value_callback_quad; - vh = vpi_register_cb(&cb_data); - CHECK_RESULT_NZ(vh); + TestVpiHandle callback_h = vpi_register_cb(&cb_data); + CHECK_RESULT_NZ(callback_h); + } + { + TestVpiHandle vh1 = VPI_HANDLE("quads"); + CHECK_RESULT_NZ(vh1); + TestVpiHandle vh2 = vpi_handle_by_index(vh1, 2); + CHECK_RESULT_NZ(vh2); - vh1 = vpi_handle_by_index(vh1, 2); - CHECK_RESULT_NZ(vh1); + cb_data.obj = vh2; + cb_data.cb_rtn = _value_callback_quad; - cb_data.obj = vh1; - cb_data.cb_rtn = _value_callback_quad; - - vh = vpi_register_cb(&cb_data); - CHECK_RESULT_NZ(vh); + TestVpiHandle callback_h = vpi_register_cb(&cb_data); + CHECK_RESULT_NZ(callback_h); + } return 0; } @@ -311,6 +327,25 @@ int _mon_check_var() { CHECK_RESULT_CSTR(p, "vpiConstant"); } + TestVpiHandle vh5 = VPI_HANDLE("quads"); + CHECK_RESULT_NZ(vh5); + { + TestVpiHandle vh10 = vpi_handle(vpiLeftRange, vh5); + CHECK_RESULT_NZ(vh10); + vpi_get_value(vh10, &tmpValue); + CHECK_RESULT(tmpValue.value.integer, 2); + p = vpi_get_str(vpiType, vh10); + CHECK_RESULT_CSTR(p, "vpiConstant"); + } + { + TestVpiHandle vh10 = vpi_handle(vpiRightRange, vh5); + CHECK_RESULT_NZ(vh10); + vpi_get_value(vh10, &tmpValue); + CHECK_RESULT(tmpValue.value.integer, 3); + p = vpi_get_str(vpiType, vh10); + CHECK_RESULT_CSTR(p, "vpiConstant"); + } + return 0; } @@ -321,21 +356,26 @@ int _mon_check_varlist() { CHECK_RESULT_NZ(vh2); TestVpiHandle vh10 = vpi_iterate(vpiReg, vh2); - CHECK_RESULT_NZ(vh10.nofree()); - - TestVpiHandle vh11 = vpi_scan(vh10); - CHECK_RESULT_NZ(vh11); - p = vpi_get_str(vpiFullName, vh11); - CHECK_RESULT_CSTR(p, TestSimulator::rooted("sub.subsig1")); - - TestVpiHandle vh12 = vpi_scan(vh10); - CHECK_RESULT_NZ(vh12); - p = vpi_get_str(vpiFullName, vh12); - CHECK_RESULT_CSTR(p, TestSimulator::rooted("sub.subsig2")); - - TestVpiHandle vh13 = vpi_scan(vh10); - CHECK_RESULT(vh13, 0); + CHECK_RESULT_NZ(vh10); + CHECK_RESULT(vpi_get(vpiType, vh10), vpiIterator); + { + TestVpiHandle vh11 = vpi_scan(vh10); + CHECK_RESULT_NZ(vh11); + p = vpi_get_str(vpiFullName, vh11); + CHECK_RESULT_CSTR(p, TestSimulator::rooted("sub.subsig1")); + } + { + TestVpiHandle vh12 = vpi_scan(vh10); + CHECK_RESULT_NZ(vh12); + p = vpi_get_str(vpiFullName, vh12); + CHECK_RESULT_CSTR(p, TestSimulator::rooted("sub.subsig2")); + } + { + TestVpiHandle vh13 = vpi_scan(vh10); + vh10.freed(); // IEEE 37.2.2 vpi_scan at end does a vpi_release_handle + CHECK_RESULT(vh13, 0); + } return 0; } @@ -377,7 +417,17 @@ int _mon_check_quad() { TestVpiHandle vhidx2 = vpi_handle_by_index(vh2, 2); CHECK_RESULT_NZ(vhidx2); TestVpiHandle vhidx3 = vpi_handle_by_index(vh2, 3); - CHECK_RESULT_NZ(vhidx2); + CHECK_RESULT_NZ(vhidx3); + + // Memory words should not be indexable + TestVpiHandle vhidx3idx0 = vpi_handle_by_index(vhidx3, 0); + CHECK_RESULT(vhidx3idx0, 0); + TestVpiHandle vhidx2idx2 = vpi_handle_by_index(vhidx2, 2); + CHECK_RESULT(vhidx2idx2, 0); + TestVpiHandle vhidx3idx3 = vpi_handle_by_index(vhidx3, 3); + CHECK_RESULT(vhidx3idx3, 0); + TestVpiHandle vhidx2idx61 = vpi_handle_by_index(vhidx2, 61); + CHECK_RESULT(vhidx2idx61, 0); v.format = vpiVectorVal; v.value.vector = vv; @@ -449,7 +499,10 @@ int _mon_check_putget_str(p_cb_data cb_data) { s_vpi_vecval vector[4]; } value; // reference } data[129]; + if (cb_data) { + if (verbose) vpi_printf(const_cast(" _mon_check_putget_str callback:\n")); + // this is the callback static unsigned int seed = 1; s_vpi_time t; @@ -528,6 +581,7 @@ int _mon_check_putget_str(p_cb_data cb_data) { } if (++callback_count_strs == callback_count_strs_max) { int success = vpi_remove_cb(cb); + cb.freed(); CHECK_RESULT_NZ(success); }; } else { @@ -546,7 +600,7 @@ int _mon_check_putget_str(p_cb_data cb_data) { static t_cb_data cb_data; static s_vpi_value v; - static TestVpiHandle count_h = VPI_HANDLE("count"); + TestVpiHandle count_h = VPI_HANDLE("count"); cb_data.reason = cbValueChange; cb_data.cb_rtn = _mon_check_putget_str; // this function @@ -556,6 +610,7 @@ int _mon_check_putget_str(p_cb_data cb_data) { v.format = vpiIntVal; cb = vpi_register_cb(&cb_data); + // It is legal to free the callback handle immediately if not otherwise needed CHECK_RESULT_NZ(cb); } return 0; @@ -599,7 +654,7 @@ int mon_check() { #ifdef IS_VPI static int mon_check_vpi() { - vpiHandle href = vpi_handle(vpiSysTfCall, 0); + TestVpiHandle href = vpi_handle(vpiSysTfCall, 0); s_vpi_value vpi_value; vpi_value.format = vpiIntVal; diff --git a/test_regress/t/t_vpi_var.v b/test_regress/t/t_vpi_var.v index 34b94b34e..89160dc60 100644 --- a/test_regress/t/t_vpi_var.v +++ b/test_regress/t/t_vpi_var.v @@ -29,7 +29,9 @@ extern "C" int mon_check(); reg [2:1] twoone /*verilator public_flat_rw @(posedge clk) */; reg [2:1] fourthreetwoone[4:3] /*verilator public_flat_rw @(posedge clk) */; - reg [61:0] quads[3:2] /*verilator public_flat_rw @(posedge clk) */; + // verilator lint_off LITENDIAN + reg [0:61] quads[2:3] /*verilator public_flat_rw @(posedge clk) */; + // verilator lint_on LITENDIAN reg [31:0] count /*verilator public_flat_rd */; reg [31:0] half_count /*verilator public_flat_rd */; diff --git a/test_regress/t/t_vpi_zero_time_cb.cpp b/test_regress/t/t_vpi_zero_time_cb.cpp index 54303e04f..00b3a9c28 100644 --- a/test_regress/t/t_vpi_zero_time_cb.cpp +++ b/test_regress/t/t_vpi_zero_time_cb.cpp @@ -100,7 +100,7 @@ static int _start_of_sim_cb(p_cb_data cb_data) { t.low = 0; cb_data_n.time = &t; cb_data_n.cb_rtn = _zero_time_cb; - vpi_register_cb(&cb_data_n); + TestVpiHandle _cb_data_n_h = vpi_register_cb(&cb_data_n); callback_count_start_of_sim++; return 0; } @@ -127,12 +127,12 @@ void vpi_compat_bootstrap(void) { cb_data.reason = cbStartOfSimulation; cb_data.time = 0; cb_data.cb_rtn = _start_of_sim_cb; - vpi_register_cb(&cb_data); + TestVpiHandle _start_of_sim_cb_h = vpi_register_cb(&cb_data); cb_data.reason = cbEndOfSimulation; cb_data.time = 0; cb_data.cb_rtn = _end_of_sim_cb; - vpi_register_cb(&cb_data); + TestVpiHandle _end_of_sim_cb_h = vpi_register_cb(&cb_data); } // icarus entry diff --git a/test_regress/t/t_xml_tag.out b/test_regress/t/t_xml_tag.out index 7c50f6d85..191ce8023 100644 --- a/test_regress/t/t_xml_tag.out +++ b/test_regress/t/t_xml_tag.out @@ -72,8 +72,8 @@ - + diff --git a/verilator-config-version.cmake.in b/verilator-config-version.cmake.in index a22cd29f2..eca80f997 100644 --- a/verilator-config-version.cmake.in +++ b/verilator-config-version.cmake.in @@ -7,7 +7,7 @@ # # find_package(verilate 4.0) # -# Copyright 2003-2020 by Wilson Snyder. This program is free software; you +# Copyright 2003-2021 by Wilson Snyder. This program is free software; you # can redistribute it and/or modify it under the terms of either the GNU # Lesser General Public License Version 3 or the Perl Artistic License # Version 2.0. diff --git a/verilator-config.cmake.in b/verilator-config.cmake.in index 0b972874b..cfd6ed2b2 100644 --- a/verilator-config.cmake.in +++ b/verilator-config.cmake.in @@ -11,7 +11,7 @@ # add_executable(simulator ) # verilate(simulator SOURCES ) # -# Copyright 2003-2020 by Wilson Snyder. This program is free software; you +# Copyright 2003-2021 by Wilson Snyder. This program is free software; you # can redistribute it and/or modify it under the terms of either the GNU # Lesser General Public License Version 3 or the Perl Artistic License # Version 2.0. @@ -129,7 +129,7 @@ function(verilate TARGET) endif() if (VERILATE_TOP_MODULE) - list(APPEND VERILATOR_ARGS --top-module ${VERILATE_TOP_MODULE}) + list(APPEND VERILATOR_ARGS --top ${VERILATE_TOP_MODULE}) endif() if (VERILATE_THREADS)