Merge branch 'master' into iface-assign-error

This commit is contained in:
Nick Brereton 2025-05-10 05:33:32 -04:00
commit da092dc666
1147 changed files with 1101149 additions and 13305 deletions

View File

@ -9,7 +9,7 @@ assignees: ''
Thanks for taking the time to report this.
Can you attach an example that shows the issue? (Must be openly licensed, completely self-contaned so can directly run what you provide. Ideally use test_regress format, see https://veripool.org/guide/latest/contributing.html?highlight=test_regress#reporting-bugs
Can you attach an example that shows the issue? (Must be openly licensed, completely self-contained and self-checking so can directly run what you provide. Ideally use test_regress format, see https://veripool.org/guide/latest/contributing.html?highlight=test_regress#reporting-bugs
What 'verilator' command line do we use to run your example?

View File

@ -13,6 +13,6 @@ What would you like added/supported?
What 'verilator --version' are you using? Did you try it with the git master version?
Can you attach an example that runs on other simulators? (Must be openly licensed, ideally in test_regress format.)
Can you attach an example that runs on other simulators? (Must be openly licensed, completely self-contained and self-checking so can directly run what you provide. Ideally use test_regress format, see https://veripool.org/guide/latest/contributing.html?highlight=test_regress#reporting-bugs
May we assist you in trying to fix this in Verilator yourself?

View File

@ -12,15 +12,6 @@ on:
schedule:
- cron: '0 0 * * 0' # weekly
env:
CI_OS_NAME: linux
CI_COMMIT: ${{ github.sha }}
CCACHE_COMPRESS: 1
CCACHE_DIR: ${{ github.workspace }}/.ccache
CCACHE_LIMIT_MULTIPLE: 0.95
INSTALL_DIR: ${{ github.workspace }}/install
RELOC_DIR: ${{ github.workspace }}/relloc
defaults:
run:
shell: bash
@ -32,138 +23,155 @@ concurrency:
jobs:
build:
strategy:
fail-fast: false
matrix:
os: [ubuntu-24.04, ubuntu-22.04]
compiler:
- {cc: clang, cxx: clang++}
- {cc: gcc, cxx: g++}
runs-on: ${{ matrix.os }}
name: Build | ${{ matrix.os }} | ${{ matrix.compiler.cc }}
env:
CI_BUILD_STAGE_NAME: build
CI_RUNS_ON: ${{ matrix.os }}
CC: ${{ matrix.compiler.cc }}
CXX: ${{ matrix.compiler.cxx }}
CACHE_BASE_KEY: build-${{ matrix.os }}-${{ matrix.compiler.cc }}
CCACHE_MAXSIZE: 1000M # Per build matrix entry (* 5 = 5000M in total)
VERILATOR_ARCHIVE: verilator-${{ github.sha }}-${{ matrix.os }}-${{ matrix.compiler.cc }}.tar.gz
steps:
- name: Checkout
uses: actions/checkout@v4
with:
path: repo
- name: Cache $CCACHE_DIR
uses: actions/cache@v4
env:
CACHE_KEY: ${{ env.CACHE_BASE_KEY }}-ccache
with:
path: ${{ env.CCACHE_DIR }}
key: ${{ env.CACHE_KEY }}-${{ github.sha }}
restore-keys: |
${{ env.CACHE_KEY }}-
- name: Install packages for build
run: ./ci/ci-install.bash
- name: Build
run: ./ci/ci-script.bash
- name: Tar up repository
working-directory: ${{ github.workspace }}
run: tar --posix -c -z -f ${{ env.VERILATOR_ARCHIVE }} repo
- name: Upload tar archive
uses: actions/upload-artifact@v4
with:
path: ${{ github.workspace }}/${{ env.VERILATOR_ARCHIVE }}
name: ${{ env.VERILATOR_ARCHIVE }}
test:
needs: build
build-2404-gcc:
name: Build
uses: ./.github/workflows/reusable-build.yml
with:
os: ${{ matrix.os }}
cc: ${{ matrix.cc }}
strategy:
fail-fast: false
matrix:
include:
# Ubuntu 24.04 GCC
- {os: ubuntu-24.04, compiler: {cc: gcc, cxx: g++}, reloc: 0, suite: dist-vlt-0}
- {os: ubuntu-24.04, compiler: {cc: gcc, cxx: g++}, reloc: 0, suite: dist-vlt-1}
- {os: ubuntu-24.04, compiler: {cc: gcc, cxx: g++}, reloc: 0, suite: dist-vlt-2}
- {os: ubuntu-24.04, compiler: {cc: gcc, cxx: g++}, reloc: 0, suite: dist-vlt-3}
- {os: ubuntu-24.04, compiler: {cc: gcc, cxx: g++}, reloc: 0, suite: vltmt-0}
- {os: ubuntu-24.04, compiler: {cc: gcc, cxx: g++}, reloc: 0, suite: vltmt-1}
# Ubuntu 24.04 Clang
- {os: ubuntu-24.04, compiler: {cc: clang, cxx: clang++}, reloc: 0, suite: dist-vlt-0}
- {os: ubuntu-24.04, compiler: {cc: clang, cxx: clang++}, reloc: 0, suite: dist-vlt-1}
- {os: ubuntu-24.04, compiler: {cc: clang, cxx: clang++}, reloc: 0, suite: dist-vlt-2}
- {os: ubuntu-24.04, compiler: {cc: clang, cxx: clang++}, reloc: 0, suite: dist-vlt-3}
- {os: ubuntu-24.04, compiler: {cc: clang, cxx: clang++}, reloc: 0, suite: vltmt-0}
- {os: ubuntu-24.04, compiler: {cc: clang, cxx: clang++}, reloc: 0, suite: vltmt-1}
# Ubuntu 22.04 GCC
- {os: ubuntu-22.04, compiler: {cc: gcc, cxx: g++}, reloc: 0, suite: dist-vlt-0}
- {os: ubuntu-22.04, compiler: {cc: gcc, cxx: g++}, reloc: 0, suite: dist-vlt-1}
- {os: ubuntu-22.04, compiler: {cc: gcc, cxx: g++}, reloc: 0, suite: dist-vlt-2}
- {os: ubuntu-22.04, compiler: {cc: gcc, cxx: g++}, reloc: 0, suite: dist-vlt-3}
- {os: ubuntu-22.04, compiler: {cc: gcc, cxx: g++}, reloc: 0, suite: vltmt-0}
- {os: ubuntu-22.04, compiler: {cc: gcc, cxx: g++}, reloc: 0, suite: vltmt-1}
# Ubuntu 22.04 Clang, also test relocation
- {os: ubuntu-22.04, compiler: {cc: clang, cxx: clang++}, reloc: 1, suite: dist-vlt-0}
- {os: ubuntu-22.04, compiler: {cc: clang, cxx: clang++}, reloc: 1, suite: dist-vlt-1}
- {os: ubuntu-22.04, compiler: {cc: clang, cxx: clang++}, reloc: 1, suite: dist-vlt-2}
- {os: ubuntu-22.04, compiler: {cc: clang, cxx: clang++}, reloc: 1, suite: dist-vlt-3}
- {os: ubuntu-22.04, compiler: {cc: clang, cxx: clang++}, reloc: 1, suite: vltmt-0}
- {os: ubuntu-22.04, compiler: {cc: clang, cxx: clang++}, reloc: 1, suite: vltmt-1}
runs-on: ${{ matrix.os }}
name: Test | ${{ matrix.os }} | ${{ matrix.compiler.cc }} | ${{ matrix.reloc && 'reloc | ' || '' }} ${{ matrix.suite }}
env:
CI_BUILD_STAGE_NAME: test
CI_RUNS_ON: ${{ matrix.os }}
CI_RELOC: ${{ matrix.reloc }}
CC: ${{ matrix.compiler.cc }}
CXX: ${{ matrix.compiler.cxx }}
CACHE_BASE_KEY: test-${{ matrix.os }}-${{ matrix.compiler.cc }}-${{ matrix.reloc }}-${{ matrix.suite }}
CCACHE_MAXSIZE: 100M # Per build per suite (* 5 * 5 = 2500M in total)
VERILATOR_ARCHIVE: verilator-${{ github.sha }}-${{ matrix.os }}-${{ matrix.compiler.cc }}.tar.gz
steps:
- {os: ubuntu-24.04, cc: gcc}
- name: Download tar archive
uses: actions/download-artifact@v4
with:
name: ${{ env.VERILATOR_ARCHIVE }}
path: ${{ github.workspace }}
build-2404-clang:
name: Build
uses: ./.github/workflows/reusable-build.yml
with:
os: ${{ matrix.os }}
cc: ${{ matrix.cc }}
strategy:
fail-fast: false
matrix:
include:
- {os: ubuntu-24.04, cc: clang}
- name: Unpack tar archive
working-directory: ${{ github.workspace }}
run: tar -x -z -f ${{ env.VERILATOR_ARCHIVE }}
build-2204-gcc:
name: Build
uses: ./.github/workflows/reusable-build.yml
with:
os: ${{ matrix.os }}
cc: ${{ matrix.cc }}
strategy:
fail-fast: false
matrix:
include:
- {os: ubuntu-22.04, cc: gcc}
- name: Cache $CCACHE_DIR
uses: actions/cache@v4
env:
CACHE_KEY: ${{ env.CACHE_BASE_KEY }}-ccache2
with:
path: ${{ env.CCACHE_DIR }}
key: ${{ env.CACHE_KEY }}-${{ github.sha }}
restore-keys: |
${{ env.CACHE_KEY }}-
build-2204-clang:
name: Build
uses: ./.github/workflows/reusable-build.yml
with:
os: ${{ matrix.os }}
cc: ${{ matrix.cc }}
strategy:
fail-fast: false
matrix:
include:
- {os: ubuntu-22.04, cc: clang}
- name: Install test dependencies
run: ./ci/ci-install.bash
test-2404-gcc:
name: Test | ${{ matrix.os }} | ${{ matrix.cc }}
needs: build-2404-gcc
uses: ./.github/workflows/reusable-test.yml
with:
os: ${{ matrix.os }}
cc: ${{ matrix.cc }}
reloc: ${{ matrix.reloc }}
suite: ${{ matrix.suite }}
strategy:
fail-fast: false
matrix:
include:
# Ubuntu 24.04 gcc
- {os: ubuntu-24.04, cc: gcc, reloc: 0, suite: dist-vlt-0}
- {os: ubuntu-24.04, cc: gcc, reloc: 0, suite: dist-vlt-1}
- {os: ubuntu-24.04, cc: gcc, reloc: 0, suite: dist-vlt-2}
- {os: ubuntu-24.04, cc: gcc, reloc: 0, suite: dist-vlt-3}
- {os: ubuntu-24.04, cc: gcc, reloc: 0, suite: vltmt-0}
- {os: ubuntu-24.04, cc: gcc, reloc: 0, suite: vltmt-1}
- {os: ubuntu-24.04, cc: gcc, reloc: 0, suite: vltmt-2}
- name: Test
env:
TESTS: ${{ matrix.suite }}
run: ./ci/ci-script.bash
test-2404-clang:
name: Test | ${{ matrix.os }} | ${{ matrix.cc }}
needs: build-2404-clang
uses: ./.github/workflows/reusable-test.yml
with:
os: ${{ matrix.os }}
cc: ${{ matrix.cc }}
reloc: ${{ matrix.reloc }}
suite: ${{ matrix.suite }}
strategy:
fail-fast: false
matrix:
include:
# Ubuntu 24.04 clang
- {os: ubuntu-24.04, cc: clang, reloc: 0, suite: dist-vlt-0}
- {os: ubuntu-24.04, cc: clang, reloc: 0, suite: dist-vlt-1}
- {os: ubuntu-24.04, cc: clang, reloc: 0, suite: dist-vlt-2}
- {os: ubuntu-24.04, cc: clang, reloc: 0, suite: dist-vlt-3}
- {os: ubuntu-24.04, cc: clang, reloc: 0, suite: vltmt-0}
- {os: ubuntu-24.04, cc: clang, reloc: 0, suite: vltmt-1}
- {os: ubuntu-24.04, cc: clang, reloc: 0, suite: vltmt-2}
test-2204-gcc:
name: Test | ${{ matrix.os }} | ${{ matrix.cc }}
needs: build-2204-gcc
uses: ./.github/workflows/reusable-test.yml
with:
os: ${{ matrix.os }}
cc: ${{ matrix.cc }}
reloc: ${{ matrix.reloc }}
suite: ${{ matrix.suite }}
strategy:
fail-fast: false
matrix:
include:
# Ubuntu 22.04 gcc
- {os: ubuntu-22.04, cc: gcc, reloc: 0, suite: dist-vlt-0}
- {os: ubuntu-22.04, cc: gcc, reloc: 0, suite: dist-vlt-1}
- {os: ubuntu-22.04, cc: gcc, reloc: 0, suite: dist-vlt-2}
- {os: ubuntu-22.04, cc: gcc, reloc: 0, suite: dist-vlt-3}
- {os: ubuntu-22.04, cc: gcc, reloc: 0, suite: vltmt-0}
- {os: ubuntu-22.04, cc: gcc, reloc: 0, suite: vltmt-1}
- {os: ubuntu-22.04, cc: gcc, reloc: 0, suite: vltmt-2}
test-2204-clang:
name: Test | ${{ matrix.os }} | ${{ matrix.cc }}
needs: build-2204-clang
uses: ./.github/workflows/reusable-test.yml
with:
os: ${{ matrix.os }}
cc: ${{ matrix.cc }}
reloc: ${{ matrix.reloc }}
suite: ${{ matrix.suite }}
strategy:
fail-fast: false
matrix:
include:
# Ubuntu 22.04 clang, also test relocation
- {os: ubuntu-22.04, cc: clang, reloc: 1, suite: dist-vlt-0}
- {os: ubuntu-22.04, cc: clang, reloc: 1, suite: dist-vlt-1}
- {os: ubuntu-22.04, cc: clang, reloc: 1, suite: dist-vlt-2}
- {os: ubuntu-22.04, cc: clang, reloc: 1, suite: dist-vlt-3}
- {os: ubuntu-22.04, cc: clang, reloc: 1, suite: vltmt-0}
- {os: ubuntu-22.04, cc: clang, reloc: 1, suite: vltmt-1}
- {os: ubuntu-22.04, cc: clang, reloc: 1, suite: vltmt-2}
lint-py:
runs-on: ubuntu-22.04
name: Lint Python
env:
CI_OS_NAME: linux
CI_COMMIT: ${{ github.sha }}
CI_BUILD_STAGE_NAME: build
CI_RUNS_ON: ubuntu-22.04
CCACHE_COMPRESS: 1
CCACHE_DIR: ${{ github.workspace }}/.ccache
CCACHE_LIMIT_MULTIPLE: 0.95
strategy:
fail-fast: false
steps:
- name: Checkout
uses: actions/checkout@v4

View File

@ -76,11 +76,11 @@ jobs:
- name: Build and Push to Docker
uses: docker/build-push-action@v4
if: startsWith(github.ref, 'refs/tags/v')
if: startsWith(github.ref, 'refs/tags/v') || github.event_name == 'workflow_dispatch'
with:
context: ${{ env.build_context }}
build-args: SOURCE_COMMIT=${{ env.git_tag }}
platforms: linux/arm64,linux/amd64
push: ${{ !env.ACT && startsWith(github.ref, 'refs/tags/v') }}
push: ${{ !env.ACT && (startsWith(github.ref, 'refs/tags/v') || github.event_name == 'workflow_dispatch') }}
tags: ${{ steps.docker_meta.outputs.tags }}
labels: ${{ steps.docker_meta.outputs.labels }}

76
.github/workflows/reusable-build.yml vendored Normal file
View File

@ -0,0 +1,76 @@
---
# DESCRIPTION: Github actions config
# This name is key to badges in README.rst, so we use the name build
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
name: reusable-build
on:
workflow_call:
inputs:
os: # e.g. ubuntu-24.04
required: true
type: string
cc: # gcc or clang
required: true
type: string
env:
CI_OS_NAME: linux
CI_COMMIT: ${{ github.sha }}
CCACHE_COMPRESS: 1
CCACHE_DIR: ${{ github.workspace }}/.ccache
CCACHE_LIMIT_MULTIPLE: 0.95
INSTALL_DIR: ${{ github.workspace }}/install
RELOC_DIR: ${{ github.workspace }}/relloc
defaults:
run:
shell: bash
working-directory: repo
jobs:
build:
runs-on: ${{ inputs.os }}
name: Sub-build | ${{ inputs.os }} | ${{ inputs.cc }}
env:
CI_BUILD_STAGE_NAME: build
CI_RUNS_ON: ${{ inputs.os }}
CC: ${{ inputs.cc }}
CXX: ${{ inputs.cc == 'clang' && 'clang++' || 'g++' }}
CACHE_BASE_KEY: build-${{ inputs.os }}-${{ inputs.cc }}
CCACHE_MAXSIZE: 1000M # Per build matrix entry (* 5 = 5000M in total)
VERILATOR_ARCHIVE: verilator-${{ github.sha }}-${{ inputs.os }}-${{ inputs.cc }}.tar.gz
steps:
- name: Checkout
uses: actions/checkout@v4
with:
path: repo
- name: Cache $CCACHE_DIR
uses: actions/cache@v4
env:
CACHE_KEY: ${{ env.CACHE_BASE_KEY }}-ccache
with:
path: ${{ env.CCACHE_DIR }}
key: ${{ env.CACHE_KEY }}-${{ github.sha }}
restore-keys: |
${{ env.CACHE_KEY }}-
- name: Install packages for build
run: ./ci/ci-install.bash
- name: Build
run: ./ci/ci-script.bash
- name: Tar up repository
working-directory: ${{ github.workspace }}
run: tar --posix -c -z -f ${{ env.VERILATOR_ARCHIVE }} repo
- name: Upload tar archive
uses: actions/upload-artifact@v4
with:
path: ${{ github.workspace }}/${{ env.VERILATOR_ARCHIVE }}
name: ${{ env.VERILATOR_ARCHIVE }}

View File

@ -0,0 +1,73 @@
---
# DESCRIPTION: Github actions config
# This name is key to badges in README.rst, so we use the name build
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
name: reusable-rtlmeter-build
on:
workflow_call:
inputs:
runs-on:
description: "Runner to use, e.g.: ubuntu-24.04"
type: string
required: true
cc:
description: "Compiler to use: 'gcc' or 'clang'"
type: string
required: true
defaults:
run:
shell: bash
env:
CCACHE_DIR: ${{ github.workspace }}/ccache
CCACHE_MAXSIZE: 512M
jobs:
build:
runs-on: ${{ inputs.runs-on }}
name: Build
steps:
- name: Install dependencies
run: |
sudo apt update
sudo apt install ccache mold help2man libfl-dev libgoogle-perftools-dev libsystemc-dev
- name: Use saved ccache
uses: actions/cache@v4
with:
path: ccache
key: rtlmeter-build-ccache-${{ inputs.runs-on }}-${{ inputs.cc }}-${{ github.run_id }}-${{ github.run_attempt }}
restore-keys: rtlmeter-build-ccache-${{ inputs.runs-on }}-${{ inputs.cc }}
- name: Checkout
uses: actions/checkout@v4
with:
path: repo
fetch-depth: 0 # Required for 'git describe' used for 'verilator --version'
- name: Configure
working-directory: repo
run: |
autoconf
./configure --prefix=${{ github.workspace }}/install CXX=${{ inputs.cc == 'clang' && 'clang++' || 'g++' }}
- name: Make
working-directory: repo
run: make -j $(nproc)
- name: Install
working-directory: repo
run: make install
- name: Tar up installation
run: tar --posix -c -z -f verilator-rtlmeter.tar.gz install
- name: Upload Verilator installation archive
uses: actions/upload-artifact@v4
with:
path: verilator-rtlmeter.tar.gz
name: verilator-rtlmeter-${{ inputs.runs-on }}-${{ inputs.cc }}
overwrite: true

View File

@ -0,0 +1,118 @@
---
# DESCRIPTION: Github actions config
# This name is key to badges in README.rst, so we use the name build
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
name: reusable-rtlmeter-run
on:
workflow_call:
inputs:
runs-on:
description: "Runner to use, e.g.: ubuntu-24.04"
type: string
required: true
cc:
description: "Compiler to use: 'gcc' or 'clang'"
type: string
required: true
cases:
description: "RTLMeter cases to run"
type: string
required: true
compileArgs:
description: "Additional Verilator command line arguments"
type: string
default: ""
executeArgs:
description: "Additional simulator command line arguments"
type: string
default: ""
defaults:
run:
shell: bash
env:
CCACHE_DIR: ${{ github.workspace }}/ccache
CCACHE_MAXSIZE: 512M
CCACHE_DISABLE: 1
jobs:
run:
runs-on: ${{ inputs.runs-on }}
name: Run
steps:
- name: Install dependencies
run: |
sudo apt update
sudo apt install ccache mold libfl-dev libgoogle-perftools-dev libsystemc-dev
- name: Download Verilator installation archive
uses: actions/download-artifact@v4
with:
name: verilator-rtlmeter-${{ inputs.runs-on }}-${{ inputs.cc }}
- name: Unpack Verilator installation archive
run: |
tar -x -z -f verilator-rtlmeter.tar.gz
echo "${{ github.workspace }}/install/bin" >> $GITHUB_PATH
- name: Use saved ccache
if: ${{ env.CCACHE_DISABLE == 0 }}
uses: actions/cache@v4
with:
path: ${{ env.CCACHE_DIR }}
key: rtlmeter-run-ccache-${{ inputs.runs-on }}-${{ inputs.cc }}-${{ inputs.cases }}-${{ inputs.compileArgs }}-${{ github.run_id }}-${{ github.run_attempt }}
restore-keys: rtlmeter-run-ccache-${{ inputs.runs-on }}-${{ inputs.cc }}-${{ inputs.cases }}-${{ inputs.compileArgs }}
- name: Checkout RTLMeter
uses: actions/checkout@v4
with:
repository: "verilator/rtlmeter"
path: rtlmeter
- name: Setup RTLMeter venv
working-directory: rtlmeter
run: make venv
- name: Compile cases
working-directory: rtlmeter
run: |
./rtlmeter run --verbose --cases='${{ inputs.cases }}' --compileArgs='${{ inputs.compileArgs }}' --executeArgs='${{ inputs.executeArgs }}' --nExecute=0
# My YAML highlighter sucks, so I put this comment here wiht a phony closing quote mark to make it work: '
- name: Execute cases
working-directory: rtlmeter
continue-on-error: true # Do not fail on error, so we can at leat save the successful results
run: |
./rtlmeter run --verbose --cases='${{ inputs.cases }}' --compileArgs='${{ inputs.compileArgs }}' --executeArgs='${{ inputs.executeArgs }}'
# My YAML highlighter sucks, so I put this comment here wiht a phony closing quote mark to make it work: '
- name: Collate results
id: results
working-directory: rtlmeter
run: |
# 'inputs.cases' has special characters, use its md5sum as unique id
hash=$(md5sum <<< '${{ inputs.cases }}' | awk '{print $1}')
echo "hash=${hash}" >> $GITHUB_OUTPUT
./rtlmeter collate > ../results-${hash}.json
- name: Report results
working-directory: rtlmeter
run: |
./rtlmeter report --steps '*' --metrics '*' ../results-${{ steps.results.outputs.hash }}.json
- name: Upload results
uses: actions/upload-artifact@v4
with:
path: results-${{ steps.results.outputs.hash }}.json
name: rtlmeter-results-${{ inputs.runs-on }}-${{ inputs.cc }}-${{ steps.results.outputs.hash }}
overwrite: true
retention-days: 2
- name: Report status
working-directory: rtlmeter
run: | # This will fail the job if any of the runs failed
./rtlmeter run --verbose --cases='${{ inputs.cases }}' --compileArgs='${{ inputs.compileArgs }}' --executeArgs='${{ inputs.executeArgs }}'
# My YAML highlighter sucks, so I put this comment here wiht a phony closing quote mark to make it work: '

80
.github/workflows/reusable-test.yml vendored Normal file
View File

@ -0,0 +1,80 @@
---
# DESCRIPTION: Github actions config
# This name is key to badges in README.rst, so we use the name build
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
name: reusable-build
on:
workflow_call:
inputs:
os: # e.g. ubuntu-24.04
required: true
type: string
cc: # gcc or clang
required: true
type: string
reloc: # 0 or 1
required: true
type: number
suite: # e.g. dist-vlt-0
required: true
type: string
env:
CI_OS_NAME: linux
CI_COMMIT: ${{ github.sha }}
CCACHE_COMPRESS: 1
CCACHE_DIR: ${{ github.workspace }}/.ccache
CCACHE_LIMIT_MULTIPLE: 0.95
INSTALL_DIR: ${{ github.workspace }}/install
RELOC_DIR: ${{ github.workspace }}/relloc
defaults:
run:
shell: bash
working-directory: repo
jobs:
test:
runs-on: ${{ inputs.os }}
name: Sub-test | ${{ inputs.os }} | ${{ inputs.cc }} | ${{inputs.reloc && 'reloc | ' || '' }} ${{ inputs.suite }}
env:
CI_BUILD_STAGE_NAME: test
CI_RUNS_ON: ${{ inputs.os }}
CI_RELOC: ${{inputs.reloc }}
CC: ${{ inputs.cc }}
CXX: ${{ inputs.cc == 'clang' && 'clang++' || 'g++' }}
CACHE_BASE_KEY: test-${{ inputs.os }}-${{ inputs.cc }}-${{inputs.reloc }}-${{ inputs.suite }}
CCACHE_MAXSIZE: 100M # Per build per suite (* 5 * 5 = 2500M in total)
VERILATOR_ARCHIVE: verilator-${{ github.sha }}-${{ inputs.os }}-${{ inputs.cc }}.tar.gz
steps:
- name: Download tar archive
uses: actions/download-artifact@v4
with:
name: ${{ env.VERILATOR_ARCHIVE }}
path: ${{ github.workspace }}
- name: Unpack tar archive
working-directory: ${{ github.workspace }}
run: tar -x -z -f ${{ env.VERILATOR_ARCHIVE }}
- name: Cache $CCACHE_DIR
uses: actions/cache@v4
env:
CACHE_KEY: ${{ env.CACHE_BASE_KEY }}-ccache2
with:
path: ${{ env.CCACHE_DIR }}
key: ${{ env.CACHE_KEY }}-${{ github.sha }}
restore-keys: |
${{ env.CACHE_KEY }}-
- name: Install test dependencies
run: ./ci/ci-install.bash
- name: Test
env:
TESTS: ${{ inputs.suite }}
run: ./ci/ci-script.bash

158
.github/workflows/rtlmeter.yml vendored Normal file
View File

@ -0,0 +1,158 @@
---
# DESCRIPTION: Github actions config
# This name is key to badges in README.rst, so we use the name build
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
name: RTLMeter
on:
workflow_dispatch:
schedule:
- cron: '0 2 * * *' # Daily, starting at 02:00 UTC
defaults:
run:
shell: bash
concurrency:
group: RTLMeter
cancel-in-progress: false
jobs:
build-gcc:
name: Build GCC
uses: ./.github/workflows/reusable-rtlmeter-build.yml
with:
runs-on: ubuntu-24.04
cc: gcc
build-clang:
name: Build Clang
uses: ./.github/workflows/reusable-rtlmeter-build.yml
with:
runs-on: ubuntu-24.04
cc: clang
run-gcc:
name: Run GCC | ${{ matrix.cases }}
needs: build-gcc
uses: ./.github/workflows/reusable-rtlmeter-run.yml
with:
runs-on: ubuntu-24.04
cc: gcc
cases: ${{ matrix.cases }}
compileArgs: ""
executeArgs: ""
strategy:
fail-fast: false
max-parallel: 2
matrix:
cases:
- "NVDLA:*"
- "OpenPiton:1x1:*"
- "OpenPiton:2x2:*"
- "OpenPiton:4x4:*"
- "OpenTitan:*"
- "VeeR-EH1:asic*"
- "VeeR-EH1:default*"
- "VeeR-EH1:hiperf*"
- "VeeR-EH2:asic*"
- "VeeR-EH2:default*"
- "VeeR-EH2:hiperf*"
- "VeeR-EL2:asic*"
- "VeeR-EL2:default*"
- "VeeR-EL2:hiperf*"
- "Vortex:mini:*"
- "Vortex:sane:*"
# - "XiangShan:default-chisel3:* !*:linux"
# - "XiangShan:default-chisel6:* !*:linux"
- "XiangShan:mini-chisel3:* !*:linux"
# - "XiangShan:mini-chisel6:* !*:linux"
- "XuanTie-E902:*"
- "XuanTie-E906:*"
- "XuanTie-C906:*"
- "XuanTie-C910:*"
run-clang:
name: Run Clang | ${{ matrix.cases }}
needs: build-clang
uses: ./.github/workflows/reusable-rtlmeter-run.yml
with:
runs-on: ubuntu-24.04
cc: clang
cases: ${{ matrix.cases }}
compileArgs: "--threads 4"
executeArgs: ""
strategy:
fail-fast: false
max-parallel: 2
matrix:
cases:
- "NVDLA:*"
- "OpenPiton:1x1:*"
- "OpenPiton:2x2:*"
- "OpenPiton:4x4:*"
- "OpenTitan:*"
- "VeeR-EH1:asic*"
- "VeeR-EH1:default*"
- "VeeR-EH1:hiperf*"
- "VeeR-EH2:asic*"
- "VeeR-EH2:default*"
- "VeeR-EH2:hiperf*"
- "VeeR-EL2:asic*"
- "VeeR-EL2:default*"
- "VeeR-EL2:hiperf*"
- "Vortex:mini:*"
- "Vortex:sane:*"
- "XiangShan:default-chisel3:* !*:linux"
- "XiangShan:default-chisel6:* !*:linux"
- "XiangShan:mini-chisel3:* !*:linux"
- "XiangShan:mini-chisel6:* !*:linux"
- "XuanTie-E902:*"
- "XuanTie-E906:*"
- "XuanTie-C906:*"
- "XuanTie-C910:*"
combine-results:
name: Combine results
needs:
- run-gcc
- run-clang
if: ${{ always() }} # Run even if dependencies failed
runs-on: ubuntu-24.04
steps:
- name: Download all GCC results
uses: actions/download-artifact@v4
with:
pattern: rtlmeter-results-ubuntu-24.04-gcc-*
path: all-results-gcc-${{ github.run_id }}
merge-multiple: true
- name: Download all Clang results
uses: actions/download-artifact@v4
with:
pattern: rtlmeter-results-ubuntu-24.04-clang-*
path: all-results-clang-${{ github.run_id }}
merge-multiple: true
- name: Tar up results
run: |
# Ensure combined result directories exists in case of no results
mkdir -p all-results-gcc-${{ github.run_id }}
mkdir -p all-results-clang-${{ github.run_id }}
ls -la all-results*
# Tar up each directory
tar --posix -c -z -f all-results-gcc-${{ github.run_id }}.tar.gz all-results-gcc-${{ github.run_id }}
tar --posix -c -z -f all-results-clang-${{ github.run_id }}.tar.gz all-results-clang-${{ github.run_id }}
- name: Upload combined GCC results
uses: actions/upload-artifact@v4
with:
path: all-results-gcc-${{ github.run_id }}.tar.gz
name: "all-results-gcc"
overwrite: true
retention-days: 30
- name: Upload combined Clang results
uses: actions/upload-artifact@v4
with:
path: all-results-clang-${{ github.run_id }}.tar.gz
name: "all-results-clang"
overwrite: true
retention-days: 30

View File

@ -16,7 +16,7 @@ cmake_minimum_required(VERSION 3.15)
cmake_policy(SET CMP0091 NEW) # Use MSVC_RUNTIME_LIBRARY to select the runtime
project(
Verilator
VERSION 5.035
VERSION 5.037
HOMEPAGE_URL https://verilator.org
LANGUAGES CXX
)
@ -134,10 +134,7 @@ configure_package_config_file(
INSTALL_DESTINATION .
)
install(
FILES ${CMAKE_CURRENT_BINARY_DIR}/verilator-config.cmake
DESTINATION .
)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/verilator-config.cmake DESTINATION .)
configure_package_config_file(
verilator-config-version.cmake.in

68
Changes
View File

@ -8,26 +8,59 @@ The changes in each Verilator version are described below. The
contributors that suggested a given feature are shown in []. Thanks!
Verilator 5.035 devel
Verilator 5.037 devel
==========================
**Major:**
* Add `--trace-saif` for SAIF power traces (#5812). [Mateusz Gancarz]
* Change `--output-groups` to default to value of `--build-jobs` (#5751).
Those using build farms may need to now use `--output-groups 0` or otherwise.
**Other:**
* Add BADVLTPRAGMA on unknown Verilator pragmas (#5945). [Shou-Li Hsu]
* Add PROCINITASSIGN on initial assignments to process variables (#2481). [Niraj Menon]
* Fix filename backslash escapes in C code (#5947).
* Fix C++ widths in V3Expand (#5953) (#5975). [Geza Lore]
* Fix constant propagation of post-expand stages (#5955) (#5963) (#5969) (#5972) (#5983).
* Fix sign extension of signed compared with unsigned case items (#5968).
* Fix always processes ignoring $finish (#5971). [Hennadii Chernyshchyk]
* Fix streaming to/from packed arrays (#5976). [Geza Lore]
Verilator 5.036 2025-04-27
==========================
**Important:**
* Change `--output-groups` to default to value of `--build-jobs` (#5751).
Those using build farms may need to now use `--output-groups 0` or otherwise.
* Support user-defined primitives (UDPs) (#468) (#5807) (#5936). [Zhou Shen, Krzysztof Sychla, et al]
* Add `--trace-saif` for SAIF power traces (#5812) (#5914). [Mateusz Gancarz]
**Other:**
* Change `--trace` to `--trace-vcd`.
* Support simple `checker` blocks (#4066). [Srinivasan Venkataramanan]
* Support force/release with a variable reference (#5721) (#5810). [Bartłomiej Chmiel, Antmicro Ltd.]
* Support constraint random for StructArray (#5805) (#5937). [Yilou Wang]
* Support command-line overriding `define (#5900) (#5908). [Brian Li]
* Support soft unions (#5912) (#5932). [Robin Heinemann]
* Support `$setuphold` (#5884). [Krzysztof Sychla]
* Support assigning unpacked arrays to queues (#5924) (#5928). [Brian Li]
* Support `systemc_interface and related inside `class`.
* Support class extends with arguments.
* Add multi-thread hierarchical simulation (#2583) (#5871). [Bartłomiej Chmiel, Antmicro Ltd.]
* Add check for `let` misused in statement context (#5733).
* Add used language to `--preproc-resolve` output (#5795). [Kamil Rakoczy, Antmicro Ltd.]
* Add `--make json` to enable integration with non-make/cmake build systems (#5799). [Andrew Voznytsa]
* Add numactl-like automatic assignment of processor affinity (#5911).
* Add ccache support for generated cmake files (#5926) (#5930). [Andrew Voznytsa]
* Add visualization of multi-threaded waiting time with verilator_gantt (#5929). [Bartłomiej Chmiel, Antmicro Ltd.]
* Add suggesting isolate_assignments to UNOPTFLAT (#5942). [John Khoo]
* Add profiling of hierarchical mtasks with verilator_gantt (#5956). [Bartłomiej Chmiel, Antmicro Ltd.]
* Add empty veriuser.h for legacy compatibility.
* Add DEPRECATED warning on `--xml-only` and `--xml-output`.
* Remove unused gtkwave/wavealloca.h. [Geza Lore]
* Optimize automatic splitting of some packed variables (#5843). [Geza Lore]
* Optimize trigger vector in whole words (#5857). [Geza Lore]
* Fix parameters referencing interface fields (#1593) (#5910). [Ryszard Rozak, Antmicro Ltd.]
* Fix interface array assignments (#5270) (#5633) (#5869). [Nick Brereton]
* Fix change detection at time 0 (#5499) (#5864). [Geza Lore]
* Fix foreach of associative array inside a constraint block (#5727) (#5841). [Yilou Wang]
* Fix reset of automatic function variables (#5747). [Augustin Fabre]
@ -43,8 +76,9 @@ Verilator 5.035 devel
* Fix assignment pattern as function argument (#5839).
* Fix checking built-in method arguments (#5839).
* Fix splitting of packed ports with non-zero based ranges (#5842). [Geza Lore]
* Fix delays inside interface functions, and classes inside interfaces (#5846).
* Fix NBA shared flag reuse (#5848). [Geza Lore]
* Fix expression coverage on additional nodes (#5849 partial) (#5867). [Todd Strader]
* Fix multiple expression coverage issues (#5849 partial) (#5867) (#5870). [Todd Strader]
* Fix unresolved typedefs as parameters (#5850). [Eugene Feinberg, Brian Li]
* Fix removal of callbacks no longer in current list (#5851) (#5852). [Gilberto Abram]
* Fix segmentation fault on member compare (#5853).
@ -52,6 +86,22 @@ Verilator 5.035 devel
* Fix streaming of unpacked arrays concatenations (#5856). [Ryszard Rozak, Antmicro Ltd.]
* Fix Windows paths in Perl (#5858) (#5860). [Tobias Jensen]
* Fix algorithm header portability in V3Os.cpp (for std::replace) (#5861). [William D. Jones]
* Fix `$fscanf` not returning -1 on EOF (#5881).
* Fix PGO profiling for multi-threaded hierarchical scenarios (#5888). [Bartłomiej Chmiel, Antmicro Ltd.]
* Fix V3Gate assertion on eliminated circular logic (#5889) (#5898). [Geza Lore]
* Fix process comparisons (#5896).
* Fix ccache with clang (#5899). [Geza Lore]
* Fix delayed assignment malformed LHS assertion (#5904).
* Fix segfault in fork synchronization (#5906). [Krzysztof Bieganski, Antmicro Ltd.]
* Fix `new this` (#5909).
* Fix assignments with stream expressions and unpacked arrays (#5915). [Ryszard Rozak, Antmicro Ltd.]
* Fix LATCH warning for automatic variables (#5918). [Yutetsu TAKATSUKASA]
* Fix %% on elaboration severity tasks (#5922). [Ethan Sifferman]
* Fix port default values with `--coverage-line` creating `0=0` (#5920). [Drew Ranck]
* Fix vlSelf error on fork repeats (#5927). [Drew Ranck]
* Fix missing C++ regeneration when Verilog files are updated (#5934). [Zhouyi Shen]
* Fix stream expressions (#5938). [Ryszard Rozak, Antmicro Ltd.]
* Fix packed selection using over 32-bit index (#5957).
Verilator 5.034 2025-02-24
@ -299,7 +349,7 @@ Verilator 5.028 2024-08-21
* Add parsing but otherwise ignore std::randomize (#5354). [Arkadiusz Kozdra, Antmicro Ltd.]
* Add Verilated cc define when `--timing` used (#5383). [Kaleb Barrett]
* Improve emitted code to use a reference for VlSelf (#5254). [Yangyu Chen]
* Fix monitor block sensitivity items (#4400) (#5294). [Udaya Raj Subedi]
* Fix monitor block sensitivity items (#4040) (#4400) (#5294). [Udaya Raj Subedi]
* Fix fusing macro arguments to not ignore whitespace (#5061). [Tudor Timi]
* Fix optimized-out sensitivity trees with `--timing` (#5080) (#5349). [Krzysztof Bieganski, Antmicro Ltd.]
* Fix classes/modules of case-similar names (#5109). [Arkadiusz Kozdra]

View File

@ -528,6 +528,8 @@ GERSEMI_FLAGS = -i
format-cmake:
$(GERSEMI) $(GERSEMI_FLAGS) $(CMAKE_FILES)
format-yaml: yamlfix
PYLINT = pylint
PYLINT_FLAGS = --recursive=n --score=n --disable=R0801
PYLINT_TEST_FLAGS = $(PYLINT_FLAGS) --disable=C0103,C0114,C0116,C0209,C0411,C0413,C0301,R0801,R0912,R0915,R0916,R1702,W0511,W0621
@ -595,6 +597,8 @@ clean mostlyclean distclean maintainer-clean::
rm -f *.tex
rm -rf examples/*/obj_dir* examples/*/logs
rm -rf test_*/obj_dir
rm -rf src/*.tidy include/*.tidy examples/*/*.tidy
rm -rf .ruff_cache
rm -rf nodist/fuzzer/dictionary
rm -rf nodist/obj_dir
rm -rf verilator.txt

View File

@ -341,11 +341,12 @@ detailed descriptions of these arguments.
--no-debug-leak Disable leaking memory in --debug mode
--debugi <level> Enable debugging at a specified level
--debugi-<srcfile> <level> Enable debugging a source file at a level
--decorations <level> Set output comment and spacing level
--no-decoration Disable comments and lower spacing level
--decorations <level> Set output comment and spacing level
--default-language <lang> Default language to parse
+define+<var>=<value> Set preprocessor define
--dpi-hdr-only Only produce the DPI header file
--dump-<srcfile> Enable dumping everything in source file
--dump-defines Show preprocessor defines with -E
--dump-dfg Enable dumping DfgGraphs to .dot files
--dump-graph Enable dumping V3Graphs to .dot files
@ -353,12 +354,11 @@ detailed descriptions of these arguments.
--dump-tree-addrids Use short identifiers instead of addresses
--dump-tree-dot Enable dumping Ast .tree.dot debug files
--dump-tree-json Enable dumping Ast .tree.json files and .tree.meta.json file
--dump-<srcfile> Enable dumping everything in source file
--dumpi-<srcfile> <level> Enable dumping everything in source file at level
--dumpi-dfg <level> Enable dumping DfgGraphs to .dot files at level
--dumpi-graph <level> Enable dumping V3Graphs to .dot files at level
--dumpi-tree <level> Enable dumping Ast .tree files at level
--dumpi-tree-json <level> Enable dumping Ast .tree.json files at level
--dumpi-<srcfile> <level> Enable dumping everything in source file at level
-E Preprocess, but do not compile
--emit-accessors Emit getter and setter methods for model top class
--error-limit <value> Abort after this number of errors
@ -390,8 +390,8 @@ detailed descriptions of these arguments.
--no-json-edit-nums Don't dump editNum in .tree.json files
--no-json-ids Don't use short identifiers instead of adresses/paths in .tree.json
--json-only Create JSON parser output (.tree.json and .meta.json)
--json-only-output .tree.json output filename
--json-only-meta-output .tree.meta.json output filename
--json-only-output .tree.json output filename
--l2-name <value> Verilog scope name of the top module
--language <lang> Default language standard to parse
-LDFLAGS <flags> Linker pre-object arguments for makefile
@ -399,20 +399,20 @@ detailed descriptions of these arguments.
+libext+<ext>+[ext]... Extensions for finding modules
--lint-only Lint, but do not make output
--localize-max-size <value> Tune localize optimization variable size
--make <build-tool> Generate scripts for specified build tool
-MAKEFLAGS <flags> Arguments to pass to make during --build
--main Generate C++ main() file
--main-top-name Specify top name passed to Verilated model in generated C++ main
--make <build-tool> Generate scripts for specified build tool
-MAKEFLAGS <flags> Arguments to pass to make during --build
--max-num-width <value> Maximum number width (default: 64K)
--Mdir <directory> Name of output object directory
--MMD Create .d dependency files
--mod-prefix <topname> Name to prepend to lower classes
--MP Create phony dependency targets
+notimingchecks Ignored
-o <executable> Name of final executable
-O0 Disable optimizations
-O3 High-performance optimizations
-O<optimization-letter> Selectable optimizations
-o <executable> Name of final executable
--output-groups <numfiles> Group .cpp files into larger ones
--output-split <statements> Split .cpp files into pieces
--output-split-cfuncs <statements> Split model functions
@ -467,13 +467,13 @@ detailed descriptions of these arguments.
--threads <threads> Enable multithreading
--threads-dpi <mode> Enable multithreaded DPI
--threads-max-mtasks <mtasks> Tune maximum mtask partitioning
--timing Enable timing support
--no-timing Disable timing support
--timescale <timescale> Sets default timescale
--timescale-override <timescale> Overrides all timescales
--timing Enable timing support
--no-timing Disable timing support
--top <topname> Alias of --top-module
--top-module <topname> Name of top-level input module
--trace Enable waveform creation
--trace Enable VCD waveform creation
--trace-coverage Enable tracing of coverage
--trace-depth <levels> Depth of tracing
--trace-fst Enable FST waveform creation
@ -485,6 +485,7 @@ detailed descriptions of these arguments.
--trace-threads <threads> Enable FST waveform creation on separate threads
--no-trace-top Do not emit traces for signals in the top module generated by verilator
--trace-underscore Enable tracing of _signals
--trace-vcd Enable VCD waveform creation
-U<var> Undefine preprocessor define
--no-unlimited-stack Don't disable stack size limit
--unroll-count <loops> Tune maximum loop iterations
@ -493,8 +494,8 @@ detailed descriptions of these arguments.
-V Verbose version and config
-v <filename> Verilog library
--valgrind Run Verilator under valgrind
--verilate-jobs Job threads for Verilation stage
--no-verilate Skip Verilation and just compile previously Verilated code
--verilate-jobs Job threads for Verilation stage
+verilog1995ext+<ext> Synonym for +1364-1995ext+<ext>
+verilog2001ext+<ext> Synonym for +1364-2001ext+<ext>
--version Show program version and exits
@ -527,9 +528,9 @@ description of these arguments.
=for VL_SPHINX_EXTRACT "_build/gen/args_verilated.rst"
+verilator+coverage+file+<filename> Set coverage output filename
+verilator+debug Enable debugging
+verilator+debugi+<value> Enable debugging at a level
+verilator+coverage+file+<filename> Set coverage output filename
+verilator+error+limit+<value> Set error limit
+verilator+help Show help
+verilator+noassert Disable assert checking

View File

@ -8,17 +8,27 @@ import collections
import math
import re
import statistics
from collections import OrderedDict
# from pprint import pprint
Sections = []
Sections = OrderedDict()
LongestVcdStrValueLength = 0
Threads = collections.defaultdict(lambda: []) # List of records per thread id
Mtasks = collections.defaultdict(lambda: {'elapsed': 0, 'end': 0})
Cpus = collections.defaultdict(lambda: {'mtask_time': 0})
Global = {'args': {}, 'cpuinfo': collections.defaultdict(lambda: {}), 'stats': {}}
Global = {
'args': {},
'cpuinfo': collections.defaultdict(lambda: {}),
'info': {
'numa': 'no data'
},
'stats': {}
}
ElapsedTime = None # total elapsed time
ExecGraphTime = 0 # total elapsed time excuting an exec graph
ExecGraphTime = 0 # total elapsed time executing an exec graph
WaitingTime = 0 # total elapsed time waiting for mtasks
ExecGraphIntervals = [] # list of (start, end) pairs
ThreadScheduleWaitIntervals = [] # list of (start, tick, ecpu) pairs
######################################################################
@ -27,23 +37,29 @@ def read_data(filename):
with open(filename, "r", encoding="utf8") as fh:
re_thread = re.compile(r'^VLPROFTHREAD (\d+)$')
re_record = re.compile(r'^VLPROFEXEC (\S+) (\d+)(.*)$')
re_payload_mtaskBegin = re.compile(r'id (\d+) predictStart (\d+) cpu (\d+)')
re_payload_mtaskEnd = re.compile(r'id (\d+) predictCost (\d+)')
# The hierBlock argument is optional
re_payload_mtaskBegin = re.compile(
r'id (\d+) predictStart (\d+) cpu (\d+)(?: hierBlock)?\s*(\w+)?')
re_payload_mtaskEnd = re.compile(r'predictCost (\d+)')
re_payload_wait = re.compile(r'cpu (\d+)')
re_arg1 = re.compile(r'VLPROF arg\s+(\S+)\+([0-9.]*)\s*')
re_arg2 = re.compile(r'VLPROF arg\s+(\S+)\s+([0-9.]*)\s*$')
re_stat = re.compile(r'VLPROF stat\s+(\S+)\s+([0-9.]+)')
re_info = re.compile(r'VLPROF info\s+(\S+)\s+(.*)$')
re_stat = re.compile(r'VLPROF stat\s+(\S+)\s+(\S+)')
re_proc_cpu = re.compile(r'VLPROFPROC processor\s*:\s*(\d+)\s*$')
re_proc_dat = re.compile(r'VLPROFPROC ([a-z_ ]+)\s*:\s*(.*)$')
cpu = None
thread = 0
execGraphStart = None
global LongestVcdStrValueLength
global ExecGraphTime
global WaitingTime
ExecGraphStack = []
SectionStack = []
mTaskThread = {}
MtasksStack = []
ThreadScheduleWait = collections.defaultdict(list)
for line in fh:
recordMatch = re_record.match(line)
@ -60,44 +76,57 @@ def read_data(filename):
SectionStack.pop()
Sections[thread].append((tick, tuple(SectionStack)))
elif kind == "MTASK_BEGIN":
mtask, predict_start, ecpu = re_payload_mtaskBegin.match(payload).groups()
mtask, predict_start, ecpu, hier_block = re_payload_mtaskBegin.match(
payload).groups()
hier_block = "" if hier_block is None else hier_block
mtask = int(mtask)
predict_start = int(predict_start)
ecpu = int(ecpu)
mTaskThread[mtask] = thread
records = Threads[thread]
assert not records or records[-1]['start'] <= records[-1]['end'] <= tick
records.append({
'start': tick,
'mtask': mtask,
'predict_start': predict_start,
'hier_block': hier_block,
'cpu': ecpu
})
Mtasks[mtask]['begin'] = tick
Mtasks[mtask]['thread'] = thread
Mtasks[mtask]['predict_start'] = predict_start
Mtasks[(hier_block, mtask)]['begin'] = tick
Mtasks[(hier_block, mtask)]['predict_start'] = predict_start
Mtasks[(hier_block, mtask)]['thread'] = thread
MtasksStack.append((hier_block, mtask, records[-1]))
elif kind == "MTASK_END":
mtask, predict_cost = re_payload_mtaskEnd.match(payload).groups()
predict_cost, = re_payload_mtaskEnd.match(payload).groups()
mtask = int(mtask)
hier_block, mtask, record = MtasksStack.pop()
predict_cost = int(predict_cost)
begin = Mtasks[mtask]['begin']
record = Threads[mTaskThread[mtask]][-1]
begin = Mtasks[(hier_block, mtask)]['begin']
record['end'] = tick
assert record and records[-1]['start'] <= records[-1]['end'] <= tick
record['predict_cost'] = predict_cost
Mtasks[mtask]['elapsed'] += tick - begin
Mtasks[mtask]['predict_cost'] = predict_cost
Mtasks[mtask]['end'] = max(Mtasks[mtask]['end'], tick)
Mtasks[(hier_block, mtask)]['elapsed'] += tick - begin
Mtasks[(hier_block, mtask)]['predict_cost'] = predict_cost
Mtasks[(hier_block, mtask)]['end'] = max(Mtasks[(hier_block, mtask)]['end'],
tick)
elif kind == "THREAD_SCHEDULE_WAIT_BEGIN":
ecpu = int(re_payload_wait.match(payload).groups()[0])
ThreadScheduleWait[ecpu].append(tick)
elif kind == "THREAD_SCHEDULE_WAIT_END":
ecpu = int(re_payload_wait.match(payload).groups()[0])
start = ThreadScheduleWait[ecpu].pop()
WaitingTime += tick - start
ThreadScheduleWaitIntervals.append((start, tick, ecpu))
elif kind == "EXEC_GRAPH_BEGIN":
execGraphStart = tick
ExecGraphStack.append(tick)
elif kind == "EXEC_GRAPH_END":
assert ExecGraphStack, "EXEC_GRAPH_END without EXEC_GRAPH_BEGIN"
execGraphStart = ExecGraphStack.pop()
ExecGraphTime += tick - execGraphStart
ExecGraphIntervals.append((execGraphStart, tick))
execGraphStart = None
elif Args.debug:
print("-Unknown execution trace record: %s" % line)
elif re_thread.match(line):
thread = int(re_thread.match(line).group(1))
Sections.append([])
Sections[thread] = []
elif re.match(r'^VLPROF(THREAD|VERSION)', line):
pass
elif re_arg1.match(line):
@ -106,6 +135,9 @@ def read_data(filename):
elif re_arg2.match(line):
match = re_arg2.match(line)
Global['args'][match.group(1)] = match.group(2)
elif re_info.match(line):
match = re_info.match(line)
Global['info'][match.group(1)] = match.group(2)
elif re_stat.match(line):
match = re_stat.match(line)
Global['stats'][match.group(1)] = match.group(2)
@ -156,11 +188,13 @@ def report():
print("\nSummary:")
print(" Total elapsed time = {} rdtsc ticks".format(ElapsedTime))
print(" Parallelized code = {:.2%} of elapsed time".format(ExecGraphTime / ElapsedTime))
print(" Waiting time = {:.2%} of elapsed time".format(WaitingTime / ElapsedTime))
print(" Total threads = %d" % nthreads)
print(" Total CPUs used = %d" % ncpus)
print(" Total mtasks = %d" % len(Mtasks))
print(" Total yields = %d" % int(Global['stats'].get('yields', 0)))
report_numa()
report_mtasks()
report_cpus()
report_sections()
@ -181,6 +215,11 @@ def report():
print()
def report_numa():
print("\nNUMA assignment:")
print(" NUMA status = %s" % Global['info']['numa'])
def report_mtasks():
if not Mtasks:
return
@ -201,8 +240,8 @@ def report_mtasks():
long_mtask = None
predict_mtask_time = 0
predict_elapsed = 0
for mtaskId in Mtasks:
record = Mtasks[mtaskId]
for (hier_block, mtask_id) in Mtasks:
record = Mtasks[(hier_block, mtask_id)]
predict_mtask_time += record['predict_cost']
total_mtask_time += record['elapsed']
thread_mtask_time[record['thread']] += record['elapsed']
@ -210,7 +249,8 @@ def report_mtasks():
predict_elapsed = max(predict_elapsed, predict_end)
if record['elapsed'] > long_mtask_time:
long_mtask_time = record['elapsed']
long_mtask = mtaskId
long_mtask = mtask_id
long_mtask_hier_block = hier_block
Global['predict_last_end'] = predict_elapsed
serialTime = ElapsedTime - ExecGraphTime
@ -239,31 +279,52 @@ def report_mtasks():
max_p2e = -1000000
max_mtask = None
for mtask in sorted(Mtasks.keys()):
if Mtasks[mtask]['elapsed'] > 0:
if Mtasks[mtask]['predict_cost'] == 0:
Mtasks[mtask]['predict_cost'] = 1 # don't log(0) below
p2e_ratio = math.log(Mtasks[mtask]['predict_cost'] / Mtasks[mtask]['elapsed'])
for (hier_block, mtask_id) in sorted(Mtasks.keys()):
mtask = Mtasks[(hier_block, mtask_id)]
if mtask['elapsed'] > 0:
if mtask['predict_cost'] == 0:
mtask['predict_cost'] = 1 # don't log(0) below
p2e_ratio = math.log(mtask['predict_cost'] / mtask['elapsed'])
p2e_ratios.append(p2e_ratio)
if p2e_ratio > max_p2e:
max_p2e = p2e_ratio
max_mtask = mtask
max_mtask = mtask_id
max_hier_block = hier_block
if p2e_ratio < min_p2e:
min_p2e = p2e_ratio
min_mtask = mtask
min_mtask = mtask_id
min_hier_block = hier_block
print("\nMTask statistics:")
print(" Longest mtask id = {}".format(long_mtask))
if long_mtask_hier_block:
print(" Longest mtask id = {} from hier_block '{}'".format(long_mtask,
long_mtask_hier_block))
else:
print(" Longest mtask id = {}".format(long_mtask))
print(" Longest mtask time = {:.2%} of time elapsed in parallelized code".format(
long_mtask_time / ExecGraphTime))
print(" min log(p2e) = %0.3f" % min_p2e, end="")
print(" from mtask %d (predict %d," % (min_mtask, Mtasks[min_mtask]['predict_cost']), end="")
print(" elapsed %d)" % Mtasks[min_mtask]['elapsed'])
if min_hier_block:
print(" from hier_block '%s' mtask %d (predict %d," %
(min_hier_block, min_mtask, Mtasks[(min_hier_block, min_mtask)]['predict_cost']),
end="")
else:
print(" from mtask %d (predict %d," %
(min_mtask, Mtasks[(min_hier_block, min_mtask)]['predict_cost']),
end="")
print(" elapsed %d)" % Mtasks[(min_hier_block, min_mtask)]['elapsed'])
print(" max log(p2e) = %0.3f" % max_p2e, end="")
print(" from mtask %d (predict %d," % (max_mtask, Mtasks[max_mtask]['predict_cost']), end="")
print(" elapsed %d)" % Mtasks[max_mtask]['elapsed'])
if max_hier_block:
print(" from hier_block '%s' mtask %d (predict %d," %
(max_hier_block, max_mtask, Mtasks[(max_hier_block, max_mtask)]['predict_cost']),
end="")
else:
print(" from mtask %d (predict %d," %
(max_mtask, Mtasks[(max_hier_block, max_mtask)]['predict_cost']),
end="")
print(" elapsed %d)" % Mtasks[(max_hier_block, max_mtask)]['elapsed'])
stddev = statistics.pstdev(p2e_ratios)
mean = statistics.mean(p2e_ratios)
@ -308,7 +369,7 @@ def report_cpus():
def report_sections():
for thread, section in enumerate(Sections):
for thread, section in Sections.items():
if section:
print(f"\nSection profile for thread {thread}:")
report_section(section)
@ -403,6 +464,9 @@ def write_vcd(filename):
val = buf.ljust(LongestVcdStrValueLength * 8, "0")
values[time][code] = val
def addXValue(code, time):
values[time][code] = 'x'
# Measured graph
for thread in sorted(Threads):
mcode = getCode(32, 'measured', 't%d_mtask' % thread)
@ -427,27 +491,36 @@ def write_vcd(filename):
tStart = sorted(_['start'] for records in Threads.values() for _ in records)
tEnd = sorted(_['end'] for records in Threads.values() for _ in records)
# Measured waiting time
for (start, end, cpu) in ThreadScheduleWaitIntervals:
mcode = getCode(32, 'measured', 'cpu%d_waiting' % cpu)
addXValue(mcode, start)
addValue(mcode, end, None)
# Predicted graph
for start, end in ExecGraphIntervals:
# Find the earliest MTask start after the start point, and the
# latest MTask end before the end point, so we can scale to the
# same range
start = tStart[bisect.bisect_left(tStart, start)]
tStartIdx = bisect.bisect_left(tStart, start)
if tStartIdx >= len(tStart):
continue
start = tStart[tStartIdx]
end = tEnd[bisect.bisect_right(tEnd, end) - 1]
# Compute scale so predicted graph is of same width as interval
measured_scaling = (end - start) / Global['predict_last_end']
# Predict mtasks that fill the time the execution occupied
for mtask in Mtasks:
thread = Mtasks[mtask]['thread']
pred_scaled_start = start + int(Mtasks[mtask]['predict_start'] * measured_scaling)
for (hier_block, mtask_id) in Mtasks:
mtask = Mtasks[(hier_block, mtask_id)]
thread = mtask['thread']
pred_scaled_start = start + int(mtask['predict_start'] * measured_scaling)
pred_scaled_end = start + int(
(Mtasks[mtask]['predict_start'] + Mtasks[mtask]['predict_cost']) *
measured_scaling)
(mtask['predict_start'] + mtask['predict_cost']) * measured_scaling)
if pred_scaled_start == pred_scaled_end:
continue
mcode = getCode(32, 'predicted', 't%d_mtask' % thread)
addValue(mcode, pred_scaled_start, mtask)
addValue(mcode, pred_scaled_start, mtask_id)
addValue(mcode, pred_scaled_end, None)
parallelism['predicted'][pred_scaled_start] += 1
@ -462,7 +535,7 @@ def write_vcd(filename):
addValue(pcode, time, value)
# Section graph
for thread, section in enumerate(Sections):
for thread, section in Sections.items():
if section:
scode = getCode(LongestVcdStrValueLength * 8, "section", f"t{thread}_trace")
dcode = getCode(32, "section", f"t{thread}_depth")
@ -510,6 +583,8 @@ def write_vcd(filename):
value = values[time][code]
if value is None:
fh.write("bz v%x\n" % code)
elif value == 'x':
fh.write("bx v%x\n" % code)
elif isinstance(value, str):
fh.write("b%s v%x\n" % (value, code))
else:

View File

@ -55,16 +55,16 @@ if [ "$CI_BUILD_STAGE_NAME" = "build" ]; then
sudo apt-get update
sudo apt-get install ccache help2man libfl-dev ||
sudo apt-get install ccache help2man libfl-dev
if [ "$CI_RUNS_ON" != "ubuntu-22.04" ]; then
if [[ ! "$CI_RUNS_ON" =~ "ubuntu-22.04" ]]; then
# Some conflict of libunwind verison on 22.04, can live without it for now
sudo apt-get install libgoogle-perftools-dev ||
sudo apt-get install libgoogle-perftools-dev
fi
if [ "$CI_RUNS_ON" = "ubuntu-20.04" ] || [ "$CI_RUNS_ON" = "ubuntu-22.04" ] || [ "$CI_RUNS_ON" = "ubuntu-24.04" ]; then
if [[ "$CI_RUNS_ON" =~ "ubuntu-20.04" ]] || [[ "$CI_RUNS_ON" =~ "ubuntu-22.04" ]] || [[ "$CI_RUNS_ON" =~ "ubuntu-24.04" ]]; then
sudo apt-get install libsystemc libsystemc-dev ||
sudo apt-get install libsystemc libsystemc-dev
fi
if [ "$CI_RUNS_ON" = "ubuntu-22.04" ] || [ "$CI_RUNS_ON" = "ubuntu-24.04" ]; then
if [[ "$CI_RUNS_ON" =~ "ubuntu-22.04" ]] || [[ "$CI_RUNS_ON" =~ "ubuntu-24.04" ]]; then
sudo apt-get install bear mold ||
sudo apt-get install bear mold
fi
@ -92,11 +92,11 @@ elif [ "$CI_BUILD_STAGE_NAME" = "test" ]; then
sudo apt-get install gdb gtkwave lcov libfl-dev ccache jq z3 ||
sudo apt-get install gdb gtkwave lcov libfl-dev ccache jq z3
# Required for test_regress/t/t_dist_attributes.py
if [ "$CI_RUNS_ON" = "ubuntu-22.04" ] || [ "$CI_RUNS_ON" = "ubuntu-24.04" ]; then
if [[ "$CI_RUNS_ON" =~ "ubuntu-22.04" ]] || [[ "$CI_RUNS_ON" =~ "ubuntu-24.04" ]]; then
sudo apt-get install python3-clang mold ||
sudo apt-get install python3-clang mold
fi
if [ "$CI_RUNS_ON" = "ubuntu-20.04" ] || [ "$CI_RUNS_ON" = "ubuntu-22.04" ] || [ "$CI_RUNS_ON" = "ubuntu-24.04" ]; then
if [[ "$CI_RUNS_ON" =~ "ubuntu-20.04" ]] || [[ "$CI_RUNS_ON" =~ "ubuntu-22.04" ]] || [[ "$CI_RUNS_ON" =~ "ubuntu-24.04" ]]; then
sudo apt-get install libsystemc-dev ||
sudo apt-get install libsystemc-dev
fi

View File

@ -87,7 +87,7 @@ elif [ "$CI_BUILD_STAGE_NAME" = "test" ]; then
fi
# Run sanitize on Ubuntu 22.04 only
( [ "$CI_RUNS_ON" = 'ubuntu-22.04' ] || [ "$CI_RUNS_ON" = 'ubuntu-24.04' ] ) && sanitize='--sanitize' || sanitize=''
( [[ "$CI_RUNS_ON" =~ 'ubuntu-22.04' ]] || [[ "$CI_RUNS_ON" =~ 'ubuntu-24.04' ]] ) && sanitize='--sanitize' || sanitize=''
TEST_REGRESS=test_regress
if [ "$CI_RELOC" == 1 ]; then
@ -109,22 +109,25 @@ elif [ "$CI_BUILD_STAGE_NAME" = "test" ]; then
ccache -z
case $TESTS in
dist-vlt-0)
"$MAKE" -C "$TEST_REGRESS" SCENARIOS="--dist --vlt $sanitize" DRIVER_HASHSET=--hashset=0/4
"$MAKE" -C "$TEST_REGRESS" SCENARIOS="--dist --vlt --driver-clean $sanitize" DRIVER_HASHSET=--hashset=0/4
;;
dist-vlt-1)
"$MAKE" -C "$TEST_REGRESS" SCENARIOS="--dist --vlt $sanitize" DRIVER_HASHSET=--hashset=1/4
"$MAKE" -C "$TEST_REGRESS" SCENARIOS="--dist --vlt --driver-clean $sanitize" DRIVER_HASHSET=--hashset=1/4
;;
dist-vlt-2)
"$MAKE" -C "$TEST_REGRESS" SCENARIOS="--dist --vlt $sanitize" DRIVER_HASHSET=--hashset=2/4
"$MAKE" -C "$TEST_REGRESS" SCENARIOS="--dist --vlt --driver-clean $sanitize" DRIVER_HASHSET=--hashset=2/4
;;
dist-vlt-3)
"$MAKE" -C "$TEST_REGRESS" SCENARIOS="--dist --vlt $sanitize" DRIVER_HASHSET=--hashset=3/4
"$MAKE" -C "$TEST_REGRESS" SCENARIOS="--dist --vlt --driver-clean $sanitize" DRIVER_HASHSET=--hashset=3/4
;;
vltmt-0)
"$MAKE" -C "$TEST_REGRESS" SCENARIOS=--vltmt DRIVER_HASHSET=--hashset=0/2
"$MAKE" -C "$TEST_REGRESS" SCENARIOS="--vltmt --driver-clean" DRIVER_HASHSET=--hashset=0/3
;;
vltmt-1)
"$MAKE" -C "$TEST_REGRESS" SCENARIOS=--vltmt DRIVER_HASHSET=--hashset=1/2
"$MAKE" -C "$TEST_REGRESS" SCENARIOS="--vltmt --driver-clean" DRIVER_HASHSET=--hashset=1/3
;;
vltmt-2)
"$MAKE" -C "$TEST_REGRESS" SCENARIOS="--vltmt --driver-clean" DRIVER_HASHSET=--hashset=2/3
;;
coverage-all)
nodist/code_coverage --stages 1-

View File

@ -10,7 +10,7 @@
# Then 'make maintainer-dist'
#AC_INIT([Verilator],[#.### YYYY-MM-DD])
#AC_INIT([Verilator],[#.### devel])
AC_INIT([Verilator],[5.035 devel],
AC_INIT([Verilator],[5.037 devel],
[https://verilator.org],
[verilator],[https://verilator.org])
@ -432,6 +432,7 @@ AC_SUBST(HAVE_COROUTINES)
# Flags for compiling Verilator internals including parser always
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-Qunused-arguments)
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-Xclang -fno-pch-timestamp)
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-faligned-new)
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-Wno-unused-parameter)
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-Wno-shadow)
@ -469,6 +470,7 @@ CFG_CXX_FLAGS_CMAKE="-faligned-new"
m4_foreach([cflag],[
[-fbracket-depth=4096],
[-fcf-protection=none],
[-Xclang -fno-pch-timestamp],
[-mno-cet],
[-Qunused-arguments],
[-Wno-bool-operation],

View File

@ -26,6 +26,7 @@ Arkadiusz Kozdra
Arthur Rosa
Aylon Chaim Porat
Bartłomiej Chmiel
Brian Li
Cameron Kirk
Chih-Mao Chen
Chris Bachhuber
@ -109,6 +110,7 @@ Jiuyang Liu
Joey Liu
John Coiner
John Demme
John Khoo
John Wehle
Jonathan Drolet
Jonathan Schröter
@ -134,6 +136,7 @@ Krzysztof Boronski
Krzysztof Boroński
Krzysztof Obłonczek
Krzysztof Starecki
Krzysztof Sychla
Kuba Ober
Larry Doolittle
Liam Braun
@ -194,6 +197,7 @@ Ricardo Barbedo
Richard Myers
Risto Pejašinović
Robert Balas
Robin Heinemann
Rupert Swarbrick
Ryan Ziegler
Ryszard Rozak
@ -246,6 +250,7 @@ Yutetsu TAKATSUKASA
Yves Mathieu
Zhanglei Wang
Zhou Shen
Zhouyi Shen
Zixi Li
أحمد المحمودي
404allen404

View File

@ -77,6 +77,7 @@ help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS)
clean mostlyclean distclean maintainer-clean::
rm -rf _build
rm -f $(SCRIPTS) *.tmp
rm -f *.aux *.cp *.cps *.dvi *.fn *.fns *.ky *.kys *.log
rm -f *.pg *.pgs *.toc *.tp *.tps *.vr *.vrs *.idx

View File

@ -0,0 +1,5 @@
.. comment: generated by t_lint_badvltpragma_bad
.. code-block:: sv
:emphasize-lines: 1
// verilator lintt_off WIDTH //<--- Warning (lint_off misspelled)

View File

@ -0,0 +1,7 @@
.. comment: generated by t_lint_badvltpragma_bad
.. code-block::
:emphasize-lines: 1,2
%Error-BADVLTPRAGMA: example.v:1:4 Unknown verilator comment: '/*verilator lintt_off WIDTH <--- Warning (lint_off misspelled)*/'
7 | /*verilator lintt_off WIDTH <--- Warning (lint_off misspelled)*/
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -1,4 +1,4 @@
.. comment: generated by t_lint_pinmissing_bad
.. code-block::
%Warning-PINMISSING: example.v:1:8 Cell has missing pin: 'port'
%Warning-PINMISSING: example.v:1:8 Instance has missing pin: 'port'

View File

@ -0,0 +1,12 @@
.. comment: generated by t_lint_procassinit_bad
.. code-block:: sv
:linenos:
:emphasize-lines: 1,5
logic flop_out = 1; // <--- Warning
always @(posedge clk, negedge reset_l) begin
if (enable) begin
flop_out <= ~in; // <--- Use of initialized
end
end

View File

@ -0,0 +1,15 @@
.. comment: generated by t_lint_procassinit_bad
.. code-block:: sv
:linenos:
:emphasize-lines: 5
logic flop2_out;
always @(posedge clk, negedge reset_l) begin
if (!reset_l) begin
flop2_out <= '1; // <--- Added reset init
end
else if (enable) begin
flop2_out <= ~in;
end
end

View File

@ -0,0 +1,12 @@
.. comment: generated by t_lint_procassinit_bad
.. code-block::
%Warning-PROCASSINIT: example.v:1:21 Procedural assignment to declaration with initial value: 'flop_out'
: ... note: In instance 't'
: ... Location of variable initialization
26 | logic flop_out = 1;
| ^
example.v:1:10 ... Location of variable process write
: ... Perhaps should initialize instead using a reset in this process
30 | flop_out <= ~in;
| ^~~~~~~~

View File

@ -169,15 +169,7 @@ latex_elements = {
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
# latex_documents = [
# (
# master_doc,
# "Verilog-to-Routing.tex",
# "Verilog-to-Routing Documentation",
# "VTR Developers",
# "manual",
# ),
# ]
# latex_documents = [ ... ]
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.

View File

@ -73,8 +73,8 @@ often inlined into the root scope) will need to be updated as follows:
:code:`$` character, i.e.: :code:`rootp` points to the Verilated
SystemVerilog :code:`$root` scope.
* Replace :code:`modelp->internal->member->lookup` references with
:code:`modelp->rootp->internal->member->lookup` references, which
* Replace :code:`modelp->internal->member` references with
:code:`modelp->rootp->internal->member` references, which
contain one additional indirection via the :code:`rootp` pointer.

View File

@ -72,7 +72,7 @@ and the design can be easily manually reduced. In other cases, the bug is
caused by a complex interaction of many parts of the design, and it is not
clear which parts are necessary to reproduce the bug. In these cases, an
Open Source tool called `sv-bugpoint
<https://github.com/antmicro/sv-bugpoint>_` can be used to automatically
<https://github.com/antmicro/sv-bugpoint>`_ can be used to automatically
reduce a SystemVerilog design to the smallest possible reproducer.
It can be used to automatically reduce a design with hundreds of thousands of
lines to a minimal test case while preserving the bug-inducing behavior.

View File

@ -47,6 +47,11 @@ Summary:
Display help and exit.
.. option:: +verilator+noassert
Disable assert checking per runtime argument. This is the same as
calling :code:`VerilatedContext*->assertOn(false)` in the model.
.. option:: +verilator+prof+exec+file+<filename>
When a model was Verilated using :vlopt:`--prof-exec`, sets the
@ -110,11 +115,6 @@ Summary:
simulation runtime random seed value. If zero or not specified picks a
value from the system random number generator.
.. option:: +verilator+noassert
Disable assert checking per runtime argument. This is the same as
calling :code:`VerilatedContext*->assertOn(false)` in the model.
.. option:: +verilator+V
Shows the verbose version, including configuration information.

View File

@ -1,6 +1,7 @@
.. Copyright 2003-2025 by Wilson Snyder.
.. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
===================
verilator Arguments
===================
@ -11,20 +12,6 @@ Summary:
.. include:: ../_build/gen/args_verilator.rst
.. option:: <file.v>
Specifies the Verilog file containing the top module to be Verilated.
.. option:: <file.c/.cc/.cpp/.cxx>
Used with :vlopt:`--exe` to specify optional C++ files to be linked in
with the Verilog code. The file path should either be absolute, or
relative to where the make will be executed from, or add to your
makefile's VPATH the appropriate directory to find the file.
See also :vlopt:`-CFLAGS` and :vlopt:`-LDFLAGS` options, which are
useful when the C++ files need special compiler flags.
.. option:: <file.a/.o/.so>
Specifies optional object or library files to be linked with the
@ -37,6 +24,20 @@ Summary:
rule that uses these files when linking the module's executable. This
generally is only useful when used with the :vlopt:`--exe` option.
.. option:: <file.c/.cc/.cpp/.cxx>
Used with :vlopt:`--exe` to specify optional C++ files to be linked in
with the Verilog code. The file path should either be absolute, or
relative to where the make will be executed from, or add to your
makefile's VPATH the appropriate directory to find the file.
See also :vlopt:`-CFLAGS` and :vlopt:`-LDFLAGS` options, which are
useful when the C++ files need special compiler flags.
.. option:: <file.v>
Specifies the Verilog file containing the top module to be Verilated.
.. option:: +1364-1995ext+<ext>
.. option:: +1364-2001ext+<ext>
@ -182,7 +183,7 @@ Summary:
With :vlopt:`--clk`, the specified signal is marked as a clock signal.
The provided signal name is specified using a RTL hierarchy path. For
example, v.foo.bar. If the signal is the input to top-module, then
example, v.foo.bar. If the signal is the input to the top-module, then
directly provide the signal name. Alternatively, use a
:option:`/*verilator&32;clocker*/` metacomment in RTL file to mark the
signal directly.
@ -331,11 +332,11 @@ Summary:
detailed messages. See :vlopt:`--debug` for other implications of
enabling debug.
.. option:: --decorations none
.. option:: --no-decoration
.. option:: --decorations medium
Alias for ``--decorations none``.
.. option:: --decorations node
.. option:: --decorations <level>
When creating output Verilated code, set level of comment and whitespace
decoration.
@ -362,10 +363,6 @@ Summary:
between different Verilator runs, this may harm compile caching and
should only be used for debug.
.. option:: --no-decoration
Alias for ``--decorations none``.
.. option:: --default-language <value>
Select the language used by default when first processing each
@ -402,6 +399,11 @@ Summary:
name or location of the emitted DPI header file, it is output in
:vlopt:`--Mdir` as it would be without this option.
.. option:: --dump-<srcfile>
Rarely needed - for developer use. Enable all dumping in the given
source file at level 3.
.. option:: --dump-defines
With :vlopt:`-E`, suppress normal output, and instead print a list of
@ -433,18 +435,6 @@ Summary:
:vlopt:`--debug --no-dump-tree <--dump-tree>` may be useful if the dump
files are large and not desired.
.. option:: --dump-tree-json
Rarely needed. Enable dumping Ast .json.tree debug files with dumping level 3,
which dumps the standard critical stages. For details on the format, see
the Verilator Internals manual.
.. option:: --dump-tree-dot
Rarely needed. Enable dumping Ast .tree.dot debug files in Graphviz
Dot format. This option implies :vlopt:`--dump-tree`, unless
:vlopt:`--dumpi-tree` was passed explicitly.
.. option:: --dump-tree-addrids
Rarely needed - for developer use. Replace AST node addresses with
@ -454,10 +444,24 @@ Summary:
by a newly allocated node after a node with the same address has been
dumped and then freed.
.. option:: --dump-<srcfile>
.. option:: --dump-tree-dot
Rarely needed - for developer use. Enable all dumping in the given
source file at level 3.
Rarely needed. Enable dumping Ast .tree.dot debug files in Graphviz
Dot format. This option implies :vlopt:`--dump-tree`, unless
:vlopt:`--dumpi-tree` was passed explicitly.
.. option:: --dump-tree-json
Rarely needed. Enable dumping Ast .json.tree debug files with dumping level 3,
which dumps the standard critical stages. For details on the format, see
the Verilator Internals manual.
.. option:: --dumpi-<srcfile> <level>
Rarely needed - for developer use. Set the dumping level in the
specified Verilator source file to the specified value (e.g.,
`--dumpi-V3Order 9`). Level 0 disables dumps and is equivalent to
`--no-dump-<srcfile>`. Level 9 enables the dumping of everything.
.. option:: --dumpi-dfg <level>
@ -479,13 +483,6 @@ Summary:
Rarely needed - for developer use. Set internal Ast JSON dumping level
globally to the specified value.
.. option:: --dumpi-<srcfile> <level>
Rarely needed - for developer use. Set the dumping level in the
specified Verilator source file to the specified value (e.g.,
`--dumpi-V3Order 9`). Level 0 disables dumps and is equivalent to
`--no-dump-<srcfile>`. Level 9 enables the dumping of everything.
.. option:: -E
Preprocess the source code, but do not compile, similar to C++
@ -569,7 +566,7 @@ Summary:
.. option:: -fno-const
.. options: -fno-const-before-dfg
.. option:: -fno-const-before-dfg
Do not apply any global expression folding prior to the DFG pass. This
option is solely for the purpose of DFG testing and should not be used
@ -592,14 +589,14 @@ Summary:
Disable individual DFG peephole optimizer pattern.
.. option:: -fno-dfg-pre-inline
Do not apply the DFG optimizer before inlining.
.. option:: -fno-dfg-post-inline
Do not apply the DFG optimizer after inlining.
.. option:: -fno-dfg-pre-inline
Do not apply the DFG optimizer before inlining.
.. option:: -fno-expand
.. option:: -fno-func-opt
@ -724,14 +721,6 @@ Summary:
Generate a true-random key suitable for use with :vlopt:`--protect-key`,
print it, and exit immediately.
.. option:: --getenv <variable>
If the variable is declared in the environment, print it and exit
immediately. Otherwise, if it's built into Verilator
(e.g., VERILATOR_ROOT), print that and exit immediately. Otherwise, print
a newline and exit immediately. This can be useful in makefiles. See
also :vlopt:`-V`, and the various :file:`*.mk` files.
.. option:: --get-supported <feature>
If the given feature is supported, print "1" and exit
@ -741,6 +730,14 @@ Summary:
Feature may be one of the following: COROUTINES, SYSTEMC.
.. option:: --getenv <variable>
If the variable is declared in the environment, print it and exit
immediately. Otherwise, if it's built into Verilator
(e.g., VERILATOR_ROOT), print that and exit immediately. Otherwise, print
a newline and exit immediately. This can be useful in makefiles. See
also :vlopt:`-V`, and the various :file:`*.mk` files.
.. option:: --help
Displays this message and program version and exits.
@ -803,6 +800,15 @@ Summary:
must be a positive integer specifying the maximum number of parallel
build jobs.
.. option:: --no-json-edit-nums
Don't dump edit number in .tree.json files. This may make the file more
run-to-run stable for easier comparison.
.. option:: --no-json-ids
Don't use short identifiers instead of addresses/paths in .tree.json.
.. option:: --json-only
Create JSON output only, do not create any other output.
@ -826,15 +832,6 @@ Summary:
Specifies the filename for the main output file (`.tree.json`) of --json-only.
Using this option automatically sets :vlopt:`--json-only`.
.. option:: --no-json-edit-nums
Don't dump edit number in .tree.json files. This may make the file more
run-to-run stable for easier comparison.
.. option:: --no-json-ids
Don't use short identifiers instead of addresses/paths in .tree.json.
.. option:: --l2-name <value>
Instead of using the module name when showing Verilog scope, use the
@ -908,30 +905,6 @@ Summary:
Rarely needed. Set the maximum variable size in bytes for it to be
subject to localizing-to-stack optimization. Defaults to 1024.
.. option:: --make <build-tool>
Generates a script for the specified build tool.
Supported values are ``gmake`` for GNU Make, or ``cmake`` for CMake, or
``json`` to create a JSON file to feed other build tools.
Multiple options can be specified together. If no build tool is
specified, gmake is assumed. The executable of gmake can be configured
via the environment variable :option:`MAKE`.
When using :vlopt:`--build`, Verilator takes over the responsibility of
building the model library/executable. For this reason :option:`--make`
cannot be specified when using :vlopt:`--build`.
.. option:: -MAKEFLAGS <string>
When using :vlopt:`--build`, add the specified argument to the invoked
make command line. For multiple flags, either pass them as a single
argument with space separators quoted in the shell (e.g. ``-MAKEFLAGS
"-a -b"``), or use multiple -MAKEFLAGS arguments
(e.g. ``-MAKEFLAGS -l -MAKEFLAGS -k``). Use of this option should not be
required for simple builds using the host toolchain.
.. option:: --main
Generates a top-level C++ main() file that supports parsing arguments,
@ -957,6 +930,30 @@ Summary:
If the string ``"-"`` is used, no top level scope is added.
.. option:: --make <build-tool>
Generates a script for the specified build tool.
Supported values are ``gmake`` for GNU Make, or ``cmake`` for CMake, or
``json`` to create a JSON file to feed other build tools.
Multiple options can be specified together. If no build tool is
specified, gmake is assumed. The executable of gmake can be configured
via the environment variable :option:`MAKE`.
When using :vlopt:`--build`, Verilator takes over the responsibility of
building the model library/executable. For this reason :option:`--make`
cannot be specified when using :vlopt:`--build`.
.. option:: -MAKEFLAGS <string>
When using :vlopt:`--build`, add the specified argument to the invoked
make command line. For multiple flags, either pass them as a single
argument with space separators quoted in the shell (e.g. ``-MAKEFLAGS
"-a -b"``), or use multiple -MAKEFLAGS arguments
(e.g. ``-MAKEFLAGS -l -MAKEFLAGS -k``). Use of this option should not be
required for simple builds using the host toolchain.
.. option:: --max-num-width <value>
Set the maximum number literal width (e.g., in 1024'd22 this
@ -991,6 +988,11 @@ Summary:
Ignored for compatibility with other simulators.
.. option:: -o <executable>
Specify the name for the final executable built if using :vlopt:`--exe`.
Defaults to the :vlopt:`--prefix` if not specified.
.. option:: -O0
Disables optimization of the model.
@ -1011,11 +1013,6 @@ Summary:
is deprecated and the various `-f<optimization>` arguments should be
used instead.
.. option:: -o <executable>
Specify the name for the final executable built if using :vlopt:`--exe`.
Defaults to the :vlopt:`--prefix` if not specified.
.. option:: --no-order-clock-delay
Deprecated and has no effect (ignored).
@ -1107,6 +1104,14 @@ Summary:
position to indicate the corresponding bit of the __out variable has
a value being driven from within the Verilated model.
.. option:: --pins-sc-biguint
Specifies SystemC inputs/outputs greater than 65 bits wide should use
sc_biguint between 65 and 512, and sc_bv from 513 upwards. When
combined with the :vlopt:`--pins-sc-uint` combination, it results in
sc_uint being used between 2 and 64 and sc_biguint being used between 65
and 512.
.. option:: --pins-sc-uint
Specifies SystemC inputs/outputs greater than 2 bits wide should use
@ -1118,14 +1123,6 @@ Summary:
Specifies SystemC inputs/outputs one bit wide should use sc_uint<1>.
.. option:: --pins-sc-biguint
Specifies SystemC inputs/outputs greater than 65 bits wide should use
sc_biguint between 65 and 512, and sc_bv from 513 upwards. When
combined with the :vlopt:`--pins-sc-uint` combination, it results in
sc_uint being used between 2 and 64 and sc_biguint being used between 65
and 512.
.. option:: --pins-uint8
Specifies SystemC inputs/outputs smaller than the
@ -1487,25 +1484,21 @@ Summary:
A synonym for :vlopt:`+1800-2023ext+\<ext\>`.
.. option:: --threads <threads>
With "--threads 1", the default, the generated model is single-threaded
but may run in a multithreaded environment. With "--threads N",
where N >= 2, the model is generated to run multithreaded on up to N
threads. See :ref:`Multithreading`. This option also applies to
:vlopt:`--trace` (but not :vlopt:`--trace-fst`).
.. option:: --no-threads
Deprecated and has no effect (ignored).
In versions before 5.004, created a model which was not thread-safe.
.. option:: --threads-dpi all
.. option:: --threads <threads>
.. option:: --threads-dpi none
With "--threads 1", the default, the generated model is single-threaded
but may run in a multithreaded environment. With "--threads N",
where N >= 2, the model is generated to run multithreaded on up to N
threads. See :ref:`Multithreading`. This option also applies to
:vlopt:`--trace-vcd` (but not :vlopt:`--trace-fst`).
.. option:: --threads-dpi pure
.. option:: --threads-dpi <mode>
When using :vlopt:`--threads`, controls which DPI imported tasks and
functions are considered thread-safe.
@ -1539,10 +1532,10 @@ Summary:
does not occur before a given module. Default is "1ps/1ps" (to match
SystemC). This is overridden by :vlopt:`--timescale-override`.
.. option:: --timescale-override <timeunit>/<timeprecision>
.. option:: --timescale-override /<timeprecision>
.. option:: --timescale-override <timeunit>/<timeprecision>
Overrides all "\`timescale"s in sources. The timeunit may be left empty
to specify only to override the timeprecision, e.g. "/1fs".
@ -1574,26 +1567,19 @@ Summary:
.. option:: --trace
Adds waveform tracing code to the model using VCD format. This overrides
:vlopt:`--trace-fst`.
Deprecated; use :vlopt:`--trace-fst`, :vlopt:`--trace-saif` or
:vlopt:`--trace-vcd` instead.
Verilator will generate additional :file:`<prefix>__Trace*.cpp` files
must be compiled. In addition :file:`verilated_vcd_sc.cpp`
(for SystemC traces) or :file:`verilated_vcd_c.cpp` (for both) must be
compiled and linked in. If using the Verilator-generated Makefiles,
these files will be added to the source file lists for you. If you are
not using the Verilator Makefiles, you will need to add these to your
Makefile manually.
Using :vlopt:`--trace` without :vlopt:`--trace-fst` nor
:vlopt:`--trace-fst` requests VCD traces.
Having tracing compiled in may result in small performance losses,
even when tracing is not turned on during model execution.
Using :vlopt:`--trace` :vlopt:`--trace-fst` requests FST traces.
When using :vlopt:`--threads`, VCD tracing is parallelized, using the
same number of threads as passed to :vlopt:`--threads`.
Using :vlopt:`--trace` :vlopt:`--trace-saif` requests SAIF traces.
.. option:: --trace-coverage
With :vlopt:`--trace` and ``--coverage-*``, enable tracing to include a
With `--trace-*` and ``--coverage-*``, enable tracing to include a
traced signal for every :vlopt:`--coverage-line` or
:vlopt:`--coverage-user`\ -inserted coverage point, to assist in
debugging coverage items. Note :vlopt:`--coverage-toggle` does not get
@ -1673,6 +1659,24 @@ Summary:
underscore. Otherwise, these signals are not output during tracing. See
also :vlopt:`--coverage-underscore` option.
.. option:: --trace-vcd
Adds waveform tracing code to the model using VCD format.
Verilator will generate additional :file:`<prefix>__Trace*.cpp` files
must be compiled. In addition :file:`verilated_vcd_sc.cpp`
(for SystemC traces) or :file:`verilated_vcd_c.cpp` (for both) must be
compiled and linked in. If using the Verilator-generated Makefiles,
these files will be added to the source file lists for you. If you are
not using the Verilator Makefiles, you will need to add these to your
Makefile manually.
Having tracing compiled in may result in small performance losses,
even when tracing is not turned on during model execution.
When using :vlopt:`--threads`, VCD tracing is parallelized, using the
same number of threads as passed to :vlopt:`--threads`.
.. option:: -U<var>
Undefines the given preprocessor symbol.
@ -1770,7 +1774,7 @@ Summary:
them systematically.
The generated file is in the Verilator Configuration format, see
:ref:`Configuration Files`. The standard file extension is ".vlt".
:ref:`Verilator Configuration Files`. The standard file extension is ".vlt".
These files can directly be consumed by Verilator, typically by placing
the filename as part of the Verilator command line options. Waiver files
need to be listed on the command line before listing the files they are
@ -1876,37 +1880,40 @@ Summary:
``-Wwarn-ASSIGNDLY`` ``-Wwarn-BLKSEQ`` ``-Wwarn-DECLFILENAME``
``-Wwarn-DEFPARAM`` ``-Wwarn-EOFNEWLINE`` ``-Wwarn-GENUNNAMED``
``-Wwarn-IMPORTSTAR`` ``-Wwarn-INCABSPATH`` ``-Wwarn-PINCONNECTEMPTY``
``-Wwarn-PINNOCONNECT`` ``-Wwarn-SYNCASYNCNET`` ``-Wwarn-UNDRIVEN``
``-Wwarn-UNUSEDGENVAR`` ``-Wwarn-UNUSEDLOOP`` ``-Wwarn-UNUSEDPARAM``
``-Wwarn-UNUSEDSIGNAL`` ``-Wwarn-VARHIDDEN``.
``-Wwarn-PINNOCONNECT`` ``-Wwarn-PROCASSINIT`` ``-Wwarn-SYNCASYNCNET``
``-Wwarn-UNDRIVEN`` ``-Wwarn-UNUSEDGENVAR`` ``-Wwarn-UNUSEDLOOP``
``-Wwarn-UNUSEDPARAM`` ``-Wwarn-UNUSEDSIGNAL`` ``-Wwarn-VARHIDDEN``.
.. option:: --x-assign 0
.. option:: --x-assign 1
.. option:: --x-assign fast (default)
.. option:: --x-assign unique
.. option:: --x-assign <mode>
Controls the two-state value that is substituted when an explicit X
value is encountered in the source. "--x-assign fast", the default,
converts all Xs to whatever is best for performance. "--x-assign 0"
converts all Xs to 0s, and is also fast. "--x-assign 1" converts all Xs
to 1s, this is nearly as fast as 0, but more likely to find reset bugs
as active high logic will fire. Using "--x-assign unique" will result in
all explicit Xs being replaced by a constant value determined at
runtime. The value is determined by calling a function at initialization
time. This enables the randomization of Xs with different seeds on different
executions. This method is the slowest, but safest for finding reset
bugs.
value is encountered in the source.
If using "--x-assign unique", you may want to seed your random number
generator such that each regression run gets a different randomization
sequence. The simplest is to use the :vlopt:`+verilator+seed+\<value\>`
runtime option. Alternatively, use the system's :code:`srand48()` or for
Windows :code:`srand()` function to do this. You'll probably also want
to print any seeds selected, and code to enable rerunning with that same
seed so you can reproduce bugs.
With "--x-assign 0",
converts all Xs to 0s, and is also fast.
With "--x-assign 1",
converts all Xs to 1s, this is nearly as fast as 0, but more likely to
find reset bugs as active high logic will fire.
With "--x-assign fast", the default,
converts all Xs to whatever is best for performance.
With "--x-assign unique",
all explicit Xs being replaced by a constant value determined at
runtime. The value is determined by calling a function at
initialization time. This enables the randomization of Xs with
different seeds on different executions. This method is the slowest,
but safest for finding reset bugs.
If using `--x-assign unique`, you may want to seed your random number
generator such that each regression run gets a different randomization
sequence. The simplest is to use the
:vlopt:`+verilator+seed+\<value\>` runtime option. Alternatively, use
the system's :code:`srand48()` or for Windows :code:`srand()` function
to do this. You'll probably also want to print any seeds selected,
and code to enable rerunning with that same seed so you can reproduce
bugs.
.. note::
@ -1916,24 +1923,20 @@ Summary:
specified. Initial values of all other state holding variables are
controlled with `--x-initial`.
.. option:: --x-initial 0
.. option:: --x-initial fast
.. option:: --x-initial unique (default)
.. option:: --x-initial <mode>
Controls the two-state value used to initialize variables that
are not otherwise initialized.
"--x-initial 0",
With "--x-initial 0",
initializes all otherwise uninitialized variables to zero.
"--x-initial unique", the default,
With "--x-initial unique", the default,
initializes variables using a function, which determines the value to
use for each initialization. This gives the greatest flexibility and
allows for finding reset bugs. See :ref:`Unknown states`.
"--x-initial fast",
With "--x-initial fast",
is best for performance, and initializes all variables to a state
Verilator determines is optimal. This may allow further code
optimizations, but will likely hide any code bugs relating to missing
@ -2012,17 +2015,20 @@ Summary:
filenames.
.. _Configuration Files:
.. _Verilator Configuration Files:
Configuration Files
===================
=============================
Verilator Configuration Files
=============================
In addition to the command line, warnings and other features for the
:command:`verilator` command may be controlled with configuration files,
typically named with the `.vlt` extension (what makes it a configuration
file is the :option:`\`verilator_config` directive). These files, when
named `.vlt`, are read before source code files; if this behavior is
undesired, name the config file with a `.v` suffix.
:command:`verilator` command may be controlled with Verilator Configuration
Files, not to be confused with IEEE Configurations blocks
(`config...endconfig`) inside a file. Typically named with the `.vlt`
extension, what makes it a Verilator Configuration File is the
:option:`\`verilator_config` directive. These files, when named `.vlt`,
are read before source code files; if this behavior is undesired, name the
config file with a `.v` suffix.
An example:
@ -2034,9 +2040,9 @@ An example:
This disables WIDTH warnings globally, and CASEX for a specific file.
Configuration files are fed through the normal Verilog preprocessor prior
to parsing, so "\`ifdef", "\`define", and comments may be used as if the
configuration file was standard Verilog code.
Verilator configuration files are fed through the normal Verilog
preprocessor prior to parsing, so "\`ifdef", "\`define", and comments may
be used as if the configuration file was standard Verilog code.
Note that file or line-specific configuration only applies to files read
after the configuration file. It is therefore recommended to pass the
@ -2048,15 +2054,6 @@ The grammar of configuration commands is as follows:
Take the remaining text and treat it as Verilator configuration commands.
.. option:: coverage_on [-file "<filename>" [-lines <line> [ - <line> ]]]
.. option:: coverage_off [-file "<filename>" [-lines <line> [ - <line> ]]]
Enable/disable coverage for the specified filename (or wildcard with
'\*' or '?', or all files if omitted) and range of line numbers (or all
lines if omitted). Often used to ignore an entire module for coverage
analysis purposes.
.. option:: clock_enable -module "<modulename>" -var "<signame>"
Deprecated and has no effect (ignored).
@ -2068,30 +2065,42 @@ The grammar of configuration commands is as follows:
Same as :option:`/*verilator&32;clock_enable*/` metacomment.
.. option:: clocker -module "<modulename>" [-task "<taskname>"] -var "<signame>"
.. t_dist_docs_style ignore no_clocker
.. option:: clocker -module "<modulename>" [-function "<funcname>"] -var "<signame>"
.. option:: no_clocker -module "<modulename>" [-task "<taskname>"] -var "<signame>"
.. option:: clocker -module "<modulename>" [-task "<taskname>"] -var "<signame>"
.. option:: no_clocker -module "<modulename>" [-function "<funcname>"] -var "<signame>"
.. option:: no_clocker -module "<modulename>" [-task "<taskname>"] -var "<signame>"
Indicates whether the signal is used as clock or not. Verilator uses
this information to mark the signal and any derived signals as clocker.
See :vlopt:`--clk`.
Same as :option:`/*verilator&32;clocker*/` metacomment.
.. option:: coverage_block_off -module "<modulename>" -block "<blockname>"
.. option:: coverage_block_off -file "<filename>" -line <lineno>
.. option:: coverage_block_off -module "<modulename>" -block "<blockname>"
Specifies the entire begin/end block should be ignored for coverage
analysis purposes. It can either be specified as a named block or as a
filename and line number.
Same as :option:`/*verilator&32;coverage_block_off*/` metacomment.
.. option:: coverage_off [-file "<filename>" [-lines <line> [ - <line> ]]]
.. option:: coverage_on [-file "<filename>" [-lines <line> [ - <line> ]]]
Enable/disable coverage for the specified filename (or wildcard with
'\*' or '?', or all files if omitted) and range of line numbers (or all
lines if omitted). Often used to ignore an entire module for coverage
analysis purposes.
.. option:: forceable -module "<modulename>" -var "<signame>"
Generate public `<signame>__VforceEn` and `<signame>__VforceVal` signals
@ -2102,11 +2111,8 @@ The grammar of configuration commands is as follows:
.. option:: full_case -file "<filename>" -lines <lineno>
.. option:: parallel_case -file "<filename>" -lines <lineno>
Same as :code:`//synopsys full_case` and
:code:`//synopsys parallel_case`. When these synthesis directives are
discovered, Verilator will either formally prove the directive to be
Same as :code:`//synthesis full_case`. When these synthesis directives
are discovered, Verilator will either formally prove the directive to be
true, or, failing that, will insert the appropriate code to detect
failing cases at simulation runtime and print an "Assertion failed"
error message.
@ -2124,20 +2130,27 @@ The grammar of configuration commands is as follows:
This option should not be used directly.
See :ref:`Hierarchical Verilation`.
.. option:: hier_workers -hier-dpi "<function_name>" -workers <worker_count>
Specifies how many threads need to be used for scheduling hierarchical DPI
tasks. This data is inserted internally during :vlopt:`--hierarchical`,
based on value specified in `hier_workers -module`. This option
should not be used directly. See :ref:`Hierarchical Verilation`.
.. option:: hier_workers -module "<module_name>" -workers <worker_count>
Specifies how many threads need to be used for scheduling given module with
:option:`/*verilator&32;hier_block*/` metacomment. This number needs to be
smaller than :vlopt:`--threads` to fit in a thread schedule.
See :ref:`Hierarchical Verilation`.
.. option:: inline -module "<modulename>"
Specifies the module may be inlined into any modules that use this
module. Same as :option:`/*verilator&32;inline_module*/` metacomment.
.. option:: isolate_assignments -module "<modulename>" [-task "<taskname>"] -var "<signame>"
.. option:: isolate_assignments -module "<modulename>" [-function "<funcname>"] -var "<signame>"
.. option:: isolate_assignments -module "<modulename>" -function "<fname>"
Used to indicate that the assignments to this signal in any blocks
should be isolated into new blocks. Same as
:option:`/*verilator&32;isolate_assignments*/` metacomment.
.. t_dist_docs_style ignore no_inline
.. option:: no_inline -module "<modulename>"
@ -2145,10 +2158,10 @@ The grammar of configuration commands is as follows:
this module. Same as :option:`/*verilator&32;no_inline_module*/`
metacomment.
.. option:: no_inline [-module "<modulename>"] -task "<taskname>"
.. option:: no_inline [-module "<modulename>"] -function "<funcname>"
.. option:: no_inline [-module "<modulename>"] -task "<taskname>"
Specify the function or task should not be inlined into where it is
used. This may reduce the size of the final executable when a task is
used a very large number of times. For this flag to work, the task and
@ -2157,12 +2170,22 @@ The grammar of configuration commands is as follows:
Same as :option:`/*verilator&32;no_inline_task*/` metacomment.
.. option:: lint_on [-rule <message>] [-file "<filename>" [-lines <line> [ - <line>]]]
.. option:: isolate_assignments -module "<modulename>" -function "<fname>"
.. option:: isolate_assignments -module "<modulename>" [-function "<funcname>"] -var "<signame>"
.. option:: isolate_assignments -module "<modulename>" [-task "<taskname>"] -var "<signame>"
Used to indicate that the assignments to this signal in any blocks
should be isolated into new blocks. Same as
:option:`/*verilator&32;isolate_assignments*/` metacomment.
.. option:: lint_off [-rule <message>] [-file "<filename>" [-lines <line> [ - <line>]]]
.. option:: lint_off [-rule <message>] [-file "<filename>"] [-contents "<wildcard>"] [-match "<wildcard>"]
.. option:: lint_on [-rule <message>] [-file "<filename>" [-lines <line> [ - <line>]]]
Enable/disables the specified lint warning, in the specified filename
(or wildcard with '\*' or '?', or all files if omitted) and range of
line numbers (or all lines if omitted).
@ -2193,18 +2216,13 @@ The grammar of configuration commands is as follows:
Before version 4.026, :code:`-rule` was named :code:`-msg`, and
:code:`-msg` remained a deprecated alias until Version 5.000.
.. option:: public [-module "<modulename>"] [-task/-function "<taskname>"] -var "<signame>"
.. option:: parallel_case -file "<filename>" -lines <lineno>
.. option:: public_flat [-module "<modulename>"] [-task/-function "<taskname>"] -var "<signame>"
.. option:: public_flat_rd [-module "<modulename>"] [-task/-function "<taskname>"] -var "<signame>"
.. option:: public_flat_rw [-module "<modulename>"] [-task/-function "<taskname>"] -var "<signame>" "@(edge)"
Sets the variable to be public. Same as
:option:`/*verilator&32;public*/` or
:option:`/*verilator&32;public_flat*/`, etc., metacomments. See
also :ref:`VPI Example`.
Same as :code:`//synthesis parallel_case`. When these synthesis
directives are discovered, Verilator will either formally prove the
directive to be true, or, failing that, will insert the appropriate code
to detect failing cases at simulation runtime and print an "Assertion
failed" error message.
.. option:: profile_data -hier-dpi "<function_name>" -cost <cost_value>
@ -2219,18 +2237,31 @@ The grammar of configuration commands is as follows:
order to improve model runtime performance. This option is not expected
to be used by users directly. See :ref:`Thread PGO`.
.. option:: sc_bv -module "<modulename>" [-task "<taskname>"] -var "<signame>"
.. option:: public [-module "<modulename>"] [-task/-function "<taskname>"] -var "<signame>"
.. option:: public_flat [-module "<modulename>"] [-task/-function "<taskname>"] -var "<signame>"
.. option:: public_flat_rd [-module "<modulename>"] [-task/-function "<taskname>"] -var "<signame>"
.. option:: public_flat_rw [-module "<modulename>"] [-task/-function "<taskname>"] -var "<signame>" "@(edge)"
Sets the variable to be public. Same as
:option:`/*verilator&32;public*/` or
:option:`/*verilator&32;public_flat*/`, etc., metacomments. See
also :ref:`VPI Example`.
.. option:: sc_bv -module "<modulename>" [-function "<funcname>"] -var "<signame>"
.. option:: sc_bv -module "<modulename>" [-task "<taskname>"] -var "<signame>"
Sets the port to be of :code:`sc_bv<{width}>` type, instead of bool,
uint32_t, or uint64_t. Same as :option:`/*verilator&32;sc_bv*/`
metacomment.
.. option:: sformat [-module "<modulename>"] [-task "<taskname>"] -var "<signame>"
.. option:: sformat [-module "<modulename>"] [-function "<funcname>"] -var "<signame>"
.. option:: sformat [-module "<modulename>"] [-task "<taskname>"] -var "<signame>"
Must be applied to the final argument of type :code:`input string` of a
function or task to indicate that the function or task should pass all
remaining arguments through $sformatf. This allows the creation of DPI
@ -2239,20 +2270,20 @@ The grammar of configuration commands is as follows:
Same as :option:`/*verilator&32;sformat*/` metacomment.
.. option:: split_var [-module "<modulename>"] [-task "<taskname>"] -var "<varname>"
.. option:: split_var [-module "<modulename>"] [-function "<funcname>"] -var "<varname>"
.. option:: split_var [-module "<modulename>"] [-task "<taskname>"] -var "<varname>"
Break the variable into multiple pieces typically to resolve UNOPTFLAT
performance issues. Typically the variables to attach this to are
recommended by Verilator itself; see :option:`UNOPTFLAT`.
Same as :option:`/*verilator&32;split_var*/` metacomment.
.. option:: timing_on [-file "<filename>" [-lines <line> [ - <line>]]]
.. option:: timing_off [-file "<filename>" [-lines <line> [ - <line>]]]
.. option:: timing_on [-file "<filename>" [-lines <line> [ - <line>]]]
Enables/disables timing constructs for the specified file and lines.
When disabled, all timing control constructs in the specified source
code locations are ignored the same way as with the
@ -2262,14 +2293,17 @@ The grammar of configuration commands is as follows:
Same as :option:`/*verilator&32;timing_on*/`,
:option:`/*verilator&32;timing_off*/` metacomments.
.. option:: tracing_on [-file "<filename>" [-lines <line> [ - <line> ]]]
.. t_dist_docs_style ignore tracing_on
.. option:: tracing_off [-file "<filename>" [-lines <line> [ - <line> ]]]
.. option:: tracing_on [-scope "<scopename>" [-levels <levels> ]]
.. option:: tracing_on [-file "<filename>" [-lines <line> [ - <line> ]]]
.. option:: tracing_off [-scope "<scopename>" [-levels <levels> ]]
.. option:: tracing_on [-scope "<scopename>" [-levels <levels> ]]
Enable/disable waveform tracing for all future signals declared in
all files.

View File

@ -49,116 +49,119 @@ verilator_coverage Arguments
.. option:: <filename>
Specifies the input coverage data file. Multiple filenames may be provided
to read multiple inputs. If no data file is specified, by default,
"coverage.dat" will be read.
Specifies the input coverage data file. Multiple filenames may be
provided to read multiple inputs. If no data file is specified, by
default, "coverage.dat" will be read.
.. option:: --annotate <output_directory>
Specifies the directory name to which source files with annotated coverage
data should be written.
Specifies the directory name to which source files with annotated
coverage data should be written.
Points are children of each line coverage- branches, expressions or toggle points.
When point counts are aggregated into a line, the minimum and maximum counts
are used to determine the status of the line (complete, partial, failing)
The count is equal to the maximum of the points.
Points are children of each line coverage- branches, expressions or
toggle points. When point counts are aggregated into a line, the
minimum and maximum counts are used to determine the status of the line
(complete, partial, failing) The count is equal to the maximum of the
points.
Coverage data is annotated at the beginning of the line and is formatted
as a special character followed by the number of coverage hits. The special
characters " ,%,~,+,-" indicate summary of the coverage, and allow use of grep
to filter the report.
Coverage data is annotated at the beginning of the line and is formatted
as a special character followed by the number of coverage hits. The
special characters " ,%,~,+,-" indicate summary of the coverage, and
allow use of grep to filter the report.
* " " (whitespace) indicates that all points on the line are above the coverage min.
* "%" indicates that all points on the line are below the coverage min.
* "~" indicates that some points on the line are above the coverage min and some are below.
* "+" coverage point was at or above the min. Only used with :option:`--annotate-points`.
* "-" coverage point was below the min. Only used with :option:`--annotate-points`.
* " " (whitespace) indicates that all points on the line are above the coverage min.
* "%" indicates that all points on the line are below the coverage min.
* "~" indicates that some points on the line are above the coverage min and some are below.
* "+" coverage point was at or above the min. Only used with :option:`--annotate-points`.
* "-" coverage point was below the min. Only used with :option:`--annotate-points`.
.. code-block::
.. code-block::
100000 input logic a; // Begins with whitespace, because
// number of hits (100000) is above the min.
+100000 point: comment=a // Begins with +, because
// number of hits (100000) is above the min.
%000000 input logic b; // Begins with %, because
// number of hits (0) is below the min.
-000000 point: comment=b // Begins with -, because
// number of hits (0) is below the min.
~000010 if (cyc!=0) begin // Begins with ~, because
// branches are below and above the min.
+000010 point: comment=if // The if branch is above the min.
-000000 point: comment=else // The else branch is below the min.
100000 input logic a; // Begins with whitespace, because
// number of hits (100000) is above the min.
+100000 point: comment=a // Begins with +, because
// number of hits (100000) is above the min.
%000000 input logic b; // Begins with %, because
// number of hits (0) is below the min.
-000000 point: comment=b // Begins with -, because
// number of hits (0) is below the min.
~000010 if (cyc!=0) begin // Begins with ~, because
// branches are below and above the min.
+000010 point: comment=if // The if branch is above the min.
-000000 point: comment=else // The else branch is below the min.
.. option:: --annotate-all
Specifies all files should be shown. By default, only those source files
with low coverage are written to the output directory.
Specifies all files should be shown. By default, only those source
files with low coverage are written to the output directory.
This option should be used together with :option:`--annotate`.
This option should be used together with :option:`--annotate`.
.. option:: --annotate-min <count>
Specifies the threshold (<count>) below which coverage point is considered
sufficient. If the threshold is not exceeded, then the annotation will begin
with a "%" symbol to indicate the coverage is insufficient.
Specifies the threshold (<count>) below which coverage point is
considered sufficient. If the threshold is not exceeded, then the
annotation will begin with a "%" symbol to indicate the coverage is
insufficient.
The <count> threshold defaults to 10.
The <count> threshold defaults to 10.
This option should be used together with :option:`--annotate`.
This option should be used together with :option:`--annotate`.
.. option:: --annotate-points
Specifies all coverage points should be shown after each line of text. By
default, only source lines are shown.
Specifies all coverage points should be shown after each line of text. By
default, only source lines are shown.
.. code-block::
.. code-block::
100000 input logic a, b, c;
+100000 point: comment=a // These lines are only shown
+200000 point: comment=b // with option --annotate-points
+300000 point: comment=c // enabled.
100000 input logic a, b, c;
+100000 point: comment=a // These lines are only shown
+200000 point: comment=b // with option --annotate-points
+300000 point: comment=c // enabled.
This option should be used together with :option:`--annotate`.
This option should be used together with :option:`--annotate`.
.. option:: --help
Displays a help summary, the program version, and exits.
Displays a help summary, the program version, and exits.
.. option:: --rank
Prints an experimental report listing the relative importance of each test
in covering all of the coverage points. The report shows "Covered" which
indicates the number of points the test covers; a test is considered to
cover a point if it has a bucket count of at least 1. The "rank" column has
a higher number t indicate the test is more critical, and rank 0 means the
test does not need to be run to cover the points. "RankPts" indicates the
number of coverage points this test will contribute to overall coverage if
all tests are run in the order of highest to the lowest rank.
Prints an experimental report listing the relative importance of each
test in covering all of the coverage points. The report shows "Covered"
which indicates the number of points the test covers; a test is
considered to cover a point if it has a bucket count of at least 1. The
"rank" column has a higher number t indicate the test is more critical,
and rank 0 means the test does not need to be run to cover the points.
"RankPts" indicates the number of coverage points this test will
contribute to overall coverage if all tests are run in the order of
highest to the lowest rank.
.. option:: --unlink
With :option:`--write`, unlink all input files after the output
has been successfully created.
With :option:`--write`, unlink all input files after the output has been
successfully created.
.. option:: --version
Displays program version and exits.
Displays program version and exits.
.. option:: --write <filename>
Specifies the aggregate coverage results, summed across all the files,
should be written to the given filename in verilator_coverage data format.
This is useful in scripts to combine many coverage data files (likely
generated from random test runs) into one master coverage file.
Specifies the aggregate coverage results, summed across all the files,
should be written to the given filename in verilator_coverage data
format. This is useful in scripts to combine many coverage data files
(likely generated from random test runs) into one master coverage file.
.. option:: --write-info <filename.info>
Specifies the aggregate coverage results, summed across all the files,
should be written to the given filename in :command:`lcov` .info format.
This may be used to feed into :command:`lcov` to aggregate or generate
reports. This format lacks the comments for cover points that the
verilator_coverage format has. It can be used with :command:`genhtml`
to generate an HTML report. :command:`genhtml --branch-coverage` will
also display the branch coverage, analogous to :option:`--annotate-points`
Specifies the aggregate coverage results, summed across all the files,
should be written to the given filename in :command:`lcov` .info format.
This may be used to feed into :command:`lcov` to aggregate or generate
reports. This format lacks the comments for cover points that the
verilator_coverage format has. It can be used with :command:`genhtml` to
generate an HTML report. :command:`genhtml --branch-coverage` will also
display the branch coverage, analogous to :option:`--annotate-points`.

View File

@ -51,6 +51,10 @@ predicted_parallelism
cpu#_thread
For the given CPU number, the thread number measured to be executing.
cpu#_waiting
For the given CPU number, aggregated waiting time for mtask dependencies.
Visualized as `X` values.
mtask#_cpu
For the given mtask id, the CPU it was measured to execute on.
@ -80,16 +84,16 @@ verilator_gantt Arguments
.. option:: <filename>
The filename to read data from; the default is "profile_exec.dat".
The filename to read data from; the default is "profile_exec.dat".
.. option:: --help
Displays a help summary, the program version, and exits.
Displays a help summary, the program version, and exits.
.. option:: --no-vcd
Disables creating a .vcd file.
Disables creating a .vcd file.
.. option:: --vcd <filename>
Sets the output filename for vcd dump; the default is "verilator_gantt.vcd".
Sets the output filename for vcd dump; the default is "verilator_gantt.vcd".

View File

@ -33,8 +33,8 @@ verilator_profcfunc Arguments
.. option:: <filename>
The :command:`gprof`-generated filename to read data from. Typically "gprof.out".
The :command:`gprof`-generated filename to read data from. Typically "gprof.out".
.. option:: --help
Displays a help summary, the program version, and exits.
Displays a help summary, the program version, and exits.

View File

@ -1,14 +1,19 @@
.. Copyright 2003-2025 by Wilson Snyder.
.. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
*******************
Language Extensions
*******************
=====================
Language Extensions
=====================
The following additional constructs are the extensions Verilator supports
on top of standard Verilog code. Using these features outside of comments
or "`ifdef`"'s may break other tools.
.. option:: """ [string] """
A triple-quoted block specifies a string that may include newlines and
single quotes. This extension was standardized in IEEE 1800-2023.
.. option:: `__FILE__
The :option:`\`__FILE__` define expands to the current filename as a
@ -21,6 +26,12 @@ or "`ifdef`"'s may break other tools.
C++'s __LINE__. This Verilator feature added in 2006 was incorporated
into IEEE 1800-2009.
.. option:: `coverage_block_off
Specifies the entire begin/end block should be ignored for coverage
analysis. Must be inside a code block, e.g., within a begin/end pair.
Same as :option:`coverage_block_off` in :ref:`Verilator Configuration Files`.
.. option:: `error [string]
This will report an error when the preprocessor emits it, similar to
@ -33,10 +44,117 @@ or "`ifdef`"'s may break other tools.
internal tests, so that debugging can leave the line numbers correctly
referring to the test file's line numbers.
.. option:: """ [string] """
.. option:: `systemc_class_name
A triple-quoted block specifies a string that may include newlines and
single quotes. This extension was standardized in IEEE 1800-2023.
Inside one of the :option:`\`systemc_... <\`systemc_header>` text
blocks, replaced with the C++ class name generated for the given
containing SystemVerilog class or module. Currently this is replaced
blindly, ignoring quoting or other escapes; this behavior may change in
the future. This attribute is indented only to be used internally in
`verilated_std.sv`.
.. option:: `systemc_ctor
Take the remaining text up to the next :option:`\`verilog` or
:option:`\`systemc_... <\`systemc_header>` mode switch and place it
verbatim into the C++ class constructor. Must be placed as a module or
class item, e.g., directly inside a module/endmodule or class/endclass
pair. Despite the name of this macro, this also works in pure C++ code.
.. option:: `systemc_dtor
Take the remaining text up to the next :option:`\`verilog` or
:option:`\`systemc_... <\`systemc_header>` mode switch and place it
verbatim into the C++ class destructor. Must be placed as a module or
class item, e.g., directly inside a module/endmodule or class/endclass
pair. Despite the name of this macro, this also works in pure C++ code.
.. option:: `systemc_header
Take the remaining text up to the next :option:`\`verilog` or
:option:`\`systemc_... <\`systemc_header>` mode switch and place it
verbatim into the output .h file's header. Must be placed as a module
or class item, e.g., directly inside a module/endmodule or
class/endclass pair. Despite the name of this macro, this also works in
pure C++ code.
.. option:: `systemc_header_post
Take the remaining text up to the next :option:`\`verilog` or
:option:`\`systemc_... <\`systemc_header>` mode switch and place it
verbatim into the output .h file's header after the class definition.
Must be placed as a module or class item, e.g., directly inside a
module/endmodule or class/endclass pair. Despite the name of this macro,
this also works in pure C++ code.
.. option:: `systemc_imp_header
Take the remaining text up to the next :option:`\`verilog` or
:option:`\`systemc_... <\`systemc_header>` mode switch and place it
verbatim into the header of all files for this C++ class implementation.
Must be placed as a module or class item, e.g., directly inside a
module/endmodule or class/endclass pair. Despite the name of this macro,
this also works in pure C++ code.
.. option:: `systemc_implementation
Take the remaining text up to the next :option:`\`verilog` or
:option:`\`systemc_... <\`systemc_header>` mode switch and place it
verbatim into a single file of the C++ class implementation. Must be
placed as a module or class item, e.g., directly inside a
module/endmodule or class/endclass pair. Despite the name of this macro,
this also works in pure C++ code.
If you will be reading or writing any Verilog variables in the C++
functions, the Verilog signals must be declared with a
:option:`/*verilator&32;public*/` metacomment. See also the public task
feature; writing an accessor may result in cleaner code.
.. option:: `systemc_interface
Take the remaining text up to the next :option:`\`verilog` or
:option:`\`systemc_... <\`systemc_header>` mode switch and place it
verbatim into the C++ class interface. Must be placed as a module or
class item, e.g., directly inside a module/endmodule or class/endclass
pair. Despite the name of this macro, this also works in pure C++ code.
.. option:: `SYSTEMVERILOG
The SYSTEMVERILOG, SV_COV_START, and related standard predefined macros
are defined by default when :vlopt:`--language <--language>` is
"1800-\*".
.. option:: `VERILATOR
.. option:: `verilator
.. option:: `verilator3
The VERILATOR, verilator and verilator3 predefined macros are defined by
default so you may "\`ifdef" around tool specific constructs.
.. option:: `verilator_config
Take the remaining text up to the next :option:`\`verilog` mode switch
and treat it as Verilator configuration commands. See :ref:`Verilator
Configuration Files`.
.. option:: `VERILATOR_TIMING
The VERILATOR_TIMING define is set when :vlopt:`--timing` is used to
allow an "\`ifdef" of code dependent on this feature. Note that this define
is not affected by the :option:`timing_off` configuration file option
nor timing metacomments.
.. option:: `verilog
Switch back to processing Verilog code after a
:option:`\`systemc_... <\`systemc_header>` mode switch. The Verilog
code returns to the last language mode specified with
"\`begin_keywords", or SystemVerilog if none was specified.
.. t_dist_docs_style restart_sort
.. option:: $c([string], ...);
@ -86,6 +204,16 @@ or "`ifdef`"'s may break other tools.
prints 5 digits per the C standard. This extension was standardized into
1800-2009.
.. option:: $stacktrace
Called as a task, print a stack trace. Called as a function, return a
string with a stack trace. This relies on the C++ system trace, which
may give less meaningful results if the model is not compiled with debug
symbols. Also, the data represents the C++ stack; the SystemVerilog
functions/tasks involved may be renamed and/or inlined before becoming
the C++ functions that may be visible in the stack trace. This
extension was standardized in IEEE 1800-2023.
.. option:: $timeprecision
Returns the timeprecision of the model as an integer. This extension is
@ -96,98 +224,6 @@ or "`ifdef`"'s may break other tools.
Returns the timeunit of the current module as an integer. This
extension is experimental and may be removed without deprecation.
.. option:: `coverage_block_off
Specifies the entire begin/end block should be ignored for coverage
analysis. Must be inside a code block, e.g., within a begin/end pair.
Same as :option:`coverage_block_off` in :ref:`Configuration Files`.
.. option:: `systemc_header
Take the remaining text up to the next :option:`\`verilog` or
:option:`\`systemc_... <\`systemc_header>` mode switch and place it
verbatim into the output .h file's header. Must be placed as a module
item, e.g., directly inside a module/endmodule pair. Despite the name of
this macro, this also works in pure C++ code.
.. option:: `systemc_ctor
Take the remaining text up to the next :option:`\`verilog` or
:option:`\`systemc_... <\`systemc_header>` mode switch and place it
verbatim into the C++ class constructor. Must be placed as a module
item, e.g., directly inside a module/endmodule pair. Despite the name of
this macro, this also works in pure C++ code.
.. option:: `systemc_dtor
Take the remaining text up to the next :option:`\`verilog` or
:option:`\`systemc_... <\`systemc_header>` mode switch and place it
verbatim into the C++ class destructor. Must be placed as a module
item, e.g., directly inside a module/endmodule pair. Despite the name of
this macro, this also works in pure C++ code.
.. option:: `systemc_interface
Take the remaining text up to the next :option:`\`verilog` or
:option:`\`systemc_... <\`systemc_header>` mode switch and place it
verbatim into the C++ class interface. Must be placed as a module item,
e.g., directly inside a module/endmodule pair. Despite the name of this
macro, this also works in pure C++ code.
.. option:: `systemc_imp_header
Take the remaining text up to the next :option:`\`verilog` or
:option:`\`systemc_... <\`systemc_header>` mode switch and place it
verbatim into the header of all files for this C++ class implementation.
Must be placed as a module item, e.g., directly inside a module/endmodule
pair. Despite the name of this macro, this also works in pure C++ code.
.. option:: `systemc_implementation
Take the remaining text up to the next :option:`\`verilog` or
:option:`\`systemc_... <\`systemc_header>` mode switch and place it
verbatim into a single file of the C++ class implementation. Must be
placed as a module item, e.g., directly inside a module/endmodule
pair. Despite the name of this macro, this also works in pure C++ code.
If you will be reading or writing any Verilog variables in the C++
functions, the Verilog signals must be declared with a
:option:`/*verilator&32;public*/` metacomment. See also the public task
feature; writing an accessor may result in cleaner code.
.. option:: `SYSTEMVERILOG
The SYSTEMVERILOG, SV_COV_START, and related standard defines are set by
default when :vlopt:`--language <--language>` is "1800-\*".
.. option:: `VERILATOR
.. option:: `verilator
.. option:: `verilator3
The VERILATOR, verilator and verilator3 defines are set by default so
you may "\`ifdef" around tool specific constructs.
.. option:: `verilator_config
Take the remaining text up to the next :option:`\`verilog` mode switch and
treat it as Verilator configuration commands. See :ref:`Configuration Files`.
.. option:: `VERILATOR_TIMING
The VERILATOR_TIMING define is set when :vlopt:`--timing` is used to
allow an "\`ifdef" of code dependent on this feature. Note that this define
is not affected by the :option:`timing_off` configuration file option
nor timing metacomments.
.. option:: `verilog
Switch back to processing Verilog code after a
:option:`\`systemc_... <\`systemc_header>` mode switch. The Verilog
code returns to the last language mode specified with
"\`begin_keywords", or SystemVerilog if none was specified.
.. option:: /*verilator&32;clock_enable*/
Deprecated and has no effect (ignored).
@ -212,6 +248,9 @@ or "`ifdef`"'s may break other tools.
Same as :option:`clock_enable` configuration file option.
.. t_dist_docs_style ignore /*verilator&32;no_clocker*/
.. option:: /*verilator&32;clocker*/
.. option:: /*verilator&32;no_clocker*/
@ -379,29 +418,6 @@ or "`ifdef`"'s may break other tools.
parameter [2:0] PARAM /*verilator public*/ = 2'b0;
.. option:: /*verilator&32;public*/ (on typedef enum)
Used after an enum typedef declaration to indicate the emitted C code
should have the enum values visible. Due to C++ language restrictions,
this may only be used on 64-bit or narrower integral enumerations.
.. code-block:: sv
typedef enum logic [2:0] { ZERO = 3'b0 } pub_t /*verilator public*/;
.. option:: /*verilator&32;public*/ (on variable)
Used after an input, output, register, or wire declaration to indicate
the signal should be declared so that C code may read or write the value
of the signal. This will also declare this module public; otherwise, use
:code:`/*verilator&32;public_flat*/`.
Instead of using public variables, consider making a DPI or public
function that accesses the variable. This is nicer as it provides an
obvious entry point compatible across simulators.
Same as :option:`public` configuration file option.
.. option:: /*verilator&32;public*/ (on task/function)
Used inside the declaration section of a function or task declaration to
@ -426,6 +442,52 @@ or "`ifdef`"'s may break other tools.
Same as :option:`public` configuration file option.
.. option:: /*verilator&32;public*/ (on typedef enum)
Used after an enum typedef declaration to indicate the emitted C code
should have the enum values visible. Due to C++ language restrictions,
this may only be used on 64-bit or narrower integral enumerations.
.. code-block:: sv
typedef enum logic [2:0] { ZERO = 3'b0 } pub_t /*verilator public*/;
.. option:: /*verilator&32;public*/ (on variable)
Used after an input, output, register, or wire declaration to indicate
the signal should be declared so that C code may read or write the value
of the signal. This will also declare this module public; otherwise, use
:code:`/*verilator&32;public_flat*/`.
Instead of using public variables, consider making a DPI or public
function that accesses the variable. This is nicer as it provides an
obvious entry point compatible across simulators.
Same as :option:`public` configuration file option.
.. option:: /*verilator&32;public_[|flat|flat_rd|flat_rw]_on [@(<edge_list>)]*/ (as scope)
Used to wrap multiple signals and parameters with the respective public attribute.
See attribute above for their respective behavior. Cannot be nested. e.g:
.. code-block:: sv
/*verilator public_flat_rw_on*/
logic clk;
logic rst;
parameter width = 8;
/* verilator public_off*/
logic data;
Is equivalent to:
.. code-block:: sv
logic clk /*verilator public_flat_rw*/;
logic rst /*verilator public_flat_rw*/;
parameter width /*verilator public_flat_rw*/ = 8;
logic data;
.. option:: /*verilator&32;public_flat*/ (on variable)
Used after an input, output, register, or wire declaration to indicate
@ -453,33 +515,6 @@ or "`ifdef`"'s may break other tools.
Same as :option:`public_flat_rw` configuration file option.
.. option:: /*verilator&32;public_[|flat|flat_rd|flat_rw]_on [@(<edge_list>)]*/ (as scope)
Used to wrap multiple signals and parameters with the respective public attribute.
See attribute above for their respective behavior. Cannot be nested. e.g:
.. code-block:: sv
/*verilator public_flat_rw_on*/
logic clk;
logic rst;
parameter width = 8;
/* verilator public_off*/
logic data;
Is equivalent to:
.. code-block:: sv
logic clk /*verilator public_flat_rw*/;
logic rst /*verilator public_flat_rw*/;
parameter width /*verilator public_flat_rw*/ = 8;
logic data;
.. option:: /*verilator&32;public_off*/
Terminates the previous `/*verilator public*_on*/` directive; see above.
.. option:: /*verilator&32;public_module*/
Used after a module statement to indicate the module should not be
@ -490,13 +525,9 @@ or "`ifdef`"'s may break other tools.
Same as :option:`public` configuration file option.
.. option:: /*verilator&32;sc_clock*/
.. option:: /*verilator&32;public_off*/
Deprecated and ignored. Previously used after an input declaration to
indicate the signal should be declared in SystemC as a sc_clock instead
of a bool. This was needed in SystemC 1.1 and 1.2 only; versions 2.0
and later do not require clock pins to be sc_clocks, and this is no
longer needed and is ignored.
Terminates the previous `/*verilator public*_on*/` directive; see above.
.. option:: /*verilator&32;sc_bv*/
@ -509,6 +540,14 @@ or "`ifdef`"'s may break other tools.
Same as :option:`sc_bv` configuration file option.
.. option:: /*verilator&32;sc_clock*/
Deprecated and ignored. Previously used after an input declaration to
indicate the signal should be declared in SystemC as a sc_clock instead
of a bool. This was needed in SystemC 1.1 and 1.2 only; versions 2.0
and later do not require clock pins to be sc_clocks, and this is no
longer needed and is ignored.
.. option:: /*verilator&32;sformat*/
Attached to the final argument of type "input string" of a function or
@ -597,7 +636,7 @@ or "`ifdef`"'s may break other tools.
Attached to a DPI import to indicate that function should be called when
initializing tracing. This attribute is indented only to be used
internally in code that Verilator generates when :vlopt:`--lib-create`
or :vlopt:`--hierarchical` is used along with :vlopt:`--trace`.
or :vlopt:`--hierarchical` is used along with :vlopt:`--trace-vcd`.
.. option:: /*verilator&32;tracing_off*/
@ -627,13 +666,3 @@ or "`ifdef`"'s may break other tools.
following loop at the same statement level should always be fully
unrolled by Verilator, ignoring :vlopt:`--unroll-count`. This is
similar to clang's ``#pragma clang loop unroll(full)``.
.. option:: $stacktrace
Called as a task, print a stack trace. Called as a function, return a
string with a stack trace. This relies on the C++ system trace, which
may give less meaningful results if the model is not compiled with debug
symbols. Also, the data represents the C++ stack; the SystemVerilog
functions/tasks involved may be renamed and/or inlined before becoming
the C++ functions that may be visible in the stack trace. This
extension was standardized in IEEE 1800-2023.

View File

@ -128,7 +128,7 @@ How do I generate waveforms (traces) in C++?
See also the next question for tracing in SystemC mode.
A. Pass the :vlopt:`--trace` option to Verilator. Then you may use ``$dumpfile`` and
A. Pass the :vlopt:`--trace-vcd` option to Verilator. Then you may use ``$dumpfile`` and
``$dumpvars`` to enable traces, the same as with any Verilog simulator,
although Verilator ignores the arguments to ``$dumpvars``. See
``examples/make_tracing_c`` in the distribution.
@ -177,7 +177,7 @@ file.
How do I generate waveforms (traces) in SystemC?
""""""""""""""""""""""""""""""""""""""""""""""""
A. Pass the :vlopt:`--trace` option to Verilator, and in your top-level
A. Pass the :vlopt:`--trace-vcd` option to Verilator, and in your top-level
:code:`sc_main()`, call :code:`Verilated::traceEverOn(true)`. Then you
may use :code:`$dumpfile` and code:`$dumpvars` to enable traces, as
with any Verilog simulator; see the non-SystemC example in

View File

@ -65,9 +65,9 @@ For --cc/--sc, it creates:
* - *{prefix}*\ ___024root\ *{__DepSet_hash__n}*\ .cpp
- Infrequent cold routines (hashed to reduce build times)
* - *{prefix}*\ ___024root__Trace\ *{__n}*\ .cpp
- Wave file generation code (from --trace)
- Wave file generation code (from --trace-\*)
* - *{prefix}*\ ___024root__Trace__Slow\ *{__n}*\ .cpp
- Wave file generation code (from --trace)
- Wave file generation code (from --trace-\*)
* - *{prefix}*\ __Dpi.h
- DPI import and export declarations (from --dpi)
* - *{prefix}*\ __Dpi.cpp

View File

@ -15,9 +15,9 @@ Package Manager Quick Install
=============================
Using a distribution's package manager is the easiest way to get
started. (Note packages are unlikely to have the most recent version, so
:ref:`Git Install` might be a better alternative.) To install as a
package:
started. (Note distribution packages almost never have the most recent
Verilator version, so we recommend following :ref:`Git Install` below,
instead.) To install as a package:
.. code-block:: shell
@ -118,6 +118,25 @@ To build or run Verilator, you need these standard packages:
sudo apt-get install libfl-dev # Ubuntu only (ignore if gives error)
sudo apt-get install zlibc zlib1g zlib1g-dev # Ubuntu only (ignore if gives error)
For SystemC:
.. code-block:: shell
sudo apt-get install libsystemc libsystemc-dev
For constraints:
.. code-block:: shell
sudo apt-get install z3 # Optional solver
The following is optional but is recommended for nicely rendered command line
help when running Verilator:
.. code-block:: shell
sudo apt-get install perl-doc
To build or run Verilator, the following are optional but should be installed
for good performance:
@ -127,13 +146,6 @@ for good performance:
sudo apt-get install mold # If present at build, needed for run
sudo apt-get install libgoogle-perftools-dev numactl
The following is optional but is recommended for nicely rendered command line
help when running Verilator:
.. code-block:: shell
sudo apt-get install perl-doc
To build Verilator you will need to install these packages; these do not
need to be present to run Verilator:
@ -155,7 +167,10 @@ Those developing Verilator itself may also want these (see internals.rst):
Install SystemC
^^^^^^^^^^^^^^^
If you will be using SystemC (vs straight C++ output), download `SystemC
SystemC code can be generated from Verilator (with :vlopt:`--sc`) if it is
installed as a package (see above).
Alternatively, from their sources, download `SystemC
<https://www.accellera.org/downloads/standards/systemc>`__. Follow their
installation instructions. You will need to set the
:option:`SYSTEMC_INCLUDE` environment variable to point to the include
@ -170,6 +185,10 @@ To make use of Verilator FST tracing you will want `GTKwave
<http://gtkwave.sourceforge.net/>`__ installed, however this is not
required at Verilator build time.
.. code-block:: shell
sudo apt-get install gtkwave # Optional Waveform viewer
Install Z3
^^^^^^^^^^

View File

@ -6,7 +6,7 @@ Input Languages
***************
This section describes the languages Verilator takes as input. See also
:ref:`Configuration Files`.
:ref:`Verilator Configuration Files`.
Language Standard Support
@ -334,7 +334,8 @@ Gate Primitives
The 2-state gate primitives (and, buf, nand, nor, not, or, xnor, xor) are
directly converted to behavioral equivalents. The 3-state and MOS gate
primitives are not supported. Tables are not supported.
primitives are not supported. User-defined primitive (UDP) tables are
supported.
Specify blocks
@ -396,8 +397,8 @@ This section describes specific limitations for each language keyword.
\`begin_keywords, \`begin_keywords, \`begin_keywords, \`begin_keywords,
\`define, \`else, \`elsif, \`end_keywords, \`endif, \`error, \`ifdef,
\`ifndef, \`include, \`line, \`systemc_ctor, \`systemc_dtor,
\`systemc_header, \`systemc_imp_header, \`systemc_implementation,
\`systemc_interface, \`undef, \`verilog
\`systemc_header, \`systemc_header_post, \`systemc_imp_header,
\`systemc_implementation, \`systemc_interface, \`undef, \`verilog
|cmdslong1|
Fully supported.
@ -488,7 +489,7 @@ $bits, $countbits, $countones, $finish, $isunknown, $onehot, $onehot0, $signed,
$dump/$dumpports and related
$dumpfile or $dumpports will create a VCD or FST file (based on
the :vlopt:`--trace` option given when the model was Verilated). This
the :vlopt:`--trace-vcd` option given when the model was Verilated). This
will take effect starting at the next eval() call. If you have multiple
Verilated designs under the same C model, this will dump signals
only from the design containing the $dumpvars.
@ -535,4 +536,4 @@ $test$plusargs, $value$plusargs
{VerilatedContext*} ->commandArgs(argc, argv);
to register the command line before calling $test$plusargs or
$value$plusargs.
$value$plusargs. Or use :vlopt:`--binary` or :vlopt:`--main`.

View File

@ -83,9 +83,10 @@ option will require a longer time to run Verilator, and
may increase the risk of reset bugs in trade for performance; see the above
documentation for these options.
If using Verilated multithreaded, use ``numactl`` to ensure you use
non-conflicting hardware resources. See :ref:`Multithreading`. Also,
consider using profile-guided optimization; see :ref:`Thread PGO`.
If using Verilated multithreaded, consider overriding Verilator's default
thread-to-processor assignment by using ``numactl``; see
:ref:`Multithreading`. Also, consider using profile-guided optimization;
see :ref:`Thread PGO`.
Minor Verilog code changes can also give big wins. You should not have any
:option:`UNOPTFLAT` warnings from Verilator. Fixing these warnings can

View File

@ -94,7 +94,7 @@ There are two ways to mark a module:
* Write :option:`/*verilator&32;hier_block*/` metacomment in HDL code.
* Add a :option:`hier_block` line in the :ref:`Configuration Files`.
* Add a :option:`hier_block` line in the :ref:`Verilator Configuration Files`.
Then pass the :vlopt:`--hierarchical` option to Verilator.
@ -221,7 +221,7 @@ model, it may be beneficial to performance to adjust the
influences the partitioning of the model by adjusting the assumed execution
time of DPI imports.
When using :vlopt:`--trace` to perform VCD tracing, the VCD trace
When using :vlopt:`--trace-vcd` to perform VCD tracing, the VCD trace
construction is parallelized using the same number of threads as specified
with :vlopt:`--threads`, and is executed on the same thread pool as the model.
@ -243,11 +243,14 @@ trace. FST tracing can utilize up to 2 offload threads, so there is no use
of setting :vlopt:`--trace-threads` higher than 2 at the moment.
When running a multithreaded model, the default Linux task scheduler often
works against the model by assuming short-lived threads and thus
it often schedules threads using multiple hyperthreads within the same
physical core. For best performance, use the :command:`numactl` program to
(when the threading count fits) select unique physical cores on the same
socket. The same applies for :vlopt:`--trace-threads` as well.
works against the model by assuming short-lived threads and thus it often
schedules threads using multiple hyperthreads within the same physical
core. If there is no affinity already set, on Linux only, Verilator
attempts to set thread-to-processor affinity in a reasonable way.
For best performance, use the :command:`numactl` program to (when the
threading count fits) select unique physical cores on the same socket. The
same applies for :vlopt:`--trace-threads` as well.
As an example, if a model was Verilated with
:vlopt:`--threads 4 <--threads>`, we consult:
@ -290,8 +293,8 @@ and must be called only by the eval thread.
If using :vlopt:`--sc`, the SystemC kernel is not thread-safe; therefore,
the eval thread and main thread must be the same.
If using :vlopt:`--trace`, the tracing classes must be constructed and
called from the main thread.
If using :vlopt:`--trace-vcd` or other trace options, the tracing classes
must be constructed and called from the main thread.
If using :vlopt:`--vpi`, since SystemVerilog VPI was not architected by
IEEE to be multithreaded, Verilator requires all VPI calls are only made
@ -367,10 +370,11 @@ Verilate in CMake
.. code-block:: CMake
verilate(target SOURCES source ... [TOP_MODULE top] [PREFIX name]
[TRACE] [TRACE_FST] [SYSTEMC] [COVERAGE]
[COVERAGE] [SYSTEMC]
[TRACE_FST] [TRACE_SAIF] [TRACE_VCD] [TRACE_THREADS num]
[INCLUDE_DIRS dir ...] [OPT_SLOW ...] [OPT_FAST ...]
[OPT_GLOBAL ..] [DIRECTORY dir] [THREADS num]
[TRACE_THREADS num] [VERILATOR_ARGS ...])
[VERILATOR_ARGS ...])
Lowercase and ... should be replaced with arguments; the uppercase parts
delimit the arguments and can be passed in any order or left out entirely
@ -443,10 +447,6 @@ SystemC include directories and link to the SystemC libraries.
Optional. Enable a multithreaded model; see :vlopt:`--threads`.
.. describe:: TRACE_THREADS
Optional. Enable multithreaded FST trace; see :vlopt:`--trace-threads`.
.. describe:: TOP_MODULE
Optional. Sets the name of the top module. Defaults to the name of the
@ -454,8 +454,7 @@ SystemC include directories and link to the SystemC libraries.
.. describe:: TRACE
Optional. Enables VCD tracing if present, equivalent to "VERILATOR_ARGS
--trace".
Deprecated. Same as TRACE_VCD, which should be used instead.
.. describe:: TRACE_FST
@ -467,6 +466,15 @@ SystemC include directories and link to the SystemC libraries.
Optional. Enables SAIF tracing if present, equivalent to "VERILATOR_ARGS
--trace-saif".
.. describe:: TRACE_THREADS
Optional. Enable multithreaded FST trace; see :vlopt:`--trace-threads`.
.. describe:: TRACE_VCD
Optional. Enables VCD tracing if present, equivalent to "VERILATOR_ARGS
--trace-vcd".
.. describe:: VERILATOR_ARGS
Optional. Extra arguments to Verilator. Do not specify :vlopt:`--Mdir`

View File

@ -1,9 +1,9 @@
.. Copyright 2003-2025 by Wilson Snyder.
.. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
*******************
Errors and Warnings
*******************
=====================
Errors and Warnings
=====================
.. _Disabling Warnings:
@ -37,7 +37,7 @@ Warnings may be disabled in multiple ways:
propagate upwards to any parent file (file that included the file with
the lint_off).
#. Disable the warning using :ref:`Configuration Files` with a
#. Disable the warning using :ref:`Verilator Configuration Files` with a
:option:`lint_off` command. This is useful when a script suppresses
warnings, and the Verilog source should not be changed. This method also
allows matching on the warning text.
@ -86,6 +86,8 @@ List Of Warnings
Limitations`.
.. t_dist_docs_style restart_sort
.. option:: ALWCOMBORDER
.. TODO better example
@ -165,6 +167,24 @@ List Of Warnings
'pragma protect'. Third-party pragmas not defined by IEEE 1800-2023 are
ignored.
This error may be disabled with a lint_off BADSTDPRAGMA metacomment.
.. option:: BADVLTPRAGMA
An error that a `/*verilator ...*/` metacomment pragma is badly formed
or not understood.
Faulty example:
.. include:: ../../docs/gen/ex_BADVLTPRAGMA_faulty.rst
Results in:
.. include:: ../../docs/gen/ex_BADVLTPRAGMA_msg.rst
This error may be disabled with a lint_off BADVLTPRAGMA metacomment.
.. option:: BLKANDNBLK
@ -472,6 +492,31 @@ List Of Warnings
correctly.
.. option:: DEFOVERRIDE
Warns that a macro definition within the code is being overridden by a command line directive:
For example, running Verilator with :code:`<+define+\<DUP\>=\<def2\>>` and
.. code-block:: sv
:linenos:
:emphasize-lines: 1
`define DUP def2 //<--- Warning
Results in:
.. code-block::
%Warning-DEFOVERRIDE: example.v1:20: Overriding define: 'DEF' with value: 'def2' to existing command line define value: 'def1'
... Location of previous definition, with value: '50'
While not explicitly stated in the IEEE 1800-2023 standard, this warning
tracks with the other simulators' behavior of overriding macro
definitions within code files with the definition passed in through
the command line.
.. option:: DEFPARAM
Warns that the :code:`defparam` statement was deprecated in IEEE 1364-2001,
@ -1222,13 +1267,6 @@ List Of Warnings
simulate correctly.
.. option:: NOTIMING
Error when a timing-related construct that requires :vlopt:`--timing` has
been encountered. Issued only if Verilator is run with the
:vlopt:`--no-timing` option.
.. option:: NONSTD
Warns when a non-standard language feature is used that has a standard
@ -1237,6 +1275,13 @@ List Of Warnings
:code:`$sformatf`.
.. option:: NOTIMING
Error when a timing-related construct that requires :vlopt:`--timing` has
been encountered. Issued only if Verilator is run with the
:vlopt:`--no-timing` option.
.. option:: NULLPORT
Warns that a null port was detected in the module definition port
@ -1261,6 +1306,7 @@ List Of Warnings
Ignoring this warning will only suppress the lint check; it will
simulate correctly.
.. option:: PINCONNECTEMPTY
.. TODO better example
@ -1349,6 +1395,26 @@ List Of Warnings
This error may be disabled with a lint_off PINNOTFOUND metacomment.
.. option:: PKGNODECL
An error that a package/class appears to have been referenced that has
not yet been declared. According to IEEE 1800-2023 26.3, all packages
must be declared before being used.
Faulty example:
.. include:: ../../docs/gen/ex_PKGNODECL_faulty.rst
Results in:
.. include:: ../../docs/gen/ex_PKGNODECL_msg.rst
Often the package is declared in its own header file. In this case add
an include of that package header file to the referencing file. (And
make sure you have header guards in the package's header file to prevent
multiple declarations of the package.)
.. option:: PORTSHORT
Warns that an output port is connected to a constant.
@ -1372,26 +1438,6 @@ List Of Warnings
This error may be disabled with a lint_off PORTSHORT metacomment.
.. option:: PKGNODECL
An error that a package/class appears to have been referenced that has
not yet been declared. According to IEEE 1800-2023 26.3, all packages
must be declared before being used.
Faulty example:
.. include:: ../../docs/gen/ex_PKGNODECL_faulty.rst
Results in:
.. include:: ../../docs/gen/ex_PKGNODECL_msg.rst
Often the package is declared in its own header file. In this case add
an include of that package header file to the referencing file. (And
make sure you have header guards in the package's header file to prevent
multiple declarations of the package.)
.. option:: PREPROCZERO
Warns that a preprocessor \`ifdef/\`ifndef expression (added in IEEE
@ -1417,6 +1463,35 @@ List Of Warnings
than zero, when it is to be used in a preprocessor expression.
.. option:: PROCASSINIT
Warns that the specified signal is given an initial value where it is
declared, and is also driven in an always process. Typically such
initial values should instead be set using a reset signal inside the
process, to match requirements of hardware synthesis tools.
Faulty example:
.. include:: ../../docs/gen/ex_PROCASSINIT_faulty.rst
Results in:
.. include:: ../../docs/gen/ex_PROCASSINIT_msg.rst
One possible fix, adding a reset to the always:
.. include:: ../../docs/gen/ex_PROCASSINIT_fixed.rst
Alternatively, use an initial block for the initialization:
.. code-block:: sv
initial flop_out = 1; // <--- Fixed
Disabled by default as this is a code-style warning; it will simulate
correctly.
.. option:: PROCASSWIRE
.. TODO better example
@ -2118,7 +2193,7 @@ List Of Warnings
.. include:: ../../docs/gen/ex_VARHIDDEN_msg.rst
To resolve this, rename the variable to an unique name.
To resolve this, rename the inner or outer variable to an unique name.
.. option:: WAITCONST
@ -2181,21 +2256,6 @@ List Of Warnings
.. include:: ../../docs/gen/ex_WIDTHEXPAND_1_fixed.rst
.. option:: WIDTHTRUNC
A more granular :option:`WIDTH` warning, for when a value is
truncated. See :option:`WIDTH`.
.. option:: WIDTHEXPAND
A more granular :option:`WIDTH` warning, for when a value is zero
expanded. See :option:`WIDTH`.
.. option:: WIDTHXZEXPAND
A more granular :option:`WIDTH` warning, for when a value is X/Z
expanded. See :option:`WIDTH`.
.. option:: WIDTHCONCAT
Warns that based on the width rules of Verilog, a concatenate, or
@ -2221,6 +2281,21 @@ List Of Warnings
width to the parameter usage (:code:`{PAR[31:0], PAR[31:0]}`).
.. option:: WIDTHEXPAND
A more granular :option:`WIDTH` warning, for when a value is zero
expanded. See :option:`WIDTH`.
.. option:: WIDTHTRUNC
A more granular :option:`WIDTH` warning, for when a value is
truncated. See :option:`WIDTH`.
.. option:: WIDTHXZEXPAND
A more granular :option:`WIDTH` warning, for when a value is X/Z
expanded. See :option:`WIDTH`.
.. option:: ZERODLY
Warns that `#0` delays do not schedule the process to be resumed in the

View File

@ -1903,7 +1903,7 @@ find what made a <e#*#*> line in the tree dumps):
::
watch AstNode::s_editCntGbl==####
watch AstNode::s_editCntGbl=####
Then, when the watch fires, to break at every following change to that
node:
@ -2046,6 +2046,11 @@ driver.py Non-Scenario Arguments
Same as ``verilator --debugi level``: Set Verilator internal debugging
level globally to the specified debug level (1-10).
--driver-clean
After a test passes, remove the generated objects. Reduces storage
requirements, but may result in longer runtime if the tests are run
again.
--dump-tree
Same as ``verilator --dump-tree``: Enable Verilator writing .tree debug
files with dumping level 3, which dumps the standard critical stages.
@ -2079,6 +2084,9 @@ driver.py Non-Scenario Arguments
Run number of parallel tests, or 0 to determine the count based on the
number of cores installed.
--obj-suffix <name>
Append the argument to the name of the ``test_regress/obj_`` directories.
--quiet
Suppress all output except for failures and progress messages every 15
seconds. Intended for use only in automated regressions. See also

View File

@ -273,6 +273,7 @@ Mednick
Mei
Melo
Menküc
Menon
Michail
Michiels
Microsystems
@ -303,6 +304,7 @@ Nauticus
Newgard
Nigam
Nikana
Niraj
Niranjan
Nitza
Noack
@ -652,6 +654,7 @@ elike
elsif
endcase
endcelldefine
endclass
endfunction
endgenerate
endian
@ -862,6 +865,7 @@ noprivate
noreturn
notif
nullptr
numactl
onehot
ooo
oprofile
@ -1099,6 +1103,7 @@ verilogmod
verimake
veriuser
vl
vlSelf
vlopt
vlt
vltstd

View File

@ -20,9 +20,11 @@
# binary relative to $VERILATOR_ROOT (such as when inside the git sources).
ifeq ($(VERILATOR_ROOT),)
VERILATOR = verilator
VERILATOR_COVERAGE = verilator_coverage
else
export VERILATOR_ROOT
VERILATOR = $(VERILATOR_ROOT)/bin/verilator
VERILATOR_COVERAGE = $(VERILATOR_ROOT)/bin/verilator_coverage
endif
######################################################################

View File

@ -20,9 +20,11 @@
# binary relative to $VERILATOR_ROOT (such as when inside the git sources).
ifeq ($(VERILATOR_ROOT),)
VERILATOR = verilator
VERILATOR_COVERAGE = verilator_coverage
else
export VERILATOR_ROOT
VERILATOR = $(VERILATOR_ROOT)/bin/verilator
VERILATOR_COVERAGE = $(VERILATOR_ROOT)/bin/verilator_coverage
endif
######################################################################

View File

@ -20,9 +20,11 @@
# binary relative to $VERILATOR_ROOT (such as when inside the git sources).
ifeq ($(VERILATOR_ROOT),)
VERILATOR = verilator
VERILATOR_COVERAGE = verilator_coverage
else
export VERILATOR_ROOT
VERILATOR = $(VERILATOR_ROOT)/bin/verilator
VERILATOR_COVERAGE = $(VERILATOR_ROOT)/bin/verilator_coverage
endif
######################################################################

View File

@ -36,7 +36,7 @@ add_executable(example ../make_tracing_c/sim_main.cpp)
target_compile_features(example PUBLIC cxx_std_14)
# Add the Verilated circuit to the target
verilate(example COVERAGE TRACE
verilate(example COVERAGE TRACE_VCD
INCLUDE_DIRS "../make_tracing_c"
VERILATOR_ARGS -f ../make_tracing_c/input.vc -x-assign fast
SOURCES ../make_tracing_c/top.v

View File

@ -20,9 +20,11 @@
# binary relative to $VERILATOR_ROOT (such as when inside the git sources).
ifeq ($(VERILATOR_ROOT),)
VERILATOR = verilator
VERILATOR_COVERAGE = verilator_coverage
else
export VERILATOR_ROOT
VERILATOR = $(VERILATOR_ROOT)/bin/verilator
VERILATOR_COVERAGE = $(VERILATOR_ROOT)/bin/verilator_coverage
endif
######################################################################
@ -59,7 +61,7 @@ run:
@echo
@echo "-- RUN ---------------------"
@mkdir -p logs
build/example +trace
build/example +trace_vcd
@echo
@echo "-- COVERAGE ----------------"

View File

@ -46,7 +46,7 @@ target_compile_features(example PUBLIC cxx_std_14)
set_property(TARGET example PROPERTY CXX_STANDARD ${SystemC_CXX_STANDARD})
# Add the Verilated circuit to the target
verilate(example SYSTEMC COVERAGE TRACE
verilate(example COVERAGE SYSTEMC TRACE_VCD
INCLUDE_DIRS "../make_tracing_sc"
VERILATOR_ARGS -f ../make_tracing_sc/input.vc -x-assign fast
SOURCES ../make_tracing_sc/top.v

View File

@ -20,9 +20,11 @@
# binary relative to $VERILATOR_ROOT (such as when inside the git sources).
ifeq ($(VERILATOR_ROOT),)
VERILATOR = verilator
VERILATOR_COVERAGE = verilator_coverage
else
export VERILATOR_ROOT
VERILATOR = $(VERILATOR_ROOT)/bin/verilator
VERILATOR_COVERAGE = $(VERILATOR_ROOT)/bin/verilator_coverage
endif
######################################################################
@ -77,7 +79,7 @@ run:
@echo
@echo "-- RUN ---------------------"
@mkdir -p logs
build/example +trace
build/example +trace_vcd
@echo
@echo "-- COVERAGE ----------------"

View File

@ -58,11 +58,11 @@ class VlHierGraph:
top_module = False
fh.write("];\n")
cells = self.flatten(mod, lambda n: n['type'] == "CELL")
for cell in cells:
def_number = self.addr_to_vertex_number(cell['modp'])
instances = self.flatten(mod, lambda n: n['type'] == "CELL")
for inst in instances:
def_number = self.addr_to_vertex_number(inst['modp'])
fh.write(" n%d->n%d [label=\"%s\"];\n" %
(mod_number, def_number, cell['name']))
(mod_number, def_number, inst['name']))
fh.write("}\n")

View File

@ -43,7 +43,7 @@ VERILATOR_FLAGS += -Wall
VERILATOR_FLAGS += -CFLAGS -DVL_TIME_CONTEXT
# Make waveforms
TOP_VERILATOR_FLAGS = $(VERILATOR_FLAGS) --trace
TOP_VERILATOR_FLAGS = $(VERILATOR_FLAGS) --trace-vcd
######################################################################
default: run

View File

@ -12,19 +12,26 @@ module secret_impl
input [31:0] a,
input [31:0] b,
output logic [31:0] x,
input clk);
input clk,
input reset_l);
logic [31:0] accum_q = 0;
logic [31:0] secret_value = 9;
logic [31:0] accum_q;
logic [31:0] secret_value;
initial $display("[%0t] %m: initialized", $time);
always @(posedge clk) begin
accum_q <= accum_q + a;
if (accum_q > 10)
x <= b;
else
x <= a + b + secret_value;
if (!reset_l) begin
accum_q <= 0;
secret_value <= 9;
end
else begin
accum_q <= accum_q + a;
if (accum_q > 10)
x <= b;
else
x <= a + b + secret_value;
end
end
endmodule

View File

@ -8,26 +8,36 @@
module top (input clk);
integer cyc = 0;
logic [31:0] a = 0;
logic [31:0] b = 0;
int cyc;
logic reset_l;
logic [31:0] a;
logic [31:0] b;
logic [31:0] x;
verilated_secret secret (.a, .b, .x, .clk);
verilated_secret secret (.a, .b, .x, .clk, .reset_l);
always @(posedge clk) begin
$display("[%0t] cyc=%0d a=%0d b=%0d x=%0d", $time, cyc, a, b, x);
cyc <= cyc + 1;
if (cyc == 0) begin
reset_l <= 0;
a <= 0;
b <= 0;
end
else if (cyc == 1) begin
reset_l <= 1;
a <= 5;
b <= 7;
end else if (cyc == 1) begin
end
else if (cyc == 2) begin
a <= 6;
b <= 2;
end else if (cyc == 2) begin
end
else if (cyc == 3) begin
a <= 1;
b <= 9;
end else if (cyc > 3) begin
end
else if (cyc > 4) begin
$display("Done");
$finish;
end

View File

@ -40,7 +40,7 @@ VERILATOR_FLAGS += -x-assign fast
# Warn abount lint issues; may not want this on less solid designs
VERILATOR_FLAGS += -Wall
# Make waveforms
VERILATOR_FLAGS += --trace
VERILATOR_FLAGS += --trace-vcd
# Check SystemVerilog assertions
VERILATOR_FLAGS += --assert
# Generate coverage analysis

View File

@ -41,7 +41,7 @@ VERILATOR_FLAGS += -x-assign fast
# Warn abount lint issues; may not want this on less solid designs
VERILATOR_FLAGS += -Wall
# Make waveforms
VERILATOR_FLAGS += --trace
VERILATOR_FLAGS += --trace-vcd
# Check SystemVerilog assertions
VERILATOR_FLAGS += --assert
# Generate coverage analysis

View File

@ -37,10 +37,9 @@
*
*/
// #ifndef FST_CONFIG_INCLUDE
// # define FST_CONFIG_INCLUDE <config.h>
// #endif
// #include FST_CONFIG_INCLUDE
#ifdef FST_INCLUDE_CONFIG
#include <config.h>
#endif
#include "fstapi.h"
#include "fastlz.h"
@ -60,21 +59,6 @@
#include <windows.h>
#endif
#ifdef HAVE_ALLOCA_H
#include <alloca.h>
#elif defined(__GNUC__)
#ifndef __MINGW32__
#ifndef alloca
#define alloca __builtin_alloca
#endif
#else
#include <malloc.h>
#endif
#elif defined(_MSC_VER)
#include <malloc.h>
#define alloca _alloca
#endif
#ifndef PATH_MAX
#define PATH_MAX (4096)
#endif
@ -1113,10 +1097,9 @@ static void fstDetermineBreakSize(struct fstWriterContext *xc)
/*
* file creation and close
*/
void *fstWriterCreate(const char *nam, int use_compressed_hier)
fstWriterContext *fstWriterCreate(const char *nam, int use_compressed_hier)
{
struct fstWriterContext *xc =
(struct fstWriterContext *)calloc(1, sizeof(struct fstWriterContext));
fstWriterContext *xc = (fstWriterContext *)calloc(1, sizeof(fstWriterContext));
xc->compress_hier = use_compressed_hier;
fstDetermineBreakSize(xc);
@ -1175,10 +1158,8 @@ void *fstWriterCreate(const char *nam, int use_compressed_hier)
/*
* generation and writing out of value change data sections
*/
static void fstWriterEmitSectionHeader(void *ctx)
static void fstWriterEmitSectionHeader(fstWriterContext *xc)
{
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
if (xc) {
unsigned long destlen;
unsigned char *dmem;
@ -1235,9 +1216,9 @@ static void fstWriterEmitSectionHeader(void *ctx)
* be synced up with time changes
*/
#ifdef FST_WRITER_PARALLEL
static void fstWriterFlushContextPrivate2(void *ctx)
static void fstWriterFlushContextPrivate2(fstWriterContext *xc)
#else
static void fstWriterFlushContextPrivate(void *ctx)
static void fstWriterFlushContextPrivate(fstWriterContext *xc)
#endif
{
#ifdef FST_DEBUG
@ -1257,7 +1238,6 @@ static void fstWriterFlushContextPrivate(void *ctx)
unsigned char *packmem;
unsigned int packmemlen;
uint32_t *vm4ip;
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
#ifdef FST_WRITER_PARALLEL
struct fstWriterContext *xc2 = xc->xc_parent;
#else
@ -1775,10 +1755,8 @@ static void *fstWriterFlushContextPrivate1(void *ctx)
return (NULL);
}
static void fstWriterFlushContextPrivate(void *ctx)
static void fstWriterFlushContextPrivate(fstWriterContext *xc)
{
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
if (xc->parallel_enabled) {
struct fstWriterContext *xc2 =
(struct fstWriterContext *)malloc(sizeof(struct fstWriterContext));
@ -1852,9 +1830,8 @@ static void fstWriterFlushContextPrivate(void *ctx)
/*
* queues up a flush context operation
*/
void fstWriterFlushContext(void *ctx)
void fstWriterFlushContext(fstWriterContext *xc)
{
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
if (xc) {
if (xc->tchn_idx > 1) {
xc->flush_context_pending = 1;
@ -1865,10 +1842,8 @@ void fstWriterFlushContext(void *ctx)
/*
* close out FST file
*/
void fstWriterClose(void *ctx)
void fstWriterClose(fstWriterContext *xc)
{
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
#ifdef FST_WRITER_PARALLEL
if (xc) {
pthread_mutex_lock(&xc->mutex);
@ -2234,9 +2209,8 @@ void fstWriterClose(void *ctx)
/*
* functions to set miscellaneous header/block information
*/
void fstWriterSetDate(void *ctx, const char *dat)
void fstWriterSetDate(fstWriterContext *xc, const char *dat)
{
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
if (xc) {
char s[FST_HDR_DATE_SIZE];
fst_off_t fpos = ftello(xc->handle);
@ -2251,9 +2225,8 @@ void fstWriterSetDate(void *ctx, const char *dat)
}
}
void fstWriterSetVersion(void *ctx, const char *vers)
void fstWriterSetVersion(fstWriterContext *xc, const char *vers)
{
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
if (xc && vers) {
char s[FST_HDR_SIM_VERSION_SIZE];
fst_off_t fpos = ftello(xc->handle);
@ -2268,9 +2241,8 @@ void fstWriterSetVersion(void *ctx, const char *vers)
}
}
void fstWriterSetFileType(void *ctx, enum fstFileType filetype)
void fstWriterSetFileType(fstWriterContext *xc, enum fstFileType filetype)
{
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
if (xc) {
if (/*(filetype >= FST_FT_MIN) &&*/ (filetype <= FST_FT_MAX)) {
fst_off_t fpos = ftello(xc->handle);
@ -2285,9 +2257,11 @@ void fstWriterSetFileType(void *ctx, enum fstFileType filetype)
}
}
static void fstWriterSetAttrDoubleArgGeneric(void *ctx, int typ, uint64_t arg1, uint64_t arg2)
static void fstWriterSetAttrDoubleArgGeneric(fstWriterContext *xc,
int typ,
uint64_t arg1,
uint64_t arg2)
{
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
if (xc) {
unsigned char buf[11]; /* ceil(64/7) = 10 + null term */
unsigned char *pnt = fstCopyVarint64ToRight(buf, arg1);
@ -2300,9 +2274,8 @@ static void fstWriterSetAttrDoubleArgGeneric(void *ctx, int typ, uint64_t arg1,
}
}
static void fstWriterSetAttrGeneric(void *ctx, const char *comm, int typ, uint64_t arg)
static void fstWriterSetAttrGeneric(fstWriterContext *xc, const char *comm, int typ, uint64_t arg)
{
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
if (xc && comm) {
char *s = strdup(comm);
char *sf = s;
@ -2318,14 +2291,12 @@ static void fstWriterSetAttrGeneric(void *ctx, const char *comm, int typ, uint64
}
}
static void fstWriterSetSourceStem_2(void *ctx,
static void fstWriterSetSourceStem_2(fstWriterContext *xc,
const char *path,
unsigned int line,
unsigned int use_realpath,
int typ)
{
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
if (xc && path && path[0]) {
uint64_t sidx = 0;
int slen = strlen(path);
@ -2357,7 +2328,7 @@ static void fstWriterSetSourceStem_2(void *ctx,
}
}
void fstWriterSetSourceStem(void *ctx,
void fstWriterSetSourceStem(fstWriterContext *ctx,
const char *path,
unsigned int line,
unsigned int use_realpath)
@ -2365,7 +2336,7 @@ void fstWriterSetSourceStem(void *ctx,
fstWriterSetSourceStem_2(ctx, path, line, use_realpath, FST_MT_SOURCESTEM);
}
void fstWriterSetSourceInstantiationStem(void *ctx,
void fstWriterSetSourceInstantiationStem(fstWriterContext *ctx,
const char *path,
unsigned int line,
unsigned int use_realpath)
@ -2373,24 +2344,23 @@ void fstWriterSetSourceInstantiationStem(void *ctx,
fstWriterSetSourceStem_2(ctx, path, line, use_realpath, FST_MT_SOURCEISTEM);
}
void fstWriterSetComment(void *ctx, const char *comm)
void fstWriterSetComment(fstWriterContext *ctx, const char *comm)
{
fstWriterSetAttrGeneric(ctx, comm, FST_MT_COMMENT, 0);
}
void fstWriterSetValueList(void *ctx, const char *vl)
void fstWriterSetValueList(fstWriterContext *ctx, const char *vl)
{
fstWriterSetAttrGeneric(ctx, vl, FST_MT_VALUELIST, 0);
}
void fstWriterSetEnvVar(void *ctx, const char *envvar)
void fstWriterSetEnvVar(fstWriterContext *ctx, const char *envvar)
{
fstWriterSetAttrGeneric(ctx, envvar, FST_MT_ENVVAR, 0);
}
void fstWriterSetTimescale(void *ctx, int ts)
void fstWriterSetTimescale(fstWriterContext *xc, int ts)
{
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
if (xc) {
fst_off_t fpos = ftello(xc->handle);
fstWriterFseeko(xc, xc->handle, FST_HDR_OFFS_TIMESCALE, SEEK_SET);
@ -2400,9 +2370,8 @@ void fstWriterSetTimescale(void *ctx, int ts)
}
}
void fstWriterSetTimescaleFromString(void *ctx, const char *s)
void fstWriterSetTimescaleFromString(fstWriterContext *xc, const char *s)
{
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
if (xc && s) {
int mat = 0;
int seconds_exp = -9;
@ -2458,13 +2427,12 @@ void fstWriterSetTimescaleFromString(void *ctx, const char *s)
seconds_exp += 2;
}
fstWriterSetTimescale(ctx, seconds_exp);
fstWriterSetTimescale(xc, seconds_exp);
}
}
void fstWriterSetTimezero(void *ctx, int64_t tim)
void fstWriterSetTimezero(fstWriterContext *xc, int64_t tim)
{
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
if (xc) {
fst_off_t fpos = ftello(xc->handle);
fstWriterFseeko(xc, xc->handle, FST_HDR_OFFS_TIMEZERO, SEEK_SET);
@ -2474,26 +2442,23 @@ void fstWriterSetTimezero(void *ctx, int64_t tim)
}
}
void fstWriterSetPackType(void *ctx, enum fstWriterPackType typ)
void fstWriterSetPackType(fstWriterContext *xc, enum fstWriterPackType typ)
{
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
if (xc) {
xc->fastpack = (typ != FST_WR_PT_ZLIB);
xc->fourpack = (typ == FST_WR_PT_LZ4);
}
}
void fstWriterSetRepackOnClose(void *ctx, int enable)
void fstWriterSetRepackOnClose(fstWriterContext *xc, int enable)
{
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
if (xc) {
xc->repack_on_close = (enable != 0);
}
}
void fstWriterSetParallelMode(void *ctx, int enable)
void fstWriterSetParallelMode(fstWriterContext *xc, int enable)
{
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
if (xc) {
xc->parallel_was_enabled |= xc->parallel_enabled; /* make sticky */
xc->parallel_enabled = (enable != 0);
@ -2508,17 +2473,15 @@ void fstWriterSetParallelMode(void *ctx, int enable)
}
}
void fstWriterSetDumpSizeLimit(void *ctx, uint64_t numbytes)
void fstWriterSetDumpSizeLimit(fstWriterContext *xc, uint64_t numbytes)
{
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
if (xc) {
xc->dump_size_limit = numbytes;
}
}
int fstWriterGetDumpSizeLimitReached(void *ctx)
int fstWriterGetDumpSizeLimitReached(fstWriterContext *xc)
{
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
if (xc) {
return (xc->size_limit_locked != 0);
}
@ -2526,9 +2489,8 @@ int fstWriterGetDumpSizeLimitReached(void *ctx)
return (0);
}
int fstWriterGetFseekFailed(void *ctx)
int fstWriterGetFseekFailed(fstWriterContext *xc)
{
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
if (xc) {
return (xc->fseek_failed != 0);
}
@ -2536,14 +2498,13 @@ int fstWriterGetFseekFailed(void *ctx)
return (0);
}
static int fstWriterGetFlushContextPendingInternal(struct fstWriterContext *xc)
static int fstWriterGetFlushContextPendingInternal(fstWriterContext *xc)
{
return (xc->vchg_siz >= xc->fst_break_size) || (xc->flush_context_pending);
}
int fstWriterGetFlushContextPending(void *ctx)
int fstWriterGetFlushContextPending(fstWriterContext *xc)
{
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
return xc && !xc->is_initial_time && fstWriterGetFlushContextPendingInternal(xc);
}
@ -2552,7 +2513,7 @@ int fstWriterGetFlushContextPending(void *ctx)
* fstWriterCreateVar2() is used to dump VHDL or other languages, but the
* underlying variable needs to map to Verilog/SV via the proper fstVarType vt
*/
fstHandle fstWriterCreateVar2(void *ctx,
fstHandle fstWriterCreateVar2(fstWriterContext *ctx,
enum fstVarType vt,
enum fstVarDir vd,
uint32_t len,
@ -2569,14 +2530,13 @@ fstHandle fstWriterCreateVar2(void *ctx,
return (fstWriterCreateVar(ctx, vt, vd, len, nam, aliasHandle));
}
fstHandle fstWriterCreateVar(void *ctx,
fstHandle fstWriterCreateVar(fstWriterContext *xc,
enum fstVarType vt,
enum fstVarDir vd,
uint32_t len,
const char *nam,
fstHandle aliasHandle)
{
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
unsigned int i;
int nlen, is_real;
@ -2660,13 +2620,11 @@ fstHandle fstWriterCreateVar(void *ctx,
return (0);
}
void fstWriterSetScope(void *ctx,
void fstWriterSetScope(fstWriterContext *xc,
enum fstScopeType scopetype,
const char *scopename,
const char *scopecomp)
{
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
if (xc) {
fputc(FST_ST_VCD_SCOPE, xc->hier_handle);
if (/*(scopetype < FST_ST_VCD_MODULE) ||*/ (scopetype > FST_ST_MAX)) {
@ -2692,24 +2650,20 @@ void fstWriterSetScope(void *ctx,
}
}
void fstWriterSetUpscope(void *ctx)
void fstWriterSetUpscope(fstWriterContext *xc)
{
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
if (xc) {
fputc(FST_ST_VCD_UPSCOPE, xc->hier_handle);
xc->hier_file_len++;
}
}
void fstWriterSetAttrBegin(void *ctx,
void fstWriterSetAttrBegin(fstWriterContext *xc,
enum fstAttrType attrtype,
int subtype,
const char *attrname,
uint64_t arg)
{
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
if (xc) {
fputc(FST_ST_GEN_ATTRBEGIN, xc->hier_handle);
if (/*(attrtype < FST_AT_MISC) ||*/ (attrtype > FST_AT_MAX)) {
@ -2750,17 +2704,15 @@ void fstWriterSetAttrBegin(void *ctx,
}
}
void fstWriterSetAttrEnd(void *ctx)
void fstWriterSetAttrEnd(fstWriterContext *xc)
{
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
if (xc) {
fputc(FST_ST_GEN_ATTREND, xc->hier_handle);
xc->hier_file_len++;
}
}
fstEnumHandle fstWriterCreateEnumTable(void *ctx,
fstEnumHandle fstWriterCreateEnumTable(fstWriterContext *xc,
const char *name,
uint32_t elem_count,
unsigned int min_valbits,
@ -2779,9 +2731,7 @@ fstEnumHandle fstWriterCreateEnumTable(void *ctx,
int pos = 0;
char *attr_str = NULL;
if (ctx && name && literal_arr && val_arr && (elem_count != 0)) {
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
if (xc && name && literal_arr && val_arr && (elem_count != 0)) {
uint32_t i;
name_len = strlen(name);
@ -2866,9 +2816,8 @@ fstEnumHandle fstWriterCreateEnumTable(void *ctx,
return (handle);
}
void fstWriterEmitEnumTableRef(void *ctx, fstEnumHandle handle)
void fstWriterEmitEnumTableRef(fstWriterContext *xc, fstEnumHandle handle)
{
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
if (xc && handle) {
fstWriterSetAttrBegin(xc, FST_AT_MISC, FST_MT_ENUMTABLE, NULL, handle);
}
@ -2877,9 +2826,8 @@ void fstWriterEmitEnumTableRef(void *ctx, fstEnumHandle handle)
/*
* value and time change emission
*/
void fstWriterEmitValueChange(void *ctx, fstHandle handle, const void *val)
void fstWriterEmitValueChange(fstWriterContext *xc, fstHandle handle, const void *val)
{
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
const unsigned char *buf = (const unsigned char *)val;
uint32_t offs;
int len;
@ -2987,7 +2935,10 @@ void fstWriterEmitValueChange(void *ctx, fstHandle handle, const void *val)
}
}
void fstWriterEmitValueChange32(void *ctx, fstHandle handle, uint32_t bits, uint32_t val)
void fstWriterEmitValueChange32(fstWriterContext *ctx,
fstHandle handle,
uint32_t bits,
uint32_t val)
{
char buf[32];
char *s = buf;
@ -2997,7 +2948,11 @@ void fstWriterEmitValueChange32(void *ctx, fstHandle handle, uint32_t bits, uint
}
fstWriterEmitValueChange(ctx, handle, buf);
}
void fstWriterEmitValueChange64(void *ctx, fstHandle handle, uint32_t bits, uint64_t val)
void fstWriterEmitValueChange64(fstWriterContext *ctx,
fstHandle handle,
uint32_t bits,
uint64_t val)
{
char buf[64];
char *s = buf;
@ -3007,11 +2962,14 @@ void fstWriterEmitValueChange64(void *ctx, fstHandle handle, uint32_t bits, uint
}
fstWriterEmitValueChange(ctx, handle, buf);
}
void fstWriterEmitValueChangeVec32(void *ctx, fstHandle handle, uint32_t bits, const uint32_t *val)
void fstWriterEmitValueChangeVec32(fstWriterContext *xc,
fstHandle handle,
uint32_t bits,
const uint32_t *val)
{
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
if (FST_UNLIKELY(bits <= 32)) {
fstWriterEmitValueChange32(ctx, handle, bits, val[0]);
fstWriterEmitValueChange32(xc, handle, bits, val[0]);
} else if (FST_LIKELY(xc)) {
int bq = bits / 32;
int br = bits & 31;
@ -3047,14 +3005,16 @@ void fstWriterEmitValueChangeVec32(void *ctx, fstHandle handle, uint32_t bits, c
s += 4;
}
}
fstWriterEmitValueChange(ctx, handle, xc->outval_mem);
fstWriterEmitValueChange(xc, handle, xc->outval_mem);
}
}
void fstWriterEmitValueChangeVec64(void *ctx, fstHandle handle, uint32_t bits, const uint64_t *val)
void fstWriterEmitValueChangeVec64(fstWriterContext *xc,
fstHandle handle,
uint32_t bits,
const uint64_t *val)
{
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
if (FST_UNLIKELY(bits <= 64)) {
fstWriterEmitValueChange64(ctx, handle, bits, val[0]);
fstWriterEmitValueChange64(xc, handle, bits, val[0]);
} else if (FST_LIKELY(xc)) {
int bq = bits / 64;
int br = bits & 63;
@ -3090,16 +3050,15 @@ void fstWriterEmitValueChangeVec64(void *ctx, fstHandle handle, uint32_t bits, c
s += 4;
}
}
fstWriterEmitValueChange(ctx, handle, xc->outval_mem);
fstWriterEmitValueChange(xc, handle, xc->outval_mem);
}
}
void fstWriterEmitVariableLengthValueChange(void *ctx,
void fstWriterEmitVariableLengthValueChange(fstWriterContext *xc,
fstHandle handle,
const void *val,
uint32_t len)
{
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
const unsigned char *buf = (const unsigned char *)val;
if (FST_LIKELY((xc) && (handle <= xc->maxhandle))) {
@ -3143,9 +3102,8 @@ void fstWriterEmitVariableLengthValueChange(void *ctx,
}
}
void fstWriterEmitTimeChange(void *ctx, uint64_t tim)
void fstWriterEmitTimeChange(fstWriterContext *xc, uint64_t tim)
{
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
unsigned int i;
int skip = 0;
if (xc) {
@ -3189,10 +3147,8 @@ void fstWriterEmitTimeChange(void *ctx, uint64_t tim)
}
}
void fstWriterEmitDumpActive(void *ctx, int enable)
void fstWriterEmitDumpActive(fstWriterContext *xc, int enable)
{
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
if (xc) {
struct fstBlackoutChain *b =
(struct fstBlackoutChain *)calloc(1, sizeof(struct fstBlackoutChain));
@ -3420,7 +3376,7 @@ static void fstWritex(struct fstReaderContext *xc,
/*
* scope -> flat name handling
*/
static void fstReaderDeallocateScopeData(struct fstReaderContext *xc)
static void fstReaderDeallocateScopeData(fstReaderContext *xc)
{
struct fstCurrHier *chp;
@ -3433,9 +3389,8 @@ static void fstReaderDeallocateScopeData(struct fstReaderContext *xc)
}
}
const char *fstReaderGetCurrentFlatScope(void *ctx)
const char *fstReaderGetCurrentFlatScope(fstReaderContext *xc)
{
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
if (xc) {
return (xc->curr_flat_hier_nam ? xc->curr_flat_hier_nam : "");
} else {
@ -3443,9 +3398,8 @@ const char *fstReaderGetCurrentFlatScope(void *ctx)
}
}
void *fstReaderGetCurrentScopeUserInfo(void *ctx)
void *fstReaderGetCurrentScopeUserInfo(fstReaderContext *xc)
{
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
if (xc) {
return (xc->curr_hier ? xc->curr_hier->user_info : NULL);
} else {
@ -3453,9 +3407,8 @@ void *fstReaderGetCurrentScopeUserInfo(void *ctx)
}
}
const char *fstReaderPopScope(void *ctx)
const char *fstReaderPopScope(fstReaderContext *xc)
{
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
if (xc && xc->curr_hier) {
struct fstCurrHier *ch = xc->curr_hier;
if (xc->curr_hier->prev) {
@ -3471,19 +3424,16 @@ const char *fstReaderPopScope(void *ctx)
return (NULL);
}
void fstReaderResetScope(void *ctx)
void fstReaderResetScope(fstReaderContext *xc)
{
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
if (xc) {
while (fstReaderPopScope(xc))
; /* remove any already-built scoping info */
}
}
const char *fstReaderPushScope(void *ctx, const char *nam, void *user_info)
const char *fstReaderPushScope(fstReaderContext *xc, const char *nam, void *user_info)
{
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
if (xc) {
struct fstCurrHier *ch = (struct fstCurrHier *)malloc(sizeof(struct fstCurrHier));
int chl = xc->curr_hier ? xc->curr_hier->len : 0;
@ -3512,10 +3462,8 @@ const char *fstReaderPushScope(void *ctx, const char *nam, void *user_info)
return (NULL);
}
int fstReaderGetCurrentScopeLen(void *ctx)
int fstReaderGetCurrentScopeLen(fstReaderContext *xc)
{
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
if (xc && xc->curr_hier) {
return (xc->curr_hier->len);
}
@ -3523,9 +3471,8 @@ int fstReaderGetCurrentScopeLen(void *ctx)
return (0);
}
int fstReaderGetFseekFailed(void *ctx)
int fstReaderGetFseekFailed(fstReaderContext *xc)
{
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
if (xc) {
return (xc->fseek_failed != 0);
}
@ -3536,10 +3483,8 @@ int fstReaderGetFseekFailed(void *ctx)
/*
* iter mask manipulation util functions
*/
int fstReaderGetFacProcessMask(void *ctx, fstHandle facidx)
int fstReaderGetFacProcessMask(fstReaderContext *xc, fstHandle facidx)
{
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
if (xc) {
facidx--;
if (facidx < xc->maxhandle) {
@ -3552,10 +3497,8 @@ int fstReaderGetFacProcessMask(void *ctx, fstHandle facidx)
return (0);
}
void fstReaderSetFacProcessMask(void *ctx, fstHandle facidx)
void fstReaderSetFacProcessMask(fstReaderContext *xc, fstHandle facidx)
{
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
if (xc) {
facidx--;
if (facidx < xc->maxhandle) {
@ -3567,10 +3510,8 @@ void fstReaderSetFacProcessMask(void *ctx, fstHandle facidx)
}
}
void fstReaderClrFacProcessMask(void *ctx, fstHandle facidx)
void fstReaderClrFacProcessMask(fstReaderContext *xc, fstHandle facidx)
{
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
if (xc) {
facidx--;
if (facidx < xc->maxhandle) {
@ -3582,19 +3523,15 @@ void fstReaderClrFacProcessMask(void *ctx, fstHandle facidx)
}
}
void fstReaderSetFacProcessMaskAll(void *ctx)
void fstReaderSetFacProcessMaskAll(fstReaderContext *xc)
{
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
if (xc) {
memset(xc->process_mask, 0xff, (xc->maxhandle + 7) / 8);
}
}
void fstReaderClrFacProcessMaskAll(void *ctx)
void fstReaderClrFacProcessMaskAll(fstReaderContext *xc)
{
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
if (xc) {
memset(xc->process_mask, 0x00, (xc->maxhandle + 7) / 8);
}
@ -3603,100 +3540,83 @@ void fstReaderClrFacProcessMaskAll(void *ctx)
/*
* various utility read/write functions
*/
signed char fstReaderGetTimescale(void *ctx)
signed char fstReaderGetTimescale(fstReaderContext *xc)
{
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
return (xc ? xc->timescale : 0);
}
uint64_t fstReaderGetStartTime(void *ctx)
uint64_t fstReaderGetStartTime(fstReaderContext *xc)
{
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
return (xc ? xc->start_time : 0);
}
uint64_t fstReaderGetEndTime(void *ctx)
uint64_t fstReaderGetEndTime(fstReaderContext *xc)
{
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
return (xc ? xc->end_time : 0);
}
uint64_t fstReaderGetMemoryUsedByWriter(void *ctx)
uint64_t fstReaderGetMemoryUsedByWriter(fstReaderContext *xc)
{
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
return (xc ? xc->mem_used_by_writer : 0);
}
uint64_t fstReaderGetScopeCount(void *ctx)
uint64_t fstReaderGetScopeCount(fstReaderContext *xc)
{
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
return (xc ? xc->scope_count : 0);
}
uint64_t fstReaderGetVarCount(void *ctx)
uint64_t fstReaderGetVarCount(fstReaderContext *xc)
{
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
return (xc ? xc->var_count : 0);
}
fstHandle fstReaderGetMaxHandle(void *ctx)
fstHandle fstReaderGetMaxHandle(fstReaderContext *xc)
{
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
return (xc ? xc->maxhandle : 0);
}
uint64_t fstReaderGetAliasCount(void *ctx)
uint64_t fstReaderGetAliasCount(fstReaderContext *xc)
{
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
return (xc ? xc->num_alias : 0);
}
uint64_t fstReaderGetValueChangeSectionCount(void *ctx)
uint64_t fstReaderGetValueChangeSectionCount(fstReaderContext *xc)
{
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
return (xc ? xc->vc_section_count : 0);
}
int fstReaderGetDoubleEndianMatchState(void *ctx)
int fstReaderGetDoubleEndianMatchState(fstReaderContext *xc)
{
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
return (xc ? xc->double_endian_match : 0);
}
const char *fstReaderGetVersionString(void *ctx)
const char *fstReaderGetVersionString(fstReaderContext *xc)
{
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
return (xc ? xc->version : NULL);
}
const char *fstReaderGetDateString(void *ctx)
const char *fstReaderGetDateString(fstReaderContext *xc)
{
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
return (xc ? xc->date : NULL);
}
int fstReaderGetFileType(void *ctx)
int fstReaderGetFileType(fstReaderContext *xc)
{
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
return (xc ? (int)xc->filetype : (int)FST_FT_VERILOG);
}
int64_t fstReaderGetTimezero(void *ctx)
int64_t fstReaderGetTimezero(fstReaderContext *xc)
{
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
return (xc ? xc->timezero : 0);
}
uint32_t fstReaderGetNumberDumpActivityChanges(void *ctx)
uint32_t fstReaderGetNumberDumpActivityChanges(fstReaderContext *xc)
{
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
return (xc ? xc->num_blackouts : 0);
}
uint64_t fstReaderGetDumpActivityChangeTime(void *ctx, uint32_t idx)
uint64_t fstReaderGetDumpActivityChangeTime(fstReaderContext *xc, uint32_t idx)
{
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
if (xc && (idx < xc->num_blackouts) && (xc->blackout_times)) {
return (xc->blackout_times[idx]);
} else {
@ -3704,10 +3624,8 @@ uint64_t fstReaderGetDumpActivityChangeTime(void *ctx, uint32_t idx)
}
}
unsigned char fstReaderGetDumpActivityChangeValue(void *ctx, uint32_t idx)
unsigned char fstReaderGetDumpActivityChangeValue(fstReaderContext *xc, uint32_t idx)
{
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
if (xc && (idx < xc->num_blackouts) && (xc->blackout_activity)) {
return (xc->blackout_activity[idx]);
} else {
@ -3715,10 +3633,8 @@ unsigned char fstReaderGetDumpActivityChangeValue(void *ctx, uint32_t idx)
}
}
void fstReaderSetLimitTimeRange(void *ctx, uint64_t start_time, uint64_t end_time)
void fstReaderSetLimitTimeRange(fstReaderContext *xc, uint64_t start_time, uint64_t end_time)
{
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
if (xc) {
xc->limit_range_valid = 1;
xc->limit_range_start = start_time;
@ -3726,27 +3642,22 @@ void fstReaderSetLimitTimeRange(void *ctx, uint64_t start_time, uint64_t end_tim
}
}
void fstReaderSetUnlimitedTimeRange(void *ctx)
void fstReaderSetUnlimitedTimeRange(fstReaderContext *xc)
{
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
if (xc) {
xc->limit_range_valid = 0;
}
}
void fstReaderSetVcdExtensions(void *ctx, int enable)
void fstReaderSetVcdExtensions(fstReaderContext *xc, int enable)
{
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
if (xc) {
xc->use_vcd_extensions = (enable != 0);
}
}
void fstReaderIterBlocksSetNativeDoublesOnCallback(void *ctx, int enable)
void fstReaderIterBlocksSetNativeDoublesOnCallback(fstReaderContext *xc, int enable)
{
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
if (xc) {
xc->native_doubles_for_cb = (enable != 0);
}
@ -3942,9 +3853,8 @@ static int fstReaderRecreateHierFile(struct fstReaderContext *xc)
return (pass_status);
}
int fstReaderIterateHierRewind(void *ctx)
int fstReaderIterateHierRewind(fstReaderContext *xc)
{
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
int pass_status = 0;
if (xc) {
@ -3959,13 +3869,13 @@ int fstReaderIterateHierRewind(void *ctx)
return (pass_status);
}
struct fstHier *fstReaderIterateHier(void *ctx)
struct fstHier *fstReaderIterateHier(fstReaderContext *xc)
{
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
int isfeof;
fstHandle alias;
char *pnt;
int ch;
int unnamed_scope_idx = 0;
if (!xc)
return (NULL);
@ -3997,6 +3907,9 @@ struct fstHier *fstReaderIterateHier(void *ctx)
pnt[cl++] = ch;
}
}; /* scopename */
if (!cl) {
cl = snprintf(pnt, FST_ID_NAM_SIZ, "$unnamed_scope_%d", unnamed_scope_idx++);
}
pnt[cl] = 0;
xc->hier.u.scope.name_length = cl;
@ -4122,9 +4035,8 @@ struct fstHier *fstReaderIterateHier(void *ctx)
return (!isfeof ? &xc->hier : NULL);
}
int fstReaderProcessHier(void *ctx, FILE *fv)
int fstReaderProcessHier(fstReaderContext *xc, FILE *fv)
{
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
char *str;
char *pnt;
int ch, scopetype;
@ -4136,6 +4048,7 @@ int fstReaderProcessHier(void *ctx, FILE *fv)
uint64_t attrarg;
fstHandle maxhandle_scanbuild;
int cl;
int unnamed_scope_idx = 0;
if (!xc)
return (0);
@ -4271,6 +4184,9 @@ int fstReaderProcessHier(void *ctx, FILE *fv)
pnt[cl++] = ch;
}
}; /* scopename */
if (!cl) {
cl = snprintf(pnt, FST_ID_NAM_SIZ, "$unnamed_scope_%d", unnamed_scope_idx++);
}
pnt[cl] = 0;
while (fgetc(xc->fh)) {
}; /* scopecomp */
@ -4802,18 +4718,16 @@ int fstReaderInit(struct fstReaderContext *xc)
return (hdr_seen);
}
void *fstReaderOpenForUtilitiesOnly(void)
fstReaderContext *fstReaderOpenForUtilitiesOnly(void)
{
struct fstReaderContext *xc =
(struct fstReaderContext *)calloc(1, sizeof(struct fstReaderContext));
fstReaderContext *xc = (fstReaderContext *)calloc(1, sizeof(fstReaderContext));
return (xc);
}
void *fstReaderOpen(const char *nam)
fstReaderContext *fstReaderOpen(const char *nam)
{
struct fstReaderContext *xc =
(struct fstReaderContext *)calloc(1, sizeof(struct fstReaderContext));
fstReaderContext *xc = (fstReaderContext *)calloc(1, sizeof(fstReaderContext));
if ((!nam) || (!(xc->f = fopen(nam, "rb")))) {
free(xc);
@ -4842,7 +4756,7 @@ void *fstReaderOpen(const char *nam)
((xc->fh) || (xc->contains_hier_section || (xc->contains_hier_section_lz4)))) {
/* more init */
xc->do_rewind = 1;
} else {
} else if (!rc) {
fstReaderClose(xc);
xc = NULL;
}
@ -4851,9 +4765,8 @@ void *fstReaderOpen(const char *nam)
return (xc);
}
static void fstReaderDeallocateRvatData(void *ctx)
static void fstReaderDeallocateRvatData(fstReaderContext *xc)
{
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
if (xc) {
free(xc->rvat_chain_mem);
xc->rvat_chain_mem = NULL;
@ -4870,10 +4783,8 @@ static void fstReaderDeallocateRvatData(void *ctx)
}
}
void fstReaderClose(void *ctx)
void fstReaderClose(fstReaderContext *xc)
{
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
if (xc) {
fstReaderDeallocateScopeData(xc);
fstReaderDeallocateRvatData(xc);
@ -4918,7 +4829,7 @@ void fstReaderClose(void *ctx)
*/
/* normal read which re-interleaves the value change data */
int fstReaderIterBlocks(void *ctx,
int fstReaderIterBlocks(fstReaderContext *ctx,
void (*value_change_callback)(void *user_callback_data_pointer,
uint64_t time,
fstHandle facidx,
@ -4929,7 +4840,7 @@ int fstReaderIterBlocks(void *ctx,
return (fstReaderIterBlocks2(ctx, value_change_callback, NULL, user_callback_data_pointer, fv));
}
int fstReaderIterBlocks2(void *ctx,
int fstReaderIterBlocks2(fstReaderContext *ctx,
void (*value_change_callback)(void *user_callback_data_pointer,
uint64_t time,
fstHandle facidx,
@ -6003,7 +5914,7 @@ int fstReaderIterBlocks2(void *ctx,
/* rvat functions */
static char *fstExtractRvatDataFromFrame(struct fstReaderContext *xc, fstHandle facidx, char *buf)
static char *fstExtractRvatDataFromFrame(fstReaderContext *xc, fstHandle facidx, char *buf)
{
if (facidx >= xc->rvat_frame_maxhandle) {
return (NULL);
@ -6038,9 +5949,11 @@ static char *fstExtractRvatDataFromFrame(struct fstReaderContext *xc, fstHandle
return (buf);
}
char *fstReaderGetValueFromHandleAtTime(void *ctx, uint64_t tim, fstHandle facidx, char *buf)
char *fstReaderGetValueFromHandleAtTime(fstReaderContext *xc,
uint64_t tim,
fstHandle facidx,
char *buf)
{
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
fst_off_t blkpos = 0, prev_blkpos;
uint64_t beg_tim, end_tim, beg_tim2, end_tim2;
int sectype;

View File

@ -43,8 +43,6 @@ extern "C"
#endif
#include <time.h>
#define FST_RDLOAD "FSTLOAD | "
typedef uint32_t fstHandle;
typedef uint32_t fstEnumHandle;
@ -372,16 +370,19 @@ struct fstETab
/*
* writer functions
*/
void fstWriterClose(void *ctx);
void *fstWriterCreate(const char *nam, int use_compressed_hier);
fstEnumHandle fstWriterCreateEnumTable(void *ctx,
typedef struct fstWriterContext fstWriterContext;
void fstWriterClose(fstWriterContext *ctx);
fstWriterContext *fstWriterCreate(const char *nam, int use_compressed_hier);
fstEnumHandle fstWriterCreateEnumTable(fstWriterContext *ctx,
const char *name,
uint32_t elem_count,
unsigned int min_valbits,
const char **literal_arr,
const char **val_arr);
/* used for Verilog/SV */
fstHandle fstWriterCreateVar(void *ctx,
fstHandle fstWriterCreateVar(fstWriterContext *ctx,
enum fstVarType vt,
enum fstVarDir vd,
uint32_t len,
@ -390,7 +391,7 @@ fstHandle fstWriterCreateVar(void *ctx,
/* future expansion for VHDL and other languages. The variable type, data type, etc map onto
the current Verilog/SV one. The "type" string is optional for a more verbose or custom
description */
fstHandle fstWriterCreateVar2(void *ctx,
fstHandle fstWriterCreateVar2(fstWriterContext *ctx,
enum fstVarType vt,
enum fstVarDir vd,
uint32_t len,
@ -399,123 +400,136 @@ fstHandle fstWriterCreateVar2(void *ctx,
const char *type,
enum fstSupplementalVarType svt,
enum fstSupplementalDataType sdt);
void fstWriterEmitDumpActive(void *ctx, int enable);
void fstWriterEmitEnumTableRef(void *ctx, fstEnumHandle handle);
void fstWriterEmitValueChange(void *ctx, fstHandle handle, const void *val);
void fstWriterEmitValueChange32(void *ctx, fstHandle handle, uint32_t bits, uint32_t val);
void fstWriterEmitValueChange64(void *ctx, fstHandle handle, uint32_t bits, uint64_t val);
void fstWriterEmitValueChangeVec32(void *ctx,
void fstWriterEmitDumpActive(fstWriterContext *ctx, int enable);
void fstWriterEmitEnumTableRef(fstWriterContext *ctx, fstEnumHandle handle);
void fstWriterEmitValueChange(fstWriterContext *ctx, fstHandle handle, const void *val);
void fstWriterEmitValueChange32(fstWriterContext *ctx,
fstHandle handle,
uint32_t bits,
uint32_t val);
void fstWriterEmitValueChange64(fstWriterContext *ctx,
fstHandle handle,
uint32_t bits,
uint64_t val);
void fstWriterEmitValueChangeVec32(fstWriterContext *ctx,
fstHandle handle,
uint32_t bits,
const uint32_t *val);
void fstWriterEmitValueChangeVec64(void *ctx,
void fstWriterEmitValueChangeVec64(fstWriterContext *ctx,
fstHandle handle,
uint32_t bits,
const uint64_t *val);
void fstWriterEmitVariableLengthValueChange(void *ctx,
void fstWriterEmitVariableLengthValueChange(fstWriterContext *ctx,
fstHandle handle,
const void *val,
uint32_t len);
void fstWriterEmitTimeChange(void *ctx, uint64_t tim);
void fstWriterFlushContext(void *ctx);
int fstWriterGetDumpSizeLimitReached(void *ctx);
int fstWriterGetFseekFailed(void *ctx);
int fstWriterGetFlushContextPending(void *ctx);
void fstWriterSetAttrBegin(void *ctx,
void fstWriterEmitTimeChange(fstWriterContext *ctx, uint64_t tim);
void fstWriterFlushContext(fstWriterContext *ctx);
int fstWriterGetDumpSizeLimitReached(fstWriterContext *ctx);
int fstWriterGetFseekFailed(fstWriterContext *ctx);
int fstWriterGetFlushContextPending(fstWriterContext *ctx);
void fstWriterSetAttrBegin(fstWriterContext *ctx,
enum fstAttrType attrtype,
int subtype,
const char *attrname,
uint64_t arg);
void fstWriterSetAttrEnd(void *ctx);
void fstWriterSetComment(void *ctx, const char *comm);
void fstWriterSetDate(void *ctx, const char *dat);
void fstWriterSetDumpSizeLimit(void *ctx, uint64_t numbytes);
void fstWriterSetEnvVar(void *ctx, const char *envvar);
void fstWriterSetFileType(void *ctx, enum fstFileType filetype);
void fstWriterSetPackType(void *ctx, enum fstWriterPackType typ);
void fstWriterSetParallelMode(void *ctx, int enable);
void fstWriterSetRepackOnClose(void *ctx, int enable); /* type = 0 (none), 1 (libz) */
void fstWriterSetScope(void *ctx,
void fstWriterSetAttrEnd(fstWriterContext *ctx);
void fstWriterSetComment(fstWriterContext *ctx, const char *comm);
void fstWriterSetDate(fstWriterContext *ctx, const char *dat);
void fstWriterSetDumpSizeLimit(fstWriterContext *ctx, uint64_t numbytes);
void fstWriterSetEnvVar(fstWriterContext *ctx, const char *envvar);
void fstWriterSetFileType(fstWriterContext *ctx, enum fstFileType filetype);
void fstWriterSetPackType(fstWriterContext *ctx, enum fstWriterPackType typ);
void fstWriterSetParallelMode(fstWriterContext *ctx, int enable);
void fstWriterSetRepackOnClose(fstWriterContext *ctx,
int enable); /* type = 0 (none), 1 (libz) */
void fstWriterSetScope(fstWriterContext *ctx,
enum fstScopeType scopetype,
const char *scopename,
const char *scopecomp);
void fstWriterSetSourceInstantiationStem(void *ctx,
void fstWriterSetSourceInstantiationStem(fstWriterContext *ctx,
const char *path,
unsigned int line,
unsigned int use_realpath);
void fstWriterSetSourceStem(void *ctx,
void fstWriterSetSourceStem(fstWriterContext *ctx,
const char *path,
unsigned int line,
unsigned int use_realpath);
void fstWriterSetTimescale(void *ctx, int ts);
void fstWriterSetTimescaleFromString(void *ctx, const char *s);
void fstWriterSetTimezero(void *ctx, int64_t tim);
void fstWriterSetUpscope(void *ctx);
void fstWriterSetValueList(void *ctx, const char *vl);
void fstWriterSetVersion(void *ctx, const char *vers);
void fstWriterSetTimescale(fstWriterContext *ctx, int ts);
void fstWriterSetTimescaleFromString(fstWriterContext *ctx, const char *s);
void fstWriterSetTimezero(fstWriterContext *ctx, int64_t tim);
void fstWriterSetUpscope(fstWriterContext *ctx);
void fstWriterSetValueList(fstWriterContext *ctx, const char *vl);
void fstWriterSetVersion(fstWriterContext *ctx, const char *vers);
/*
* reader functions
*/
void fstReaderClose(void *ctx);
void fstReaderClrFacProcessMask(void *ctx, fstHandle facidx);
void fstReaderClrFacProcessMaskAll(void *ctx);
uint64_t fstReaderGetAliasCount(void *ctx);
const char *fstReaderGetCurrentFlatScope(void *ctx);
void *fstReaderGetCurrentScopeUserInfo(void *ctx);
int fstReaderGetCurrentScopeLen(void *ctx);
const char *fstReaderGetDateString(void *ctx);
int fstReaderGetDoubleEndianMatchState(void *ctx);
uint64_t fstReaderGetDumpActivityChangeTime(void *ctx, uint32_t idx);
unsigned char fstReaderGetDumpActivityChangeValue(void *ctx, uint32_t idx);
uint64_t fstReaderGetEndTime(void *ctx);
int fstReaderGetFacProcessMask(void *ctx, fstHandle facidx);
int fstReaderGetFileType(void *ctx);
int fstReaderGetFseekFailed(void *ctx);
fstHandle fstReaderGetMaxHandle(void *ctx);
uint64_t fstReaderGetMemoryUsedByWriter(void *ctx);
uint32_t fstReaderGetNumberDumpActivityChanges(void *ctx);
uint64_t fstReaderGetScopeCount(void *ctx);
uint64_t fstReaderGetStartTime(void *ctx);
signed char fstReaderGetTimescale(void *ctx);
int64_t fstReaderGetTimezero(void *ctx);
uint64_t fstReaderGetValueChangeSectionCount(void *ctx);
char *fstReaderGetValueFromHandleAtTime(void *ctx, uint64_t tim, fstHandle facidx, char *buf);
uint64_t fstReaderGetVarCount(void *ctx);
const char *fstReaderGetVersionString(void *ctx);
struct fstHier *fstReaderIterateHier(void *ctx);
int fstReaderIterateHierRewind(void *ctx);
int fstReaderIterBlocks(void *ctx,
typedef struct fstReaderContext fstReaderContext;
void fstReaderClose(fstReaderContext *ctx);
void fstReaderClrFacProcessMask(fstReaderContext *ctx, fstHandle facidx);
void fstReaderClrFacProcessMaskAll(fstReaderContext *ctx);
uint64_t fstReaderGetAliasCount(fstReaderContext *ctx);
const char *fstReaderGetCurrentFlatScope(fstReaderContext *ctx);
void *fstReaderGetCurrentScopeUserInfo(fstReaderContext *ctx);
int fstReaderGetCurrentScopeLen(fstReaderContext *ctx);
const char *fstReaderGetDateString(fstReaderContext *ctx);
int fstReaderGetDoubleEndianMatchState(fstReaderContext *ctx);
uint64_t fstReaderGetDumpActivityChangeTime(fstReaderContext *ctx, uint32_t idx);
unsigned char fstReaderGetDumpActivityChangeValue(fstReaderContext *ctx, uint32_t idx);
uint64_t fstReaderGetEndTime(fstReaderContext *ctx);
int fstReaderGetFacProcessMask(fstReaderContext *ctx, fstHandle facidx);
int fstReaderGetFileType(fstReaderContext *ctx);
int fstReaderGetFseekFailed(fstReaderContext *ctx);
fstHandle fstReaderGetMaxHandle(fstReaderContext *ctx);
uint64_t fstReaderGetMemoryUsedByWriter(fstReaderContext *ctx);
uint32_t fstReaderGetNumberDumpActivityChanges(fstReaderContext *ctx);
uint64_t fstReaderGetScopeCount(fstReaderContext *ctx);
uint64_t fstReaderGetStartTime(fstReaderContext *ctx);
signed char fstReaderGetTimescale(fstReaderContext *ctx);
int64_t fstReaderGetTimezero(fstReaderContext *ctx);
uint64_t fstReaderGetValueChangeSectionCount(fstReaderContext *ctx);
char *fstReaderGetValueFromHandleAtTime(fstReaderContext *ctx,
uint64_t tim,
fstHandle facidx,
char *buf);
uint64_t fstReaderGetVarCount(fstReaderContext *ctx);
const char *fstReaderGetVersionString(fstReaderContext *ctx);
struct fstHier *fstReaderIterateHier(fstReaderContext *ctx);
int fstReaderIterateHierRewind(fstReaderContext *ctx);
int fstReaderIterBlocks(fstReaderContext *ctx,
void (*value_change_callback)(void *user_callback_data_pointer,
uint64_t time,
fstHandle facidx,
const unsigned char *value),
uint64_t time,
fstHandle facidx,
const unsigned char *value),
void *user_callback_data_pointer,
FILE *vcdhandle);
int fstReaderIterBlocks2(void *ctx,
void (*value_change_callback)(void *user_callback_data_pointer,
uint64_t time,
fstHandle facidx,
const unsigned char *value),
void (*value_change_callback_varlen)(void *user_callback_data_pointer,
uint64_t time,
fstHandle facidx,
const unsigned char *value,
uint32_t len),
void *user_callback_data_pointer,
FILE *vcdhandle);
void fstReaderIterBlocksSetNativeDoublesOnCallback(void *ctx, int enable);
void *fstReaderOpen(const char *nam);
void *fstReaderOpenForUtilitiesOnly(void);
const char *fstReaderPopScope(void *ctx);
int fstReaderProcessHier(void *ctx, FILE *vcdhandle);
const char *fstReaderPushScope(void *ctx, const char *nam, void *user_info);
void fstReaderResetScope(void *ctx);
void fstReaderSetFacProcessMask(void *ctx, fstHandle facidx);
void fstReaderSetFacProcessMaskAll(void *ctx);
void fstReaderSetLimitTimeRange(void *ctx, uint64_t start_time, uint64_t end_time);
void fstReaderSetUnlimitedTimeRange(void *ctx);
void fstReaderSetVcdExtensions(void *ctx, int enable);
int fstReaderIterBlocks2(fstReaderContext *ctx,
void (*value_change_callback)(void *user_callback_data_pointer,
uint64_t time,
fstHandle facidx,
const unsigned char *value),
void (*value_change_callback_varlen)(void *user_callback_data_pointer,
uint64_t time,
fstHandle facidx,
const unsigned char *value,
uint32_t len),
void *user_callback_data_pointer,
FILE *vcdhandle);
void fstReaderIterBlocksSetNativeDoublesOnCallback(fstReaderContext *ctx, int enable);
fstReaderContext *fstReaderOpen(const char *nam);
fstReaderContext *fstReaderOpenForUtilitiesOnly(void);
const char *fstReaderPopScope(fstReaderContext *ctx);
int fstReaderProcessHier(fstReaderContext *ctx, FILE *vcdhandle);
const char *fstReaderPushScope(fstReaderContext *ctx, const char *nam, void *user_info);
void fstReaderResetScope(fstReaderContext *ctx);
void fstReaderSetFacProcessMask(fstReaderContext *ctx, fstHandle facidx);
void fstReaderSetFacProcessMaskAll(fstReaderContext *ctx);
void fstReaderSetLimitTimeRange(fstReaderContext *ctx, uint64_t start_time, uint64_t end_time);
void fstReaderSetUnlimitedTimeRange(fstReaderContext *ctx);
void fstReaderSetVcdExtensions(fstReaderContext *ctx, int enable);
/*
* utility functions

View File

@ -577,14 +577,14 @@ WDataOutP VL_POW_WWW(int obits, int, int rbits, WDataOutP owp, const WDataInP lw
const int owords = VL_WORDS_I(obits);
VL_DEBUG_IFDEF(assert(owords <= VL_MULS_MAX_WORDS););
owp[0] = 1;
for (int i = 1; i < VL_WORDS_I(obits); i++) owp[i] = 0;
for (int i = 1; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
// cppcheck-has-bug-suppress variableScope
VlWide<VL_MULS_MAX_WORDS> powstore; // Fixed size, as MSVC++ doesn't allow [words] here
VlWide<VL_MULS_MAX_WORDS> lastpowstore; // Fixed size, as MSVC++ doesn't allow [words] here
VlWide<VL_MULS_MAX_WORDS> lastoutstore; // Fixed size, as MSVC++ doesn't allow [words] here
// cppcheck-has-bug-suppress variableScope
VL_ASSIGN_W(obits, powstore, lwp);
for (int bit = 0; bit < rbits; bit++) {
for (int bit = 0; bit < rbits; ++bit) {
if (bit > 0) { // power = power*power
VL_ASSIGN_W(obits, lastpowstore, powstore);
VL_MUL_W(owords, powstore, lastpowstore, lastpowstore);
@ -919,6 +919,7 @@ void _vl_vsformat(std::string& output, const std::string& format, va_list ap) VL
}
case 'p': { // 'x' but parameter is string
const int lbits = va_arg(ap, int);
(void)lbits;
const std::string* const cstr = va_arg(ap, const std::string*);
std::ostringstream oss;
for (unsigned char c : *cstr) oss << std::hex << static_cast<int>(c);
@ -1249,9 +1250,9 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
bool inPct = false;
bool inIgnore = false;
std::string::const_iterator pos = format.cbegin();
for (; pos != format.cend() && !_vl_vsss_eof(fp, floc); ++pos) {
// VL_DBG_MSGF("_vlscan fmt='"<<pos[0]<<"' floc="<<floc<<" file='"<<_vl_vsss_peek(fp, floc,
// fromp, fstr)<<"'\n");
for (; pos != format.cend(); ++pos) {
// VL_DBG_MSGF("_vlscan fmt='%c' floc=%d file='%c'\n", pos[0], floc,
// _vl_vsss_peek(fp, floc, fromp, fstr));
if (!inPct && pos[0] == '%') {
inPct = true;
inIgnore = false;
@ -1435,7 +1436,12 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
} // switch
}
}
// Processed all arguments
return got;
done:
// Scan stopped early, return parsed or EOF
if (_vl_vsss_eof(fp, floc)) return -1;
return got;
}
@ -1764,7 +1770,7 @@ std::string VL_STACKTRACE_N() VL_MT_SAFE {
if (!strings) return "Unable to backtrace\n";
std::string result = "Backtrace:\n";
for (int j = 0; j < nptrs; j++) result += std::string{strings[j]} + "\n"s;
for (int j = 0; j < nptrs; ++j) result += std::string{strings[j]} + "\n"s;
free(strings);
return result;
}
@ -2036,7 +2042,7 @@ static const char* formatBinary(int nBits, uint32_t bits) {
assert((nBits >= 1) && (nBits <= 32));
static thread_local char t_buf[64];
for (int i = 0; i < nBits; i++) {
for (int i = 0; i < nBits; ++i) {
const bool isOne = bits & (1 << (nBits - 1 - i));
t_buf[i] = (isOne ? '1' : '0');
}
@ -3032,7 +3038,7 @@ void VerilatedContext::trace(VerilatedTraceBaseC* tfp, int levels, int options)
if (m_ns.m_traceBaseModelCbs.empty())
VL_FATAL_MT("", 0, "",
"Testbench C call to 'VerilatedContext::trace()' requires model(s) Verilated"
" with --trace or --trace-vcd option");
" with --trace-fst or --trace-vcd option");
for (auto& cbr : m_ns.m_traceBaseModelCbs) cbr(tfp, levels, options);
}
void VerilatedContext::traceBaseModelCbAdd(traceBaseModelCb_t cb) VL_MT_SAFE {
@ -3470,7 +3476,7 @@ void VerilatedHierarchy::remove(VerilatedScope* fromp, VerilatedScope* top) {
void VerilatedAssertOneThread::fatal_different() VL_MT_SAFE {
VL_FATAL_MT(__FILE__, __LINE__, "",
"Routine called that is single threaded, but called from"
" a different thread then the expected constructing thread");
" a different thread than the expected constructing thread");
}
#endif

View File

@ -175,9 +175,14 @@ enum class VerilatedAssertDirectiveType : uint8_t {
using VerilatedAssertType_t = std::underlying_type<VerilatedAssertType>::type;
using VerilatedAssertDirectiveType_t = std::underlying_type<VerilatedAssertDirectiveType>::type;
// Type trait for custom struct
// Type trait: whether T is a user-defined custom struct
template <typename>
struct VlIsCustomStruct : public std::false_type {};
// Type trait: used to detect if array element is a custom struct (e.g. for struct arrays)
template <typename T>
struct VlContainsCustomStruct : VlIsCustomStruct<T> {};
//=============================================================================
// Utility functions

View File

@ -312,7 +312,7 @@ public:
const char* fnstartp = m_insertFilenamep;
while (const char* foundp = std::strchr(fnstartp, '/')) fnstartp = foundp + 1;
const char* fnendp = fnstartp;
for (; *fnendp && *fnendp != '.'; fnendp++) {}
for (; *fnendp && *fnendp != '.'; ++fnendp) {}
const size_t page_len = fnendp - fnstartp;
const std::string page_default = "sp_user/" + std::string{fnstartp, page_len};
ckeyps[2] = "page";

View File

@ -101,6 +101,7 @@ void VerilatedFst::open(const char* filename) VL_MT_SAFE_EXCLUDES(m_mutex) {
void VerilatedFst::close() VL_MT_SAFE_EXCLUDES(m_mutex) {
const VerilatedLockGuard lock{m_mutex};
Super::closeBase();
emitTimeChangeMaybe();
fstWriterClose(m_fst);
m_fst = nullptr;
}
@ -108,10 +109,22 @@ void VerilatedFst::close() VL_MT_SAFE_EXCLUDES(m_mutex) {
void VerilatedFst::flush() VL_MT_SAFE_EXCLUDES(m_mutex) {
const VerilatedLockGuard lock{m_mutex};
Super::flushBase();
emitTimeChangeMaybe();
fstWriterFlushContext(m_fst);
}
void VerilatedFst::emitTimeChange(uint64_t timeui) { fstWriterEmitTimeChange(m_fst, timeui); }
void VerilatedFst::emitTimeChange(uint64_t timeui) {
if (!timeui) fstWriterEmitTimeChange(m_fst, timeui);
m_timeui = timeui;
}
VL_ATTR_ALWINLINE
void VerilatedFst::emitTimeChangeMaybe() {
if (VL_UNLIKELY(m_timeui)) {
fstWriterEmitTimeChange(m_fst, m_timeui);
m_timeui = 0;
}
}
//=============================================================================
// Decl
@ -311,12 +324,14 @@ void VerilatedFst::configure(const VerilatedTraceConfig& config) {
VL_ATTR_ALWINLINE
void VerilatedFstBuffer::emitEvent(uint32_t code) {
VL_DEBUG_IFDEF(assert(m_symbolp[code]););
m_owner.emitTimeChangeMaybe();
fstWriterEmitValueChange(m_fst, m_symbolp[code], "1");
}
VL_ATTR_ALWINLINE
void VerilatedFstBuffer::emitBit(uint32_t code, CData newval) {
VL_DEBUG_IFDEF(assert(m_symbolp[code]););
m_owner.emitTimeChangeMaybe();
fstWriterEmitValueChange(m_fst, m_symbolp[code], newval ? "1" : "0");
}
@ -325,6 +340,7 @@ void VerilatedFstBuffer::emitCData(uint32_t code, CData newval, int bits) {
char buf[VL_BYTESIZE];
VL_DEBUG_IFDEF(assert(m_symbolp[code]););
cvtCDataToStr(buf, newval << (VL_BYTESIZE - bits));
m_owner.emitTimeChangeMaybe();
fstWriterEmitValueChange(m_fst, m_symbolp[code], buf);
}
@ -333,6 +349,7 @@ void VerilatedFstBuffer::emitSData(uint32_t code, SData newval, int bits) {
char buf[VL_SHORTSIZE];
VL_DEBUG_IFDEF(assert(m_symbolp[code]););
cvtSDataToStr(buf, newval << (VL_SHORTSIZE - bits));
m_owner.emitTimeChangeMaybe();
fstWriterEmitValueChange(m_fst, m_symbolp[code], buf);
}
@ -341,6 +358,7 @@ void VerilatedFstBuffer::emitIData(uint32_t code, IData newval, int bits) {
char buf[VL_IDATASIZE];
VL_DEBUG_IFDEF(assert(m_symbolp[code]););
cvtIDataToStr(buf, newval << (VL_IDATASIZE - bits));
m_owner.emitTimeChangeMaybe();
fstWriterEmitValueChange(m_fst, m_symbolp[code], buf);
}
@ -349,6 +367,7 @@ void VerilatedFstBuffer::emitQData(uint32_t code, QData newval, int bits) {
char buf[VL_QUADSIZE];
VL_DEBUG_IFDEF(assert(m_symbolp[code]););
cvtQDataToStr(buf, newval << (VL_QUADSIZE - bits));
m_owner.emitTimeChangeMaybe();
fstWriterEmitValueChange(m_fst, m_symbolp[code], buf);
}
@ -365,10 +384,12 @@ void VerilatedFstBuffer::emitWData(uint32_t code, const WData* newvalp, int bits
cvtEDataToStr(wp, newvalp[--words]);
wp += VL_EDATASIZE;
}
m_owner.emitTimeChangeMaybe();
fstWriterEmitValueChange(m_fst, m_symbolp[code], m_strbufp);
}
VL_ATTR_ALWINLINE
void VerilatedFstBuffer::emitDouble(uint32_t code, double newval) {
m_owner.emitTimeChangeMaybe();
fstWriterEmitValueChange(m_fst, m_symbolp[code], &newval);
}

View File

@ -34,6 +34,8 @@ typedef uint32_t vlFstEnumHandle;
class VerilatedFstBuffer;
struct fstWriterContext;
//=============================================================================
// VerilatedFst
// Base class to create a Verilator FST dump
@ -49,11 +51,12 @@ private:
//=========================================================================
// FST-specific internals
void* m_fst = nullptr;
fstWriterContext* m_fst = nullptr;
std::map<uint32_t, vlFstHandle> m_code2symbol;
std::map<int, vlFstEnumHandle> m_local2fstdtype;
vlFstHandle* m_symbolp = nullptr; // same as m_code2symbol, but as an array
char* m_strbufp = nullptr; // String buffer long enough to hold maxBits() chars
uint64_t m_timeui = 0; // Time to emit, 0 = not needed
bool m_useFstWriterThread = false; // Whether to use the separate FST writer thread
@ -73,6 +76,7 @@ protected:
// Called when the trace moves forward to a new time point
void emitTimeChange(uint64_t timeui) override;
void emitTimeChangeMaybe();
// Hooks called from VerilatedTrace
bool preFullDump() override { return isOpen(); }
@ -161,7 +165,7 @@ class VerilatedFstBuffer VL_NOT_FINAL {
VerilatedFst& m_owner; // Trace file owning this buffer. Required by subclasses.
// The FST file handle
void* const m_fst = m_owner.m_fst;
fstWriterContext* const m_fst = m_owner.m_fst;
// code to fstHande map, as an array
const vlFstHandle* const m_symbolp = m_owner.m_symbolp;
// String buffer long enough to hold maxBits() chars

View File

@ -233,6 +233,14 @@ static inline std::string VL_CVT_N_CSTR(const char* lhsp) VL_PURE {
return lhsp ? std::string{lhsp} : ""s;
}
// Return queue from an unpacked array
template <typename T, std::size_t N_Depth>
static inline VlQueue<T> VL_CVT_UNPACK_TO_Q(const VlUnpacked<T, N_Depth>& q) VL_PURE {
VlQueue<T> ret;
for (size_t i = 0; i < N_Depth; ++i) ret.push_back(q[i]);
return ret;
}
// Return double from lhs (numeric) unsigned
double VL_ITOR_D_W(int lbits, WDataInP const lwp) VL_PURE;
static inline double VL_ITOR_D_I(int, IData lhs) VL_PURE {

View File

@ -116,7 +116,7 @@ IData VL_DIST_ERLANG(IData& seedr, IData uk, IData umean) VL_MT_SAFE {
return 0;
}
double x = 1.0;
for (int32_t i = 1; i <= k; i++) x = x * _vl_dbase_uniform(seedr, 0, 1);
for (int32_t i = 1; i <= k; ++i) x = x * _vl_dbase_uniform(seedr, 0, 1);
const double a = static_cast<double>(mean);
const double b = static_cast<double>(k);
double r = -a * log(x) / b;

View File

@ -34,28 +34,6 @@ thread_local VlExecutionProfiler::ExecutionTrace VlExecutionProfiler::t_trace;
constexpr const char* const VlExecutionRecord::s_ascii[];
//=============================================================================
// VlPgoProfiler implementation
uint16_t VlExecutionRecord::getcpu() {
#if defined(__linux)
return sched_getcpu(); // TODO: this is a system call. Not exactly cheap.
#elif defined(__APPLE__) && !defined(__arm64__)
uint32_t info[4];
__cpuid_count(1, 0, info[0], info[1], info[2], info[3]);
// info[1] is EBX, bits 24-31 are APIC ID
if ((info[3] & (1 << 9)) == 0) {
return -1; // no APIC on chip
} else {
return (unsigned)info[1] >> 24;
}
#elif defined(_WIN32)
return GetCurrentProcessorNumber();
#else
return 0;
#endif
}
//=============================================================================
// VlExecutionProfiler implementation
@ -161,11 +139,17 @@ void VlExecutionProfiler::dump(const char* filenamep, uint64_t tickEnd)
// TODO Perhaps merge with verilated_coverage output format, so can
// have a common merging and reporting tool, etc.
fprintf(fp, "VLPROFVERSION 2.1 # Verilator execution profile version 2.1\n");
fprintf(fp, "VLPROFVERSION 2.2 # Verilator execution profile version 2.2\n");
fprintf(fp, "VLPROF arg +verilator+prof+exec+start+%" PRIu64 "\n",
Verilated::threadContextp()->profExecStart());
fprintf(fp, "VLPROF arg +verilator+prof+exec+window+%u\n",
Verilated::threadContextp()->profExecWindow());
std::string numa = "no threads";
if (VlThreadPool* const threadPoolp
= static_cast<VlThreadPool*>(Verilated::threadContextp()->threadPoolp())) {
numa = threadPoolp->numaStatus();
}
fprintf(fp, "VLPROF info numa %s\n", numa.c_str());
// Note that VerilatedContext will by default create as many threads as there are hardware
// processors, but not all of them might be utilized. Report the actual number that has trace
// entries to avoid over-counting.
@ -206,13 +190,24 @@ void VlExecutionProfiler::dump(const char* filenamep, uint64_t tickEnd)
break;
case VlExecutionRecord::Type::MTASK_BEGIN: {
const auto& payload = er.m_payload.mtaskBegin;
fprintf(fp, " id %u predictStart %u cpu %u\n", payload.m_id,
payload.m_predictStart, payload.m_cpu);
if (payload.m_hierBlock[0] != '\0') {
fprintf(fp, " id %u predictStart %u cpu %u hierBlock %s\n", payload.m_id,
payload.m_predictStart, payload.m_cpu, payload.m_hierBlock);
} else {
fprintf(fp, " id %u predictStart %u cpu %u\n", payload.m_id,
payload.m_predictStart, payload.m_cpu);
}
break;
}
case VlExecutionRecord::Type::MTASK_END: {
const auto& payload = er.m_payload.mtaskEnd;
fprintf(fp, " id %u predictCost %u\n", payload.m_id, payload.m_predictCost);
fprintf(fp, " predictCost %u\n", payload.m_predictCost);
break;
}
case VlExecutionRecord::Type::THREAD_SCHEDULE_WAIT_BEGIN:
case VlExecutionRecord::Type::THREAD_SCHEDULE_WAIT_END: {
const auto& payload = er.m_payload.threadScheduleWait;
fprintf(fp, " cpu %u\n", payload.m_cpu);
break;
}
case VlExecutionRecord::Type::SECTION_PUSH: {

View File

@ -62,6 +62,8 @@ VL_ATTR_ALWINLINE QData VL_CPU_TICK() {
_VL_FOREACH_APPLY(macro, SECTION_POP) \
_VL_FOREACH_APPLY(macro, MTASK_BEGIN) \
_VL_FOREACH_APPLY(macro, MTASK_END) \
_VL_FOREACH_APPLY(macro, THREAD_SCHEDULE_WAIT_BEGIN) \
_VL_FOREACH_APPLY(macro, THREAD_SCHEDULE_WAIT_END) \
_VL_FOREACH_APPLY(macro, EXEC_GRAPH_BEGIN) \
_VL_FOREACH_APPLY(macro, EXEC_GRAPH_END)
// clang-format on
@ -90,11 +92,14 @@ class VlExecutionRecord final {
uint32_t m_id; // MTask id
uint32_t m_predictStart; // Time scheduler predicted would start
uint32_t m_cpu; // Executing CPU id
const char* m_hierBlock; // Name of a hier block with this mtask
} mtaskBegin;
struct {
uint32_t m_id; // MTask id
uint32_t m_predictCost; // How long scheduler predicted would take
} mtaskEnd;
struct {
uint32_t m_cpu; // Executing CPU id
} threadScheduleWait;
};
// STATE
@ -105,8 +110,6 @@ class VlExecutionRecord final {
static_assert(alignof(uint64_t) >= alignof(Payload), "Padding not allowed");
static_assert(alignof(Payload) >= alignof(Type), "Padding not allowed");
static uint16_t getcpu(); // Return currently executing CPU id
public:
// CONSTRUCTOR
VlExecutionRecord() = default;
@ -117,17 +120,25 @@ public:
m_type = Type::SECTION_PUSH;
}
void sectionPop() { m_type = Type::SECTION_POP; }
void mtaskBegin(uint32_t id, uint32_t predictStart) {
void mtaskBegin(uint32_t id, uint32_t predictStart, const char* hierBlock = "") {
m_payload.mtaskBegin.m_id = id;
m_payload.mtaskBegin.m_predictStart = predictStart;
m_payload.mtaskBegin.m_cpu = getcpu();
m_payload.mtaskBegin.m_cpu = VlOs::getcpu();
m_payload.mtaskBegin.m_hierBlock = hierBlock;
m_type = Type::MTASK_BEGIN;
}
void mtaskEnd(uint32_t id, uint32_t predictCost) {
m_payload.mtaskEnd.m_id = id;
void mtaskEnd(uint32_t predictCost) {
m_payload.mtaskEnd.m_predictCost = predictCost;
m_type = Type::MTASK_END;
}
void threadScheduleWaitBegin() {
m_payload.threadScheduleWait.m_cpu = VlOs::getcpu();
m_type = Type::THREAD_SCHEDULE_WAIT_BEGIN;
}
void threadScheduleWaitEnd() {
m_payload.threadScheduleWait.m_cpu = VlOs::getcpu();
m_type = Type::THREAD_SCHEDULE_WAIT_END;
}
void execGraphBegin() { m_type = Type::EXEC_GRAPH_BEGIN; }
void execGraphEnd() { m_type = Type::EXEC_GRAPH_END; }
};
@ -214,7 +225,7 @@ public:
// METHODS
VlPgoProfiler() = default;
~VlPgoProfiler() = default;
void write(const char* modelp, const std::string& filename) VL_MT_SAFE;
void write(const char* modelp, const std::string& filename, bool firstHierCall) VL_MT_SAFE;
void addCounter(size_t counter, const std::string& name) {
VL_DEBUG_IF(assert(counter < N_Entries););
m_records.emplace_back(Record{name, counter});
@ -228,7 +239,8 @@ public:
};
template <std::size_t N_Entries>
void VlPgoProfiler<N_Entries>::write(const char* modelp, const std::string& filename) VL_MT_SAFE {
void VlPgoProfiler<N_Entries>::write(const char* modelp, const std::string& filename,
bool firstHierCall) VL_MT_SAFE {
static VerilatedMutex s_mutex;
const VerilatedLockGuard lock{s_mutex};
@ -238,7 +250,7 @@ void VlPgoProfiler<N_Entries>::write(const char* modelp, const std::string& file
// each will collect is own data correctly. However when each is
// destroyed we need to get all the data, not keep overwriting and only
// get the last model's data.
static bool s_firstCall = true;
static bool s_firstCall = firstHierCall;
VL_DEBUG_IF(VL_DBG_MSGF("+prof+vlt+file writing to '%s'\n", filename.c_str()););
@ -246,12 +258,14 @@ void VlPgoProfiler<N_Entries>::write(const char* modelp, const std::string& file
if (VL_UNLIKELY(!fp)) {
VL_FATAL_MT(filename.c_str(), 0, "", "+prof+vlt+file file not writable");
}
s_firstCall = false;
if (s_firstCall) {
// TODO Perhaps merge with verilated_coverage output format, so can
// have a common merging and reporting tool, etc.
fprintf(fp, "// Verilated model profile-guided optimization data dump file\n");
fprintf(fp, "`verilator_config\n");
}
// TODO Perhaps merge with verilated_coverage output format, so can
// have a common merging and reporting tool, etc.
fprintf(fp, "// Verilated model profile-guided optimization data dump file\n");
fprintf(fp, "`verilator_config\n");
s_firstCall = false;
for (const Record& rec : m_records) {
fprintf(fp, "profile_data -model \"%s\" -mtask \"%s\" -cost 64'd%" PRIu64 "\n", modelp,

View File

@ -112,7 +112,7 @@ public:
if (m_pidStatus) {
std::stringstream msg;
msg << "Subprocess command `" << m_cmd[0];
for (const char* const* arg = m_cmd + 1; *arg; arg++) msg << ' ' << *arg;
for (const char* const* arg = m_cmd + 1; *arg; ++arg) msg << ' ' << *arg;
msg << "' failed: ";
if (WIFSIGNALED(m_pidStatus))
msg << strsignal(WTERMSIG(m_pidStatus))
@ -221,7 +221,7 @@ static Process& getSolver() {
static std::vector<const char*> s_argv;
static std::string s_program = Verilated::threadContextp()->solverProgram();
s_argv.emplace_back(&s_program[0]);
for (char* arg = &s_program[0]; *arg; arg++) {
for (char* arg = &s_program[0]; *arg; ++arg) {
if (*arg == ' ') {
*arg = '\0';
s_argv.emplace_back(arg + 1);
@ -242,7 +242,7 @@ static Process& getSolver() {
msg << "Unable to communicate with SAT solver, please check its installation or specify a "
"different one in VERILATOR_SOLVER environment variable.\n";
msg << " ... Tried: $";
for (const char* const* arg = cmd; *arg; arg++) msg << ' ' << *arg;
for (const char* const* arg = cmd; *arg; ++arg) msg << ' ' << *arg;
msg << '\n';
const std::string str = msg.str();
VL_WARN_MT("", 0, "randomize", str.c_str());
@ -294,7 +294,7 @@ void VlRandomVar::emitType(std::ostream& s) const { s << "(_ BitVec " << width()
int VlRandomVar::totalWidth() const { return m_width; }
static bool parseSMTNum(int obits, WDataOutP owp, const std::string& val) {
int i;
for (i = 0; val[i] && val[i] != '#'; i++) {}
for (i = 0; val[i] && val[i] != '#'; ++i) {}
if (val[i++] != '#') return false;
switch (val[i++]) {
case 'b': _vl_vsss_based(owp, obits, 1, &val[i], 0, val.size() - i); break;
@ -345,7 +345,7 @@ void VlRandomizer::randomConstraint(std::ostream& os, VlRNG& rngr, int bits) {
os << "(= #b";
for (int i = bits - 1; i >= 0; i--) os << (VL_BITISSET_I(hash, i) ? '1' : '0');
if (bits > 1) os << " (concat";
for (int i = 0; i < bits; i++) {
for (int i = 0; i < bits; ++i) {
IData varBitsLeft = varBits;
IData varBitsWant = (varBits + 1) / 2;
if (varBits > 2) os << " (bvxor";
@ -393,7 +393,7 @@ bool VlRandomizer::next(VlRNG& rngr) {
f << "(reset)\n";
return false;
}
for (int i = 0; i < _VL_SOLVER_HASH_LEN_TOTAL && sat; i++) {
for (int i = 0; i < _VL_SOLVER_HASH_LEN_TOTAL && sat; ++i) {
f << "(assert ";
randomConstraint(f, rngr, _VL_SOLVER_HASH_LEN);
f << ")\n";

View File

@ -143,7 +143,7 @@ public:
}
void emitGetValue(std::ostream& s) const override {
const int elementCounts = countMatchingElements(*m_arrVarsRefp, name());
for (int i = 0; i < elementCounts; i++) {
for (int i = 0; i < elementCounts; ++i) {
const std::string indexed_name = name() + std::to_string(i);
const auto it = m_arrVarsRefp->find(indexed_name);
if (it != m_arrVarsRefp->end()) {
@ -200,8 +200,8 @@ class VlRandomizer final {
std::map<std::string, std::shared_ptr<const VlRandomVar>> m_vars; // Solver-dependent
// variables
ArrayInfoMap m_arr_vars; // Tracks each element in array structures for iteration
std::map<size_t, std::string> seen_values; // Record String Index to avoid conflicts
const VlQueue<CData>* m_randmode; // rand_mode state;
int m_index = 0; // Internal counter for key generation
// PRIVATE METHODS
void randomConstraint(std::ostream& os, VlRNG& rngr, int bits);
@ -216,6 +216,11 @@ public:
// Finds the next solution satisfying the constraints
bool next(VlRNG& rngr);
// -----------------------------------------------
// --- Process the key for associative array ---
// -----------------------------------------------
// process_key: Handle integral keys (<= 32-bit)
template <typename T_Key>
typename std::enable_if<std::is_integral<T_Key>::value && (sizeof(T_Key) <= 4)>::type
process_key(const T_Key& key, std::string& indexed_name, std::vector<size_t>& integral_index,
@ -225,6 +230,8 @@ public:
= base_name + "[" + std::to_string(integral_index[integral_index.size() - 1]) + "]";
idx_width = sizeof(T_Key) * 8;
}
// process_key: Handle integral keys (> 32-bit), split into 2 x 32-bit segments
template <typename T_Key>
typename std::enable_if<std::is_integral<T_Key>::value && (sizeof(T_Key) > 4)>::type
process_key(const T_Key& key, std::string& indexed_name, std::vector<size_t>& integral_index,
@ -244,6 +251,8 @@ public:
idx_width = sizeof(T_Key) * 8;
}
// process_key: Handle wide keys (VlWide-like), segment is 32-bit per element
template <typename T_Key>
typename std::enable_if<VlIsVlWide<T_Key>::value>::type
process_key(const T_Key& key, std::string& indexed_name, std::vector<size_t>& integral_index,
@ -261,6 +270,8 @@ public:
indexed_name = base_name + "[" + index_string + "]";
idx_width = key.size() * 32;
}
// process_key: Handle string key, encoded as 128-bit hex
template <typename T_Key>
typename std::enable_if<std::is_same<T_Key, std::string>::value>::type
process_key(const T_Key& key, std::string& indexed_name, std::vector<size_t>& integral_index,
@ -289,6 +300,8 @@ public:
idx_width = 128;
}
// process_key: Unsupported key type fallback
template <typename T_Key>
typename std::enable_if<!std::is_integral<T_Key>::value
&& !std::is_same<T_Key, std::string>::value
@ -300,8 +313,13 @@ public:
"supported currently.");
}
// -----------------------------------------
// --- write_var to register variables ---
// -----------------------------------------
// Register scalar variable (non-struct, basic type)
template <typename T>
typename std::enable_if<!VlIsCustomStruct<T>::value, void>::type
typename std::enable_if<!VlContainsCustomStruct<T>::value, void>::type
write_var(T& var, int width, const char* name, int dimension,
std::uint32_t randmodeIdx = std::numeric_limits<std::uint32_t>::max()) {
if (m_vars.find(name) != m_vars.end()) return;
@ -309,49 +327,8 @@ public:
m_vars[name]
= std::make_shared<const VlRandomVar>(name, width, &var, dimension, randmodeIdx);
}
template <typename T>
void write_var(VlQueue<T>& var, int width, const char* name, int dimension,
std::uint32_t randmodeIdx = std::numeric_limits<std::uint32_t>::max()) {
if (m_vars.find(name) != m_vars.end()) return;
m_vars[name] = std::make_shared<const VlRandomArrayVarTemplate<VlQueue<T>>>(
name, width, &var, dimension, randmodeIdx);
if (dimension > 0) {
idx = 0;
record_arr_table(var, name, dimension, {}, {});
}
}
template <typename T, std::size_t N_Depth>
void write_var(VlUnpacked<T, N_Depth>& var, int width, const char* name, int dimension,
std::uint32_t randmodeIdx = std::numeric_limits<std::uint32_t>::max()) {
if (m_vars.find(name) != m_vars.end()) return;
m_vars[name] = std::make_shared<const VlRandomArrayVarTemplate<VlUnpacked<T, N_Depth>>>(
name, width, &var, dimension, randmodeIdx);
if (dimension > 0) {
idx = 0;
record_arr_table(var, name, dimension, {}, {});
}
}
template <typename T_Key, typename T_Value>
void write_var(VlAssocArray<T_Key, T_Value>& var, int width, const char* name, int dimension,
std::uint32_t randmodeIdx = std::numeric_limits<std::uint32_t>::max()) {
if (m_vars.find(name) != m_vars.end()) return;
m_vars[name]
= std::make_shared<const VlRandomArrayVarTemplate<VlAssocArray<T_Key, T_Value>>>(
name, width, &var, dimension, randmodeIdx);
if (dimension > 0) {
idx = 0;
record_arr_table(var, name, dimension, {}, {});
}
}
template <typename T, std::size_t... I>
void modifyMembers(T& obj, std::index_sequence<I...>, std::string baseName) {
// Use the indices to access each member via std::get
(void)std::initializer_list<int>{
(write_var(std::get<I>(obj.getMembers(obj)), obj.memberWidth()[I],
(baseName + "." + obj.memberNames()[I]).c_str(), obj.memberDimension()[I]),
0)...};
}
// Register user-defined struct variable by recursively writing members
template <typename T>
typename std::enable_if<VlIsCustomStruct<T>::value, void>::type
write_var(T& var, int width, const char* name, int dimension,
@ -359,39 +336,87 @@ public:
modifyMembers(var, var.memberIndices(), name);
}
int idx;
std::string generateKey(const std::string& name, int idx) {
if (!name.empty() && name[0] == '\\') {
const size_t space_pos = name.find(' ');
return (space_pos != std::string::npos ? name.substr(0, space_pos) : name)
+ std::to_string(idx);
// Register queue of non-struct types
template <typename T>
typename std::enable_if<!VlContainsCustomStruct<T>::value, void>::type
write_var(VlQueue<T>& var, int width, const char* name, int dimension,
std::uint32_t randmodeIdx = std::numeric_limits<std::uint32_t>::max()) {
if (m_vars.find(name) != m_vars.end()) return;
m_vars[name] = std::make_shared<const VlRandomArrayVarTemplate<VlQueue<T>>>(
name, width, &var, dimension, randmodeIdx);
if (dimension > 0) {
m_index = 0;
record_arr_table(var, name, dimension, {}, {});
}
const size_t bracket_pos = name.find('[');
return (bracket_pos != std::string::npos ? name.substr(0, bracket_pos) : name)
+ std::to_string(idx);
}
// Register queue of structs
template <typename T>
typename std::enable_if<VlContainsCustomStruct<T>::value, void>::type
write_var(VlQueue<T>& var, int width, const char* name, int dimension,
std::uint32_t randmodeIdx = std::numeric_limits<std::uint32_t>::max()) {
if (dimension > 0) record_struct_arr(var, name, dimension, {}, {});
}
// Register unpacked array of non-struct types
template <typename T, std::size_t N_Depth>
typename std::enable_if<!VlContainsCustomStruct<T>::value, void>::type
write_var(VlUnpacked<T, N_Depth>& var, int width, const char* name, int dimension,
std::uint32_t randmodeIdx = std::numeric_limits<std::uint32_t>::max()) {
if (m_vars.find(name) != m_vars.end()) return;
m_vars[name] = std::make_shared<const VlRandomArrayVarTemplate<VlUnpacked<T, N_Depth>>>(
name, width, &var, dimension, randmodeIdx);
if (dimension > 0) {
m_index = 0;
record_arr_table(var, name, dimension, {}, {});
}
}
// Register unpacked array of structs
template <typename T, std::size_t N_Depth>
typename std::enable_if<VlContainsCustomStruct<T>::value, void>::type
write_var(VlUnpacked<T, N_Depth>& var, int width, const char* name, int dimension,
std::uint32_t randmodeIdx = std::numeric_limits<std::uint32_t>::max()) {
if (dimension > 0) record_struct_arr(var, name, dimension, {}, {});
}
// Register associative array of non-struct types
template <typename T_Key, typename T_Value>
typename std::enable_if<!VlContainsCustomStruct<T_Value>::value, void>::type
write_var(VlAssocArray<T_Key, T_Value>& var, int width, const char* name, int dimension,
std::uint32_t randmodeIdx = std::numeric_limits<std::uint32_t>::max()) {
if (m_vars.find(name) != m_vars.end()) return;
m_vars[name]
= std::make_shared<const VlRandomArrayVarTemplate<VlAssocArray<T_Key, T_Value>>>(
name, width, &var, dimension, randmodeIdx);
if (dimension > 0) {
m_index = 0;
record_arr_table(var, name, dimension, {}, {});
}
}
// Register associative array of structs
template <typename T_Key, typename T_Value>
typename std::enable_if<VlContainsCustomStruct<T_Value>::value, void>::type
write_var(VlAssocArray<T_Key, T_Value>& var, int width, const char* name, int dimension,
std::uint32_t randmodeIdx = std::numeric_limits<std::uint32_t>::max()) {
if (dimension > 0) record_struct_arr(var, name, dimension, {}, {});
}
// ----------------------------------------
// --- Record Arrays: flat and struct ---
// ----------------------------------------
// Record a flat (non-class) element into the array variable table
template <typename T>
typename std::enable_if<!std::is_class<T>::value, void>::type
record_arr_table(T& var, const std::string name, int dimension, std::vector<IData> indices,
std::vector<size_t> idxWidths) {
const std::string key = generateKey(name, idx);
m_arr_vars[key] = std::make_shared<ArrayInfo>(name, &var, idx, indices, idxWidths);
++idx;
}
template <typename T>
void record_arr_table(VlQueue<T>& var, const std::string name, int dimension,
std::vector<IData> indices, std::vector<size_t> idxWidths) {
if ((dimension > 0) && (var.size() != 0)) {
idxWidths.push_back(32);
for (size_t i = 0; i < var.size(); ++i) {
const std::string indexed_name = name + "[" + std::to_string(i) + "]";
indices.push_back(i);
record_arr_table(var.atWrite(i), indexed_name, dimension - 1, indices, idxWidths);
indices.pop_back();
}
}
const std::string key = generateKey(name, m_index);
m_arr_vars[key] = std::make_shared<ArrayInfo>(name, &var, m_index, indices, idxWidths);
++m_index;
}
// Recursively record all elements in an unpacked array
template <typename T, std::size_t N_Depth>
void record_arr_table(VlUnpacked<T, N_Depth>& var, const std::string name, int dimension,
std::vector<IData> indices, std::vector<size_t> idxWidths) {
@ -406,6 +431,23 @@ public:
}
}
}
// Recursively record all elements in a queue
template <typename T>
void record_arr_table(VlQueue<T>& var, const std::string name, int dimension,
std::vector<IData> indices, std::vector<size_t> idxWidths) {
if ((dimension > 0) && (var.size() != 0)) {
idxWidths.push_back(32);
for (size_t i = 0; i < var.size(); ++i) {
const std::string indexed_name = name + "[" + std::to_string(i) + "]";
indices.push_back(i);
record_arr_table(var.atWrite(i), indexed_name, dimension - 1, indices, idxWidths);
indices.pop_back();
}
}
}
// Recursively record all elements in an associative array
template <typename T_Key, typename T_Value>
void record_arr_table(VlAssocArray<T_Key, T_Value>& var, const std::string name, int dimension,
std::vector<IData> indices, std::vector<size_t> idxWidths) {
@ -433,6 +475,102 @@ public:
}
}
// Register a single structArray element via write_var
template <typename T>
typename std::enable_if<VlContainsCustomStruct<T>::value, void>::type
record_struct_arr(T& var, const std::string name, int dimension, std::vector<IData> indices,
std::vector<size_t> idxWidths) {
std::ostringstream oss;
for (size_t i = 0; i < indices.size(); ++i) {
oss << std::hex << std::setw(int(idxWidths[i] / 4)) << std::setfill('0')
<< static_cast<int>(indices[i]);
if (i < indices.size() - 1) oss << ".";
}
write_var(var, 1ULL,
oss.str().length() > 0 ? (name + "." + oss.str()).c_str() : name.c_str(), 1ULL);
}
// Recursively process VlUnpacked of structs
template <typename T, std::size_t N_Depth>
void record_struct_arr(VlUnpacked<T, N_Depth>& var, const std::string name, int dimension,
std::vector<IData> indices, std::vector<size_t> idxWidths) {
if (dimension > 0 && N_Depth != 0) {
constexpr size_t idx_width = 1 << VL_CLOG2_CE_Q(VL_CLOG2_CE_Q(N_Depth) + 1);
idxWidths.push_back(idx_width);
for (size_t i = 0; i < N_Depth; ++i) {
indices.push_back(i);
record_struct_arr(var.operator[](i), name, dimension - 1, indices, idxWidths);
indices.pop_back();
}
}
}
// Recursively process VlQueue of structs
template <typename T>
void record_struct_arr(VlQueue<T>& var, const std::string name, int dimension,
std::vector<IData> indices, std::vector<size_t> idxWidths) {
if ((dimension > 0) && (var.size() != 0)) {
idxWidths.push_back(32);
for (size_t i = 0; i < var.size(); ++i) {
indices.push_back(i);
record_struct_arr(var.atWrite(i), name, dimension - 1, indices, idxWidths);
indices.pop_back();
}
}
}
// Recursively process associative arrays of structs
template <typename T_Key, typename T_Value>
void record_struct_arr(VlAssocArray<T_Key, T_Value>& var, const std::string name,
int dimension, std::vector<IData> indices,
std::vector<size_t> idxWidths) {
if ((dimension > 0) && (!var.empty())) {
for (auto it = var.begin(); it != var.end(); ++it) {
const T_Key& key = it->first;
const T_Value& value = it->second;
std::string indexed_name;
std::vector<size_t> integral_index;
size_t idx_width = 0;
process_key(key, indexed_name, integral_index, name, idx_width);
std::ostringstream oss;
for (int i = 0; i < integral_index.size(); ++i)
oss << std::hex << static_cast<int>(integral_index[i]);
std::string result = oss.str();
result.insert(result.begin(), int(idx_width / 4) - result.size(), '0');
record_struct_arr(var.at(key), name + "." + result, dimension - 1, indices,
idxWidths);
}
}
}
// --------------------------
// --- Helper functions ---
// --------------------------
// Helper: Register all members of a user-defined struct
template <typename T, std::size_t... I>
void modifyMembers(T& obj, std::index_sequence<I...>, std::string baseName) {
// Use the indices to access each member via std::get
(void)std::initializer_list<int>{
(write_var(std::get<I>(obj.getMembers(obj)), obj.memberWidth()[I],
(baseName + "." + obj.memberNames()[I]).c_str(), obj.memberDimension()[I]),
0)...};
}
// Helper: Generate unique variable key from name and index
std::string generateKey(const std::string& name, int idx) {
if (!name.empty() && name[0] == '\\') {
const size_t space_pos = name.find(' ');
return (space_pos != std::string::npos ? name.substr(0, space_pos) : name)
+ std::to_string(idx);
}
const size_t bracket_pos = name.find('[');
return (bracket_pos != std::string::npos ? name.substr(0, bracket_pos) : name)
+ std::to_string(idx);
}
void hard(std::string&& constraint);
void clear();
void set_randmode(const VlQueue<CData>& randmode) { m_randmode = &randmode; }

View File

@ -15,9 +15,9 @@
/// \brief Verilated C++ tracing in SAIF format implementation code
///
/// This file must be compiled and linked against all Verilated objects
/// that use --trace.
/// that use --trace-saif.
///
/// Use "verilator --trace" to add this to the Makefile for the linker.
/// Use "verilator --trace-saif" to add this to the Makefile for the linker.
///
//=============================================================================
@ -110,7 +110,7 @@ public:
"The emitted value must be of integral type");
const uint64_t dt = time - m_lastTime;
for (size_t i = 0; i < std::min(m_width, bits); i++) {
for (size_t i = 0; i < std::min(m_width, bits); ++i) {
m_bits[i].aggregateVal(dt, (newval >> i) & 1);
}
updateLastTime(time);
@ -319,6 +319,7 @@ void VerilatedSaif::close() VL_MT_SAFE_EXCLUDES(m_mutex) {
finalizeSaifFileContents();
clearCurrentlyCollectedData();
writeBuffered(true);
::close(m_filep);
m_isOpen = false;
@ -400,11 +401,6 @@ bool VerilatedSaif::printActivityStats(VerilatedSaifActivityVar& activity,
for (size_t i = 0; i < activity.width(); ++i) {
VerilatedSaifActivityBit& bit = activity.bit(i);
if (bit.toggleCount() <= 0) {
// Skip bits with no toggles
continue;
}
bit.aggregateVal(currentTime() - activity.lastUpdateTime(), bit.bitValue());
if (!anyNetWritten) {
@ -442,9 +438,25 @@ void VerilatedSaif::clearCurrentlyCollectedData() {
m_activityAccumulators.clear();
}
void VerilatedSaif::printStr(const char* str) { ::write(m_filep, str, strlen(str)); }
void VerilatedSaif::printStr(const char* str) {
m_buffer.append(str);
writeBuffered(false);
}
void VerilatedSaif::printStr(const std::string& str) { ::write(m_filep, str.c_str(), str.size()); }
void VerilatedSaif::printStr(const std::string& str) {
m_buffer.append(str);
writeBuffered(false);
}
void VerilatedSaif::writeBuffered(bool force) {
if (VL_UNLIKELY(m_buffer.size() >= WRITE_BUFFER_SIZE || force)) {
if (VL_UNLIKELY(!m_buffer.empty())) {
::write(m_filep, m_buffer.data(), m_buffer.size());
m_buffer = "";
m_buffer.reserve(WRITE_BUFFER_SIZE * 2);
}
}
}
//=============================================================================
// Definitions
@ -459,7 +471,7 @@ void VerilatedSaif::incrementIndent() { m_indent += 1; }
void VerilatedSaif::decrementIndent() { m_indent -= 1; }
void VerilatedSaif::printIndent() {
for (int i = 0; i < m_indent; ++i) printStr(" ");
printStr(std::string(m_indent, ' ')); // Must use () constructor
}
void VerilatedSaif::pushPrefix(const std::string& name, VerilatedTracePrefixType type) {

View File

@ -52,8 +52,10 @@ private:
int m_filep = 0; // File we're writing to
bool m_isOpen = false; // True indicates open file
std::string m_filename; // Filename we're writing to (if open)
std::string m_buffer; // Write data buffer
int m_indent = 0; // Indentation size in spaces
static constexpr size_t WRITE_BUFFER_SIZE = 256 * 1024; // Bytes between write calls
// Currently active scope
VerilatedSaifActivityScope* m_currentScope = nullptr;
@ -92,6 +94,7 @@ private:
void printStr(const char* str);
void printStr(const std::string& str);
void writeBuffered(bool force);
void clearCurrentlyCollectedData();

View File

@ -175,6 +175,32 @@ package std;
`endif
endtask
// Two process references are equal if the different classes' containing
// m_process are equal. Can't yet use <=> as the base class template
// comparisons doesn't define <=> as they don't yet require --timing and C++20.
`ifdef VERILATOR_TIMING
`systemc_header_post
template<> template<>
inline bool VlClassRef<`systemc_class_name>::operator==(const VlClassRef<`systemc_class_name>& rhs) const {
if (!m_objp && !rhs.m_objp) return true;
if (!m_objp || !rhs.m_objp) return false;
return m_objp->__PVT__m_process == rhs.m_objp->__PVT__m_process;
};
template<> template<>
inline bool VlClassRef<`systemc_class_name>::operator!=(const VlClassRef<`systemc_class_name>& rhs) const {
if (!m_objp && !rhs.m_objp) return false;
if (!m_objp || !rhs.m_objp) return true;
return m_objp->__PVT__m_process != rhs.m_objp->__PVT__m_process;
};
template<> template<>
inline bool VlClassRef<`systemc_class_name>::operator<(const VlClassRef<`systemc_class_name>& rhs) const {
if (!m_objp && !rhs.m_objp) return false;
if (!m_objp || !rhs.m_objp) return false;
return m_objp->__PVT__m_process < rhs.m_objp->__PVT__m_process;
};
`verilog
`endif
// When really implemented, srandom must operate on the process, but for
// now rely on the srandom() that is automatically generated for all
// classes.

View File

@ -26,6 +26,8 @@
#include "verilated_threads.h"
#include <cstdio>
#include <fstream>
#include <iostream>
#include <memory>
#include <string>
@ -100,10 +102,153 @@ void VlWorkerThread::startWorker(VlWorkerThread* workerp, VerilatedContext* cont
// VlThreadPool
VlThreadPool::VlThreadPool(VerilatedContext* contextp, unsigned nThreads) {
for (unsigned i = 0; i < nThreads; ++i) m_workers.push_back(new VlWorkerThread{contextp});
for (unsigned i = 0; i < nThreads; ++i) {
m_workers.push_back(new VlWorkerThread{contextp});
m_unassignedWorkers.push(i);
}
m_numaStatus = numaAssign();
}
VlThreadPool::~VlThreadPool() {
// Each ~WorkerThread will wait for its thread to exit.
for (auto& i : m_workers) delete i;
}
bool VlThreadPool::isNumactlRunning() {
// We assume if current thread is CPU-masked, then under numactl, otherwise not.
// This shows that numactl is visible through the affinity mask
#if defined(__linux) || defined(CPU_ZERO) // Linux-like; assume we have pthreads etc
const unsigned num_cpus = std::thread::hardware_concurrency();
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
const int rc = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
if (rc != 0) return true; // Error; assuming returning true is the least-damage option
for (unsigned c = 0; c < std::min(num_cpus, static_cast<unsigned>(CPU_SETSIZE)); ++c) {
if (!CPU_ISSET(c, &cpuset)) return true;
}
#endif
return false;
}
std::string VlThreadPool::numaAssign() {
#if defined(__linux) || defined(CPU_ZERO) // Linux-like; assume we have pthreads etc
// If not under numactl, make a reasonable processor affinity selection
if (isNumactlRunning()) return "running under numactl"; // User presumably set affinity
const int num_threads = static_cast<int>(m_workers.size());
const int num_proc = static_cast<int>(std::thread::hardware_concurrency());
if (num_threads < 2) return "too few threads";
if (num_threads > num_proc) return "too many threads";
// Read CPU info.
// Uncertain if any modern system has gaps in the processor id (Solaris
// did), but just in case use vectors instead of processor number math.
//
// Currently ignoring socket number "physical id".
// If processor numbers are sequential on sockets, algorithm works out ok.
// If processor numbers are strided on sockets, algorithm also works out ok.
std::ifstream is{"/proc/cpuinfo"};
if (VL_UNLIKELY(!is)) return "%Warning: no /proc/cpuinfo";
std::vector<int> unassigned_processors; // Processors to assign in sorted order
std::map<int, int> processor_core;
std::multimap<int, int> core_processors;
std::set<int> cores;
int processor = -1;
int core = -1;
while (!is.eof()) {
std::string line;
std::getline(is, line);
static std::string::size_type pos = line.find(":");
int number = -1;
if (pos != std::string::npos) number = atoi(line.c_str() + pos + 1);
if (line.compare(0, std::strlen("processor"), "processor") == 0) {
processor = number;
core = -1;
} else if (line.compare(0, std::strlen("core id"), "core id") == 0) {
core = number;
// std::cout << "p" << processor << " socket " << socket << " c" << core << std::endl;
cores.emplace(core);
processor_core[processor] = core;
core_processors.emplace(core, processor);
unassigned_processors.push_back(processor);
}
}
// Start scheduling on the current CPU + 1.
// This will help to land on the same socket as current CPU, and also
// help make sure that different processes have different masks (when
// num_threads is not a common-factor of the processor count).
std::sort(unassigned_processors.begin(), unassigned_processors.end());
{
const int on_cpu = sched_getcpu(); // TODO: this is a system call. Not exactly cheap.
bool hit = false;
std::vector<int> new_front;
std::vector<int> new_back;
for (const int processor : unassigned_processors) {
if (hit) {
new_front.push_back(processor);
} else {
new_back.push_back(processor);
}
if (processor == on_cpu) hit = true;
}
unassigned_processors = new_front;
unassigned_processors.insert(unassigned_processors.end(), new_back.begin(),
new_back.end());
}
// If less threads than cores, we can schedule per-core
const bool core_per_thread = num_threads <= cores.size();
// Compute core mapping
std::multimap<int, int> thread_processors;
{
std::set<int> assigned_processors;
int thread = 0;
for (const int processor : unassigned_processors) {
// Find free processor, the current thread can use that
if (assigned_processors.find(processor) != assigned_processors.end()) continue;
assigned_processors.emplace(processor);
thread_processors.emplace(thread, processor);
if (core_per_thread) {
// Also include all other processors same core,
// so that another thread doesn't land on different processor in same core
const int core = processor_core[processor];
const auto bounds = core_processors.equal_range(core);
for (auto it{bounds.first}; it != bounds.second; ++it) {
if (assigned_processors.find(it->second) != assigned_processors.end())
continue;
if (it->second == processor) continue;
thread_processors.emplace(thread, it->second);
assigned_processors.emplace(it->second);
}
}
// Prepare for next loop
thread = (thread + 1) % num_threads;
}
}
// Set affinity
std::string status = "assigned ";
for (int thread = 0; thread < num_threads; ++thread) {
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
const auto bounds = thread_processors.equal_range(thread);
for (auto it{bounds.first}; it != bounds.second; ++it) {
if (it != bounds.first) status += ',';
status += std::to_string(it->second);
CPU_SET(it->second, &cpuset);
}
status += ";";
const int rc = pthread_setaffinity_np(m_workers[thread]->m_cthread.native_handle(),
sizeof(cpu_set_t), &cpuset);
if (rc != 0) return "%Warning: pthread_setaffinity_np failed";
}
// std::cout << "Status: " << status << std::endl;
return status;
#else
return "non-supported host OS";
#endif
}

View File

@ -30,18 +30,10 @@
#include <atomic>
#include <condition_variable>
#include <set>
#include <stack>
#include <thread>
#include <vector>
// clang-format off
#if defined(__linux)
# include <sched.h> // For sched_getcpu()
#endif
#if defined(__APPLE__) && !defined(__arm64__)
# include <cpuid.h> // For __cpuid_count()
#endif
// clang-format on
class VlExecutionProfiler;
class VlThreadPool;
@ -155,6 +147,10 @@ private:
VL_UNCOPYABLE(VlWorkerThread);
protected:
friend class VlThreadPool;
const std::thread& cthread() const { return m_cthread; }
public:
// CONSTRUCTORS
explicit VlWorkerThread(VerilatedContext* contextp);
@ -205,6 +201,13 @@ class VlThreadPool final : public VerilatedVirtualBase {
// MEMBERS
std::vector<VlWorkerThread*> m_workers; // our workers
mutable VerilatedMutex m_mutex; // Guards indexes of unassigned workers
// Indexes of unassigned workers
std::stack<size_t> m_unassignedWorkers VL_GUARDED_BY(m_mutex);
// For sequentially generating task IDs to avoid shadowing
std::atomic<unsigned> m_assignedTasks{0};
std::string m_numaStatus; // Status of NUMA assignment
public:
// CONSTRUCTORS
// Construct a thread pool with 'nThreads' dedicated threads. The thread
@ -214,7 +217,21 @@ public:
~VlThreadPool() override;
// METHODS
size_t assignWorkerIndex() {
const VerilatedLockGuard lock{m_mutex};
assert(!m_unassignedWorkers.empty());
const size_t index = m_unassignedWorkers.top();
m_unassignedWorkers.pop();
return index;
}
void freeWorkerIndexes(std::vector<size_t>& indexes) {
const VerilatedLockGuard lock{m_mutex};
for (size_t index : indexes) m_unassignedWorkers.push(index);
indexes.clear();
}
unsigned assignTaskIndex() { return m_assignedTasks++; }
int numThreads() const { return static_cast<int>(m_workers.size()); }
std::string numaStatus() const { return m_numaStatus; }
VlWorkerThread* workerp(int index) {
assert(index >= 0);
assert(index < static_cast<int>(m_workers.size()));
@ -223,6 +240,9 @@ public:
private:
VL_UNCOPYABLE(VlThreadPool);
static bool isNumactlRunning();
std::string numaAssign();
};
#endif

View File

@ -47,7 +47,7 @@ static double timescaleToDouble(const char* unitp) VL_PURE {
// On error so we allow just "ns" to return 1e-9.
if (value == 0.0 && endp == unitp) value = 1;
unitp = endp;
for (; *unitp && std::isspace(*unitp); unitp++) {}
for (; *unitp && std::isspace(*unitp); ++unitp) {}
switch (*unitp) {
case 's': value *= 1e0; break;
case 'm': value *= 1e-3; break;

View File

@ -621,11 +621,13 @@ public:
T_Value& atWriteAppend(int32_t index) {
// cppcheck-suppress variableScope
static thread_local T_Value t_throwAway;
if (VL_UNLIKELY(index < 0 || index > m_deque.size())) {
if (VL_UNLIKELY(index < 0 || index >= m_deque.size())) {
if (index == m_deque.size()) {
push_back(atDefault());
return m_deque[index];
}
t_throwAway = atDefault();
return t_throwAway;
} else if (VL_UNLIKELY(index == m_deque.size())) {
push_back(atDefault());
}
return m_deque[index];
}
@ -924,6 +926,9 @@ std::string VL_TO_STRING(const VlQueue<T_Value, N_MaxSize>& obj) {
return obj.to_string();
}
template <typename T_Value, size_t N_MaxSize>
struct VlContainsCustomStruct<VlQueue<T_Value, N_MaxSize>> : VlContainsCustomStruct<T_Value> {};
//===================================================================
// Verilog associative array container
// There are no multithreaded locks on this; the base variable must
@ -964,6 +969,7 @@ public:
// Size of array. Verilog: function int size(), or int num()
int size() const { return m_map.size(); }
bool empty() const { return m_map.empty(); }
// Clear array. Verilog: function void delete([input index])
void clear() { m_map.clear(); }
void erase(const T_Key& index) { m_map.erase(index); }
@ -1259,6 +1265,9 @@ std::string VL_TO_STRING(const VlAssocArray<T_Key, T_Value>& obj) {
return obj.to_string();
}
template <typename T_Key, typename T_Value>
struct VlContainsCustomStruct<VlAssocArray<T_Key, T_Value>> : VlContainsCustomStruct<T_Value> {};
template <typename T_Key, typename T_Value>
void VL_READMEM_N(bool hex, int bits, const std::string& filename,
VlAssocArray<T_Key, T_Value>& obj, QData start, QData end) VL_MT_SAFE {
@ -1589,6 +1598,9 @@ std::string VL_TO_STRING(const VlUnpacked<T_Value, N_Depth>& obj) {
return obj.to_string();
}
template <typename T_Value, std::size_t N_Depth>
struct VlContainsCustomStruct<VlUnpacked<T_Value, N_Depth>> : VlContainsCustomStruct<T_Value> {};
//===================================================================
// Helper to apply the given indices to a target expression

View File

@ -15,9 +15,9 @@
/// \brief Verilated C++ tracing in VCD format implementation code
///
/// This file must be compiled and linked against all Verilated objects
/// that use --trace.
/// that use --trace-vcd.
///
/// Use "verilator --trace" to add this to the Makefile for the linker.
/// Use "verilator --trace-vcd" to add this to the Makefile for the linker.
///
//=============================================================================
@ -100,6 +100,8 @@ VerilatedVcd::VerilatedVcd(VerilatedVcdFile* filep) {
m_wrBufp = new char[m_wrChunkSize * 8];
m_wrFlushp = m_wrBufp + m_wrChunkSize * 6;
m_writep = m_wrBufp;
m_wrTimeBeginp = nullptr;
m_wrTimeEndp = nullptr;
}
void VerilatedVcd::open(const char* filename) VL_MT_SAFE_EXCLUDES(m_mutex) {
@ -187,10 +189,19 @@ bool VerilatedVcd::preChangeDump() {
}
void VerilatedVcd::emitTimeChange(uint64_t timeui) {
printStr("#");
const std::string str = std::to_string(timeui);
printStr(str.c_str());
printStr("\n");
// Remember pointers when last emitted time stamp; if last output was
// timestamp backup and overwrite it.
// This is faster then checking on every signal change if time needs to
// be emitted. Note buffer flushes may still emit a rare duplicate.
if (m_wrTimeEndp == m_writep) m_writep = m_wrTimeBeginp;
m_wrTimeBeginp = m_writep;
{
printStr("#");
const std::string str = std::to_string(timeui);
printStr(str.c_str());
printStr("\n");
}
m_wrTimeEndp = m_writep;
}
VerilatedVcd::~VerilatedVcd() {
@ -257,6 +268,10 @@ void VerilatedVcd::bufferResize(size_t minsize) {
m_wrBufp = new char[m_wrChunkSize * 8];
std::memcpy(m_wrBufp, oldbufp, m_writep - oldbufp);
m_writep = m_wrBufp + (m_writep - oldbufp);
if (m_wrTimeBeginp) {
m_wrTimeBeginp = m_wrBufp + (m_wrTimeBeginp - oldbufp);
m_wrTimeEndp = m_wrBufp + (m_wrTimeEndp - oldbufp);
}
m_wrFlushp = m_wrBufp + m_wrChunkSize * 6;
VL_DO_CLEAR(delete[] oldbufp, oldbufp = nullptr);
}
@ -293,6 +308,8 @@ void VerilatedVcd::bufferFlush() VL_MT_UNSAFE_ONE {
// Reset buffer
m_writep = m_wrBufp;
m_wrTimeBeginp = nullptr;
m_wrTimeEndp = nullptr;
}
//=============================================================================

View File

@ -55,6 +55,8 @@ private:
char* m_wrBufp; // Output buffer
char* m_wrFlushp; // Output buffer flush trigger location
char* m_writep; // Write pointer into output buffer
char* m_wrTimeBeginp = nullptr; // Write pointer for last time dump
char* m_wrTimeEndp = nullptr; // Write pointer for last time dump
size_t m_wrChunkSize; // Output buffer size
size_t m_maxSignalBytes = 0; // Upper bound on number of bytes a single signal can generate
uint64_t m_wroteBytes = 0; // Number of bytes written to this file

View File

@ -85,7 +85,7 @@ public:
// To simplify our free list, we use a size large enough for all derived types
// We reserve word zero for the next pointer, as that's safer in case a
// dangling reference to the original remains around.
static constexpr size_t CHUNK_SIZE = 128;
static constexpr size_t CHUNK_SIZE = 256;
if (VL_UNCOVERABLE(size > CHUNK_SIZE))
VL_FATAL_MT(__FILE__, __LINE__, "", "increase CHUNK_SIZE");
if (VL_LIKELY(t_freeHeadp)) {
@ -205,7 +205,7 @@ public:
uint32_t size() const override {
const int maxDimNum = maxDim(isIndexedDimUnpacked());
int size = 1;
for (int dim = indexedDim() + 1; dim <= maxDimNum; dim++)
for (int dim = indexedDim() + 1; dim <= maxDimNum; ++dim)
size *= varp()->range(dim)->elements();
return size;
}
@ -503,7 +503,7 @@ public:
explicit VerilatedVpioRegIter(const VerilatedVpioVar* vop)
: m_var{new VerilatedVpioVar(vop)}
, m_maxDim{vop->varp()->udims() - 1} {
for (auto it = vop->indexedDim() + 1; it <= m_maxDim; it++)
for (auto it = vop->indexedDim() + 1; it <= m_maxDim; ++it)
m_ranges.push_back(*vop->varp()->range(it));
for (auto it : m_ranges) m_nextIndex.push_back(it.right());
}
@ -2219,7 +2219,7 @@ vpiHandle vpi_iterate(PLI_INT32 type, vpiHandle object) {
std::vector<VerilatedRange> ranges;
const int maxDim = vop->maxDim(vop->isIndexedDimUnpacked());
for (int dim = vop->indexedDim() + 1; dim <= maxDim; dim++)
for (int dim = vop->indexedDim() + 1; dim <= maxDim; ++dim)
ranges.emplace_back(*vop->varp()->range(dim));
// allow one more range layer (regbit)
@ -2574,8 +2574,8 @@ void vl_vpi_put_word(const VerilatedVpioVar* vop, QData word, size_t bitCount, s
}
void vl_vpi_get_value(const VerilatedVpioVarBase* vop, p_vpi_value valuep) {
const VerilatedVar* varp = vop->varp();
void* varDatap = vop->varDatap();
const VerilatedVar* const varp = vop->varp();
void* const varDatap = vop->varDatap();
const char* fullname = vop->fullname();
if (!vl_check_format(varp, valuep, fullname, true)) return;
@ -2788,8 +2788,8 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value valuep, p_vpi_time /*time_
} else if (valuep->format == vpiOctStrVal) {
const int len = std::strlen(valuep->value.str);
for (int i = 0; i < len; ++i) {
char digit = valuep->value.str[len - i - 1] - '0';
if (digit < 0 || digit > 7) {
unsigned char digit = valuep->value.str[len - i - 1] - '0';
if (digit > 7) { // If str was < '0', then as unsigned, digit > 7
VL_VPI_WARNING_(__FILE__, __LINE__,
"%s: Non octal character '%c' in '%s' as value %s for %s",
__func__, digit + '0', valuep->value.str,
@ -2945,7 +2945,7 @@ void vl_get_value_array_integrals(unsigned index, const unsigned num, const unsi
const unsigned packedSize, const bool leftIsLow, const T* src,
K* dst) {
static_assert(sizeof(K) >= sizeof(T), "size of type K is less than size of type T");
for (int i = 0; i < num; i++) {
for (int i = 0; i < num; ++i) {
dst[i] = src[index];
index = leftIsLow ? index == (size - 1) ? 0 : index + 1
: index == 0 ? size - 1
@ -2964,7 +2964,7 @@ void vl_put_value_array_integrals(unsigned index, const unsigned num, const unsi
const T mask = element_size_bytes == sizeof(T)
? static_cast<T>(-1)
: ~(static_cast<T>(-1) << (element_size_bytes * 8));
for (unsigned i = 0; i < num; i++) {
for (unsigned i = 0; i < num; ++i) {
dst[index] = src[i] & static_cast<T>(mask);
index = leftIsLow ? index == (size - 1) ? 0 : index + 1
: index == 0 ? size - 1
@ -2980,9 +2980,8 @@ void vl_get_value_array_vectors(unsigned index, const unsigned num, const unsign
"type T is not unsigned"); // ensure logical right shift
const unsigned element_size_bytes = VL_BYTES_I(packedSize);
const unsigned element_size_words = VL_WORDS_I(packedSize);
const unsigned element_size_repr = (element_size_bytes + sizeof(T) - 1) / sizeof(T);
if (sizeof(T) == sizeof(QData)) {
for (unsigned i = 0; i < num; i++) {
for (unsigned i = 0; i < num; ++i) {
dst[i * 2].aval = static_cast<QData>(src[index]);
dst[i * 2].bval = 0;
dst[(i * 2) + 1].aval = static_cast<QData>(src[index]) >> 32;
@ -2992,10 +2991,10 @@ void vl_get_value_array_vectors(unsigned index, const unsigned num, const unsign
: index - 1;
}
} else {
for (unsigned i = 0; i < num; i++) {
for (unsigned i = 0; i < num; ++i) {
const size_t dst_index = i * element_size_words;
const size_t src_index = index * element_size_words;
for (unsigned j = 0; j < element_size_words; j++) {
for (unsigned j = 0; j < element_size_words; ++j) {
dst[dst_index + j].aval = src[src_index + j];
dst[dst_index + j].bval = 0;
}
@ -3018,7 +3017,7 @@ void vl_put_value_array_vectors(unsigned index, const unsigned num, const unsign
const QData mask = element_size_bytes == sizeof(T)
? static_cast<QData>(-1)
: ~(static_cast<QData>(-1) << (element_size_bytes * 8));
for (unsigned i = 0; i < num; i++) {
for (unsigned i = 0; i < num; ++i) {
dst[index] = src[i * 2].aval;
dst[index]
|= (static_cast<QData>(src[(i * 2) + 1].aval) << (sizeof(PLI_UINT32) * 8)) & mask;
@ -3027,9 +3026,9 @@ void vl_put_value_array_vectors(unsigned index, const unsigned num, const unsign
: index - 1;
}
} else {
for (unsigned i = 0; i < num; i++) {
for (unsigned i = 0; i < num; ++i) {
unsigned bytes_stored = 0;
for (unsigned j = 0; j < element_size_words; j++) {
for (unsigned j = 0; j < element_size_words; ++j) {
if (bytes_stored >= element_size_bytes) break;
const T mask
= (element_size_bytes - bytes_stored) >= sizeof(PLI_UINT32)
@ -3058,9 +3057,9 @@ void vl_get_value_array_rawvals(unsigned index, unsigned num, const unsigned siz
while (num-- > 0) {
const size_t src_offset = index * element_size_repr;
unsigned bytes_copied = 0;
for (unsigned j = 0; j < element_size_repr; j++) {
for (unsigned j = 0; j < element_size_repr; ++j) {
const T& src_data = src[src_offset + j];
for (unsigned k = 0; k < sizeof(T); k++) {
for (unsigned k = 0; k < sizeof(T); ++k) {
if (bytes_copied++ == element_size_bytes) break;
dst[dst_index++] = src_data >> (k * 8);
}
@ -3081,13 +3080,13 @@ void vl_put_value_array_rawvals(unsigned index, const unsigned num, const unsign
const bool fourState, const PLI_UBYTE8* src, T* dst) {
const unsigned element_size_bytes VL_BYTES_I(packedSize);
const unsigned element_size_repr = (element_size_bytes + sizeof(T) - 1) / sizeof(T);
for (unsigned i = 0; i < num; i++) {
for (unsigned i = 0; i < num; ++i) {
unsigned bytes_copied = 0;
const size_t dst_offset = index * element_size_repr;
const size_t src_offset = i * element_size_bytes;
for (unsigned j = 0; j < element_size_repr; j++) {
for (unsigned j = 0; j < element_size_repr; ++j) {
T& dst_data = dst[dst_offset + j];
for (unsigned k = 0; k < sizeof(T); k++) {
for (unsigned k = 0; k < sizeof(T); ++k) {
if (bytes_copied == element_size_bytes) break;
const unsigned src_index
= fourState ? (src_offset * 2) + bytes_copied : (src_offset) + bytes_copied;
@ -3102,7 +3101,7 @@ void vl_put_value_array_rawvals(unsigned index, const unsigned num, const unsign
}
}
void vl_get_value_array(vpiHandle object, p_vpi_arrayvalue arrayvalue_p, PLI_INT32* index_p,
void vl_get_value_array(vpiHandle object, p_vpi_arrayvalue arrayvalue_p, const PLI_INT32* index_p,
PLI_UINT32 num) {
const VerilatedVpioVar* const vop = VerilatedVpioVar::castp(object);
if (!vl_check_array_format(vop->varp(), arrayvalue_p, vop->fullname())) return;
@ -3119,7 +3118,7 @@ void vl_get_value_array(vpiHandle object, p_vpi_arrayvalue arrayvalue_p, PLI_INT
}
const bool leftIsLow = vop->rangep()->left() == vop->rangep()->low();
int index
const int index
= leftIsLow ? index_p[0] - vop->rangep()->left() : vop->rangep()->left() - index_p[0];
if (arrayvalue_p->format == vpiShortIntVal) {
@ -3310,9 +3309,8 @@ void vpi_get_value_array(vpiHandle object, p_vpi_arrayvalue arrayvalue_p, PLI_IN
return;
}
int lowRange = vop->rangep()->low();
int highRange = vop->rangep()->high();
const int lowRange = vop->rangep()->low();
const int highRange = vop->rangep()->high();
if ((index_p[0] > highRange) || (index_p[0] < lowRange)) {
VL_VPI_ERROR_(__FILE__, __LINE__, "%s: index %u for object %s is out of bounds [%u,%u]",
__func__, index_p[0], vop->fullname(), lowRange, highRange);
@ -3328,14 +3326,14 @@ void vpi_get_value_array(vpiHandle object, p_vpi_arrayvalue arrayvalue_p, PLI_IN
vl_get_value_array(object, arrayvalue_p, index_p, num);
}
void vl_put_value_array(vpiHandle object, p_vpi_arrayvalue arrayvalue_p, PLI_INT32* index_p,
void vl_put_value_array(vpiHandle object, p_vpi_arrayvalue arrayvalue_p, const PLI_INT32* index_p,
PLI_UINT32 num) {
const VerilatedVpioVar* const vop = VerilatedVpioVar::castp(object);
if (!vl_check_array_format(vop->varp(), arrayvalue_p, vop->fullname())) return;
const VerilatedVar* const varp = vop->varp();
int size = vop->size();
const int size = vop->size();
if (VL_UNCOVERABLE(num > size)) {
VL_VPI_ERROR_(__FILE__, __LINE__,
"%s: requested elements to set (%u) exceed array size (%u)", __func__, num,
@ -3344,7 +3342,7 @@ void vl_put_value_array(vpiHandle object, p_vpi_arrayvalue arrayvalue_p, PLI_INT
}
const bool leftIsLow = vop->rangep()->left() == vop->rangep()->low();
int index
const int index
= leftIsLow ? index_p[0] - vop->rangep()->left() : vop->rangep()->left() - index_p[0];
if (arrayvalue_p->format == vpiShortIntVal) {
@ -3492,11 +3490,8 @@ void vpi_put_value_array(vpiHandle object, p_vpi_arrayvalue arrayvalue_p, PLI_IN
return;
}
const VerilatedVar* const varp = vop->varp();
int lowRange = vop->rangep()->low();
int highRange = vop->rangep()->high();
const int lowRange = vop->rangep()->low();
const int highRange = vop->rangep()->high();
if ((index_p[0] > highRange) || (index_p[0] < lowRange)) {
VL_VPI_ERROR_(__FILE__, __LINE__, "%s: index %u for object %s is out of bounds [%u,%u]",
__func__, index_p[0], vop->fullname(), lowRange, highRange);

View File

@ -632,7 +632,12 @@ namespace VlOs {
/// Get environment variable
extern std::string getenvStr(const std::string& envvar,
const std::string& defaultValue) VL_MT_SAFE;
extern uint64_t memUsageBytes() VL_MT_SAFE; ///< Return memory usage in bytes, or 0 if unknown
/// Return currently executing processor number; may do an OS call underneath so slow
extern uint16_t getcpu() VL_MT_SAFE;
/// Return memory usage in bytes, or 0 if unknown
extern uint64_t memUsageBytes() VL_MT_SAFE;
// Internal: Record CPU time, starting point on construction, and current delta from that
class DeltaCpuTime final {

View File

@ -31,6 +31,13 @@
# include <processthreadsapi.h> // GetProcessTimes
# include <psapi.h> // GetProcessMemoryInfo
#endif
#if defined(__linux)
# include <sched.h> // For sched_getcpu()
#endif
#if defined(__APPLE__) && !defined(__arm64__)
# include <cpuid.h> // For __cpuid_count()
#endif
// clang-format on
namespace VlOs {
@ -72,6 +79,28 @@ double DeltaWallTime::gettime() VL_MT_SAFE {
#endif
}
//=============================================================================
// Vlos::getcpu implementation
uint16_t getcpu() VL_MT_SAFE {
#if defined(__linux)
return sched_getcpu(); // TODO: this is a system call. Not exactly cheap.
#elif defined(__APPLE__) && !defined(__arm64__)
uint32_t info[4];
__cpuid_count(1, 0, info[0], info[1], info[2], info[3]);
// info[1] is EBX, bits 24-31 are APIC ID
if ((info[3] & (1 << 9)) == 0) {
return 0; // no APIC on chip
} else {
return (unsigned)info[1] >> 24;
}
#elif defined(_WIN32)
return GetCurrentProcessorNumber();
#else
return 0;
#endif
}
//=========================================================================
// VlOs::memUsageBytes implementation

View File

@ -90,7 +90,7 @@ def process():
print()
print("You may now want to clean up spelling, and commit:")
print(" (cd docs ; make spelling | grep -v 'Writing output')")
print(" (cd docs ; make spelling | grep -vi 'writing output')")
print(" git ci -am 'Commentary: Changes update'")
print()

View File

@ -178,6 +178,7 @@ set(HEADERS
V3Trace.h
V3TraceDecl.h
V3Tristate.h
V3Udp.h
V3Undriven.h
V3UniqueNames.h
V3Unknown.h
@ -326,6 +327,7 @@ set(COMMON_SOURCES
V3TraceDecl.cpp
V3Tristate.cpp
V3TSP.cpp
V3Udp.cpp
V3Undriven.cpp
V3Unknown.cpp
V3Unroll.cpp

View File

@ -311,6 +311,7 @@ RAW_OBJS_PCH_ASTNOMT = \
V3Trace.o \
V3TraceDecl.o \
V3Tristate.o \
V3Udp.o \
V3Undriven.o \
V3Unknown.o \
V3Unroll.o \

View File

@ -314,7 +314,7 @@ class ActiveLatchCheckVisitor final : public VNVisitorConst {
void visit(AstVarRef* nodep) override {
const AstVar* const varp = nodep->varp();
if (nodep->access().isWriteOrRW() && varp->isSignal() && !varp->isUsedLoopIdx()
&& !varp->isFuncLocalSticky()) {
&& !varp->isFuncLocalSticky() && !varp->lifetime().isAutomatic()) {
m_graph.addAssignment(nodep);
}
}

View File

@ -295,7 +295,7 @@ private:
popp->makeStmt()});
}
} else {
nodep->v3fatal("Invalid direction");
nodep->v3fatalSrc("Invalid direction");
}
VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep);
}

View File

@ -64,10 +64,12 @@ std::ostream& operator<<(std::ostream& os, VNType rhs);
const std::shared_ptr<const string> VSelfPointerText::s_emptyp = std::make_shared<string>("");
const std::shared_ptr<const string> VSelfPointerText::s_thisp = std::make_shared<string>("this");
string VSelfPointerText::replaceThis(bool useSelfForThis, const string& text) {
return useSelfForThis ? VString::replaceWord(text, "this", "vlSelf") : text;
}
string VSelfPointerText::protect(bool useSelfForThis, bool protect) const {
const string& sp
= useSelfForThis ? VString::replaceWord(asString(), "this", "vlSelf") : asString();
return VIdProtect::protectWordsIf(sp, protect);
return VIdProtect::protectWordsIf(replaceThis(useSelfForThis, asString()), protect);
}
//######################################################################
@ -322,7 +324,7 @@ void AstNode::debugTreeChange(const AstNode* nodep, const char* prefix, int line
// // Commenting out the section below may crash, as the tree state
// // between edits is not always consistent for printing
// cout<<"-treeChange: V3Ast.cpp:"<<lineno<<" Tree Change for "<<prefix<<endl;
// v3Global.rootp()->dumpTree("- treeChange: ");
// if (debug()) v3Global.rootp()->dumpTree("- treeChange: ");
// if (next||1) nodep->dumpTreeAndNext(cout, prefix);
// else nodep->dumpTree(prefix);
// nodep->checkTree();
@ -519,6 +521,10 @@ void AstNode::replaceWith(AstNode* newp) {
this->unlinkFrBack(&repHandle);
repHandle.relink(newp);
}
void AstNode::replaceWithKeepDType(AstNode* newp) {
newp->dtypeFrom(this);
replaceWith(newp);
}
void VNRelinker::dump(std::ostream& str) const {
str << " BK=" << reinterpret_cast<uint32_t*>(m_backp);
@ -1340,7 +1346,7 @@ void AstNode::dumpTreeFile(const string& filename, bool doDump) {
{ // Write log & close
UINFO(2, "Dumping " << filename << endl);
const std::unique_ptr<std::ofstream> logsp{V3File::new_ofstream(filename)};
if (logsp->fail()) v3fatal("Can't write " << filename);
if (logsp->fail()) v3fatal("Can't write file: " << filename);
*logsp << "Verilator Tree Dump (format 0x3900) from <e" << std::dec << editCountLast();
*logsp << "> to <e" << std::dec << editCountGbl() << ">\n";
if (editCountGbl() == editCountLast() && ::dumpTreeLevel() < 9) {
@ -1385,7 +1391,7 @@ void AstNode::dumpTreeJsonFile(const string& filename, bool doDump) {
if (!doDump) return;
UINFO(2, "Dumping " << filename << endl);
const std::unique_ptr<std::ofstream> treejsonp{V3File::new_ofstream(filename)};
if (treejsonp->fail()) v3fatal("Can't write " << filename);
if (treejsonp->fail()) v3fatal("Can't write file: " << filename);
dumpTreeJson(*treejsonp);
*treejsonp << '\n';
}
@ -1394,7 +1400,7 @@ void AstNode::dumpJsonMetaFileGdb(const char* filename) { dumpJsonMetaFile(filen
void AstNode::dumpJsonMetaFile(const string& filename) {
UINFO(2, "Dumping " << filename << endl);
const std::unique_ptr<std::ofstream> treejsonp{V3File::new_ofstream(filename)};
if (treejsonp->fail()) v3fatalStatic("Can't write " << filename);
if (treejsonp->fail()) v3fatalStatic("Can't write file: " << filename);
*treejsonp << '{';
FileLine::fileNameNumMapDumpJson(*treejsonp);
*treejsonp << ',';
@ -1408,7 +1414,7 @@ void AstNode::dumpTreeDotFile(const string& filename, bool doDump) {
if (doDump) {
UINFO(2, "Dumping " << filename << endl);
const std::unique_ptr<std::ofstream> treedotp{V3File::new_ofstream(filename)};
if (treedotp->fail()) v3fatal("Can't write " << filename);
if (treedotp->fail()) v3fatal("Can't write file: " << filename);
*treedotp << "digraph vTree{\n";
*treedotp << "\tgraph\t[label=\"" << filename + ".dot"
<< "\",\n";

View File

@ -336,6 +336,7 @@ public:
NO_INLINE_TASK,
PUBLIC_MODULE,
PUBLIC_TASK,
TIMEUNIT_SET,
UNROLL_DISABLE,
UNROLL_FULL,
FULL_CASE,
@ -458,6 +459,7 @@ public:
ILLEGAL,
//
DIM_BITS, // V3Const converts to constant
DIM_BITS_OR_NUMBER, // V3Const converts to constant
DIM_DIMENSIONS, // V3Width converts to constant
DIM_HIGH, // V3Width processes
DIM_INCREMENT, // V3Width processes
@ -500,7 +502,8 @@ public:
// clang-format off
static const char* const names[] = {
"%E-AT",
"DIM_BITS", "DIM_DIMENSIONS", "DIM_HIGH", "DIM_INCREMENT", "DIM_LEFT",
"DIM_BITS", "DIM_BITS_OR_NUMBER", "DIM_DIMENSIONS",
"DIM_HIGH", "DIM_INCREMENT", "DIM_LEFT",
"DIM_LOW", "DIM_RIGHT", "DIM_SIZE", "DIM_UNPK_DIMENSIONS",
"DT_PUBLIC",
"ENUM_FIRST", "ENUM_LAST", "ENUM_NUM",
@ -1686,6 +1689,7 @@ public:
bool isVlSym() const { return m_strp->find("vlSymsp") != string::npos; }
bool hasThis() const { return m_strp == s_thisp || VString::startsWith(*m_strp, "this"); }
string protect(bool useSelfForThis, bool protect) const;
static string replaceThis(bool useSelfForThis, const string& text);
const std::string& asString() const { return *m_strp; }
bool operator==(const VSelfPointerText& other) const { return *m_strp == *other.m_strp; }
};
@ -2414,6 +2418,7 @@ public:
void addNextHere(AstNode* newp); // Insert newp at this->nextp
void addHereThisAsNext(AstNode* newp); // Adds at old place of this, this becomes next
void replaceWith(AstNode* newp); // Replace current node in tree with new node
void replaceWithKeepDType(AstNode* newp); // Replace current node in tree, keep old dtype
// Unlink this from whoever points to it.
AstNode* unlinkFrBack(VNRelinker* linkerp = nullptr);
// Unlink this from whoever points to it, keep entire next list with unlinked node

View File

@ -34,7 +34,7 @@ int AstNode::widthInstrs() const {
return (!dtypep() ? 1 : (dtypep()->isWide() ? dtypep()->widthWords() : 1));
}
bool AstNode::isDouble() const VL_MT_STABLE {
return dtypep() && VN_IS(dtypep(), BasicDType) && VN_AS(dtypep(), BasicDType)->isDouble();
return dtypep() && dtypep()->basicp() && dtypep()->basicp()->isDouble();
}
bool AstNode::isString() const VL_MT_STABLE {
return dtypep() && dtypep()->basicp() && dtypep()->basicp()->isString();

View File

@ -120,15 +120,7 @@ public:
// Iff has second dtype, set as generic node function
virtual void virtRefDType2p(AstNodeDType* nodep) {}
// Assignable equivalence. Calls skipRefToNonRefp() during comparisons.
bool similarDType(const AstNodeDType* samep) const {
const AstNodeDType* nodep = this;
nodep = nodep->skipRefToNonRefp();
samep = samep->skipRefToNonRefp();
if (nodep == samep) return true;
if (nodep->type() != samep->type()) return false;
return nodep->similarDTypeNode(samep);
}
bool similarDType(const AstNodeDType* samep) const;
// Iff has a non-null subDTypep(), as generic node function
virtual AstNodeDType* subDTypep() const VL_MT_STABLE { return nullptr; }
virtual bool isFourstate() const;
@ -165,7 +157,7 @@ public:
bool generic() const VL_MT_SAFE { return m_generic; }
void generic(bool flag) { m_generic = flag; }
std::pair<uint32_t, uint32_t> dimensions(bool includeBasic);
uint32_t arrayUnpackedElements(); // 1, or total multiplication of all dimensions
uint32_t arrayUnpackedElements() const; // 1, or total multiplication of all dimensions
static int uniqueNumInc() { return ++s_uniqueNum; }
const char* charIQWN() const {
return (isString() ? "N" : isWide() ? "W" : isQuad() ? "Q" : "I");
@ -435,6 +427,8 @@ public:
string prettyDTypeName(bool full) const override;
const char* broken() const override {
BROKEN_RTN(dtypep() != this);
BROKEN_RTN(v3Global.widthMinUsage() == VWidthMinUsage::VERILOG_WIDTH
&& widthMin() > width());
return nullptr;
}
void setSignedState(const VSigning& signst) {
@ -581,7 +575,11 @@ public:
const AstClassRefDType* const asamep = VN_DBG_AS(samep, ClassRefDType);
return (m_classp == asamep->m_classp && m_classOrPackagep == asamep->m_classOrPackagep);
}
bool similarDTypeNode(const AstNodeDType* samep) const override { return sameNode(samep); }
bool similarDTypeNode(const AstNodeDType* samep) const override {
// Doesn't need to compare m_classOrPackagep
const AstClassRefDType* const asamep = VN_DBG_AS(samep, ClassRefDType);
return m_classp == asamep->m_classp;
}
void dump(std::ostream& str = std::cout) const override;
void dumpJson(std::ostream& str = std::cout) const override;
void dumpSmall(std::ostream& str) const override;
@ -668,16 +666,12 @@ class AstDefImplicitDType final : public AstNodeDType {
// After link, these become typedefs
// @astgen op1 := childDTypep : Optional[AstNodeDType]
string m_name;
void* m_containerp; // In what scope is the name unique, so we can know what are duplicate
// definitions (arbitrary value)
const int m_uniqueNum;
public:
AstDefImplicitDType(FileLine* fl, const string& name, void* containerp, VFlagChildDType,
AstNodeDType* dtp)
AstDefImplicitDType(FileLine* fl, const string& name, VFlagChildDType, AstNodeDType* dtp)
: ASTGEN_SUPER_DefImplicitDType(fl)
, m_name{name}
, m_containerp{containerp}
, m_uniqueNum{uniqueNumInc()} {
childDTypep(dtp); // Only for parser
dtypep(nullptr); // V3Width will resolve
@ -685,7 +679,6 @@ public:
AstDefImplicitDType(const AstDefImplicitDType& other)
: AstNodeDType(other)
, m_name(other.m_name)
, m_containerp(other.m_containerp)
, m_uniqueNum(uniqueNumInc()) {}
ASTGEN_MEMBERS_AstDefImplicitDType;
int uniqueNum() const { return m_uniqueNum; }
@ -698,7 +691,6 @@ public:
AstNodeDType* subDTypep() const override VL_MT_STABLE {
return dtypep() ? dtypep() : childDTypep();
}
void* containerp() const { return m_containerp; }
// METHODS
// op1 = Range of variable
AstNodeDType* dtypeSkipRefp() const { return dtypep()->skipRefp(); }
@ -1392,13 +1384,20 @@ public:
string verilogKwd() const override { return "struct"; }
};
class AstUnionDType final : public AstNodeUOrStructDType {
bool m_isSoft; // Is a "union soft"
public:
// UNSUP: bool isTagged;
// VSigning below is mispurposed to indicate if packed or not
AstUnionDType(FileLine* fl, VSigning numericUnpack)
: ASTGEN_SUPER_UnionDType(fl, numericUnpack) {}
// isSoft implies packed
AstUnionDType(FileLine* fl, bool isSoft, VSigning numericUnpack)
: ASTGEN_SUPER_UnionDType(fl, numericUnpack)
, m_isSoft(isSoft) {
packed(packed() | m_isSoft);
}
ASTGEN_MEMBERS_AstUnionDType;
string verilogKwd() const override { return "union"; }
bool isSoft() const { return m_isSoft; }
};
#endif // Guard

View File

@ -953,7 +953,7 @@ class AstConst final : public AstNodeExpr {
} else if (m_num.isString()) {
dtypeSetString();
} else {
dtypeSetLogicUnsized(m_num.width(), (m_num.sized() ? 0 : m_num.widthMin()),
dtypeSetLogicUnsized(m_num.width(), (m_num.sized() ? 0 : m_num.widthToFit()),
VSigning::fromBool(m_num.isSigned()));
}
m_num.nodep(this);
@ -987,7 +987,7 @@ public:
class VerilogStringLiteral {}; // for creator type-overload selection
AstConst(FileLine* fl, VerilogStringLiteral, const string& str)
: ASTGEN_SUPER_Const(fl)
, m_num(V3Number::VerilogStringLiteral{}, this, str) {
, m_num{V3Number::VerilogStringLiteral{}, this, str} {
initWithNumber();
}
AstConst(FileLine* fl, uint32_t num)
@ -1000,14 +1000,14 @@ public:
: ASTGEN_SUPER_Const(fl)
, m_num(this, 32, num) {
m_num.width(32, false);
dtypeSetLogicUnsized(32, m_num.widthMin(), VSigning::UNSIGNED);
dtypeSetLogicUnsized(32, m_num.widthToFit(), VSigning::UNSIGNED);
}
class Signed32 {}; // for creator type-overload selection
AstConst(FileLine* fl, Signed32, int32_t num) // Signed 32-bit integer of specified value
: ASTGEN_SUPER_Const(fl)
, m_num(this, 32, num) {
m_num.width(32, true);
dtypeSetLogicUnsized(32, m_num.widthMin(), VSigning::SIGNED);
dtypeSetLogicUnsized(32, m_num.widthToFit(), VSigning::SIGNED);
}
class Unsized64 {}; // for creator type-overload selection
AstConst(FileLine* fl, Unsized64, uint64_t num)
@ -1033,7 +1033,7 @@ public:
class String {}; // for creator type-overload selection
AstConst(FileLine* fl, String, const string& num)
: ASTGEN_SUPER_Const(fl)
, m_num(V3Number::String{}, this, num) {
, m_num{V3Number::String{}, this, num} {
dtypeSetString();
}
class BitFalse {};
@ -1066,14 +1066,14 @@ public:
class Null {};
AstConst(FileLine* fl, Null)
: ASTGEN_SUPER_Const(fl)
, m_num(V3Number::Null{}, this) {
, m_num{V3Number::Null{}, this} {
dtypeSetBit(); // Events 1 bit, objects 64 bits, so autoExtend=1 and use bit here
initWithNumber();
}
class OneStep {};
AstConst(FileLine* fl, OneStep)
: ASTGEN_SUPER_Const(fl)
, m_num(V3Number::OneStep{}, this) {
, m_num{V3Number::OneStep{}, this} {
dtypeSetLogicSized(64, VSigning::UNSIGNED);
initWithNumber();
}
@ -1156,6 +1156,20 @@ public:
string emitC() override { V3ERROR_NA_RETURN(""); }
bool cleanOut() const override { return true; }
};
class AstCvtUnpackedToQueue final : public AstNodeExpr {
// Cast from unpacked array to dynamic/unpacked queue data type
// @astgen op1 := fromp : AstNodeExpr
public:
AstCvtUnpackedToQueue(FileLine* fl, AstNodeExpr* fromp, AstNodeDType* dtp)
: ASTGEN_SUPER_CvtUnpackedToQueue(fl) {
this->fromp(fromp);
dtypeFrom(dtp);
}
ASTGEN_MEMBERS_AstCvtUnpackedToQueue;
string emitVerilog() override { V3ERROR_NA_RETURN(""); }
string emitC() override { return "VL_CVT_UNPACK_TO_Q(%P, %li)"; }
bool cleanOut() const override { return true; }
};
class AstDist final : public AstNodeExpr {
// @astgen op1 := exprp : AstNodeExpr
// @astgen op2 := itemsp : List[AstDistItem]
@ -1913,6 +1927,7 @@ public:
}
ASTGEN_MEMBERS_AstSFormatF;
string name() const override VL_MT_STABLE { return m_text; }
void name(const string& name) override { m_text = name; }
int instrCount() const override { return INSTR_COUNT_PLI; }
bool sameNode(const AstNode* samep) const override {
return text() == VN_DBG_AS(samep, SFormatF)->text();
@ -4407,12 +4422,15 @@ public:
class AstNew final : public AstNodeFTaskRef {
// New as constructor
// Don't need the class we are extracting from, as the "fromp()"'s datatype can get us to it
bool m_isImplicit = false; // Implicitly generated from extends args
public:
AstNew(FileLine* fl, AstNodeExpr* pinsp)
: ASTGEN_SUPER_New(fl, "new", pinsp) {}
ASTGEN_MEMBERS_AstNew;
bool sameNode(const AstNode* /*samep*/) const override { return true; }
int instrCount() const override { return widthInstrs(); }
bool isImplicit() const { return m_isImplicit; }
void isImplicit(bool flag) { m_isImplicit = flag; }
};
class AstTaskRef final : public AstNodeFTaskRef {
// A reference to a task
@ -5742,6 +5760,7 @@ class AstVarXRef final : public AstNodeVarRef {
string m_name;
string m_dotted; // Dotted part of scope the name()'ed reference is under or ""
string m_inlinedDots; // Dotted hierarchy flattened out
bool m_containsGenBlock = false; // Contains gen block reference
public:
AstVarXRef(FileLine* fl, const string& name, const string& dotted, const VAccess& access)
: ASTGEN_SUPER_VarXRef(fl, nullptr, access)
@ -5757,6 +5776,8 @@ public:
void dotted(const string& dotted) { m_dotted = dotted; }
string inlinedDots() const { return m_inlinedDots; }
void inlinedDots(const string& flag) { m_inlinedDots = flag; }
bool containsGenBlock() const { return m_containsGenBlock; }
void containsGenBlock(const bool flag) { m_containsGenBlock = flag; }
string emitVerilog() override { V3ERROR_NA_RETURN(""); }
string emitC() override { V3ERROR_NA_RETURN(""); }
bool cleanOut() const override { return true; }

View File

@ -631,8 +631,10 @@ class AstCFunc final : public AstNode {
bool m_isConstructor : 1; // Is C class constructor
bool m_isDestructor : 1; // Is C class destructor
bool m_isMethod : 1; // Is inside a class definition
bool m_isLoose : 1; // Semantically this is a method, but is implemented as a function
// with an explicitly passed 'self' pointer as the first argument
bool m_isLoose : 1; // Semantically this is a method, but is implemented as a function with
// an explicitly passed 'self' pointer as the first argument. This can
// be slightly faster due to __restrict, and we do not declare in header
// so adding/removing loose functions doesn't recompile everything.
bool m_isInline : 1; // Inline function
bool m_isVirtual : 1; // Virtual function
bool m_entryPoint : 1; // User may call into this top level function
@ -915,6 +917,7 @@ class AstClassExtends final : public AstNode {
// during early parse, then moves to dtype
// @astgen op1 := childDTypep : Optional[AstNodeDType]
// @astgen op2 := classOrPkgsp : Optional[AstNode]
// @astgen op3 := argsp : List[AstNodeExpr]
const bool m_isImplements = false; // class implements
bool m_parameterized = false; // has parameters in its statement
@ -1491,18 +1494,24 @@ public:
};
class AstPragma final : public AstNode {
const VPragmaType m_pragType; // Type of pragma
const VTimescale m_timescale; // For TIMEUNIT_SET
public:
// Pragmas don't result in any output code, they're just flags that affect
// other processing in verilator.
AstPragma(FileLine* fl, VPragmaType pragType)
: ASTGEN_SUPER_Pragma(fl)
, m_pragType{pragType} {}
AstPragma(FileLine* fl, VPragmaType pragType, const VTimescale& timescale)
: ASTGEN_SUPER_Pragma(fl)
, m_pragType{pragType}
, m_timescale(timescale) {}
ASTGEN_MEMBERS_AstPragma;
VPragmaType pragType() const { return m_pragType; } // *=type of the pragma
bool isPredictOptimizable() const override { return false; }
bool sameNode(const AstNode* samep) const override {
return pragType() == VN_DBG_AS(samep, Pragma)->pragType();
}
VTimescale timescale() const { return m_timescale; }
};
class AstPropSpec final : public AstNode {
// A clocked property
@ -1797,19 +1806,48 @@ class AstUdpTable final : public AstNode {
public:
AstUdpTable(FileLine* fl, AstUdpTableLine* linesp)
: ASTGEN_SUPER_UdpTable(fl) {
addLinesp(linesp);
this->addLinesp(linesp);
if (!v3Global.hasTable()) v3Global.setHasTable();
}
ASTGEN_MEMBERS_AstUdpTable;
};
class AstUdpTableLine final : public AstNode {
string m_text;
// @astgen op1 := iFieldsp : List[AstUdpTableLineVal] // Input fields
// @astgen op2 := oFieldsp : List[AstUdpTableLineVal] // Output fields
private:
const bool m_udpIsCombo; // Combinational or sequential UDP
public:
AstUdpTableLine(FileLine* fl, const string& text)
class UdpCombo {};
AstUdpTableLine(UdpCombo, FileLine* fl, AstUdpTableLineVal* iFieldsp,
AstUdpTableLineVal* oFieldsp)
: ASTGEN_SUPER_UdpTableLine(fl)
, m_text{text} {}
, m_udpIsCombo{true} {
addIFieldsp(iFieldsp);
addOFieldsp(oFieldsp);
}
class UdpSequential {};
AstUdpTableLine(UdpSequential, FileLine* fl, AstUdpTableLineVal* iFieldsp,
AstUdpTableLineVal* oFieldsp1, AstUdpTableLineVal* oFieldsp2)
: ASTGEN_SUPER_UdpTableLine(fl)
, m_udpIsCombo{false} {
addIFieldsp(iFieldsp);
addOFieldsp(oFieldsp1);
addOFieldsp(oFieldsp2);
}
ASTGEN_MEMBERS_AstUdpTableLine;
int udpIsCombo() const { return m_udpIsCombo; }
};
class AstUdpTableLineVal final : public AstNode {
string m_text; // Value character
public:
AstUdpTableLineVal(FileLine* fl, const string& text)
: ASTGEN_SUPER_UdpTableLineVal(fl)
, m_text{text} {}
ASTGEN_MEMBERS_AstUdpTableLineVal;
string name() const override VL_MT_STABLE { return m_text; }
void name(std::string const& text) override VL_MT_STABLE { m_text = text; }
string text() const VL_MT_SAFE { return m_text; }
};
class AstVar final : public AstNode {
@ -2489,14 +2527,28 @@ public:
};
class AstModule final : public AstNodeModule {
// A module declaration
const bool m_isProgram; // Module represents a program
const bool m_isChecker = false; // Module represents a checker
const bool m_isProgram = false; // Module represents a program
public:
AstModule(FileLine* fl, const string& name, bool program = false)
class Checker {}; // for constructor type-overload selection
class Program {}; // for constructor type-overload selection
AstModule(FileLine* fl, const string& name)
: ASTGEN_SUPER_Module(fl, name) {}
AstModule(FileLine* fl, const string& name, Checker)
: ASTGEN_SUPER_Module(fl, name)
, m_isProgram{program} {}
, m_isChecker{true} {}
AstModule(FileLine* fl, const string& name, Program)
: ASTGEN_SUPER_Module(fl, name)
, m_isProgram{true} {}
ASTGEN_MEMBERS_AstModule;
string verilogKwd() const override { return m_isProgram ? "program" : "module"; }
string verilogKwd() const override {
return m_isChecker ? "checker" : m_isProgram ? "program" : "module";
}
bool timescaleMatters() const override { return true; }
bool isChecker() const { return m_isChecker; }
bool isProgram() const { return m_isProgram; }
void dump(std::ostream& str) const override;
void dumpJson(std::ostream& str) const override;
};
class AstNotFoundModule final : public AstNodeModule {
// A missing module declaration
@ -3339,6 +3391,24 @@ public:
int instrCount() const override { return INSTR_COUNT_PLI; }
bool sameNode(const AstNode* /*samep*/) const override { return true; }
};
class AstSetuphold final : public AstNodeStmt {
// Verilog $setuphold
// @astgen op1 := refevp : AstNodeExpr
// @astgen op2 := dataevp : AstNodeExpr
// @astgen op3 := delrefp : Optional[AstNodeExpr]
// @astgen op4 := deldatap : Optional[AstNodeExpr]
public:
AstSetuphold(FileLine* fl, AstNodeExpr* refevp, AstNodeExpr* dataevp,
AstNodeExpr* delrefp = nullptr, AstNodeExpr* deldatap = nullptr)
: ASTGEN_SUPER_Setuphold(fl) {
this->refevp(refevp);
this->dataevp(dataevp);
this->delrefp(delrefp);
this->deldatap(deldatap);
}
ASTGEN_MEMBERS_AstSetuphold;
bool sameNode(const AstNode* /*samep*/) const override { return true; }
};
class AstStackTraceT final : public AstNodeStmt {
// $stacktrace used as task
public:
@ -3898,6 +3968,14 @@ public:
bool isPure() override { return false; } // SPECIAL: User may order w/other sigs
bool isOutputter() override { return true; }
};
class AstScHdrPost final : public AstNodeText {
public:
AstScHdrPost(FileLine* fl, const string& textp)
: ASTGEN_SUPER_ScHdrPost(fl, textp) {}
ASTGEN_MEMBERS_AstScHdrPost;
bool isPure() override { return false; } // SPECIAL: User may order w/other sigs
bool isOutputter() override { return true; }
};
class AstScImp final : public AstNodeText {
public:
AstScImp(FileLine* fl, const string& textp)

View File

@ -848,6 +848,15 @@ const AstNodeDType* AstNodeDType::skipRefIterp(bool skipConst, bool skipEnum,
}
}
bool AstNodeDType::similarDType(const AstNodeDType* samep) const {
const AstNodeDType* nodep = this;
nodep = nodep->skipRefToNonRefp();
samep = samep->skipRefToNonRefp();
if (nodep == samep) return true;
if (nodep->type() != samep->type()) return false;
return nodep->similarDTypeNode(samep);
}
bool AstNodeDType::isFourstate() const { return basicp() && basicp()->isFourstate(); }
class AstNodeDType::CTypeRecursed final {
@ -1007,11 +1016,11 @@ AstNodeDType::CTypeRecursed AstNodeDType::cTypeRecurse(bool compound, bool packe
return info;
}
uint32_t AstNodeDType::arrayUnpackedElements() {
uint32_t AstNodeDType::arrayUnpackedElements() const {
uint32_t entries = 1;
for (AstNodeDType* dtypep = this; dtypep;) {
for (const AstNodeDType* dtypep = this; dtypep;) {
dtypep = dtypep->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node
if (AstUnpackArrayDType* const adtypep = VN_CAST(dtypep, UnpackArrayDType)) {
if (const AstUnpackArrayDType* const adtypep = VN_CAST(dtypep, UnpackArrayDType)) {
entries *= adtypep->elementsConst();
dtypep = adtypep->subDTypep();
} else {
@ -1852,10 +1861,10 @@ void AstIfaceRefDType::dump(std::ostream& str) const {
if (ifaceName() != "") str << " if=" << ifaceName();
if (modportName() != "") str << " mp=" << modportName();
if (cellp()) {
str << " -> ";
str << " c-> ";
cellp()->dump(str);
} else if (ifacep()) {
str << " -> ";
str << " i-> ";
ifacep()->dump(str);
} else {
str << " -> UNLINKED";
@ -2039,6 +2048,16 @@ void AstModportVarRef::dumpJson(std::ostream& str) const {
dumpJsonStr(str, "direction", direction().ascii());
dumpJsonGen(str);
}
void AstModule::dump(std::ostream& str) const {
this->AstNodeModule::dump(str);
if (isChecker()) str << " [CHECKER]";
if (isProgram()) str << " [PROGRAM]";
}
void AstModule::dumpJson(std::ostream& str) const {
dumpJsonBoolFunc(str, isChecker);
dumpJsonBoolFunc(str, isProgram);
dumpJsonGen(str);
}
void AstPin::dump(std::ostream& str) const {
this->AstNode::dump(str);
if (modVarp()) {
@ -2500,6 +2519,7 @@ AstNodeVarRef* AstNodeVarRef::varRefLValueRecurse(AstNode* nodep) {
void AstVarXRef::dump(std::ostream& str) const {
this->AstNodeVarRef::dump(str);
if (containsGenBlock()) str << " [GENBLK]";
str << ".=" << dotted() << " ";
if (inlinedDots() != "") str << " inline.=" << inlinedDots() << " - ";
if (varScopep()) {
@ -2511,6 +2531,7 @@ void AstVarXRef::dump(std::ostream& str) const {
}
}
void AstVarXRef::dumpJson(std::ostream& str) const {
dumpJsonBoolFunc(str, containsGenBlock);
dumpJsonStrFunc(str, dotted);
dumpJsonStrFunc(str, inlinedDots);
dumpJsonGen(str);

View File

@ -114,7 +114,7 @@ public:
callp->argTypes("vlSymsp");
} else {
if (m_type.isCoverage()) callp->argTypes("first");
callp->selfPointer(VSelfPointerText{VSelfPointerText::This()});
callp->selfPointer(VSelfPointerText{VSelfPointerText::This{}});
}
rootFuncp->addStmtsp(callp->makeStmt());
}
@ -132,12 +132,22 @@ private:
class CCtorsVisitor final : public VNVisitor {
// NODE STATE
// STATE
// STATE - for current visit position (use VL_RESTORER)
AstNodeModule* m_modp = nullptr; // Current module
AstCFunc* m_cfuncp = nullptr; // Current function
V3CCtorsBuilder* m_varResetp = nullptr; // Builder of _ctor_var_reset
// VISITs
// METHODS
static void insertSc(AstCFunc* cfuncp, const AstNodeModule* modp, VNType type) {
auto textAndFileline = EmitCBaseVisitorConst::textSection(modp, type);
if (!textAndFileline.first.empty()) {
AstTextBlock* const newp
= new AstTextBlock{textAndFileline.second, textAndFileline.first, false, false};
cfuncp->addStmtsp(newp);
}
}
// VISITORS
void visit(AstNodeModule* nodep) override {
VL_RESTORER(m_modp);
VL_RESTORER(m_varResetp);
@ -167,6 +177,7 @@ class CCtorsVisitor final : public VNVisitor {
// If can be referred to by base pointer, need virtual delete
funcp->isVirtual(classp->isExtended());
funcp->slow(false);
insertSc(funcp, classp, VNType::atScDtor);
classp->addStmtsp(funcp);
}
}
@ -177,6 +188,7 @@ class CCtorsVisitor final : public VNVisitor {
m_varResetp = nullptr;
m_cfuncp = nodep;
iterateChildren(nodep);
if (nodep->name() == "new") insertSc(nodep, m_modp, VNType::atScCtor);
}
void visit(AstVar* nodep) override {
if (nodep->needsCReset()) {
@ -223,7 +235,7 @@ void V3CCtors::evalAsserts() {
// if (signal & CONST(upper_non_clean_mask)) { fail; }
AstVarRef* const vrefp
= new AstVarRef{varp->fileline(), varp, VAccess::READ};
vrefp->selfPointer(VSelfPointerText{VSelfPointerText::This()});
vrefp->selfPointer(VSelfPointerText{VSelfPointerText::This{}});
AstNodeExpr* newp = vrefp;
if (varp->isWide()) {
newp = new AstWordSel{

View File

@ -578,7 +578,7 @@ class CaseVisitor final : public VNVisitor {
}
//--------------------
void visit(AstAlways* nodep) override {
VL_RESTORER(m_alwaysp)
VL_RESTORER(m_alwaysp);
m_alwaysp = nodep;
iterateChildren(nodep);
}

View File

@ -40,7 +40,7 @@ class ClassVisitor final : public VNVisitor {
const VNUser1InUse m_inuser1;
// MEMBERS
string m_prefix; // String prefix to add to name based on hier
string m_prefix; // String prefix to add to class name based on hier
V3UniqueNames m_names; // For unique naming of structs and unions
AstNodeModule* m_modp = nullptr; // Current module
AstNodeModule* m_classPackagep = nullptr; // Package moving into

View File

@ -45,7 +45,7 @@ class CleanVisitor final : public VNVisitor {
// TYPES
enum CleanState : uint8_t { CS_UNKNOWN, CS_CLEAN, CS_DIRTY };
// STATE
// STATE - for current visit position (use VL_RESTORER)
const AstNodeModule* m_modp = nullptr;
// METHODS

View File

@ -68,8 +68,9 @@ public:
class ClockVisitor final : public VNVisitor {
// NODE STATE
// STATE
AstCFunc* m_evalp = nullptr; // The '_eval' function
AstCFunc* const m_evalp = nullptr; // The '_eval' function
AstSenTree* m_lastSenp = nullptr; // Last sensitivity match, so we can detect duplicates.
AstIf* m_lastIfp = nullptr; // Last sensitivity if active to add more under
@ -96,7 +97,7 @@ class ClockVisitor final : public VNVisitor {
}
// VISITORS
void visit(AstCoverToggle* nodep) override {
// nodep->dumpTree("- ct: ");
// if (debug()) nodep->dumpTree("- ct: ");
// COVERTOGGLE(INC, ORIG, CHANGE) ->
// IF(ORIG ^ CHANGE) { INC; CHANGE = ORIG; }
AstNode* const incp = nodep->incp()->unlinkFrBack();
@ -174,8 +175,8 @@ class ClockVisitor final : public VNVisitor {
public:
// CONSTRUCTORS
explicit ClockVisitor(AstNetlist* netlistp) {
m_evalp = netlistp->evalp();
explicit ClockVisitor(AstNetlist* netlistp)
: m_evalp{netlistp->evalp()} {
// Simplify all SenTrees
for (AstSenTree* senTreep = netlistp->topScopep()->senTreesp(); senTreep;
senTreep = VN_AS(senTreep->nextp(), SenTree)) {

View File

@ -540,6 +540,8 @@ class V3ConfigResolver final {
std::unordered_map<string, std::unordered_map<string, uint64_t>>
m_profileData; // Access to profile_data records
uint8_t m_mode = NONE;
std::unordered_map<string, int> m_hierWorkers;
FileLine* m_hierWorkersFileLine = nullptr;
FileLine* m_profileFileLine = nullptr;
V3ConfigResolver() = default;
@ -570,6 +572,16 @@ public:
// Empty key for hierarchical DPI wrapper costs.
return getProfileData(hierDpi, "");
}
void addHierWorkers(FileLine* fl, const string& model, int workers) {
if (!m_hierWorkersFileLine) m_hierWorkersFileLine = fl;
m_hierWorkers[model] = workers;
}
int getHierWorkers(const string& model) const {
const auto mit = m_hierWorkers.find(model);
// Assign a single worker if no specified.
return mit != m_hierWorkers.cend() ? mit->second : 0;
}
FileLine* getHierWorkersFileLine() const { return m_hierWorkersFileLine; }
uint64_t getProfileData(const string& model, const string& key) const {
const auto mit = m_profileData.find(model);
if (mit == m_profileData.cend()) return 0;
@ -602,6 +614,10 @@ void V3Config::addCoverageBlockOff(const string& module, const string& blockname
V3ConfigResolver::s().modules().at(module).addCoverageBlockOff(blockname);
}
void V3Config::addHierWorkers(FileLine* fl, const string& model, int workers) {
V3ConfigResolver::s().addHierWorkers(fl, model, workers);
}
void V3Config::addIgnore(V3ErrorCode code, bool on, const string& filename, int min, int max) {
if (filename == "*") {
FileLine::globalWarnOff(code, !on);
@ -741,6 +757,12 @@ void V3Config::applyVarAttr(AstNodeModule* modulep, AstNodeFTask* ftaskp, AstVar
if (vp) vp->apply(varp);
}
int V3Config::getHierWorkers(const string& model) {
return V3ConfigResolver::s().getHierWorkers(model);
}
FileLine* V3Config::getHierWorkersFileLine() {
return V3ConfigResolver::s().getHierWorkersFileLine();
}
uint64_t V3Config::getProfileData(const string& hierDpi) {
return V3ConfigResolver::s().getProfileData(hierDpi);
}

View File

@ -33,6 +33,7 @@ public:
static void addCaseParallel(const string& file, int lineno);
static void addCoverageBlockOff(const string& file, int lineno);
static void addCoverageBlockOff(const string& module, const string& blockname);
static void addHierWorkers(FileLine* fl, const string& model, int workers);
static void addIgnore(V3ErrorCode code, bool on, const string& filename, int min, int max);
static void addIgnoreMatch(V3ErrorCode code, const string& filename, const string& contents,
const string& match);
@ -52,6 +53,8 @@ public:
static void applyModule(AstNodeModule* modulep);
static void applyVarAttr(AstNodeModule* modulep, AstNodeFTask* ftaskp, AstVar* varp);
static int getHierWorkers(const string& model);
static FileLine* getHierWorkersFileLine();
static uint64_t getProfileData(const string& hierDpi);
static uint64_t getProfileData(const string& model, const string& key);
static FileLine* getProfileDataFileLine();

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