Merge from master for release.
This commit is contained in:
commit
0dc93c1d5c
|
|
@ -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?
|
||||
|
||||
|
|
|
|||
|
|
@ -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?
|
||||
|
|
|
|||
|
|
@ -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,134 +23,155 @@ concurrency:
|
|||
|
||||
jobs:
|
||||
|
||||
build:
|
||||
build-2404-gcc:
|
||||
name: Build
|
||||
uses: ./.github/workflows/reusable-build.yml
|
||||
with:
|
||||
os: ${{ matrix.os }}
|
||||
cc: ${{ matrix.cc }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-24.04, ubuntu-22.04, ubuntu-20.04]
|
||||
compiler:
|
||||
- {cc: clang, cxx: clang++}
|
||||
- {cc: gcc, cxx: g++}
|
||||
include:
|
||||
# Build GCC 10 on ubuntu-20.04
|
||||
- os: ubuntu-20.04
|
||||
compiler: {cc: gcc-10, cxx: g++-10}
|
||||
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:
|
||||
- {os: ubuntu-24.04, cc: gcc}
|
||||
|
||||
- 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-clang:
|
||||
name: Build
|
||||
uses: ./.github/workflows/reusable-build.yml
|
||||
with:
|
||||
os: ${{ matrix.os }}
|
||||
cc: ${{ matrix.cc }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-22.04, ubuntu-20.04]
|
||||
compiler:
|
||||
- {cc: clang, cxx: clang++}
|
||||
- {cc: gcc, cxx: g++}
|
||||
reloc: [0]
|
||||
suite: [dist-vlt-0, dist-vlt-1, dist-vlt-2, dist-vlt-3, vltmt-0, vltmt-1]
|
||||
include:
|
||||
# Test with GCC 10 on ubuntu-20.04, also test relocation
|
||||
- {os: ubuntu-20.04, compiler: {cc: gcc-10, cxx: g++-10}, reloc: 1, suite: dist-vlt-0}
|
||||
- {os: ubuntu-20.04, compiler: {cc: gcc-10, cxx: g++-10}, reloc: 1, suite: dist-vlt-1}
|
||||
- {os: ubuntu-20.04, compiler: {cc: gcc-10, cxx: g++-10}, reloc: 1, suite: dist-vlt-2}
|
||||
- {os: ubuntu-20.04, compiler: {cc: gcc-10, cxx: g++-10}, reloc: 1, suite: dist-vlt-3}
|
||||
- {os: ubuntu-20.04, compiler: {cc: gcc-10, cxx: g++-10}, reloc: 1, suite: vltmt-0}
|
||||
- {os: ubuntu-20.04, compiler: {cc: gcc-10, cxx: g++-10}, reloc: 1, suite: vltmt-1}
|
||||
# Ubuntu 24.04 only on GCC; not passing on clang yet
|
||||
- {os: ubuntu-24.04, compiler: {cc: gcc, cxx: g++}, suite: dist-vlt-0}
|
||||
- {os: ubuntu-24.04, compiler: {cc: gcc, cxx: g++}, suite: dist-vlt-1}
|
||||
- {os: ubuntu-24.04, compiler: {cc: gcc, cxx: g++}, suite: dist-vlt-2}
|
||||
- {os: ubuntu-24.04, compiler: {cc: gcc, cxx: g++}, suite: dist-vlt-3}
|
||||
- {os: ubuntu-24.04, compiler: {cc: gcc, cxx: g++}, suite: vltmt-0}
|
||||
- {os: ubuntu-24.04, compiler: {cc: gcc, cxx: g++}, 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: clang}
|
||||
|
||||
- name: Download tar archive
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: ${{ env.VERILATOR_ARCHIVE }}
|
||||
path: ${{ github.workspace }}
|
||||
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: Unpack tar archive
|
||||
working-directory: ${{ github.workspace }}
|
||||
run: tar -x -z -f ${{ env.VERILATOR_ARCHIVE }}
|
||||
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: 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 }}-
|
||||
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: Install test dependencies
|
||||
run: ./ci/ci-install.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}
|
||||
|
||||
- name: Test
|
||||
env:
|
||||
TESTS: ${{ matrix.suite }}
|
||||
run: ./ci/ci-script.bash
|
||||
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
|
||||
|
|
|
|||
|
|
@ -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 }}
|
||||
|
|
|
|||
|
|
@ -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 }}
|
||||
|
|
@ -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
|
||||
|
|
@ -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: '
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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.034
|
||||
VERSION 5.036
|
||||
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
|
||||
|
|
|
|||
117
Changes
117
Changes
|
|
@ -8,6 +8,87 @@ The changes in each Verilator version are described below. The
|
|||
contributors that suggested a given feature are shown in []. Thanks!
|
||||
|
||||
|
||||
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]
|
||||
* Fix invalid code motion over branches (#5811) (#5814). [Geza Lore]
|
||||
* Fix sorting of wide SenItems (#5816). [Geza Lore]
|
||||
* Fix tcmalloc static link and non-22.04 builds (#5817) (#5818). [Geza Lore]
|
||||
* Fix error on out-of-range lvalue part select (#5820).
|
||||
* Fix UNOPTFLAT warnings with `--coverage-trace` and always_comb (#5821).
|
||||
* Fix function locals in SenExprBuilder (#5822). [Geza Lore]
|
||||
* Fix type_id package scope resolution (#5826). [Krzysztof Bieganski, Antmicro Ltd.]
|
||||
* Fix `rand_mode` method with cast (#5831).
|
||||
* Fix invalidating variable caches in SenExprBulider (#5834) (#5835). [Geza Lore]
|
||||
* 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 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).
|
||||
* Fix recursive error on virtual interfaces (#5854). [Yilou Wang]
|
||||
* 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
|
||||
==========================
|
||||
|
||||
|
|
@ -195,7 +276,7 @@ Verilator 5.030 2024-10-27
|
|||
* Fix short-circuiting with associative array access (#5484). [Ethan Sifferman]
|
||||
* Fix short-circuiting on method calls (#5486). [Ethan Sifferman]
|
||||
* Fix exponential concatenate performance (#5488). [Arkadiusz Kozdra, Antmicro Ltd.]
|
||||
* Fix V3Table trying to generate 'x' bits in the lookup table. (#5491). [Geza Lore]
|
||||
* Fix V3Table trying to generate 'x' bits in the lookup table (#5491). [Geza Lore]
|
||||
* Fix randomize with foreach constraints (#5492). [Arkadiusz Kozdra, Antmicro Ltd.]
|
||||
* Fix explicit CMAKE_INSTALL_PREFIX usages (#5500). [Fabian Keßler]
|
||||
* Fix configure inserting absolute paths for Python and Perl (#5504) (#5505). [Nathan Graybeal]
|
||||
|
|
@ -253,7 +334,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]
|
||||
|
|
@ -280,7 +361,7 @@ Verilator 5.028 2024-08-21
|
|||
* Fix static variable initializers in procedures (#5296). [Bartłomiej Chmiel, Antmicro Ltd.]
|
||||
* Fix randomizing current object with `rand` class instance member (#5292). [Krzysztof Bieganski, Antmicro Ltd.]
|
||||
* Fix handling of rand fields not referenced in constraints (#5305). [Ryszard Rozak, Antmicro Ltd.]
|
||||
* Fix Python3 path discovery in make flows to avoid mixing system and user python interpreters (#5307) [Markus Krause]
|
||||
* Fix Python3 path discovery in make flows to avoid mixing system and user python interpreters (#5307). [Markus Krause]
|
||||
* Fix make flows to pass PYTHON3 (like PERL) (#5307) (#5308). [Markus Krause]
|
||||
* Fix assert on wide expression (#5319) (#5324). [Varun Koyyalagunta]
|
||||
* Fix output clock variable overwriting signal (#5320) (#5347). [Krzysztof Bieganski, Antmicro Ltd.]
|
||||
|
|
@ -459,7 +540,7 @@ Verilator 5.022 2024-02-24
|
|||
* Fix `vpi_get()` and `vpi_get64()` to return vpiUndefined on errors (#4795). [Marlon James]
|
||||
* Fix VPI parameter iteration (#4798). [Marlon James]
|
||||
* Fix delays using wrong timeunit when modules inlined (#4806). [Paul Wright]
|
||||
* Fix warnings in verilated_sc_trace.h for Clang. (#4807) (#4827). [Anthony Donlon]
|
||||
* Fix warnings in verilated_sc_trace.h for Clang (#4807) (#4827). [Anthony Donlon]
|
||||
* Fix null pointer dereference (#4810) (#4825). [Adrian Sampson]
|
||||
* Fix compilation error on multi-inherited interface class usage (#4819).
|
||||
* Fix maybe-uninitialized compiler warning (#4820) (#4822). [Larry Doolittle]
|
||||
|
|
@ -537,7 +618,7 @@ Verilator 5.020 2024-01-01
|
|||
* Fix conflicted namespace for coroutines (#4701) (#4707). [Jinyan Xu]
|
||||
* Fix compilers seeing empty input due to file system races (#4708). [Flavien Solt]
|
||||
* Fix shift of > 32-bit number (#4719). [Flavien Solt]
|
||||
* Fix Windows include gates in filesystem Flush implementation. (#4720). [William D. Jones]
|
||||
* Fix Windows include gates in filesystem Flush implementation (#4720). [William D. Jones]
|
||||
* Fix power operator with wide numbers and constants (#4721) (#4763). [Flavien Solt]
|
||||
* Fix parameter passing to ports (#4723). [Ryszard Rozak, Antmicro Ltd.]
|
||||
* Fix block names of nested do..while loops (#4728). [Ryszard Rozak, Antmicro Ltd.]
|
||||
|
|
@ -546,7 +627,7 @@ Verilator 5.020 2024-01-01
|
|||
* Fix $finish twice to no longer exit (#4757). [Tim Hutt]
|
||||
* Fix dynamic NBA conditions (#4773). [Krzysztof Bieganski, Antmicro Ltd.]
|
||||
* Fix `V3Fork` stage to run only if `--timing` is set (#4778). [Krzysztof Bieganski, Antmicro Ltd.]
|
||||
* Fix max multiply width and add runtime assertions if too small. (#4781)
|
||||
* Fix max multiply width and add runtime assertions if too small (#4781).
|
||||
* Fix select value too wide (#5148) (#5153). [Dercury]
|
||||
|
||||
|
||||
|
|
@ -1211,7 +1292,7 @@ Verilator 4.218 2022-01-17
|
|||
|
||||
* Support class static members (#2233).
|
||||
* Support force/release (#2431) (#2593). [Shunyao CAD]
|
||||
* Add 'forceable' attribute to allow forcing from C++. (#3272). [Geza Lore, Shunyao CAD]
|
||||
* Add 'forceable' attribute to allow forcing from C++ (#3272). [Geza Lore, Shunyao CAD]
|
||||
* Support lower dimension looping in foreach loops (#3172). [Ehab Ibrahim]
|
||||
* Support up to 64 bit enums for .next/.prev/.name (#3244). [Alexander Grobman]
|
||||
* Reduce .rodata footprint of trace initialization (#3250). [Geza Lore, Shunyao CAD]
|
||||
|
|
@ -1435,7 +1516,7 @@ Verilator 4.200 2021-03-12
|
|||
**Major:**
|
||||
|
||||
* Add simulation context (VerilatedContext) to allow multiple fully independent
|
||||
models to be in the same process. Please see the updated examples. (#2660)
|
||||
models to be in the same process. Please see the updated examples (#2660).
|
||||
* Add context->time() and context->timeInc() API calls, to set simulation time.
|
||||
These now are recommended in place of the legacy sc_time_stamp().
|
||||
|
||||
|
|
@ -1446,7 +1527,7 @@ Verilator 4.200 2021-03-12
|
|||
* Fix slice-assign overflow (#2803) (#2811). [David Turner]
|
||||
* Fix interface array connection ordering broken in v4.110 (#2827). [Don Owen]
|
||||
* Fix or-reduction on different scopes broken in 4.110 (#2828). [Yinan Xu]
|
||||
* Fix MSVC++ compile error. (#2831) (#2833) [Drew Taussig]
|
||||
* Fix MSVC++ compile error (#2831) (#2833). [Drew Taussig]
|
||||
|
||||
|
||||
Verilator 4.110 2021-02-25
|
||||
|
|
@ -1501,7 +1582,7 @@ Verilator 4.108 2021-01-10
|
|||
* Fix vpiLeftRange on little-endian memories (#2696). [Marlon James]
|
||||
* Fix VPI module tree (#2704). [Todd Strader]
|
||||
* Fix vpi_release_handle to be called implicitly per IEEE (#2706).
|
||||
* Fix to allow inheriting 'VerilatedVcdFile' class. (#2720) [HyungKi Jeong]
|
||||
* Fix to allow inheriting 'VerilatedVcdFile' class (#2720). [HyungKi Jeong]
|
||||
* Fix $urandom_range maximum value (#2723). [Nandu Raj]
|
||||
* Fix tracing empty sc module (#2729).
|
||||
* Fix generate for unrolling to be signed (#2730). [yanx21]
|
||||
|
|
@ -1607,11 +1688,11 @@ Verilator 4.040 2020-08-15
|
|||
**Minor:**
|
||||
|
||||
* Fix arrayed interfaces, broke in 4.038 (#2468). [Josh Redford]
|
||||
* Support $stable, $rose and $fell. (#2148) (#2501) [Peter Monsson]
|
||||
* Support $stable, $rose and $fell (#2148) (#2501). [Peter Monsson]
|
||||
* Support simple function localparams (#2461). [James Hanlon]
|
||||
* Miscellaneous parsing error changes towards UVM support.
|
||||
* Fix arrayed interfaces (#2469). [Josh Redford]
|
||||
* Fix protect lib VCS warning. (#2479) [Julien Margetts]
|
||||
* Fix protect lib VCS warning (#2479). [Julien Margetts]
|
||||
* Fix combining different-width parameters (#2484). [abirkmanis]
|
||||
* Fix protect-lib without sequential logic (#2492). [Yutetsu TAKATSUKASA]
|
||||
* Fix V3Unknown from running with flat XML output (#2494). [James Hanlon]
|
||||
|
|
@ -1667,16 +1748,16 @@ Verilator 4.036 2020-06-06
|
|||
waivers to the warnings emitted during a Verilator run.
|
||||
* Support verilator_coverage --write-info for lcov HTML reports.
|
||||
* Line Coverage now tracks all statement lines, not just branch lines.
|
||||
* The run-time library is now compiled with -Os by default. (#2369, #2373)
|
||||
* The run-time library is now compiled with -Os by default (#2369, #2373).
|
||||
* Support multi channel descriptor I/O (#2190) [Stephen Henry]
|
||||
* Support $countbits. (#2287) [Yossi Nivin]
|
||||
* Support $isunbounded and parameter $. (#2104)
|
||||
* Support $countbits (#2287). [Yossi Nivin]
|
||||
* Support $isunbounded and parameter $ (#2104).
|
||||
* Support unpacked array .sum and .product.
|
||||
* Support prefix/postfix increment/decrement. (#2223) [Maciej Sobkowski]
|
||||
* Support prefix/postfix increment/decrement (#2223). [Maciej Sobkowski]
|
||||
* Fix FST tracing of little bit endian signals. [Geza Lore]
|
||||
* Fix +: and -: on unpacked arrays. (#2304) [engr248]
|
||||
* Fix +: and -: on unpacked arrays (#2304). [engr248]
|
||||
* Fix $isunknown with constant Z's.
|
||||
* Fix queues and dynamic array wide ops. (#2352) [Vassilis Papaefstathiou]
|
||||
* Fix queues and dynamic array wide ops (#2352). [Vassilis Papaefstathiou]
|
||||
|
||||
|
||||
Verilator 4.034 2020-05-03
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
.. Github doesn't render images unless absolute URL
|
||||
.. Do not know of a conditional tag, "only: github" nor "github display" works
|
||||
|
||||
|badge1| |badge2| |badge3| |badge4| |badge5| |badge6| |badge7|
|
||||
|badge1| |badge2| |badge3| |badge4| |badge5| |badge7|
|
||||
|
||||
.. |badge1| image:: https://img.shields.io/badge/Website-Verilator.org-181717.svg
|
||||
:target: https://verilator.org
|
||||
|
|
@ -13,8 +13,6 @@
|
|||
:target: https://repology.org/project/verilator/versions
|
||||
.. |badge5| image:: https://img.shields.io/docker/pulls/verilator/verilator
|
||||
:target: https://hub.docker.com/r/verilator/verilator
|
||||
.. |badge6| image:: https://api.codacy.com/project/badge/Grade/fa78caa433c84a4ab9049c43e9debc6f
|
||||
:target: https://www.codacy.com/gh/verilator/verilator
|
||||
.. |badge7| image:: https://github.com/verilator/verilator/workflows/build/badge.svg
|
||||
:target: https://github.com/verilator/verilator/actions?query=workflow%3Abuild
|
||||
|
||||
|
|
@ -134,7 +132,7 @@ Related Projects
|
|||
- `GTKwave <http://gtkwave.sourceforge.net/>`_ - Waveform viewer for
|
||||
Verilator traces.
|
||||
|
||||
- `Icarus Verilog`_ - Icarus is a full-featured interpreted Verilog
|
||||
- `Icarus Verilog`_ - Icarus is a highly-featured interpreted Verilog
|
||||
simulator. If Verilator does not support your needs, perhaps Icarus may.
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -256,7 +256,7 @@ sub sh_escape {
|
|||
# This is similar to quotemeta() but less aggressive.
|
||||
# There's no need to escape hyphens, periods, or forward slashes
|
||||
# for the shell as these have no special meaning to the shell.
|
||||
$arg =~ s/([^0-9a-zA-Z_\-\+\=\.\/])/\\$1/g;
|
||||
$arg =~ s/([^0-9a-zA-Z_\-\+\=\.\/:])/\\$1/g;
|
||||
return $arg;
|
||||
}
|
||||
|
||||
|
|
@ -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,23 +467,25 @@ 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
|
||||
--trace-max-array <depth> Maximum array depth for tracing
|
||||
--trace-max-width <width> Maximum bit width for tracing
|
||||
--trace-params Enable tracing of parameters
|
||||
--trace-saif Enable SAIF file creation
|
||||
--trace-structs Enable tracing structure names
|
||||
--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
|
||||
|
|
@ -492,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
|
||||
|
|
@ -526,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
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ fi
|
|||
install-vcddiff() {
|
||||
TMP_DIR="$(mktemp -d)"
|
||||
git clone https://github.com/veripool/vcddiff "$TMP_DIR"
|
||||
git -C "${TMP_DIR}" checkout e5664be5fe39d353bf3fcb50aa05214ab7ed4ac4
|
||||
git -C "${TMP_DIR}" checkout dca845020668887fd13498c772939814d9264fd5
|
||||
"$MAKE" -C "${TMP_DIR}"
|
||||
sudo cp "${TMP_DIR}/vcddiff" /usr/local/bin
|
||||
}
|
||||
|
|
@ -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-20.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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -98,6 +98,8 @@ elif [ "$CI_BUILD_STAGE_NAME" = "test" ]; then
|
|||
export VERILATOR_ROOT="$RELOC_DIR/relocated-install/share/verilator"
|
||||
TEST_REGRESS="$RELOC_DIR/test_regress"
|
||||
mv test_regress "$TEST_REGRESS"
|
||||
NODIST="$RELOC_DIR/nodist"
|
||||
mv nodist "$NODIST"
|
||||
# Feeling brave?
|
||||
find . -delete
|
||||
ls -la .
|
||||
|
|
@ -107,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-
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
# Then 'make maintainer-dist'
|
||||
#AC_INIT([Verilator],[#.### YYYY-MM-DD])
|
||||
#AC_INIT([Verilator],[#.### devel])
|
||||
AC_INIT([Verilator],[5.034 2025-02-24],
|
||||
AC_INIT([Verilator],[5.036 2025-04-27],
|
||||
[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],
|
||||
|
|
@ -515,7 +517,7 @@ if test "$CFG_ENABLE_PARTIAL_STATIC" = "yes"; then
|
|||
_MY_LDLIBS_CHECK_OPT(CFG_LDFLAGS_SRC, -static-libgcc)
|
||||
_MY_LDLIBS_CHECK_OPT(CFG_LDFLAGS_SRC, -static-libstdc++)
|
||||
_MY_LDLIBS_CHECK_OPT(CFG_LDFLAGS_SRC, -Xlinker -gc-sections)
|
||||
LTCMALLOC=-l:libtcmalloc_minimal.a
|
||||
LTCMALLOC="-Wl,--whole-archive -l:libtcmalloc_minimal.a -Wl,--no-whole-archive"
|
||||
else
|
||||
LTCMALLOC=-ltcmalloc_minimal
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -19,12 +19,14 @@ Andreas Kuster
|
|||
Andrei Kostovski
|
||||
Andrew Miloradovsky
|
||||
Andrew Nolte
|
||||
Andrew Voznytsa
|
||||
Anthony Donlon
|
||||
Anthony Moore
|
||||
Arkadiusz Kozdra
|
||||
Arthur Rosa
|
||||
Aylon Chaim Porat
|
||||
Bartłomiej Chmiel
|
||||
Brian Li
|
||||
Cameron Kirk
|
||||
Chih-Mao Chen
|
||||
Chris Bachhuber
|
||||
|
|
@ -65,6 +67,7 @@ Garrett Smith
|
|||
Geza Lore
|
||||
Gianfranco Costamagna
|
||||
Gijs Burghoorn
|
||||
Gilberto Abram
|
||||
Glen Gibb
|
||||
Gökçe Aydos
|
||||
Graham Rushton
|
||||
|
|
@ -107,6 +110,7 @@ Jiuyang Liu
|
|||
Joey Liu
|
||||
John Coiner
|
||||
John Demme
|
||||
John Khoo
|
||||
John Wehle
|
||||
Jonathan Drolet
|
||||
Jonathan Schröter
|
||||
|
|
@ -132,6 +136,7 @@ Krzysztof Boronski
|
|||
Krzysztof Boroński
|
||||
Krzysztof Obłonczek
|
||||
Krzysztof Starecki
|
||||
Krzysztof Sychla
|
||||
Kuba Ober
|
||||
Larry Doolittle
|
||||
Liam Braun
|
||||
|
|
@ -148,6 +153,7 @@ Marlon James
|
|||
Marshal Qiao
|
||||
Martin Schmidt
|
||||
Martin Stadler
|
||||
Mateusz Gancarz
|
||||
Matthew Ballance
|
||||
Michael Bikovitsky
|
||||
Michael Killough
|
||||
|
|
@ -191,6 +197,7 @@ Ricardo Barbedo
|
|||
Richard Myers
|
||||
Risto Pejašinović
|
||||
Robert Balas
|
||||
Robin Heinemann
|
||||
Rupert Swarbrick
|
||||
Ryan Ziegler
|
||||
Ryszard Rozak
|
||||
|
|
@ -243,6 +250,8 @@ Yutetsu TAKATSUKASA
|
|||
Yves Mathieu
|
||||
Zhanglei Wang
|
||||
Zhou Shen
|
||||
Zhouyi Shen
|
||||
Zixi Li
|
||||
أحمد المحمودي
|
||||
404allen404
|
||||
Tobias Jensen
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -72,13 +72,17 @@ 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.
|
||||
|
||||
Please refer to the `README
|
||||
<https://github.com/antmicro/sv-bugpoint/blob/main/README.md>`_ file for more
|
||||
With :vlopt:`--debug`, Verilator will write a *{prefix}*\ __inputs\ .vpp
|
||||
file which has all of the individual input files combined and
|
||||
pre-processed, this is often useful as the input design into `sv-bugpoint`.
|
||||
|
||||
Please refer to `sv-bugpoint README
|
||||
<https://github.com/antmicro/sv-bugpoint/blob/main/README.md>`_ for more
|
||||
information on how to use `sv-bugpoint`.
|
||||
|
||||
.. Contributing
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
.. Copyright 2003-2025 by Wilson Snyder.
|
||||
.. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
verilator Arguments
|
||||
===================
|
||||
=====================
|
||||
verilator Arguments
|
||||
=====================
|
||||
|
||||
The following arguments may be passed to the "verilator" executable.
|
||||
|
||||
|
|
@ -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>
|
||||
|
|
@ -146,13 +147,16 @@ Summary:
|
|||
|
||||
This option was named `--bin` before version 4.228.
|
||||
|
||||
.. option:: --build-jobs [<value>]
|
||||
.. option:: --build-jobs <value>
|
||||
|
||||
Specify the level of parallelism for :vlopt:`--build`. If zero, uses the
|
||||
number of threads in the current hardware. Otherwise, the <value> must
|
||||
be a positive integer specifying the maximum number of parallel build
|
||||
jobs.
|
||||
|
||||
If not provided, and :vlopt:`-j` is provided, the :vlopt:`-j` value is
|
||||
used.
|
||||
|
||||
This forms the :command:`make` option ``-j`` value, unless the
|
||||
:option:`MAKEFLAGS` environment variable contains ``-jobserver-auth``,
|
||||
in which case Verilator assumes that make's jobserver is being used.
|
||||
|
|
@ -328,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.
|
||||
|
|
@ -359,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
|
||||
|
|
@ -399,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
|
||||
|
|
@ -430,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
|
||||
|
|
@ -451,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>
|
||||
|
||||
|
|
@ -476,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++
|
||||
|
|
@ -566,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
|
||||
|
|
@ -589,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
|
||||
|
|
@ -641,6 +641,11 @@ Summary:
|
|||
are typically used only when recommended by a maintainer to help debug
|
||||
or work around an issue.
|
||||
|
||||
.. option:: -fno-var-split
|
||||
|
||||
Do not attempt to split variables automatically. Variables explicitly
|
||||
annotated with :option:`/*verilator&32;split_var*/` are still split.
|
||||
|
||||
.. option:: -future0 <option>
|
||||
|
||||
Rarely needed. Suppress an unknown Verilator option for an option that
|
||||
|
|
@ -716,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
|
||||
|
|
@ -733,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.
|
||||
|
|
@ -788,9 +793,21 @@ Summary:
|
|||
|
||||
Specify the level of parallelism for :vlopt:`--build` if
|
||||
:vlopt:`--build-jobs` isn't provided, and the internal compilation steps
|
||||
of Verilator if :vlopt:`--verilate-jobs` isn't provided. If zero, uses
|
||||
the number of threads in the current hardware. Otherwise, must be a
|
||||
positive integer specifying the maximum number of parallel build jobs.
|
||||
of Verilator if :vlopt:`--verilate-jobs` isn't provided. Also sets
|
||||
:vlopt:`--output-groups` if isn't provided.
|
||||
|
||||
If zero, uses the number of threads in the current hardware. Otherwise,
|
||||
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
|
||||
|
||||
|
|
@ -815,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
|
||||
|
|
@ -897,28 +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 and ``cmake`` for CMake.
|
||||
Both 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,
|
||||
|
|
@ -944,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
|
||||
|
|
@ -978,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.
|
||||
|
|
@ -998,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).
|
||||
|
|
@ -1016,18 +1026,24 @@ Summary:
|
|||
.. option:: --output-groups <numfiles>
|
||||
|
||||
Enables concatenating the output .cpp files into the given number of
|
||||
effective output .cpp files. This is useful if the compiler startup
|
||||
overhead from compiling many small files becomes unacceptable,
|
||||
which can happen in designs making extensive use of SystemVerilog classes,
|
||||
templates or generate blocks.
|
||||
effective output .cpp files. This minimizes the compiler startup
|
||||
overhead from compiling many small files, which can happen in designs
|
||||
making extensive use of SystemVerilog classes, templates or generate
|
||||
blocks.
|
||||
|
||||
Using :vlopt:`--output-groups` can adversely impact caching and stability
|
||||
(as in reproducibility) of compiled code. Compilation of larger .cpp
|
||||
files also has higher memory requirements. Too low values might result in
|
||||
swap thrashing with large designs, high values give no benefits. The
|
||||
value should range from 2 to 20 for small to medium designs.
|
||||
swap thrashing with large designs, high values give no benefits.
|
||||
|
||||
Default is zero, which disables this feature.
|
||||
Typically setting the number of files to the hardware thread count,
|
||||
corresponding to number of compiler jobs that can run in parallel, will
|
||||
lead to fastest build times. (e.g. for small to medium designs the value
|
||||
should range from 2 to 20.)
|
||||
|
||||
Zero disables this feature. Negative one, the default, sets the groups
|
||||
to the value from :vlopt:`--build-jobs`, or from :vlopt:`-j`, or zero in
|
||||
that priority.
|
||||
|
||||
.. option:: --output-split <statements>
|
||||
|
||||
|
|
@ -1088,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
|
||||
|
|
@ -1099,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
|
||||
|
|
@ -1468,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.
|
||||
|
|
@ -1520,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".
|
||||
|
||||
|
|
@ -1555,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
|
||||
|
|
@ -1614,6 +1619,12 @@ Summary:
|
|||
|
||||
Disable tracing of parameters.
|
||||
|
||||
.. option:: --trace-saif
|
||||
|
||||
Enable SAIF tracing in the model. This overrides :vlopt:`--trace`.
|
||||
Specification of this format can be found in `IEEE 1801-2018
|
||||
<https://ieeexplore.ieee.org/document/8686430>`_ (see Annex I).
|
||||
|
||||
.. option:: --trace-structs
|
||||
|
||||
Enable tracing to show the name of packed structure, union, and packed
|
||||
|
|
@ -1648,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.
|
||||
|
|
@ -1700,13 +1729,16 @@ Summary:
|
|||
execute only the build. This can be useful for rebuilding the Verilated code
|
||||
produced by a previous invocation of Verilator.
|
||||
|
||||
.. option:: --verilate-jobs [<value>]
|
||||
.. option:: --verilate-jobs <value>
|
||||
|
||||
Specify the level of parallelism for the internal compilation steps of
|
||||
Verilator. If zero, uses the number of threads in the current hardware.
|
||||
Otherwise, must be a positive integer specifying the maximum number of
|
||||
parallel build jobs.
|
||||
|
||||
If not provided, and :vlopt:`-j` is provided, the :vlopt:`-j` value is
|
||||
used.
|
||||
|
||||
See also :vlopt:`-j`.
|
||||
|
||||
.. option:: +verilog1995ext+<ext>
|
||||
|
|
@ -1852,33 +1884,36 @@ Summary:
|
|||
``-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::
|
||||
|
||||
|
|
@ -1888,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
|
||||
|
|
@ -1986,8 +2017,9 @@ Summary:
|
|||
|
||||
.. _Configuration Files:
|
||||
|
||||
Configuration Files
|
||||
===================
|
||||
=====================
|
||||
Configuration Files
|
||||
=====================
|
||||
|
||||
In addition to the command line, warnings and other features for the
|
||||
:command:`verilator` command may be controlled with configuration files,
|
||||
|
|
@ -2020,15 +2052,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).
|
||||
|
|
@ -2040,30 +2063,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
|
||||
|
|
@ -2074,11 +2109,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.
|
||||
|
|
@ -2096,20 +2128,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>"
|
||||
|
||||
|
|
@ -2117,10 +2156,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
|
||||
|
|
@ -2129,12 +2168,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).
|
||||
|
|
@ -2165,18 +2214,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>
|
||||
|
||||
|
|
@ -2191,18 +2235,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
|
||||
|
|
@ -2211,20 +2268,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
|
||||
|
|
@ -2234,14 +2291,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.
|
||||
|
||||
|
|
|
|||
|
|
@ -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`.
|
||||
|
|
|
|||
|
|
@ -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".
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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:`Configuration Files`.
|
||||
|
||||
.. option:: `error [string]
|
||||
|
||||
This will report an error when the preprocessor emits it, similar to
|
||||
|
|
@ -33,10 +44,116 @@ 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:`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 +203,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 +223,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 +247,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 +417,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 +441,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 +514,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 +524,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 +539,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
|
||||
|
|
@ -550,6 +588,20 @@ or "`ifdef`"'s may break other tools.
|
|||
large arrays may slow down the Verilation speed, so use this only on
|
||||
variables that require it.
|
||||
|
||||
Packed variables that are only referenced locally (without hierarchical
|
||||
references) via non-overlapping, constant-indexed bit or part select
|
||||
expressions are split automatically. This covers the somewhat common
|
||||
usage pattern:
|
||||
|
||||
.. code-block:: sv
|
||||
|
||||
logic [1:0][31:0] tmp;
|
||||
|
||||
assign tmp[0] = foo + a;
|
||||
assign tmp[1] = tmp[1] + b;
|
||||
assign bar = tmp[1] + c;
|
||||
|
||||
|
||||
Same as :option:`split_var` configuration file option.
|
||||
|
||||
.. option:: /*verilator&32;tag <text...>*/
|
||||
|
|
@ -583,7 +635,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*/
|
||||
|
||||
|
|
@ -613,13 +665,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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
||||
|
|
@ -146,7 +158,7 @@ Those developing Verilator itself may also want these (see internals.rst):
|
|||
.. code-block:: shell
|
||||
|
||||
sudo apt-get install clang clang-format-14 cmake gdb gprof graphviz lcov
|
||||
sudo apt-get install python3-clang yapf3 bear jq
|
||||
sudo apt-get install python3-clang python3-distro yapf3 bear jq
|
||||
sudo pip3 install sphinx sphinx_rtd_theme sphinxcontrib-spelling breathe ruff
|
||||
sudo pip3 install git+https://github.com/antmicro/astsee.git
|
||||
cpan install Pod::Perldoc
|
||||
|
|
@ -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
|
||||
^^^^^^^^^^
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
@ -451,17 +452,17 @@ disable
|
|||
force, release
|
||||
Verilator supports the procedural `force` (and corresponding `release`)
|
||||
statement. However, the behavior of the `force` statement does not
|
||||
entirely comply with IEEE 1800. According to the standard, when a
|
||||
procedural statement of the form `force a = b;` is executed, the
|
||||
simulation should behave as if, from that point forwards, a continuous
|
||||
assignment `assign a = b;` has been added to override the drivers of `a`.
|
||||
More specifically: the value of `a` should be updated whenever the value
|
||||
of `b` changes, until a `release a;` statement is executed. Verilator
|
||||
instead evaluates the current value of `b` when the `force` statement is
|
||||
executed, and forces `a` to that value, without updating it until a new
|
||||
`force` or `release` statement is encountered that applies to `a`. This
|
||||
non-standard behavior is nevertheless consistent with some other
|
||||
simulators.
|
||||
entirely comply with IEEE 1800-2023:
|
||||
|
||||
#. Using forced variable as a value to another force statement is
|
||||
currently not supported. The dependent force statement is forced by an
|
||||
initial constant value.
|
||||
|
||||
#. Force/release with procedural continuous assignment is not supported.
|
||||
The assignment is treated as procedural.
|
||||
|
||||
#. Expressions using multiple variable references or function calls on
|
||||
forced right-hand side are not sensitive to dependency changes.
|
||||
|
||||
inside
|
||||
Inside expressions may not include unpacked array traversal or $ as an
|
||||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,14 +454,27 @@ 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
|
||||
|
||||
Optional. Enables FST tracing if present, equivalent to "VERILATOR_ARGS
|
||||
--trace-fst".
|
||||
|
||||
.. describe:: TRACE_SAIF
|
||||
|
||||
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`
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
||||
|
|
@ -86,6 +86,8 @@ List Of Warnings
|
|||
Limitations`.
|
||||
|
||||
|
||||
.. t_dist_docs_style restart_sort
|
||||
|
||||
.. option:: ALWCOMBORDER
|
||||
|
||||
.. TODO better example
|
||||
|
|
@ -472,6 +474,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 +1249,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 +1257,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 +1288,7 @@ List Of Warnings
|
|||
Ignoring this warning will only suppress the lint check; it will
|
||||
simulate correctly.
|
||||
|
||||
|
||||
.. option:: PINCONNECTEMPTY
|
||||
|
||||
.. TODO better example
|
||||
|
|
@ -1349,6 +1377,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 +1420,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
|
||||
|
|
@ -2181,21 +2209,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 +2234,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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
@ -2077,7 +2082,10 @@ driver.py Non-Scenario Arguments
|
|||
|
||||
--j #
|
||||
Run number of parallel tests, or 0 to determine the count based on the
|
||||
number of cores installed. Requires Perl's Parallel::Forker package.
|
||||
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
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ Asciidoc
|
|||
Ashutosh
|
||||
Ast
|
||||
Atmel
|
||||
Augustin
|
||||
Aurelien
|
||||
Badáň
|
||||
Bagri
|
||||
|
|
@ -109,6 +110,7 @@ Embecosm
|
|||
Engstrom
|
||||
Enzo
|
||||
Eugen
|
||||
Fabre
|
||||
Fabrizio
|
||||
Faucher
|
||||
Faure
|
||||
|
|
@ -650,6 +652,7 @@ elike
|
|||
elsif
|
||||
endcase
|
||||
endcelldefine
|
||||
endclass
|
||||
endfunction
|
||||
endgenerate
|
||||
endian
|
||||
|
|
@ -860,6 +863,7 @@ noprivate
|
|||
noreturn
|
||||
notif
|
||||
nullptr
|
||||
numactl
|
||||
onehot
|
||||
ooo
|
||||
oprofile
|
||||
|
|
@ -960,6 +964,7 @@ runtime
|
|||
runtimes
|
||||
rw
|
||||
sVerilator
|
||||
saif
|
||||
sawatzke
|
||||
sc
|
||||
scalared
|
||||
|
|
@ -1018,6 +1023,7 @@ swrite
|
|||
synthesizeable
|
||||
sys
|
||||
systemc
|
||||
tcmalloc
|
||||
tenghtt
|
||||
testbench
|
||||
threadsafe
|
||||
|
|
@ -1093,7 +1099,9 @@ verilator
|
|||
verilog
|
||||
verilogmod
|
||||
verimake
|
||||
veriuser
|
||||
vl
|
||||
vlSelf
|
||||
vlopt
|
||||
vlt
|
||||
vltstd
|
||||
|
|
@ -1113,6 +1121,7 @@ vpiUndefined
|
|||
vpm
|
||||
vpp
|
||||
warmup
|
||||
wavealloca
|
||||
waveforms
|
||||
whitespace
|
||||
widthed
|
||||
|
|
|
|||
|
|
@ -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
|
||||
######################################################################
|
||||
|
|
|
|||
|
|
@ -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
|
||||
######################################################################
|
||||
|
|
|
|||
|
|
@ -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
|
||||
######################################################################
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 ----------------"
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 ----------------"
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
10219
include/gtkwave/fstapi.c
10219
include/gtkwave/fstapi.c
File diff suppressed because it is too large
Load Diff
|
|
@ -26,7 +26,8 @@
|
|||
#define FST_API_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
|
@ -36,428 +37,508 @@ extern "C" {
|
|||
#include <zlib.h>
|
||||
#include <inttypes.h>
|
||||
#if defined(_MSC_VER)
|
||||
#include "fst_win_unistd.h"
|
||||
#include "fst_win_unistd.h"
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <time.h>
|
||||
|
||||
#define FST_RDLOAD "FSTLOAD | "
|
||||
|
||||
typedef uint32_t fstHandle;
|
||||
typedef uint32_t fstEnumHandle;
|
||||
|
||||
enum fstWriterPackType {
|
||||
FST_WR_PT_ZLIB = 0,
|
||||
FST_WR_PT_FASTLZ = 1,
|
||||
FST_WR_PT_LZ4 = 2
|
||||
enum fstWriterPackType
|
||||
{
|
||||
FST_WR_PT_ZLIB = 0,
|
||||
FST_WR_PT_FASTLZ = 1,
|
||||
FST_WR_PT_LZ4 = 2
|
||||
};
|
||||
|
||||
enum fstFileType {
|
||||
FST_FT_MIN = 0,
|
||||
enum fstFileType
|
||||
{
|
||||
FST_FT_MIN = 0,
|
||||
|
||||
FST_FT_VERILOG = 0,
|
||||
FST_FT_VHDL = 1,
|
||||
FST_FT_VERILOG_VHDL = 2,
|
||||
FST_FT_VERILOG = 0,
|
||||
FST_FT_VHDL = 1,
|
||||
FST_FT_VERILOG_VHDL = 2,
|
||||
|
||||
FST_FT_MAX = 2
|
||||
FST_FT_MAX = 2
|
||||
};
|
||||
|
||||
enum fstBlockType {
|
||||
FST_BL_HDR = 0,
|
||||
FST_BL_VCDATA = 1,
|
||||
FST_BL_BLACKOUT = 2,
|
||||
FST_BL_GEOM = 3,
|
||||
FST_BL_HIER = 4,
|
||||
FST_BL_VCDATA_DYN_ALIAS = 5,
|
||||
FST_BL_HIER_LZ4 = 6,
|
||||
FST_BL_HIER_LZ4DUO = 7,
|
||||
FST_BL_VCDATA_DYN_ALIAS2 = 8,
|
||||
enum fstBlockType
|
||||
{
|
||||
FST_BL_HDR = 0,
|
||||
FST_BL_VCDATA = 1,
|
||||
FST_BL_BLACKOUT = 2,
|
||||
FST_BL_GEOM = 3,
|
||||
FST_BL_HIER = 4,
|
||||
FST_BL_VCDATA_DYN_ALIAS = 5,
|
||||
FST_BL_HIER_LZ4 = 6,
|
||||
FST_BL_HIER_LZ4DUO = 7,
|
||||
FST_BL_VCDATA_DYN_ALIAS2 = 8,
|
||||
|
||||
FST_BL_ZWRAPPER = 254, /* indicates that whole trace is gz wrapped */
|
||||
FST_BL_SKIP = 255 /* used while block is being written */
|
||||
FST_BL_ZWRAPPER = 254, /* indicates that whole trace is gz wrapped */
|
||||
FST_BL_SKIP = 255 /* used while block is being written */
|
||||
};
|
||||
|
||||
enum fstScopeType {
|
||||
FST_ST_MIN = 0,
|
||||
enum fstScopeType
|
||||
{
|
||||
FST_ST_MIN = 0,
|
||||
|
||||
FST_ST_VCD_MODULE = 0,
|
||||
FST_ST_VCD_TASK = 1,
|
||||
FST_ST_VCD_FUNCTION = 2,
|
||||
FST_ST_VCD_BEGIN = 3,
|
||||
FST_ST_VCD_FORK = 4,
|
||||
FST_ST_VCD_GENERATE = 5,
|
||||
FST_ST_VCD_STRUCT = 6,
|
||||
FST_ST_VCD_UNION = 7,
|
||||
FST_ST_VCD_CLASS = 8,
|
||||
FST_ST_VCD_INTERFACE = 9,
|
||||
FST_ST_VCD_PACKAGE = 10,
|
||||
FST_ST_VCD_PROGRAM = 11,
|
||||
FST_ST_VCD_MODULE = 0,
|
||||
FST_ST_VCD_TASK = 1,
|
||||
FST_ST_VCD_FUNCTION = 2,
|
||||
FST_ST_VCD_BEGIN = 3,
|
||||
FST_ST_VCD_FORK = 4,
|
||||
FST_ST_VCD_GENERATE = 5,
|
||||
FST_ST_VCD_STRUCT = 6,
|
||||
FST_ST_VCD_UNION = 7,
|
||||
FST_ST_VCD_CLASS = 8,
|
||||
FST_ST_VCD_INTERFACE = 9,
|
||||
FST_ST_VCD_PACKAGE = 10,
|
||||
FST_ST_VCD_PROGRAM = 11,
|
||||
|
||||
FST_ST_VHDL_ARCHITECTURE = 12,
|
||||
FST_ST_VHDL_PROCEDURE = 13,
|
||||
FST_ST_VHDL_FUNCTION = 14,
|
||||
FST_ST_VHDL_RECORD = 15,
|
||||
FST_ST_VHDL_PROCESS = 16,
|
||||
FST_ST_VHDL_BLOCK = 17,
|
||||
FST_ST_VHDL_FOR_GENERATE = 18,
|
||||
FST_ST_VHDL_IF_GENERATE = 19,
|
||||
FST_ST_VHDL_GENERATE = 20,
|
||||
FST_ST_VHDL_PACKAGE = 21,
|
||||
FST_ST_VHDL_ARCHITECTURE = 12,
|
||||
FST_ST_VHDL_PROCEDURE = 13,
|
||||
FST_ST_VHDL_FUNCTION = 14,
|
||||
FST_ST_VHDL_RECORD = 15,
|
||||
FST_ST_VHDL_PROCESS = 16,
|
||||
FST_ST_VHDL_BLOCK = 17,
|
||||
FST_ST_VHDL_FOR_GENERATE = 18,
|
||||
FST_ST_VHDL_IF_GENERATE = 19,
|
||||
FST_ST_VHDL_GENERATE = 20,
|
||||
FST_ST_VHDL_PACKAGE = 21,
|
||||
|
||||
FST_ST_MAX = 21,
|
||||
FST_ST_MAX = 21,
|
||||
|
||||
FST_ST_GEN_ATTRBEGIN = 252,
|
||||
FST_ST_GEN_ATTREND = 253,
|
||||
FST_ST_GEN_ATTRBEGIN = 252,
|
||||
FST_ST_GEN_ATTREND = 253,
|
||||
|
||||
FST_ST_VCD_SCOPE = 254,
|
||||
FST_ST_VCD_UPSCOPE = 255
|
||||
FST_ST_VCD_SCOPE = 254,
|
||||
FST_ST_VCD_UPSCOPE = 255
|
||||
};
|
||||
|
||||
enum fstVarType {
|
||||
FST_VT_MIN = 0, /* start of vartypes */
|
||||
enum fstVarType
|
||||
{
|
||||
FST_VT_MIN = 0, /* start of vartypes */
|
||||
|
||||
FST_VT_VCD_EVENT = 0,
|
||||
FST_VT_VCD_INTEGER = 1,
|
||||
FST_VT_VCD_PARAMETER = 2,
|
||||
FST_VT_VCD_REAL = 3,
|
||||
FST_VT_VCD_REAL_PARAMETER = 4,
|
||||
FST_VT_VCD_REG = 5,
|
||||
FST_VT_VCD_SUPPLY0 = 6,
|
||||
FST_VT_VCD_SUPPLY1 = 7,
|
||||
FST_VT_VCD_TIME = 8,
|
||||
FST_VT_VCD_TRI = 9,
|
||||
FST_VT_VCD_TRIAND = 10,
|
||||
FST_VT_VCD_TRIOR = 11,
|
||||
FST_VT_VCD_TRIREG = 12,
|
||||
FST_VT_VCD_TRI0 = 13,
|
||||
FST_VT_VCD_TRI1 = 14,
|
||||
FST_VT_VCD_WAND = 15,
|
||||
FST_VT_VCD_WIRE = 16,
|
||||
FST_VT_VCD_WOR = 17,
|
||||
FST_VT_VCD_PORT = 18,
|
||||
FST_VT_VCD_SPARRAY = 19, /* used to define the rownum (index) port for a sparse array */
|
||||
FST_VT_VCD_REALTIME = 20,
|
||||
FST_VT_VCD_EVENT = 0,
|
||||
FST_VT_VCD_INTEGER = 1,
|
||||
FST_VT_VCD_PARAMETER = 2,
|
||||
FST_VT_VCD_REAL = 3,
|
||||
FST_VT_VCD_REAL_PARAMETER = 4,
|
||||
FST_VT_VCD_REG = 5,
|
||||
FST_VT_VCD_SUPPLY0 = 6,
|
||||
FST_VT_VCD_SUPPLY1 = 7,
|
||||
FST_VT_VCD_TIME = 8,
|
||||
FST_VT_VCD_TRI = 9,
|
||||
FST_VT_VCD_TRIAND = 10,
|
||||
FST_VT_VCD_TRIOR = 11,
|
||||
FST_VT_VCD_TRIREG = 12,
|
||||
FST_VT_VCD_TRI0 = 13,
|
||||
FST_VT_VCD_TRI1 = 14,
|
||||
FST_VT_VCD_WAND = 15,
|
||||
FST_VT_VCD_WIRE = 16,
|
||||
FST_VT_VCD_WOR = 17,
|
||||
FST_VT_VCD_PORT = 18,
|
||||
FST_VT_VCD_SPARRAY = 19, /* used to define the rownum (index) port for a sparse array */
|
||||
FST_VT_VCD_REALTIME = 20,
|
||||
|
||||
FST_VT_GEN_STRING = 21, /* generic string type (max len is defined dynamically via fstWriterEmitVariableLengthValueChange) */
|
||||
FST_VT_GEN_STRING = 21, /* generic string type (max len is defined dynamically via
|
||||
fstWriterEmitVariableLengthValueChange) */
|
||||
|
||||
FST_VT_SV_BIT = 22,
|
||||
FST_VT_SV_LOGIC = 23,
|
||||
FST_VT_SV_INT = 24, /* declare as size = 32 */
|
||||
FST_VT_SV_SHORTINT = 25, /* declare as size = 16 */
|
||||
FST_VT_SV_LONGINT = 26, /* declare as size = 64 */
|
||||
FST_VT_SV_BYTE = 27, /* declare as size = 8 */
|
||||
FST_VT_SV_ENUM = 28, /* declare as appropriate type range */
|
||||
FST_VT_SV_SHORTREAL = 29, /* declare and emit same as FST_VT_VCD_REAL (needs to be emitted as double, not a float) */
|
||||
FST_VT_SV_BIT = 22,
|
||||
FST_VT_SV_LOGIC = 23,
|
||||
FST_VT_SV_INT = 24, /* declare as size = 32 */
|
||||
FST_VT_SV_SHORTINT = 25, /* declare as size = 16 */
|
||||
FST_VT_SV_LONGINT = 26, /* declare as size = 64 */
|
||||
FST_VT_SV_BYTE = 27, /* declare as size = 8 */
|
||||
FST_VT_SV_ENUM = 28, /* declare as appropriate type range */
|
||||
FST_VT_SV_SHORTREAL = 29, /* declare and emit same as FST_VT_VCD_REAL (needs to be emitted
|
||||
as double, not a float) */
|
||||
|
||||
FST_VT_MAX = 29 /* end of vartypes */
|
||||
FST_VT_MAX = 29 /* end of vartypes */
|
||||
};
|
||||
|
||||
enum fstVarDir {
|
||||
FST_VD_MIN = 0,
|
||||
enum fstVarDir
|
||||
{
|
||||
FST_VD_MIN = 0,
|
||||
|
||||
FST_VD_IMPLICIT = 0,
|
||||
FST_VD_INPUT = 1,
|
||||
FST_VD_OUTPUT = 2,
|
||||
FST_VD_INOUT = 3,
|
||||
FST_VD_BUFFER = 4,
|
||||
FST_VD_LINKAGE = 5,
|
||||
FST_VD_IMPLICIT = 0,
|
||||
FST_VD_INPUT = 1,
|
||||
FST_VD_OUTPUT = 2,
|
||||
FST_VD_INOUT = 3,
|
||||
FST_VD_BUFFER = 4,
|
||||
FST_VD_LINKAGE = 5,
|
||||
|
||||
FST_VD_MAX = 5
|
||||
FST_VD_MAX = 5
|
||||
};
|
||||
|
||||
enum fstHierType {
|
||||
FST_HT_MIN = 0,
|
||||
enum fstHierType
|
||||
{
|
||||
FST_HT_MIN = 0,
|
||||
|
||||
FST_HT_SCOPE = 0,
|
||||
FST_HT_UPSCOPE = 1,
|
||||
FST_HT_VAR = 2,
|
||||
FST_HT_ATTRBEGIN = 3,
|
||||
FST_HT_ATTREND = 4,
|
||||
FST_HT_SCOPE = 0,
|
||||
FST_HT_UPSCOPE = 1,
|
||||
FST_HT_VAR = 2,
|
||||
FST_HT_ATTRBEGIN = 3,
|
||||
FST_HT_ATTREND = 4,
|
||||
|
||||
/* FST_HT_TREEBEGIN and FST_HT_TREEEND are not yet used by FST but are currently used when fstHier bridges other formats */
|
||||
FST_HT_TREEBEGIN = 5,
|
||||
FST_HT_TREEEND = 6,
|
||||
/* FST_HT_TREEBEGIN and FST_HT_TREEEND are not yet used by FST but are currently used when
|
||||
fstHier bridges other formats */
|
||||
FST_HT_TREEBEGIN = 5,
|
||||
FST_HT_TREEEND = 6,
|
||||
|
||||
FST_HT_MAX = 6
|
||||
FST_HT_MAX = 6
|
||||
};
|
||||
|
||||
enum fstAttrType {
|
||||
FST_AT_MIN = 0,
|
||||
enum fstAttrType
|
||||
{
|
||||
FST_AT_MIN = 0,
|
||||
|
||||
FST_AT_MISC = 0, /* self-contained: does not need matching FST_HT_ATTREND */
|
||||
FST_AT_ARRAY = 1,
|
||||
FST_AT_ENUM = 2,
|
||||
FST_AT_PACK = 3,
|
||||
FST_AT_MISC = 0, /* self-contained: does not need matching FST_HT_ATTREND */
|
||||
FST_AT_ARRAY = 1,
|
||||
FST_AT_ENUM = 2,
|
||||
FST_AT_PACK = 3,
|
||||
|
||||
FST_AT_MAX = 3
|
||||
FST_AT_MAX = 3
|
||||
};
|
||||
|
||||
enum fstMiscType {
|
||||
FST_MT_MIN = 0,
|
||||
enum fstMiscType
|
||||
{
|
||||
FST_MT_MIN = 0,
|
||||
|
||||
FST_MT_COMMENT = 0, /* use fstWriterSetComment() to emit */
|
||||
FST_MT_ENVVAR = 1, /* use fstWriterSetEnvVar() to emit */
|
||||
FST_MT_SUPVAR = 2, /* use fstWriterCreateVar2() to emit */
|
||||
FST_MT_PATHNAME = 3, /* reserved for fstWriterSetSourceStem() string -> number management */
|
||||
FST_MT_SOURCESTEM = 4, /* use fstWriterSetSourceStem() to emit */
|
||||
FST_MT_SOURCEISTEM = 5, /* use fstWriterSetSourceInstantiationStem() to emit */
|
||||
FST_MT_VALUELIST = 6, /* use fstWriterSetValueList() to emit, followed by fstWriterCreateVar*() */
|
||||
FST_MT_ENUMTABLE = 7, /* use fstWriterCreateEnumTable() and fstWriterEmitEnumTableRef() to emit */
|
||||
FST_MT_UNKNOWN = 8,
|
||||
FST_MT_COMMENT = 0, /* use fstWriterSetComment() to emit */
|
||||
FST_MT_ENVVAR = 1, /* use fstWriterSetEnvVar() to emit */
|
||||
FST_MT_SUPVAR = 2, /* use fstWriterCreateVar2() to emit */
|
||||
FST_MT_PATHNAME = 3, /* reserved for fstWriterSetSourceStem() string -> number management */
|
||||
FST_MT_SOURCESTEM = 4, /* use fstWriterSetSourceStem() to emit */
|
||||
FST_MT_SOURCEISTEM = 5, /* use fstWriterSetSourceInstantiationStem() to emit */
|
||||
FST_MT_VALUELIST =
|
||||
6, /* use fstWriterSetValueList() to emit, followed by fstWriterCreateVar*() */
|
||||
FST_MT_ENUMTABLE =
|
||||
7, /* use fstWriterCreateEnumTable() and fstWriterEmitEnumTableRef() to emit */
|
||||
FST_MT_UNKNOWN = 8,
|
||||
|
||||
FST_MT_MAX = 8
|
||||
FST_MT_MAX = 8
|
||||
};
|
||||
|
||||
enum fstArrayType {
|
||||
FST_AR_MIN = 0,
|
||||
enum fstArrayType
|
||||
{
|
||||
FST_AR_MIN = 0,
|
||||
|
||||
FST_AR_NONE = 0,
|
||||
FST_AR_UNPACKED = 1,
|
||||
FST_AR_PACKED = 2,
|
||||
FST_AR_SPARSE = 3,
|
||||
FST_AR_NONE = 0,
|
||||
FST_AR_UNPACKED = 1,
|
||||
FST_AR_PACKED = 2,
|
||||
FST_AR_SPARSE = 3,
|
||||
|
||||
FST_AR_MAX = 3
|
||||
FST_AR_MAX = 3
|
||||
};
|
||||
|
||||
enum fstEnumValueType {
|
||||
FST_EV_SV_INTEGER = 0,
|
||||
FST_EV_SV_BIT = 1,
|
||||
FST_EV_SV_LOGIC = 2,
|
||||
FST_EV_SV_INT = 3,
|
||||
FST_EV_SV_SHORTINT = 4,
|
||||
FST_EV_SV_LONGINT = 5,
|
||||
FST_EV_SV_BYTE = 6,
|
||||
FST_EV_SV_UNSIGNED_INTEGER = 7,
|
||||
FST_EV_SV_UNSIGNED_BIT = 8,
|
||||
FST_EV_SV_UNSIGNED_LOGIC = 9,
|
||||
FST_EV_SV_UNSIGNED_INT = 10,
|
||||
enum fstEnumValueType
|
||||
{
|
||||
FST_EV_SV_INTEGER = 0,
|
||||
FST_EV_SV_BIT = 1,
|
||||
FST_EV_SV_LOGIC = 2,
|
||||
FST_EV_SV_INT = 3,
|
||||
FST_EV_SV_SHORTINT = 4,
|
||||
FST_EV_SV_LONGINT = 5,
|
||||
FST_EV_SV_BYTE = 6,
|
||||
FST_EV_SV_UNSIGNED_INTEGER = 7,
|
||||
FST_EV_SV_UNSIGNED_BIT = 8,
|
||||
FST_EV_SV_UNSIGNED_LOGIC = 9,
|
||||
FST_EV_SV_UNSIGNED_INT = 10,
|
||||
FST_EV_SV_UNSIGNED_SHORTINT = 11,
|
||||
FST_EV_SV_UNSIGNED_LONGINT = 12,
|
||||
FST_EV_SV_UNSIGNED_BYTE = 13,
|
||||
FST_EV_SV_UNSIGNED_LONGINT = 12,
|
||||
FST_EV_SV_UNSIGNED_BYTE = 13,
|
||||
|
||||
FST_EV_REG = 14,
|
||||
FST_EV_TIME = 15,
|
||||
FST_EV_REG = 14,
|
||||
FST_EV_TIME = 15,
|
||||
|
||||
FST_EV_MAX = 15
|
||||
FST_EV_MAX = 15
|
||||
};
|
||||
|
||||
enum fstPackType {
|
||||
FST_PT_NONE = 0,
|
||||
FST_PT_UNPACKED = 1,
|
||||
FST_PT_PACKED = 2,
|
||||
enum fstPackType
|
||||
{
|
||||
FST_PT_NONE = 0,
|
||||
FST_PT_UNPACKED = 1,
|
||||
FST_PT_PACKED = 2,
|
||||
FST_PT_TAGGED_PACKED = 3,
|
||||
|
||||
FST_PT_MAX = 3
|
||||
FST_PT_MAX = 3
|
||||
};
|
||||
|
||||
enum fstSupplementalVarType {
|
||||
FST_SVT_MIN = 0,
|
||||
enum fstSupplementalVarType
|
||||
{
|
||||
FST_SVT_MIN = 0,
|
||||
|
||||
FST_SVT_NONE = 0,
|
||||
FST_SVT_NONE = 0,
|
||||
|
||||
FST_SVT_VHDL_SIGNAL = 1,
|
||||
FST_SVT_VHDL_VARIABLE = 2,
|
||||
FST_SVT_VHDL_CONSTANT = 3,
|
||||
FST_SVT_VHDL_FILE = 4,
|
||||
FST_SVT_VHDL_MEMORY = 5,
|
||||
FST_SVT_VHDL_SIGNAL = 1,
|
||||
FST_SVT_VHDL_VARIABLE = 2,
|
||||
FST_SVT_VHDL_CONSTANT = 3,
|
||||
FST_SVT_VHDL_FILE = 4,
|
||||
FST_SVT_VHDL_MEMORY = 5,
|
||||
|
||||
FST_SVT_MAX = 5
|
||||
FST_SVT_MAX = 5
|
||||
};
|
||||
|
||||
enum fstSupplementalDataType {
|
||||
FST_SDT_MIN = 0,
|
||||
enum fstSupplementalDataType
|
||||
{
|
||||
FST_SDT_MIN = 0,
|
||||
|
||||
FST_SDT_NONE = 0,
|
||||
FST_SDT_NONE = 0,
|
||||
|
||||
FST_SDT_VHDL_BOOLEAN = 1,
|
||||
FST_SDT_VHDL_BIT = 2,
|
||||
FST_SDT_VHDL_BIT_VECTOR = 3,
|
||||
FST_SDT_VHDL_STD_ULOGIC = 4,
|
||||
FST_SDT_VHDL_BOOLEAN = 1,
|
||||
FST_SDT_VHDL_BIT = 2,
|
||||
FST_SDT_VHDL_BIT_VECTOR = 3,
|
||||
FST_SDT_VHDL_STD_ULOGIC = 4,
|
||||
FST_SDT_VHDL_STD_ULOGIC_VECTOR = 5,
|
||||
FST_SDT_VHDL_STD_LOGIC = 6,
|
||||
FST_SDT_VHDL_STD_LOGIC_VECTOR = 7,
|
||||
FST_SDT_VHDL_UNSIGNED = 8,
|
||||
FST_SDT_VHDL_SIGNED = 9,
|
||||
FST_SDT_VHDL_INTEGER = 10,
|
||||
FST_SDT_VHDL_REAL = 11,
|
||||
FST_SDT_VHDL_NATURAL = 12,
|
||||
FST_SDT_VHDL_POSITIVE = 13,
|
||||
FST_SDT_VHDL_TIME = 14,
|
||||
FST_SDT_VHDL_CHARACTER = 15,
|
||||
FST_SDT_VHDL_STRING = 16,
|
||||
FST_SDT_VHDL_STD_LOGIC = 6,
|
||||
FST_SDT_VHDL_STD_LOGIC_VECTOR = 7,
|
||||
FST_SDT_VHDL_UNSIGNED = 8,
|
||||
FST_SDT_VHDL_SIGNED = 9,
|
||||
FST_SDT_VHDL_INTEGER = 10,
|
||||
FST_SDT_VHDL_REAL = 11,
|
||||
FST_SDT_VHDL_NATURAL = 12,
|
||||
FST_SDT_VHDL_POSITIVE = 13,
|
||||
FST_SDT_VHDL_TIME = 14,
|
||||
FST_SDT_VHDL_CHARACTER = 15,
|
||||
FST_SDT_VHDL_STRING = 16,
|
||||
|
||||
FST_SDT_MAX = 16,
|
||||
FST_SDT_MAX = 16,
|
||||
|
||||
FST_SDT_SVT_SHIFT_COUNT = 10, /* FST_SVT_* is ORed in by fstWriterCreateVar2() to the left after shifting FST_SDT_SVT_SHIFT_COUNT */
|
||||
FST_SDT_ABS_MAX = ((1<<(FST_SDT_SVT_SHIFT_COUNT))-1)
|
||||
FST_SDT_SVT_SHIFT_COUNT = 10, /* FST_SVT_* is ORed in by fstWriterCreateVar2() to the left
|
||||
after shifting FST_SDT_SVT_SHIFT_COUNT */
|
||||
FST_SDT_ABS_MAX = ((1 << (FST_SDT_SVT_SHIFT_COUNT)) - 1)
|
||||
};
|
||||
|
||||
|
||||
struct fstHier
|
||||
{
|
||||
unsigned char htyp;
|
||||
unsigned char htyp;
|
||||
|
||||
union {
|
||||
union
|
||||
{
|
||||
/* if htyp == FST_HT_SCOPE */
|
||||
struct fstHierScope {
|
||||
unsigned char typ; /* FST_ST_MIN ... FST_ST_MAX */
|
||||
const char *name;
|
||||
const char *component;
|
||||
uint32_t name_length; /* strlen(u.scope.name) */
|
||||
uint32_t component_length; /* strlen(u.scope.component) */
|
||||
} scope;
|
||||
struct fstHierScope
|
||||
{
|
||||
unsigned char typ; /* FST_ST_MIN ... FST_ST_MAX */
|
||||
const char *name;
|
||||
const char *component;
|
||||
uint32_t name_length; /* strlen(u.scope.name) */
|
||||
uint32_t component_length; /* strlen(u.scope.component) */
|
||||
} scope;
|
||||
|
||||
/* if htyp == FST_HT_VAR */
|
||||
struct fstHierVar {
|
||||
unsigned char typ; /* FST_VT_MIN ... FST_VT_MAX */
|
||||
unsigned char direction; /* FST_VD_MIN ... FST_VD_MAX */
|
||||
unsigned char svt_workspace; /* zeroed out by FST reader, for client code use */
|
||||
unsigned char sdt_workspace; /* zeroed out by FST reader, for client code use */
|
||||
unsigned int sxt_workspace; /* zeroed out by FST reader, for client code use */
|
||||
const char *name;
|
||||
uint32_t length;
|
||||
fstHandle handle;
|
||||
uint32_t name_length; /* strlen(u.var.name) */
|
||||
unsigned is_alias : 1;
|
||||
} var;
|
||||
struct fstHierVar
|
||||
{
|
||||
unsigned char typ; /* FST_VT_MIN ... FST_VT_MAX */
|
||||
unsigned char direction; /* FST_VD_MIN ... FST_VD_MAX */
|
||||
unsigned char svt_workspace; /* zeroed out by FST reader, for client code use */
|
||||
unsigned char sdt_workspace; /* zeroed out by FST reader, for client code use */
|
||||
unsigned int sxt_workspace; /* zeroed out by FST reader, for client code use */
|
||||
const char *name;
|
||||
uint32_t length;
|
||||
fstHandle handle;
|
||||
uint32_t name_length; /* strlen(u.var.name) */
|
||||
unsigned is_alias : 1;
|
||||
} var;
|
||||
|
||||
/* if htyp == FST_HT_ATTRBEGIN */
|
||||
struct fstHierAttr {
|
||||
unsigned char typ; /* FST_AT_MIN ... FST_AT_MAX */
|
||||
unsigned char subtype; /* from fstMiscType, fstArrayType, fstEnumValueType, fstPackType */
|
||||
const char *name;
|
||||
uint64_t arg; /* number of array elements, struct members, or some other payload (possibly ignored) */
|
||||
uint64_t arg_from_name; /* for when name is overloaded as a variable-length integer (FST_AT_MISC + FST_MT_SOURCESTEM) */
|
||||
uint32_t name_length; /* strlen(u.attr.name) */
|
||||
} attr;
|
||||
} u;
|
||||
struct fstHierAttr
|
||||
{
|
||||
unsigned char typ; /* FST_AT_MIN ... FST_AT_MAX */
|
||||
unsigned char
|
||||
subtype; /* from fstMiscType, fstArrayType, fstEnumValueType, fstPackType */
|
||||
const char *name;
|
||||
uint64_t arg; /* number of array elements, struct members, or some other payload
|
||||
(possibly ignored) */
|
||||
uint64_t arg_from_name; /* for when name is overloaded as a variable-length integer
|
||||
(FST_AT_MISC + FST_MT_SOURCESTEM) */
|
||||
uint32_t name_length; /* strlen(u.attr.name) */
|
||||
} attr;
|
||||
} u;
|
||||
};
|
||||
|
||||
|
||||
struct fstETab
|
||||
{
|
||||
char *name;
|
||||
uint32_t elem_count;
|
||||
char **literal_arr;
|
||||
char **val_arr;
|
||||
char *name;
|
||||
uint32_t elem_count;
|
||||
char **literal_arr;
|
||||
char **val_arr;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* writer functions
|
||||
*/
|
||||
void fstWriterClose(void *ctx);
|
||||
void * fstWriterCreate(const char *nam, int use_compressed_hier);
|
||||
fstEnumHandle fstWriterCreateEnumTable(void *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, enum fstVarType vt, enum fstVarDir vd,
|
||||
uint32_t len, const char *nam, fstHandle aliasHandle);
|
||||
/* 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, enum fstVarType vt, enum fstVarDir vd,
|
||||
uint32_t len, const char *nam, fstHandle aliasHandle,
|
||||
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, fstHandle handle,
|
||||
uint32_t bits, const uint32_t *val);
|
||||
void fstWriterEmitValueChangeVec64(void *ctx, fstHandle handle,
|
||||
uint32_t bits, const uint64_t *val);
|
||||
void fstWriterEmitVariableLengthValueChange(void *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);
|
||||
void fstWriterSetAttrBegin(void *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, enum fstScopeType scopetype,
|
||||
const char *scopename, const char *scopecomp);
|
||||
void fstWriterSetSourceInstantiationStem(void *ctx, const char *path, unsigned int line, unsigned int use_realpath);
|
||||
void fstWriterSetSourceStem(void *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);
|
||||
|
||||
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(fstWriterContext *ctx,
|
||||
enum fstVarType vt,
|
||||
enum fstVarDir vd,
|
||||
uint32_t len,
|
||||
const char *nam,
|
||||
fstHandle aliasHandle);
|
||||
/* 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(fstWriterContext *ctx,
|
||||
enum fstVarType vt,
|
||||
enum fstVarDir vd,
|
||||
uint32_t len,
|
||||
const char *nam,
|
||||
fstHandle aliasHandle,
|
||||
const char *type,
|
||||
enum fstSupplementalVarType svt,
|
||||
enum fstSupplementalDataType sdt);
|
||||
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(fstWriterContext *ctx,
|
||||
fstHandle handle,
|
||||
uint32_t bits,
|
||||
const uint64_t *val);
|
||||
void fstWriterEmitVariableLengthValueChange(fstWriterContext *ctx,
|
||||
fstHandle handle,
|
||||
const void *val,
|
||||
uint32_t len);
|
||||
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(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(fstWriterContext *ctx,
|
||||
const char *path,
|
||||
unsigned int line,
|
||||
unsigned int use_realpath);
|
||||
void fstWriterSetSourceStem(fstWriterContext *ctx,
|
||||
const char *path,
|
||||
unsigned int line,
|
||||
unsigned int use_realpath);
|
||||
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,
|
||||
void (*value_change_callback)(void *user_callback_data_pointer, 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);
|
||||
|
||||
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),
|
||||
void *user_callback_data_pointer,
|
||||
FILE *vcdhandle);
|
||||
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
|
||||
*/
|
||||
int fstUtilityBinToEscConvertedLen(const unsigned char *s, int len); /* used for mallocs for fstUtilityBinToEsc() */
|
||||
int fstUtilityBinToEsc(unsigned char *d, const unsigned char *s, int len);
|
||||
int fstUtilityEscToBin(unsigned char *d, unsigned char *s, int len);
|
||||
int fstUtilityBinToEscConvertedLen(const unsigned char *s, int len); /* used for mallocs for fstUtilityBinToEsc() */
|
||||
int fstUtilityBinToEsc(unsigned char *d, const unsigned char *s, int len);
|
||||
int fstUtilityEscToBin(unsigned char *d, unsigned char *s, int len);
|
||||
struct fstETab *fstUtilityExtractEnumTableFromString(const char *s);
|
||||
void fstUtilityFreeEnumTable(struct fstETab *etab); /* must use to free fstETab properly */
|
||||
|
||||
void fstUtilityFreeEnumTable(struct fstETab *etab); /* must use to free fstETab properly */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,41 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 1999 Tony Bybell.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#ifndef WAVE_ALLOCA_H
|
||||
#define WAVE_ALLOCA_H
|
||||
#include <stdlib.h>
|
||||
#ifdef HAVE_ALLOCA_H
|
||||
#include <alloca.h>
|
||||
#elif defined(__GNUC__)
|
||||
#ifndef __MINGW32__
|
||||
#ifndef alloca
|
||||
#define alloca __builtin_alloca
|
||||
#endif
|
||||
#else
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
#endif
|
||||
#define wave_alloca alloca
|
||||
#endif
|
||||
|
||||
|
|
@ -56,6 +56,7 @@
|
|||
#include <cctype>
|
||||
#include <cerrno>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
#include <list>
|
||||
#include <sstream>
|
||||
|
|
@ -916,6 +917,21 @@ void _vl_vsformat(std::string& output, const std::string& format, va_list ap) VL
|
|||
}
|
||||
break;
|
||||
}
|
||||
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);
|
||||
std::string hex_str = oss.str();
|
||||
if (width > 0 && widthSet) {
|
||||
hex_str = hex_str.size() > width
|
||||
? hex_str.substr(0, width)
|
||||
: std::string(width - hex_str.size(), '0') + hex_str;
|
||||
output += hex_str;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
// Deal with all read-and-print somethings
|
||||
const int lbits = va_arg(ap, int);
|
||||
|
|
@ -1234,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;
|
||||
|
|
@ -1420,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;
|
||||
}
|
||||
|
||||
|
|
@ -3017,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 {
|
||||
|
|
@ -3455,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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ VK_CPPFLAGS_ALWAYS += \
|
|||
-DVM_TRACE=$(VM_TRACE) \
|
||||
-DVM_TRACE_FST=$(VM_TRACE_FST) \
|
||||
-DVM_TRACE_VCD=$(VM_TRACE_VCD) \
|
||||
-DVM_TRACE_SAIF=$(VM_TRACE_SAIF) \
|
||||
$(CFG_CXXFLAGS_NO_UNUSED) \
|
||||
|
||||
ifeq ($(CFG_WITH_CCWARN),yes) # Local... Else don't burden users
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
@ -157,15 +135,21 @@ void VlExecutionProfiler::dump(const char* filenamep, uint64_t tickEnd)
|
|||
VL_DEBUG_IF(VL_DBG_MSGF("+prof+exec writing to '%s'\n", filenamep););
|
||||
|
||||
FILE* const fp = std::fopen(filenamep, "w");
|
||||
if (VL_UNLIKELY(!fp)) { VL_FATAL_MT(filenamep, 0, "", "+prof+exec+file file not writable"); }
|
||||
if (VL_UNLIKELY(!fp)) VL_FATAL_MT(filenamep, 0, "", "+prof+exec+file file not writable");
|
||||
|
||||
// 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: {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -166,7 +166,7 @@ public:
|
|||
s << "(Array (_ BitVec " << idxWidths[i] << ") ";
|
||||
}
|
||||
s << "(_ BitVec " << width() << ")";
|
||||
for (int i = 0; i < dimension(); ++i) { s << ")"; }
|
||||
for (int i = 0; i < dimension(); ++i) s << ")";
|
||||
}
|
||||
} else {
|
||||
VL_FATAL_MT(__FILE__, __LINE__, "randomize", "indexed_name not found in m_arr_vars");
|
||||
|
|
@ -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,28 +327,60 @@ public:
|
|||
m_vars[name]
|
||||
= std::make_shared<const VlRandomVar>(name, width, &var, dimension, randmodeIdx);
|
||||
}
|
||||
|
||||
// Register user-defined struct variable by recursively writing members
|
||||
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()) {
|
||||
typename std::enable_if<VlIsCustomStruct<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()) {
|
||||
modifyMembers(var, var.memberIndices(), name);
|
||||
}
|
||||
|
||||
// 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) {
|
||||
idx = 0;
|
||||
m_index = 0;
|
||||
record_arr_table(var, name, dimension, {}, {});
|
||||
}
|
||||
}
|
||||
|
||||
// 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>
|
||||
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()) {
|
||||
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) {
|
||||
idx = 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>
|
||||
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()) {
|
||||
|
|
@ -339,59 +389,28 @@ public:
|
|||
= std::make_shared<const VlRandomArrayVarTemplate<VlAssocArray<T_Key, T_Value>>>(
|
||||
name, width, &var, dimension, randmodeIdx);
|
||||
if (dimension > 0) {
|
||||
idx = 0;
|
||||
m_index = 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)...};
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename std::enable_if<VlIsCustomStruct<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()) {
|
||||
modifyMembers(var, var.memberIndices(), name);
|
||||
}
|
||||
// TODO: Register associative array of structs
|
||||
|
||||
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);
|
||||
}
|
||||
const size_t bracket_pos = name.find('[');
|
||||
return (bracket_pos != std::string::npos ? name.substr(0, bracket_pos) : name)
|
||||
+ std::to_string(idx);
|
||||
}
|
||||
// ----------------------------------------
|
||||
// --- 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 +425,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 +469,76 @@ 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 << static_cast<int>(indices[i]);
|
||||
if (i < indices.size() - 1) oss << ".";
|
||||
}
|
||||
write_var(var, 1ULL, (name + "." + oss.str()).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) {
|
||||
idxWidths.push_back(32);
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Add support for associative arrays of structs
|
||||
// Recursively process associative arrays of structs
|
||||
|
||||
// --------------------------
|
||||
// --- 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; }
|
||||
|
|
|
|||
|
|
@ -0,0 +1,662 @@
|
|||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//=============================================================================
|
||||
//
|
||||
// Code available from: https://verilator.org
|
||||
//
|
||||
// Copyright 2001-2025 by Wilson Snyder. This program is free software; you
|
||||
// can redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
//
|
||||
//=============================================================================
|
||||
///
|
||||
/// \file
|
||||
/// \brief Verilated C++ tracing in SAIF format implementation code
|
||||
///
|
||||
/// This file must be compiled and linked against all Verilated objects
|
||||
/// that use --trace-saif.
|
||||
///
|
||||
/// Use "verilator --trace-saif" to add this to the Makefile for the linker.
|
||||
///
|
||||
//=============================================================================
|
||||
|
||||
// clang-format off
|
||||
|
||||
#include "verilatedos.h"
|
||||
#include "verilated.h"
|
||||
#include "verilated_saif_c.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cerrno>
|
||||
#include <fcntl.h>
|
||||
#include <string>
|
||||
|
||||
#if defined(_WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__)
|
||||
# include <io.h>
|
||||
#else
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifndef O_LARGEFILE // WIN32 headers omit this
|
||||
# define O_LARGEFILE 0
|
||||
#endif
|
||||
#ifndef O_NONBLOCK // WIN32 headers omit this
|
||||
# define O_NONBLOCK 0
|
||||
#endif
|
||||
#ifndef O_CLOEXEC // WIN32 headers omit this
|
||||
# define O_CLOEXEC 0
|
||||
#endif
|
||||
|
||||
// clang-format on
|
||||
|
||||
//=============================================================================
|
||||
// Specialization of the generics for this trace format
|
||||
|
||||
#define VL_SUB_T VerilatedSaif
|
||||
#define VL_BUF_T VerilatedSaifBuffer
|
||||
#include "verilated_trace_imp.h"
|
||||
#undef VL_SUB_T
|
||||
#undef VL_BUF_T
|
||||
|
||||
//=============================================================================
|
||||
// VerilatedSaifActivityBit
|
||||
|
||||
class VerilatedSaifActivityBit final {
|
||||
// MEMBERS
|
||||
bool m_lastVal = false; // Last emitted activity bit value
|
||||
uint64_t m_highTime = 0; // Total time when bit was high
|
||||
size_t m_transitions = 0; // Total number of bit transitions
|
||||
|
||||
public:
|
||||
// METHODS
|
||||
VL_ATTR_ALWINLINE
|
||||
void aggregateVal(uint64_t dt, bool newVal) {
|
||||
m_transitions += newVal != m_lastVal ? 1 : 0;
|
||||
m_highTime += m_lastVal ? dt : 0;
|
||||
m_lastVal = newVal;
|
||||
}
|
||||
|
||||
// ACCESSORS
|
||||
VL_ATTR_ALWINLINE bool bitValue() const { return m_lastVal; }
|
||||
VL_ATTR_ALWINLINE uint64_t highTime() const { return m_highTime; }
|
||||
VL_ATTR_ALWINLINE uint64_t toggleCount() const { return m_transitions; }
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
// VerilatedSaifActivityVar
|
||||
|
||||
class VerilatedSaifActivityVar final {
|
||||
// MEMBERS
|
||||
uint64_t m_lastTime = 0; // Last time when variable value was updated
|
||||
VerilatedSaifActivityBit* m_bits; // Pointer to variable bits objects
|
||||
uint32_t m_width; // Width of variable (in bits)
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
VerilatedSaifActivityVar(uint32_t width, VerilatedSaifActivityBit* bits)
|
||||
: m_bits{bits}
|
||||
, m_width{width} {}
|
||||
|
||||
VerilatedSaifActivityVar(VerilatedSaifActivityVar&&) = default;
|
||||
VerilatedSaifActivityVar& operator=(VerilatedSaifActivityVar&&) = default;
|
||||
|
||||
// METHODS
|
||||
VL_ATTR_ALWINLINE void emitBit(uint64_t time, CData newval);
|
||||
|
||||
template <typename DataType>
|
||||
VL_ATTR_ALWINLINE void emitData(uint64_t time, DataType newval, uint32_t bits) {
|
||||
static_assert(std::is_integral<DataType>::value,
|
||||
"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++) {
|
||||
m_bits[i].aggregateVal(dt, (newval >> i) & 1);
|
||||
}
|
||||
updateLastTime(time);
|
||||
}
|
||||
|
||||
VL_ATTR_ALWINLINE void emitWData(uint64_t time, const WData* newvalp, uint32_t bits);
|
||||
VL_ATTR_ALWINLINE void updateLastTime(uint64_t val) { m_lastTime = val; }
|
||||
|
||||
// ACCESSORS
|
||||
VL_ATTR_ALWINLINE uint32_t width() const { return m_width; }
|
||||
VL_ATTR_ALWINLINE VerilatedSaifActivityBit& bit(std::size_t index);
|
||||
VL_ATTR_ALWINLINE uint64_t lastUpdateTime() const { return m_lastTime; }
|
||||
|
||||
private:
|
||||
// CONSTRUCTORS
|
||||
VL_UNCOPYABLE(VerilatedSaifActivityVar);
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
// VerilatedSaifActivityScope
|
||||
|
||||
class VerilatedSaifActivityScope final {
|
||||
// MEMBERS
|
||||
// Absolute path to the scope
|
||||
std::string m_scopePath;
|
||||
// Name of the activity scope
|
||||
std::string m_scopeName;
|
||||
// Array indices of child scopes
|
||||
std::vector<std::unique_ptr<VerilatedSaifActivityScope>> m_childScopes{};
|
||||
// Children signals codes mapped to their names in the current scope
|
||||
std::vector<std::pair<uint32_t, std::string>> m_childActivities{};
|
||||
// Parent scope pointer
|
||||
VerilatedSaifActivityScope* m_parentScope = nullptr;
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
VerilatedSaifActivityScope(std::string scopePath, std::string name,
|
||||
VerilatedSaifActivityScope* parentScope = nullptr)
|
||||
: m_scopePath{std::move(scopePath)}
|
||||
, m_scopeName{std::move(name)}
|
||||
, m_parentScope{parentScope} {}
|
||||
|
||||
VerilatedSaifActivityScope(VerilatedSaifActivityScope&&) = default;
|
||||
VerilatedSaifActivityScope& operator=(VerilatedSaifActivityScope&&) = default;
|
||||
|
||||
// METHODS
|
||||
VL_ATTR_ALWINLINE void addChildScope(std::unique_ptr<VerilatedSaifActivityScope> childScope) {
|
||||
m_childScopes.emplace_back(std::move(childScope));
|
||||
}
|
||||
VL_ATTR_ALWINLINE void addActivityVar(uint32_t code, std::string name) {
|
||||
m_childActivities.emplace_back(code, std::move(name));
|
||||
}
|
||||
VL_ATTR_ALWINLINE bool hasParent() const { return m_parentScope; }
|
||||
|
||||
// ACCESSORS
|
||||
VL_ATTR_ALWINLINE const std::string& path() const { return m_scopePath; }
|
||||
VL_ATTR_ALWINLINE const std::string& name() const { return m_scopeName; }
|
||||
VL_ATTR_ALWINLINE const std::vector<std::unique_ptr<VerilatedSaifActivityScope>>&
|
||||
childScopes() const {
|
||||
return m_childScopes;
|
||||
}
|
||||
VL_ATTR_ALWINLINE
|
||||
const std::vector<std::pair<uint32_t, std::string>>& childActivities() const {
|
||||
return m_childActivities;
|
||||
}
|
||||
VL_ATTR_ALWINLINE VerilatedSaifActivityScope* parentScope() const { return m_parentScope; }
|
||||
|
||||
private:
|
||||
// CONSTRUCTORS
|
||||
VL_UNCOPYABLE(VerilatedSaifActivityScope);
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
// VerilatedSaifActivityAccumulator
|
||||
|
||||
class VerilatedSaifActivityAccumulator final {
|
||||
// Give access to the private activities
|
||||
friend class VerilatedSaifBuffer;
|
||||
friend class VerilatedSaif;
|
||||
|
||||
// MEMBERS
|
||||
// Map of scopes paths to codes of activities inside
|
||||
std::unordered_map<std::string, std::vector<std::pair<uint32_t, std::string>>>
|
||||
m_scopeToActivities;
|
||||
// Map of variables codes mapped to their activity objects
|
||||
std::unordered_map<uint32_t, VerilatedSaifActivityVar> m_activity;
|
||||
// Memory pool for signals bits objects
|
||||
std::vector<std::vector<VerilatedSaifActivityBit>> m_activityArena;
|
||||
|
||||
public:
|
||||
// METHODS
|
||||
void declare(uint32_t code, const std::string& absoluteScopePath, std::string variableName,
|
||||
int bits, bool array, int arraynum);
|
||||
|
||||
// CONSTRUCTORS
|
||||
VerilatedSaifActivityAccumulator() = default;
|
||||
|
||||
VerilatedSaifActivityAccumulator(VerilatedSaifActivityAccumulator&&) = default;
|
||||
VerilatedSaifActivityAccumulator& operator=(VerilatedSaifActivityAccumulator&&) = default;
|
||||
|
||||
private:
|
||||
VL_UNCOPYABLE(VerilatedSaifActivityAccumulator);
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
//=============================================================================
|
||||
//=============================================================================
|
||||
// VerilatedSaifActivityVar implementation
|
||||
|
||||
VL_ATTR_ALWINLINE
|
||||
void VerilatedSaifActivityVar::emitBit(const uint64_t time, const CData newval) {
|
||||
assert(m_lastTime <= time);
|
||||
m_bits[0].aggregateVal(time - m_lastTime, newval);
|
||||
updateLastTime(time);
|
||||
}
|
||||
|
||||
VL_ATTR_ALWINLINE
|
||||
void VerilatedSaifActivityVar::emitWData(const uint64_t time, const WData* newvalp,
|
||||
const uint32_t bits) {
|
||||
assert(m_lastTime <= time);
|
||||
const uint64_t dt = time - m_lastTime;
|
||||
for (std::size_t i = 0; i < std::min(m_width, bits); ++i) {
|
||||
const size_t wordIndex = i / VL_EDATASIZE;
|
||||
m_bits[i].aggregateVal(dt, (newvalp[wordIndex] >> VL_BITBIT_E(i)) & 1);
|
||||
}
|
||||
|
||||
updateLastTime(time);
|
||||
}
|
||||
|
||||
VerilatedSaifActivityBit& VerilatedSaifActivityVar::bit(const std::size_t index) {
|
||||
assert(index < m_width);
|
||||
return m_bits[index];
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//=============================================================================
|
||||
//=============================================================================
|
||||
// VerilatedSaifActivityAccumulator implementation
|
||||
|
||||
void VerilatedSaifActivityAccumulator::declare(uint32_t code, const std::string& absoluteScopePath,
|
||||
std::string variableName, int bits, bool array,
|
||||
int arraynum) {
|
||||
const size_t block_size = 1024;
|
||||
if (m_activityArena.empty()
|
||||
|| m_activityArena.back().size() + bits > m_activityArena.back().capacity()) {
|
||||
m_activityArena.emplace_back();
|
||||
m_activityArena.back().reserve(block_size);
|
||||
}
|
||||
const size_t bitsIdx = m_activityArena.back().size();
|
||||
m_activityArena.back().resize(m_activityArena.back().size() + bits);
|
||||
|
||||
if (array) {
|
||||
variableName += '[';
|
||||
variableName += std::to_string(arraynum);
|
||||
variableName += ']';
|
||||
}
|
||||
m_scopeToActivities[absoluteScopePath].emplace_back(code, variableName);
|
||||
m_activity.emplace(code, VerilatedSaifActivityVar{static_cast<uint32_t>(bits),
|
||||
m_activityArena.back().data() + bitsIdx});
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//=============================================================================
|
||||
//=============================================================================
|
||||
// VerilatedSaif implementation
|
||||
|
||||
VerilatedSaif::VerilatedSaif(void* filep) {
|
||||
m_activityAccumulators.emplace_back(std::make_unique<VerilatedSaifActivityAccumulator>());
|
||||
}
|
||||
|
||||
void VerilatedSaif::open(const char* filename) VL_MT_SAFE_EXCLUDES(m_mutex) {
|
||||
const VerilatedLockGuard lock{m_mutex};
|
||||
if (isOpen()) return;
|
||||
|
||||
m_filename = filename; // "" is ok, as someone may overload open
|
||||
m_filep = ::open(m_filename.c_str(),
|
||||
O_CREAT | O_WRONLY | O_TRUNC | O_LARGEFILE | O_NONBLOCK | O_CLOEXEC, 0666);
|
||||
m_isOpen = true;
|
||||
|
||||
initializeSaifFileContents();
|
||||
|
||||
Super::traceInit();
|
||||
}
|
||||
|
||||
void VerilatedSaif::initializeSaifFileContents() {
|
||||
printStr("// Generated by verilated_saif\n");
|
||||
printStr("(SAIFILE\n");
|
||||
printStr("(SAIFVERSION \"2.0\")\n");
|
||||
printStr("(DIRECTION \"backward\")\n");
|
||||
printStr("(PROGRAM_NAME \"Verilator\")\n");
|
||||
printStr("(DIVIDER / )\n");
|
||||
printStr("(TIMESCALE ");
|
||||
printStr(timeResStr());
|
||||
printStr(")\n");
|
||||
}
|
||||
|
||||
void VerilatedSaif::emitTimeChange(uint64_t timeui) { m_time = timeui; }
|
||||
|
||||
VerilatedSaif::~VerilatedSaif() { close(); }
|
||||
|
||||
void VerilatedSaif::close() VL_MT_SAFE_EXCLUDES(m_mutex) {
|
||||
// This function is on the flush() call path
|
||||
const VerilatedLockGuard lock{m_mutex};
|
||||
if (!isOpen()) return;
|
||||
|
||||
finalizeSaifFileContents();
|
||||
clearCurrentlyCollectedData();
|
||||
|
||||
writeBuffered(true);
|
||||
::close(m_filep);
|
||||
m_isOpen = false;
|
||||
|
||||
Super::closeBase();
|
||||
}
|
||||
|
||||
void VerilatedSaif::finalizeSaifFileContents() {
|
||||
printStr("(DURATION ");
|
||||
printStr(std::to_string(currentTime()));
|
||||
printStr(")\n");
|
||||
|
||||
incrementIndent();
|
||||
for (const auto& topScope : m_scopes) recursivelyPrintScopes(*topScope);
|
||||
decrementIndent();
|
||||
|
||||
printStr(")\n"); // SAIFILE
|
||||
}
|
||||
|
||||
void VerilatedSaif::recursivelyPrintScopes(const VerilatedSaifActivityScope& scope) {
|
||||
openInstanceScope(scope.name());
|
||||
printScopeActivities(scope);
|
||||
for (const auto& childScope : scope.childScopes()) recursivelyPrintScopes(*childScope);
|
||||
closeInstanceScope();
|
||||
}
|
||||
|
||||
void VerilatedSaif::openInstanceScope(const std::string& instanceName) {
|
||||
printIndent();
|
||||
printStr("(INSTANCE ");
|
||||
printStr(instanceName);
|
||||
printStr("\n");
|
||||
incrementIndent();
|
||||
}
|
||||
|
||||
void VerilatedSaif::closeInstanceScope() {
|
||||
decrementIndent();
|
||||
printIndent();
|
||||
printStr(")\n"); // INSTANCE
|
||||
}
|
||||
|
||||
void VerilatedSaif::printScopeActivities(const VerilatedSaifActivityScope& scope) {
|
||||
bool anyNetWritten = false;
|
||||
|
||||
for (auto& accumulator : m_activityAccumulators) {
|
||||
anyNetWritten |= printScopeActivitiesFromAccumulatorIfPresent(scope.path(), *accumulator,
|
||||
anyNetWritten);
|
||||
}
|
||||
|
||||
if (anyNetWritten) closeNetScope();
|
||||
}
|
||||
|
||||
bool VerilatedSaif::printScopeActivitiesFromAccumulatorIfPresent(
|
||||
const std::string& absoluteScopePath, VerilatedSaifActivityAccumulator& accumulator,
|
||||
bool anyNetWritten) {
|
||||
if (accumulator.m_scopeToActivities.count(absoluteScopePath) == 0) return false;
|
||||
|
||||
for (const auto& childSignal : accumulator.m_scopeToActivities.at(absoluteScopePath)) {
|
||||
VerilatedSaifActivityVar& activityVariable = accumulator.m_activity.at(childSignal.first);
|
||||
anyNetWritten
|
||||
= printActivityStats(activityVariable, childSignal.second.c_str(), anyNetWritten);
|
||||
}
|
||||
|
||||
return anyNetWritten;
|
||||
}
|
||||
|
||||
void VerilatedSaif::openNetScope() {
|
||||
printIndent();
|
||||
printStr("(NET\n");
|
||||
incrementIndent();
|
||||
}
|
||||
|
||||
void VerilatedSaif::closeNetScope() {
|
||||
decrementIndent();
|
||||
printIndent();
|
||||
printStr(")\n"); // NET
|
||||
}
|
||||
|
||||
bool VerilatedSaif::printActivityStats(VerilatedSaifActivityVar& activity,
|
||||
const std::string& activityName, bool anyNetWritten) {
|
||||
for (size_t i = 0; i < activity.width(); ++i) {
|
||||
VerilatedSaifActivityBit& bit = activity.bit(i);
|
||||
|
||||
bit.aggregateVal(currentTime() - activity.lastUpdateTime(), bit.bitValue());
|
||||
|
||||
if (!anyNetWritten) {
|
||||
openNetScope();
|
||||
anyNetWritten = true;
|
||||
}
|
||||
|
||||
printIndent();
|
||||
printStr("(");
|
||||
printStr(activityName);
|
||||
if (activity.width() > 1) {
|
||||
printStr("\\[");
|
||||
printStr(std::to_string(i));
|
||||
printStr("\\]");
|
||||
}
|
||||
|
||||
// We only have two-value logic so TZ, TX and TB will always be 0
|
||||
printStr(" (T0 ");
|
||||
printStr(std::to_string(currentTime() - bit.highTime()));
|
||||
printStr(") (T1 ");
|
||||
printStr(std::to_string(bit.highTime()));
|
||||
printStr(") (TZ 0) (TX 0) (TB 0) (TC ");
|
||||
printStr(std::to_string(bit.toggleCount()));
|
||||
printStr("))\n");
|
||||
}
|
||||
|
||||
activity.updateLastTime(currentTime());
|
||||
|
||||
return anyNetWritten;
|
||||
}
|
||||
|
||||
void VerilatedSaif::clearCurrentlyCollectedData() {
|
||||
m_currentScope = nullptr;
|
||||
m_scopes.clear();
|
||||
m_activityAccumulators.clear();
|
||||
}
|
||||
|
||||
void VerilatedSaif::printStr(const char* str) {
|
||||
m_buffer.append(str);
|
||||
writeBuffered(false);
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
void VerilatedSaif::flush() VL_MT_SAFE_EXCLUDES(m_mutex) {
|
||||
const VerilatedLockGuard lock{m_mutex};
|
||||
Super::flushBase();
|
||||
}
|
||||
|
||||
void VerilatedSaif::incrementIndent() { m_indent += 1; }
|
||||
|
||||
void VerilatedSaif::decrementIndent() { m_indent -= 1; }
|
||||
|
||||
void VerilatedSaif::printIndent() {
|
||||
printStr(std::string(m_indent, ' ')); // Must use () constructor
|
||||
}
|
||||
|
||||
void VerilatedSaif::pushPrefix(const std::string& name, VerilatedTracePrefixType type) {
|
||||
std::string pname = name;
|
||||
|
||||
if (m_prefixStack.back().second == VerilatedTracePrefixType::ROOTIO_MODULE) popPrefix();
|
||||
if (pname.empty()) {
|
||||
pname = "$rootio";
|
||||
type = VerilatedTracePrefixType::ROOTIO_MODULE;
|
||||
}
|
||||
|
||||
if (type != VerilatedTracePrefixType::ARRAY_UNPACKED
|
||||
&& type != VerilatedTracePrefixType::ARRAY_PACKED) {
|
||||
|
||||
std::string scopePath = m_prefixStack.back().first + pname;
|
||||
std::string scopeName = lastWord(scopePath);
|
||||
|
||||
auto newScope = std::make_unique<VerilatedSaifActivityScope>(
|
||||
std::move(scopePath), std::move(scopeName), m_currentScope);
|
||||
VerilatedSaifActivityScope* newScopePtr = newScope.get();
|
||||
|
||||
if (m_currentScope) {
|
||||
m_currentScope->addChildScope(std::move(newScope));
|
||||
} else {
|
||||
m_scopes.emplace_back(std::move(newScope));
|
||||
}
|
||||
|
||||
m_currentScope = newScopePtr;
|
||||
}
|
||||
|
||||
std::string newPrefix = m_prefixStack.back().first + pname;
|
||||
if (type != VerilatedTracePrefixType::ARRAY_UNPACKED
|
||||
&& type != VerilatedTracePrefixType::ARRAY_PACKED) {
|
||||
newPrefix += ' ';
|
||||
}
|
||||
|
||||
m_prefixStack.emplace_back(newPrefix, type);
|
||||
}
|
||||
|
||||
void VerilatedSaif::popPrefix() {
|
||||
if (m_prefixStack.back().second != VerilatedTracePrefixType::ARRAY_UNPACKED
|
||||
&& m_prefixStack.back().second != VerilatedTracePrefixType::ARRAY_PACKED
|
||||
&& m_currentScope != nullptr) {
|
||||
m_currentScope = m_currentScope->parentScope();
|
||||
}
|
||||
|
||||
m_prefixStack.pop_back();
|
||||
}
|
||||
|
||||
void VerilatedSaif::declare(const uint32_t code, uint32_t fidx, const char* name,
|
||||
const char* wirep, const bool array, const int arraynum,
|
||||
const bool bussed, const int msb, const int lsb) {
|
||||
assert(m_activityAccumulators.size() > fidx);
|
||||
VerilatedSaifActivityAccumulator& accumulator = *m_activityAccumulators.at(fidx);
|
||||
|
||||
const int bits = ((msb > lsb) ? (msb - lsb) : (lsb - msb)) + 1;
|
||||
|
||||
const std::string hierarchicalName = m_prefixStack.back().first + name;
|
||||
|
||||
if (!Super::declCode(code, hierarchicalName, bits)) return;
|
||||
|
||||
std::string variableName = lastWord(hierarchicalName);
|
||||
m_currentScope->addActivityVar(code, variableName);
|
||||
|
||||
accumulator.declare(code, m_currentScope->path(), std::move(variableName), bits, array,
|
||||
arraynum);
|
||||
}
|
||||
|
||||
void VerilatedSaif::declEvent(const uint32_t code, const uint32_t fidx, const char* name,
|
||||
const int dtypenum, const VerilatedTraceSigDirection,
|
||||
const VerilatedTraceSigKind, const VerilatedTraceSigType,
|
||||
const bool array, const int arraynum) {
|
||||
declare(code, fidx, name, "event", array, arraynum, false, 0, 0);
|
||||
}
|
||||
|
||||
void VerilatedSaif::declBit(const uint32_t code, const uint32_t fidx, const char* name,
|
||||
const int dtypenum, const VerilatedTraceSigDirection,
|
||||
const VerilatedTraceSigKind, const VerilatedTraceSigType,
|
||||
const bool array, const int arraynum) {
|
||||
declare(code, fidx, name, "wire", array, arraynum, false, 0, 0);
|
||||
}
|
||||
void VerilatedSaif::declBus(const uint32_t code, const uint32_t fidx, const char* name,
|
||||
const int dtypenum, const VerilatedTraceSigDirection,
|
||||
const VerilatedTraceSigKind, const VerilatedTraceSigType,
|
||||
const bool array, const int arraynum, const int msb, const int lsb) {
|
||||
declare(code, fidx, name, "wire", array, arraynum, true, msb, lsb);
|
||||
}
|
||||
void VerilatedSaif::declQuad(const uint32_t code, const uint32_t fidx, const char* name,
|
||||
const int dtypenum, const VerilatedTraceSigDirection,
|
||||
const VerilatedTraceSigKind, const VerilatedTraceSigType,
|
||||
const bool array, const int arraynum, const int msb, const int lsb) {
|
||||
declare(code, fidx, name, "wire", array, arraynum, true, msb, lsb);
|
||||
}
|
||||
void VerilatedSaif::declArray(const uint32_t code, const uint32_t fidx, const char* name,
|
||||
const int dtypenum, const VerilatedTraceSigDirection,
|
||||
const VerilatedTraceSigKind, const VerilatedTraceSigType,
|
||||
const bool array, const int arraynum, const int msb, const int lsb) {
|
||||
declare(code, fidx, name, "wire", array, arraynum, true, msb, lsb);
|
||||
}
|
||||
void VerilatedSaif::declDouble(const uint32_t code, const uint32_t fidx, const char* name,
|
||||
const int dtypenum, const VerilatedTraceSigDirection,
|
||||
const VerilatedTraceSigKind, const VerilatedTraceSigType,
|
||||
const bool array, const int arraynum) {
|
||||
declare(code, fidx, name, "real", array, arraynum, false, 63, 0);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
// Get/commit trace buffer
|
||||
|
||||
VerilatedSaif::Buffer* VerilatedSaif::getTraceBuffer(uint32_t fidx) { return new Buffer{*this}; }
|
||||
|
||||
void VerilatedSaif::commitTraceBuffer(VerilatedSaif::Buffer* bufp) { delete bufp; }
|
||||
|
||||
//=============================================================================
|
||||
//=============================================================================
|
||||
//=============================================================================
|
||||
// VerilatedSaifBuffer implementation
|
||||
|
||||
//=============================================================================
|
||||
// emit* trace routines
|
||||
|
||||
// Note: emit* are only ever called from one place (full* in
|
||||
// verilated_trace_imp.h, which is included in this file at the top),
|
||||
// so always inline them.
|
||||
|
||||
VL_ATTR_ALWINLINE
|
||||
void VerilatedSaifBuffer::emitEvent(const uint32_t code) {
|
||||
// NOP
|
||||
}
|
||||
|
||||
VL_ATTR_ALWINLINE
|
||||
void VerilatedSaifBuffer::emitBit(const uint32_t code, const CData newval) {
|
||||
assert(m_owner.m_activityAccumulators.at(m_fidx)->m_activity.count(code)
|
||||
&& "Activity must be declared earlier");
|
||||
VerilatedSaifActivityVar& activity
|
||||
= m_owner.m_activityAccumulators.at(m_fidx)->m_activity.at(code);
|
||||
activity.emitBit(m_owner.currentTime(), newval);
|
||||
}
|
||||
|
||||
VL_ATTR_ALWINLINE
|
||||
void VerilatedSaifBuffer::emitCData(const uint32_t code, const CData newval, const int bits) {
|
||||
assert(m_owner.m_activityAccumulators.at(m_fidx)->m_activity.count(code)
|
||||
&& "Activity must be declared earlier");
|
||||
VerilatedSaifActivityVar& activity
|
||||
= m_owner.m_activityAccumulators.at(m_fidx)->m_activity.at(code);
|
||||
activity.emitData<CData>(m_owner.currentTime(), newval, bits);
|
||||
}
|
||||
|
||||
VL_ATTR_ALWINLINE
|
||||
void VerilatedSaifBuffer::emitSData(const uint32_t code, const SData newval, const int bits) {
|
||||
assert(m_owner.m_activityAccumulators.at(m_fidx)->m_activity.count(code)
|
||||
&& "Activity must be declared earlier");
|
||||
VerilatedSaifActivityVar& activity
|
||||
= m_owner.m_activityAccumulators.at(m_fidx)->m_activity.at(code);
|
||||
activity.emitData<SData>(m_owner.currentTime(), newval, bits);
|
||||
}
|
||||
|
||||
VL_ATTR_ALWINLINE
|
||||
void VerilatedSaifBuffer::emitIData(const uint32_t code, const IData newval, const int bits) {
|
||||
assert(m_owner.m_activityAccumulators.at(m_fidx)->m_activity.count(code)
|
||||
&& "Activity must be declared earlier");
|
||||
VerilatedSaifActivityVar& activity
|
||||
= m_owner.m_activityAccumulators.at(m_fidx)->m_activity.at(code);
|
||||
activity.emitData<IData>(m_owner.currentTime(), newval, bits);
|
||||
}
|
||||
|
||||
VL_ATTR_ALWINLINE
|
||||
void VerilatedSaifBuffer::emitQData(const uint32_t code, const QData newval, const int bits) {
|
||||
assert(m_owner.m_activityAccumulators.at(m_fidx)->m_activity.count(code)
|
||||
&& "Activity must be declared earlier");
|
||||
VerilatedSaifActivityVar& activity
|
||||
= m_owner.m_activityAccumulators.at(m_fidx)->m_activity.at(code);
|
||||
activity.emitData<QData>(m_owner.currentTime(), newval, bits);
|
||||
}
|
||||
|
||||
VL_ATTR_ALWINLINE
|
||||
void VerilatedSaifBuffer::emitWData(const uint32_t code, const WData* newvalp, const int bits) {
|
||||
assert(m_owner.m_activityAccumulators.at(m_fidx)->m_activity.count(code)
|
||||
&& "Activity must be declared earlier");
|
||||
VerilatedSaifActivityVar& activity
|
||||
= m_owner.m_activityAccumulators.at(m_fidx)->m_activity.at(code);
|
||||
activity.emitWData(m_owner.currentTime(), newvalp, bits);
|
||||
}
|
||||
|
||||
VL_ATTR_ALWINLINE
|
||||
void VerilatedSaifBuffer::emitDouble(const uint32_t code, const double newval) {
|
||||
// NOP
|
||||
}
|
||||
|
|
@ -0,0 +1,292 @@
|
|||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//=============================================================================
|
||||
//
|
||||
// Code available from: https://verilator.org
|
||||
//
|
||||
// Copyright 2001-2025 by Wilson Snyder. This program is free software; you
|
||||
// can redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
//
|
||||
//=============================================================================
|
||||
///
|
||||
/// \file
|
||||
/// \brief Verilated tracing in SAIF format header
|
||||
///
|
||||
/// User wrapper code should use this header when creating SAIF traces.
|
||||
///
|
||||
//=============================================================================
|
||||
|
||||
#ifndef VERILATOR_VERILATED_SAIF_C_H_
|
||||
#define VERILATOR_VERILATED_SAIF_C_H_
|
||||
|
||||
#include "verilated.h"
|
||||
#include "verilated_trace.h"
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
class VerilatedSaifBuffer;
|
||||
class VerilatedSaifActivityAccumulator;
|
||||
class VerilatedSaifActivityScope;
|
||||
class VerilatedSaifActivityVar;
|
||||
class VerilatedSaifActivityBit;
|
||||
|
||||
//=============================================================================
|
||||
// VerilatedSaif
|
||||
// Base class to create a Verilator SAIF dump
|
||||
// This is an internally used class - see VerilatedSaifC for what to call from applications
|
||||
|
||||
class VerilatedSaif VL_NOT_FINAL : public VerilatedTrace<VerilatedSaif, VerilatedSaifBuffer> {
|
||||
public:
|
||||
using Super = VerilatedTrace<VerilatedSaif, VerilatedSaifBuffer>;
|
||||
|
||||
private:
|
||||
friend VerilatedSaifBuffer; // Give the buffer access to the private bits
|
||||
|
||||
//=========================================================================
|
||||
// SAIF-specific internals
|
||||
|
||||
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;
|
||||
// Array of declared scopes
|
||||
std::vector<std::unique_ptr<VerilatedSaifActivityScope>> m_scopes{};
|
||||
// Activity accumulators used to store variables statistics over simulation time
|
||||
std::vector<std::unique_ptr<VerilatedSaifActivityAccumulator>> m_activityAccumulators{};
|
||||
// Total time of the currently traced simulation
|
||||
uint64_t m_time = 0;
|
||||
|
||||
// Stack of declared scopes combined names
|
||||
std::vector<std::pair<std::string, VerilatedTracePrefixType>> m_prefixStack{
|
||||
{"", VerilatedTracePrefixType::SCOPE_MODULE}};
|
||||
|
||||
// METHODS
|
||||
VL_ATTR_ALWINLINE uint64_t currentTime() const { return m_time; }
|
||||
|
||||
void initializeSaifFileContents();
|
||||
void finalizeSaifFileContents();
|
||||
void recursivelyPrintScopes(const VerilatedSaifActivityScope& scope);
|
||||
void openInstanceScope(const std::string& instanceName);
|
||||
void closeInstanceScope();
|
||||
void printScopeActivities(const VerilatedSaifActivityScope& scope);
|
||||
bool
|
||||
printScopeActivitiesFromAccumulatorIfPresent(const std::string& absoluteScopePath,
|
||||
VerilatedSaifActivityAccumulator& accumulator,
|
||||
bool anyNetWritten);
|
||||
void openNetScope();
|
||||
void closeNetScope();
|
||||
bool printActivityStats(VerilatedSaifActivityVar& activity, const std::string& activityName,
|
||||
bool anyNetWritten);
|
||||
|
||||
void incrementIndent();
|
||||
void decrementIndent();
|
||||
void printIndent();
|
||||
|
||||
void printStr(const char* str);
|
||||
void printStr(const std::string& str);
|
||||
void writeBuffered(bool force);
|
||||
|
||||
void clearCurrentlyCollectedData();
|
||||
|
||||
void declare(uint32_t code, uint32_t fidx, const char* name, const char* wirep, bool array,
|
||||
int arraynum, bool bussed, int msb, int lsb);
|
||||
|
||||
// CONSTRUCTORS
|
||||
VL_UNCOPYABLE(VerilatedSaif);
|
||||
|
||||
protected:
|
||||
//=========================================================================
|
||||
// Implementation of VerilatedTrace interface
|
||||
|
||||
// Called when the trace moves forward to a new time point
|
||||
void emitTimeChange(uint64_t timeui) override;
|
||||
|
||||
// Hooks called from VerilatedTrace
|
||||
bool preFullDump() override { return isOpen(); }
|
||||
bool preChangeDump() override { return isOpen(); }
|
||||
|
||||
// Trace buffer management
|
||||
Buffer* getTraceBuffer(uint32_t fidx) override;
|
||||
void commitTraceBuffer(Buffer*) override;
|
||||
|
||||
// Configure sub-class
|
||||
void configure(const VerilatedTraceConfig&) override {}
|
||||
|
||||
public:
|
||||
//=========================================================================
|
||||
// External interface to client code
|
||||
|
||||
// CONSTRUCTOR
|
||||
explicit VerilatedSaif(void* filep = nullptr);
|
||||
~VerilatedSaif();
|
||||
|
||||
// METHODS - All must be thread safe
|
||||
// Open the file; call isOpen() to see if errors
|
||||
void open(const char* filename) VL_MT_SAFE_EXCLUDES(m_mutex);
|
||||
// Close the file
|
||||
void close() VL_MT_SAFE_EXCLUDES(m_mutex);
|
||||
// Flush any remaining data to this file
|
||||
void flush() VL_MT_SAFE_EXCLUDES(m_mutex);
|
||||
// Return if file is open
|
||||
bool isOpen() const VL_MT_SAFE { return m_isOpen; }
|
||||
|
||||
//=========================================================================
|
||||
// Internal interface to Verilator generated code
|
||||
|
||||
void pushPrefix(const std::string&, VerilatedTracePrefixType);
|
||||
void popPrefix();
|
||||
|
||||
void declEvent(uint32_t code, uint32_t fidx, const char* name, int dtypenum,
|
||||
VerilatedTraceSigDirection, VerilatedTraceSigKind, VerilatedTraceSigType,
|
||||
bool array, int arraynum);
|
||||
void declBit(uint32_t code, uint32_t fidx, const char* name, int dtypenum,
|
||||
VerilatedTraceSigDirection, VerilatedTraceSigKind, VerilatedTraceSigType,
|
||||
bool array, int arraynum);
|
||||
void declBus(uint32_t code, uint32_t fidx, const char* name, int dtypenum,
|
||||
VerilatedTraceSigDirection, VerilatedTraceSigKind, VerilatedTraceSigType,
|
||||
bool array, int arraynum, int msb, int lsb);
|
||||
void declQuad(uint32_t code, uint32_t fidx, const char* name, int dtypenum,
|
||||
VerilatedTraceSigDirection, VerilatedTraceSigKind, VerilatedTraceSigType,
|
||||
bool array, int arraynum, int msb, int lsb);
|
||||
void declArray(uint32_t code, uint32_t fidx, const char* name, int dtypenum,
|
||||
VerilatedTraceSigDirection, VerilatedTraceSigKind, VerilatedTraceSigType,
|
||||
bool array, int arraynum, int msb, int lsb);
|
||||
void declDouble(uint32_t code, uint32_t fidx, const char* name, int dtypenum,
|
||||
VerilatedTraceSigDirection, VerilatedTraceSigKind, VerilatedTraceSigType,
|
||||
bool array, int arraynum);
|
||||
};
|
||||
|
||||
#ifndef DOXYGEN
|
||||
// Declare specialization here as it's used in VerilatedSaifC just below
|
||||
template <>
|
||||
void VerilatedSaif::Super::dump(uint64_t time);
|
||||
template <>
|
||||
void VerilatedSaif::Super::set_time_unit(const char* unitp);
|
||||
template <>
|
||||
void VerilatedSaif::Super::set_time_unit(const std::string& unit);
|
||||
template <>
|
||||
void VerilatedSaif::Super::set_time_resolution(const char* unitp);
|
||||
template <>
|
||||
void VerilatedSaif::Super::set_time_resolution(const std::string& unit);
|
||||
template <>
|
||||
void VerilatedSaif::Super::dumpvars(int level, const std::string& hier);
|
||||
#endif // DOXYGEN
|
||||
|
||||
//=============================================================================
|
||||
// VerilatedSaifBuffer
|
||||
|
||||
class VerilatedSaifBuffer VL_NOT_FINAL {
|
||||
// Give the trace file and sub-classes access to the private bits
|
||||
friend VerilatedSaif;
|
||||
friend VerilatedSaif::Super;
|
||||
friend VerilatedSaif::Buffer;
|
||||
friend VerilatedSaif::OffloadBuffer;
|
||||
|
||||
VerilatedSaif& m_owner; // Trace file owning this buffer. Required by subclasses.
|
||||
uint32_t m_fidx; // Index of target activity accumulator
|
||||
|
||||
// CONSTRUCTORS
|
||||
explicit VerilatedSaifBuffer(VerilatedSaif& owner)
|
||||
: m_owner{owner}
|
||||
, m_fidx{0} {}
|
||||
explicit VerilatedSaifBuffer(VerilatedSaif& owner, uint32_t fidx)
|
||||
: m_owner{owner}
|
||||
, m_fidx{fidx} {}
|
||||
virtual ~VerilatedSaifBuffer() = default;
|
||||
|
||||
//=========================================================================
|
||||
// Implementation of VerilatedTraceBuffer interface
|
||||
// Implementations of duck-typed methods for VerilatedTraceBuffer. These are
|
||||
// called from only one place (the full* methods), so always inline them.
|
||||
VL_ATTR_ALWINLINE void emitEvent(uint32_t code);
|
||||
VL_ATTR_ALWINLINE void emitBit(uint32_t code, CData newval);
|
||||
VL_ATTR_ALWINLINE void emitCData(uint32_t code, CData newval, int bits);
|
||||
VL_ATTR_ALWINLINE void emitSData(uint32_t code, SData newval, int bits);
|
||||
VL_ATTR_ALWINLINE void emitIData(uint32_t code, IData newval, int bits);
|
||||
VL_ATTR_ALWINLINE void emitQData(uint32_t code, QData newval, int bits);
|
||||
VL_ATTR_ALWINLINE void emitWData(uint32_t code, const WData* newvalp, int bits);
|
||||
VL_ATTR_ALWINLINE void emitDouble(uint32_t code, double newval);
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
// VerilatedSaifC
|
||||
// Class representing a SAIF dump file in C standalone (no SystemC)
|
||||
// simulations. Also derived for use in SystemC simulations.
|
||||
|
||||
class VerilatedSaifC VL_NOT_FINAL : public VerilatedTraceBaseC {
|
||||
VerilatedSaif m_sptrace; // Trace file being created
|
||||
|
||||
// CONSTRUCTORS
|
||||
VL_UNCOPYABLE(VerilatedSaifC);
|
||||
|
||||
public:
|
||||
// Construct the dump. Optional argument is ignored
|
||||
explicit VerilatedSaifC(void* filep = nullptr)
|
||||
: m_sptrace{filep} {}
|
||||
// Destruct, flush, and close the dump
|
||||
virtual ~VerilatedSaifC() { close(); }
|
||||
|
||||
// METHODS - User called
|
||||
|
||||
// Return if file is open
|
||||
bool isOpen() const override VL_MT_SAFE { return m_sptrace.isOpen(); }
|
||||
// Open a new SAIF file
|
||||
// This includes a complete header dump each time it is called,
|
||||
// just as if this object was deleted and reconstructed.
|
||||
virtual void open(const char* filename) VL_MT_SAFE { m_sptrace.open(filename); }
|
||||
|
||||
void rolloverSize(size_t size) VL_MT_SAFE {} // NOP
|
||||
|
||||
// Close dump
|
||||
void close() VL_MT_SAFE {
|
||||
m_sptrace.close();
|
||||
modelConnected(false);
|
||||
}
|
||||
// Flush dump
|
||||
void flush() VL_MT_SAFE { m_sptrace.flush(); }
|
||||
// Write one cycle of dump data
|
||||
// Call with the current context's time just after eval'ed,
|
||||
// e.g. ->dump(contextp->time())
|
||||
void dump(uint64_t timeui) VL_MT_SAFE { m_sptrace.dump(timeui); }
|
||||
// Write one cycle of dump data - backward compatible and to reduce
|
||||
// conversion warnings. It's better to use a uint64_t time instead.
|
||||
void dump(double timestamp) { dump(static_cast<uint64_t>(timestamp)); }
|
||||
void dump(uint32_t timestamp) { dump(static_cast<uint64_t>(timestamp)); }
|
||||
void dump(int timestamp) { dump(static_cast<uint64_t>(timestamp)); }
|
||||
|
||||
// METHODS - Internal/backward compatible
|
||||
// \protectedsection
|
||||
|
||||
// Set time units (s/ms, defaults to ns)
|
||||
// Users should not need to call this, as for Verilated models, these
|
||||
// propagate from the Verilated default timeunit
|
||||
void set_time_unit(const char* unit) VL_MT_SAFE { m_sptrace.set_time_unit(unit); }
|
||||
void set_time_unit(const std::string& unit) VL_MT_SAFE { m_sptrace.set_time_unit(unit); }
|
||||
// Set time resolution (s/ms, defaults to ns)
|
||||
// Users should not need to call this, as for Verilated models, these
|
||||
// propagate from the Verilated default timeprecision
|
||||
void set_time_resolution(const char* unit) VL_MT_SAFE { m_sptrace.set_time_resolution(unit); }
|
||||
void set_time_resolution(const std::string& unit) VL_MT_SAFE {
|
||||
m_sptrace.set_time_resolution(unit);
|
||||
}
|
||||
// Set variables to dump, using $dumpvars format
|
||||
// If level = 0, dump everything and hier is then ignored
|
||||
void dumpvars(int level, const std::string& hier) VL_MT_SAFE {
|
||||
m_sptrace.dumpvars(level, hier);
|
||||
}
|
||||
|
||||
// Internal class access
|
||||
VerilatedSaif* spTrace() { return &m_sptrace; }
|
||||
};
|
||||
|
||||
#endif // guard
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//=============================================================================
|
||||
//
|
||||
// Copyright 2001-2025 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
//
|
||||
//=============================================================================
|
||||
///
|
||||
/// \file
|
||||
/// \brief Verilated tracing in SAIF format for SystemC header
|
||||
///
|
||||
/// User wrapper code should use this header when creating SAIF SystemC traces.
|
||||
///
|
||||
/// This class is not threadsafe, as the SystemC kernel is not threadsafe.
|
||||
///
|
||||
//=============================================================================
|
||||
|
||||
#ifndef VERILATOR_VERILATED_SAIF_SC_H_
|
||||
#define VERILATOR_VERILATED_SAIF_SC_H_
|
||||
|
||||
#include "verilatedos.h"
|
||||
|
||||
#include "verilated_saif_c.h"
|
||||
#include "verilated_sc_trace.h"
|
||||
|
||||
//=============================================================================
|
||||
// VerilatedSaifSc
|
||||
/// Trace file used to create SAIF dump for SystemC version of Verilated models. It's very similar
|
||||
/// to its C version (see the class VerilatedSaifC)
|
||||
|
||||
class VerilatedSaifSc final : VerilatedScTraceBase, public VerilatedSaifC {
|
||||
// CONSTRUCTORS
|
||||
VL_UNCOPYABLE(VerilatedSaifSc);
|
||||
|
||||
public:
|
||||
VerilatedSaifSc() {
|
||||
spTrace()->set_time_unit(VerilatedScTraceBase::getScTimeUnit());
|
||||
spTrace()->set_time_resolution(VerilatedScTraceBase::getScTimeResolution());
|
||||
}
|
||||
|
||||
// METHODS
|
||||
// Override VerilatedSaifC. Must be called after starting simulation.
|
||||
void open(const char* filename) override VL_MT_SAFE {
|
||||
VerilatedScTraceBase::checkScElaborationDone();
|
||||
VerilatedSaifC::open(filename);
|
||||
}
|
||||
|
||||
// METHODS - for SC kernel
|
||||
// Called from SystemC kernel
|
||||
void cycle() override { VerilatedSaifC::dump(sc_core::sc_time_stamp().to_double()); }
|
||||
};
|
||||
|
||||
#endif // Guard
|
||||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -184,8 +184,11 @@ public:
|
|||
// Word at given 'wordIndex'
|
||||
uint64_t word(size_t wordIndex) const { return m_flags[wordIndex]; }
|
||||
|
||||
// Set specified flag to given value
|
||||
void set(size_t index, bool value) {
|
||||
// Set specified word to given value
|
||||
void setWord(size_t wordIndex, uint64_t value) { m_flags[wordIndex] = value; }
|
||||
|
||||
// Set specified bit to given value
|
||||
void setBit(size_t index, bool value) {
|
||||
uint64_t& w = m_flags[index / 64];
|
||||
const size_t bitIndex = index % 64;
|
||||
w &= ~(1ULL << bitIndex);
|
||||
|
|
@ -618,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];
|
||||
}
|
||||
|
|
@ -921,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
|
||||
|
|
@ -1256,6 +1264,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_Key> {};
|
||||
|
||||
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 {
|
||||
|
|
@ -1586,6 +1597,9 @@ std::string VL_TO_STRING(const VlUnpacked<T_Value, N_Depth>& obj) {
|
|||
return obj.to_string();
|
||||
}
|
||||
|
||||
template <typename T, int N>
|
||||
struct VlContainsCustomStruct<VlUnpacked<T, N>> : VlContainsCustomStruct<T> {};
|
||||
|
||||
//===================================================================
|
||||
// Helper to apply the given indices to a target expression
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)) {
|
||||
|
|
@ -421,7 +421,7 @@ public:
|
|||
const char* fullname() const override {
|
||||
static thread_local std::string t_out;
|
||||
t_out = std::string{scopep()->name()} + "." + name();
|
||||
for (auto idx : index()) { t_out += "[" + std::to_string(idx) + "]"; }
|
||||
for (auto idx : index()) t_out += "[" + std::to_string(idx) + "]";
|
||||
return t_out.c_str();
|
||||
}
|
||||
void* prevDatap() const { return m_prevDatap; }
|
||||
|
|
@ -873,6 +873,7 @@ class VerilatedVpiImp final {
|
|||
// All only medium-speed, so use singleton function
|
||||
// Callbacks that are past or at current timestamp
|
||||
std::array<VpioCbList, CB_ENUM_MAX_VALUE> m_cbCurrentLists;
|
||||
VpioCbList m_cbCallList; // List of callbacks currently being called by callCbs
|
||||
VpioFutureCbs m_futureCbs; // Time based callbacks for future timestamps
|
||||
VpioFutureCbs m_nextCbs; // cbNextSimTime callbacks
|
||||
std::list<VerilatedVpiPutHolder> m_inertialPuts; // Pending vpi puts due to vpiInertialDelay
|
||||
|
|
@ -925,7 +926,13 @@ public:
|
|||
for (auto& ir : s().m_cbCurrentLists[reason]) {
|
||||
if (ir.id() == id) {
|
||||
ir.invalidate();
|
||||
return; // Once found, it won't also be in m_futureCbs
|
||||
return; // Once found, it won't also be in m_cbCallList, m_futureCbs, or m_nextCbs
|
||||
}
|
||||
}
|
||||
for (auto& ir : s().m_cbCallList) {
|
||||
if (ir.id() == id) {
|
||||
ir.invalidate();
|
||||
return; // Once found, it won't also be in m_futureCbs or m_nextCbs
|
||||
}
|
||||
}
|
||||
{ // Remove from cbFuture queue
|
||||
|
|
@ -985,10 +992,9 @@ public:
|
|||
moveFutureCbs();
|
||||
if (s().m_cbCurrentLists[reason].empty()) return false;
|
||||
// Iterate on old list, making new list empty, to prevent looping over newly added elements
|
||||
VpioCbList cbObjList;
|
||||
std::swap(s().m_cbCurrentLists[reason], cbObjList);
|
||||
std::swap(s().m_cbCurrentLists[reason], s().m_cbCallList);
|
||||
bool called = false;
|
||||
for (VerilatedVpiCbHolder& ihor : cbObjList) {
|
||||
for (VerilatedVpiCbHolder& ihor : s().m_cbCallList) {
|
||||
// cbReasonRemove sets to nullptr, so we know on removal the old end() will still exist
|
||||
if (VL_LIKELY(!ihor.invalid())) { // Not deleted earlier
|
||||
VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: reason_callback reason=%d id=%" PRId64 "\n",
|
||||
|
|
@ -998,6 +1004,7 @@ public:
|
|||
called = true;
|
||||
}
|
||||
}
|
||||
s().m_cbCallList.clear();
|
||||
return called;
|
||||
}
|
||||
static bool callValueCbs() VL_MT_UNSAFE_ONE {
|
||||
|
|
@ -2567,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;
|
||||
|
|
@ -2781,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,
|
||||
|
|
@ -2973,7 +2980,6 @@ 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++) {
|
||||
dst[i * 2].aval = static_cast<QData>(src[index]);
|
||||
|
|
@ -3095,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;
|
||||
|
|
@ -3112,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) {
|
||||
|
|
@ -3303,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);
|
||||
|
|
@ -3321,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,
|
||||
|
|
@ -3337,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) {
|
||||
|
|
@ -3485,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);
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,31 @@
|
|||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Code available from: https://verilator.org
|
||||
//
|
||||
// Copyright 2009-2025 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
//
|
||||
//=========================================================================
|
||||
///
|
||||
/// \file
|
||||
/// \brief Verilated user tf_routines
|
||||
///
|
||||
/// This file contains routines to interface user VPI/PLI C++ code with
|
||||
/// Verilator. Traditionally the veriuser.h code has been used for only
|
||||
/// tf_ routines, which verilator does not implement, so this file is
|
||||
/// empty.
|
||||
///
|
||||
/// User code relying on tf_ routines should migrate to VPI (vpi_user.h) or
|
||||
/// DPI (svdpi.h) routines.
|
||||
///
|
||||
/// This file is only provided for backwards compatibility for applications
|
||||
/// which include veriuser.h even though they use only vpi_ or dpi_
|
||||
/// routines.
|
||||
///
|
||||
//=========================================================================
|
||||
|
||||
// Intentionally empty, see above.
|
||||
|
|
@ -90,7 +90,7 @@ def process():
|
|||
|
||||
print()
|
||||
print("You may now want to clean up spelling, and commit:")
|
||||
print(" (cd docs ; make spelling)")
|
||||
print(" (cd docs ; make spelling | grep -vi 'writing output')")
|
||||
print(" git ci -am 'Commentary: Changes update'")
|
||||
print()
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,241 @@
|
|||
#!/usr/bin/env python3
|
||||
# pylint: disable=C0114,C0115,C0116,R0902,R0903,R0912,R0915,W0719,W0718
|
||||
######################################################################
|
||||
#
|
||||
# Copyright 2025 by Wilson Snyder. This program is free software; you
|
||||
# can redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
import argparse
|
||||
import re
|
||||
|
||||
SUCCESS_CODE = 0
|
||||
FAILURE_CODE = 1
|
||||
INSTANCE_TYPE = "INSTANCE"
|
||||
NET_LIST_TYPE = "NET"
|
||||
SIGNAL_TYPE = "SIGNAL"
|
||||
EOF_ERROR = "Unexpected EOF"
|
||||
|
||||
|
||||
def saif_assert(expression, message):
|
||||
if not expression:
|
||||
raise Exception(message)
|
||||
|
||||
|
||||
def saif_error(message):
|
||||
raise Exception(message)
|
||||
|
||||
|
||||
class SAIFSignalBit:
|
||||
name: str
|
||||
high_time: int
|
||||
low_time: int
|
||||
transitions: int
|
||||
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.high_time = 0
|
||||
self.low_time = 0
|
||||
self.transitions = 0
|
||||
|
||||
|
||||
class SAIFInstance:
|
||||
|
||||
def __init__(self, scope_name):
|
||||
self.scope_name = scope_name
|
||||
self.parent_instance = None
|
||||
self.nets = {}
|
||||
self.child_instances = {}
|
||||
|
||||
|
||||
class SAIFToken:
|
||||
|
||||
def __init__(self, token):
|
||||
self.token = token
|
||||
self.type = ''
|
||||
self.value = ''
|
||||
|
||||
|
||||
class SAIFParser:
|
||||
|
||||
def __init__(self):
|
||||
self.token_stack = []
|
||||
# For parsing simplicity
|
||||
self.token_stack.append(SAIFToken('saif_root'))
|
||||
self.current_instance = None
|
||||
self.has_saifile_header = False
|
||||
self.direction = ''
|
||||
self.saif_version = ''
|
||||
self.top_instances = {}
|
||||
self.duration = 0
|
||||
self.divider = ''
|
||||
self.timescale = ''
|
||||
|
||||
def parse(self, saif_filename):
|
||||
file_contents = ''
|
||||
with open(saif_filename, 'r', encoding="utf8") as saif_file:
|
||||
content = saif_file.readlines()
|
||||
filtered_lines = [line for line in content if not line.strip().startswith('//')]
|
||||
file_contents = ''.join(filtered_lines)
|
||||
tokens = file_contents.replace('(', ' ( ').replace(')', ' ) ').split()
|
||||
num_of_tokens = len(tokens)
|
||||
index = 0
|
||||
while index < num_of_tokens:
|
||||
token = tokens[index]
|
||||
index += 1
|
||||
if token == '(':
|
||||
self.token_stack.append(SAIFToken(token))
|
||||
self.token_stack[-1].type = self.token_stack[-2].type
|
||||
self.token_stack[-1].value = self.token_stack[-2].value
|
||||
continue
|
||||
if token == ')':
|
||||
if self.token_stack[-1].type == INSTANCE_TYPE:
|
||||
self.current_instance = self.current_instance.parent_instance
|
||||
self.token_stack.pop()
|
||||
continue
|
||||
if re.match(r'SAIFILE', token):
|
||||
self.has_saifile_header = True
|
||||
continue
|
||||
if re.match(r'DIRECTION', token):
|
||||
saif_assert(index < num_of_tokens, EOF_ERROR)
|
||||
self.direction = tokens[index].replace('\"', '')
|
||||
index += 1
|
||||
continue
|
||||
if re.match(r'SAIFVERSION', token):
|
||||
saif_assert(index < num_of_tokens, EOF_ERROR)
|
||||
self.saif_version = tokens[index].replace('\"', '')
|
||||
index += 1
|
||||
continue
|
||||
if re.match(r'DESIGN|DATE|VENDOR|PROGRAM_NAME|VERSION', token):
|
||||
# NOP, only skip value
|
||||
saif_assert(index < num_of_tokens, EOF_ERROR)
|
||||
index += 1
|
||||
continue
|
||||
if re.match(r'DIVIDER', token):
|
||||
saif_assert(index < num_of_tokens, EOF_ERROR)
|
||||
self.divider = tokens[index]
|
||||
index += 1
|
||||
continue
|
||||
if re.match(r'TIMESCALE', token):
|
||||
saif_assert(index < num_of_tokens, EOF_ERROR)
|
||||
self.timescale = tokens[index]
|
||||
index += 1
|
||||
continue
|
||||
if re.match(r'DURATION', token):
|
||||
saif_assert(index < num_of_tokens, EOF_ERROR)
|
||||
self.duration = tokens[index]
|
||||
index += 1
|
||||
continue
|
||||
if re.match(r'INSTANCE', token):
|
||||
saif_assert(index < num_of_tokens, EOF_ERROR)
|
||||
instance_name = tokens[index]
|
||||
index += 1
|
||||
self.token_stack[-1].type = INSTANCE_TYPE
|
||||
self.token_stack[-1].value = instance_name
|
||||
instance = SAIFInstance(instance_name)
|
||||
if self.current_instance is None:
|
||||
self.top_instances[instance_name] = instance
|
||||
else:
|
||||
self.current_instance.child_instances[instance_name] = instance
|
||||
instance.parent_instance = self.current_instance
|
||||
self.current_instance = instance
|
||||
continue
|
||||
if re.match(r'NET', token):
|
||||
self.token_stack[-1].type = NET_LIST_TYPE
|
||||
continue
|
||||
if re.match(r'T1', token):
|
||||
net_name = self.token_stack[-1].value
|
||||
saif_assert(index < num_of_tokens, EOF_ERROR)
|
||||
self.current_instance.nets[net_name].high_time = tokens[index]
|
||||
index += 1
|
||||
continue
|
||||
if re.match(r'T0', token):
|
||||
net_name = self.token_stack[-1].value
|
||||
saif_assert(index < num_of_tokens, EOF_ERROR)
|
||||
self.current_instance.nets[net_name].low_time = tokens[index]
|
||||
index += 1
|
||||
continue
|
||||
if re.match(r'TC', token):
|
||||
net_name = self.token_stack[-1].value
|
||||
saif_assert(index < num_of_tokens, EOF_ERROR)
|
||||
self.current_instance.nets[net_name].transitions = tokens[index]
|
||||
index += 1
|
||||
continue
|
||||
if re.match(r'TZ|TX|TB|TG|IG|IK', token):
|
||||
# NOP, only skip value
|
||||
index += 1
|
||||
continue
|
||||
if self.token_stack[-2].type == NET_LIST_TYPE:
|
||||
self.token_stack[-1].type = SIGNAL_TYPE
|
||||
self.token_stack[-1].value = token
|
||||
self.current_instance.nets[token] = SAIFSignalBit(token)
|
||||
saif_assert(self.has_saifile_header, "SAIF file doesn't contain a SAIFILE keyword")
|
||||
saif_assert(self.direction == "backward",
|
||||
f"SAIF file doesn't have a valid/compatible direction: {self.direction}")
|
||||
saif_assert(self.saif_version == "2.0",
|
||||
f"SAIF file doesn't have a valid/compatible version: {self.saif_version}")
|
||||
# Only 'saif_root' token should be left
|
||||
saif_assert(len(self.token_stack) == 1, "Incorrect nesting of scopes")
|
||||
|
||||
|
||||
def compare_saif_instances(first: SAIFInstance, second: SAIFInstance):
|
||||
if len(first.nets) != len(second.nets):
|
||||
saif_error(f"Number of nets doesn't match in {first.scope_name}: "
|
||||
f"{len(first.nets)} != {len(second.nets)}")
|
||||
for signal_name, saif_signal in first.nets.items():
|
||||
if signal_name not in second.nets:
|
||||
saif_error(f"Signal {signal_name} doesn't exist in the second object\n")
|
||||
other_signal = second.nets[signal_name]
|
||||
if (saif_signal.high_time != other_signal.high_time
|
||||
or saif_signal.low_time != other_signal.low_time
|
||||
or saif_signal.transitions != other_signal.transitions):
|
||||
saif_error("Incompatible signal bit parameters in "
|
||||
f"{signal_name}\n")
|
||||
if len(first.child_instances) != len(second.child_instances):
|
||||
saif_error(f"Number of child instances doesn't match in {first.scope_name}: "
|
||||
f"{len(first.child_instances)} != {len(second.child_instances)}")
|
||||
for instance_name, instance in first.child_instances.items():
|
||||
if instance_name not in second.child_instances:
|
||||
saif_error(f"Instance {instance_name} doesn't exist in the second object\n")
|
||||
compare_saif_instances(instance, second.child_instances[instance_name])
|
||||
|
||||
|
||||
def compare_saif_contents(first_file: str, second_file: str):
|
||||
"""Test if second SAIF file has the same values as the first"""
|
||||
first_saif = SAIFParser()
|
||||
first_saif.parse(first_file)
|
||||
second_saif = SAIFParser()
|
||||
second_saif.parse(second_file)
|
||||
if first_saif.duration != second_saif.duration:
|
||||
saif_error("Duration of trace doesn't match: "
|
||||
f"{first_saif.duration} != {second_saif.duration}")
|
||||
if first_saif.divider != second_saif.divider:
|
||||
saif_error(f"Dividers don't match: {first_saif.divider} != {second_saif.divider}")
|
||||
if first_saif.timescale != second_saif.timescale:
|
||||
saif_error(f"Timescale doesn't match: {first_saif.timescale} != {second_saif.timescale}")
|
||||
if len(first_saif.top_instances) != len(second_saif.top_instances):
|
||||
saif_error("Number of top instances doesn't match: "
|
||||
f"{len(first_saif.top_instances)} != {len(second_saif.top_instances)}")
|
||||
for top_instance_name, top_instance in first_saif.top_instances.items():
|
||||
if top_instance_name not in second_saif.top_instances:
|
||||
saif_error(f"Top instance {top_instance_name} missing in other SAIF")
|
||||
compare_saif_instances(top_instance, second_saif.top_instances[top_instance_name])
|
||||
return SUCCESS_CODE
|
||||
|
||||
|
||||
parser = argparse.ArgumentParser(allow_abbrev=False,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
description="""verilator_saif_diff checks if two SAIF files are logically-identical. It returns first encountered difference as output.
|
||||
Run as:
|
||||
cd $VERILATOR_ROOT
|
||||
nodist/code_coverage --first example.saif --second other.saif""")
|
||||
parser.add_argument('--first', action='store', help='First SAIF file')
|
||||
parser.add_argument('--second', action='store', help='Second SAIF file')
|
||||
parser.set_defaults(stop=True)
|
||||
args = parser.parse_args()
|
||||
try:
|
||||
compare_saif_contents(args.first, args.second)
|
||||
except Exception as error:
|
||||
print(error)
|
||||
|
|
@ -85,6 +85,7 @@ set(HEADERS
|
|||
V3EmitCMain.h
|
||||
V3EmitCMake.h
|
||||
V3EmitMk.h
|
||||
V3EmitMkJson.h
|
||||
V3EmitV.h
|
||||
V3EmitXml.h
|
||||
V3Error.h
|
||||
|
|
@ -177,6 +178,7 @@ set(HEADERS
|
|||
V3Trace.h
|
||||
V3TraceDecl.h
|
||||
V3Tristate.h
|
||||
V3Udp.h
|
||||
V3Undriven.h
|
||||
V3UniqueNames.h
|
||||
V3Unknown.h
|
||||
|
|
@ -246,6 +248,7 @@ set(COMMON_SOURCES
|
|||
V3EmitCPch.cpp
|
||||
V3EmitCSyms.cpp
|
||||
V3EmitMk.cpp
|
||||
V3EmitMkJson.cpp
|
||||
V3EmitV.cpp
|
||||
V3EmitXml.cpp
|
||||
V3Error.cpp
|
||||
|
|
@ -324,6 +327,7 @@ set(COMMON_SOURCES
|
|||
V3TraceDecl.cpp
|
||||
V3Tristate.cpp
|
||||
V3TSP.cpp
|
||||
V3Udp.cpp
|
||||
V3Undriven.cpp
|
||||
V3Unknown.cpp
|
||||
V3Unroll.cpp
|
||||
|
|
|
|||
|
|
@ -253,6 +253,7 @@ RAW_OBJS_PCH_ASTNOMT = \
|
|||
V3EmitCModel.o \
|
||||
V3EmitCSyms.o \
|
||||
V3EmitMk.o \
|
||||
V3EmitMkJson.o \
|
||||
V3EmitXml.o \
|
||||
V3ExecGraph.o \
|
||||
V3Expand.o \
|
||||
|
|
@ -310,6 +311,7 @@ RAW_OBJS_PCH_ASTNOMT = \
|
|||
V3Trace.o \
|
||||
V3TraceDecl.o \
|
||||
V3Tristate.o \
|
||||
V3Udp.o \
|
||||
V3Undriven.o \
|
||||
V3Unknown.o \
|
||||
V3Unroll.o \
|
||||
|
|
|
|||
|
|
@ -239,7 +239,7 @@ public:
|
|||
|
||||
// Make a new AstActive sensitive to the given sentree and return it
|
||||
AstActive* makeActive(FileLine* const fl, AstSenTree* const senTreep) {
|
||||
auto* const activep = new AstActive{fl, "", senTreep};
|
||||
AstActive* const activep = new AstActive{fl, "", senTreep};
|
||||
activep->sensesStorep(activep->sensesp());
|
||||
addActive(activep);
|
||||
return activep;
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -572,8 +572,8 @@ class ActiveVisitor final : public VNVisitor {
|
|||
m_clockedProcess = true;
|
||||
if (nodep->edgeType() != VEdgeType::ET_CHANGED) m_allChanged = false;
|
||||
|
||||
if (const auto* const dtypep = nodep->sensp()->dtypep()) {
|
||||
if (const auto* const basicp = dtypep->basicp()) {
|
||||
if (const AstNodeDType* const dtypep = nodep->sensp()->dtypep()) {
|
||||
if (const AstBasicDType* const basicp = dtypep->basicp()) {
|
||||
if (basicp->isEvent()) nodep->edgeType(VEdgeType::ET_EVENT);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -143,7 +143,7 @@ class AssertVisitor final : public VNVisitor {
|
|||
}
|
||||
}
|
||||
AstSampled* newSampledExpr(AstNodeExpr* nodep) {
|
||||
const auto sampledp = new AstSampled{nodep->fileline(), nodep};
|
||||
AstSampled* const sampledp = new AstSampled{nodep->fileline(), nodep};
|
||||
sampledp->dtypeFrom(nodep);
|
||||
return sampledp;
|
||||
}
|
||||
|
|
@ -153,7 +153,7 @@ class AssertVisitor final : public VNVisitor {
|
|||
nodep->findUInt64DType()};
|
||||
v3Global.rootp()->dollarUnitPkgAddp()->addStmtsp(m_monitorNumVarp);
|
||||
}
|
||||
const auto varrefp = new AstVarRef{nodep->fileline(), m_monitorNumVarp, access};
|
||||
AstVarRef* const varrefp = new AstVarRef{nodep->fileline(), m_monitorNumVarp, access};
|
||||
varrefp->classOrPackagep(v3Global.rootp()->dollarUnitPkgAddp());
|
||||
return varrefp;
|
||||
}
|
||||
|
|
@ -163,7 +163,7 @@ class AssertVisitor final : public VNVisitor {
|
|||
nodep->findBitDType()};
|
||||
v3Global.rootp()->dollarUnitPkgAddp()->addStmtsp(m_monitorOffVarp);
|
||||
}
|
||||
const auto varrefp = new AstVarRef{nodep->fileline(), m_monitorOffVarp, access};
|
||||
AstVarRef* const varrefp = new AstVarRef{nodep->fileline(), m_monitorOffVarp, access};
|
||||
varrefp->classOrPackagep(v3Global.rootp()->dollarUnitPkgAddp());
|
||||
return varrefp;
|
||||
}
|
||||
|
|
@ -528,7 +528,7 @@ class AssertVisitor final : public VNVisitor {
|
|||
replaceDisplay(nodep, "%%Fatal");
|
||||
} else if (nodep->displayType() == VDisplayType::DT_MONITOR) {
|
||||
nodep->displayType(VDisplayType::DT_DISPLAY);
|
||||
const auto fl = nodep->fileline();
|
||||
FileLine* const fl = nodep->fileline();
|
||||
AstNode* monExprsp = nodep->fmtp()->exprsp();
|
||||
AstSenItem* monSenItemsp = nullptr;
|
||||
while (monExprsp) {
|
||||
|
|
@ -548,8 +548,8 @@ class AssertVisitor final : public VNVisitor {
|
|||
AstSenTree* const monSenTree = new AstSenTree{fl, monSenItemsp};
|
||||
const auto monNum = ++m_monitorNum;
|
||||
// Where $monitor was we do "__VmonitorNum = N;"
|
||||
const auto newsetp = new AstAssign{fl, newMonitorNumVarRefp(nodep, VAccess::WRITE),
|
||||
new AstConst{fl, monNum}};
|
||||
AstAssign* const newsetp = new AstAssign{
|
||||
fl, newMonitorNumVarRefp(nodep, VAccess::WRITE), new AstConst{fl, monNum}};
|
||||
nodep->replaceWith(newsetp);
|
||||
// Add "always_comb if (__VmonitorOn && __VmonitorNum==N) $display(...);"
|
||||
AstNode* const stmtsp = nodep;
|
||||
|
|
@ -566,14 +566,14 @@ class AssertVisitor final : public VNVisitor {
|
|||
} else if (nodep->displayType() == VDisplayType::DT_STROBE) {
|
||||
nodep->displayType(VDisplayType::DT_DISPLAY);
|
||||
// Need one-shot
|
||||
const auto fl = nodep->fileline();
|
||||
const auto varp
|
||||
FileLine* const fl = nodep->fileline();
|
||||
AstVar* const varp
|
||||
= new AstVar{fl, VVarType::MODULETEMP, "__Vstrobe" + cvtToStr(m_modStrobeNum++),
|
||||
nodep->findBitDType()};
|
||||
m_modp->addStmtsp(varp);
|
||||
// Where $strobe was we do "__Vstrobe = '1;"
|
||||
const auto newsetp = new AstAssign{fl, new AstVarRef{fl, varp, VAccess::WRITE},
|
||||
new AstConst{fl, AstConst::BitTrue{}}};
|
||||
AstAssign* const newsetp = new AstAssign{fl, new AstVarRef{fl, varp, VAccess::WRITE},
|
||||
new AstConst{fl, AstConst::BitTrue{}}};
|
||||
nodep->replaceWith(newsetp);
|
||||
// Add "always_comb if (__Vstrobe) begin $display(...); __Vstrobe = '0; end"
|
||||
AstNode* const stmtsp = nodep;
|
||||
|
|
@ -587,7 +587,7 @@ class AssertVisitor final : public VNVisitor {
|
|||
}
|
||||
}
|
||||
void visit(AstMonitorOff* nodep) override {
|
||||
const auto newp
|
||||
AstAssign* const newp
|
||||
= new AstAssign{nodep->fileline(), newMonitorOffVarRefp(nodep, VAccess::WRITE),
|
||||
new AstConst{nodep->fileline(), AstConst::BitTrue{}, nodep->off()}};
|
||||
nodep->replaceWith(newp);
|
||||
|
|
|
|||
|
|
@ -95,10 +95,10 @@ private:
|
|||
if (const AstVarRef* varrefp = VN_CAST(nodep, VarRef)) {
|
||||
if (varp == varrefp->varp()) nodep->replaceWith(exprp->cloneTree(false));
|
||||
}
|
||||
replaceVarRefsWithExprRecurse(nodep->op1p(), varp, exprp);
|
||||
replaceVarRefsWithExprRecurse(nodep->op2p(), varp, exprp);
|
||||
replaceVarRefsWithExprRecurse(nodep->op3p(), varp, exprp);
|
||||
replaceVarRefsWithExprRecurse(nodep->op4p(), varp, exprp);
|
||||
if (AstNode* const refp = nodep->op1p()) replaceVarRefsWithExprRecurse(refp, varp, exprp);
|
||||
if (AstNode* const refp = nodep->op2p()) replaceVarRefsWithExprRecurse(refp, varp, exprp);
|
||||
if (AstNode* const refp = nodep->op3p()) replaceVarRefsWithExprRecurse(refp, varp, exprp);
|
||||
if (AstNode* const refp = nodep->op4p()) replaceVarRefsWithExprRecurse(refp, varp, exprp);
|
||||
}
|
||||
AstPropSpec* substitutePropertyCall(AstPropSpec* nodep) {
|
||||
if (AstFuncRef* const funcrefp = VN_CAST(nodep->propp(), FuncRef)) {
|
||||
|
|
@ -295,7 +295,7 @@ private:
|
|||
popp->makeStmt()});
|
||||
}
|
||||
} else {
|
||||
nodep->v3fatal("Invalid direction");
|
||||
nodep->v3fatalSrc("Invalid direction");
|
||||
}
|
||||
VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
//######################################################################
|
||||
|
|
@ -228,7 +230,7 @@ string AstNode::vpiName(const string& namein) {
|
|||
// we change that identifier to an escaped identifier, wrapping it with '\' and ' '
|
||||
// as specified in LRM 23.6
|
||||
string name = namein;
|
||||
if (0 == namein.substr(0, 7).compare("__SYM__")) { name = namein.substr(7); }
|
||||
if (0 == namein.substr(0, 7).compare("__SYM__")) name = namein.substr(7);
|
||||
string pretty;
|
||||
pretty.reserve(name.length());
|
||||
bool inEscapedIdent = false;
|
||||
|
|
@ -1340,7 +1342,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 +1387,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 +1396,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 +1410,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";
|
||||
|
|
|
|||
|
|
@ -1686,6 +1686,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; }
|
||||
};
|
||||
|
|
@ -2359,6 +2360,7 @@ public:
|
|||
AstNodeDType* findBitDType() const { return findBasicDType(VBasicDTypeKwd::LOGIC); }
|
||||
AstNodeDType* findDoubleDType() const { return findBasicDType(VBasicDTypeKwd::DOUBLE); }
|
||||
AstNodeDType* findStringDType() const { return findBasicDType(VBasicDTypeKwd::STRING); }
|
||||
AstNodeDType* findSigned8DType() const { return findBasicDType(VBasicDTypeKwd::BYTE); }
|
||||
AstNodeDType* findSigned32DType() const { return findBasicDType(VBasicDTypeKwd::INTEGER); }
|
||||
AstNodeDType* findUInt32DType() const { return findBasicDType(VBasicDTypeKwd::UINT32); }
|
||||
AstNodeDType* findUInt64DType() const { return findBasicDType(VBasicDTypeKwd::UINT64); }
|
||||
|
|
@ -2485,6 +2487,8 @@ public:
|
|||
virtual bool isGateOptimizable() const { return !isTimingControl(); }
|
||||
// GateDedupable is a slightly larger superset of GateOptimzable (eg, AstNodeIf)
|
||||
virtual bool isGateDedupable() const { return isGateOptimizable(); }
|
||||
// Whether the node can be used in expression coverage
|
||||
virtual bool isExprCoverageEligible() const { return isGateDedupable(); }
|
||||
// Else creates output or exits, etc, not unconsumed
|
||||
virtual bool isOutputter() { return false; }
|
||||
// Else a AstTime etc which output can't be predicted from input
|
||||
|
|
|
|||
|
|
@ -189,8 +189,8 @@ bool AstVarRef::sameNode(const AstVarRef* samep) const {
|
|||
return (varScopep() == samep->varScopep() && access() == samep->access());
|
||||
} else {
|
||||
return (selfPointer() == samep->selfPointer()
|
||||
&& classOrPackagep() == samep->classOrPackagep()
|
||||
&& varp()->name() == samep->varp()->name() && access() == samep->access());
|
||||
&& classOrPackagep() == samep->classOrPackagep() && access() == samep->access()
|
||||
&& (varp() && samep->varp() && varp()->name() == samep->varp()->name()));
|
||||
}
|
||||
}
|
||||
bool AstVarRef::sameNoLvalue(AstVarRef* samep) const {
|
||||
|
|
|
|||
|
|
@ -50,7 +50,8 @@ protected:
|
|||
|
||||
private:
|
||||
// METHODS
|
||||
const AstNodeDType* skipRefIterp(bool skipConst, bool skipEnum) const VL_MT_STABLE;
|
||||
const AstNodeDType* skipRefIterp(bool skipConst, bool skipEnum,
|
||||
bool assertOn = true) const VL_MT_STABLE;
|
||||
|
||||
protected:
|
||||
// METHODS
|
||||
|
|
@ -78,6 +79,15 @@ public:
|
|||
return const_cast<AstNodeDType*>(
|
||||
static_cast<const AstNodeDType*>(this)->skipRefIterp(true, true));
|
||||
}
|
||||
// (Slow) Recurse over MemberDType|ParamTypeDType|RefDType|ConstDType|EnumDType to other type,
|
||||
// Returns null if not resolved
|
||||
const AstNodeDType* skipRefOrNullp() const VL_MT_STABLE {
|
||||
return skipRefIterp(true, true, false);
|
||||
}
|
||||
AstNodeDType* skipRefOrNullp() VL_MT_STABLE {
|
||||
return const_cast<AstNodeDType*>(
|
||||
static_cast<const AstNodeDType*>(this)->skipRefIterp(true, true, false));
|
||||
}
|
||||
// (Slow) Recurse over MemberDType|ParamTypeDType|RefDType|EnumDType to ConstDType
|
||||
const AstNodeDType* skipRefToConstp() const { return skipRefIterp(false, true); }
|
||||
AstNodeDType* skipRefToConstp() {
|
||||
|
|
@ -110,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;
|
||||
|
|
@ -155,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");
|
||||
|
|
@ -522,7 +524,7 @@ public:
|
|||
AstCDType(FileLine* fl, const string& name)
|
||||
: ASTGEN_SUPER_CDType(fl)
|
||||
, m_name{name} {
|
||||
this->dtypep(this);
|
||||
dtypep(this);
|
||||
}
|
||||
|
||||
public:
|
||||
|
|
@ -562,8 +564,8 @@ public:
|
|||
AstClassRefDType(FileLine* fl, AstClass* classp, AstPin* paramsp)
|
||||
: ASTGEN_SUPER_ClassRefDType(fl)
|
||||
, m_classp{classp} {
|
||||
this->dtypep(this);
|
||||
this->addParamsp(paramsp);
|
||||
dtypep(this);
|
||||
addParamsp(paramsp);
|
||||
}
|
||||
ASTGEN_MEMBERS_AstClassRefDType;
|
||||
// METHODS
|
||||
|
|
@ -571,7 +573,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;
|
||||
|
|
@ -1065,7 +1071,7 @@ class AstQueueDType final : public AstNodeDType {
|
|||
public:
|
||||
AstQueueDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp, AstNodeExpr* boundp)
|
||||
: ASTGEN_SUPER_QueueDType(fl) {
|
||||
this->childDTypep(dtp);
|
||||
childDTypep(dtp);
|
||||
this->boundp(boundp);
|
||||
refDTypep(nullptr);
|
||||
dtypep(nullptr); // V3Width will resolve
|
||||
|
|
@ -1125,7 +1131,7 @@ public:
|
|||
AstRefDType(FileLine* fl, const string& name, AstNodeExpr* classOrPackagep, AstPin* paramsp)
|
||||
: ASTGEN_SUPER_RefDType(fl)
|
||||
, m_name{name} {
|
||||
this->classOrPackageOpp(classOrPackagep);
|
||||
classOrPackageOpp(classOrPackagep);
|
||||
addParamsp(paramsp);
|
||||
}
|
||||
class FlagTypeOfExpr {}; // type(expr) for parser only
|
||||
|
|
@ -1342,7 +1348,7 @@ class AstUnpackArrayDType final : public AstNodeArrayDType {
|
|||
public:
|
||||
AstUnpackArrayDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp, AstRange* rangep)
|
||||
: ASTGEN_SUPER_UnpackArrayDType(fl) {
|
||||
this->childDTypep(dtp); // Only for parser
|
||||
childDTypep(dtp); // Only for parser
|
||||
this->rangep(rangep);
|
||||
refDTypep(nullptr);
|
||||
dtypep(nullptr); // V3Width will resolve
|
||||
|
|
@ -1382,13 +1388,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
|
||||
|
|
|
|||
|
|
@ -243,12 +243,12 @@ protected:
|
|||
AstNodeFTaskRef(VNType t, FileLine* fl, AstNode* namep, AstNodeExpr* pinsp)
|
||||
: AstNodeExpr{t, fl} {
|
||||
this->namep(namep);
|
||||
this->addPinsp(pinsp);
|
||||
addPinsp(pinsp);
|
||||
}
|
||||
AstNodeFTaskRef(VNType t, FileLine* fl, const string& name, AstNodeExpr* pinsp)
|
||||
: AstNodeExpr{t, fl}
|
||||
, m_name{name} {
|
||||
this->addPinsp(pinsp);
|
||||
addPinsp(pinsp);
|
||||
}
|
||||
|
||||
public:
|
||||
|
|
@ -542,6 +542,7 @@ public:
|
|||
// Know no children, and hot function, so skip iterator for speed
|
||||
// cppcheck-suppress functionConst
|
||||
void iterateChildren(VNVisitorConst& v) {}
|
||||
static AstNodeVarRef* varRefLValueRecurse(AstNode* nodep);
|
||||
};
|
||||
|
||||
// === Concrete node types =====================================================
|
||||
|
|
@ -647,7 +648,7 @@ public:
|
|||
: ASTGEN_SUPER_CMethodHard(fl)
|
||||
, m_name{name} {
|
||||
this->fromp(fromp);
|
||||
this->addPinsp(pinsp);
|
||||
addPinsp(pinsp);
|
||||
setPurity();
|
||||
}
|
||||
ASTGEN_MEMBERS_AstCMethodHard;
|
||||
|
|
@ -674,7 +675,7 @@ public:
|
|||
AstCast(FileLine* fl, AstNodeExpr* fromp, VFlagChildDType, AstNodeDType* dtp)
|
||||
: ASTGEN_SUPER_Cast(fl) {
|
||||
this->fromp(fromp);
|
||||
this->childDTypep(dtp);
|
||||
childDTypep(dtp);
|
||||
dtypeFrom(dtp);
|
||||
}
|
||||
AstCast(FileLine* fl, AstNodeExpr* fromp, AstNodeDType* dtp)
|
||||
|
|
@ -728,7 +729,7 @@ public:
|
|||
AstCellArrayRef(FileLine* fl, const string& name, AstNodeExpr* selp)
|
||||
: ASTGEN_SUPER_CellArrayRef(fl)
|
||||
, m_name{name} {
|
||||
this->addSelp(selp);
|
||||
addSelp(selp);
|
||||
}
|
||||
ASTGEN_MEMBERS_AstCellArrayRef;
|
||||
// ACCESSORS
|
||||
|
|
@ -769,7 +770,7 @@ public:
|
|||
: ASTGEN_SUPER_ClassOrPackageRef(fl)
|
||||
, m_name{name}
|
||||
, m_classOrPackageNodep{classOrPackageNodep} {
|
||||
this->addParamsp(paramsp);
|
||||
addParamsp(paramsp);
|
||||
}
|
||||
ASTGEN_MEMBERS_AstClassOrPackageRef;
|
||||
// METHODS
|
||||
|
|
@ -876,7 +877,7 @@ public:
|
|||
AstConsPackMember* membersp = nullptr)
|
||||
: ASTGEN_SUPER_ConsPackUOrStruct(fl) {
|
||||
this->dtypep(dtypep);
|
||||
this->addMembersp(membersp);
|
||||
addMembersp(membersp);
|
||||
}
|
||||
ASTGEN_MEMBERS_AstConsPackUOrStruct;
|
||||
const char* broken() const override {
|
||||
|
|
@ -1155,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]
|
||||
|
|
@ -1162,7 +1177,7 @@ public:
|
|||
AstDist(FileLine* fl, AstNodeExpr* exprp, AstDistItem* itemsp)
|
||||
: ASTGEN_SUPER_Inside(fl) {
|
||||
this->exprp(exprp);
|
||||
this->addItemsp(itemsp);
|
||||
addItemsp(itemsp);
|
||||
dtypeSetBit();
|
||||
}
|
||||
ASTGEN_MEMBERS_AstDist;
|
||||
|
|
@ -1552,7 +1567,7 @@ public:
|
|||
AstInside(FileLine* fl, AstNodeExpr* exprp, AstNodeExpr* itemsp)
|
||||
: ASTGEN_SUPER_Inside(fl) {
|
||||
this->exprp(exprp);
|
||||
this->addItemsp(itemsp);
|
||||
addItemsp(itemsp);
|
||||
dtypeSetBit();
|
||||
}
|
||||
ASTGEN_MEMBERS_AstInside;
|
||||
|
|
@ -1599,6 +1614,7 @@ public:
|
|||
string name() const override VL_MT_STABLE { return m_name; } // * = Var name
|
||||
void name(const string& name) override { m_name = name; }
|
||||
bool index() const { return m_index; }
|
||||
bool isExprCoverageEligible() const override { return false; }
|
||||
};
|
||||
class AstMemberSel final : public AstNodeExpr {
|
||||
// @astgen op1 := fromp : AstNodeExpr
|
||||
|
|
@ -1744,7 +1760,7 @@ class AstPatMember final : public AstNodeExpr {
|
|||
public:
|
||||
AstPatMember(FileLine* fl, AstNodeExpr* lhssp, AstNode* keyp, AstNodeExpr* repp)
|
||||
: ASTGEN_SUPER_PatMember(fl) {
|
||||
this->addLhssp(lhssp);
|
||||
addLhssp(lhssp);
|
||||
this->keyp(keyp);
|
||||
this->repp(repp);
|
||||
}
|
||||
|
|
@ -1911,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();
|
||||
|
|
@ -1941,7 +1958,7 @@ public:
|
|||
AstSScanF(FileLine* fl, const string& text, AstNode* fromp, AstNode* exprsp)
|
||||
: ASTGEN_SUPER_SScanF(fl)
|
||||
, m_text{text} {
|
||||
this->addExprsp(exprsp);
|
||||
addExprsp(exprsp);
|
||||
this->fromp(fromp);
|
||||
}
|
||||
ASTGEN_MEMBERS_AstSScanF;
|
||||
|
|
@ -2029,7 +2046,7 @@ public:
|
|||
AstSelLoopVars(FileLine* fl, AstNodeExpr* fromp, AstNode* elementsp)
|
||||
: ASTGEN_SUPER_SelLoopVars(fl) {
|
||||
this->fromp(fromp);
|
||||
this->addElementsp(elementsp);
|
||||
addElementsp(elementsp);
|
||||
}
|
||||
ASTGEN_MEMBERS_AstSelLoopVars;
|
||||
bool sameNode(const AstNode* /*samep*/) const override { return true; }
|
||||
|
|
@ -2150,7 +2167,7 @@ class AstSysIgnore final : public AstNodeExpr {
|
|||
public:
|
||||
AstSysIgnore(FileLine* fl, AstNode* exprsp)
|
||||
: ASTGEN_SUPER_SysIgnore(fl) {
|
||||
this->addExprsp(exprsp);
|
||||
addExprsp(exprsp);
|
||||
}
|
||||
ASTGEN_MEMBERS_AstSysIgnore;
|
||||
string verilogKwd() const override { return "$ignored"; }
|
||||
|
|
@ -2261,7 +2278,7 @@ class AstUCFunc final : public AstNodeExpr {
|
|||
public:
|
||||
AstUCFunc(FileLine* fl, AstNode* exprsp)
|
||||
: ASTGEN_SUPER_UCFunc(fl) {
|
||||
this->addExprsp(exprsp);
|
||||
addExprsp(exprsp);
|
||||
}
|
||||
ASTGEN_MEMBERS_AstUCFunc;
|
||||
bool cleanOut() const override { return false; }
|
||||
|
|
@ -2343,7 +2360,7 @@ public:
|
|||
: ASTGEN_SUPER_With(fl) {
|
||||
this->indexArgRefp(indexArgRefp);
|
||||
this->valueArgRefp(valueArgRefp);
|
||||
this->addExprp(exprp);
|
||||
addExprp(exprp);
|
||||
}
|
||||
ASTGEN_MEMBERS_AstWith;
|
||||
bool sameNode(const AstNode* /*samep*/) const override { return true; }
|
||||
|
|
@ -2368,7 +2385,7 @@ public:
|
|||
AstWithParse(FileLine* fl, AstNodeExpr* funcrefp, AstNode* exprsp)
|
||||
: ASTGEN_SUPER_WithParse(fl) {
|
||||
this->funcrefp(funcrefp);
|
||||
this->addExprsp(exprsp);
|
||||
addExprsp(exprsp);
|
||||
}
|
||||
ASTGEN_MEMBERS_AstWithParse;
|
||||
bool sameNode(const AstNode* /*samep*/) const override { return true; }
|
||||
|
|
@ -4405,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
|
||||
|
|
@ -5740,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)
|
||||
|
|
@ -5755,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; }
|
||||
|
|
|
|||
|
|
@ -388,7 +388,7 @@ protected:
|
|||
AstNodeCase(VNType t, FileLine* fl, AstNodeExpr* exprp, AstCaseItem* itemsp)
|
||||
: AstNodeStmt{t, fl} {
|
||||
this->exprp(exprp);
|
||||
this->addItemsp(itemsp);
|
||||
addItemsp(itemsp);
|
||||
}
|
||||
|
||||
public:
|
||||
|
|
@ -414,7 +414,7 @@ public:
|
|||
, m_type{type}
|
||||
, m_directive{directive} {
|
||||
this->propp(propp);
|
||||
this->addPasssp(passsp);
|
||||
addPasssp(passsp);
|
||||
}
|
||||
ASTGEN_MEMBERS_AstNodeCoverOrAssert;
|
||||
string name() const override VL_MT_STABLE { return m_name; } // * = Var name
|
||||
|
|
@ -440,10 +440,10 @@ protected:
|
|||
AstNodeFor(VNType t, FileLine* fl, AstNode* initsp, AstNodeExpr* condp, AstNode* incsp,
|
||||
AstNode* stmtsp)
|
||||
: AstNodeStmt{t, fl} {
|
||||
this->addInitsp(initsp);
|
||||
addInitsp(initsp);
|
||||
this->condp(condp);
|
||||
this->addIncsp(incsp);
|
||||
this->addStmtsp(stmtsp);
|
||||
addIncsp(incsp);
|
||||
addStmtsp(stmtsp);
|
||||
}
|
||||
|
||||
public:
|
||||
|
|
@ -459,7 +459,7 @@ public:
|
|||
AstNodeForeach(VNType t, FileLine* fl, AstNode* arrayp, AstNode* stmtsp)
|
||||
: AstNodeStmt(t, fl) {
|
||||
this->arrayp(arrayp);
|
||||
this->addStmtsp(stmtsp);
|
||||
addStmtsp(stmtsp);
|
||||
}
|
||||
ASTGEN_MEMBERS_AstNodeForeach;
|
||||
bool isGateOptimizable() const override { return false; }
|
||||
|
|
@ -477,8 +477,8 @@ protected:
|
|||
AstNodeIf(VNType t, FileLine* fl, AstNodeExpr* condp, AstNode* thensp, AstNode* elsesp)
|
||||
: AstNodeStmt{t, fl} {
|
||||
this->condp(condp);
|
||||
this->addThensp(thensp);
|
||||
this->addElsesp(elsesp);
|
||||
addThensp(thensp);
|
||||
addElsesp(elsesp);
|
||||
isBoundsCheck(false);
|
||||
}
|
||||
|
||||
|
|
@ -598,7 +598,7 @@ public:
|
|||
: ASTGEN_SUPER_Bind(fl)
|
||||
, m_name{name} {
|
||||
UASSERT_OBJ(VN_IS(cellsp, Cell), cellsp, "Only instances allowed to be bound");
|
||||
this->addCellsp(cellsp);
|
||||
addCellsp(cellsp);
|
||||
}
|
||||
ASTGEN_MEMBERS_AstBind;
|
||||
// ACCESSORS
|
||||
|
|
@ -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
|
||||
|
|
@ -762,7 +764,7 @@ class AstCLocalScope final : public AstNode {
|
|||
public:
|
||||
AstCLocalScope(FileLine* fl, AstNode* stmtsp)
|
||||
: ASTGEN_SUPER_CLocalScope(fl) {
|
||||
this->addStmtsp(stmtsp);
|
||||
addStmtsp(stmtsp);
|
||||
}
|
||||
ASTGEN_MEMBERS_AstCLocalScope;
|
||||
};
|
||||
|
|
@ -790,8 +792,8 @@ class AstCaseItem final : public AstNode {
|
|||
public:
|
||||
AstCaseItem(FileLine* fl, AstNodeExpr* condsp, AstNode* stmtsp)
|
||||
: ASTGEN_SUPER_CaseItem(fl) {
|
||||
this->addCondsp(condsp);
|
||||
this->addStmtsp(stmtsp);
|
||||
addCondsp(condsp);
|
||||
addStmtsp(stmtsp);
|
||||
}
|
||||
ASTGEN_MEMBERS_AstCaseItem;
|
||||
int instrCount() const override { return widthInstrs() + INSTR_COUNT_BRANCH; }
|
||||
|
|
@ -824,8 +826,8 @@ public:
|
|||
, m_hasIfaceVar{false}
|
||||
, m_recursive{false}
|
||||
, m_trace{true} {
|
||||
this->addPinsp(pinsp);
|
||||
this->addParamsp(paramsp);
|
||||
addPinsp(pinsp);
|
||||
addParamsp(paramsp);
|
||||
this->rangep(rangep);
|
||||
}
|
||||
ASTGEN_MEMBERS_AstCell;
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -1037,7 +1040,7 @@ public:
|
|||
AstConstraint(FileLine* fl, const string& name, AstNode* itemsp)
|
||||
: ASTGEN_SUPER_Constraint(fl)
|
||||
, m_name(name) {
|
||||
this->addItemsp(itemsp);
|
||||
addItemsp(itemsp);
|
||||
}
|
||||
ASTGEN_MEMBERS_AstConstraint;
|
||||
void dump(std::ostream& str) const override;
|
||||
|
|
@ -1067,8 +1070,8 @@ class AstConstraintBefore final : public AstNode {
|
|||
public:
|
||||
AstConstraintBefore(FileLine* fl, AstNodeExpr* lhssp, AstNodeExpr* rhssp)
|
||||
: ASTGEN_SUPER_ConstraintBefore(fl) {
|
||||
this->addLhssp(lhssp);
|
||||
this->addRhssp(rhssp);
|
||||
addLhssp(lhssp);
|
||||
addRhssp(rhssp);
|
||||
}
|
||||
ASTGEN_MEMBERS_AstConstraintBefore;
|
||||
bool isGateOptimizable() const override { return false; }
|
||||
|
|
@ -1187,7 +1190,7 @@ class AstImplicit final : public AstNode {
|
|||
public:
|
||||
AstImplicit(FileLine* fl, AstNode* exprsp)
|
||||
: ASTGEN_SUPER_Implicit(fl) {
|
||||
this->addExprsp(exprsp);
|
||||
addExprsp(exprsp);
|
||||
}
|
||||
ASTGEN_MEMBERS_AstImplicit;
|
||||
};
|
||||
|
|
@ -1250,7 +1253,7 @@ public:
|
|||
AstModport(FileLine* fl, const string& name, AstNode* varsp)
|
||||
: ASTGEN_SUPER_Modport(fl)
|
||||
, m_name{name} {
|
||||
this->addVarsp(varsp);
|
||||
addVarsp(varsp);
|
||||
}
|
||||
string verilogKwd() const override { return "modport"; }
|
||||
string name() const override VL_MT_STABLE { return m_name; }
|
||||
|
|
@ -1645,7 +1648,7 @@ class AstSenTree final : public AstNode {
|
|||
public:
|
||||
AstSenTree(FileLine* fl, AstSenItem* sensesp)
|
||||
: ASTGEN_SUPER_SenTree(fl) {
|
||||
this->addSensesp(sensesp);
|
||||
addSensesp(sensesp);
|
||||
}
|
||||
ASTGEN_MEMBERS_AstSenTree;
|
||||
void dump(std::ostream& str) const override;
|
||||
|
|
@ -1798,18 +1801,47 @@ public:
|
|||
AstUdpTable(FileLine* fl, AstUdpTableLine* linesp)
|
||||
: ASTGEN_SUPER_UdpTable(fl) {
|
||||
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 {
|
||||
|
|
@ -1878,6 +1910,7 @@ class AstVar final : public AstNode {
|
|||
bool m_isWrittenByDpi : 1; // This variable can be written by a DPI Export
|
||||
bool m_isWrittenBySuspendable : 1; // This variable can be written by a suspendable process
|
||||
bool m_ignorePostWrite : 1; // Ignore writes in 'Post' blocks during ordering
|
||||
bool m_ignoreSchedWrite : 1; // Ignore writes in scheduling (for coverage increments)
|
||||
|
||||
void init() {
|
||||
m_ansi = false;
|
||||
|
|
@ -1923,6 +1956,7 @@ class AstVar final : public AstNode {
|
|||
m_isWrittenByDpi = false;
|
||||
m_isWrittenBySuspendable = false;
|
||||
m_ignorePostWrite = false;
|
||||
m_ignoreSchedWrite = false;
|
||||
m_attrClocker = VVarAttrClocker::CLOCKER_UNKNOWN;
|
||||
}
|
||||
|
||||
|
|
@ -2080,6 +2114,8 @@ public:
|
|||
void setWrittenBySuspendable() { m_isWrittenBySuspendable = true; }
|
||||
bool ignorePostWrite() const { return m_ignorePostWrite; }
|
||||
void setIgnorePostWrite() { m_ignorePostWrite = true; }
|
||||
bool ignoreSchedWrite() const { return m_ignoreSchedWrite; }
|
||||
void setIgnoreSchedWrite() { m_ignoreSchedWrite = true; }
|
||||
|
||||
// METHODS
|
||||
void name(const string& name) override { m_name = name; }
|
||||
|
|
@ -2165,6 +2201,8 @@ public:
|
|||
string verilogKwd() const override;
|
||||
void lifetime(const VLifetime& flag) { m_lifetime = flag; }
|
||||
VLifetime lifetime() const { return m_lifetime; }
|
||||
void pinNum(int id) { m_pinNum = id; }
|
||||
int pinNum() const { return m_pinNum; }
|
||||
void propagateAttrFrom(const AstVar* fromp) {
|
||||
// This is getting connected to fromp; keep attributes
|
||||
// Note the method below too
|
||||
|
|
@ -2197,9 +2235,11 @@ public:
|
|||
m_direction = VDirection::NONE;
|
||||
m_name = name;
|
||||
}
|
||||
bool needsCReset() const {
|
||||
return !isIfaceParent() && !isIfaceRef() && !noReset() && !isParam() && !isStatementTemp()
|
||||
&& !(basicp() && (basicp()->isEvent() || basicp()->isTriggerVec()));
|
||||
}
|
||||
static AstVar* scVarRecurse(AstNode* nodep);
|
||||
void pinNum(int id) { m_pinNum = id; }
|
||||
int pinNum() const { return m_pinNum; }
|
||||
};
|
||||
class AstVarScope final : public AstNode {
|
||||
// A particular scoped usage of a variable
|
||||
|
|
@ -2302,7 +2342,7 @@ public:
|
|||
class AstLet final : public AstNodeFTask {
|
||||
// Verilog "let" statement
|
||||
// Parents: MODULE
|
||||
// stmtp is always a StmtExpr as Let always returns AstNodeExpr
|
||||
// stmtp list first item is returned StmtExpr, as Let always returns AstNodeExpr
|
||||
public:
|
||||
AstLet(FileLine* fl, const string& name)
|
||||
: ASTGEN_SUPER_Let(fl, name, nullptr) {}
|
||||
|
|
@ -2382,7 +2422,6 @@ class AstClass final : public AstNodeModule {
|
|||
bool m_extended = false; // Is extension or extended by other classes
|
||||
bool m_interfaceClass = false; // Interface class
|
||||
bool m_needRNG = false; // Need RNG, uses srandom/randomize
|
||||
bool m_parameterized = false; // Parameterized class
|
||||
bool m_useVirtualPublic = false; // Subclasses need virtual public as uses interface class
|
||||
bool m_virtual = false; // Virtual class
|
||||
|
||||
|
|
@ -2403,8 +2442,6 @@ public:
|
|||
void isExtended(bool flag) { m_extended = flag; }
|
||||
bool isInterfaceClass() const { return m_interfaceClass; }
|
||||
void isInterfaceClass(bool flag) { m_interfaceClass = flag; }
|
||||
bool isParameterized() const { return m_parameterized; }
|
||||
void isParameterized(bool flag) { m_parameterized = flag; }
|
||||
bool isVirtual() const { return m_virtual; }
|
||||
void isVirtual(bool flag) { m_virtual = flag; }
|
||||
bool needRNG() const { return m_needRNG; }
|
||||
|
|
@ -2484,14 +2521,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
|
||||
|
|
@ -2740,15 +2791,22 @@ public:
|
|||
class AstCReset final : public AstNodeStmt {
|
||||
// Reset variable at startup
|
||||
// @astgen op1 := varrefp : AstVarRef
|
||||
const bool m_constructing; // Previously cleared by constructor
|
||||
public:
|
||||
AstCReset(FileLine* fl, AstVarRef* varrefp)
|
||||
: ASTGEN_SUPER_CReset(fl) {
|
||||
AstCReset(FileLine* fl, AstVarRef* varrefp, bool constructing)
|
||||
: ASTGEN_SUPER_CReset(fl)
|
||||
, m_constructing(constructing) {
|
||||
this->varrefp(varrefp);
|
||||
}
|
||||
ASTGEN_MEMBERS_AstCReset;
|
||||
void dump(std::ostream& str) const override;
|
||||
void dumpJson(std::ostream& str) const override;
|
||||
bool isGateOptimizable() const override { return false; }
|
||||
bool isPredictOptimizable() const override { return false; }
|
||||
bool sameNode(const AstNode* /*samep*/) const override { return true; }
|
||||
bool sameNode(const AstNode* samep) const override {
|
||||
return constructing() == VN_DBG_AS(samep, CReset)->constructing();
|
||||
}
|
||||
bool constructing() const { return m_constructing; }
|
||||
};
|
||||
class AstCReturn final : public AstNodeStmt {
|
||||
// C++ return from a function
|
||||
|
|
@ -2768,7 +2826,7 @@ class AstCStmt final : public AstNodeStmt {
|
|||
public:
|
||||
AstCStmt(FileLine* fl, AstNode* exprsp)
|
||||
: ASTGEN_SUPER_CStmt(fl) {
|
||||
this->addExprsp(exprsp);
|
||||
addExprsp(exprsp);
|
||||
}
|
||||
inline AstCStmt(FileLine* fl, const string& textStmt);
|
||||
ASTGEN_MEMBERS_AstCStmt;
|
||||
|
|
@ -2817,7 +2875,7 @@ class AstConstraintUnique final : public AstNodeStmt {
|
|||
public:
|
||||
AstConstraintUnique(FileLine* fl, AstNode* rangesp)
|
||||
: ASTGEN_SUPER_ConstraintUnique(fl) {
|
||||
this->addRangesp(rangesp);
|
||||
addRangesp(rangesp);
|
||||
}
|
||||
ASTGEN_MEMBERS_AstConstraintUnique;
|
||||
bool isGateOptimizable() const override { return false; }
|
||||
|
|
@ -2983,14 +3041,14 @@ public:
|
|||
AstNodeExpr* exprsp, char missingArgChar = 'd')
|
||||
: ASTGEN_SUPER_Display(fl)
|
||||
, m_displayType{dispType} {
|
||||
this->fmtp(new AstSFormatF{fl, text, true, exprsp, missingArgChar});
|
||||
fmtp(new AstSFormatF{fl, text, true, exprsp, missingArgChar});
|
||||
this->filep(filep);
|
||||
}
|
||||
AstDisplay(FileLine* fl, VDisplayType dispType, AstNodeExpr* filep, AstNodeExpr* exprsp,
|
||||
char missingArgChar = 'd')
|
||||
: ASTGEN_SUPER_Display(fl)
|
||||
, m_displayType{dispType} {
|
||||
this->fmtp(new AstSFormatF{fl, AstSFormatF::NoFormat{}, exprsp, missingArgChar});
|
||||
fmtp(new AstSFormatF{fl, AstSFormatF::NoFormat{}, exprsp, missingArgChar});
|
||||
this->filep(filep);
|
||||
}
|
||||
ASTGEN_MEMBERS_AstDisplay;
|
||||
|
|
@ -3063,7 +3121,7 @@ public:
|
|||
AstEventControl(FileLine* fl, AstSenTree* sensesp, AstNode* stmtsp)
|
||||
: ASTGEN_SUPER_EventControl(fl) {
|
||||
this->sensesp(sensesp);
|
||||
this->addStmtsp(stmtsp);
|
||||
addStmtsp(stmtsp);
|
||||
}
|
||||
ASTGEN_MEMBERS_AstEventControl;
|
||||
string verilogKwd() const override { return "@(%l) %r"; }
|
||||
|
|
@ -3144,7 +3202,7 @@ public:
|
|||
// After construction must call ->labelp to associate with appropriate label
|
||||
AstJumpBlock(FileLine* fl, AstNode* stmtsp)
|
||||
: ASTGEN_SUPER_JumpBlock(fl) {
|
||||
this->addStmtsp(stmtsp);
|
||||
addStmtsp(stmtsp);
|
||||
}
|
||||
ASTGEN_MEMBERS_AstJumpBlock;
|
||||
const char* broken() const override;
|
||||
|
|
@ -3276,7 +3334,7 @@ public:
|
|||
AstRepeat(FileLine* fl, AstNodeExpr* countp, AstNode* stmtsp)
|
||||
: ASTGEN_SUPER_Repeat(fl) {
|
||||
this->countp(countp);
|
||||
this->addStmtsp(stmtsp);
|
||||
addStmtsp(stmtsp);
|
||||
}
|
||||
ASTGEN_MEMBERS_AstRepeat;
|
||||
bool isGateOptimizable() const override { return false; } // Not relevant - converted to FOR
|
||||
|
|
@ -3305,12 +3363,12 @@ public:
|
|||
AstSFormat(FileLine* fl, AstNodeExpr* lhsp, const string& text, AstNodeExpr* exprsp,
|
||||
char missingArgChar = 'd')
|
||||
: ASTGEN_SUPER_SFormat(fl) {
|
||||
this->fmtp(new AstSFormatF{fl, text, true, exprsp, missingArgChar});
|
||||
fmtp(new AstSFormatF{fl, text, true, exprsp, missingArgChar});
|
||||
this->lhsp(lhsp);
|
||||
}
|
||||
AstSFormat(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* exprsp, char missingArgChar = 'd')
|
||||
: ASTGEN_SUPER_SFormat(fl) {
|
||||
this->fmtp(new AstSFormatF{fl, AstSFormatF::NoFormat{}, exprsp, missingArgChar});
|
||||
fmtp(new AstSFormatF{fl, AstSFormatF::NoFormat{}, exprsp, missingArgChar});
|
||||
this->lhsp(lhsp);
|
||||
}
|
||||
ASTGEN_MEMBERS_AstSFormat;
|
||||
|
|
@ -3327,6 +3385,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:
|
||||
|
|
@ -3540,7 +3616,7 @@ class AstUCStmt final : public AstNodeStmt {
|
|||
public:
|
||||
AstUCStmt(FileLine* fl, AstNode* exprsp)
|
||||
: ASTGEN_SUPER_UCStmt(fl) {
|
||||
this->addExprsp(exprsp);
|
||||
addExprsp(exprsp);
|
||||
}
|
||||
ASTGEN_MEMBERS_AstUCStmt;
|
||||
bool isGateOptimizable() const override { return false; }
|
||||
|
|
@ -3556,7 +3632,7 @@ public:
|
|||
AstWait(FileLine* fl, AstNodeExpr* condp, AstNode* stmtsp)
|
||||
: ASTGEN_SUPER_Wait(fl) {
|
||||
this->condp(condp);
|
||||
this->addStmtsp(stmtsp);
|
||||
addStmtsp(stmtsp);
|
||||
}
|
||||
ASTGEN_MEMBERS_AstWait;
|
||||
bool isFirstInMyListOfStatements(AstNode* n) const override { return n == stmtsp(); }
|
||||
|
|
@ -3580,8 +3656,8 @@ public:
|
|||
AstWhile(FileLine* fl, AstNodeExpr* condp, AstNode* stmtsp = nullptr, AstNode* incsp = nullptr)
|
||||
: ASTGEN_SUPER_While(fl) {
|
||||
this->condp(condp);
|
||||
this->addStmtsp(stmtsp);
|
||||
this->addIncsp(incsp);
|
||||
addStmtsp(stmtsp);
|
||||
addIncsp(incsp);
|
||||
}
|
||||
ASTGEN_MEMBERS_AstWhile;
|
||||
void dump(std::ostream& str) const override;
|
||||
|
|
@ -3756,7 +3832,7 @@ public:
|
|||
AstAssert(FileLine* fl, AstNode* propp, AstNode* passsp, AstNode* failsp, VAssertType type,
|
||||
VAssertDirectiveType directive, const string& name = "")
|
||||
: ASTGEN_SUPER_Assert(fl, propp, passsp, type, directive, name) {
|
||||
this->addFailsp(failsp);
|
||||
addFailsp(failsp);
|
||||
}
|
||||
};
|
||||
class AstAssertIntrinsic final : public AstNodeCoverOrAssert {
|
||||
|
|
@ -3769,7 +3845,7 @@ public:
|
|||
// Intrinsic asserts are always enabled thus 'type' field is set to INTERNAL.
|
||||
: ASTGEN_SUPER_AssertIntrinsic(fl, propp, passsp, VAssertType::INTERNAL,
|
||||
VAssertDirectiveType::INTRINSIC, name) {
|
||||
this->addFailsp(failsp);
|
||||
addFailsp(failsp);
|
||||
}
|
||||
};
|
||||
class AstCover final : public AstNodeCoverOrAssert {
|
||||
|
|
@ -3886,6 +3962,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)
|
||||
|
|
|
|||
|
|
@ -327,6 +327,15 @@ AstNodeExpr* AstInsideRange::newAndFromInside(AstNodeExpr* exprp, AstNodeExpr* l
|
|||
return new AstLogAnd{fileline(), ap, bp};
|
||||
}
|
||||
|
||||
void AstCReset::dump(std::ostream& str) const {
|
||||
this->AstNode::dump(str);
|
||||
if (constructing()) str << " [CONS]";
|
||||
}
|
||||
void AstCReset::dumpJson(std::ostream& str) const {
|
||||
dumpJsonBoolFunc(str, constructing);
|
||||
dumpJsonGen(str);
|
||||
}
|
||||
|
||||
AstVar* AstClocking::ensureEventp(bool childDType) {
|
||||
if (!eventp()) {
|
||||
AstVar* const evp
|
||||
|
|
@ -815,12 +824,12 @@ AstVar* AstVar::scVarRecurse(AstNode* nodep) {
|
|||
}
|
||||
} else if (AstArraySel* const arraySelp = VN_CAST(nodep, ArraySel)) {
|
||||
if (AstVar* const p = scVarRecurse(arraySelp->fromp())) return p;
|
||||
if (AstVar* const p = scVarRecurse(arraySelp->bitp())) return p;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const AstNodeDType* AstNodeDType::skipRefIterp(bool skipConst, bool skipEnum) const VL_MT_STABLE {
|
||||
const AstNodeDType* AstNodeDType::skipRefIterp(bool skipConst, bool skipEnum,
|
||||
bool assertOn) const VL_MT_STABLE {
|
||||
const AstNodeDType* nodep = this;
|
||||
while (true) {
|
||||
if (VL_UNLIKELY(VN_IS(nodep, MemberDType) || VN_IS(nodep, ParamTypeDType)
|
||||
|
|
@ -831,7 +840,7 @@ const AstNodeDType* AstNodeDType::skipRefIterp(bool skipConst, bool skipEnum) co
|
|||
nodep = subp;
|
||||
continue;
|
||||
} else {
|
||||
nodep->v3fatalSrc(nodep->prettyTypeName() << " not linked to type");
|
||||
if (assertOn) nodep->v3fatalSrc(nodep->prettyTypeName() << " not linked to type");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
|
@ -839,6 +848,15 @@ const AstNodeDType* AstNodeDType::skipRefIterp(bool skipConst, bool skipEnum) co
|
|||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
|
|
@ -998,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 {
|
||||
|
|
@ -1986,8 +2004,8 @@ AstMemberSel::AstMemberSel(FileLine* fl, AstNodeExpr* fromp, AstVar* varp)
|
|||
}
|
||||
bool AstMemberSel::sameNode(const AstNode* samep) const {
|
||||
const AstMemberSel* const sp = VN_DBG_AS(samep, MemberSel);
|
||||
return sp != nullptr && access() == sp->access() && fromp()->isSame(sp->fromp())
|
||||
&& name() == sp->name() && varp()->sameNode(sp->varp());
|
||||
return sp && access() == sp->access() && fromp()->isSame(sp->fromp()) && name() == sp->name()
|
||||
&& (varp() && sp->varp() && varp()->sameNode(sp->varp()));
|
||||
}
|
||||
|
||||
void AstMemberSel::dump(std::ostream& str) const {
|
||||
|
|
@ -2030,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()) {
|
||||
|
|
@ -2474,8 +2502,24 @@ void AstNodeVarRef::dumpJson(std::ostream& str) const {
|
|||
dumpJsonStr(str, "access", access().ascii());
|
||||
dumpJsonGen(str);
|
||||
}
|
||||
AstNodeVarRef* AstNodeVarRef::varRefLValueRecurse(AstNode* nodep) {
|
||||
// Given a (possible) lvalue expression, recurse to find the being-set NodeVarRef, else nullptr
|
||||
if (AstNodeVarRef* const anodep = VN_CAST(nodep, NodeVarRef)) return anodep;
|
||||
if (AstNodeSel* const anodep = VN_CAST(nodep, NodeSel))
|
||||
return varRefLValueRecurse(anodep->fromp());
|
||||
if (AstSel* const anodep = VN_CAST(nodep, Sel)) return varRefLValueRecurse(anodep->fromp());
|
||||
if (AstArraySel* const anodep = VN_CAST(nodep, ArraySel))
|
||||
return varRefLValueRecurse(anodep->fromp());
|
||||
if (AstMemberSel* const anodep = VN_CAST(nodep, MemberSel))
|
||||
return varRefLValueRecurse(anodep->fromp());
|
||||
if (AstStructSel* const anodep = VN_CAST(nodep, StructSel))
|
||||
return varRefLValueRecurse(anodep->fromp());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void AstVarXRef::dump(std::ostream& str) const {
|
||||
this->AstNodeVarRef::dump(str);
|
||||
if (containsGenBlock()) str << " [GENBLK]";
|
||||
str << ".=" << dotted() << " ";
|
||||
if (inlinedDots() != "") str << " inline.=" << inlinedDots() << " - ";
|
||||
if (varScopep()) {
|
||||
|
|
@ -2487,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);
|
||||
|
|
@ -2538,6 +2583,8 @@ void AstVar::dump(std::ostream& str) const {
|
|||
str << " [FUNC]";
|
||||
}
|
||||
if (isDpiOpenArray()) str << " [DPIOPENA]";
|
||||
if (ignorePostWrite()) str << " [IGNPWR]";
|
||||
if (ignoreSchedWrite()) str << " [IGNWR]";
|
||||
if (!attrClocker().unknown()) str << " [" << attrClocker().ascii() << "] ";
|
||||
if (!lifetime().isNone()) str << " [" << lifetime().ascii() << "] ";
|
||||
str << " " << varType();
|
||||
|
|
@ -2570,6 +2617,8 @@ void AstVar::dumpJson(std::ostream& str) const {
|
|||
dumpJsonBoolFunc(str, isParam);
|
||||
dumpJsonBoolFunc(str, attrScBv);
|
||||
dumpJsonBoolFunc(str, attrSFormat);
|
||||
dumpJsonBoolFunc(str, ignorePostWrite);
|
||||
dumpJsonBoolFunc(str, ignoreSchedWrite);
|
||||
dumpJsonGen(str);
|
||||
}
|
||||
bool AstVar::sameNode(const AstNode* samep) const {
|
||||
|
|
@ -2656,7 +2705,9 @@ AstNodeModule* AstClassOrPackageRef::classOrPackageSkipp() const {
|
|||
AstNode* lastp = nullptr;
|
||||
while (foundp != lastp) {
|
||||
lastp = foundp;
|
||||
if (AstNodeDType* const anodep = VN_CAST(foundp, NodeDType)) foundp = anodep->skipRefp();
|
||||
if (AstNodeDType* const anodep = VN_CAST(foundp, NodeDType)) {
|
||||
foundp = anodep->skipRefOrNullp();
|
||||
}
|
||||
if (AstTypedef* const anodep = VN_CAST(foundp, Typedef)) foundp = anodep->subDTypep();
|
||||
if (AstClassRefDType* const anodep = VN_CAST(foundp, ClassRefDType))
|
||||
foundp = anodep->classp();
|
||||
|
|
@ -2988,7 +3039,8 @@ void AstCMethodHard::setPurity() {
|
|||
{"resume", false},
|
||||
{"reverse", false},
|
||||
{"rsort", false},
|
||||
{"set", false},
|
||||
{"setBit", false},
|
||||
{"setWord", false},
|
||||
{"set_randmode", false},
|
||||
{"shuffle", false},
|
||||
{"size", true},
|
||||
|
|
@ -3055,7 +3107,7 @@ AstAlways* AstAssignW::convertToAlways() {
|
|||
if (hasTimingControl) {
|
||||
// If there's a timing control, put the assignment in a fork..join_none. This process won't
|
||||
// get marked as suspendable and thus will be scheduled normally
|
||||
auto* forkp = new AstFork{flp, "", bodysp};
|
||||
AstFork* forkp = new AstFork{flp, "", bodysp};
|
||||
forkp->joinType(VJoinType::JOIN_NONE);
|
||||
bodysp = forkp;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ public:
|
|||
}
|
||||
|
||||
// Get a pointer to the user data if exists, otherwise nullptr
|
||||
T_Data* tryGet(const T_Node* nodep) { return getUserp(nodep); }
|
||||
T_Data* tryGet(const T_Node* nodep) const { return getUserp(nodep); }
|
||||
|
||||
void clear() { m_allocated.clear(); }
|
||||
};
|
||||
|
|
|
|||
|
|
@ -377,7 +377,7 @@ void V3Begin::debeginAll(AstNetlist* nodep) {
|
|||
{
|
||||
BeginState state;
|
||||
{ BeginVisitor{nodep, &state}; }
|
||||
if (state.anyFuncInBegin()) { BeginRelinkVisitor{nodep, &state}; }
|
||||
if (state.anyFuncInBegin()) BeginRelinkVisitor{nodep, &state};
|
||||
} // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("begin", 0, dumpTreeEitherLevel() >= 3);
|
||||
}
|
||||
|
|
@ -506,8 +506,9 @@ AstNode* V3Begin::convertToWhile(AstForeach* nodep) {
|
|||
AstNode* const first_clearp
|
||||
= new AstAssign{fl, new AstVarRef{fl, first_varp, VAccess::WRITE},
|
||||
new AstConst{fl, AstConst::BitFalse{}}};
|
||||
auto* const orp = new AstLogOr{fl, new AstVarRef{fl, first_varp, VAccess::READ},
|
||||
new AstNeq{fl, new AstConst{fl, 0}, nextp}};
|
||||
AstLogOr* const orp
|
||||
= new AstLogOr{fl, new AstVarRef{fl, first_varp, VAccess::READ},
|
||||
new AstNeq{fl, new AstConst{fl, 0}, nextp}};
|
||||
AstNode* const whilep = new AstWhile{fl, orp, first_clearp};
|
||||
first_clearp->addNext(bodyPointp);
|
||||
AstNode* const ifbodyp
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
|
|
@ -137,7 +137,17 @@ class CCtorsVisitor final : public VNVisitor {
|
|||
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,18 +188,16 @@ 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->isIfaceParent() && !nodep->isIfaceRef() && !nodep->noReset()
|
||||
&& !nodep->isParam() && !nodep->isStatementTemp()
|
||||
&& !(nodep->basicp()
|
||||
&& (nodep->basicp()->isEvent() || nodep->basicp()->isTriggerVec()))) {
|
||||
if (nodep->needsCReset()) {
|
||||
if (m_varResetp) {
|
||||
const auto vrefp = new AstVarRef{nodep->fileline(), nodep, VAccess::WRITE};
|
||||
m_varResetp->add(new AstCReset{nodep->fileline(), vrefp});
|
||||
AstVarRef* const vrefp = new AstVarRef{nodep->fileline(), nodep, VAccess::WRITE};
|
||||
m_varResetp->add(new AstCReset{nodep->fileline(), vrefp, true});
|
||||
} else if (m_cfuncp) {
|
||||
const auto vrefp = new AstVarRef{nodep->fileline(), nodep, VAccess::WRITE};
|
||||
nodep->addNextHere(new AstCReset{nodep->fileline(), vrefp});
|
||||
AstVarRef* const vrefp = new AstVarRef{nodep->fileline(), nodep, VAccess::WRITE};
|
||||
nodep->addNextHere(new AstCReset{nodep->fileline(), vrefp, true});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -226,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{
|
||||
|
|
|
|||
|
|
@ -72,13 +72,13 @@ class CaseLintVisitor final : public VNVisitorConst {
|
|||
|
||||
// Check for X/Z in non-casex statements
|
||||
{
|
||||
VL_RESTORER(m_caseExprp);
|
||||
m_caseExprp = nodep;
|
||||
iterateConst(nodep->exprp());
|
||||
for (AstCaseItem* itemp = nodep->itemsp(); itemp;
|
||||
itemp = VN_AS(itemp->nextp(), CaseItem)) {
|
||||
iterateAndNextConstNull(itemp->condsp());
|
||||
}
|
||||
m_caseExprp = nullptr;
|
||||
}
|
||||
}
|
||||
void visit(AstConst* nodep) override {
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -188,9 +188,9 @@ class CombineVisitor final : VNVisitor {
|
|||
}
|
||||
void visit(AstNodeModule* nodep) override {
|
||||
UASSERT_OBJ(!m_modp, nodep, "Should not nest");
|
||||
VL_RESTORER(m_modp);
|
||||
m_modp = nodep;
|
||||
iterateChildrenConst(nodep);
|
||||
m_modp = nullptr;
|
||||
}
|
||||
void visit(AstCFunc* nodep) override {
|
||||
iterateChildrenConst(nodep);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -2169,7 +2169,7 @@ class ConstVisitor final : public VNVisitor {
|
|||
// Add a cast if needed.
|
||||
AstStreamR* const streamp = VN_AS(nodep->rhsp(), StreamR)->unlinkFrBack();
|
||||
AstNodeExpr* srcp = streamp->lhsp()->unlinkFrBack();
|
||||
AstNodeDType* const srcDTypep = srcp->dtypep();
|
||||
AstNodeDType* const srcDTypep = srcp->dtypep()->skipRefp();
|
||||
if (VN_IS(srcDTypep, QueueDType) || VN_IS(srcDTypep, DynArrayDType)) {
|
||||
srcp = new AstCvtArrayToPacked{srcp->fileline(), srcp, nodep->dtypep()};
|
||||
} else if (VN_IS(srcDTypep, UnpackArrayDType)) {
|
||||
|
|
@ -2191,30 +2191,32 @@ class ConstVisitor final : public VNVisitor {
|
|||
// Push the stream operator to the rhs of the assignment statement
|
||||
AstNodeExpr* streamp = nodep->lhsp()->unlinkFrBack();
|
||||
AstNodeExpr* const dstp = VN_AS(streamp, StreamL)->lhsp()->unlinkFrBack();
|
||||
AstNodeDType* const dstDTypep = dstp->dtypep()->skipRefp();
|
||||
AstNodeExpr* const srcp = nodep->rhsp()->unlinkFrBack();
|
||||
AstNodeDType* const srcDTypep = srcp->dtypep()->skipRefp();
|
||||
const int sWidth = srcp->width();
|
||||
const int dWidth = dstp->width();
|
||||
// Connect the rhs to the stream operator and update its width
|
||||
VN_AS(streamp, StreamL)->lhsp(srcp);
|
||||
if (VN_IS(srcp->dtypep(), DynArrayDType) || VN_IS(srcp->dtypep(), QueueDType)
|
||||
|| VN_IS(srcp->dtypep(), UnpackArrayDType)) {
|
||||
if (VN_IS(srcDTypep, DynArrayDType) || VN_IS(srcDTypep, QueueDType)
|
||||
|| VN_IS(srcDTypep, UnpackArrayDType)) {
|
||||
streamp->dtypeSetStream();
|
||||
} else {
|
||||
streamp->dtypeSetLogicUnsized(srcp->width(), srcp->widthMin(), VSigning::UNSIGNED);
|
||||
}
|
||||
if (VN_IS(dstp->dtypep(), UnpackArrayDType)) {
|
||||
streamp = new AstCvtPackedToArray{nodep->fileline(), streamp, dstp->dtypep()};
|
||||
if (VN_IS(dstDTypep, UnpackArrayDType)) {
|
||||
streamp = new AstCvtPackedToArray{nodep->fileline(), streamp, dstDTypep};
|
||||
} else {
|
||||
UASSERT(sWidth >= dWidth, "sWidth >= dWidth should have caused an error earlier");
|
||||
if (dWidth == 0) {
|
||||
streamp = new AstCvtPackedToArray{nodep->fileline(), streamp, dstp->dtypep()};
|
||||
streamp = new AstCvtPackedToArray{nodep->fileline(), streamp, dstDTypep};
|
||||
} else if (sWidth >= dWidth) {
|
||||
streamp = new AstSel{streamp->fileline(), streamp, sWidth - dWidth, dWidth};
|
||||
}
|
||||
}
|
||||
nodep->lhsp(dstp);
|
||||
nodep->rhsp(streamp);
|
||||
nodep->dtypep(dstp->dtypep());
|
||||
nodep->dtypep(dstDTypep);
|
||||
return true;
|
||||
} else if (m_doV && VN_IS(nodep->lhsp(), StreamR)) {
|
||||
// The right stream operator on lhs of assignment statement does
|
||||
|
|
@ -2222,12 +2224,13 @@ class ConstVisitor final : public VNVisitor {
|
|||
// then we select bits from the left-most, not the right-most.
|
||||
AstNodeExpr* const streamp = nodep->lhsp()->unlinkFrBack();
|
||||
AstNodeExpr* const dstp = VN_AS(streamp, StreamR)->lhsp()->unlinkFrBack();
|
||||
AstNodeDType* const dstDTypep = dstp->dtypep()->skipRefp();
|
||||
AstNodeExpr* srcp = nodep->rhsp()->unlinkFrBack();
|
||||
const int sWidth = srcp->width();
|
||||
const int dWidth = dstp->width();
|
||||
if (VN_IS(dstp->dtypep(), UnpackArrayDType)) {
|
||||
if (VN_IS(dstDTypep, UnpackArrayDType)) {
|
||||
const int dstBitWidth
|
||||
= dWidth * VN_AS(dstp->dtypep(), UnpackArrayDType)->arrayUnpackedElements();
|
||||
= dWidth * VN_AS(dstDTypep, UnpackArrayDType)->arrayUnpackedElements();
|
||||
// Handling the case where rhs is wider than lhs. StreamL does not require this
|
||||
// since the combination of the left streaming operation and the implicit
|
||||
// truncation in VL_ASSIGN_UNPACK automatically selects the left-most bits.
|
||||
|
|
@ -2235,30 +2238,30 @@ class ConstVisitor final : public VNVisitor {
|
|||
srcp
|
||||
= new AstSel{streamp->fileline(), srcp, sWidth - dstBitWidth, dstBitWidth};
|
||||
}
|
||||
srcp = new AstCvtPackedToArray{nodep->fileline(), srcp, dstp->dtypep()};
|
||||
srcp = new AstCvtPackedToArray{nodep->fileline(), srcp, dstDTypep};
|
||||
} else {
|
||||
UASSERT(sWidth >= dWidth, "sWidth >= dWidth should have caused an error earlier");
|
||||
if (dWidth == 0) {
|
||||
srcp = new AstCvtPackedToArray{nodep->fileline(), srcp, dstp->dtypep()};
|
||||
srcp = new AstCvtPackedToArray{nodep->fileline(), srcp, dstDTypep};
|
||||
} else if (sWidth >= dWidth) {
|
||||
srcp = new AstSel{streamp->fileline(), srcp, sWidth - dWidth, dWidth};
|
||||
}
|
||||
}
|
||||
nodep->lhsp(dstp);
|
||||
nodep->rhsp(srcp);
|
||||
nodep->dtypep(dstp->dtypep());
|
||||
nodep->dtypep(dstDTypep);
|
||||
VL_DO_DANGLING(pushDeletep(streamp), streamp);
|
||||
// Further reduce, any of the nodes may have more reductions.
|
||||
return true;
|
||||
} else if (m_doV && VN_IS(nodep->rhsp(), StreamL)) {
|
||||
AstNodeDType* const lhsDtypep = nodep->lhsp()->dtypep();
|
||||
AstNodeDType* const lhsDtypep = nodep->lhsp()->dtypep()->skipRefp();
|
||||
AstStreamL* streamp = VN_AS(nodep->rhsp(), StreamL);
|
||||
AstNodeExpr* const srcp = streamp->lhsp();
|
||||
const AstNodeDType* const srcDTypep = srcp->dtypep();
|
||||
const AstNodeDType* const srcDTypep = srcp->dtypep()->skipRefp();
|
||||
if (VN_IS(srcDTypep, QueueDType) || VN_IS(srcDTypep, DynArrayDType)
|
||||
|| VN_IS(srcDTypep, UnpackArrayDType)) {
|
||||
streamp->lhsp(new AstCvtArrayToPacked{srcp->fileline(), srcp->unlinkFrBack(),
|
||||
nodep->dtypep()});
|
||||
streamp->lhsp(
|
||||
new AstCvtArrayToPacked{srcp->fileline(), srcp->unlinkFrBack(), lhsDtypep});
|
||||
streamp->dtypeFrom(lhsDtypep);
|
||||
}
|
||||
} else if (m_doV && replaceAssignMultiSel(nodep)) {
|
||||
|
|
@ -2896,8 +2899,8 @@ class ConstVisitor final : public VNVisitor {
|
|||
|
||||
if (const AstConst* const aConstp = VN_CAST(ap, Const)) {
|
||||
const AstConst* const bConstp = VN_AS(bp, Const);
|
||||
if (aConstp->toUQuad() < bConstp->toUQuad()) return -1;
|
||||
if (aConstp->toUQuad() > bConstp->toUQuad()) return 1;
|
||||
if (aConstp->num().isLtXZ(bConstp->num())) return -1;
|
||||
if (bConstp->num().isLtXZ(aConstp->num())) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -3249,7 +3252,7 @@ class ConstVisitor final : public VNVisitor {
|
|||
}
|
||||
}
|
||||
if (m_doNConst && anyconst) {
|
||||
// UINFO(9," Display in "<<nodep->text()<<endl);
|
||||
// UINFO(9, " Display in " << nodep->text() << endl);
|
||||
string newFormat;
|
||||
string fmt;
|
||||
bool inPct = false;
|
||||
|
|
@ -3265,9 +3268,9 @@ class ConstVisitor final : public VNVisitor {
|
|||
inPct = false;
|
||||
fmt += ch;
|
||||
switch (std::tolower(ch)) {
|
||||
case '%': break; // %% - just output a %
|
||||
case 'm': break; // %m - auto insert "name"
|
||||
case 'l': break; // %l - auto insert "library"
|
||||
case '%': break; // %% - still %%
|
||||
case 'm': break; // %m - still %m - auto insert "name"
|
||||
case 'l': break; // %l - still %l - auto insert "library"
|
||||
case 't': // FALLTHRU
|
||||
case '^': // %t/%^ - don't know $timeformat so can't constify
|
||||
if (argp) argp = argp->nextp();
|
||||
|
|
@ -3871,7 +3874,7 @@ AstNode* V3Const::constifyParamsEdit(AstNode* nodep) {
|
|||
} else {
|
||||
nodep = visitor.mainAcceptEdit(nodep);
|
||||
}
|
||||
// Because we do edits, nodep links may get trashed and core dump this.
|
||||
// Because we do edits, nodep links may get trashed and core dump if have next line
|
||||
// if (debug() > 0) nodep->dumpTree("- forceConDONE: ");
|
||||
return nodep;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,6 +35,40 @@
|
|||
|
||||
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||
|
||||
class ExprCoverageEligibleVisitor final : public VNVisitor {
|
||||
// STATE
|
||||
bool m_eligible = true;
|
||||
|
||||
void visit(AstNodeVarRef* nodep) override {
|
||||
AstNodeDType* dtypep = nodep->varp()->dtypep();
|
||||
// Class objecs and references not supported for expression coverage
|
||||
// because the object may not persist until the point at which
|
||||
// coverage data is gathered
|
||||
// This could be resolved in the future by protecting against dereferrencing
|
||||
// null pointers when cloning the expression for expression coverage
|
||||
if (VN_CAST(dtypep, ClassRefDType)) {
|
||||
m_eligible = false;
|
||||
} else {
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
}
|
||||
|
||||
void visit(AstNode* nodep) override {
|
||||
if (!nodep->isExprCoverageEligible()) {
|
||||
m_eligible = false;
|
||||
} else {
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit ExprCoverageEligibleVisitor(AstNode* nodep) { iterateChildren(nodep); }
|
||||
~ExprCoverageEligibleVisitor() override = default;
|
||||
|
||||
bool eligible() { return m_eligible; }
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
// Coverage state, as a visitor of each AstNode
|
||||
|
||||
|
|
@ -159,6 +193,7 @@ class CoverageVisitor final : public VNVisitor {
|
|||
fl_nowarn->modifyWarnOff(V3ErrorCode::UNUSEDSIGNAL, true);
|
||||
AstVar* const varp = new AstVar{fl_nowarn, VVarType::MODULETEMP, trace_var_name,
|
||||
incp->findUInt32DType()};
|
||||
varp->setIgnoreSchedWrite(); // Ignore the increment output, so no UNOPTFLAT
|
||||
varp->trace(true);
|
||||
m_modp->addStmtsp(varp);
|
||||
UINFO(5, "New coverage trace: " << varp << endl);
|
||||
|
|
@ -668,6 +703,7 @@ class CoverageVisitor final : public VNVisitor {
|
|||
m_objective = true;
|
||||
iterate(nodep);
|
||||
if (checkMaxExprs(falseExprs.size())) return;
|
||||
if (m_seeking == ABORTED) return;
|
||||
|
||||
addExprCoverInc(nodep);
|
||||
const int start = m_exprs.size();
|
||||
|
|
@ -871,26 +907,30 @@ class CoverageVisitor final : public VNVisitor {
|
|||
lineTrack(nodep);
|
||||
}
|
||||
|
||||
// Lambdas not supported for expression coverage
|
||||
void visit(AstWith* nodep) override {
|
||||
VL_RESTORER(m_seeking);
|
||||
if (m_seeking == SEEKING) abortExprCoverage();
|
||||
m_seeking = ABORTED;
|
||||
iterateChildren(nodep);
|
||||
lineTrack(nodep);
|
||||
void visit(AstFuncRef* nodep) override {
|
||||
if (nodep->taskp()->lifetime().isAutomatic()) {
|
||||
visit(static_cast<AstNodeExpr*>(nodep));
|
||||
} else {
|
||||
exprUnsupported(nodep, "non-automatic function");
|
||||
}
|
||||
}
|
||||
|
||||
void visit(AstNodeExpr* nodep) override {
|
||||
if (m_seeking != SEEKING) {
|
||||
iterateChildren(nodep);
|
||||
} else {
|
||||
std::stringstream emitV;
|
||||
V3EmitV::verilogForTree(nodep, emitV);
|
||||
// Add new expression with a single term
|
||||
CoverExpr expr;
|
||||
expr.emplace_back(nodep, m_objective, emitV.str());
|
||||
m_exprs.push_back(std::move(expr));
|
||||
checkMaxExprs();
|
||||
ExprCoverageEligibleVisitor elgibleVisitor(nodep);
|
||||
if (elgibleVisitor.eligible()) {
|
||||
std::stringstream emitV;
|
||||
V3EmitV::verilogForTree(nodep, emitV);
|
||||
// Add new expression with a single term
|
||||
CoverExpr expr;
|
||||
expr.emplace_back(nodep, m_objective, emitV.str());
|
||||
m_exprs.push_back(std::move(expr));
|
||||
checkMaxExprs();
|
||||
} else {
|
||||
exprUnsupported(nodep, "not coverage eligible");
|
||||
}
|
||||
}
|
||||
lineTrack(nodep);
|
||||
}
|
||||
|
|
@ -901,6 +941,17 @@ class CoverageVisitor final : public VNVisitor {
|
|||
lineTrack(nodep);
|
||||
}
|
||||
|
||||
void exprUnsupported(AstNode* nodep, const string& why) {
|
||||
UINFO(9, "unsupported: " << why << " " << nodep << endl);
|
||||
bool wasSeeking = m_seeking == SEEKING;
|
||||
Objective oldSeeking = m_seeking;
|
||||
if (wasSeeking) abortExprCoverage();
|
||||
m_seeking = ABORTED;
|
||||
iterateChildren(nodep);
|
||||
lineTrack(nodep);
|
||||
if (!wasSeeking) m_seeking = oldSeeking;
|
||||
}
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit CoverageVisitor(AstNetlist* rootp) { iterateChildren(rootp); }
|
||||
|
|
|
|||
|
|
@ -155,6 +155,7 @@ class DelayedVisitor final : public VNVisitor {
|
|||
struct { // Stuff needed for Scheme::FlagShared
|
||||
AstActive* activep; // The active block for the Pre/Post logic
|
||||
AstAlwaysPost* postp; // The post block for commiting results
|
||||
AstVarScope* commitFlagp; // The commit flag variable, for reuse
|
||||
AstIf* commitIfp; // The previous if statement for committing, for reuse
|
||||
} m_flagSharedKit;
|
||||
struct { // Stuff needed for Scheme::FlagUnique
|
||||
|
|
@ -346,8 +347,8 @@ class DelayedVisitor final : public VNVisitor {
|
|||
arrSelp->bitp(captureVal(scopep, insertp, arrSelp->bitp()->unlinkFrBack(), tmpName));
|
||||
nodep = arrSelp->fromp();
|
||||
}
|
||||
// What remains must be an AstVarRef
|
||||
UASSERT_OBJ(VN_IS(nodep, VarRef), lhsp, "Malformed LHS in NBA");
|
||||
// What remains must be an AstVarRef, or some sort of select, we assume can reuse it.
|
||||
UASSERT_OBJ(nodep->isPure(), lhsp, "Malformed LHS in NBA");
|
||||
// Now have been converted to use the captured values
|
||||
return lhsp;
|
||||
}
|
||||
|
|
@ -421,6 +422,9 @@ class DelayedVisitor final : public VNVisitor {
|
|||
AstAlwaysPost* const postp = new AstAlwaysPost{flp};
|
||||
activep->addStmtsp(postp);
|
||||
vscpInfo.flagSharedKit().postp = postp;
|
||||
// Initialize
|
||||
vscpInfo.flagSharedKit().commitFlagp = nullptr;
|
||||
vscpInfo.flagSharedKit().commitIfp = nullptr;
|
||||
}
|
||||
void convertSchemeFlagShared(AstAssignDly* nodep, AstVarScope* vscp, VarScopeInfo& vscpInfo) {
|
||||
UASSERT_OBJ(vscpInfo.m_scheme == Scheme::FlagShared, vscp, "Inconsistent NBA scheme");
|
||||
|
|
@ -443,14 +447,16 @@ class DelayedVisitor final : public VNVisitor {
|
|||
const bool consecutive = nodep == m_nextDlyp;
|
||||
m_nextDlyp = VN_CAST(nodep->nextp(), AssignDly);
|
||||
|
||||
VarScopeInfo* const prevVscpInfop = consecutive ? &m_vscpInfo(m_prevVscp) : nullptr;
|
||||
|
||||
// We can reuse the flag of the previous assignment if:
|
||||
const bool reuseTheFlag =
|
||||
// Consecutive NBAs
|
||||
consecutive
|
||||
// ... that use the same scheme
|
||||
&& m_vscpInfo(m_prevVscp).m_scheme == Scheme::FlagShared
|
||||
&& prevVscpInfop->m_scheme == Scheme::FlagShared
|
||||
// ... and share the same overall update domain
|
||||
&& m_vscpInfo(m_prevVscp).senTreep()->sameTree(vscpInfo.senTreep());
|
||||
&& prevVscpInfop->senTreep()->sameTree(vscpInfo.senTreep());
|
||||
|
||||
if (!reuseTheFlag) {
|
||||
// Create new flag
|
||||
|
|
@ -466,10 +472,25 @@ class DelayedVisitor final : public VNVisitor {
|
|||
// Add the 'Post' scheduled commit
|
||||
AstIf* const ifp = new AstIf{flp, new AstVarRef{flp, flagVscp, VAccess::READ}};
|
||||
vscpInfo.flagSharedKit().postp->addStmtsp(ifp);
|
||||
vscpInfo.flagSharedKit().commitFlagp = flagVscp;
|
||||
vscpInfo.flagSharedKit().commitIfp = ifp;
|
||||
} else {
|
||||
// Reuse the commit block of the previous assignment
|
||||
vscpInfo.flagSharedKit().commitIfp = m_vscpInfo(m_prevVscp).flagSharedKit().commitIfp;
|
||||
if (vscp != m_prevVscp) {
|
||||
// Different variable, ensure the commit block exists for this variable,
|
||||
// can reuse existing one with the same flag, otherwise create a new one.
|
||||
AstVarScope* const flagVscp = prevVscpInfop->flagSharedKit().commitFlagp;
|
||||
UASSERT_OBJ(flagVscp, nodep, "Commit flag of previous assignment should exist");
|
||||
if (vscpInfo.flagSharedKit().commitFlagp != flagVscp) {
|
||||
AstIf* const ifp = new AstIf{flp, new AstVarRef{flp, flagVscp, VAccess::READ}};
|
||||
vscpInfo.flagSharedKit().postp->addStmtsp(ifp);
|
||||
vscpInfo.flagSharedKit().commitFlagp = flagVscp;
|
||||
vscpInfo.flagSharedKit().commitIfp = ifp;
|
||||
}
|
||||
} else {
|
||||
// Same variable, reuse the commit block of the previous assignment
|
||||
vscpInfo.flagSharedKit().commitFlagp = prevVscpInfop->flagSharedKit().commitFlagp;
|
||||
vscpInfo.flagSharedKit().commitIfp = prevVscpInfop->flagSharedKit().commitIfp;
|
||||
}
|
||||
++m_nSharedSetFlags;
|
||||
}
|
||||
// Commit the captured value to the captured destination
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ class DescopeVisitor final : public VNVisitor {
|
|||
string name = scopep->name();
|
||||
string::size_type pos;
|
||||
if ((pos = name.rfind('.')) != string::npos) name.erase(0, pos + 1);
|
||||
ret.thisPtr = VSelfPointerText{VSelfPointerText::This(), name};
|
||||
ret.thisPtr = VSelfPointerText{VSelfPointerText::This{}, name};
|
||||
}
|
||||
return ret.thisPtr;
|
||||
}
|
||||
|
|
@ -104,9 +104,9 @@ class DescopeVisitor final : public VNVisitor {
|
|||
if (VN_IS(scopep->modp(), Class)) {
|
||||
// Direct reference to class members are from within the class itself, references from
|
||||
// outside the class must go via AstMemberSel
|
||||
return VSelfPointerText{VSelfPointerText::This()};
|
||||
return VSelfPointerText{VSelfPointerText::This{}};
|
||||
} else if (relativeRefOk && scopep == m_scopep) {
|
||||
return VSelfPointerText{VSelfPointerText::This()};
|
||||
return VSelfPointerText{VSelfPointerText::This{}};
|
||||
} else if (relativeRefOk && !m_modSingleton && scopep->aboveScopep() == m_scopep
|
||||
&& VN_IS(scopep->modp(), Module)) {
|
||||
// Reference to scope of instance directly under this module, can just "this->cell",
|
||||
|
|
@ -215,9 +215,9 @@ class DescopeVisitor final : public VNVisitor {
|
|||
makePublicFuncWrappers();
|
||||
}
|
||||
void visit(AstScope* nodep) override {
|
||||
VL_RESTORER(m_scopep);
|
||||
m_scopep = nodep;
|
||||
iterateChildren(nodep);
|
||||
m_scopep = nullptr;
|
||||
}
|
||||
void visit(AstVarScope* nodep) override {
|
||||
// Delete the varscope when we're finished
|
||||
|
|
|
|||
|
|
@ -193,7 +193,7 @@ void DfgGraph::dumpDotFile(const string& filename, const string& label) const {
|
|||
// This generates a file used by graphviz, https://www.graphviz.org
|
||||
// "hardcoded" parameters:
|
||||
const std::unique_ptr<std::ofstream> os{V3File::new_ofstream(filename)};
|
||||
if (os->fail()) v3fatal("Cannot write to file: " << filename);
|
||||
if (os->fail()) v3fatal("Can't write file: " << filename);
|
||||
dumpDot(*os.get(), label);
|
||||
os->close();
|
||||
}
|
||||
|
|
@ -244,7 +244,7 @@ void DfgGraph::dumpDotUpstreamCone(const string& fileName, const DfgVertex& vtx,
|
|||
const string& name) const {
|
||||
// Open output file
|
||||
const std::unique_ptr<std::ofstream> os{V3File::new_ofstream(fileName)};
|
||||
if (os->fail()) v3fatal("Cannot write to file: " << fileName);
|
||||
if (os->fail()) v3fatal("Can't write file: " << fileName);
|
||||
|
||||
// Header
|
||||
*os << "digraph dfg {\n";
|
||||
|
|
@ -278,7 +278,7 @@ void DfgGraph::dumpDotAllVarConesPrefixed(const string& label) const {
|
|||
const string coneName{prefix + sinkp->varp()->name()};
|
||||
const string fileName{v3Global.debugFilename(coneName) + ".dot"};
|
||||
const std::unique_ptr<std::ofstream> os{V3File::new_ofstream(fileName)};
|
||||
if (os->fail()) v3fatal("Cannot write to file: " << fileName);
|
||||
if (os->fail()) v3fatal("Can't write file: " << fileName);
|
||||
|
||||
// Header
|
||||
*os << "digraph dfg {\n";
|
||||
|
|
|
|||
|
|
@ -199,7 +199,7 @@ class DfgToAstVisitor final : DfgVisitor {
|
|||
|
||||
// VISITORS
|
||||
void visit(DfgVertex* vtxp) override { // LCOV_EXCL_START
|
||||
vtxp->v3fatal("Unhandled DfgVertex: " << vtxp->typeName());
|
||||
vtxp->v3fatalSrc("Unhandled DfgVertex: " << vtxp->typeName());
|
||||
} // LCOV_EXCL_STOP
|
||||
|
||||
void visit(DfgVarPacked* vtxp) override {
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue