Merge branch 'master' into iface-assign-error
This commit is contained in:
commit
da092dc666
|
|
@ -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,138 +23,155 @@ concurrency:
|
|||
|
||||
jobs:
|
||||
|
||||
build:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-24.04, ubuntu-22.04]
|
||||
compiler:
|
||||
- {cc: clang, cxx: clang++}
|
||||
- {cc: gcc, cxx: g++}
|
||||
runs-on: ${{ matrix.os }}
|
||||
name: Build | ${{ matrix.os }} | ${{ matrix.compiler.cc }}
|
||||
env:
|
||||
CI_BUILD_STAGE_NAME: build
|
||||
CI_RUNS_ON: ${{ matrix.os }}
|
||||
CC: ${{ matrix.compiler.cc }}
|
||||
CXX: ${{ matrix.compiler.cxx }}
|
||||
CACHE_BASE_KEY: build-${{ matrix.os }}-${{ matrix.compiler.cc }}
|
||||
CCACHE_MAXSIZE: 1000M # Per build matrix entry (* 5 = 5000M in total)
|
||||
VERILATOR_ARCHIVE: verilator-${{ github.sha }}-${{ matrix.os }}-${{ matrix.compiler.cc }}.tar.gz
|
||||
steps:
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
path: repo
|
||||
|
||||
- name: Cache $CCACHE_DIR
|
||||
uses: actions/cache@v4
|
||||
env:
|
||||
CACHE_KEY: ${{ env.CACHE_BASE_KEY }}-ccache
|
||||
with:
|
||||
path: ${{ env.CCACHE_DIR }}
|
||||
key: ${{ env.CACHE_KEY }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
${{ env.CACHE_KEY }}-
|
||||
|
||||
- name: Install packages for build
|
||||
run: ./ci/ci-install.bash
|
||||
|
||||
- name: Build
|
||||
run: ./ci/ci-script.bash
|
||||
|
||||
- name: Tar up repository
|
||||
working-directory: ${{ github.workspace }}
|
||||
run: tar --posix -c -z -f ${{ env.VERILATOR_ARCHIVE }} repo
|
||||
|
||||
- name: Upload tar archive
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
path: ${{ github.workspace }}/${{ env.VERILATOR_ARCHIVE }}
|
||||
name: ${{ env.VERILATOR_ARCHIVE }}
|
||||
|
||||
test:
|
||||
needs: build
|
||||
build-2404-gcc:
|
||||
name: Build
|
||||
uses: ./.github/workflows/reusable-build.yml
|
||||
with:
|
||||
os: ${{ matrix.os }}
|
||||
cc: ${{ matrix.cc }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
# Ubuntu 24.04 GCC
|
||||
- {os: ubuntu-24.04, compiler: {cc: gcc, cxx: g++}, reloc: 0, suite: dist-vlt-0}
|
||||
- {os: ubuntu-24.04, compiler: {cc: gcc, cxx: g++}, reloc: 0, suite: dist-vlt-1}
|
||||
- {os: ubuntu-24.04, compiler: {cc: gcc, cxx: g++}, reloc: 0, suite: dist-vlt-2}
|
||||
- {os: ubuntu-24.04, compiler: {cc: gcc, cxx: g++}, reloc: 0, suite: dist-vlt-3}
|
||||
- {os: ubuntu-24.04, compiler: {cc: gcc, cxx: g++}, reloc: 0, suite: vltmt-0}
|
||||
- {os: ubuntu-24.04, compiler: {cc: gcc, cxx: g++}, reloc: 0, suite: vltmt-1}
|
||||
# Ubuntu 24.04 Clang
|
||||
- {os: ubuntu-24.04, compiler: {cc: clang, cxx: clang++}, reloc: 0, suite: dist-vlt-0}
|
||||
- {os: ubuntu-24.04, compiler: {cc: clang, cxx: clang++}, reloc: 0, suite: dist-vlt-1}
|
||||
- {os: ubuntu-24.04, compiler: {cc: clang, cxx: clang++}, reloc: 0, suite: dist-vlt-2}
|
||||
- {os: ubuntu-24.04, compiler: {cc: clang, cxx: clang++}, reloc: 0, suite: dist-vlt-3}
|
||||
- {os: ubuntu-24.04, compiler: {cc: clang, cxx: clang++}, reloc: 0, suite: vltmt-0}
|
||||
- {os: ubuntu-24.04, compiler: {cc: clang, cxx: clang++}, reloc: 0, suite: vltmt-1}
|
||||
# Ubuntu 22.04 GCC
|
||||
- {os: ubuntu-22.04, compiler: {cc: gcc, cxx: g++}, reloc: 0, suite: dist-vlt-0}
|
||||
- {os: ubuntu-22.04, compiler: {cc: gcc, cxx: g++}, reloc: 0, suite: dist-vlt-1}
|
||||
- {os: ubuntu-22.04, compiler: {cc: gcc, cxx: g++}, reloc: 0, suite: dist-vlt-2}
|
||||
- {os: ubuntu-22.04, compiler: {cc: gcc, cxx: g++}, reloc: 0, suite: dist-vlt-3}
|
||||
- {os: ubuntu-22.04, compiler: {cc: gcc, cxx: g++}, reloc: 0, suite: vltmt-0}
|
||||
- {os: ubuntu-22.04, compiler: {cc: gcc, cxx: g++}, reloc: 0, suite: vltmt-1}
|
||||
# Ubuntu 22.04 Clang, also test relocation
|
||||
- {os: ubuntu-22.04, compiler: {cc: clang, cxx: clang++}, reloc: 1, suite: dist-vlt-0}
|
||||
- {os: ubuntu-22.04, compiler: {cc: clang, cxx: clang++}, reloc: 1, suite: dist-vlt-1}
|
||||
- {os: ubuntu-22.04, compiler: {cc: clang, cxx: clang++}, reloc: 1, suite: dist-vlt-2}
|
||||
- {os: ubuntu-22.04, compiler: {cc: clang, cxx: clang++}, reloc: 1, suite: dist-vlt-3}
|
||||
- {os: ubuntu-22.04, compiler: {cc: clang, cxx: clang++}, reloc: 1, suite: vltmt-0}
|
||||
- {os: ubuntu-22.04, compiler: {cc: clang, cxx: clang++}, reloc: 1, suite: vltmt-1}
|
||||
runs-on: ${{ matrix.os }}
|
||||
name: Test | ${{ matrix.os }} | ${{ matrix.compiler.cc }} | ${{ matrix.reloc && 'reloc | ' || '' }} ${{ matrix.suite }}
|
||||
env:
|
||||
CI_BUILD_STAGE_NAME: test
|
||||
CI_RUNS_ON: ${{ matrix.os }}
|
||||
CI_RELOC: ${{ matrix.reloc }}
|
||||
CC: ${{ matrix.compiler.cc }}
|
||||
CXX: ${{ matrix.compiler.cxx }}
|
||||
CACHE_BASE_KEY: test-${{ matrix.os }}-${{ matrix.compiler.cc }}-${{ matrix.reloc }}-${{ matrix.suite }}
|
||||
CCACHE_MAXSIZE: 100M # Per build per suite (* 5 * 5 = 2500M in total)
|
||||
VERILATOR_ARCHIVE: verilator-${{ github.sha }}-${{ matrix.os }}-${{ matrix.compiler.cc }}.tar.gz
|
||||
steps:
|
||||
- {os: ubuntu-24.04, cc: gcc}
|
||||
|
||||
- name: Download tar archive
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: ${{ env.VERILATOR_ARCHIVE }}
|
||||
path: ${{ github.workspace }}
|
||||
build-2404-clang:
|
||||
name: Build
|
||||
uses: ./.github/workflows/reusable-build.yml
|
||||
with:
|
||||
os: ${{ matrix.os }}
|
||||
cc: ${{ matrix.cc }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- {os: ubuntu-24.04, cc: clang}
|
||||
|
||||
- name: Unpack tar archive
|
||||
working-directory: ${{ github.workspace }}
|
||||
run: tar -x -z -f ${{ env.VERILATOR_ARCHIVE }}
|
||||
build-2204-gcc:
|
||||
name: Build
|
||||
uses: ./.github/workflows/reusable-build.yml
|
||||
with:
|
||||
os: ${{ matrix.os }}
|
||||
cc: ${{ matrix.cc }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- {os: ubuntu-22.04, cc: gcc}
|
||||
|
||||
- name: Cache $CCACHE_DIR
|
||||
uses: actions/cache@v4
|
||||
env:
|
||||
CACHE_KEY: ${{ env.CACHE_BASE_KEY }}-ccache2
|
||||
with:
|
||||
path: ${{ env.CCACHE_DIR }}
|
||||
key: ${{ env.CACHE_KEY }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
${{ env.CACHE_KEY }}-
|
||||
build-2204-clang:
|
||||
name: Build
|
||||
uses: ./.github/workflows/reusable-build.yml
|
||||
with:
|
||||
os: ${{ matrix.os }}
|
||||
cc: ${{ matrix.cc }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- {os: ubuntu-22.04, cc: clang}
|
||||
|
||||
- name: Install test dependencies
|
||||
run: ./ci/ci-install.bash
|
||||
test-2404-gcc:
|
||||
name: Test | ${{ matrix.os }} | ${{ matrix.cc }}
|
||||
needs: build-2404-gcc
|
||||
uses: ./.github/workflows/reusable-test.yml
|
||||
with:
|
||||
os: ${{ matrix.os }}
|
||||
cc: ${{ matrix.cc }}
|
||||
reloc: ${{ matrix.reloc }}
|
||||
suite: ${{ matrix.suite }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
# Ubuntu 24.04 gcc
|
||||
- {os: ubuntu-24.04, cc: gcc, reloc: 0, suite: dist-vlt-0}
|
||||
- {os: ubuntu-24.04, cc: gcc, reloc: 0, suite: dist-vlt-1}
|
||||
- {os: ubuntu-24.04, cc: gcc, reloc: 0, suite: dist-vlt-2}
|
||||
- {os: ubuntu-24.04, cc: gcc, reloc: 0, suite: dist-vlt-3}
|
||||
- {os: ubuntu-24.04, cc: gcc, reloc: 0, suite: vltmt-0}
|
||||
- {os: ubuntu-24.04, cc: gcc, reloc: 0, suite: vltmt-1}
|
||||
- {os: ubuntu-24.04, cc: gcc, reloc: 0, suite: vltmt-2}
|
||||
|
||||
- name: Test
|
||||
env:
|
||||
TESTS: ${{ matrix.suite }}
|
||||
run: ./ci/ci-script.bash
|
||||
test-2404-clang:
|
||||
name: Test | ${{ matrix.os }} | ${{ matrix.cc }}
|
||||
needs: build-2404-clang
|
||||
uses: ./.github/workflows/reusable-test.yml
|
||||
with:
|
||||
os: ${{ matrix.os }}
|
||||
cc: ${{ matrix.cc }}
|
||||
reloc: ${{ matrix.reloc }}
|
||||
suite: ${{ matrix.suite }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
# Ubuntu 24.04 clang
|
||||
- {os: ubuntu-24.04, cc: clang, reloc: 0, suite: dist-vlt-0}
|
||||
- {os: ubuntu-24.04, cc: clang, reloc: 0, suite: dist-vlt-1}
|
||||
- {os: ubuntu-24.04, cc: clang, reloc: 0, suite: dist-vlt-2}
|
||||
- {os: ubuntu-24.04, cc: clang, reloc: 0, suite: dist-vlt-3}
|
||||
- {os: ubuntu-24.04, cc: clang, reloc: 0, suite: vltmt-0}
|
||||
- {os: ubuntu-24.04, cc: clang, reloc: 0, suite: vltmt-1}
|
||||
- {os: ubuntu-24.04, cc: clang, reloc: 0, suite: vltmt-2}
|
||||
|
||||
test-2204-gcc:
|
||||
name: Test | ${{ matrix.os }} | ${{ matrix.cc }}
|
||||
needs: build-2204-gcc
|
||||
uses: ./.github/workflows/reusable-test.yml
|
||||
with:
|
||||
os: ${{ matrix.os }}
|
||||
cc: ${{ matrix.cc }}
|
||||
reloc: ${{ matrix.reloc }}
|
||||
suite: ${{ matrix.suite }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
# Ubuntu 22.04 gcc
|
||||
- {os: ubuntu-22.04, cc: gcc, reloc: 0, suite: dist-vlt-0}
|
||||
- {os: ubuntu-22.04, cc: gcc, reloc: 0, suite: dist-vlt-1}
|
||||
- {os: ubuntu-22.04, cc: gcc, reloc: 0, suite: dist-vlt-2}
|
||||
- {os: ubuntu-22.04, cc: gcc, reloc: 0, suite: dist-vlt-3}
|
||||
- {os: ubuntu-22.04, cc: gcc, reloc: 0, suite: vltmt-0}
|
||||
- {os: ubuntu-22.04, cc: gcc, reloc: 0, suite: vltmt-1}
|
||||
- {os: ubuntu-22.04, cc: gcc, reloc: 0, suite: vltmt-2}
|
||||
|
||||
test-2204-clang:
|
||||
name: Test | ${{ matrix.os }} | ${{ matrix.cc }}
|
||||
needs: build-2204-clang
|
||||
uses: ./.github/workflows/reusable-test.yml
|
||||
with:
|
||||
os: ${{ matrix.os }}
|
||||
cc: ${{ matrix.cc }}
|
||||
reloc: ${{ matrix.reloc }}
|
||||
suite: ${{ matrix.suite }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
# Ubuntu 22.04 clang, also test relocation
|
||||
- {os: ubuntu-22.04, cc: clang, reloc: 1, suite: dist-vlt-0}
|
||||
- {os: ubuntu-22.04, cc: clang, reloc: 1, suite: dist-vlt-1}
|
||||
- {os: ubuntu-22.04, cc: clang, reloc: 1, suite: dist-vlt-2}
|
||||
- {os: ubuntu-22.04, cc: clang, reloc: 1, suite: dist-vlt-3}
|
||||
- {os: ubuntu-22.04, cc: clang, reloc: 1, suite: vltmt-0}
|
||||
- {os: ubuntu-22.04, cc: clang, reloc: 1, suite: vltmt-1}
|
||||
- {os: ubuntu-22.04, cc: clang, reloc: 1, suite: vltmt-2}
|
||||
|
||||
lint-py:
|
||||
runs-on: ubuntu-22.04
|
||||
name: Lint Python
|
||||
env:
|
||||
CI_OS_NAME: linux
|
||||
CI_COMMIT: ${{ github.sha }}
|
||||
CI_BUILD_STAGE_NAME: build
|
||||
CI_RUNS_ON: ubuntu-22.04
|
||||
CCACHE_COMPRESS: 1
|
||||
CCACHE_DIR: ${{ github.workspace }}/.ccache
|
||||
CCACHE_LIMIT_MULTIPLE: 0.95
|
||||
strategy:
|
||||
fail-fast: false
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
|
|
|||
|
|
@ -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.035
|
||||
VERSION 5.037
|
||||
HOMEPAGE_URL https://verilator.org
|
||||
LANGUAGES CXX
|
||||
)
|
||||
|
|
@ -134,10 +134,7 @@ configure_package_config_file(
|
|||
INSTALL_DESTINATION .
|
||||
)
|
||||
|
||||
install(
|
||||
FILES ${CMAKE_CURRENT_BINARY_DIR}/verilator-config.cmake
|
||||
DESTINATION .
|
||||
)
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/verilator-config.cmake DESTINATION .)
|
||||
|
||||
configure_package_config_file(
|
||||
verilator-config-version.cmake.in
|
||||
|
|
|
|||
68
Changes
68
Changes
|
|
@ -8,26 +8,59 @@ The changes in each Verilator version are described below. The
|
|||
contributors that suggested a given feature are shown in []. Thanks!
|
||||
|
||||
|
||||
Verilator 5.035 devel
|
||||
Verilator 5.037 devel
|
||||
==========================
|
||||
|
||||
**Major:**
|
||||
|
||||
* Add `--trace-saif` for SAIF power traces (#5812). [Mateusz Gancarz]
|
||||
* Change `--output-groups` to default to value of `--build-jobs` (#5751).
|
||||
Those using build farms may need to now use `--output-groups 0` or otherwise.
|
||||
|
||||
**Other:**
|
||||
|
||||
* Add BADVLTPRAGMA on unknown Verilator pragmas (#5945). [Shou-Li Hsu]
|
||||
* Add PROCINITASSIGN on initial assignments to process variables (#2481). [Niraj Menon]
|
||||
* Fix filename backslash escapes in C code (#5947).
|
||||
* Fix C++ widths in V3Expand (#5953) (#5975). [Geza Lore]
|
||||
* Fix constant propagation of post-expand stages (#5955) (#5963) (#5969) (#5972) (#5983).
|
||||
* Fix sign extension of signed compared with unsigned case items (#5968).
|
||||
* Fix always processes ignoring $finish (#5971). [Hennadii Chernyshchyk]
|
||||
* Fix streaming to/from packed arrays (#5976). [Geza Lore]
|
||||
|
||||
|
||||
Verilator 5.036 2025-04-27
|
||||
==========================
|
||||
|
||||
**Important:**
|
||||
|
||||
* Change `--output-groups` to default to value of `--build-jobs` (#5751).
|
||||
Those using build farms may need to now use `--output-groups 0` or otherwise.
|
||||
* Support user-defined primitives (UDPs) (#468) (#5807) (#5936). [Zhou Shen, Krzysztof Sychla, et al]
|
||||
* Add `--trace-saif` for SAIF power traces (#5812) (#5914). [Mateusz Gancarz]
|
||||
|
||||
**Other:**
|
||||
|
||||
* Change `--trace` to `--trace-vcd`.
|
||||
* Support simple `checker` blocks (#4066). [Srinivasan Venkataramanan]
|
||||
* Support force/release with a variable reference (#5721) (#5810). [Bartłomiej Chmiel, Antmicro Ltd.]
|
||||
* Support constraint random for StructArray (#5805) (#5937). [Yilou Wang]
|
||||
* Support command-line overriding `define (#5900) (#5908). [Brian Li]
|
||||
* Support soft unions (#5912) (#5932). [Robin Heinemann]
|
||||
* Support `$setuphold` (#5884). [Krzysztof Sychla]
|
||||
* Support assigning unpacked arrays to queues (#5924) (#5928). [Brian Li]
|
||||
* Support `systemc_interface and related inside `class`.
|
||||
* Support class extends with arguments.
|
||||
* Add multi-thread hierarchical simulation (#2583) (#5871). [Bartłomiej Chmiel, Antmicro Ltd.]
|
||||
* Add check for `let` misused in statement context (#5733).
|
||||
* Add used language to `--preproc-resolve` output (#5795). [Kamil Rakoczy, Antmicro Ltd.]
|
||||
* Add `--make json` to enable integration with non-make/cmake build systems (#5799). [Andrew Voznytsa]
|
||||
* Add numactl-like automatic assignment of processor affinity (#5911).
|
||||
* Add ccache support for generated cmake files (#5926) (#5930). [Andrew Voznytsa]
|
||||
* Add visualization of multi-threaded waiting time with verilator_gantt (#5929). [Bartłomiej Chmiel, Antmicro Ltd.]
|
||||
* Add suggesting isolate_assignments to UNOPTFLAT (#5942). [John Khoo]
|
||||
* Add profiling of hierarchical mtasks with verilator_gantt (#5956). [Bartłomiej Chmiel, Antmicro Ltd.]
|
||||
* Add empty veriuser.h for legacy compatibility.
|
||||
* Add DEPRECATED warning on `--xml-only` and `--xml-output`.
|
||||
* Remove unused gtkwave/wavealloca.h. [Geza Lore]
|
||||
* Optimize automatic splitting of some packed variables (#5843). [Geza Lore]
|
||||
* Optimize trigger vector in whole words (#5857). [Geza Lore]
|
||||
* Fix parameters referencing interface fields (#1593) (#5910). [Ryszard Rozak, Antmicro Ltd.]
|
||||
* Fix interface array assignments (#5270) (#5633) (#5869). [Nick Brereton]
|
||||
* Fix change detection at time 0 (#5499) (#5864). [Geza Lore]
|
||||
* Fix foreach of associative array inside a constraint block (#5727) (#5841). [Yilou Wang]
|
||||
* Fix reset of automatic function variables (#5747). [Augustin Fabre]
|
||||
|
|
@ -43,8 +76,9 @@ Verilator 5.035 devel
|
|||
* Fix assignment pattern as function argument (#5839).
|
||||
* Fix checking built-in method arguments (#5839).
|
||||
* Fix splitting of packed ports with non-zero based ranges (#5842). [Geza Lore]
|
||||
* Fix delays inside interface functions, and classes inside interfaces (#5846).
|
||||
* Fix NBA shared flag reuse (#5848). [Geza Lore]
|
||||
* Fix expression coverage on additional nodes (#5849 partial) (#5867). [Todd Strader]
|
||||
* Fix multiple expression coverage issues (#5849 partial) (#5867) (#5870). [Todd Strader]
|
||||
* Fix unresolved typedefs as parameters (#5850). [Eugene Feinberg, Brian Li]
|
||||
* Fix removal of callbacks no longer in current list (#5851) (#5852). [Gilberto Abram]
|
||||
* Fix segmentation fault on member compare (#5853).
|
||||
|
|
@ -52,6 +86,22 @@ Verilator 5.035 devel
|
|||
* Fix streaming of unpacked arrays concatenations (#5856). [Ryszard Rozak, Antmicro Ltd.]
|
||||
* Fix Windows paths in Perl (#5858) (#5860). [Tobias Jensen]
|
||||
* Fix algorithm header portability in V3Os.cpp (for std::replace) (#5861). [William D. Jones]
|
||||
* Fix `$fscanf` not returning -1 on EOF (#5881).
|
||||
* Fix PGO profiling for multi-threaded hierarchical scenarios (#5888). [Bartłomiej Chmiel, Antmicro Ltd.]
|
||||
* Fix V3Gate assertion on eliminated circular logic (#5889) (#5898). [Geza Lore]
|
||||
* Fix process comparisons (#5896).
|
||||
* Fix ccache with clang (#5899). [Geza Lore]
|
||||
* Fix delayed assignment malformed LHS assertion (#5904).
|
||||
* Fix segfault in fork synchronization (#5906). [Krzysztof Bieganski, Antmicro Ltd.]
|
||||
* Fix `new this` (#5909).
|
||||
* Fix assignments with stream expressions and unpacked arrays (#5915). [Ryszard Rozak, Antmicro Ltd.]
|
||||
* Fix LATCH warning for automatic variables (#5918). [Yutetsu TAKATSUKASA]
|
||||
* Fix %% on elaboration severity tasks (#5922). [Ethan Sifferman]
|
||||
* Fix port default values with `--coverage-line` creating `0=0` (#5920). [Drew Ranck]
|
||||
* Fix vlSelf error on fork repeats (#5927). [Drew Ranck]
|
||||
* Fix missing C++ regeneration when Verilog files are updated (#5934). [Zhouyi Shen]
|
||||
* Fix stream expressions (#5938). [Ryszard Rozak, Antmicro Ltd.]
|
||||
* Fix packed selection using over 32-bit index (#5957).
|
||||
|
||||
|
||||
Verilator 5.034 2025-02-24
|
||||
|
|
@ -299,7 +349,7 @@ Verilator 5.028 2024-08-21
|
|||
* Add parsing but otherwise ignore std::randomize (#5354). [Arkadiusz Kozdra, Antmicro Ltd.]
|
||||
* Add Verilated cc define when `--timing` used (#5383). [Kaleb Barrett]
|
||||
* Improve emitted code to use a reference for VlSelf (#5254). [Yangyu Chen]
|
||||
* Fix monitor block sensitivity items (#4400) (#5294). [Udaya Raj Subedi]
|
||||
* Fix monitor block sensitivity items (#4040) (#4400) (#5294). [Udaya Raj Subedi]
|
||||
* Fix fusing macro arguments to not ignore whitespace (#5061). [Tudor Timi]
|
||||
* Fix optimized-out sensitivity trees with `--timing` (#5080) (#5349). [Krzysztof Bieganski, Antmicro Ltd.]
|
||||
* Fix classes/modules of case-similar names (#5109). [Arkadiusz Kozdra]
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -341,11 +341,12 @@ detailed descriptions of these arguments.
|
|||
--no-debug-leak Disable leaking memory in --debug mode
|
||||
--debugi <level> Enable debugging at a specified level
|
||||
--debugi-<srcfile> <level> Enable debugging a source file at a level
|
||||
--decorations <level> Set output comment and spacing level
|
||||
--no-decoration Disable comments and lower spacing level
|
||||
--decorations <level> Set output comment and spacing level
|
||||
--default-language <lang> Default language to parse
|
||||
+define+<var>=<value> Set preprocessor define
|
||||
--dpi-hdr-only Only produce the DPI header file
|
||||
--dump-<srcfile> Enable dumping everything in source file
|
||||
--dump-defines Show preprocessor defines with -E
|
||||
--dump-dfg Enable dumping DfgGraphs to .dot files
|
||||
--dump-graph Enable dumping V3Graphs to .dot files
|
||||
|
|
@ -353,12 +354,11 @@ detailed descriptions of these arguments.
|
|||
--dump-tree-addrids Use short identifiers instead of addresses
|
||||
--dump-tree-dot Enable dumping Ast .tree.dot debug files
|
||||
--dump-tree-json Enable dumping Ast .tree.json files and .tree.meta.json file
|
||||
--dump-<srcfile> Enable dumping everything in source file
|
||||
--dumpi-<srcfile> <level> Enable dumping everything in source file at level
|
||||
--dumpi-dfg <level> Enable dumping DfgGraphs to .dot files at level
|
||||
--dumpi-graph <level> Enable dumping V3Graphs to .dot files at level
|
||||
--dumpi-tree <level> Enable dumping Ast .tree files at level
|
||||
--dumpi-tree-json <level> Enable dumping Ast .tree.json files at level
|
||||
--dumpi-<srcfile> <level> Enable dumping everything in source file at level
|
||||
-E Preprocess, but do not compile
|
||||
--emit-accessors Emit getter and setter methods for model top class
|
||||
--error-limit <value> Abort after this number of errors
|
||||
|
|
@ -390,8 +390,8 @@ detailed descriptions of these arguments.
|
|||
--no-json-edit-nums Don't dump editNum in .tree.json files
|
||||
--no-json-ids Don't use short identifiers instead of adresses/paths in .tree.json
|
||||
--json-only Create JSON parser output (.tree.json and .meta.json)
|
||||
--json-only-output .tree.json output filename
|
||||
--json-only-meta-output .tree.meta.json output filename
|
||||
--json-only-output .tree.json output filename
|
||||
--l2-name <value> Verilog scope name of the top module
|
||||
--language <lang> Default language standard to parse
|
||||
-LDFLAGS <flags> Linker pre-object arguments for makefile
|
||||
|
|
@ -399,20 +399,20 @@ detailed descriptions of these arguments.
|
|||
+libext+<ext>+[ext]... Extensions for finding modules
|
||||
--lint-only Lint, but do not make output
|
||||
--localize-max-size <value> Tune localize optimization variable size
|
||||
--make <build-tool> Generate scripts for specified build tool
|
||||
-MAKEFLAGS <flags> Arguments to pass to make during --build
|
||||
--main Generate C++ main() file
|
||||
--main-top-name Specify top name passed to Verilated model in generated C++ main
|
||||
--make <build-tool> Generate scripts for specified build tool
|
||||
-MAKEFLAGS <flags> Arguments to pass to make during --build
|
||||
--max-num-width <value> Maximum number width (default: 64K)
|
||||
--Mdir <directory> Name of output object directory
|
||||
--MMD Create .d dependency files
|
||||
--mod-prefix <topname> Name to prepend to lower classes
|
||||
--MP Create phony dependency targets
|
||||
+notimingchecks Ignored
|
||||
-o <executable> Name of final executable
|
||||
-O0 Disable optimizations
|
||||
-O3 High-performance optimizations
|
||||
-O<optimization-letter> Selectable optimizations
|
||||
-o <executable> Name of final executable
|
||||
--output-groups <numfiles> Group .cpp files into larger ones
|
||||
--output-split <statements> Split .cpp files into pieces
|
||||
--output-split-cfuncs <statements> Split model functions
|
||||
|
|
@ -467,13 +467,13 @@ detailed descriptions of these arguments.
|
|||
--threads <threads> Enable multithreading
|
||||
--threads-dpi <mode> Enable multithreaded DPI
|
||||
--threads-max-mtasks <mtasks> Tune maximum mtask partitioning
|
||||
--timing Enable timing support
|
||||
--no-timing Disable timing support
|
||||
--timescale <timescale> Sets default timescale
|
||||
--timescale-override <timescale> Overrides all timescales
|
||||
--timing Enable timing support
|
||||
--no-timing Disable timing support
|
||||
--top <topname> Alias of --top-module
|
||||
--top-module <topname> Name of top-level input module
|
||||
--trace Enable waveform creation
|
||||
--trace Enable VCD waveform creation
|
||||
--trace-coverage Enable tracing of coverage
|
||||
--trace-depth <levels> Depth of tracing
|
||||
--trace-fst Enable FST waveform creation
|
||||
|
|
@ -485,6 +485,7 @@ detailed descriptions of these arguments.
|
|||
--trace-threads <threads> Enable FST waveform creation on separate threads
|
||||
--no-trace-top Do not emit traces for signals in the top module generated by verilator
|
||||
--trace-underscore Enable tracing of _signals
|
||||
--trace-vcd Enable VCD waveform creation
|
||||
-U<var> Undefine preprocessor define
|
||||
--no-unlimited-stack Don't disable stack size limit
|
||||
--unroll-count <loops> Tune maximum loop iterations
|
||||
|
|
@ -493,8 +494,8 @@ detailed descriptions of these arguments.
|
|||
-V Verbose version and config
|
||||
-v <filename> Verilog library
|
||||
--valgrind Run Verilator under valgrind
|
||||
--verilate-jobs Job threads for Verilation stage
|
||||
--no-verilate Skip Verilation and just compile previously Verilated code
|
||||
--verilate-jobs Job threads for Verilation stage
|
||||
+verilog1995ext+<ext> Synonym for +1364-1995ext+<ext>
|
||||
+verilog2001ext+<ext> Synonym for +1364-2001ext+<ext>
|
||||
--version Show program version and exits
|
||||
|
|
@ -527,9 +528,9 @@ description of these arguments.
|
|||
|
||||
=for VL_SPHINX_EXTRACT "_build/gen/args_verilated.rst"
|
||||
|
||||
+verilator+coverage+file+<filename> Set coverage output filename
|
||||
+verilator+debug Enable debugging
|
||||
+verilator+debugi+<value> Enable debugging at a level
|
||||
+verilator+coverage+file+<filename> Set coverage output filename
|
||||
+verilator+error+limit+<value> Set error limit
|
||||
+verilator+help Show help
|
||||
+verilator+noassert Disable assert checking
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -55,16 +55,16 @@ if [ "$CI_BUILD_STAGE_NAME" = "build" ]; then
|
|||
sudo apt-get update
|
||||
sudo apt-get install ccache help2man libfl-dev ||
|
||||
sudo apt-get install ccache help2man libfl-dev
|
||||
if [ "$CI_RUNS_ON" != "ubuntu-22.04" ]; then
|
||||
if [[ ! "$CI_RUNS_ON" =~ "ubuntu-22.04" ]]; then
|
||||
# Some conflict of libunwind verison on 22.04, can live without it for now
|
||||
sudo apt-get install libgoogle-perftools-dev ||
|
||||
sudo apt-get install libgoogle-perftools-dev
|
||||
fi
|
||||
if [ "$CI_RUNS_ON" = "ubuntu-20.04" ] || [ "$CI_RUNS_ON" = "ubuntu-22.04" ] || [ "$CI_RUNS_ON" = "ubuntu-24.04" ]; then
|
||||
if [[ "$CI_RUNS_ON" =~ "ubuntu-20.04" ]] || [[ "$CI_RUNS_ON" =~ "ubuntu-22.04" ]] || [[ "$CI_RUNS_ON" =~ "ubuntu-24.04" ]]; then
|
||||
sudo apt-get install libsystemc libsystemc-dev ||
|
||||
sudo apt-get install libsystemc libsystemc-dev
|
||||
fi
|
||||
if [ "$CI_RUNS_ON" = "ubuntu-22.04" ] || [ "$CI_RUNS_ON" = "ubuntu-24.04" ]; then
|
||||
if [[ "$CI_RUNS_ON" =~ "ubuntu-22.04" ]] || [[ "$CI_RUNS_ON" =~ "ubuntu-24.04" ]]; then
|
||||
sudo apt-get install bear mold ||
|
||||
sudo apt-get install bear mold
|
||||
fi
|
||||
|
|
@ -92,11 +92,11 @@ elif [ "$CI_BUILD_STAGE_NAME" = "test" ]; then
|
|||
sudo apt-get install gdb gtkwave lcov libfl-dev ccache jq z3 ||
|
||||
sudo apt-get install gdb gtkwave lcov libfl-dev ccache jq z3
|
||||
# Required for test_regress/t/t_dist_attributes.py
|
||||
if [ "$CI_RUNS_ON" = "ubuntu-22.04" ] || [ "$CI_RUNS_ON" = "ubuntu-24.04" ]; then
|
||||
if [[ "$CI_RUNS_ON" =~ "ubuntu-22.04" ]] || [[ "$CI_RUNS_ON" =~ "ubuntu-24.04" ]]; then
|
||||
sudo apt-get install python3-clang mold ||
|
||||
sudo apt-get install python3-clang mold
|
||||
fi
|
||||
if [ "$CI_RUNS_ON" = "ubuntu-20.04" ] || [ "$CI_RUNS_ON" = "ubuntu-22.04" ] || [ "$CI_RUNS_ON" = "ubuntu-24.04" ]; then
|
||||
if [[ "$CI_RUNS_ON" =~ "ubuntu-20.04" ]] || [[ "$CI_RUNS_ON" =~ "ubuntu-22.04" ]] || [[ "$CI_RUNS_ON" =~ "ubuntu-24.04" ]]; then
|
||||
sudo apt-get install libsystemc-dev ||
|
||||
sudo apt-get install libsystemc-dev
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ elif [ "$CI_BUILD_STAGE_NAME" = "test" ]; then
|
|||
fi
|
||||
|
||||
# Run sanitize on Ubuntu 22.04 only
|
||||
( [ "$CI_RUNS_ON" = 'ubuntu-22.04' ] || [ "$CI_RUNS_ON" = 'ubuntu-24.04' ] ) && sanitize='--sanitize' || sanitize=''
|
||||
( [[ "$CI_RUNS_ON" =~ 'ubuntu-22.04' ]] || [[ "$CI_RUNS_ON" =~ 'ubuntu-24.04' ]] ) && sanitize='--sanitize' || sanitize=''
|
||||
|
||||
TEST_REGRESS=test_regress
|
||||
if [ "$CI_RELOC" == 1 ]; then
|
||||
|
|
@ -109,22 +109,25 @@ elif [ "$CI_BUILD_STAGE_NAME" = "test" ]; then
|
|||
ccache -z
|
||||
case $TESTS in
|
||||
dist-vlt-0)
|
||||
"$MAKE" -C "$TEST_REGRESS" SCENARIOS="--dist --vlt $sanitize" DRIVER_HASHSET=--hashset=0/4
|
||||
"$MAKE" -C "$TEST_REGRESS" SCENARIOS="--dist --vlt --driver-clean $sanitize" DRIVER_HASHSET=--hashset=0/4
|
||||
;;
|
||||
dist-vlt-1)
|
||||
"$MAKE" -C "$TEST_REGRESS" SCENARIOS="--dist --vlt $sanitize" DRIVER_HASHSET=--hashset=1/4
|
||||
"$MAKE" -C "$TEST_REGRESS" SCENARIOS="--dist --vlt --driver-clean $sanitize" DRIVER_HASHSET=--hashset=1/4
|
||||
;;
|
||||
dist-vlt-2)
|
||||
"$MAKE" -C "$TEST_REGRESS" SCENARIOS="--dist --vlt $sanitize" DRIVER_HASHSET=--hashset=2/4
|
||||
"$MAKE" -C "$TEST_REGRESS" SCENARIOS="--dist --vlt --driver-clean $sanitize" DRIVER_HASHSET=--hashset=2/4
|
||||
;;
|
||||
dist-vlt-3)
|
||||
"$MAKE" -C "$TEST_REGRESS" SCENARIOS="--dist --vlt $sanitize" DRIVER_HASHSET=--hashset=3/4
|
||||
"$MAKE" -C "$TEST_REGRESS" SCENARIOS="--dist --vlt --driver-clean $sanitize" DRIVER_HASHSET=--hashset=3/4
|
||||
;;
|
||||
vltmt-0)
|
||||
"$MAKE" -C "$TEST_REGRESS" SCENARIOS=--vltmt DRIVER_HASHSET=--hashset=0/2
|
||||
"$MAKE" -C "$TEST_REGRESS" SCENARIOS="--vltmt --driver-clean" DRIVER_HASHSET=--hashset=0/3
|
||||
;;
|
||||
vltmt-1)
|
||||
"$MAKE" -C "$TEST_REGRESS" SCENARIOS=--vltmt DRIVER_HASHSET=--hashset=1/2
|
||||
"$MAKE" -C "$TEST_REGRESS" SCENARIOS="--vltmt --driver-clean" DRIVER_HASHSET=--hashset=1/3
|
||||
;;
|
||||
vltmt-2)
|
||||
"$MAKE" -C "$TEST_REGRESS" SCENARIOS="--vltmt --driver-clean" DRIVER_HASHSET=--hashset=2/3
|
||||
;;
|
||||
coverage-all)
|
||||
nodist/code_coverage --stages 1-
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
# Then 'make maintainer-dist'
|
||||
#AC_INIT([Verilator],[#.### YYYY-MM-DD])
|
||||
#AC_INIT([Verilator],[#.### devel])
|
||||
AC_INIT([Verilator],[5.035 devel],
|
||||
AC_INIT([Verilator],[5.037 devel],
|
||||
[https://verilator.org],
|
||||
[verilator],[https://verilator.org])
|
||||
|
||||
|
|
@ -432,6 +432,7 @@ AC_SUBST(HAVE_COROUTINES)
|
|||
|
||||
# Flags for compiling Verilator internals including parser always
|
||||
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-Qunused-arguments)
|
||||
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-Xclang -fno-pch-timestamp)
|
||||
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-faligned-new)
|
||||
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-Wno-unused-parameter)
|
||||
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-Wno-shadow)
|
||||
|
|
@ -469,6 +470,7 @@ CFG_CXX_FLAGS_CMAKE="-faligned-new"
|
|||
m4_foreach([cflag],[
|
||||
[-fbracket-depth=4096],
|
||||
[-fcf-protection=none],
|
||||
[-Xclang -fno-pch-timestamp],
|
||||
[-mno-cet],
|
||||
[-Qunused-arguments],
|
||||
[-Wno-bool-operation],
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ Arkadiusz Kozdra
|
|||
Arthur Rosa
|
||||
Aylon Chaim Porat
|
||||
Bartłomiej Chmiel
|
||||
Brian Li
|
||||
Cameron Kirk
|
||||
Chih-Mao Chen
|
||||
Chris Bachhuber
|
||||
|
|
@ -109,6 +110,7 @@ Jiuyang Liu
|
|||
Joey Liu
|
||||
John Coiner
|
||||
John Demme
|
||||
John Khoo
|
||||
John Wehle
|
||||
Jonathan Drolet
|
||||
Jonathan Schröter
|
||||
|
|
@ -134,6 +136,7 @@ Krzysztof Boronski
|
|||
Krzysztof Boroński
|
||||
Krzysztof Obłonczek
|
||||
Krzysztof Starecki
|
||||
Krzysztof Sychla
|
||||
Kuba Ober
|
||||
Larry Doolittle
|
||||
Liam Braun
|
||||
|
|
@ -194,6 +197,7 @@ Ricardo Barbedo
|
|||
Richard Myers
|
||||
Risto Pejašinović
|
||||
Robert Balas
|
||||
Robin Heinemann
|
||||
Rupert Swarbrick
|
||||
Ryan Ziegler
|
||||
Ryszard Rozak
|
||||
|
|
@ -246,6 +250,7 @@ Yutetsu TAKATSUKASA
|
|||
Yves Mathieu
|
||||
Zhanglei Wang
|
||||
Zhou Shen
|
||||
Zhouyi Shen
|
||||
Zixi Li
|
||||
أحمد المحمودي
|
||||
404allen404
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
.. comment: generated by t_lint_badvltpragma_bad
|
||||
.. code-block:: sv
|
||||
:emphasize-lines: 1
|
||||
|
||||
// verilator lintt_off WIDTH //<--- Warning (lint_off misspelled)
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
.. comment: generated by t_lint_badvltpragma_bad
|
||||
.. code-block::
|
||||
:emphasize-lines: 1,2
|
||||
|
||||
%Error-BADVLTPRAGMA: example.v:1:4 Unknown verilator comment: '/*verilator lintt_off WIDTH <--- Warning (lint_off misspelled)*/'
|
||||
7 | /*verilator lintt_off WIDTH <--- Warning (lint_off misspelled)*/
|
||||
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
.. comment: generated by t_lint_pinmissing_bad
|
||||
.. code-block::
|
||||
|
||||
%Warning-PINMISSING: example.v:1:8 Cell has missing pin: 'port'
|
||||
%Warning-PINMISSING: example.v:1:8 Instance has missing pin: 'port'
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
.. comment: generated by t_lint_procassinit_bad
|
||||
.. code-block:: sv
|
||||
:linenos:
|
||||
:emphasize-lines: 1,5
|
||||
|
||||
logic flop_out = 1; // <--- Warning
|
||||
|
||||
always @(posedge clk, negedge reset_l) begin
|
||||
if (enable) begin
|
||||
flop_out <= ~in; // <--- Use of initialized
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
.. comment: generated by t_lint_procassinit_bad
|
||||
.. code-block:: sv
|
||||
:linenos:
|
||||
:emphasize-lines: 5
|
||||
|
||||
logic flop2_out;
|
||||
|
||||
always @(posedge clk, negedge reset_l) begin
|
||||
if (!reset_l) begin
|
||||
flop2_out <= '1; // <--- Added reset init
|
||||
end
|
||||
else if (enable) begin
|
||||
flop2_out <= ~in;
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
.. comment: generated by t_lint_procassinit_bad
|
||||
.. code-block::
|
||||
|
||||
%Warning-PROCASSINIT: example.v:1:21 Procedural assignment to declaration with initial value: 'flop_out'
|
||||
: ... note: In instance 't'
|
||||
: ... Location of variable initialization
|
||||
26 | logic flop_out = 1;
|
||||
| ^
|
||||
example.v:1:10 ... Location of variable process write
|
||||
: ... Perhaps should initialize instead using a reset in this process
|
||||
30 | flop_out <= ~in;
|
||||
| ^~~~~~~~
|
||||
|
|
@ -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,7 +72,7 @@ and the design can be easily manually reduced. In other cases, the bug is
|
|||
caused by a complex interaction of many parts of the design, and it is not
|
||||
clear which parts are necessary to reproduce the bug. In these cases, an
|
||||
Open Source tool called `sv-bugpoint
|
||||
<https://github.com/antmicro/sv-bugpoint>_` can be used to automatically
|
||||
<https://github.com/antmicro/sv-bugpoint>`_ can be used to automatically
|
||||
reduce a SystemVerilog design to the smallest possible reproducer.
|
||||
It can be used to automatically reduce a design with hundreds of thousands of
|
||||
lines to a minimal test case while preserving the bug-inducing behavior.
|
||||
|
|
|
|||
|
|
@ -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,6 +1,7 @@
|
|||
.. Copyright 2003-2025 by Wilson Snyder.
|
||||
.. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
===================
|
||||
verilator Arguments
|
||||
===================
|
||||
|
||||
|
|
@ -11,20 +12,6 @@ Summary:
|
|||
.. include:: ../_build/gen/args_verilator.rst
|
||||
|
||||
|
||||
.. option:: <file.v>
|
||||
|
||||
Specifies the Verilog file containing the top module to be Verilated.
|
||||
|
||||
.. option:: <file.c/.cc/.cpp/.cxx>
|
||||
|
||||
Used with :vlopt:`--exe` to specify optional C++ files to be linked in
|
||||
with the Verilog code. The file path should either be absolute, or
|
||||
relative to where the make will be executed from, or add to your
|
||||
makefile's VPATH the appropriate directory to find the file.
|
||||
|
||||
See also :vlopt:`-CFLAGS` and :vlopt:`-LDFLAGS` options, which are
|
||||
useful when the C++ files need special compiler flags.
|
||||
|
||||
.. option:: <file.a/.o/.so>
|
||||
|
||||
Specifies optional object or library files to be linked with the
|
||||
|
|
@ -37,6 +24,20 @@ Summary:
|
|||
rule that uses these files when linking the module's executable. This
|
||||
generally is only useful when used with the :vlopt:`--exe` option.
|
||||
|
||||
.. option:: <file.c/.cc/.cpp/.cxx>
|
||||
|
||||
Used with :vlopt:`--exe` to specify optional C++ files to be linked in
|
||||
with the Verilog code. The file path should either be absolute, or
|
||||
relative to where the make will be executed from, or add to your
|
||||
makefile's VPATH the appropriate directory to find the file.
|
||||
|
||||
See also :vlopt:`-CFLAGS` and :vlopt:`-LDFLAGS` options, which are
|
||||
useful when the C++ files need special compiler flags.
|
||||
|
||||
.. option:: <file.v>
|
||||
|
||||
Specifies the Verilog file containing the top module to be Verilated.
|
||||
|
||||
.. option:: +1364-1995ext+<ext>
|
||||
|
||||
.. option:: +1364-2001ext+<ext>
|
||||
|
|
@ -182,7 +183,7 @@ Summary:
|
|||
With :vlopt:`--clk`, the specified signal is marked as a clock signal.
|
||||
|
||||
The provided signal name is specified using a RTL hierarchy path. For
|
||||
example, v.foo.bar. If the signal is the input to top-module, then
|
||||
example, v.foo.bar. If the signal is the input to the top-module, then
|
||||
directly provide the signal name. Alternatively, use a
|
||||
:option:`/*verilator&32;clocker*/` metacomment in RTL file to mark the
|
||||
signal directly.
|
||||
|
|
@ -331,11 +332,11 @@ Summary:
|
|||
detailed messages. See :vlopt:`--debug` for other implications of
|
||||
enabling debug.
|
||||
|
||||
.. option:: --decorations none
|
||||
.. option:: --no-decoration
|
||||
|
||||
.. option:: --decorations medium
|
||||
Alias for ``--decorations none``.
|
||||
|
||||
.. option:: --decorations node
|
||||
.. option:: --decorations <level>
|
||||
|
||||
When creating output Verilated code, set level of comment and whitespace
|
||||
decoration.
|
||||
|
|
@ -362,10 +363,6 @@ Summary:
|
|||
between different Verilator runs, this may harm compile caching and
|
||||
should only be used for debug.
|
||||
|
||||
.. option:: --no-decoration
|
||||
|
||||
Alias for ``--decorations none``.
|
||||
|
||||
.. option:: --default-language <value>
|
||||
|
||||
Select the language used by default when first processing each
|
||||
|
|
@ -402,6 +399,11 @@ Summary:
|
|||
name or location of the emitted DPI header file, it is output in
|
||||
:vlopt:`--Mdir` as it would be without this option.
|
||||
|
||||
.. option:: --dump-<srcfile>
|
||||
|
||||
Rarely needed - for developer use. Enable all dumping in the given
|
||||
source file at level 3.
|
||||
|
||||
.. option:: --dump-defines
|
||||
|
||||
With :vlopt:`-E`, suppress normal output, and instead print a list of
|
||||
|
|
@ -433,18 +435,6 @@ Summary:
|
|||
:vlopt:`--debug --no-dump-tree <--dump-tree>` may be useful if the dump
|
||||
files are large and not desired.
|
||||
|
||||
.. option:: --dump-tree-json
|
||||
|
||||
Rarely needed. Enable dumping Ast .json.tree debug files with dumping level 3,
|
||||
which dumps the standard critical stages. For details on the format, see
|
||||
the Verilator Internals manual.
|
||||
|
||||
.. option:: --dump-tree-dot
|
||||
|
||||
Rarely needed. Enable dumping Ast .tree.dot debug files in Graphviz
|
||||
Dot format. This option implies :vlopt:`--dump-tree`, unless
|
||||
:vlopt:`--dumpi-tree` was passed explicitly.
|
||||
|
||||
.. option:: --dump-tree-addrids
|
||||
|
||||
Rarely needed - for developer use. Replace AST node addresses with
|
||||
|
|
@ -454,10 +444,24 @@ Summary:
|
|||
by a newly allocated node after a node with the same address has been
|
||||
dumped and then freed.
|
||||
|
||||
.. option:: --dump-<srcfile>
|
||||
.. option:: --dump-tree-dot
|
||||
|
||||
Rarely needed - for developer use. Enable all dumping in the given
|
||||
source file at level 3.
|
||||
Rarely needed. Enable dumping Ast .tree.dot debug files in Graphviz
|
||||
Dot format. This option implies :vlopt:`--dump-tree`, unless
|
||||
:vlopt:`--dumpi-tree` was passed explicitly.
|
||||
|
||||
.. option:: --dump-tree-json
|
||||
|
||||
Rarely needed. Enable dumping Ast .json.tree debug files with dumping level 3,
|
||||
which dumps the standard critical stages. For details on the format, see
|
||||
the Verilator Internals manual.
|
||||
|
||||
.. option:: --dumpi-<srcfile> <level>
|
||||
|
||||
Rarely needed - for developer use. Set the dumping level in the
|
||||
specified Verilator source file to the specified value (e.g.,
|
||||
`--dumpi-V3Order 9`). Level 0 disables dumps and is equivalent to
|
||||
`--no-dump-<srcfile>`. Level 9 enables the dumping of everything.
|
||||
|
||||
.. option:: --dumpi-dfg <level>
|
||||
|
||||
|
|
@ -479,13 +483,6 @@ Summary:
|
|||
Rarely needed - for developer use. Set internal Ast JSON dumping level
|
||||
globally to the specified value.
|
||||
|
||||
.. option:: --dumpi-<srcfile> <level>
|
||||
|
||||
Rarely needed - for developer use. Set the dumping level in the
|
||||
specified Verilator source file to the specified value (e.g.,
|
||||
`--dumpi-V3Order 9`). Level 0 disables dumps and is equivalent to
|
||||
`--no-dump-<srcfile>`. Level 9 enables the dumping of everything.
|
||||
|
||||
.. option:: -E
|
||||
|
||||
Preprocess the source code, but do not compile, similar to C++
|
||||
|
|
@ -569,7 +566,7 @@ Summary:
|
|||
|
||||
.. option:: -fno-const
|
||||
|
||||
.. options: -fno-const-before-dfg
|
||||
.. option:: -fno-const-before-dfg
|
||||
|
||||
Do not apply any global expression folding prior to the DFG pass. This
|
||||
option is solely for the purpose of DFG testing and should not be used
|
||||
|
|
@ -592,14 +589,14 @@ Summary:
|
|||
|
||||
Disable individual DFG peephole optimizer pattern.
|
||||
|
||||
.. option:: -fno-dfg-pre-inline
|
||||
|
||||
Do not apply the DFG optimizer before inlining.
|
||||
|
||||
.. option:: -fno-dfg-post-inline
|
||||
|
||||
Do not apply the DFG optimizer after inlining.
|
||||
|
||||
.. option:: -fno-dfg-pre-inline
|
||||
|
||||
Do not apply the DFG optimizer before inlining.
|
||||
|
||||
.. option:: -fno-expand
|
||||
|
||||
.. option:: -fno-func-opt
|
||||
|
|
@ -724,14 +721,6 @@ Summary:
|
|||
Generate a true-random key suitable for use with :vlopt:`--protect-key`,
|
||||
print it, and exit immediately.
|
||||
|
||||
.. option:: --getenv <variable>
|
||||
|
||||
If the variable is declared in the environment, print it and exit
|
||||
immediately. Otherwise, if it's built into Verilator
|
||||
(e.g., VERILATOR_ROOT), print that and exit immediately. Otherwise, print
|
||||
a newline and exit immediately. This can be useful in makefiles. See
|
||||
also :vlopt:`-V`, and the various :file:`*.mk` files.
|
||||
|
||||
.. option:: --get-supported <feature>
|
||||
|
||||
If the given feature is supported, print "1" and exit
|
||||
|
|
@ -741,6 +730,14 @@ Summary:
|
|||
|
||||
Feature may be one of the following: COROUTINES, SYSTEMC.
|
||||
|
||||
.. option:: --getenv <variable>
|
||||
|
||||
If the variable is declared in the environment, print it and exit
|
||||
immediately. Otherwise, if it's built into Verilator
|
||||
(e.g., VERILATOR_ROOT), print that and exit immediately. Otherwise, print
|
||||
a newline and exit immediately. This can be useful in makefiles. See
|
||||
also :vlopt:`-V`, and the various :file:`*.mk` files.
|
||||
|
||||
.. option:: --help
|
||||
|
||||
Displays this message and program version and exits.
|
||||
|
|
@ -803,6 +800,15 @@ Summary:
|
|||
must be a positive integer specifying the maximum number of parallel
|
||||
build jobs.
|
||||
|
||||
.. option:: --no-json-edit-nums
|
||||
|
||||
Don't dump edit number in .tree.json files. This may make the file more
|
||||
run-to-run stable for easier comparison.
|
||||
|
||||
.. option:: --no-json-ids
|
||||
|
||||
Don't use short identifiers instead of addresses/paths in .tree.json.
|
||||
|
||||
.. option:: --json-only
|
||||
|
||||
Create JSON output only, do not create any other output.
|
||||
|
|
@ -826,15 +832,6 @@ Summary:
|
|||
Specifies the filename for the main output file (`.tree.json`) of --json-only.
|
||||
Using this option automatically sets :vlopt:`--json-only`.
|
||||
|
||||
.. option:: --no-json-edit-nums
|
||||
|
||||
Don't dump edit number in .tree.json files. This may make the file more
|
||||
run-to-run stable for easier comparison.
|
||||
|
||||
.. option:: --no-json-ids
|
||||
|
||||
Don't use short identifiers instead of addresses/paths in .tree.json.
|
||||
|
||||
.. option:: --l2-name <value>
|
||||
|
||||
Instead of using the module name when showing Verilog scope, use the
|
||||
|
|
@ -908,30 +905,6 @@ Summary:
|
|||
Rarely needed. Set the maximum variable size in bytes for it to be
|
||||
subject to localizing-to-stack optimization. Defaults to 1024.
|
||||
|
||||
.. option:: --make <build-tool>
|
||||
|
||||
Generates a script for the specified build tool.
|
||||
|
||||
Supported values are ``gmake`` for GNU Make, or ``cmake`` for CMake, or
|
||||
``json`` to create a JSON file to feed other build tools.
|
||||
|
||||
Multiple options can be specified together. If no build tool is
|
||||
specified, gmake is assumed. The executable of gmake can be configured
|
||||
via the environment variable :option:`MAKE`.
|
||||
|
||||
When using :vlopt:`--build`, Verilator takes over the responsibility of
|
||||
building the model library/executable. For this reason :option:`--make`
|
||||
cannot be specified when using :vlopt:`--build`.
|
||||
|
||||
.. option:: -MAKEFLAGS <string>
|
||||
|
||||
When using :vlopt:`--build`, add the specified argument to the invoked
|
||||
make command line. For multiple flags, either pass them as a single
|
||||
argument with space separators quoted in the shell (e.g. ``-MAKEFLAGS
|
||||
"-a -b"``), or use multiple -MAKEFLAGS arguments
|
||||
(e.g. ``-MAKEFLAGS -l -MAKEFLAGS -k``). Use of this option should not be
|
||||
required for simple builds using the host toolchain.
|
||||
|
||||
.. option:: --main
|
||||
|
||||
Generates a top-level C++ main() file that supports parsing arguments,
|
||||
|
|
@ -957,6 +930,30 @@ Summary:
|
|||
|
||||
If the string ``"-"`` is used, no top level scope is added.
|
||||
|
||||
.. option:: --make <build-tool>
|
||||
|
||||
Generates a script for the specified build tool.
|
||||
|
||||
Supported values are ``gmake`` for GNU Make, or ``cmake`` for CMake, or
|
||||
``json`` to create a JSON file to feed other build tools.
|
||||
|
||||
Multiple options can be specified together. If no build tool is
|
||||
specified, gmake is assumed. The executable of gmake can be configured
|
||||
via the environment variable :option:`MAKE`.
|
||||
|
||||
When using :vlopt:`--build`, Verilator takes over the responsibility of
|
||||
building the model library/executable. For this reason :option:`--make`
|
||||
cannot be specified when using :vlopt:`--build`.
|
||||
|
||||
.. option:: -MAKEFLAGS <string>
|
||||
|
||||
When using :vlopt:`--build`, add the specified argument to the invoked
|
||||
make command line. For multiple flags, either pass them as a single
|
||||
argument with space separators quoted in the shell (e.g. ``-MAKEFLAGS
|
||||
"-a -b"``), or use multiple -MAKEFLAGS arguments
|
||||
(e.g. ``-MAKEFLAGS -l -MAKEFLAGS -k``). Use of this option should not be
|
||||
required for simple builds using the host toolchain.
|
||||
|
||||
.. option:: --max-num-width <value>
|
||||
|
||||
Set the maximum number literal width (e.g., in 1024'd22 this
|
||||
|
|
@ -991,6 +988,11 @@ Summary:
|
|||
|
||||
Ignored for compatibility with other simulators.
|
||||
|
||||
.. option:: -o <executable>
|
||||
|
||||
Specify the name for the final executable built if using :vlopt:`--exe`.
|
||||
Defaults to the :vlopt:`--prefix` if not specified.
|
||||
|
||||
.. option:: -O0
|
||||
|
||||
Disables optimization of the model.
|
||||
|
|
@ -1011,11 +1013,6 @@ Summary:
|
|||
is deprecated and the various `-f<optimization>` arguments should be
|
||||
used instead.
|
||||
|
||||
.. option:: -o <executable>
|
||||
|
||||
Specify the name for the final executable built if using :vlopt:`--exe`.
|
||||
Defaults to the :vlopt:`--prefix` if not specified.
|
||||
|
||||
.. option:: --no-order-clock-delay
|
||||
|
||||
Deprecated and has no effect (ignored).
|
||||
|
|
@ -1107,6 +1104,14 @@ Summary:
|
|||
position to indicate the corresponding bit of the __out variable has
|
||||
a value being driven from within the Verilated model.
|
||||
|
||||
.. option:: --pins-sc-biguint
|
||||
|
||||
Specifies SystemC inputs/outputs greater than 65 bits wide should use
|
||||
sc_biguint between 65 and 512, and sc_bv from 513 upwards. When
|
||||
combined with the :vlopt:`--pins-sc-uint` combination, it results in
|
||||
sc_uint being used between 2 and 64 and sc_biguint being used between 65
|
||||
and 512.
|
||||
|
||||
.. option:: --pins-sc-uint
|
||||
|
||||
Specifies SystemC inputs/outputs greater than 2 bits wide should use
|
||||
|
|
@ -1118,14 +1123,6 @@ Summary:
|
|||
|
||||
Specifies SystemC inputs/outputs one bit wide should use sc_uint<1>.
|
||||
|
||||
.. option:: --pins-sc-biguint
|
||||
|
||||
Specifies SystemC inputs/outputs greater than 65 bits wide should use
|
||||
sc_biguint between 65 and 512, and sc_bv from 513 upwards. When
|
||||
combined with the :vlopt:`--pins-sc-uint` combination, it results in
|
||||
sc_uint being used between 2 and 64 and sc_biguint being used between 65
|
||||
and 512.
|
||||
|
||||
.. option:: --pins-uint8
|
||||
|
||||
Specifies SystemC inputs/outputs smaller than the
|
||||
|
|
@ -1487,25 +1484,21 @@ Summary:
|
|||
|
||||
A synonym for :vlopt:`+1800-2023ext+\<ext\>`.
|
||||
|
||||
.. option:: --threads <threads>
|
||||
|
||||
With "--threads 1", the default, the generated model is single-threaded
|
||||
but may run in a multithreaded environment. With "--threads N",
|
||||
where N >= 2, the model is generated to run multithreaded on up to N
|
||||
threads. See :ref:`Multithreading`. This option also applies to
|
||||
:vlopt:`--trace` (but not :vlopt:`--trace-fst`).
|
||||
|
||||
.. option:: --no-threads
|
||||
|
||||
Deprecated and has no effect (ignored).
|
||||
|
||||
In versions before 5.004, created a model which was not thread-safe.
|
||||
|
||||
.. option:: --threads-dpi all
|
||||
.. option:: --threads <threads>
|
||||
|
||||
.. option:: --threads-dpi none
|
||||
With "--threads 1", the default, the generated model is single-threaded
|
||||
but may run in a multithreaded environment. With "--threads N",
|
||||
where N >= 2, the model is generated to run multithreaded on up to N
|
||||
threads. See :ref:`Multithreading`. This option also applies to
|
||||
:vlopt:`--trace-vcd` (but not :vlopt:`--trace-fst`).
|
||||
|
||||
.. option:: --threads-dpi pure
|
||||
.. option:: --threads-dpi <mode>
|
||||
|
||||
When using :vlopt:`--threads`, controls which DPI imported tasks and
|
||||
functions are considered thread-safe.
|
||||
|
|
@ -1539,10 +1532,10 @@ Summary:
|
|||
does not occur before a given module. Default is "1ps/1ps" (to match
|
||||
SystemC). This is overridden by :vlopt:`--timescale-override`.
|
||||
|
||||
.. option:: --timescale-override <timeunit>/<timeprecision>
|
||||
|
||||
.. option:: --timescale-override /<timeprecision>
|
||||
|
||||
.. option:: --timescale-override <timeunit>/<timeprecision>
|
||||
|
||||
Overrides all "\`timescale"s in sources. The timeunit may be left empty
|
||||
to specify only to override the timeprecision, e.g. "/1fs".
|
||||
|
||||
|
|
@ -1574,26 +1567,19 @@ Summary:
|
|||
|
||||
.. option:: --trace
|
||||
|
||||
Adds waveform tracing code to the model using VCD format. This overrides
|
||||
:vlopt:`--trace-fst`.
|
||||
Deprecated; use :vlopt:`--trace-fst`, :vlopt:`--trace-saif` or
|
||||
:vlopt:`--trace-vcd` instead.
|
||||
|
||||
Verilator will generate additional :file:`<prefix>__Trace*.cpp` files
|
||||
must be compiled. In addition :file:`verilated_vcd_sc.cpp`
|
||||
(for SystemC traces) or :file:`verilated_vcd_c.cpp` (for both) must be
|
||||
compiled and linked in. If using the Verilator-generated Makefiles,
|
||||
these files will be added to the source file lists for you. If you are
|
||||
not using the Verilator Makefiles, you will need to add these to your
|
||||
Makefile manually.
|
||||
Using :vlopt:`--trace` without :vlopt:`--trace-fst` nor
|
||||
:vlopt:`--trace-fst` requests VCD traces.
|
||||
|
||||
Having tracing compiled in may result in small performance losses,
|
||||
even when tracing is not turned on during model execution.
|
||||
Using :vlopt:`--trace` :vlopt:`--trace-fst` requests FST traces.
|
||||
|
||||
When using :vlopt:`--threads`, VCD tracing is parallelized, using the
|
||||
same number of threads as passed to :vlopt:`--threads`.
|
||||
Using :vlopt:`--trace` :vlopt:`--trace-saif` requests SAIF traces.
|
||||
|
||||
.. option:: --trace-coverage
|
||||
|
||||
With :vlopt:`--trace` and ``--coverage-*``, enable tracing to include a
|
||||
With `--trace-*` and ``--coverage-*``, enable tracing to include a
|
||||
traced signal for every :vlopt:`--coverage-line` or
|
||||
:vlopt:`--coverage-user`\ -inserted coverage point, to assist in
|
||||
debugging coverage items. Note :vlopt:`--coverage-toggle` does not get
|
||||
|
|
@ -1673,6 +1659,24 @@ Summary:
|
|||
underscore. Otherwise, these signals are not output during tracing. See
|
||||
also :vlopt:`--coverage-underscore` option.
|
||||
|
||||
.. option:: --trace-vcd
|
||||
|
||||
Adds waveform tracing code to the model using VCD format.
|
||||
|
||||
Verilator will generate additional :file:`<prefix>__Trace*.cpp` files
|
||||
must be compiled. In addition :file:`verilated_vcd_sc.cpp`
|
||||
(for SystemC traces) or :file:`verilated_vcd_c.cpp` (for both) must be
|
||||
compiled and linked in. If using the Verilator-generated Makefiles,
|
||||
these files will be added to the source file lists for you. If you are
|
||||
not using the Verilator Makefiles, you will need to add these to your
|
||||
Makefile manually.
|
||||
|
||||
Having tracing compiled in may result in small performance losses,
|
||||
even when tracing is not turned on during model execution.
|
||||
|
||||
When using :vlopt:`--threads`, VCD tracing is parallelized, using the
|
||||
same number of threads as passed to :vlopt:`--threads`.
|
||||
|
||||
.. option:: -U<var>
|
||||
|
||||
Undefines the given preprocessor symbol.
|
||||
|
|
@ -1770,7 +1774,7 @@ Summary:
|
|||
them systematically.
|
||||
|
||||
The generated file is in the Verilator Configuration format, see
|
||||
:ref:`Configuration Files`. The standard file extension is ".vlt".
|
||||
:ref:`Verilator Configuration Files`. The standard file extension is ".vlt".
|
||||
These files can directly be consumed by Verilator, typically by placing
|
||||
the filename as part of the Verilator command line options. Waiver files
|
||||
need to be listed on the command line before listing the files they are
|
||||
|
|
@ -1876,37 +1880,40 @@ Summary:
|
|||
``-Wwarn-ASSIGNDLY`` ``-Wwarn-BLKSEQ`` ``-Wwarn-DECLFILENAME``
|
||||
``-Wwarn-DEFPARAM`` ``-Wwarn-EOFNEWLINE`` ``-Wwarn-GENUNNAMED``
|
||||
``-Wwarn-IMPORTSTAR`` ``-Wwarn-INCABSPATH`` ``-Wwarn-PINCONNECTEMPTY``
|
||||
``-Wwarn-PINNOCONNECT`` ``-Wwarn-SYNCASYNCNET`` ``-Wwarn-UNDRIVEN``
|
||||
``-Wwarn-UNUSEDGENVAR`` ``-Wwarn-UNUSEDLOOP`` ``-Wwarn-UNUSEDPARAM``
|
||||
``-Wwarn-UNUSEDSIGNAL`` ``-Wwarn-VARHIDDEN``.
|
||||
``-Wwarn-PINNOCONNECT`` ``-Wwarn-PROCASSINIT`` ``-Wwarn-SYNCASYNCNET``
|
||||
``-Wwarn-UNDRIVEN`` ``-Wwarn-UNUSEDGENVAR`` ``-Wwarn-UNUSEDLOOP``
|
||||
``-Wwarn-UNUSEDPARAM`` ``-Wwarn-UNUSEDSIGNAL`` ``-Wwarn-VARHIDDEN``.
|
||||
|
||||
.. option:: --x-assign 0
|
||||
|
||||
.. option:: --x-assign 1
|
||||
|
||||
.. option:: --x-assign fast (default)
|
||||
|
||||
.. option:: --x-assign unique
|
||||
.. option:: --x-assign <mode>
|
||||
|
||||
Controls the two-state value that is substituted when an explicit X
|
||||
value is encountered in the source. "--x-assign fast", the default,
|
||||
converts all Xs to whatever is best for performance. "--x-assign 0"
|
||||
converts all Xs to 0s, and is also fast. "--x-assign 1" converts all Xs
|
||||
to 1s, this is nearly as fast as 0, but more likely to find reset bugs
|
||||
as active high logic will fire. Using "--x-assign unique" will result in
|
||||
all explicit Xs being replaced by a constant value determined at
|
||||
runtime. The value is determined by calling a function at initialization
|
||||
time. This enables the randomization of Xs with different seeds on different
|
||||
executions. This method is the slowest, but safest for finding reset
|
||||
bugs.
|
||||
value is encountered in the source.
|
||||
|
||||
If using "--x-assign unique", you may want to seed your random number
|
||||
generator such that each regression run gets a different randomization
|
||||
sequence. The simplest is to use the :vlopt:`+verilator+seed+\<value\>`
|
||||
runtime option. Alternatively, use the system's :code:`srand48()` or for
|
||||
Windows :code:`srand()` function to do this. You'll probably also want
|
||||
to print any seeds selected, and code to enable rerunning with that same
|
||||
seed so you can reproduce bugs.
|
||||
With "--x-assign 0",
|
||||
converts all Xs to 0s, and is also fast.
|
||||
|
||||
With "--x-assign 1",
|
||||
converts all Xs to 1s, this is nearly as fast as 0, but more likely to
|
||||
find reset bugs as active high logic will fire.
|
||||
|
||||
With "--x-assign fast", the default,
|
||||
converts all Xs to whatever is best for performance.
|
||||
|
||||
With "--x-assign unique",
|
||||
all explicit Xs being replaced by a constant value determined at
|
||||
runtime. The value is determined by calling a function at
|
||||
initialization time. This enables the randomization of Xs with
|
||||
different seeds on different executions. This method is the slowest,
|
||||
but safest for finding reset bugs.
|
||||
|
||||
If using `--x-assign unique`, you may want to seed your random number
|
||||
generator such that each regression run gets a different randomization
|
||||
sequence. The simplest is to use the
|
||||
:vlopt:`+verilator+seed+\<value\>` runtime option. Alternatively, use
|
||||
the system's :code:`srand48()` or for Windows :code:`srand()` function
|
||||
to do this. You'll probably also want to print any seeds selected,
|
||||
and code to enable rerunning with that same seed so you can reproduce
|
||||
bugs.
|
||||
|
||||
.. note::
|
||||
|
||||
|
|
@ -1916,24 +1923,20 @@ Summary:
|
|||
specified. Initial values of all other state holding variables are
|
||||
controlled with `--x-initial`.
|
||||
|
||||
.. option:: --x-initial 0
|
||||
|
||||
.. option:: --x-initial fast
|
||||
|
||||
.. option:: --x-initial unique (default)
|
||||
.. option:: --x-initial <mode>
|
||||
|
||||
Controls the two-state value used to initialize variables that
|
||||
are not otherwise initialized.
|
||||
|
||||
"--x-initial 0",
|
||||
With "--x-initial 0",
|
||||
initializes all otherwise uninitialized variables to zero.
|
||||
|
||||
"--x-initial unique", the default,
|
||||
With "--x-initial unique", the default,
|
||||
initializes variables using a function, which determines the value to
|
||||
use for each initialization. This gives the greatest flexibility and
|
||||
allows for finding reset bugs. See :ref:`Unknown states`.
|
||||
|
||||
"--x-initial fast",
|
||||
With "--x-initial fast",
|
||||
is best for performance, and initializes all variables to a state
|
||||
Verilator determines is optimal. This may allow further code
|
||||
optimizations, but will likely hide any code bugs relating to missing
|
||||
|
|
@ -2012,17 +2015,20 @@ Summary:
|
|||
filenames.
|
||||
|
||||
|
||||
.. _Configuration Files:
|
||||
.. _Verilator Configuration Files:
|
||||
|
||||
Configuration Files
|
||||
===================
|
||||
=============================
|
||||
Verilator Configuration Files
|
||||
=============================
|
||||
|
||||
In addition to the command line, warnings and other features for the
|
||||
:command:`verilator` command may be controlled with configuration files,
|
||||
typically named with the `.vlt` extension (what makes it a configuration
|
||||
file is the :option:`\`verilator_config` directive). These files, when
|
||||
named `.vlt`, are read before source code files; if this behavior is
|
||||
undesired, name the config file with a `.v` suffix.
|
||||
:command:`verilator` command may be controlled with Verilator Configuration
|
||||
Files, not to be confused with IEEE Configurations blocks
|
||||
(`config...endconfig`) inside a file. Typically named with the `.vlt`
|
||||
extension, what makes it a Verilator Configuration File is the
|
||||
:option:`\`verilator_config` directive. These files, when named `.vlt`,
|
||||
are read before source code files; if this behavior is undesired, name the
|
||||
config file with a `.v` suffix.
|
||||
|
||||
An example:
|
||||
|
||||
|
|
@ -2034,9 +2040,9 @@ An example:
|
|||
|
||||
This disables WIDTH warnings globally, and CASEX for a specific file.
|
||||
|
||||
Configuration files are fed through the normal Verilog preprocessor prior
|
||||
to parsing, so "\`ifdef", "\`define", and comments may be used as if the
|
||||
configuration file was standard Verilog code.
|
||||
Verilator configuration files are fed through the normal Verilog
|
||||
preprocessor prior to parsing, so "\`ifdef", "\`define", and comments may
|
||||
be used as if the configuration file was standard Verilog code.
|
||||
|
||||
Note that file or line-specific configuration only applies to files read
|
||||
after the configuration file. It is therefore recommended to pass the
|
||||
|
|
@ -2048,15 +2054,6 @@ The grammar of configuration commands is as follows:
|
|||
|
||||
Take the remaining text and treat it as Verilator configuration commands.
|
||||
|
||||
.. option:: coverage_on [-file "<filename>" [-lines <line> [ - <line> ]]]
|
||||
|
||||
.. option:: coverage_off [-file "<filename>" [-lines <line> [ - <line> ]]]
|
||||
|
||||
Enable/disable coverage for the specified filename (or wildcard with
|
||||
'\*' or '?', or all files if omitted) and range of line numbers (or all
|
||||
lines if omitted). Often used to ignore an entire module for coverage
|
||||
analysis purposes.
|
||||
|
||||
.. option:: clock_enable -module "<modulename>" -var "<signame>"
|
||||
|
||||
Deprecated and has no effect (ignored).
|
||||
|
|
@ -2068,30 +2065,42 @@ The grammar of configuration commands is as follows:
|
|||
|
||||
Same as :option:`/*verilator&32;clock_enable*/` metacomment.
|
||||
|
||||
.. option:: clocker -module "<modulename>" [-task "<taskname>"] -var "<signame>"
|
||||
|
||||
.. t_dist_docs_style ignore no_clocker
|
||||
|
||||
.. option:: clocker -module "<modulename>" [-function "<funcname>"] -var "<signame>"
|
||||
|
||||
.. option:: no_clocker -module "<modulename>" [-task "<taskname>"] -var "<signame>"
|
||||
.. option:: clocker -module "<modulename>" [-task "<taskname>"] -var "<signame>"
|
||||
|
||||
.. option:: no_clocker -module "<modulename>" [-function "<funcname>"] -var "<signame>"
|
||||
|
||||
.. option:: no_clocker -module "<modulename>" [-task "<taskname>"] -var "<signame>"
|
||||
|
||||
Indicates whether the signal is used as clock or not. Verilator uses
|
||||
this information to mark the signal and any derived signals as clocker.
|
||||
See :vlopt:`--clk`.
|
||||
|
||||
Same as :option:`/*verilator&32;clocker*/` metacomment.
|
||||
|
||||
.. option:: coverage_block_off -module "<modulename>" -block "<blockname>"
|
||||
|
||||
.. option:: coverage_block_off -file "<filename>" -line <lineno>
|
||||
|
||||
.. option:: coverage_block_off -module "<modulename>" -block "<blockname>"
|
||||
|
||||
Specifies the entire begin/end block should be ignored for coverage
|
||||
analysis purposes. It can either be specified as a named block or as a
|
||||
filename and line number.
|
||||
|
||||
Same as :option:`/*verilator&32;coverage_block_off*/` metacomment.
|
||||
|
||||
.. option:: coverage_off [-file "<filename>" [-lines <line> [ - <line> ]]]
|
||||
|
||||
.. option:: coverage_on [-file "<filename>" [-lines <line> [ - <line> ]]]
|
||||
|
||||
Enable/disable coverage for the specified filename (or wildcard with
|
||||
'\*' or '?', or all files if omitted) and range of line numbers (or all
|
||||
lines if omitted). Often used to ignore an entire module for coverage
|
||||
analysis purposes.
|
||||
|
||||
.. option:: forceable -module "<modulename>" -var "<signame>"
|
||||
|
||||
Generate public `<signame>__VforceEn` and `<signame>__VforceVal` signals
|
||||
|
|
@ -2102,11 +2111,8 @@ The grammar of configuration commands is as follows:
|
|||
|
||||
.. option:: full_case -file "<filename>" -lines <lineno>
|
||||
|
||||
.. option:: parallel_case -file "<filename>" -lines <lineno>
|
||||
|
||||
Same as :code:`//synopsys full_case` and
|
||||
:code:`//synopsys parallel_case`. When these synthesis directives are
|
||||
discovered, Verilator will either formally prove the directive to be
|
||||
Same as :code:`//synthesis full_case`. When these synthesis directives
|
||||
are discovered, Verilator will either formally prove the directive to be
|
||||
true, or, failing that, will insert the appropriate code to detect
|
||||
failing cases at simulation runtime and print an "Assertion failed"
|
||||
error message.
|
||||
|
|
@ -2124,20 +2130,27 @@ The grammar of configuration commands is as follows:
|
|||
This option should not be used directly.
|
||||
See :ref:`Hierarchical Verilation`.
|
||||
|
||||
.. option:: hier_workers -hier-dpi "<function_name>" -workers <worker_count>
|
||||
|
||||
Specifies how many threads need to be used for scheduling hierarchical DPI
|
||||
tasks. This data is inserted internally during :vlopt:`--hierarchical`,
|
||||
based on value specified in `hier_workers -module`. This option
|
||||
should not be used directly. See :ref:`Hierarchical Verilation`.
|
||||
|
||||
.. option:: hier_workers -module "<module_name>" -workers <worker_count>
|
||||
|
||||
Specifies how many threads need to be used for scheduling given module with
|
||||
:option:`/*verilator&32;hier_block*/` metacomment. This number needs to be
|
||||
smaller than :vlopt:`--threads` to fit in a thread schedule.
|
||||
See :ref:`Hierarchical Verilation`.
|
||||
|
||||
.. option:: inline -module "<modulename>"
|
||||
|
||||
Specifies the module may be inlined into any modules that use this
|
||||
module. Same as :option:`/*verilator&32;inline_module*/` metacomment.
|
||||
|
||||
.. option:: isolate_assignments -module "<modulename>" [-task "<taskname>"] -var "<signame>"
|
||||
|
||||
.. option:: isolate_assignments -module "<modulename>" [-function "<funcname>"] -var "<signame>"
|
||||
|
||||
.. option:: isolate_assignments -module "<modulename>" -function "<fname>"
|
||||
|
||||
Used to indicate that the assignments to this signal in any blocks
|
||||
should be isolated into new blocks. Same as
|
||||
:option:`/*verilator&32;isolate_assignments*/` metacomment.
|
||||
.. t_dist_docs_style ignore no_inline
|
||||
|
||||
.. option:: no_inline -module "<modulename>"
|
||||
|
||||
|
|
@ -2145,10 +2158,10 @@ The grammar of configuration commands is as follows:
|
|||
this module. Same as :option:`/*verilator&32;no_inline_module*/`
|
||||
metacomment.
|
||||
|
||||
.. option:: no_inline [-module "<modulename>"] -task "<taskname>"
|
||||
|
||||
.. option:: no_inline [-module "<modulename>"] -function "<funcname>"
|
||||
|
||||
.. option:: no_inline [-module "<modulename>"] -task "<taskname>"
|
||||
|
||||
Specify the function or task should not be inlined into where it is
|
||||
used. This may reduce the size of the final executable when a task is
|
||||
used a very large number of times. For this flag to work, the task and
|
||||
|
|
@ -2157,12 +2170,22 @@ The grammar of configuration commands is as follows:
|
|||
|
||||
Same as :option:`/*verilator&32;no_inline_task*/` metacomment.
|
||||
|
||||
.. option:: lint_on [-rule <message>] [-file "<filename>" [-lines <line> [ - <line>]]]
|
||||
.. option:: isolate_assignments -module "<modulename>" -function "<fname>"
|
||||
|
||||
.. option:: isolate_assignments -module "<modulename>" [-function "<funcname>"] -var "<signame>"
|
||||
|
||||
.. option:: isolate_assignments -module "<modulename>" [-task "<taskname>"] -var "<signame>"
|
||||
|
||||
Used to indicate that the assignments to this signal in any blocks
|
||||
should be isolated into new blocks. Same as
|
||||
:option:`/*verilator&32;isolate_assignments*/` metacomment.
|
||||
|
||||
.. option:: lint_off [-rule <message>] [-file "<filename>" [-lines <line> [ - <line>]]]
|
||||
|
||||
.. option:: lint_off [-rule <message>] [-file "<filename>"] [-contents "<wildcard>"] [-match "<wildcard>"]
|
||||
|
||||
.. option:: lint_on [-rule <message>] [-file "<filename>" [-lines <line> [ - <line>]]]
|
||||
|
||||
Enable/disables the specified lint warning, in the specified filename
|
||||
(or wildcard with '\*' or '?', or all files if omitted) and range of
|
||||
line numbers (or all lines if omitted).
|
||||
|
|
@ -2193,18 +2216,13 @@ The grammar of configuration commands is as follows:
|
|||
Before version 4.026, :code:`-rule` was named :code:`-msg`, and
|
||||
:code:`-msg` remained a deprecated alias until Version 5.000.
|
||||
|
||||
.. option:: public [-module "<modulename>"] [-task/-function "<taskname>"] -var "<signame>"
|
||||
.. option:: parallel_case -file "<filename>" -lines <lineno>
|
||||
|
||||
.. option:: public_flat [-module "<modulename>"] [-task/-function "<taskname>"] -var "<signame>"
|
||||
|
||||
.. option:: public_flat_rd [-module "<modulename>"] [-task/-function "<taskname>"] -var "<signame>"
|
||||
|
||||
.. option:: public_flat_rw [-module "<modulename>"] [-task/-function "<taskname>"] -var "<signame>" "@(edge)"
|
||||
|
||||
Sets the variable to be public. Same as
|
||||
:option:`/*verilator&32;public*/` or
|
||||
:option:`/*verilator&32;public_flat*/`, etc., metacomments. See
|
||||
also :ref:`VPI Example`.
|
||||
Same as :code:`//synthesis parallel_case`. When these synthesis
|
||||
directives are discovered, Verilator will either formally prove the
|
||||
directive to be true, or, failing that, will insert the appropriate code
|
||||
to detect failing cases at simulation runtime and print an "Assertion
|
||||
failed" error message.
|
||||
|
||||
.. option:: profile_data -hier-dpi "<function_name>" -cost <cost_value>
|
||||
|
||||
|
|
@ -2219,18 +2237,31 @@ The grammar of configuration commands is as follows:
|
|||
order to improve model runtime performance. This option is not expected
|
||||
to be used by users directly. See :ref:`Thread PGO`.
|
||||
|
||||
.. option:: sc_bv -module "<modulename>" [-task "<taskname>"] -var "<signame>"
|
||||
.. option:: public [-module "<modulename>"] [-task/-function "<taskname>"] -var "<signame>"
|
||||
|
||||
.. option:: public_flat [-module "<modulename>"] [-task/-function "<taskname>"] -var "<signame>"
|
||||
|
||||
.. option:: public_flat_rd [-module "<modulename>"] [-task/-function "<taskname>"] -var "<signame>"
|
||||
|
||||
.. option:: public_flat_rw [-module "<modulename>"] [-task/-function "<taskname>"] -var "<signame>" "@(edge)"
|
||||
|
||||
Sets the variable to be public. Same as
|
||||
:option:`/*verilator&32;public*/` or
|
||||
:option:`/*verilator&32;public_flat*/`, etc., metacomments. See
|
||||
also :ref:`VPI Example`.
|
||||
|
||||
.. option:: sc_bv -module "<modulename>" [-function "<funcname>"] -var "<signame>"
|
||||
|
||||
.. option:: sc_bv -module "<modulename>" [-task "<taskname>"] -var "<signame>"
|
||||
|
||||
Sets the port to be of :code:`sc_bv<{width}>` type, instead of bool,
|
||||
uint32_t, or uint64_t. Same as :option:`/*verilator&32;sc_bv*/`
|
||||
metacomment.
|
||||
|
||||
.. option:: sformat [-module "<modulename>"] [-task "<taskname>"] -var "<signame>"
|
||||
|
||||
.. option:: sformat [-module "<modulename>"] [-function "<funcname>"] -var "<signame>"
|
||||
|
||||
.. option:: sformat [-module "<modulename>"] [-task "<taskname>"] -var "<signame>"
|
||||
|
||||
Must be applied to the final argument of type :code:`input string` of a
|
||||
function or task to indicate that the function or task should pass all
|
||||
remaining arguments through $sformatf. This allows the creation of DPI
|
||||
|
|
@ -2239,20 +2270,20 @@ The grammar of configuration commands is as follows:
|
|||
|
||||
Same as :option:`/*verilator&32;sformat*/` metacomment.
|
||||
|
||||
.. option:: split_var [-module "<modulename>"] [-task "<taskname>"] -var "<varname>"
|
||||
|
||||
.. option:: split_var [-module "<modulename>"] [-function "<funcname>"] -var "<varname>"
|
||||
|
||||
.. option:: split_var [-module "<modulename>"] [-task "<taskname>"] -var "<varname>"
|
||||
|
||||
Break the variable into multiple pieces typically to resolve UNOPTFLAT
|
||||
performance issues. Typically the variables to attach this to are
|
||||
recommended by Verilator itself; see :option:`UNOPTFLAT`.
|
||||
|
||||
Same as :option:`/*verilator&32;split_var*/` metacomment.
|
||||
|
||||
.. option:: timing_on [-file "<filename>" [-lines <line> [ - <line>]]]
|
||||
|
||||
.. option:: timing_off [-file "<filename>" [-lines <line> [ - <line>]]]
|
||||
|
||||
.. option:: timing_on [-file "<filename>" [-lines <line> [ - <line>]]]
|
||||
|
||||
Enables/disables timing constructs for the specified file and lines.
|
||||
When disabled, all timing control constructs in the specified source
|
||||
code locations are ignored the same way as with the
|
||||
|
|
@ -2262,14 +2293,17 @@ The grammar of configuration commands is as follows:
|
|||
Same as :option:`/*verilator&32;timing_on*/`,
|
||||
:option:`/*verilator&32;timing_off*/` metacomments.
|
||||
|
||||
.. option:: tracing_on [-file "<filename>" [-lines <line> [ - <line> ]]]
|
||||
|
||||
.. t_dist_docs_style ignore tracing_on
|
||||
|
||||
.. option:: tracing_off [-file "<filename>" [-lines <line> [ - <line> ]]]
|
||||
|
||||
.. option:: tracing_on [-scope "<scopename>" [-levels <levels> ]]
|
||||
.. option:: tracing_on [-file "<filename>" [-lines <line> [ - <line> ]]]
|
||||
|
||||
.. option:: tracing_off [-scope "<scopename>" [-levels <levels> ]]
|
||||
|
||||
.. option:: tracing_on [-scope "<scopename>" [-levels <levels> ]]
|
||||
|
||||
Enable/disable waveform tracing for all future signals declared in
|
||||
all files.
|
||||
|
||||
|
|
|
|||
|
|
@ -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:`Verilator Configuration Files`.
|
||||
|
||||
.. option:: `error [string]
|
||||
|
||||
This will report an error when the preprocessor emits it, similar to
|
||||
|
|
@ -33,10 +44,117 @@ or "`ifdef`"'s may break other tools.
|
|||
internal tests, so that debugging can leave the line numbers correctly
|
||||
referring to the test file's line numbers.
|
||||
|
||||
.. option:: """ [string] """
|
||||
.. option:: `systemc_class_name
|
||||
|
||||
A triple-quoted block specifies a string that may include newlines and
|
||||
single quotes. This extension was standardized in IEEE 1800-2023.
|
||||
Inside one of the :option:`\`systemc_... <\`systemc_header>` text
|
||||
blocks, replaced with the C++ class name generated for the given
|
||||
containing SystemVerilog class or module. Currently this is replaced
|
||||
blindly, ignoring quoting or other escapes; this behavior may change in
|
||||
the future. This attribute is indented only to be used internally in
|
||||
`verilated_std.sv`.
|
||||
|
||||
.. option:: `systemc_ctor
|
||||
|
||||
Take the remaining text up to the next :option:`\`verilog` or
|
||||
:option:`\`systemc_... <\`systemc_header>` mode switch and place it
|
||||
verbatim into the C++ class constructor. Must be placed as a module or
|
||||
class item, e.g., directly inside a module/endmodule or class/endclass
|
||||
pair. Despite the name of this macro, this also works in pure C++ code.
|
||||
|
||||
.. option:: `systemc_dtor
|
||||
|
||||
Take the remaining text up to the next :option:`\`verilog` or
|
||||
:option:`\`systemc_... <\`systemc_header>` mode switch and place it
|
||||
verbatim into the C++ class destructor. Must be placed as a module or
|
||||
class item, e.g., directly inside a module/endmodule or class/endclass
|
||||
pair. Despite the name of this macro, this also works in pure C++ code.
|
||||
|
||||
.. option:: `systemc_header
|
||||
|
||||
Take the remaining text up to the next :option:`\`verilog` or
|
||||
:option:`\`systemc_... <\`systemc_header>` mode switch and place it
|
||||
verbatim into the output .h file's header. Must be placed as a module
|
||||
or class item, e.g., directly inside a module/endmodule or
|
||||
class/endclass pair. Despite the name of this macro, this also works in
|
||||
pure C++ code.
|
||||
|
||||
.. option:: `systemc_header_post
|
||||
|
||||
Take the remaining text up to the next :option:`\`verilog` or
|
||||
:option:`\`systemc_... <\`systemc_header>` mode switch and place it
|
||||
verbatim into the output .h file's header after the class definition.
|
||||
Must be placed as a module or class item, e.g., directly inside a
|
||||
module/endmodule or class/endclass pair. Despite the name of this macro,
|
||||
this also works in pure C++ code.
|
||||
|
||||
.. option:: `systemc_imp_header
|
||||
|
||||
Take the remaining text up to the next :option:`\`verilog` or
|
||||
:option:`\`systemc_... <\`systemc_header>` mode switch and place it
|
||||
verbatim into the header of all files for this C++ class implementation.
|
||||
Must be placed as a module or class item, e.g., directly inside a
|
||||
module/endmodule or class/endclass pair. Despite the name of this macro,
|
||||
this also works in pure C++ code.
|
||||
|
||||
.. option:: `systemc_implementation
|
||||
|
||||
Take the remaining text up to the next :option:`\`verilog` or
|
||||
:option:`\`systemc_... <\`systemc_header>` mode switch and place it
|
||||
verbatim into a single file of the C++ class implementation. Must be
|
||||
placed as a module or class item, e.g., directly inside a
|
||||
module/endmodule or class/endclass pair. Despite the name of this macro,
|
||||
this also works in pure C++ code.
|
||||
|
||||
If you will be reading or writing any Verilog variables in the C++
|
||||
functions, the Verilog signals must be declared with a
|
||||
:option:`/*verilator&32;public*/` metacomment. See also the public task
|
||||
feature; writing an accessor may result in cleaner code.
|
||||
|
||||
.. option:: `systemc_interface
|
||||
|
||||
Take the remaining text up to the next :option:`\`verilog` or
|
||||
:option:`\`systemc_... <\`systemc_header>` mode switch and place it
|
||||
verbatim into the C++ class interface. Must be placed as a module or
|
||||
class item, e.g., directly inside a module/endmodule or class/endclass
|
||||
pair. Despite the name of this macro, this also works in pure C++ code.
|
||||
|
||||
.. option:: `SYSTEMVERILOG
|
||||
|
||||
The SYSTEMVERILOG, SV_COV_START, and related standard predefined macros
|
||||
are defined by default when :vlopt:`--language <--language>` is
|
||||
"1800-\*".
|
||||
|
||||
.. option:: `VERILATOR
|
||||
|
||||
.. option:: `verilator
|
||||
|
||||
.. option:: `verilator3
|
||||
|
||||
The VERILATOR, verilator and verilator3 predefined macros are defined by
|
||||
default so you may "\`ifdef" around tool specific constructs.
|
||||
|
||||
.. option:: `verilator_config
|
||||
|
||||
Take the remaining text up to the next :option:`\`verilog` mode switch
|
||||
and treat it as Verilator configuration commands. See :ref:`Verilator
|
||||
Configuration Files`.
|
||||
|
||||
.. option:: `VERILATOR_TIMING
|
||||
|
||||
The VERILATOR_TIMING define is set when :vlopt:`--timing` is used to
|
||||
allow an "\`ifdef" of code dependent on this feature. Note that this define
|
||||
is not affected by the :option:`timing_off` configuration file option
|
||||
nor timing metacomments.
|
||||
|
||||
.. option:: `verilog
|
||||
|
||||
Switch back to processing Verilog code after a
|
||||
:option:`\`systemc_... <\`systemc_header>` mode switch. The Verilog
|
||||
code returns to the last language mode specified with
|
||||
"\`begin_keywords", or SystemVerilog if none was specified.
|
||||
|
||||
|
||||
.. t_dist_docs_style restart_sort
|
||||
|
||||
.. option:: $c([string], ...);
|
||||
|
||||
|
|
@ -86,6 +204,16 @@ or "`ifdef`"'s may break other tools.
|
|||
prints 5 digits per the C standard. This extension was standardized into
|
||||
1800-2009.
|
||||
|
||||
.. option:: $stacktrace
|
||||
|
||||
Called as a task, print a stack trace. Called as a function, return a
|
||||
string with a stack trace. This relies on the C++ system trace, which
|
||||
may give less meaningful results if the model is not compiled with debug
|
||||
symbols. Also, the data represents the C++ stack; the SystemVerilog
|
||||
functions/tasks involved may be renamed and/or inlined before becoming
|
||||
the C++ functions that may be visible in the stack trace. This
|
||||
extension was standardized in IEEE 1800-2023.
|
||||
|
||||
.. option:: $timeprecision
|
||||
|
||||
Returns the timeprecision of the model as an integer. This extension is
|
||||
|
|
@ -96,98 +224,6 @@ or "`ifdef`"'s may break other tools.
|
|||
Returns the timeunit of the current module as an integer. This
|
||||
extension is experimental and may be removed without deprecation.
|
||||
|
||||
.. option:: `coverage_block_off
|
||||
|
||||
Specifies the entire begin/end block should be ignored for coverage
|
||||
analysis. Must be inside a code block, e.g., within a begin/end pair.
|
||||
Same as :option:`coverage_block_off` in :ref:`Configuration Files`.
|
||||
|
||||
.. option:: `systemc_header
|
||||
|
||||
Take the remaining text up to the next :option:`\`verilog` or
|
||||
:option:`\`systemc_... <\`systemc_header>` mode switch and place it
|
||||
verbatim into the output .h file's header. Must be placed as a module
|
||||
item, e.g., directly inside a module/endmodule pair. Despite the name of
|
||||
this macro, this also works in pure C++ code.
|
||||
|
||||
.. option:: `systemc_ctor
|
||||
|
||||
Take the remaining text up to the next :option:`\`verilog` or
|
||||
:option:`\`systemc_... <\`systemc_header>` mode switch and place it
|
||||
verbatim into the C++ class constructor. Must be placed as a module
|
||||
item, e.g., directly inside a module/endmodule pair. Despite the name of
|
||||
this macro, this also works in pure C++ code.
|
||||
|
||||
.. option:: `systemc_dtor
|
||||
|
||||
Take the remaining text up to the next :option:`\`verilog` or
|
||||
:option:`\`systemc_... <\`systemc_header>` mode switch and place it
|
||||
verbatim into the C++ class destructor. Must be placed as a module
|
||||
item, e.g., directly inside a module/endmodule pair. Despite the name of
|
||||
this macro, this also works in pure C++ code.
|
||||
|
||||
.. option:: `systemc_interface
|
||||
|
||||
Take the remaining text up to the next :option:`\`verilog` or
|
||||
:option:`\`systemc_... <\`systemc_header>` mode switch and place it
|
||||
verbatim into the C++ class interface. Must be placed as a module item,
|
||||
e.g., directly inside a module/endmodule pair. Despite the name of this
|
||||
macro, this also works in pure C++ code.
|
||||
|
||||
.. option:: `systemc_imp_header
|
||||
|
||||
Take the remaining text up to the next :option:`\`verilog` or
|
||||
:option:`\`systemc_... <\`systemc_header>` mode switch and place it
|
||||
verbatim into the header of all files for this C++ class implementation.
|
||||
Must be placed as a module item, e.g., directly inside a module/endmodule
|
||||
pair. Despite the name of this macro, this also works in pure C++ code.
|
||||
|
||||
.. option:: `systemc_implementation
|
||||
|
||||
Take the remaining text up to the next :option:`\`verilog` or
|
||||
:option:`\`systemc_... <\`systemc_header>` mode switch and place it
|
||||
verbatim into a single file of the C++ class implementation. Must be
|
||||
placed as a module item, e.g., directly inside a module/endmodule
|
||||
pair. Despite the name of this macro, this also works in pure C++ code.
|
||||
|
||||
If you will be reading or writing any Verilog variables in the C++
|
||||
functions, the Verilog signals must be declared with a
|
||||
:option:`/*verilator&32;public*/` metacomment. See also the public task
|
||||
feature; writing an accessor may result in cleaner code.
|
||||
|
||||
.. option:: `SYSTEMVERILOG
|
||||
|
||||
The SYSTEMVERILOG, SV_COV_START, and related standard defines are set by
|
||||
default when :vlopt:`--language <--language>` is "1800-\*".
|
||||
|
||||
.. option:: `VERILATOR
|
||||
|
||||
.. option:: `verilator
|
||||
|
||||
.. option:: `verilator3
|
||||
|
||||
The VERILATOR, verilator and verilator3 defines are set by default so
|
||||
you may "\`ifdef" around tool specific constructs.
|
||||
|
||||
.. option:: `verilator_config
|
||||
|
||||
Take the remaining text up to the next :option:`\`verilog` mode switch and
|
||||
treat it as Verilator configuration commands. See :ref:`Configuration Files`.
|
||||
|
||||
.. option:: `VERILATOR_TIMING
|
||||
|
||||
The VERILATOR_TIMING define is set when :vlopt:`--timing` is used to
|
||||
allow an "\`ifdef" of code dependent on this feature. Note that this define
|
||||
is not affected by the :option:`timing_off` configuration file option
|
||||
nor timing metacomments.
|
||||
|
||||
.. option:: `verilog
|
||||
|
||||
Switch back to processing Verilog code after a
|
||||
:option:`\`systemc_... <\`systemc_header>` mode switch. The Verilog
|
||||
code returns to the last language mode specified with
|
||||
"\`begin_keywords", or SystemVerilog if none was specified.
|
||||
|
||||
.. option:: /*verilator&32;clock_enable*/
|
||||
|
||||
Deprecated and has no effect (ignored).
|
||||
|
|
@ -212,6 +248,9 @@ or "`ifdef`"'s may break other tools.
|
|||
|
||||
Same as :option:`clock_enable` configuration file option.
|
||||
|
||||
|
||||
.. t_dist_docs_style ignore /*verilator&32;no_clocker*/
|
||||
|
||||
.. option:: /*verilator&32;clocker*/
|
||||
|
||||
.. option:: /*verilator&32;no_clocker*/
|
||||
|
|
@ -379,29 +418,6 @@ or "`ifdef`"'s may break other tools.
|
|||
|
||||
parameter [2:0] PARAM /*verilator public*/ = 2'b0;
|
||||
|
||||
.. option:: /*verilator&32;public*/ (on typedef enum)
|
||||
|
||||
Used after an enum typedef declaration to indicate the emitted C code
|
||||
should have the enum values visible. Due to C++ language restrictions,
|
||||
this may only be used on 64-bit or narrower integral enumerations.
|
||||
|
||||
.. code-block:: sv
|
||||
|
||||
typedef enum logic [2:0] { ZERO = 3'b0 } pub_t /*verilator public*/;
|
||||
|
||||
.. option:: /*verilator&32;public*/ (on variable)
|
||||
|
||||
Used after an input, output, register, or wire declaration to indicate
|
||||
the signal should be declared so that C code may read or write the value
|
||||
of the signal. This will also declare this module public; otherwise, use
|
||||
:code:`/*verilator&32;public_flat*/`.
|
||||
|
||||
Instead of using public variables, consider making a DPI or public
|
||||
function that accesses the variable. This is nicer as it provides an
|
||||
obvious entry point compatible across simulators.
|
||||
|
||||
Same as :option:`public` configuration file option.
|
||||
|
||||
.. option:: /*verilator&32;public*/ (on task/function)
|
||||
|
||||
Used inside the declaration section of a function or task declaration to
|
||||
|
|
@ -426,6 +442,52 @@ or "`ifdef`"'s may break other tools.
|
|||
|
||||
Same as :option:`public` configuration file option.
|
||||
|
||||
.. option:: /*verilator&32;public*/ (on typedef enum)
|
||||
|
||||
Used after an enum typedef declaration to indicate the emitted C code
|
||||
should have the enum values visible. Due to C++ language restrictions,
|
||||
this may only be used on 64-bit or narrower integral enumerations.
|
||||
|
||||
.. code-block:: sv
|
||||
|
||||
typedef enum logic [2:0] { ZERO = 3'b0 } pub_t /*verilator public*/;
|
||||
|
||||
.. option:: /*verilator&32;public*/ (on variable)
|
||||
|
||||
Used after an input, output, register, or wire declaration to indicate
|
||||
the signal should be declared so that C code may read or write the value
|
||||
of the signal. This will also declare this module public; otherwise, use
|
||||
:code:`/*verilator&32;public_flat*/`.
|
||||
|
||||
Instead of using public variables, consider making a DPI or public
|
||||
function that accesses the variable. This is nicer as it provides an
|
||||
obvious entry point compatible across simulators.
|
||||
|
||||
Same as :option:`public` configuration file option.
|
||||
|
||||
.. option:: /*verilator&32;public_[|flat|flat_rd|flat_rw]_on [@(<edge_list>)]*/ (as scope)
|
||||
|
||||
Used to wrap multiple signals and parameters with the respective public attribute.
|
||||
See attribute above for their respective behavior. Cannot be nested. e.g:
|
||||
|
||||
.. code-block:: sv
|
||||
|
||||
/*verilator public_flat_rw_on*/
|
||||
logic clk;
|
||||
logic rst;
|
||||
parameter width = 8;
|
||||
/* verilator public_off*/
|
||||
logic data;
|
||||
|
||||
Is equivalent to:
|
||||
|
||||
.. code-block:: sv
|
||||
|
||||
logic clk /*verilator public_flat_rw*/;
|
||||
logic rst /*verilator public_flat_rw*/;
|
||||
parameter width /*verilator public_flat_rw*/ = 8;
|
||||
logic data;
|
||||
|
||||
.. option:: /*verilator&32;public_flat*/ (on variable)
|
||||
|
||||
Used after an input, output, register, or wire declaration to indicate
|
||||
|
|
@ -453,33 +515,6 @@ or "`ifdef`"'s may break other tools.
|
|||
|
||||
Same as :option:`public_flat_rw` configuration file option.
|
||||
|
||||
.. option:: /*verilator&32;public_[|flat|flat_rd|flat_rw]_on [@(<edge_list>)]*/ (as scope)
|
||||
|
||||
Used to wrap multiple signals and parameters with the respective public attribute.
|
||||
See attribute above for their respective behavior. Cannot be nested. e.g:
|
||||
|
||||
.. code-block:: sv
|
||||
|
||||
/*verilator public_flat_rw_on*/
|
||||
logic clk;
|
||||
logic rst;
|
||||
parameter width = 8;
|
||||
/* verilator public_off*/
|
||||
logic data;
|
||||
|
||||
Is equivalent to:
|
||||
|
||||
.. code-block:: sv
|
||||
|
||||
logic clk /*verilator public_flat_rw*/;
|
||||
logic rst /*verilator public_flat_rw*/;
|
||||
parameter width /*verilator public_flat_rw*/ = 8;
|
||||
logic data;
|
||||
|
||||
.. option:: /*verilator&32;public_off*/
|
||||
|
||||
Terminates the previous `/*verilator public*_on*/` directive; see above.
|
||||
|
||||
.. option:: /*verilator&32;public_module*/
|
||||
|
||||
Used after a module statement to indicate the module should not be
|
||||
|
|
@ -490,13 +525,9 @@ or "`ifdef`"'s may break other tools.
|
|||
|
||||
Same as :option:`public` configuration file option.
|
||||
|
||||
.. option:: /*verilator&32;sc_clock*/
|
||||
.. option:: /*verilator&32;public_off*/
|
||||
|
||||
Deprecated and ignored. Previously used after an input declaration to
|
||||
indicate the signal should be declared in SystemC as a sc_clock instead
|
||||
of a bool. This was needed in SystemC 1.1 and 1.2 only; versions 2.0
|
||||
and later do not require clock pins to be sc_clocks, and this is no
|
||||
longer needed and is ignored.
|
||||
Terminates the previous `/*verilator public*_on*/` directive; see above.
|
||||
|
||||
.. option:: /*verilator&32;sc_bv*/
|
||||
|
||||
|
|
@ -509,6 +540,14 @@ or "`ifdef`"'s may break other tools.
|
|||
|
||||
Same as :option:`sc_bv` configuration file option.
|
||||
|
||||
.. option:: /*verilator&32;sc_clock*/
|
||||
|
||||
Deprecated and ignored. Previously used after an input declaration to
|
||||
indicate the signal should be declared in SystemC as a sc_clock instead
|
||||
of a bool. This was needed in SystemC 1.1 and 1.2 only; versions 2.0
|
||||
and later do not require clock pins to be sc_clocks, and this is no
|
||||
longer needed and is ignored.
|
||||
|
||||
.. option:: /*verilator&32;sformat*/
|
||||
|
||||
Attached to the final argument of type "input string" of a function or
|
||||
|
|
@ -597,7 +636,7 @@ or "`ifdef`"'s may break other tools.
|
|||
Attached to a DPI import to indicate that function should be called when
|
||||
initializing tracing. This attribute is indented only to be used
|
||||
internally in code that Verilator generates when :vlopt:`--lib-create`
|
||||
or :vlopt:`--hierarchical` is used along with :vlopt:`--trace`.
|
||||
or :vlopt:`--hierarchical` is used along with :vlopt:`--trace-vcd`.
|
||||
|
||||
.. option:: /*verilator&32;tracing_off*/
|
||||
|
||||
|
|
@ -627,13 +666,3 @@ or "`ifdef`"'s may break other tools.
|
|||
following loop at the same statement level should always be fully
|
||||
unrolled by Verilator, ignoring :vlopt:`--unroll-count`. This is
|
||||
similar to clang's ``#pragma clang loop unroll(full)``.
|
||||
|
||||
.. option:: $stacktrace
|
||||
|
||||
Called as a task, print a stack trace. Called as a function, return a
|
||||
string with a stack trace. This relies on the C++ system trace, which
|
||||
may give less meaningful results if the model is not compiled with debug
|
||||
symbols. Also, the data represents the C++ stack; the SystemVerilog
|
||||
functions/tasks involved may be renamed and/or inlined before becoming
|
||||
the C++ functions that may be visible in the stack trace. This
|
||||
extension was standardized in IEEE 1800-2023.
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
||||
|
|
@ -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
|
||||
^^^^^^^^^^
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ Input Languages
|
|||
***************
|
||||
|
||||
This section describes the languages Verilator takes as input. See also
|
||||
:ref:`Configuration Files`.
|
||||
:ref:`Verilator Configuration Files`.
|
||||
|
||||
|
||||
Language Standard Support
|
||||
|
|
@ -334,7 +334,8 @@ Gate Primitives
|
|||
|
||||
The 2-state gate primitives (and, buf, nand, nor, not, or, xnor, xor) are
|
||||
directly converted to behavioral equivalents. The 3-state and MOS gate
|
||||
primitives are not supported. Tables are not supported.
|
||||
primitives are not supported. User-defined primitive (UDP) tables are
|
||||
supported.
|
||||
|
||||
|
||||
Specify blocks
|
||||
|
|
@ -396,8 +397,8 @@ This section describes specific limitations for each language keyword.
|
|||
\`begin_keywords, \`begin_keywords, \`begin_keywords, \`begin_keywords,
|
||||
\`define, \`else, \`elsif, \`end_keywords, \`endif, \`error, \`ifdef,
|
||||
\`ifndef, \`include, \`line, \`systemc_ctor, \`systemc_dtor,
|
||||
\`systemc_header, \`systemc_imp_header, \`systemc_implementation,
|
||||
\`systemc_interface, \`undef, \`verilog
|
||||
\`systemc_header, \`systemc_header_post, \`systemc_imp_header,
|
||||
\`systemc_implementation, \`systemc_interface, \`undef, \`verilog
|
||||
|
||||
|cmdslong1|
|
||||
Fully supported.
|
||||
|
|
@ -488,7 +489,7 @@ $bits, $countbits, $countones, $finish, $isunknown, $onehot, $onehot0, $signed,
|
|||
|
||||
$dump/$dumpports and related
|
||||
$dumpfile or $dumpports will create a VCD or FST file (based on
|
||||
the :vlopt:`--trace` option given when the model was Verilated). This
|
||||
the :vlopt:`--trace-vcd` option given when the model was Verilated). This
|
||||
will take effect starting at the next eval() call. If you have multiple
|
||||
Verilated designs under the same C model, this will dump signals
|
||||
only from the design containing the $dumpvars.
|
||||
|
|
@ -535,4 +536,4 @@ $test$plusargs, $value$plusargs
|
|||
{VerilatedContext*} ->commandArgs(argc, argv);
|
||||
|
||||
to register the command line before calling $test$plusargs or
|
||||
$value$plusargs.
|
||||
$value$plusargs. Or use :vlopt:`--binary` or :vlopt:`--main`.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ There are two ways to mark a module:
|
|||
|
||||
* Write :option:`/*verilator&32;hier_block*/` metacomment in HDL code.
|
||||
|
||||
* Add a :option:`hier_block` line in the :ref:`Configuration Files`.
|
||||
* Add a :option:`hier_block` line in the :ref:`Verilator Configuration Files`.
|
||||
|
||||
Then pass the :vlopt:`--hierarchical` option to Verilator.
|
||||
|
||||
|
|
@ -221,7 +221,7 @@ model, it may be beneficial to performance to adjust the
|
|||
influences the partitioning of the model by adjusting the assumed execution
|
||||
time of DPI imports.
|
||||
|
||||
When using :vlopt:`--trace` to perform VCD tracing, the VCD trace
|
||||
When using :vlopt:`--trace-vcd` to perform VCD tracing, the VCD trace
|
||||
construction is parallelized using the same number of threads as specified
|
||||
with :vlopt:`--threads`, and is executed on the same thread pool as the model.
|
||||
|
||||
|
|
@ -243,11 +243,14 @@ trace. FST tracing can utilize up to 2 offload threads, so there is no use
|
|||
of setting :vlopt:`--trace-threads` higher than 2 at the moment.
|
||||
|
||||
When running a multithreaded model, the default Linux task scheduler often
|
||||
works against the model by assuming short-lived threads and thus
|
||||
it often schedules threads using multiple hyperthreads within the same
|
||||
physical core. For best performance, use the :command:`numactl` program to
|
||||
(when the threading count fits) select unique physical cores on the same
|
||||
socket. The same applies for :vlopt:`--trace-threads` as well.
|
||||
works against the model by assuming short-lived threads and thus it often
|
||||
schedules threads using multiple hyperthreads within the same physical
|
||||
core. If there is no affinity already set, on Linux only, Verilator
|
||||
attempts to set thread-to-processor affinity in a reasonable way.
|
||||
|
||||
For best performance, use the :command:`numactl` program to (when the
|
||||
threading count fits) select unique physical cores on the same socket. The
|
||||
same applies for :vlopt:`--trace-threads` as well.
|
||||
|
||||
As an example, if a model was Verilated with
|
||||
:vlopt:`--threads 4 <--threads>`, we consult:
|
||||
|
|
@ -290,8 +293,8 @@ and must be called only by the eval thread.
|
|||
If using :vlopt:`--sc`, the SystemC kernel is not thread-safe; therefore,
|
||||
the eval thread and main thread must be the same.
|
||||
|
||||
If using :vlopt:`--trace`, the tracing classes must be constructed and
|
||||
called from the main thread.
|
||||
If using :vlopt:`--trace-vcd` or other trace options, the tracing classes
|
||||
must be constructed and called from the main thread.
|
||||
|
||||
If using :vlopt:`--vpi`, since SystemVerilog VPI was not architected by
|
||||
IEEE to be multithreaded, Verilator requires all VPI calls are only made
|
||||
|
|
@ -367,10 +370,11 @@ Verilate in CMake
|
|||
.. code-block:: CMake
|
||||
|
||||
verilate(target SOURCES source ... [TOP_MODULE top] [PREFIX name]
|
||||
[TRACE] [TRACE_FST] [SYSTEMC] [COVERAGE]
|
||||
[COVERAGE] [SYSTEMC]
|
||||
[TRACE_FST] [TRACE_SAIF] [TRACE_VCD] [TRACE_THREADS num]
|
||||
[INCLUDE_DIRS dir ...] [OPT_SLOW ...] [OPT_FAST ...]
|
||||
[OPT_GLOBAL ..] [DIRECTORY dir] [THREADS num]
|
||||
[TRACE_THREADS num] [VERILATOR_ARGS ...])
|
||||
[VERILATOR_ARGS ...])
|
||||
|
||||
Lowercase and ... should be replaced with arguments; the uppercase parts
|
||||
delimit the arguments and can be passed in any order or left out entirely
|
||||
|
|
@ -443,10 +447,6 @@ SystemC include directories and link to the SystemC libraries.
|
|||
|
||||
Optional. Enable a multithreaded model; see :vlopt:`--threads`.
|
||||
|
||||
.. describe:: TRACE_THREADS
|
||||
|
||||
Optional. Enable multithreaded FST trace; see :vlopt:`--trace-threads`.
|
||||
|
||||
.. describe:: TOP_MODULE
|
||||
|
||||
Optional. Sets the name of the top module. Defaults to the name of the
|
||||
|
|
@ -454,8 +454,7 @@ SystemC include directories and link to the SystemC libraries.
|
|||
|
||||
.. describe:: TRACE
|
||||
|
||||
Optional. Enables VCD tracing if present, equivalent to "VERILATOR_ARGS
|
||||
--trace".
|
||||
Deprecated. Same as TRACE_VCD, which should be used instead.
|
||||
|
||||
.. describe:: TRACE_FST
|
||||
|
||||
|
|
@ -467,6 +466,15 @@ SystemC include directories and link to the SystemC libraries.
|
|||
Optional. Enables SAIF tracing if present, equivalent to "VERILATOR_ARGS
|
||||
--trace-saif".
|
||||
|
||||
.. describe:: TRACE_THREADS
|
||||
|
||||
Optional. Enable multithreaded FST trace; see :vlopt:`--trace-threads`.
|
||||
|
||||
.. describe:: TRACE_VCD
|
||||
|
||||
Optional. Enables VCD tracing if present, equivalent to "VERILATOR_ARGS
|
||||
--trace-vcd".
|
||||
|
||||
.. describe:: VERILATOR_ARGS
|
||||
|
||||
Optional. Extra arguments to Verilator. Do not specify :vlopt:`--Mdir`
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
.. Copyright 2003-2025 by Wilson Snyder.
|
||||
.. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
*******************
|
||||
Errors and Warnings
|
||||
*******************
|
||||
=====================
|
||||
Errors and Warnings
|
||||
=====================
|
||||
|
||||
.. _Disabling Warnings:
|
||||
|
||||
|
|
@ -37,7 +37,7 @@ Warnings may be disabled in multiple ways:
|
|||
propagate upwards to any parent file (file that included the file with
|
||||
the lint_off).
|
||||
|
||||
#. Disable the warning using :ref:`Configuration Files` with a
|
||||
#. Disable the warning using :ref:`Verilator Configuration Files` with a
|
||||
:option:`lint_off` command. This is useful when a script suppresses
|
||||
warnings, and the Verilog source should not be changed. This method also
|
||||
allows matching on the warning text.
|
||||
|
|
@ -86,6 +86,8 @@ List Of Warnings
|
|||
Limitations`.
|
||||
|
||||
|
||||
.. t_dist_docs_style restart_sort
|
||||
|
||||
.. option:: ALWCOMBORDER
|
||||
|
||||
.. TODO better example
|
||||
|
|
@ -165,6 +167,24 @@ List Of Warnings
|
|||
'pragma protect'. Third-party pragmas not defined by IEEE 1800-2023 are
|
||||
ignored.
|
||||
|
||||
This error may be disabled with a lint_off BADSTDPRAGMA metacomment.
|
||||
|
||||
|
||||
.. option:: BADVLTPRAGMA
|
||||
|
||||
An error that a `/*verilator ...*/` metacomment pragma is badly formed
|
||||
or not understood.
|
||||
|
||||
Faulty example:
|
||||
|
||||
.. include:: ../../docs/gen/ex_BADVLTPRAGMA_faulty.rst
|
||||
|
||||
Results in:
|
||||
|
||||
.. include:: ../../docs/gen/ex_BADVLTPRAGMA_msg.rst
|
||||
|
||||
This error may be disabled with a lint_off BADVLTPRAGMA metacomment.
|
||||
|
||||
|
||||
.. option:: BLKANDNBLK
|
||||
|
||||
|
|
@ -472,6 +492,31 @@ List Of Warnings
|
|||
correctly.
|
||||
|
||||
|
||||
.. option:: DEFOVERRIDE
|
||||
|
||||
Warns that a macro definition within the code is being overridden by a command line directive:
|
||||
|
||||
For example, running Verilator with :code:`<+define+\<DUP\>=\<def2\>>` and
|
||||
|
||||
.. code-block:: sv
|
||||
:linenos:
|
||||
:emphasize-lines: 1
|
||||
|
||||
`define DUP def2 //<--- Warning
|
||||
|
||||
Results in:
|
||||
|
||||
.. code-block::
|
||||
|
||||
%Warning-DEFOVERRIDE: example.v1:20: Overriding define: 'DEF' with value: 'def2' to existing command line define value: 'def1'
|
||||
... Location of previous definition, with value: '50'
|
||||
|
||||
While not explicitly stated in the IEEE 1800-2023 standard, this warning
|
||||
tracks with the other simulators' behavior of overriding macro
|
||||
definitions within code files with the definition passed in through
|
||||
the command line.
|
||||
|
||||
|
||||
.. option:: DEFPARAM
|
||||
|
||||
Warns that the :code:`defparam` statement was deprecated in IEEE 1364-2001,
|
||||
|
|
@ -1222,13 +1267,6 @@ List Of Warnings
|
|||
simulate correctly.
|
||||
|
||||
|
||||
.. option:: NOTIMING
|
||||
|
||||
Error when a timing-related construct that requires :vlopt:`--timing` has
|
||||
been encountered. Issued only if Verilator is run with the
|
||||
:vlopt:`--no-timing` option.
|
||||
|
||||
|
||||
.. option:: NONSTD
|
||||
|
||||
Warns when a non-standard language feature is used that has a standard
|
||||
|
|
@ -1237,6 +1275,13 @@ List Of Warnings
|
|||
:code:`$sformatf`.
|
||||
|
||||
|
||||
.. option:: NOTIMING
|
||||
|
||||
Error when a timing-related construct that requires :vlopt:`--timing` has
|
||||
been encountered. Issued only if Verilator is run with the
|
||||
:vlopt:`--no-timing` option.
|
||||
|
||||
|
||||
.. option:: NULLPORT
|
||||
|
||||
Warns that a null port was detected in the module definition port
|
||||
|
|
@ -1261,6 +1306,7 @@ List Of Warnings
|
|||
Ignoring this warning will only suppress the lint check; it will
|
||||
simulate correctly.
|
||||
|
||||
|
||||
.. option:: PINCONNECTEMPTY
|
||||
|
||||
.. TODO better example
|
||||
|
|
@ -1349,6 +1395,26 @@ List Of Warnings
|
|||
This error may be disabled with a lint_off PINNOTFOUND metacomment.
|
||||
|
||||
|
||||
.. option:: PKGNODECL
|
||||
|
||||
An error that a package/class appears to have been referenced that has
|
||||
not yet been declared. According to IEEE 1800-2023 26.3, all packages
|
||||
must be declared before being used.
|
||||
|
||||
Faulty example:
|
||||
|
||||
.. include:: ../../docs/gen/ex_PKGNODECL_faulty.rst
|
||||
|
||||
Results in:
|
||||
|
||||
.. include:: ../../docs/gen/ex_PKGNODECL_msg.rst
|
||||
|
||||
Often the package is declared in its own header file. In this case add
|
||||
an include of that package header file to the referencing file. (And
|
||||
make sure you have header guards in the package's header file to prevent
|
||||
multiple declarations of the package.)
|
||||
|
||||
|
||||
.. option:: PORTSHORT
|
||||
|
||||
Warns that an output port is connected to a constant.
|
||||
|
|
@ -1372,26 +1438,6 @@ List Of Warnings
|
|||
This error may be disabled with a lint_off PORTSHORT metacomment.
|
||||
|
||||
|
||||
.. option:: PKGNODECL
|
||||
|
||||
An error that a package/class appears to have been referenced that has
|
||||
not yet been declared. According to IEEE 1800-2023 26.3, all packages
|
||||
must be declared before being used.
|
||||
|
||||
Faulty example:
|
||||
|
||||
.. include:: ../../docs/gen/ex_PKGNODECL_faulty.rst
|
||||
|
||||
Results in:
|
||||
|
||||
.. include:: ../../docs/gen/ex_PKGNODECL_msg.rst
|
||||
|
||||
Often the package is declared in its own header file. In this case add
|
||||
an include of that package header file to the referencing file. (And
|
||||
make sure you have header guards in the package's header file to prevent
|
||||
multiple declarations of the package.)
|
||||
|
||||
|
||||
.. option:: PREPROCZERO
|
||||
|
||||
Warns that a preprocessor \`ifdef/\`ifndef expression (added in IEEE
|
||||
|
|
@ -1417,6 +1463,35 @@ List Of Warnings
|
|||
than zero, when it is to be used in a preprocessor expression.
|
||||
|
||||
|
||||
.. option:: PROCASSINIT
|
||||
|
||||
Warns that the specified signal is given an initial value where it is
|
||||
declared, and is also driven in an always process. Typically such
|
||||
initial values should instead be set using a reset signal inside the
|
||||
process, to match requirements of hardware synthesis tools.
|
||||
|
||||
Faulty example:
|
||||
|
||||
.. include:: ../../docs/gen/ex_PROCASSINIT_faulty.rst
|
||||
|
||||
Results in:
|
||||
|
||||
.. include:: ../../docs/gen/ex_PROCASSINIT_msg.rst
|
||||
|
||||
One possible fix, adding a reset to the always:
|
||||
|
||||
.. include:: ../../docs/gen/ex_PROCASSINIT_fixed.rst
|
||||
|
||||
Alternatively, use an initial block for the initialization:
|
||||
|
||||
.. code-block:: sv
|
||||
|
||||
initial flop_out = 1; // <--- Fixed
|
||||
|
||||
Disabled by default as this is a code-style warning; it will simulate
|
||||
correctly.
|
||||
|
||||
|
||||
.. option:: PROCASSWIRE
|
||||
|
||||
.. TODO better example
|
||||
|
|
@ -2118,7 +2193,7 @@ List Of Warnings
|
|||
|
||||
.. include:: ../../docs/gen/ex_VARHIDDEN_msg.rst
|
||||
|
||||
To resolve this, rename the variable to an unique name.
|
||||
To resolve this, rename the inner or outer variable to an unique name.
|
||||
|
||||
|
||||
.. option:: WAITCONST
|
||||
|
|
@ -2181,21 +2256,6 @@ List Of Warnings
|
|||
.. include:: ../../docs/gen/ex_WIDTHEXPAND_1_fixed.rst
|
||||
|
||||
|
||||
.. option:: WIDTHTRUNC
|
||||
|
||||
A more granular :option:`WIDTH` warning, for when a value is
|
||||
truncated. See :option:`WIDTH`.
|
||||
|
||||
.. option:: WIDTHEXPAND
|
||||
|
||||
A more granular :option:`WIDTH` warning, for when a value is zero
|
||||
expanded. See :option:`WIDTH`.
|
||||
|
||||
.. option:: WIDTHXZEXPAND
|
||||
|
||||
A more granular :option:`WIDTH` warning, for when a value is X/Z
|
||||
expanded. See :option:`WIDTH`.
|
||||
|
||||
.. option:: WIDTHCONCAT
|
||||
|
||||
Warns that based on the width rules of Verilog, a concatenate, or
|
||||
|
|
@ -2221,6 +2281,21 @@ List Of Warnings
|
|||
width to the parameter usage (:code:`{PAR[31:0], PAR[31:0]}`).
|
||||
|
||||
|
||||
.. option:: WIDTHEXPAND
|
||||
|
||||
A more granular :option:`WIDTH` warning, for when a value is zero
|
||||
expanded. See :option:`WIDTH`.
|
||||
|
||||
.. option:: WIDTHTRUNC
|
||||
|
||||
A more granular :option:`WIDTH` warning, for when a value is
|
||||
truncated. See :option:`WIDTH`.
|
||||
|
||||
.. option:: WIDTHXZEXPAND
|
||||
|
||||
A more granular :option:`WIDTH` warning, for when a value is X/Z
|
||||
expanded. See :option:`WIDTH`.
|
||||
|
||||
.. option:: ZERODLY
|
||||
|
||||
Warns that `#0` delays do not schedule the process to be resumed in the
|
||||
|
|
|
|||
|
|
@ -1903,7 +1903,7 @@ find what made a <e#*#*> line in the tree dumps):
|
|||
|
||||
::
|
||||
|
||||
watch AstNode::s_editCntGbl==####
|
||||
watch AstNode::s_editCntGbl=####
|
||||
|
||||
Then, when the watch fires, to break at every following change to that
|
||||
node:
|
||||
|
|
@ -2046,6 +2046,11 @@ driver.py Non-Scenario Arguments
|
|||
Same as ``verilator --debugi level``: Set Verilator internal debugging
|
||||
level globally to the specified debug level (1-10).
|
||||
|
||||
--driver-clean
|
||||
After a test passes, remove the generated objects. Reduces storage
|
||||
requirements, but may result in longer runtime if the tests are run
|
||||
again.
|
||||
|
||||
--dump-tree
|
||||
Same as ``verilator --dump-tree``: Enable Verilator writing .tree debug
|
||||
files with dumping level 3, which dumps the standard critical stages.
|
||||
|
|
@ -2079,6 +2084,9 @@ driver.py Non-Scenario Arguments
|
|||
Run number of parallel tests, or 0 to determine the count based on the
|
||||
number of cores installed.
|
||||
|
||||
--obj-suffix <name>
|
||||
Append the argument to the name of the ``test_regress/obj_`` directories.
|
||||
|
||||
--quiet
|
||||
Suppress all output except for failures and progress messages every 15
|
||||
seconds. Intended for use only in automated regressions. See also
|
||||
|
|
|
|||
|
|
@ -273,6 +273,7 @@ Mednick
|
|||
Mei
|
||||
Melo
|
||||
Menküc
|
||||
Menon
|
||||
Michail
|
||||
Michiels
|
||||
Microsystems
|
||||
|
|
@ -303,6 +304,7 @@ Nauticus
|
|||
Newgard
|
||||
Nigam
|
||||
Nikana
|
||||
Niraj
|
||||
Niranjan
|
||||
Nitza
|
||||
Noack
|
||||
|
|
@ -652,6 +654,7 @@ elike
|
|||
elsif
|
||||
endcase
|
||||
endcelldefine
|
||||
endclass
|
||||
endfunction
|
||||
endgenerate
|
||||
endian
|
||||
|
|
@ -862,6 +865,7 @@ noprivate
|
|||
noreturn
|
||||
notif
|
||||
nullptr
|
||||
numactl
|
||||
onehot
|
||||
ooo
|
||||
oprofile
|
||||
|
|
@ -1099,6 +1103,7 @@ verilogmod
|
|||
verimake
|
||||
veriuser
|
||||
vl
|
||||
vlSelf
|
||||
vlopt
|
||||
vlt
|
||||
vltstd
|
||||
|
|
|
|||
|
|
@ -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 ----------------"
|
||||
|
|
|
|||
|
|
@ -58,11 +58,11 @@ class VlHierGraph:
|
|||
top_module = False
|
||||
fh.write("];\n")
|
||||
|
||||
cells = self.flatten(mod, lambda n: n['type'] == "CELL")
|
||||
for cell in cells:
|
||||
def_number = self.addr_to_vertex_number(cell['modp'])
|
||||
instances = self.flatten(mod, lambda n: n['type'] == "CELL")
|
||||
for inst in instances:
|
||||
def_number = self.addr_to_vertex_number(inst['modp'])
|
||||
fh.write(" n%d->n%d [label=\"%s\"];\n" %
|
||||
(mod_number, def_number, cell['name']))
|
||||
(mod_number, def_number, inst['name']))
|
||||
|
||||
fh.write("}\n")
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -12,19 +12,26 @@ module secret_impl
|
|||
input [31:0] a,
|
||||
input [31:0] b,
|
||||
output logic [31:0] x,
|
||||
input clk);
|
||||
input clk,
|
||||
input reset_l);
|
||||
|
||||
logic [31:0] accum_q = 0;
|
||||
logic [31:0] secret_value = 9;
|
||||
logic [31:0] accum_q;
|
||||
logic [31:0] secret_value;
|
||||
|
||||
initial $display("[%0t] %m: initialized", $time);
|
||||
|
||||
always @(posedge clk) begin
|
||||
accum_q <= accum_q + a;
|
||||
if (accum_q > 10)
|
||||
x <= b;
|
||||
else
|
||||
x <= a + b + secret_value;
|
||||
if (!reset_l) begin
|
||||
accum_q <= 0;
|
||||
secret_value <= 9;
|
||||
end
|
||||
else begin
|
||||
accum_q <= accum_q + a;
|
||||
if (accum_q > 10)
|
||||
x <= b;
|
||||
else
|
||||
x <= a + b + secret_value;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
|
|
|||
|
|
@ -8,26 +8,36 @@
|
|||
|
||||
module top (input clk);
|
||||
|
||||
integer cyc = 0;
|
||||
logic [31:0] a = 0;
|
||||
logic [31:0] b = 0;
|
||||
int cyc;
|
||||
logic reset_l;
|
||||
logic [31:0] a;
|
||||
logic [31:0] b;
|
||||
logic [31:0] x;
|
||||
|
||||
verilated_secret secret (.a, .b, .x, .clk);
|
||||
verilated_secret secret (.a, .b, .x, .clk, .reset_l);
|
||||
|
||||
always @(posedge clk) begin
|
||||
$display("[%0t] cyc=%0d a=%0d b=%0d x=%0d", $time, cyc, a, b, x);
|
||||
cyc <= cyc + 1;
|
||||
if (cyc == 0) begin
|
||||
reset_l <= 0;
|
||||
a <= 0;
|
||||
b <= 0;
|
||||
end
|
||||
else if (cyc == 1) begin
|
||||
reset_l <= 1;
|
||||
a <= 5;
|
||||
b <= 7;
|
||||
end else if (cyc == 1) begin
|
||||
end
|
||||
else if (cyc == 2) begin
|
||||
a <= 6;
|
||||
b <= 2;
|
||||
end else if (cyc == 2) begin
|
||||
end
|
||||
else if (cyc == 3) begin
|
||||
a <= 1;
|
||||
b <= 9;
|
||||
end else if (cyc > 3) begin
|
||||
end
|
||||
else if (cyc > 4) begin
|
||||
$display("Done");
|
||||
$finish;
|
||||
end
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -37,10 +37,9 @@
|
|||
*
|
||||
*/
|
||||
|
||||
// #ifndef FST_CONFIG_INCLUDE
|
||||
// # define FST_CONFIG_INCLUDE <config.h>
|
||||
// #endif
|
||||
// #include FST_CONFIG_INCLUDE
|
||||
#ifdef FST_INCLUDE_CONFIG
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include "fstapi.h"
|
||||
#include "fastlz.h"
|
||||
|
|
@ -60,21 +59,6 @@
|
|||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ALLOCA_H
|
||||
#include <alloca.h>
|
||||
#elif defined(__GNUC__)
|
||||
#ifndef __MINGW32__
|
||||
#ifndef alloca
|
||||
#define alloca __builtin_alloca
|
||||
#endif
|
||||
#else
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
#elif defined(_MSC_VER)
|
||||
#include <malloc.h>
|
||||
#define alloca _alloca
|
||||
#endif
|
||||
|
||||
#ifndef PATH_MAX
|
||||
#define PATH_MAX (4096)
|
||||
#endif
|
||||
|
|
@ -1113,10 +1097,9 @@ static void fstDetermineBreakSize(struct fstWriterContext *xc)
|
|||
/*
|
||||
* file creation and close
|
||||
*/
|
||||
void *fstWriterCreate(const char *nam, int use_compressed_hier)
|
||||
fstWriterContext *fstWriterCreate(const char *nam, int use_compressed_hier)
|
||||
{
|
||||
struct fstWriterContext *xc =
|
||||
(struct fstWriterContext *)calloc(1, sizeof(struct fstWriterContext));
|
||||
fstWriterContext *xc = (fstWriterContext *)calloc(1, sizeof(fstWriterContext));
|
||||
|
||||
xc->compress_hier = use_compressed_hier;
|
||||
fstDetermineBreakSize(xc);
|
||||
|
|
@ -1175,10 +1158,8 @@ void *fstWriterCreate(const char *nam, int use_compressed_hier)
|
|||
/*
|
||||
* generation and writing out of value change data sections
|
||||
*/
|
||||
static void fstWriterEmitSectionHeader(void *ctx)
|
||||
static void fstWriterEmitSectionHeader(fstWriterContext *xc)
|
||||
{
|
||||
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
|
||||
|
||||
if (xc) {
|
||||
unsigned long destlen;
|
||||
unsigned char *dmem;
|
||||
|
|
@ -1235,9 +1216,9 @@ static void fstWriterEmitSectionHeader(void *ctx)
|
|||
* be synced up with time changes
|
||||
*/
|
||||
#ifdef FST_WRITER_PARALLEL
|
||||
static void fstWriterFlushContextPrivate2(void *ctx)
|
||||
static void fstWriterFlushContextPrivate2(fstWriterContext *xc)
|
||||
#else
|
||||
static void fstWriterFlushContextPrivate(void *ctx)
|
||||
static void fstWriterFlushContextPrivate(fstWriterContext *xc)
|
||||
#endif
|
||||
{
|
||||
#ifdef FST_DEBUG
|
||||
|
|
@ -1257,7 +1238,6 @@ static void fstWriterFlushContextPrivate(void *ctx)
|
|||
unsigned char *packmem;
|
||||
unsigned int packmemlen;
|
||||
uint32_t *vm4ip;
|
||||
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
|
||||
#ifdef FST_WRITER_PARALLEL
|
||||
struct fstWriterContext *xc2 = xc->xc_parent;
|
||||
#else
|
||||
|
|
@ -1775,10 +1755,8 @@ static void *fstWriterFlushContextPrivate1(void *ctx)
|
|||
return (NULL);
|
||||
}
|
||||
|
||||
static void fstWriterFlushContextPrivate(void *ctx)
|
||||
static void fstWriterFlushContextPrivate(fstWriterContext *xc)
|
||||
{
|
||||
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
|
||||
|
||||
if (xc->parallel_enabled) {
|
||||
struct fstWriterContext *xc2 =
|
||||
(struct fstWriterContext *)malloc(sizeof(struct fstWriterContext));
|
||||
|
|
@ -1852,9 +1830,8 @@ static void fstWriterFlushContextPrivate(void *ctx)
|
|||
/*
|
||||
* queues up a flush context operation
|
||||
*/
|
||||
void fstWriterFlushContext(void *ctx)
|
||||
void fstWriterFlushContext(fstWriterContext *xc)
|
||||
{
|
||||
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
|
||||
if (xc) {
|
||||
if (xc->tchn_idx > 1) {
|
||||
xc->flush_context_pending = 1;
|
||||
|
|
@ -1865,10 +1842,8 @@ void fstWriterFlushContext(void *ctx)
|
|||
/*
|
||||
* close out FST file
|
||||
*/
|
||||
void fstWriterClose(void *ctx)
|
||||
void fstWriterClose(fstWriterContext *xc)
|
||||
{
|
||||
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
|
||||
|
||||
#ifdef FST_WRITER_PARALLEL
|
||||
if (xc) {
|
||||
pthread_mutex_lock(&xc->mutex);
|
||||
|
|
@ -2234,9 +2209,8 @@ void fstWriterClose(void *ctx)
|
|||
/*
|
||||
* functions to set miscellaneous header/block information
|
||||
*/
|
||||
void fstWriterSetDate(void *ctx, const char *dat)
|
||||
void fstWriterSetDate(fstWriterContext *xc, const char *dat)
|
||||
{
|
||||
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
|
||||
if (xc) {
|
||||
char s[FST_HDR_DATE_SIZE];
|
||||
fst_off_t fpos = ftello(xc->handle);
|
||||
|
|
@ -2251,9 +2225,8 @@ void fstWriterSetDate(void *ctx, const char *dat)
|
|||
}
|
||||
}
|
||||
|
||||
void fstWriterSetVersion(void *ctx, const char *vers)
|
||||
void fstWriterSetVersion(fstWriterContext *xc, const char *vers)
|
||||
{
|
||||
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
|
||||
if (xc && vers) {
|
||||
char s[FST_HDR_SIM_VERSION_SIZE];
|
||||
fst_off_t fpos = ftello(xc->handle);
|
||||
|
|
@ -2268,9 +2241,8 @@ void fstWriterSetVersion(void *ctx, const char *vers)
|
|||
}
|
||||
}
|
||||
|
||||
void fstWriterSetFileType(void *ctx, enum fstFileType filetype)
|
||||
void fstWriterSetFileType(fstWriterContext *xc, enum fstFileType filetype)
|
||||
{
|
||||
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
|
||||
if (xc) {
|
||||
if (/*(filetype >= FST_FT_MIN) &&*/ (filetype <= FST_FT_MAX)) {
|
||||
fst_off_t fpos = ftello(xc->handle);
|
||||
|
|
@ -2285,9 +2257,11 @@ void fstWriterSetFileType(void *ctx, enum fstFileType filetype)
|
|||
}
|
||||
}
|
||||
|
||||
static void fstWriterSetAttrDoubleArgGeneric(void *ctx, int typ, uint64_t arg1, uint64_t arg2)
|
||||
static void fstWriterSetAttrDoubleArgGeneric(fstWriterContext *xc,
|
||||
int typ,
|
||||
uint64_t arg1,
|
||||
uint64_t arg2)
|
||||
{
|
||||
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
|
||||
if (xc) {
|
||||
unsigned char buf[11]; /* ceil(64/7) = 10 + null term */
|
||||
unsigned char *pnt = fstCopyVarint64ToRight(buf, arg1);
|
||||
|
|
@ -2300,9 +2274,8 @@ static void fstWriterSetAttrDoubleArgGeneric(void *ctx, int typ, uint64_t arg1,
|
|||
}
|
||||
}
|
||||
|
||||
static void fstWriterSetAttrGeneric(void *ctx, const char *comm, int typ, uint64_t arg)
|
||||
static void fstWriterSetAttrGeneric(fstWriterContext *xc, const char *comm, int typ, uint64_t arg)
|
||||
{
|
||||
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
|
||||
if (xc && comm) {
|
||||
char *s = strdup(comm);
|
||||
char *sf = s;
|
||||
|
|
@ -2318,14 +2291,12 @@ static void fstWriterSetAttrGeneric(void *ctx, const char *comm, int typ, uint64
|
|||
}
|
||||
}
|
||||
|
||||
static void fstWriterSetSourceStem_2(void *ctx,
|
||||
static void fstWriterSetSourceStem_2(fstWriterContext *xc,
|
||||
const char *path,
|
||||
unsigned int line,
|
||||
unsigned int use_realpath,
|
||||
int typ)
|
||||
{
|
||||
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
|
||||
|
||||
if (xc && path && path[0]) {
|
||||
uint64_t sidx = 0;
|
||||
int slen = strlen(path);
|
||||
|
|
@ -2357,7 +2328,7 @@ static void fstWriterSetSourceStem_2(void *ctx,
|
|||
}
|
||||
}
|
||||
|
||||
void fstWriterSetSourceStem(void *ctx,
|
||||
void fstWriterSetSourceStem(fstWriterContext *ctx,
|
||||
const char *path,
|
||||
unsigned int line,
|
||||
unsigned int use_realpath)
|
||||
|
|
@ -2365,7 +2336,7 @@ void fstWriterSetSourceStem(void *ctx,
|
|||
fstWriterSetSourceStem_2(ctx, path, line, use_realpath, FST_MT_SOURCESTEM);
|
||||
}
|
||||
|
||||
void fstWriterSetSourceInstantiationStem(void *ctx,
|
||||
void fstWriterSetSourceInstantiationStem(fstWriterContext *ctx,
|
||||
const char *path,
|
||||
unsigned int line,
|
||||
unsigned int use_realpath)
|
||||
|
|
@ -2373,24 +2344,23 @@ void fstWriterSetSourceInstantiationStem(void *ctx,
|
|||
fstWriterSetSourceStem_2(ctx, path, line, use_realpath, FST_MT_SOURCEISTEM);
|
||||
}
|
||||
|
||||
void fstWriterSetComment(void *ctx, const char *comm)
|
||||
void fstWriterSetComment(fstWriterContext *ctx, const char *comm)
|
||||
{
|
||||
fstWriterSetAttrGeneric(ctx, comm, FST_MT_COMMENT, 0);
|
||||
}
|
||||
|
||||
void fstWriterSetValueList(void *ctx, const char *vl)
|
||||
void fstWriterSetValueList(fstWriterContext *ctx, const char *vl)
|
||||
{
|
||||
fstWriterSetAttrGeneric(ctx, vl, FST_MT_VALUELIST, 0);
|
||||
}
|
||||
|
||||
void fstWriterSetEnvVar(void *ctx, const char *envvar)
|
||||
void fstWriterSetEnvVar(fstWriterContext *ctx, const char *envvar)
|
||||
{
|
||||
fstWriterSetAttrGeneric(ctx, envvar, FST_MT_ENVVAR, 0);
|
||||
}
|
||||
|
||||
void fstWriterSetTimescale(void *ctx, int ts)
|
||||
void fstWriterSetTimescale(fstWriterContext *xc, int ts)
|
||||
{
|
||||
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
|
||||
if (xc) {
|
||||
fst_off_t fpos = ftello(xc->handle);
|
||||
fstWriterFseeko(xc, xc->handle, FST_HDR_OFFS_TIMESCALE, SEEK_SET);
|
||||
|
|
@ -2400,9 +2370,8 @@ void fstWriterSetTimescale(void *ctx, int ts)
|
|||
}
|
||||
}
|
||||
|
||||
void fstWriterSetTimescaleFromString(void *ctx, const char *s)
|
||||
void fstWriterSetTimescaleFromString(fstWriterContext *xc, const char *s)
|
||||
{
|
||||
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
|
||||
if (xc && s) {
|
||||
int mat = 0;
|
||||
int seconds_exp = -9;
|
||||
|
|
@ -2458,13 +2427,12 @@ void fstWriterSetTimescaleFromString(void *ctx, const char *s)
|
|||
seconds_exp += 2;
|
||||
}
|
||||
|
||||
fstWriterSetTimescale(ctx, seconds_exp);
|
||||
fstWriterSetTimescale(xc, seconds_exp);
|
||||
}
|
||||
}
|
||||
|
||||
void fstWriterSetTimezero(void *ctx, int64_t tim)
|
||||
void fstWriterSetTimezero(fstWriterContext *xc, int64_t tim)
|
||||
{
|
||||
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
|
||||
if (xc) {
|
||||
fst_off_t fpos = ftello(xc->handle);
|
||||
fstWriterFseeko(xc, xc->handle, FST_HDR_OFFS_TIMEZERO, SEEK_SET);
|
||||
|
|
@ -2474,26 +2442,23 @@ void fstWriterSetTimezero(void *ctx, int64_t tim)
|
|||
}
|
||||
}
|
||||
|
||||
void fstWriterSetPackType(void *ctx, enum fstWriterPackType typ)
|
||||
void fstWriterSetPackType(fstWriterContext *xc, enum fstWriterPackType typ)
|
||||
{
|
||||
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
|
||||
if (xc) {
|
||||
xc->fastpack = (typ != FST_WR_PT_ZLIB);
|
||||
xc->fourpack = (typ == FST_WR_PT_LZ4);
|
||||
}
|
||||
}
|
||||
|
||||
void fstWriterSetRepackOnClose(void *ctx, int enable)
|
||||
void fstWriterSetRepackOnClose(fstWriterContext *xc, int enable)
|
||||
{
|
||||
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
|
||||
if (xc) {
|
||||
xc->repack_on_close = (enable != 0);
|
||||
}
|
||||
}
|
||||
|
||||
void fstWriterSetParallelMode(void *ctx, int enable)
|
||||
void fstWriterSetParallelMode(fstWriterContext *xc, int enable)
|
||||
{
|
||||
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
|
||||
if (xc) {
|
||||
xc->parallel_was_enabled |= xc->parallel_enabled; /* make sticky */
|
||||
xc->parallel_enabled = (enable != 0);
|
||||
|
|
@ -2508,17 +2473,15 @@ void fstWriterSetParallelMode(void *ctx, int enable)
|
|||
}
|
||||
}
|
||||
|
||||
void fstWriterSetDumpSizeLimit(void *ctx, uint64_t numbytes)
|
||||
void fstWriterSetDumpSizeLimit(fstWriterContext *xc, uint64_t numbytes)
|
||||
{
|
||||
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
|
||||
if (xc) {
|
||||
xc->dump_size_limit = numbytes;
|
||||
}
|
||||
}
|
||||
|
||||
int fstWriterGetDumpSizeLimitReached(void *ctx)
|
||||
int fstWriterGetDumpSizeLimitReached(fstWriterContext *xc)
|
||||
{
|
||||
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
|
||||
if (xc) {
|
||||
return (xc->size_limit_locked != 0);
|
||||
}
|
||||
|
|
@ -2526,9 +2489,8 @@ int fstWriterGetDumpSizeLimitReached(void *ctx)
|
|||
return (0);
|
||||
}
|
||||
|
||||
int fstWriterGetFseekFailed(void *ctx)
|
||||
int fstWriterGetFseekFailed(fstWriterContext *xc)
|
||||
{
|
||||
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
|
||||
if (xc) {
|
||||
return (xc->fseek_failed != 0);
|
||||
}
|
||||
|
|
@ -2536,14 +2498,13 @@ int fstWriterGetFseekFailed(void *ctx)
|
|||
return (0);
|
||||
}
|
||||
|
||||
static int fstWriterGetFlushContextPendingInternal(struct fstWriterContext *xc)
|
||||
static int fstWriterGetFlushContextPendingInternal(fstWriterContext *xc)
|
||||
{
|
||||
return (xc->vchg_siz >= xc->fst_break_size) || (xc->flush_context_pending);
|
||||
}
|
||||
|
||||
int fstWriterGetFlushContextPending(void *ctx)
|
||||
int fstWriterGetFlushContextPending(fstWriterContext *xc)
|
||||
{
|
||||
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
|
||||
return xc && !xc->is_initial_time && fstWriterGetFlushContextPendingInternal(xc);
|
||||
}
|
||||
|
||||
|
|
@ -2552,7 +2513,7 @@ int fstWriterGetFlushContextPending(void *ctx)
|
|||
* fstWriterCreateVar2() is used to dump VHDL or other languages, but the
|
||||
* underlying variable needs to map to Verilog/SV via the proper fstVarType vt
|
||||
*/
|
||||
fstHandle fstWriterCreateVar2(void *ctx,
|
||||
fstHandle fstWriterCreateVar2(fstWriterContext *ctx,
|
||||
enum fstVarType vt,
|
||||
enum fstVarDir vd,
|
||||
uint32_t len,
|
||||
|
|
@ -2569,14 +2530,13 @@ fstHandle fstWriterCreateVar2(void *ctx,
|
|||
return (fstWriterCreateVar(ctx, vt, vd, len, nam, aliasHandle));
|
||||
}
|
||||
|
||||
fstHandle fstWriterCreateVar(void *ctx,
|
||||
fstHandle fstWriterCreateVar(fstWriterContext *xc,
|
||||
enum fstVarType vt,
|
||||
enum fstVarDir vd,
|
||||
uint32_t len,
|
||||
const char *nam,
|
||||
fstHandle aliasHandle)
|
||||
{
|
||||
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
|
||||
unsigned int i;
|
||||
int nlen, is_real;
|
||||
|
||||
|
|
@ -2660,13 +2620,11 @@ fstHandle fstWriterCreateVar(void *ctx,
|
|||
return (0);
|
||||
}
|
||||
|
||||
void fstWriterSetScope(void *ctx,
|
||||
void fstWriterSetScope(fstWriterContext *xc,
|
||||
enum fstScopeType scopetype,
|
||||
const char *scopename,
|
||||
const char *scopecomp)
|
||||
{
|
||||
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
|
||||
|
||||
if (xc) {
|
||||
fputc(FST_ST_VCD_SCOPE, xc->hier_handle);
|
||||
if (/*(scopetype < FST_ST_VCD_MODULE) ||*/ (scopetype > FST_ST_MAX)) {
|
||||
|
|
@ -2692,24 +2650,20 @@ void fstWriterSetScope(void *ctx,
|
|||
}
|
||||
}
|
||||
|
||||
void fstWriterSetUpscope(void *ctx)
|
||||
void fstWriterSetUpscope(fstWriterContext *xc)
|
||||
{
|
||||
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
|
||||
|
||||
if (xc) {
|
||||
fputc(FST_ST_VCD_UPSCOPE, xc->hier_handle);
|
||||
xc->hier_file_len++;
|
||||
}
|
||||
}
|
||||
|
||||
void fstWriterSetAttrBegin(void *ctx,
|
||||
void fstWriterSetAttrBegin(fstWriterContext *xc,
|
||||
enum fstAttrType attrtype,
|
||||
int subtype,
|
||||
const char *attrname,
|
||||
uint64_t arg)
|
||||
{
|
||||
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
|
||||
|
||||
if (xc) {
|
||||
fputc(FST_ST_GEN_ATTRBEGIN, xc->hier_handle);
|
||||
if (/*(attrtype < FST_AT_MISC) ||*/ (attrtype > FST_AT_MAX)) {
|
||||
|
|
@ -2750,17 +2704,15 @@ void fstWriterSetAttrBegin(void *ctx,
|
|||
}
|
||||
}
|
||||
|
||||
void fstWriterSetAttrEnd(void *ctx)
|
||||
void fstWriterSetAttrEnd(fstWriterContext *xc)
|
||||
{
|
||||
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
|
||||
|
||||
if (xc) {
|
||||
fputc(FST_ST_GEN_ATTREND, xc->hier_handle);
|
||||
xc->hier_file_len++;
|
||||
}
|
||||
}
|
||||
|
||||
fstEnumHandle fstWriterCreateEnumTable(void *ctx,
|
||||
fstEnumHandle fstWriterCreateEnumTable(fstWriterContext *xc,
|
||||
const char *name,
|
||||
uint32_t elem_count,
|
||||
unsigned int min_valbits,
|
||||
|
|
@ -2779,9 +2731,7 @@ fstEnumHandle fstWriterCreateEnumTable(void *ctx,
|
|||
int pos = 0;
|
||||
char *attr_str = NULL;
|
||||
|
||||
if (ctx && name && literal_arr && val_arr && (elem_count != 0)) {
|
||||
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
|
||||
|
||||
if (xc && name && literal_arr && val_arr && (elem_count != 0)) {
|
||||
uint32_t i;
|
||||
|
||||
name_len = strlen(name);
|
||||
|
|
@ -2866,9 +2816,8 @@ fstEnumHandle fstWriterCreateEnumTable(void *ctx,
|
|||
return (handle);
|
||||
}
|
||||
|
||||
void fstWriterEmitEnumTableRef(void *ctx, fstEnumHandle handle)
|
||||
void fstWriterEmitEnumTableRef(fstWriterContext *xc, fstEnumHandle handle)
|
||||
{
|
||||
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
|
||||
if (xc && handle) {
|
||||
fstWriterSetAttrBegin(xc, FST_AT_MISC, FST_MT_ENUMTABLE, NULL, handle);
|
||||
}
|
||||
|
|
@ -2877,9 +2826,8 @@ void fstWriterEmitEnumTableRef(void *ctx, fstEnumHandle handle)
|
|||
/*
|
||||
* value and time change emission
|
||||
*/
|
||||
void fstWriterEmitValueChange(void *ctx, fstHandle handle, const void *val)
|
||||
void fstWriterEmitValueChange(fstWriterContext *xc, fstHandle handle, const void *val)
|
||||
{
|
||||
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
|
||||
const unsigned char *buf = (const unsigned char *)val;
|
||||
uint32_t offs;
|
||||
int len;
|
||||
|
|
@ -2987,7 +2935,10 @@ void fstWriterEmitValueChange(void *ctx, fstHandle handle, const void *val)
|
|||
}
|
||||
}
|
||||
|
||||
void fstWriterEmitValueChange32(void *ctx, fstHandle handle, uint32_t bits, uint32_t val)
|
||||
void fstWriterEmitValueChange32(fstWriterContext *ctx,
|
||||
fstHandle handle,
|
||||
uint32_t bits,
|
||||
uint32_t val)
|
||||
{
|
||||
char buf[32];
|
||||
char *s = buf;
|
||||
|
|
@ -2997,7 +2948,11 @@ void fstWriterEmitValueChange32(void *ctx, fstHandle handle, uint32_t bits, uint
|
|||
}
|
||||
fstWriterEmitValueChange(ctx, handle, buf);
|
||||
}
|
||||
void fstWriterEmitValueChange64(void *ctx, fstHandle handle, uint32_t bits, uint64_t val)
|
||||
|
||||
void fstWriterEmitValueChange64(fstWriterContext *ctx,
|
||||
fstHandle handle,
|
||||
uint32_t bits,
|
||||
uint64_t val)
|
||||
{
|
||||
char buf[64];
|
||||
char *s = buf;
|
||||
|
|
@ -3007,11 +2962,14 @@ void fstWriterEmitValueChange64(void *ctx, fstHandle handle, uint32_t bits, uint
|
|||
}
|
||||
fstWriterEmitValueChange(ctx, handle, buf);
|
||||
}
|
||||
void fstWriterEmitValueChangeVec32(void *ctx, fstHandle handle, uint32_t bits, const uint32_t *val)
|
||||
|
||||
void fstWriterEmitValueChangeVec32(fstWriterContext *xc,
|
||||
fstHandle handle,
|
||||
uint32_t bits,
|
||||
const uint32_t *val)
|
||||
{
|
||||
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
|
||||
if (FST_UNLIKELY(bits <= 32)) {
|
||||
fstWriterEmitValueChange32(ctx, handle, bits, val[0]);
|
||||
fstWriterEmitValueChange32(xc, handle, bits, val[0]);
|
||||
} else if (FST_LIKELY(xc)) {
|
||||
int bq = bits / 32;
|
||||
int br = bits & 31;
|
||||
|
|
@ -3047,14 +3005,16 @@ void fstWriterEmitValueChangeVec32(void *ctx, fstHandle handle, uint32_t bits, c
|
|||
s += 4;
|
||||
}
|
||||
}
|
||||
fstWriterEmitValueChange(ctx, handle, xc->outval_mem);
|
||||
fstWriterEmitValueChange(xc, handle, xc->outval_mem);
|
||||
}
|
||||
}
|
||||
void fstWriterEmitValueChangeVec64(void *ctx, fstHandle handle, uint32_t bits, const uint64_t *val)
|
||||
void fstWriterEmitValueChangeVec64(fstWriterContext *xc,
|
||||
fstHandle handle,
|
||||
uint32_t bits,
|
||||
const uint64_t *val)
|
||||
{
|
||||
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
|
||||
if (FST_UNLIKELY(bits <= 64)) {
|
||||
fstWriterEmitValueChange64(ctx, handle, bits, val[0]);
|
||||
fstWriterEmitValueChange64(xc, handle, bits, val[0]);
|
||||
} else if (FST_LIKELY(xc)) {
|
||||
int bq = bits / 64;
|
||||
int br = bits & 63;
|
||||
|
|
@ -3090,16 +3050,15 @@ void fstWriterEmitValueChangeVec64(void *ctx, fstHandle handle, uint32_t bits, c
|
|||
s += 4;
|
||||
}
|
||||
}
|
||||
fstWriterEmitValueChange(ctx, handle, xc->outval_mem);
|
||||
fstWriterEmitValueChange(xc, handle, xc->outval_mem);
|
||||
}
|
||||
}
|
||||
|
||||
void fstWriterEmitVariableLengthValueChange(void *ctx,
|
||||
void fstWriterEmitVariableLengthValueChange(fstWriterContext *xc,
|
||||
fstHandle handle,
|
||||
const void *val,
|
||||
uint32_t len)
|
||||
{
|
||||
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
|
||||
const unsigned char *buf = (const unsigned char *)val;
|
||||
|
||||
if (FST_LIKELY((xc) && (handle <= xc->maxhandle))) {
|
||||
|
|
@ -3143,9 +3102,8 @@ void fstWriterEmitVariableLengthValueChange(void *ctx,
|
|||
}
|
||||
}
|
||||
|
||||
void fstWriterEmitTimeChange(void *ctx, uint64_t tim)
|
||||
void fstWriterEmitTimeChange(fstWriterContext *xc, uint64_t tim)
|
||||
{
|
||||
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
|
||||
unsigned int i;
|
||||
int skip = 0;
|
||||
if (xc) {
|
||||
|
|
@ -3189,10 +3147,8 @@ void fstWriterEmitTimeChange(void *ctx, uint64_t tim)
|
|||
}
|
||||
}
|
||||
|
||||
void fstWriterEmitDumpActive(void *ctx, int enable)
|
||||
void fstWriterEmitDumpActive(fstWriterContext *xc, int enable)
|
||||
{
|
||||
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
|
||||
|
||||
if (xc) {
|
||||
struct fstBlackoutChain *b =
|
||||
(struct fstBlackoutChain *)calloc(1, sizeof(struct fstBlackoutChain));
|
||||
|
|
@ -3420,7 +3376,7 @@ static void fstWritex(struct fstReaderContext *xc,
|
|||
/*
|
||||
* scope -> flat name handling
|
||||
*/
|
||||
static void fstReaderDeallocateScopeData(struct fstReaderContext *xc)
|
||||
static void fstReaderDeallocateScopeData(fstReaderContext *xc)
|
||||
{
|
||||
struct fstCurrHier *chp;
|
||||
|
||||
|
|
@ -3433,9 +3389,8 @@ static void fstReaderDeallocateScopeData(struct fstReaderContext *xc)
|
|||
}
|
||||
}
|
||||
|
||||
const char *fstReaderGetCurrentFlatScope(void *ctx)
|
||||
const char *fstReaderGetCurrentFlatScope(fstReaderContext *xc)
|
||||
{
|
||||
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
|
||||
if (xc) {
|
||||
return (xc->curr_flat_hier_nam ? xc->curr_flat_hier_nam : "");
|
||||
} else {
|
||||
|
|
@ -3443,9 +3398,8 @@ const char *fstReaderGetCurrentFlatScope(void *ctx)
|
|||
}
|
||||
}
|
||||
|
||||
void *fstReaderGetCurrentScopeUserInfo(void *ctx)
|
||||
void *fstReaderGetCurrentScopeUserInfo(fstReaderContext *xc)
|
||||
{
|
||||
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
|
||||
if (xc) {
|
||||
return (xc->curr_hier ? xc->curr_hier->user_info : NULL);
|
||||
} else {
|
||||
|
|
@ -3453,9 +3407,8 @@ void *fstReaderGetCurrentScopeUserInfo(void *ctx)
|
|||
}
|
||||
}
|
||||
|
||||
const char *fstReaderPopScope(void *ctx)
|
||||
const char *fstReaderPopScope(fstReaderContext *xc)
|
||||
{
|
||||
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
|
||||
if (xc && xc->curr_hier) {
|
||||
struct fstCurrHier *ch = xc->curr_hier;
|
||||
if (xc->curr_hier->prev) {
|
||||
|
|
@ -3471,19 +3424,16 @@ const char *fstReaderPopScope(void *ctx)
|
|||
return (NULL);
|
||||
}
|
||||
|
||||
void fstReaderResetScope(void *ctx)
|
||||
void fstReaderResetScope(fstReaderContext *xc)
|
||||
{
|
||||
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
|
||||
|
||||
if (xc) {
|
||||
while (fstReaderPopScope(xc))
|
||||
; /* remove any already-built scoping info */
|
||||
}
|
||||
}
|
||||
|
||||
const char *fstReaderPushScope(void *ctx, const char *nam, void *user_info)
|
||||
const char *fstReaderPushScope(fstReaderContext *xc, const char *nam, void *user_info)
|
||||
{
|
||||
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
|
||||
if (xc) {
|
||||
struct fstCurrHier *ch = (struct fstCurrHier *)malloc(sizeof(struct fstCurrHier));
|
||||
int chl = xc->curr_hier ? xc->curr_hier->len : 0;
|
||||
|
|
@ -3512,10 +3462,8 @@ const char *fstReaderPushScope(void *ctx, const char *nam, void *user_info)
|
|||
return (NULL);
|
||||
}
|
||||
|
||||
int fstReaderGetCurrentScopeLen(void *ctx)
|
||||
int fstReaderGetCurrentScopeLen(fstReaderContext *xc)
|
||||
{
|
||||
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
|
||||
|
||||
if (xc && xc->curr_hier) {
|
||||
return (xc->curr_hier->len);
|
||||
}
|
||||
|
|
@ -3523,9 +3471,8 @@ int fstReaderGetCurrentScopeLen(void *ctx)
|
|||
return (0);
|
||||
}
|
||||
|
||||
int fstReaderGetFseekFailed(void *ctx)
|
||||
int fstReaderGetFseekFailed(fstReaderContext *xc)
|
||||
{
|
||||
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
|
||||
if (xc) {
|
||||
return (xc->fseek_failed != 0);
|
||||
}
|
||||
|
|
@ -3536,10 +3483,8 @@ int fstReaderGetFseekFailed(void *ctx)
|
|||
/*
|
||||
* iter mask manipulation util functions
|
||||
*/
|
||||
int fstReaderGetFacProcessMask(void *ctx, fstHandle facidx)
|
||||
int fstReaderGetFacProcessMask(fstReaderContext *xc, fstHandle facidx)
|
||||
{
|
||||
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
|
||||
|
||||
if (xc) {
|
||||
facidx--;
|
||||
if (facidx < xc->maxhandle) {
|
||||
|
|
@ -3552,10 +3497,8 @@ int fstReaderGetFacProcessMask(void *ctx, fstHandle facidx)
|
|||
return (0);
|
||||
}
|
||||
|
||||
void fstReaderSetFacProcessMask(void *ctx, fstHandle facidx)
|
||||
void fstReaderSetFacProcessMask(fstReaderContext *xc, fstHandle facidx)
|
||||
{
|
||||
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
|
||||
|
||||
if (xc) {
|
||||
facidx--;
|
||||
if (facidx < xc->maxhandle) {
|
||||
|
|
@ -3567,10 +3510,8 @@ void fstReaderSetFacProcessMask(void *ctx, fstHandle facidx)
|
|||
}
|
||||
}
|
||||
|
||||
void fstReaderClrFacProcessMask(void *ctx, fstHandle facidx)
|
||||
void fstReaderClrFacProcessMask(fstReaderContext *xc, fstHandle facidx)
|
||||
{
|
||||
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
|
||||
|
||||
if (xc) {
|
||||
facidx--;
|
||||
if (facidx < xc->maxhandle) {
|
||||
|
|
@ -3582,19 +3523,15 @@ void fstReaderClrFacProcessMask(void *ctx, fstHandle facidx)
|
|||
}
|
||||
}
|
||||
|
||||
void fstReaderSetFacProcessMaskAll(void *ctx)
|
||||
void fstReaderSetFacProcessMaskAll(fstReaderContext *xc)
|
||||
{
|
||||
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
|
||||
|
||||
if (xc) {
|
||||
memset(xc->process_mask, 0xff, (xc->maxhandle + 7) / 8);
|
||||
}
|
||||
}
|
||||
|
||||
void fstReaderClrFacProcessMaskAll(void *ctx)
|
||||
void fstReaderClrFacProcessMaskAll(fstReaderContext *xc)
|
||||
{
|
||||
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
|
||||
|
||||
if (xc) {
|
||||
memset(xc->process_mask, 0x00, (xc->maxhandle + 7) / 8);
|
||||
}
|
||||
|
|
@ -3603,100 +3540,83 @@ void fstReaderClrFacProcessMaskAll(void *ctx)
|
|||
/*
|
||||
* various utility read/write functions
|
||||
*/
|
||||
signed char fstReaderGetTimescale(void *ctx)
|
||||
signed char fstReaderGetTimescale(fstReaderContext *xc)
|
||||
{
|
||||
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
|
||||
return (xc ? xc->timescale : 0);
|
||||
}
|
||||
|
||||
uint64_t fstReaderGetStartTime(void *ctx)
|
||||
uint64_t fstReaderGetStartTime(fstReaderContext *xc)
|
||||
{
|
||||
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
|
||||
return (xc ? xc->start_time : 0);
|
||||
}
|
||||
|
||||
uint64_t fstReaderGetEndTime(void *ctx)
|
||||
uint64_t fstReaderGetEndTime(fstReaderContext *xc)
|
||||
{
|
||||
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
|
||||
return (xc ? xc->end_time : 0);
|
||||
}
|
||||
|
||||
uint64_t fstReaderGetMemoryUsedByWriter(void *ctx)
|
||||
uint64_t fstReaderGetMemoryUsedByWriter(fstReaderContext *xc)
|
||||
{
|
||||
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
|
||||
return (xc ? xc->mem_used_by_writer : 0);
|
||||
}
|
||||
|
||||
uint64_t fstReaderGetScopeCount(void *ctx)
|
||||
uint64_t fstReaderGetScopeCount(fstReaderContext *xc)
|
||||
{
|
||||
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
|
||||
return (xc ? xc->scope_count : 0);
|
||||
}
|
||||
|
||||
uint64_t fstReaderGetVarCount(void *ctx)
|
||||
uint64_t fstReaderGetVarCount(fstReaderContext *xc)
|
||||
{
|
||||
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
|
||||
return (xc ? xc->var_count : 0);
|
||||
}
|
||||
|
||||
fstHandle fstReaderGetMaxHandle(void *ctx)
|
||||
fstHandle fstReaderGetMaxHandle(fstReaderContext *xc)
|
||||
{
|
||||
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
|
||||
return (xc ? xc->maxhandle : 0);
|
||||
}
|
||||
|
||||
uint64_t fstReaderGetAliasCount(void *ctx)
|
||||
uint64_t fstReaderGetAliasCount(fstReaderContext *xc)
|
||||
{
|
||||
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
|
||||
return (xc ? xc->num_alias : 0);
|
||||
}
|
||||
|
||||
uint64_t fstReaderGetValueChangeSectionCount(void *ctx)
|
||||
uint64_t fstReaderGetValueChangeSectionCount(fstReaderContext *xc)
|
||||
{
|
||||
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
|
||||
return (xc ? xc->vc_section_count : 0);
|
||||
}
|
||||
|
||||
int fstReaderGetDoubleEndianMatchState(void *ctx)
|
||||
int fstReaderGetDoubleEndianMatchState(fstReaderContext *xc)
|
||||
{
|
||||
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
|
||||
return (xc ? xc->double_endian_match : 0);
|
||||
}
|
||||
|
||||
const char *fstReaderGetVersionString(void *ctx)
|
||||
const char *fstReaderGetVersionString(fstReaderContext *xc)
|
||||
{
|
||||
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
|
||||
return (xc ? xc->version : NULL);
|
||||
}
|
||||
|
||||
const char *fstReaderGetDateString(void *ctx)
|
||||
const char *fstReaderGetDateString(fstReaderContext *xc)
|
||||
{
|
||||
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
|
||||
return (xc ? xc->date : NULL);
|
||||
}
|
||||
|
||||
int fstReaderGetFileType(void *ctx)
|
||||
int fstReaderGetFileType(fstReaderContext *xc)
|
||||
{
|
||||
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
|
||||
return (xc ? (int)xc->filetype : (int)FST_FT_VERILOG);
|
||||
}
|
||||
|
||||
int64_t fstReaderGetTimezero(void *ctx)
|
||||
int64_t fstReaderGetTimezero(fstReaderContext *xc)
|
||||
{
|
||||
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
|
||||
return (xc ? xc->timezero : 0);
|
||||
}
|
||||
|
||||
uint32_t fstReaderGetNumberDumpActivityChanges(void *ctx)
|
||||
uint32_t fstReaderGetNumberDumpActivityChanges(fstReaderContext *xc)
|
||||
{
|
||||
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
|
||||
return (xc ? xc->num_blackouts : 0);
|
||||
}
|
||||
|
||||
uint64_t fstReaderGetDumpActivityChangeTime(void *ctx, uint32_t idx)
|
||||
uint64_t fstReaderGetDumpActivityChangeTime(fstReaderContext *xc, uint32_t idx)
|
||||
{
|
||||
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
|
||||
|
||||
if (xc && (idx < xc->num_blackouts) && (xc->blackout_times)) {
|
||||
return (xc->blackout_times[idx]);
|
||||
} else {
|
||||
|
|
@ -3704,10 +3624,8 @@ uint64_t fstReaderGetDumpActivityChangeTime(void *ctx, uint32_t idx)
|
|||
}
|
||||
}
|
||||
|
||||
unsigned char fstReaderGetDumpActivityChangeValue(void *ctx, uint32_t idx)
|
||||
unsigned char fstReaderGetDumpActivityChangeValue(fstReaderContext *xc, uint32_t idx)
|
||||
{
|
||||
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
|
||||
|
||||
if (xc && (idx < xc->num_blackouts) && (xc->blackout_activity)) {
|
||||
return (xc->blackout_activity[idx]);
|
||||
} else {
|
||||
|
|
@ -3715,10 +3633,8 @@ unsigned char fstReaderGetDumpActivityChangeValue(void *ctx, uint32_t idx)
|
|||
}
|
||||
}
|
||||
|
||||
void fstReaderSetLimitTimeRange(void *ctx, uint64_t start_time, uint64_t end_time)
|
||||
void fstReaderSetLimitTimeRange(fstReaderContext *xc, uint64_t start_time, uint64_t end_time)
|
||||
{
|
||||
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
|
||||
|
||||
if (xc) {
|
||||
xc->limit_range_valid = 1;
|
||||
xc->limit_range_start = start_time;
|
||||
|
|
@ -3726,27 +3642,22 @@ void fstReaderSetLimitTimeRange(void *ctx, uint64_t start_time, uint64_t end_tim
|
|||
}
|
||||
}
|
||||
|
||||
void fstReaderSetUnlimitedTimeRange(void *ctx)
|
||||
void fstReaderSetUnlimitedTimeRange(fstReaderContext *xc)
|
||||
{
|
||||
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
|
||||
|
||||
if (xc) {
|
||||
xc->limit_range_valid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void fstReaderSetVcdExtensions(void *ctx, int enable)
|
||||
void fstReaderSetVcdExtensions(fstReaderContext *xc, int enable)
|
||||
{
|
||||
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
|
||||
|
||||
if (xc) {
|
||||
xc->use_vcd_extensions = (enable != 0);
|
||||
}
|
||||
}
|
||||
|
||||
void fstReaderIterBlocksSetNativeDoublesOnCallback(void *ctx, int enable)
|
||||
void fstReaderIterBlocksSetNativeDoublesOnCallback(fstReaderContext *xc, int enable)
|
||||
{
|
||||
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
|
||||
if (xc) {
|
||||
xc->native_doubles_for_cb = (enable != 0);
|
||||
}
|
||||
|
|
@ -3942,9 +3853,8 @@ static int fstReaderRecreateHierFile(struct fstReaderContext *xc)
|
|||
return (pass_status);
|
||||
}
|
||||
|
||||
int fstReaderIterateHierRewind(void *ctx)
|
||||
int fstReaderIterateHierRewind(fstReaderContext *xc)
|
||||
{
|
||||
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
|
||||
int pass_status = 0;
|
||||
|
||||
if (xc) {
|
||||
|
|
@ -3959,13 +3869,13 @@ int fstReaderIterateHierRewind(void *ctx)
|
|||
return (pass_status);
|
||||
}
|
||||
|
||||
struct fstHier *fstReaderIterateHier(void *ctx)
|
||||
struct fstHier *fstReaderIterateHier(fstReaderContext *xc)
|
||||
{
|
||||
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
|
||||
int isfeof;
|
||||
fstHandle alias;
|
||||
char *pnt;
|
||||
int ch;
|
||||
int unnamed_scope_idx = 0;
|
||||
|
||||
if (!xc)
|
||||
return (NULL);
|
||||
|
|
@ -3997,6 +3907,9 @@ struct fstHier *fstReaderIterateHier(void *ctx)
|
|||
pnt[cl++] = ch;
|
||||
}
|
||||
}; /* scopename */
|
||||
if (!cl) {
|
||||
cl = snprintf(pnt, FST_ID_NAM_SIZ, "$unnamed_scope_%d", unnamed_scope_idx++);
|
||||
}
|
||||
pnt[cl] = 0;
|
||||
xc->hier.u.scope.name_length = cl;
|
||||
|
||||
|
|
@ -4122,9 +4035,8 @@ struct fstHier *fstReaderIterateHier(void *ctx)
|
|||
return (!isfeof ? &xc->hier : NULL);
|
||||
}
|
||||
|
||||
int fstReaderProcessHier(void *ctx, FILE *fv)
|
||||
int fstReaderProcessHier(fstReaderContext *xc, FILE *fv)
|
||||
{
|
||||
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
|
||||
char *str;
|
||||
char *pnt;
|
||||
int ch, scopetype;
|
||||
|
|
@ -4136,6 +4048,7 @@ int fstReaderProcessHier(void *ctx, FILE *fv)
|
|||
uint64_t attrarg;
|
||||
fstHandle maxhandle_scanbuild;
|
||||
int cl;
|
||||
int unnamed_scope_idx = 0;
|
||||
|
||||
if (!xc)
|
||||
return (0);
|
||||
|
|
@ -4271,6 +4184,9 @@ int fstReaderProcessHier(void *ctx, FILE *fv)
|
|||
pnt[cl++] = ch;
|
||||
}
|
||||
}; /* scopename */
|
||||
if (!cl) {
|
||||
cl = snprintf(pnt, FST_ID_NAM_SIZ, "$unnamed_scope_%d", unnamed_scope_idx++);
|
||||
}
|
||||
pnt[cl] = 0;
|
||||
while (fgetc(xc->fh)) {
|
||||
}; /* scopecomp */
|
||||
|
|
@ -4802,18 +4718,16 @@ int fstReaderInit(struct fstReaderContext *xc)
|
|||
return (hdr_seen);
|
||||
}
|
||||
|
||||
void *fstReaderOpenForUtilitiesOnly(void)
|
||||
fstReaderContext *fstReaderOpenForUtilitiesOnly(void)
|
||||
{
|
||||
struct fstReaderContext *xc =
|
||||
(struct fstReaderContext *)calloc(1, sizeof(struct fstReaderContext));
|
||||
fstReaderContext *xc = (fstReaderContext *)calloc(1, sizeof(fstReaderContext));
|
||||
|
||||
return (xc);
|
||||
}
|
||||
|
||||
void *fstReaderOpen(const char *nam)
|
||||
fstReaderContext *fstReaderOpen(const char *nam)
|
||||
{
|
||||
struct fstReaderContext *xc =
|
||||
(struct fstReaderContext *)calloc(1, sizeof(struct fstReaderContext));
|
||||
fstReaderContext *xc = (fstReaderContext *)calloc(1, sizeof(fstReaderContext));
|
||||
|
||||
if ((!nam) || (!(xc->f = fopen(nam, "rb")))) {
|
||||
free(xc);
|
||||
|
|
@ -4842,7 +4756,7 @@ void *fstReaderOpen(const char *nam)
|
|||
((xc->fh) || (xc->contains_hier_section || (xc->contains_hier_section_lz4)))) {
|
||||
/* more init */
|
||||
xc->do_rewind = 1;
|
||||
} else {
|
||||
} else if (!rc) {
|
||||
fstReaderClose(xc);
|
||||
xc = NULL;
|
||||
}
|
||||
|
|
@ -4851,9 +4765,8 @@ void *fstReaderOpen(const char *nam)
|
|||
return (xc);
|
||||
}
|
||||
|
||||
static void fstReaderDeallocateRvatData(void *ctx)
|
||||
static void fstReaderDeallocateRvatData(fstReaderContext *xc)
|
||||
{
|
||||
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
|
||||
if (xc) {
|
||||
free(xc->rvat_chain_mem);
|
||||
xc->rvat_chain_mem = NULL;
|
||||
|
|
@ -4870,10 +4783,8 @@ static void fstReaderDeallocateRvatData(void *ctx)
|
|||
}
|
||||
}
|
||||
|
||||
void fstReaderClose(void *ctx)
|
||||
void fstReaderClose(fstReaderContext *xc)
|
||||
{
|
||||
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
|
||||
|
||||
if (xc) {
|
||||
fstReaderDeallocateScopeData(xc);
|
||||
fstReaderDeallocateRvatData(xc);
|
||||
|
|
@ -4918,7 +4829,7 @@ void fstReaderClose(void *ctx)
|
|||
*/
|
||||
|
||||
/* normal read which re-interleaves the value change data */
|
||||
int fstReaderIterBlocks(void *ctx,
|
||||
int fstReaderIterBlocks(fstReaderContext *ctx,
|
||||
void (*value_change_callback)(void *user_callback_data_pointer,
|
||||
uint64_t time,
|
||||
fstHandle facidx,
|
||||
|
|
@ -4929,7 +4840,7 @@ int fstReaderIterBlocks(void *ctx,
|
|||
return (fstReaderIterBlocks2(ctx, value_change_callback, NULL, user_callback_data_pointer, fv));
|
||||
}
|
||||
|
||||
int fstReaderIterBlocks2(void *ctx,
|
||||
int fstReaderIterBlocks2(fstReaderContext *ctx,
|
||||
void (*value_change_callback)(void *user_callback_data_pointer,
|
||||
uint64_t time,
|
||||
fstHandle facidx,
|
||||
|
|
@ -6003,7 +5914,7 @@ int fstReaderIterBlocks2(void *ctx,
|
|||
|
||||
/* rvat functions */
|
||||
|
||||
static char *fstExtractRvatDataFromFrame(struct fstReaderContext *xc, fstHandle facidx, char *buf)
|
||||
static char *fstExtractRvatDataFromFrame(fstReaderContext *xc, fstHandle facidx, char *buf)
|
||||
{
|
||||
if (facidx >= xc->rvat_frame_maxhandle) {
|
||||
return (NULL);
|
||||
|
|
@ -6038,9 +5949,11 @@ static char *fstExtractRvatDataFromFrame(struct fstReaderContext *xc, fstHandle
|
|||
return (buf);
|
||||
}
|
||||
|
||||
char *fstReaderGetValueFromHandleAtTime(void *ctx, uint64_t tim, fstHandle facidx, char *buf)
|
||||
char *fstReaderGetValueFromHandleAtTime(fstReaderContext *xc,
|
||||
uint64_t tim,
|
||||
fstHandle facidx,
|
||||
char *buf)
|
||||
{
|
||||
struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
|
||||
fst_off_t blkpos = 0, prev_blkpos;
|
||||
uint64_t beg_tim, end_tim, beg_tim2, end_tim2;
|
||||
int sectype;
|
||||
|
|
|
|||
|
|
@ -43,8 +43,6 @@ extern "C"
|
|||
#endif
|
||||
#include <time.h>
|
||||
|
||||
#define FST_RDLOAD "FSTLOAD | "
|
||||
|
||||
typedef uint32_t fstHandle;
|
||||
typedef uint32_t fstEnumHandle;
|
||||
|
||||
|
|
@ -372,16 +370,19 @@ struct fstETab
|
|||
/*
|
||||
* writer functions
|
||||
*/
|
||||
void fstWriterClose(void *ctx);
|
||||
void *fstWriterCreate(const char *nam, int use_compressed_hier);
|
||||
fstEnumHandle fstWriterCreateEnumTable(void *ctx,
|
||||
|
||||
typedef struct fstWriterContext fstWriterContext;
|
||||
|
||||
void fstWriterClose(fstWriterContext *ctx);
|
||||
fstWriterContext *fstWriterCreate(const char *nam, int use_compressed_hier);
|
||||
fstEnumHandle fstWriterCreateEnumTable(fstWriterContext *ctx,
|
||||
const char *name,
|
||||
uint32_t elem_count,
|
||||
unsigned int min_valbits,
|
||||
const char **literal_arr,
|
||||
const char **val_arr);
|
||||
/* used for Verilog/SV */
|
||||
fstHandle fstWriterCreateVar(void *ctx,
|
||||
fstHandle fstWriterCreateVar(fstWriterContext *ctx,
|
||||
enum fstVarType vt,
|
||||
enum fstVarDir vd,
|
||||
uint32_t len,
|
||||
|
|
@ -390,7 +391,7 @@ fstHandle fstWriterCreateVar(void *ctx,
|
|||
/* future expansion for VHDL and other languages. The variable type, data type, etc map onto
|
||||
the current Verilog/SV one. The "type" string is optional for a more verbose or custom
|
||||
description */
|
||||
fstHandle fstWriterCreateVar2(void *ctx,
|
||||
fstHandle fstWriterCreateVar2(fstWriterContext *ctx,
|
||||
enum fstVarType vt,
|
||||
enum fstVarDir vd,
|
||||
uint32_t len,
|
||||
|
|
@ -399,123 +400,136 @@ fstHandle fstWriterCreateVar2(void *ctx,
|
|||
const char *type,
|
||||
enum fstSupplementalVarType svt,
|
||||
enum fstSupplementalDataType sdt);
|
||||
void fstWriterEmitDumpActive(void *ctx, int enable);
|
||||
void fstWriterEmitEnumTableRef(void *ctx, fstEnumHandle handle);
|
||||
void fstWriterEmitValueChange(void *ctx, fstHandle handle, const void *val);
|
||||
void fstWriterEmitValueChange32(void *ctx, fstHandle handle, uint32_t bits, uint32_t val);
|
||||
void fstWriterEmitValueChange64(void *ctx, fstHandle handle, uint32_t bits, uint64_t val);
|
||||
void fstWriterEmitValueChangeVec32(void *ctx,
|
||||
void fstWriterEmitDumpActive(fstWriterContext *ctx, int enable);
|
||||
void fstWriterEmitEnumTableRef(fstWriterContext *ctx, fstEnumHandle handle);
|
||||
void fstWriterEmitValueChange(fstWriterContext *ctx, fstHandle handle, const void *val);
|
||||
void fstWriterEmitValueChange32(fstWriterContext *ctx,
|
||||
fstHandle handle,
|
||||
uint32_t bits,
|
||||
uint32_t val);
|
||||
void fstWriterEmitValueChange64(fstWriterContext *ctx,
|
||||
fstHandle handle,
|
||||
uint32_t bits,
|
||||
uint64_t val);
|
||||
void fstWriterEmitValueChangeVec32(fstWriterContext *ctx,
|
||||
fstHandle handle,
|
||||
uint32_t bits,
|
||||
const uint32_t *val);
|
||||
void fstWriterEmitValueChangeVec64(void *ctx,
|
||||
void fstWriterEmitValueChangeVec64(fstWriterContext *ctx,
|
||||
fstHandle handle,
|
||||
uint32_t bits,
|
||||
const uint64_t *val);
|
||||
void fstWriterEmitVariableLengthValueChange(void *ctx,
|
||||
void fstWriterEmitVariableLengthValueChange(fstWriterContext *ctx,
|
||||
fstHandle handle,
|
||||
const void *val,
|
||||
uint32_t len);
|
||||
void fstWriterEmitTimeChange(void *ctx, uint64_t tim);
|
||||
void fstWriterFlushContext(void *ctx);
|
||||
int fstWriterGetDumpSizeLimitReached(void *ctx);
|
||||
int fstWriterGetFseekFailed(void *ctx);
|
||||
int fstWriterGetFlushContextPending(void *ctx);
|
||||
void fstWriterSetAttrBegin(void *ctx,
|
||||
void fstWriterEmitTimeChange(fstWriterContext *ctx, uint64_t tim);
|
||||
void fstWriterFlushContext(fstWriterContext *ctx);
|
||||
int fstWriterGetDumpSizeLimitReached(fstWriterContext *ctx);
|
||||
int fstWriterGetFseekFailed(fstWriterContext *ctx);
|
||||
int fstWriterGetFlushContextPending(fstWriterContext *ctx);
|
||||
void fstWriterSetAttrBegin(fstWriterContext *ctx,
|
||||
enum fstAttrType attrtype,
|
||||
int subtype,
|
||||
const char *attrname,
|
||||
uint64_t arg);
|
||||
void fstWriterSetAttrEnd(void *ctx);
|
||||
void fstWriterSetComment(void *ctx, const char *comm);
|
||||
void fstWriterSetDate(void *ctx, const char *dat);
|
||||
void fstWriterSetDumpSizeLimit(void *ctx, uint64_t numbytes);
|
||||
void fstWriterSetEnvVar(void *ctx, const char *envvar);
|
||||
void fstWriterSetFileType(void *ctx, enum fstFileType filetype);
|
||||
void fstWriterSetPackType(void *ctx, enum fstWriterPackType typ);
|
||||
void fstWriterSetParallelMode(void *ctx, int enable);
|
||||
void fstWriterSetRepackOnClose(void *ctx, int enable); /* type = 0 (none), 1 (libz) */
|
||||
void fstWriterSetScope(void *ctx,
|
||||
void fstWriterSetAttrEnd(fstWriterContext *ctx);
|
||||
void fstWriterSetComment(fstWriterContext *ctx, const char *comm);
|
||||
void fstWriterSetDate(fstWriterContext *ctx, const char *dat);
|
||||
void fstWriterSetDumpSizeLimit(fstWriterContext *ctx, uint64_t numbytes);
|
||||
void fstWriterSetEnvVar(fstWriterContext *ctx, const char *envvar);
|
||||
void fstWriterSetFileType(fstWriterContext *ctx, enum fstFileType filetype);
|
||||
void fstWriterSetPackType(fstWriterContext *ctx, enum fstWriterPackType typ);
|
||||
void fstWriterSetParallelMode(fstWriterContext *ctx, int enable);
|
||||
void fstWriterSetRepackOnClose(fstWriterContext *ctx,
|
||||
int enable); /* type = 0 (none), 1 (libz) */
|
||||
void fstWriterSetScope(fstWriterContext *ctx,
|
||||
enum fstScopeType scopetype,
|
||||
const char *scopename,
|
||||
const char *scopecomp);
|
||||
void fstWriterSetSourceInstantiationStem(void *ctx,
|
||||
void fstWriterSetSourceInstantiationStem(fstWriterContext *ctx,
|
||||
const char *path,
|
||||
unsigned int line,
|
||||
unsigned int use_realpath);
|
||||
void fstWriterSetSourceStem(void *ctx,
|
||||
void fstWriterSetSourceStem(fstWriterContext *ctx,
|
||||
const char *path,
|
||||
unsigned int line,
|
||||
unsigned int use_realpath);
|
||||
void fstWriterSetTimescale(void *ctx, int ts);
|
||||
void fstWriterSetTimescaleFromString(void *ctx, const char *s);
|
||||
void fstWriterSetTimezero(void *ctx, int64_t tim);
|
||||
void fstWriterSetUpscope(void *ctx);
|
||||
void fstWriterSetValueList(void *ctx, const char *vl);
|
||||
void fstWriterSetVersion(void *ctx, const char *vers);
|
||||
void fstWriterSetTimescale(fstWriterContext *ctx, int ts);
|
||||
void fstWriterSetTimescaleFromString(fstWriterContext *ctx, const char *s);
|
||||
void fstWriterSetTimezero(fstWriterContext *ctx, int64_t tim);
|
||||
void fstWriterSetUpscope(fstWriterContext *ctx);
|
||||
void fstWriterSetValueList(fstWriterContext *ctx, const char *vl);
|
||||
void fstWriterSetVersion(fstWriterContext *ctx, const char *vers);
|
||||
|
||||
/*
|
||||
* reader functions
|
||||
*/
|
||||
void fstReaderClose(void *ctx);
|
||||
void fstReaderClrFacProcessMask(void *ctx, fstHandle facidx);
|
||||
void fstReaderClrFacProcessMaskAll(void *ctx);
|
||||
uint64_t fstReaderGetAliasCount(void *ctx);
|
||||
const char *fstReaderGetCurrentFlatScope(void *ctx);
|
||||
void *fstReaderGetCurrentScopeUserInfo(void *ctx);
|
||||
int fstReaderGetCurrentScopeLen(void *ctx);
|
||||
const char *fstReaderGetDateString(void *ctx);
|
||||
int fstReaderGetDoubleEndianMatchState(void *ctx);
|
||||
uint64_t fstReaderGetDumpActivityChangeTime(void *ctx, uint32_t idx);
|
||||
unsigned char fstReaderGetDumpActivityChangeValue(void *ctx, uint32_t idx);
|
||||
uint64_t fstReaderGetEndTime(void *ctx);
|
||||
int fstReaderGetFacProcessMask(void *ctx, fstHandle facidx);
|
||||
int fstReaderGetFileType(void *ctx);
|
||||
int fstReaderGetFseekFailed(void *ctx);
|
||||
fstHandle fstReaderGetMaxHandle(void *ctx);
|
||||
uint64_t fstReaderGetMemoryUsedByWriter(void *ctx);
|
||||
uint32_t fstReaderGetNumberDumpActivityChanges(void *ctx);
|
||||
uint64_t fstReaderGetScopeCount(void *ctx);
|
||||
uint64_t fstReaderGetStartTime(void *ctx);
|
||||
signed char fstReaderGetTimescale(void *ctx);
|
||||
int64_t fstReaderGetTimezero(void *ctx);
|
||||
uint64_t fstReaderGetValueChangeSectionCount(void *ctx);
|
||||
char *fstReaderGetValueFromHandleAtTime(void *ctx, uint64_t tim, fstHandle facidx, char *buf);
|
||||
uint64_t fstReaderGetVarCount(void *ctx);
|
||||
const char *fstReaderGetVersionString(void *ctx);
|
||||
struct fstHier *fstReaderIterateHier(void *ctx);
|
||||
int fstReaderIterateHierRewind(void *ctx);
|
||||
int fstReaderIterBlocks(void *ctx,
|
||||
|
||||
typedef struct fstReaderContext fstReaderContext;
|
||||
|
||||
void fstReaderClose(fstReaderContext *ctx);
|
||||
void fstReaderClrFacProcessMask(fstReaderContext *ctx, fstHandle facidx);
|
||||
void fstReaderClrFacProcessMaskAll(fstReaderContext *ctx);
|
||||
uint64_t fstReaderGetAliasCount(fstReaderContext *ctx);
|
||||
const char *fstReaderGetCurrentFlatScope(fstReaderContext *ctx);
|
||||
void *fstReaderGetCurrentScopeUserInfo(fstReaderContext *ctx);
|
||||
int fstReaderGetCurrentScopeLen(fstReaderContext *ctx);
|
||||
const char *fstReaderGetDateString(fstReaderContext *ctx);
|
||||
int fstReaderGetDoubleEndianMatchState(fstReaderContext *ctx);
|
||||
uint64_t fstReaderGetDumpActivityChangeTime(fstReaderContext *ctx, uint32_t idx);
|
||||
unsigned char fstReaderGetDumpActivityChangeValue(fstReaderContext *ctx, uint32_t idx);
|
||||
uint64_t fstReaderGetEndTime(fstReaderContext *ctx);
|
||||
int fstReaderGetFacProcessMask(fstReaderContext *ctx, fstHandle facidx);
|
||||
int fstReaderGetFileType(fstReaderContext *ctx);
|
||||
int fstReaderGetFseekFailed(fstReaderContext *ctx);
|
||||
fstHandle fstReaderGetMaxHandle(fstReaderContext *ctx);
|
||||
uint64_t fstReaderGetMemoryUsedByWriter(fstReaderContext *ctx);
|
||||
uint32_t fstReaderGetNumberDumpActivityChanges(fstReaderContext *ctx);
|
||||
uint64_t fstReaderGetScopeCount(fstReaderContext *ctx);
|
||||
uint64_t fstReaderGetStartTime(fstReaderContext *ctx);
|
||||
signed char fstReaderGetTimescale(fstReaderContext *ctx);
|
||||
int64_t fstReaderGetTimezero(fstReaderContext *ctx);
|
||||
uint64_t fstReaderGetValueChangeSectionCount(fstReaderContext *ctx);
|
||||
char *fstReaderGetValueFromHandleAtTime(fstReaderContext *ctx,
|
||||
uint64_t tim,
|
||||
fstHandle facidx,
|
||||
char *buf);
|
||||
uint64_t fstReaderGetVarCount(fstReaderContext *ctx);
|
||||
const char *fstReaderGetVersionString(fstReaderContext *ctx);
|
||||
struct fstHier *fstReaderIterateHier(fstReaderContext *ctx);
|
||||
int fstReaderIterateHierRewind(fstReaderContext *ctx);
|
||||
int fstReaderIterBlocks(fstReaderContext *ctx,
|
||||
void (*value_change_callback)(void *user_callback_data_pointer,
|
||||
uint64_t time,
|
||||
fstHandle facidx,
|
||||
const unsigned char *value),
|
||||
uint64_t time,
|
||||
fstHandle facidx,
|
||||
const unsigned char *value),
|
||||
void *user_callback_data_pointer,
|
||||
FILE *vcdhandle);
|
||||
int fstReaderIterBlocks2(void *ctx,
|
||||
void (*value_change_callback)(void *user_callback_data_pointer,
|
||||
uint64_t time,
|
||||
fstHandle facidx,
|
||||
const unsigned char *value),
|
||||
void (*value_change_callback_varlen)(void *user_callback_data_pointer,
|
||||
uint64_t time,
|
||||
fstHandle facidx,
|
||||
const unsigned char *value,
|
||||
uint32_t len),
|
||||
void *user_callback_data_pointer,
|
||||
FILE *vcdhandle);
|
||||
void fstReaderIterBlocksSetNativeDoublesOnCallback(void *ctx, int enable);
|
||||
void *fstReaderOpen(const char *nam);
|
||||
void *fstReaderOpenForUtilitiesOnly(void);
|
||||
const char *fstReaderPopScope(void *ctx);
|
||||
int fstReaderProcessHier(void *ctx, FILE *vcdhandle);
|
||||
const char *fstReaderPushScope(void *ctx, const char *nam, void *user_info);
|
||||
void fstReaderResetScope(void *ctx);
|
||||
void fstReaderSetFacProcessMask(void *ctx, fstHandle facidx);
|
||||
void fstReaderSetFacProcessMaskAll(void *ctx);
|
||||
void fstReaderSetLimitTimeRange(void *ctx, uint64_t start_time, uint64_t end_time);
|
||||
void fstReaderSetUnlimitedTimeRange(void *ctx);
|
||||
void fstReaderSetVcdExtensions(void *ctx, int enable);
|
||||
int fstReaderIterBlocks2(fstReaderContext *ctx,
|
||||
void (*value_change_callback)(void *user_callback_data_pointer,
|
||||
uint64_t time,
|
||||
fstHandle facidx,
|
||||
const unsigned char *value),
|
||||
void (*value_change_callback_varlen)(void *user_callback_data_pointer,
|
||||
uint64_t time,
|
||||
fstHandle facidx,
|
||||
const unsigned char *value,
|
||||
uint32_t len),
|
||||
void *user_callback_data_pointer,
|
||||
FILE *vcdhandle);
|
||||
void fstReaderIterBlocksSetNativeDoublesOnCallback(fstReaderContext *ctx, int enable);
|
||||
fstReaderContext *fstReaderOpen(const char *nam);
|
||||
fstReaderContext *fstReaderOpenForUtilitiesOnly(void);
|
||||
const char *fstReaderPopScope(fstReaderContext *ctx);
|
||||
int fstReaderProcessHier(fstReaderContext *ctx, FILE *vcdhandle);
|
||||
const char *fstReaderPushScope(fstReaderContext *ctx, const char *nam, void *user_info);
|
||||
void fstReaderResetScope(fstReaderContext *ctx);
|
||||
void fstReaderSetFacProcessMask(fstReaderContext *ctx, fstHandle facidx);
|
||||
void fstReaderSetFacProcessMaskAll(fstReaderContext *ctx);
|
||||
void fstReaderSetLimitTimeRange(fstReaderContext *ctx, uint64_t start_time, uint64_t end_time);
|
||||
void fstReaderSetUnlimitedTimeRange(fstReaderContext *ctx);
|
||||
void fstReaderSetVcdExtensions(fstReaderContext *ctx, int enable);
|
||||
|
||||
/*
|
||||
* utility functions
|
||||
|
|
|
|||
|
|
@ -577,14 +577,14 @@ WDataOutP VL_POW_WWW(int obits, int, int rbits, WDataOutP owp, const WDataInP lw
|
|||
const int owords = VL_WORDS_I(obits);
|
||||
VL_DEBUG_IFDEF(assert(owords <= VL_MULS_MAX_WORDS););
|
||||
owp[0] = 1;
|
||||
for (int i = 1; i < VL_WORDS_I(obits); i++) owp[i] = 0;
|
||||
for (int i = 1; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
|
||||
// cppcheck-has-bug-suppress variableScope
|
||||
VlWide<VL_MULS_MAX_WORDS> powstore; // Fixed size, as MSVC++ doesn't allow [words] here
|
||||
VlWide<VL_MULS_MAX_WORDS> lastpowstore; // Fixed size, as MSVC++ doesn't allow [words] here
|
||||
VlWide<VL_MULS_MAX_WORDS> lastoutstore; // Fixed size, as MSVC++ doesn't allow [words] here
|
||||
// cppcheck-has-bug-suppress variableScope
|
||||
VL_ASSIGN_W(obits, powstore, lwp);
|
||||
for (int bit = 0; bit < rbits; bit++) {
|
||||
for (int bit = 0; bit < rbits; ++bit) {
|
||||
if (bit > 0) { // power = power*power
|
||||
VL_ASSIGN_W(obits, lastpowstore, powstore);
|
||||
VL_MUL_W(owords, powstore, lastpowstore, lastpowstore);
|
||||
|
|
@ -919,6 +919,7 @@ void _vl_vsformat(std::string& output, const std::string& format, va_list ap) VL
|
|||
}
|
||||
case 'p': { // 'x' but parameter is string
|
||||
const int lbits = va_arg(ap, int);
|
||||
(void)lbits;
|
||||
const std::string* const cstr = va_arg(ap, const std::string*);
|
||||
std::ostringstream oss;
|
||||
for (unsigned char c : *cstr) oss << std::hex << static_cast<int>(c);
|
||||
|
|
@ -1249,9 +1250,9 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
|
|||
bool inPct = false;
|
||||
bool inIgnore = false;
|
||||
std::string::const_iterator pos = format.cbegin();
|
||||
for (; pos != format.cend() && !_vl_vsss_eof(fp, floc); ++pos) {
|
||||
// VL_DBG_MSGF("_vlscan fmt='"<<pos[0]<<"' floc="<<floc<<" file='"<<_vl_vsss_peek(fp, floc,
|
||||
// fromp, fstr)<<"'\n");
|
||||
for (; pos != format.cend(); ++pos) {
|
||||
// VL_DBG_MSGF("_vlscan fmt='%c' floc=%d file='%c'\n", pos[0], floc,
|
||||
// _vl_vsss_peek(fp, floc, fromp, fstr));
|
||||
if (!inPct && pos[0] == '%') {
|
||||
inPct = true;
|
||||
inIgnore = false;
|
||||
|
|
@ -1435,7 +1436,12 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
|
|||
} // switch
|
||||
}
|
||||
}
|
||||
// Processed all arguments
|
||||
return got;
|
||||
|
||||
done:
|
||||
// Scan stopped early, return parsed or EOF
|
||||
if (_vl_vsss_eof(fp, floc)) return -1;
|
||||
return got;
|
||||
}
|
||||
|
||||
|
|
@ -1764,7 +1770,7 @@ std::string VL_STACKTRACE_N() VL_MT_SAFE {
|
|||
if (!strings) return "Unable to backtrace\n";
|
||||
|
||||
std::string result = "Backtrace:\n";
|
||||
for (int j = 0; j < nptrs; j++) result += std::string{strings[j]} + "\n"s;
|
||||
for (int j = 0; j < nptrs; ++j) result += std::string{strings[j]} + "\n"s;
|
||||
free(strings);
|
||||
return result;
|
||||
}
|
||||
|
|
@ -2036,7 +2042,7 @@ static const char* formatBinary(int nBits, uint32_t bits) {
|
|||
assert((nBits >= 1) && (nBits <= 32));
|
||||
|
||||
static thread_local char t_buf[64];
|
||||
for (int i = 0; i < nBits; i++) {
|
||||
for (int i = 0; i < nBits; ++i) {
|
||||
const bool isOne = bits & (1 << (nBits - 1 - i));
|
||||
t_buf[i] = (isOne ? '1' : '0');
|
||||
}
|
||||
|
|
@ -3032,7 +3038,7 @@ void VerilatedContext::trace(VerilatedTraceBaseC* tfp, int levels, int options)
|
|||
if (m_ns.m_traceBaseModelCbs.empty())
|
||||
VL_FATAL_MT("", 0, "",
|
||||
"Testbench C call to 'VerilatedContext::trace()' requires model(s) Verilated"
|
||||
" with --trace or --trace-vcd option");
|
||||
" with --trace-fst or --trace-vcd option");
|
||||
for (auto& cbr : m_ns.m_traceBaseModelCbs) cbr(tfp, levels, options);
|
||||
}
|
||||
void VerilatedContext::traceBaseModelCbAdd(traceBaseModelCb_t cb) VL_MT_SAFE {
|
||||
|
|
@ -3470,7 +3476,7 @@ void VerilatedHierarchy::remove(VerilatedScope* fromp, VerilatedScope* top) {
|
|||
void VerilatedAssertOneThread::fatal_different() VL_MT_SAFE {
|
||||
VL_FATAL_MT(__FILE__, __LINE__, "",
|
||||
"Routine called that is single threaded, but called from"
|
||||
" a different thread then the expected constructing thread");
|
||||
" a different thread than the expected constructing thread");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -312,7 +312,7 @@ public:
|
|||
const char* fnstartp = m_insertFilenamep;
|
||||
while (const char* foundp = std::strchr(fnstartp, '/')) fnstartp = foundp + 1;
|
||||
const char* fnendp = fnstartp;
|
||||
for (; *fnendp && *fnendp != '.'; fnendp++) {}
|
||||
for (; *fnendp && *fnendp != '.'; ++fnendp) {}
|
||||
const size_t page_len = fnendp - fnstartp;
|
||||
const std::string page_default = "sp_user/" + std::string{fnstartp, page_len};
|
||||
ckeyps[2] = "page";
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@ IData VL_DIST_ERLANG(IData& seedr, IData uk, IData umean) VL_MT_SAFE {
|
|||
return 0;
|
||||
}
|
||||
double x = 1.0;
|
||||
for (int32_t i = 1; i <= k; i++) x = x * _vl_dbase_uniform(seedr, 0, 1);
|
||||
for (int32_t i = 1; i <= k; ++i) x = x * _vl_dbase_uniform(seedr, 0, 1);
|
||||
const double a = static_cast<double>(mean);
|
||||
const double b = static_cast<double>(k);
|
||||
double r = -a * log(x) / b;
|
||||
|
|
|
|||
|
|
@ -34,28 +34,6 @@ thread_local VlExecutionProfiler::ExecutionTrace VlExecutionProfiler::t_trace;
|
|||
|
||||
constexpr const char* const VlExecutionRecord::s_ascii[];
|
||||
|
||||
//=============================================================================
|
||||
// VlPgoProfiler implementation
|
||||
|
||||
uint16_t VlExecutionRecord::getcpu() {
|
||||
#if defined(__linux)
|
||||
return sched_getcpu(); // TODO: this is a system call. Not exactly cheap.
|
||||
#elif defined(__APPLE__) && !defined(__arm64__)
|
||||
uint32_t info[4];
|
||||
__cpuid_count(1, 0, info[0], info[1], info[2], info[3]);
|
||||
// info[1] is EBX, bits 24-31 are APIC ID
|
||||
if ((info[3] & (1 << 9)) == 0) {
|
||||
return -1; // no APIC on chip
|
||||
} else {
|
||||
return (unsigned)info[1] >> 24;
|
||||
}
|
||||
#elif defined(_WIN32)
|
||||
return GetCurrentProcessorNumber();
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
// VlExecutionProfiler implementation
|
||||
|
||||
|
|
@ -161,11 +139,17 @@ void VlExecutionProfiler::dump(const char* filenamep, uint64_t tickEnd)
|
|||
|
||||
// TODO Perhaps merge with verilated_coverage output format, so can
|
||||
// have a common merging and reporting tool, etc.
|
||||
fprintf(fp, "VLPROFVERSION 2.1 # Verilator execution profile version 2.1\n");
|
||||
fprintf(fp, "VLPROFVERSION 2.2 # Verilator execution profile version 2.2\n");
|
||||
fprintf(fp, "VLPROF arg +verilator+prof+exec+start+%" PRIu64 "\n",
|
||||
Verilated::threadContextp()->profExecStart());
|
||||
fprintf(fp, "VLPROF arg +verilator+prof+exec+window+%u\n",
|
||||
Verilated::threadContextp()->profExecWindow());
|
||||
std::string numa = "no threads";
|
||||
if (VlThreadPool* const threadPoolp
|
||||
= static_cast<VlThreadPool*>(Verilated::threadContextp()->threadPoolp())) {
|
||||
numa = threadPoolp->numaStatus();
|
||||
}
|
||||
fprintf(fp, "VLPROF info numa %s\n", numa.c_str());
|
||||
// Note that VerilatedContext will by default create as many threads as there are hardware
|
||||
// processors, but not all of them might be utilized. Report the actual number that has trace
|
||||
// entries to avoid over-counting.
|
||||
|
|
@ -206,13 +190,24 @@ void VlExecutionProfiler::dump(const char* filenamep, uint64_t tickEnd)
|
|||
break;
|
||||
case VlExecutionRecord::Type::MTASK_BEGIN: {
|
||||
const auto& payload = er.m_payload.mtaskBegin;
|
||||
fprintf(fp, " id %u predictStart %u cpu %u\n", payload.m_id,
|
||||
payload.m_predictStart, payload.m_cpu);
|
||||
if (payload.m_hierBlock[0] != '\0') {
|
||||
fprintf(fp, " id %u predictStart %u cpu %u hierBlock %s\n", payload.m_id,
|
||||
payload.m_predictStart, payload.m_cpu, payload.m_hierBlock);
|
||||
} else {
|
||||
fprintf(fp, " id %u predictStart %u cpu %u\n", payload.m_id,
|
||||
payload.m_predictStart, payload.m_cpu);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case VlExecutionRecord::Type::MTASK_END: {
|
||||
const auto& payload = er.m_payload.mtaskEnd;
|
||||
fprintf(fp, " id %u predictCost %u\n", payload.m_id, payload.m_predictCost);
|
||||
fprintf(fp, " predictCost %u\n", payload.m_predictCost);
|
||||
break;
|
||||
}
|
||||
case VlExecutionRecord::Type::THREAD_SCHEDULE_WAIT_BEGIN:
|
||||
case VlExecutionRecord::Type::THREAD_SCHEDULE_WAIT_END: {
|
||||
const auto& payload = er.m_payload.threadScheduleWait;
|
||||
fprintf(fp, " cpu %u\n", payload.m_cpu);
|
||||
break;
|
||||
}
|
||||
case VlExecutionRecord::Type::SECTION_PUSH: {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ public:
|
|||
if (m_pidStatus) {
|
||||
std::stringstream msg;
|
||||
msg << "Subprocess command `" << m_cmd[0];
|
||||
for (const char* const* arg = m_cmd + 1; *arg; arg++) msg << ' ' << *arg;
|
||||
for (const char* const* arg = m_cmd + 1; *arg; ++arg) msg << ' ' << *arg;
|
||||
msg << "' failed: ";
|
||||
if (WIFSIGNALED(m_pidStatus))
|
||||
msg << strsignal(WTERMSIG(m_pidStatus))
|
||||
|
|
@ -221,7 +221,7 @@ static Process& getSolver() {
|
|||
static std::vector<const char*> s_argv;
|
||||
static std::string s_program = Verilated::threadContextp()->solverProgram();
|
||||
s_argv.emplace_back(&s_program[0]);
|
||||
for (char* arg = &s_program[0]; *arg; arg++) {
|
||||
for (char* arg = &s_program[0]; *arg; ++arg) {
|
||||
if (*arg == ' ') {
|
||||
*arg = '\0';
|
||||
s_argv.emplace_back(arg + 1);
|
||||
|
|
@ -242,7 +242,7 @@ static Process& getSolver() {
|
|||
msg << "Unable to communicate with SAT solver, please check its installation or specify a "
|
||||
"different one in VERILATOR_SOLVER environment variable.\n";
|
||||
msg << " ... Tried: $";
|
||||
for (const char* const* arg = cmd; *arg; arg++) msg << ' ' << *arg;
|
||||
for (const char* const* arg = cmd; *arg; ++arg) msg << ' ' << *arg;
|
||||
msg << '\n';
|
||||
const std::string str = msg.str();
|
||||
VL_WARN_MT("", 0, "randomize", str.c_str());
|
||||
|
|
@ -294,7 +294,7 @@ void VlRandomVar::emitType(std::ostream& s) const { s << "(_ BitVec " << width()
|
|||
int VlRandomVar::totalWidth() const { return m_width; }
|
||||
static bool parseSMTNum(int obits, WDataOutP owp, const std::string& val) {
|
||||
int i;
|
||||
for (i = 0; val[i] && val[i] != '#'; i++) {}
|
||||
for (i = 0; val[i] && val[i] != '#'; ++i) {}
|
||||
if (val[i++] != '#') return false;
|
||||
switch (val[i++]) {
|
||||
case 'b': _vl_vsss_based(owp, obits, 1, &val[i], 0, val.size() - i); break;
|
||||
|
|
@ -345,7 +345,7 @@ void VlRandomizer::randomConstraint(std::ostream& os, VlRNG& rngr, int bits) {
|
|||
os << "(= #b";
|
||||
for (int i = bits - 1; i >= 0; i--) os << (VL_BITISSET_I(hash, i) ? '1' : '0');
|
||||
if (bits > 1) os << " (concat";
|
||||
for (int i = 0; i < bits; i++) {
|
||||
for (int i = 0; i < bits; ++i) {
|
||||
IData varBitsLeft = varBits;
|
||||
IData varBitsWant = (varBits + 1) / 2;
|
||||
if (varBits > 2) os << " (bvxor";
|
||||
|
|
@ -393,7 +393,7 @@ bool VlRandomizer::next(VlRNG& rngr) {
|
|||
f << "(reset)\n";
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < _VL_SOLVER_HASH_LEN_TOTAL && sat; i++) {
|
||||
for (int i = 0; i < _VL_SOLVER_HASH_LEN_TOTAL && sat; ++i) {
|
||||
f << "(assert ";
|
||||
randomConstraint(f, rngr, _VL_SOLVER_HASH_LEN);
|
||||
f << ")\n";
|
||||
|
|
|
|||
|
|
@ -143,7 +143,7 @@ public:
|
|||
}
|
||||
void emitGetValue(std::ostream& s) const override {
|
||||
const int elementCounts = countMatchingElements(*m_arrVarsRefp, name());
|
||||
for (int i = 0; i < elementCounts; i++) {
|
||||
for (int i = 0; i < elementCounts; ++i) {
|
||||
const std::string indexed_name = name() + std::to_string(i);
|
||||
const auto it = m_arrVarsRefp->find(indexed_name);
|
||||
if (it != m_arrVarsRefp->end()) {
|
||||
|
|
@ -200,8 +200,8 @@ class VlRandomizer final {
|
|||
std::map<std::string, std::shared_ptr<const VlRandomVar>> m_vars; // Solver-dependent
|
||||
// variables
|
||||
ArrayInfoMap m_arr_vars; // Tracks each element in array structures for iteration
|
||||
std::map<size_t, std::string> seen_values; // Record String Index to avoid conflicts
|
||||
const VlQueue<CData>* m_randmode; // rand_mode state;
|
||||
int m_index = 0; // Internal counter for key generation
|
||||
|
||||
// PRIVATE METHODS
|
||||
void randomConstraint(std::ostream& os, VlRNG& rngr, int bits);
|
||||
|
|
@ -216,6 +216,11 @@ public:
|
|||
// Finds the next solution satisfying the constraints
|
||||
bool next(VlRNG& rngr);
|
||||
|
||||
// -----------------------------------------------
|
||||
// --- Process the key for associative array ---
|
||||
// -----------------------------------------------
|
||||
|
||||
// process_key: Handle integral keys (<= 32-bit)
|
||||
template <typename T_Key>
|
||||
typename std::enable_if<std::is_integral<T_Key>::value && (sizeof(T_Key) <= 4)>::type
|
||||
process_key(const T_Key& key, std::string& indexed_name, std::vector<size_t>& integral_index,
|
||||
|
|
@ -225,6 +230,8 @@ public:
|
|||
= base_name + "[" + std::to_string(integral_index[integral_index.size() - 1]) + "]";
|
||||
idx_width = sizeof(T_Key) * 8;
|
||||
}
|
||||
|
||||
// process_key: Handle integral keys (> 32-bit), split into 2 x 32-bit segments
|
||||
template <typename T_Key>
|
||||
typename std::enable_if<std::is_integral<T_Key>::value && (sizeof(T_Key) > 4)>::type
|
||||
process_key(const T_Key& key, std::string& indexed_name, std::vector<size_t>& integral_index,
|
||||
|
|
@ -244,6 +251,8 @@ public:
|
|||
|
||||
idx_width = sizeof(T_Key) * 8;
|
||||
}
|
||||
|
||||
// process_key: Handle wide keys (VlWide-like), segment is 32-bit per element
|
||||
template <typename T_Key>
|
||||
typename std::enable_if<VlIsVlWide<T_Key>::value>::type
|
||||
process_key(const T_Key& key, std::string& indexed_name, std::vector<size_t>& integral_index,
|
||||
|
|
@ -261,6 +270,8 @@ public:
|
|||
indexed_name = base_name + "[" + index_string + "]";
|
||||
idx_width = key.size() * 32;
|
||||
}
|
||||
|
||||
// process_key: Handle string key, encoded as 128-bit hex
|
||||
template <typename T_Key>
|
||||
typename std::enable_if<std::is_same<T_Key, std::string>::value>::type
|
||||
process_key(const T_Key& key, std::string& indexed_name, std::vector<size_t>& integral_index,
|
||||
|
|
@ -289,6 +300,8 @@ public:
|
|||
|
||||
idx_width = 128;
|
||||
}
|
||||
|
||||
// process_key: Unsupported key type fallback
|
||||
template <typename T_Key>
|
||||
typename std::enable_if<!std::is_integral<T_Key>::value
|
||||
&& !std::is_same<T_Key, std::string>::value
|
||||
|
|
@ -300,8 +313,13 @@ public:
|
|||
"supported currently.");
|
||||
}
|
||||
|
||||
// -----------------------------------------
|
||||
// --- write_var to register variables ---
|
||||
// -----------------------------------------
|
||||
|
||||
// Register scalar variable (non-struct, basic type)
|
||||
template <typename T>
|
||||
typename std::enable_if<!VlIsCustomStruct<T>::value, void>::type
|
||||
typename std::enable_if<!VlContainsCustomStruct<T>::value, void>::type
|
||||
write_var(T& var, int width, const char* name, int dimension,
|
||||
std::uint32_t randmodeIdx = std::numeric_limits<std::uint32_t>::max()) {
|
||||
if (m_vars.find(name) != m_vars.end()) return;
|
||||
|
|
@ -309,49 +327,8 @@ public:
|
|||
m_vars[name]
|
||||
= std::make_shared<const VlRandomVar>(name, width, &var, dimension, randmodeIdx);
|
||||
}
|
||||
template <typename T>
|
||||
void write_var(VlQueue<T>& var, int width, const char* name, int dimension,
|
||||
std::uint32_t randmodeIdx = std::numeric_limits<std::uint32_t>::max()) {
|
||||
if (m_vars.find(name) != m_vars.end()) return;
|
||||
m_vars[name] = std::make_shared<const VlRandomArrayVarTemplate<VlQueue<T>>>(
|
||||
name, width, &var, dimension, randmodeIdx);
|
||||
if (dimension > 0) {
|
||||
idx = 0;
|
||||
record_arr_table(var, name, dimension, {}, {});
|
||||
}
|
||||
}
|
||||
template <typename T, std::size_t N_Depth>
|
||||
void write_var(VlUnpacked<T, N_Depth>& var, int width, const char* name, int dimension,
|
||||
std::uint32_t randmodeIdx = std::numeric_limits<std::uint32_t>::max()) {
|
||||
if (m_vars.find(name) != m_vars.end()) return;
|
||||
m_vars[name] = std::make_shared<const VlRandomArrayVarTemplate<VlUnpacked<T, N_Depth>>>(
|
||||
name, width, &var, dimension, randmodeIdx);
|
||||
if (dimension > 0) {
|
||||
idx = 0;
|
||||
record_arr_table(var, name, dimension, {}, {});
|
||||
}
|
||||
}
|
||||
template <typename T_Key, typename T_Value>
|
||||
void write_var(VlAssocArray<T_Key, T_Value>& var, int width, const char* name, int dimension,
|
||||
std::uint32_t randmodeIdx = std::numeric_limits<std::uint32_t>::max()) {
|
||||
if (m_vars.find(name) != m_vars.end()) return;
|
||||
m_vars[name]
|
||||
= std::make_shared<const VlRandomArrayVarTemplate<VlAssocArray<T_Key, T_Value>>>(
|
||||
name, width, &var, dimension, randmodeIdx);
|
||||
if (dimension > 0) {
|
||||
idx = 0;
|
||||
record_arr_table(var, name, dimension, {}, {});
|
||||
}
|
||||
}
|
||||
template <typename T, std::size_t... I>
|
||||
void modifyMembers(T& obj, std::index_sequence<I...>, std::string baseName) {
|
||||
// Use the indices to access each member via std::get
|
||||
(void)std::initializer_list<int>{
|
||||
(write_var(std::get<I>(obj.getMembers(obj)), obj.memberWidth()[I],
|
||||
(baseName + "." + obj.memberNames()[I]).c_str(), obj.memberDimension()[I]),
|
||||
0)...};
|
||||
}
|
||||
|
||||
// Register user-defined struct variable by recursively writing members
|
||||
template <typename T>
|
||||
typename std::enable_if<VlIsCustomStruct<T>::value, void>::type
|
||||
write_var(T& var, int width, const char* name, int dimension,
|
||||
|
|
@ -359,39 +336,87 @@ public:
|
|||
modifyMembers(var, var.memberIndices(), name);
|
||||
}
|
||||
|
||||
int idx;
|
||||
std::string generateKey(const std::string& name, int idx) {
|
||||
if (!name.empty() && name[0] == '\\') {
|
||||
const size_t space_pos = name.find(' ');
|
||||
return (space_pos != std::string::npos ? name.substr(0, space_pos) : name)
|
||||
+ std::to_string(idx);
|
||||
// Register queue of non-struct types
|
||||
template <typename T>
|
||||
typename std::enable_if<!VlContainsCustomStruct<T>::value, void>::type
|
||||
write_var(VlQueue<T>& var, int width, const char* name, int dimension,
|
||||
std::uint32_t randmodeIdx = std::numeric_limits<std::uint32_t>::max()) {
|
||||
if (m_vars.find(name) != m_vars.end()) return;
|
||||
m_vars[name] = std::make_shared<const VlRandomArrayVarTemplate<VlQueue<T>>>(
|
||||
name, width, &var, dimension, randmodeIdx);
|
||||
if (dimension > 0) {
|
||||
m_index = 0;
|
||||
record_arr_table(var, name, dimension, {}, {});
|
||||
}
|
||||
const size_t bracket_pos = name.find('[');
|
||||
return (bracket_pos != std::string::npos ? name.substr(0, bracket_pos) : name)
|
||||
+ std::to_string(idx);
|
||||
}
|
||||
|
||||
// Register queue of structs
|
||||
template <typename T>
|
||||
typename std::enable_if<VlContainsCustomStruct<T>::value, void>::type
|
||||
write_var(VlQueue<T>& var, int width, const char* name, int dimension,
|
||||
std::uint32_t randmodeIdx = std::numeric_limits<std::uint32_t>::max()) {
|
||||
if (dimension > 0) record_struct_arr(var, name, dimension, {}, {});
|
||||
}
|
||||
|
||||
// Register unpacked array of non-struct types
|
||||
template <typename T, std::size_t N_Depth>
|
||||
typename std::enable_if<!VlContainsCustomStruct<T>::value, void>::type
|
||||
write_var(VlUnpacked<T, N_Depth>& var, int width, const char* name, int dimension,
|
||||
std::uint32_t randmodeIdx = std::numeric_limits<std::uint32_t>::max()) {
|
||||
if (m_vars.find(name) != m_vars.end()) return;
|
||||
m_vars[name] = std::make_shared<const VlRandomArrayVarTemplate<VlUnpacked<T, N_Depth>>>(
|
||||
name, width, &var, dimension, randmodeIdx);
|
||||
if (dimension > 0) {
|
||||
m_index = 0;
|
||||
record_arr_table(var, name, dimension, {}, {});
|
||||
}
|
||||
}
|
||||
|
||||
// Register unpacked array of structs
|
||||
template <typename T, std::size_t N_Depth>
|
||||
typename std::enable_if<VlContainsCustomStruct<T>::value, void>::type
|
||||
write_var(VlUnpacked<T, N_Depth>& var, int width, const char* name, int dimension,
|
||||
std::uint32_t randmodeIdx = std::numeric_limits<std::uint32_t>::max()) {
|
||||
if (dimension > 0) record_struct_arr(var, name, dimension, {}, {});
|
||||
}
|
||||
|
||||
// Register associative array of non-struct types
|
||||
template <typename T_Key, typename T_Value>
|
||||
typename std::enable_if<!VlContainsCustomStruct<T_Value>::value, void>::type
|
||||
write_var(VlAssocArray<T_Key, T_Value>& var, int width, const char* name, int dimension,
|
||||
std::uint32_t randmodeIdx = std::numeric_limits<std::uint32_t>::max()) {
|
||||
if (m_vars.find(name) != m_vars.end()) return;
|
||||
m_vars[name]
|
||||
= std::make_shared<const VlRandomArrayVarTemplate<VlAssocArray<T_Key, T_Value>>>(
|
||||
name, width, &var, dimension, randmodeIdx);
|
||||
if (dimension > 0) {
|
||||
m_index = 0;
|
||||
record_arr_table(var, name, dimension, {}, {});
|
||||
}
|
||||
}
|
||||
|
||||
// Register associative array of structs
|
||||
template <typename T_Key, typename T_Value>
|
||||
typename std::enable_if<VlContainsCustomStruct<T_Value>::value, void>::type
|
||||
write_var(VlAssocArray<T_Key, T_Value>& var, int width, const char* name, int dimension,
|
||||
std::uint32_t randmodeIdx = std::numeric_limits<std::uint32_t>::max()) {
|
||||
if (dimension > 0) record_struct_arr(var, name, dimension, {}, {});
|
||||
}
|
||||
// ----------------------------------------
|
||||
// --- Record Arrays: flat and struct ---
|
||||
// ----------------------------------------
|
||||
|
||||
// Record a flat (non-class) element into the array variable table
|
||||
template <typename T>
|
||||
typename std::enable_if<!std::is_class<T>::value, void>::type
|
||||
record_arr_table(T& var, const std::string name, int dimension, std::vector<IData> indices,
|
||||
std::vector<size_t> idxWidths) {
|
||||
const std::string key = generateKey(name, idx);
|
||||
m_arr_vars[key] = std::make_shared<ArrayInfo>(name, &var, idx, indices, idxWidths);
|
||||
++idx;
|
||||
}
|
||||
template <typename T>
|
||||
void record_arr_table(VlQueue<T>& var, const std::string name, int dimension,
|
||||
std::vector<IData> indices, std::vector<size_t> idxWidths) {
|
||||
if ((dimension > 0) && (var.size() != 0)) {
|
||||
idxWidths.push_back(32);
|
||||
for (size_t i = 0; i < var.size(); ++i) {
|
||||
const std::string indexed_name = name + "[" + std::to_string(i) + "]";
|
||||
indices.push_back(i);
|
||||
record_arr_table(var.atWrite(i), indexed_name, dimension - 1, indices, idxWidths);
|
||||
indices.pop_back();
|
||||
}
|
||||
}
|
||||
const std::string key = generateKey(name, m_index);
|
||||
m_arr_vars[key] = std::make_shared<ArrayInfo>(name, &var, m_index, indices, idxWidths);
|
||||
++m_index;
|
||||
}
|
||||
|
||||
// Recursively record all elements in an unpacked array
|
||||
template <typename T, std::size_t N_Depth>
|
||||
void record_arr_table(VlUnpacked<T, N_Depth>& var, const std::string name, int dimension,
|
||||
std::vector<IData> indices, std::vector<size_t> idxWidths) {
|
||||
|
|
@ -406,6 +431,23 @@ public:
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Recursively record all elements in a queue
|
||||
template <typename T>
|
||||
void record_arr_table(VlQueue<T>& var, const std::string name, int dimension,
|
||||
std::vector<IData> indices, std::vector<size_t> idxWidths) {
|
||||
if ((dimension > 0) && (var.size() != 0)) {
|
||||
idxWidths.push_back(32);
|
||||
for (size_t i = 0; i < var.size(); ++i) {
|
||||
const std::string indexed_name = name + "[" + std::to_string(i) + "]";
|
||||
indices.push_back(i);
|
||||
record_arr_table(var.atWrite(i), indexed_name, dimension - 1, indices, idxWidths);
|
||||
indices.pop_back();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Recursively record all elements in an associative array
|
||||
template <typename T_Key, typename T_Value>
|
||||
void record_arr_table(VlAssocArray<T_Key, T_Value>& var, const std::string name, int dimension,
|
||||
std::vector<IData> indices, std::vector<size_t> idxWidths) {
|
||||
|
|
@ -433,6 +475,102 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
// Register a single structArray element via write_var
|
||||
template <typename T>
|
||||
typename std::enable_if<VlContainsCustomStruct<T>::value, void>::type
|
||||
record_struct_arr(T& var, const std::string name, int dimension, std::vector<IData> indices,
|
||||
std::vector<size_t> idxWidths) {
|
||||
std::ostringstream oss;
|
||||
for (size_t i = 0; i < indices.size(); ++i) {
|
||||
oss << std::hex << std::setw(int(idxWidths[i] / 4)) << std::setfill('0')
|
||||
<< static_cast<int>(indices[i]);
|
||||
if (i < indices.size() - 1) oss << ".";
|
||||
}
|
||||
write_var(var, 1ULL,
|
||||
oss.str().length() > 0 ? (name + "." + oss.str()).c_str() : name.c_str(), 1ULL);
|
||||
}
|
||||
|
||||
// Recursively process VlUnpacked of structs
|
||||
template <typename T, std::size_t N_Depth>
|
||||
void record_struct_arr(VlUnpacked<T, N_Depth>& var, const std::string name, int dimension,
|
||||
std::vector<IData> indices, std::vector<size_t> idxWidths) {
|
||||
if (dimension > 0 && N_Depth != 0) {
|
||||
constexpr size_t idx_width = 1 << VL_CLOG2_CE_Q(VL_CLOG2_CE_Q(N_Depth) + 1);
|
||||
idxWidths.push_back(idx_width);
|
||||
for (size_t i = 0; i < N_Depth; ++i) {
|
||||
indices.push_back(i);
|
||||
record_struct_arr(var.operator[](i), name, dimension - 1, indices, idxWidths);
|
||||
indices.pop_back();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Recursively process VlQueue of structs
|
||||
template <typename T>
|
||||
void record_struct_arr(VlQueue<T>& var, const std::string name, int dimension,
|
||||
std::vector<IData> indices, std::vector<size_t> idxWidths) {
|
||||
if ((dimension > 0) && (var.size() != 0)) {
|
||||
idxWidths.push_back(32);
|
||||
for (size_t i = 0; i < var.size(); ++i) {
|
||||
indices.push_back(i);
|
||||
record_struct_arr(var.atWrite(i), name, dimension - 1, indices, idxWidths);
|
||||
indices.pop_back();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Recursively process associative arrays of structs
|
||||
template <typename T_Key, typename T_Value>
|
||||
void record_struct_arr(VlAssocArray<T_Key, T_Value>& var, const std::string name,
|
||||
int dimension, std::vector<IData> indices,
|
||||
std::vector<size_t> idxWidths) {
|
||||
if ((dimension > 0) && (!var.empty())) {
|
||||
for (auto it = var.begin(); it != var.end(); ++it) {
|
||||
const T_Key& key = it->first;
|
||||
const T_Value& value = it->second;
|
||||
|
||||
std::string indexed_name;
|
||||
std::vector<size_t> integral_index;
|
||||
size_t idx_width = 0;
|
||||
|
||||
process_key(key, indexed_name, integral_index, name, idx_width);
|
||||
std::ostringstream oss;
|
||||
for (int i = 0; i < integral_index.size(); ++i)
|
||||
oss << std::hex << static_cast<int>(integral_index[i]);
|
||||
|
||||
std::string result = oss.str();
|
||||
result.insert(result.begin(), int(idx_width / 4) - result.size(), '0');
|
||||
record_struct_arr(var.at(key), name + "." + result, dimension - 1, indices,
|
||||
idxWidths);
|
||||
}
|
||||
}
|
||||
}
|
||||
// --------------------------
|
||||
// --- Helper functions ---
|
||||
// --------------------------
|
||||
|
||||
// Helper: Register all members of a user-defined struct
|
||||
template <typename T, std::size_t... I>
|
||||
void modifyMembers(T& obj, std::index_sequence<I...>, std::string baseName) {
|
||||
// Use the indices to access each member via std::get
|
||||
(void)std::initializer_list<int>{
|
||||
(write_var(std::get<I>(obj.getMembers(obj)), obj.memberWidth()[I],
|
||||
(baseName + "." + obj.memberNames()[I]).c_str(), obj.memberDimension()[I]),
|
||||
0)...};
|
||||
}
|
||||
|
||||
// Helper: Generate unique variable key from name and index
|
||||
std::string generateKey(const std::string& name, int idx) {
|
||||
if (!name.empty() && name[0] == '\\') {
|
||||
const size_t space_pos = name.find(' ');
|
||||
return (space_pos != std::string::npos ? name.substr(0, space_pos) : name)
|
||||
+ std::to_string(idx);
|
||||
}
|
||||
const size_t bracket_pos = name.find('[');
|
||||
return (bracket_pos != std::string::npos ? name.substr(0, bracket_pos) : name)
|
||||
+ std::to_string(idx);
|
||||
}
|
||||
|
||||
void hard(std::string&& constraint);
|
||||
void clear();
|
||||
void set_randmode(const VlQueue<CData>& randmode) { m_randmode = &randmode; }
|
||||
|
|
|
|||
|
|
@ -15,9 +15,9 @@
|
|||
/// \brief Verilated C++ tracing in SAIF format implementation code
|
||||
///
|
||||
/// This file must be compiled and linked against all Verilated objects
|
||||
/// that use --trace.
|
||||
/// that use --trace-saif.
|
||||
///
|
||||
/// Use "verilator --trace" to add this to the Makefile for the linker.
|
||||
/// Use "verilator --trace-saif" to add this to the Makefile for the linker.
|
||||
///
|
||||
//=============================================================================
|
||||
|
||||
|
|
@ -110,7 +110,7 @@ public:
|
|||
"The emitted value must be of integral type");
|
||||
|
||||
const uint64_t dt = time - m_lastTime;
|
||||
for (size_t i = 0; i < std::min(m_width, bits); i++) {
|
||||
for (size_t i = 0; i < std::min(m_width, bits); ++i) {
|
||||
m_bits[i].aggregateVal(dt, (newval >> i) & 1);
|
||||
}
|
||||
updateLastTime(time);
|
||||
|
|
@ -319,6 +319,7 @@ void VerilatedSaif::close() VL_MT_SAFE_EXCLUDES(m_mutex) {
|
|||
finalizeSaifFileContents();
|
||||
clearCurrentlyCollectedData();
|
||||
|
||||
writeBuffered(true);
|
||||
::close(m_filep);
|
||||
m_isOpen = false;
|
||||
|
||||
|
|
@ -400,11 +401,6 @@ bool VerilatedSaif::printActivityStats(VerilatedSaifActivityVar& activity,
|
|||
for (size_t i = 0; i < activity.width(); ++i) {
|
||||
VerilatedSaifActivityBit& bit = activity.bit(i);
|
||||
|
||||
if (bit.toggleCount() <= 0) {
|
||||
// Skip bits with no toggles
|
||||
continue;
|
||||
}
|
||||
|
||||
bit.aggregateVal(currentTime() - activity.lastUpdateTime(), bit.bitValue());
|
||||
|
||||
if (!anyNetWritten) {
|
||||
|
|
@ -442,9 +438,25 @@ void VerilatedSaif::clearCurrentlyCollectedData() {
|
|||
m_activityAccumulators.clear();
|
||||
}
|
||||
|
||||
void VerilatedSaif::printStr(const char* str) { ::write(m_filep, str, strlen(str)); }
|
||||
void VerilatedSaif::printStr(const char* str) {
|
||||
m_buffer.append(str);
|
||||
writeBuffered(false);
|
||||
}
|
||||
|
||||
void VerilatedSaif::printStr(const std::string& str) { ::write(m_filep, str.c_str(), str.size()); }
|
||||
void VerilatedSaif::printStr(const std::string& str) {
|
||||
m_buffer.append(str);
|
||||
writeBuffered(false);
|
||||
}
|
||||
|
||||
void VerilatedSaif::writeBuffered(bool force) {
|
||||
if (VL_UNLIKELY(m_buffer.size() >= WRITE_BUFFER_SIZE || force)) {
|
||||
if (VL_UNLIKELY(!m_buffer.empty())) {
|
||||
::write(m_filep, m_buffer.data(), m_buffer.size());
|
||||
m_buffer = "";
|
||||
m_buffer.reserve(WRITE_BUFFER_SIZE * 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
// Definitions
|
||||
|
|
@ -459,7 +471,7 @@ void VerilatedSaif::incrementIndent() { m_indent += 1; }
|
|||
void VerilatedSaif::decrementIndent() { m_indent -= 1; }
|
||||
|
||||
void VerilatedSaif::printIndent() {
|
||||
for (int i = 0; i < m_indent; ++i) printStr(" ");
|
||||
printStr(std::string(m_indent, ' ')); // Must use () constructor
|
||||
}
|
||||
|
||||
void VerilatedSaif::pushPrefix(const std::string& name, VerilatedTracePrefixType type) {
|
||||
|
|
|
|||
|
|
@ -52,8 +52,10 @@ private:
|
|||
int m_filep = 0; // File we're writing to
|
||||
bool m_isOpen = false; // True indicates open file
|
||||
std::string m_filename; // Filename we're writing to (if open)
|
||||
std::string m_buffer; // Write data buffer
|
||||
|
||||
int m_indent = 0; // Indentation size in spaces
|
||||
static constexpr size_t WRITE_BUFFER_SIZE = 256 * 1024; // Bytes between write calls
|
||||
|
||||
// Currently active scope
|
||||
VerilatedSaifActivityScope* m_currentScope = nullptr;
|
||||
|
|
@ -92,6 +94,7 @@ private:
|
|||
|
||||
void printStr(const char* str);
|
||||
void printStr(const std::string& str);
|
||||
void writeBuffered(bool force);
|
||||
|
||||
void clearCurrentlyCollectedData();
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ static double timescaleToDouble(const char* unitp) VL_PURE {
|
|||
// On error so we allow just "ns" to return 1e-9.
|
||||
if (value == 0.0 && endp == unitp) value = 1;
|
||||
unitp = endp;
|
||||
for (; *unitp && std::isspace(*unitp); unitp++) {}
|
||||
for (; *unitp && std::isspace(*unitp); ++unitp) {}
|
||||
switch (*unitp) {
|
||||
case 's': value *= 1e0; break;
|
||||
case 'm': value *= 1e-3; break;
|
||||
|
|
|
|||
|
|
@ -621,11 +621,13 @@ public:
|
|||
T_Value& atWriteAppend(int32_t index) {
|
||||
// cppcheck-suppress variableScope
|
||||
static thread_local T_Value t_throwAway;
|
||||
if (VL_UNLIKELY(index < 0 || index > m_deque.size())) {
|
||||
if (VL_UNLIKELY(index < 0 || index >= m_deque.size())) {
|
||||
if (index == m_deque.size()) {
|
||||
push_back(atDefault());
|
||||
return m_deque[index];
|
||||
}
|
||||
t_throwAway = atDefault();
|
||||
return t_throwAway;
|
||||
} else if (VL_UNLIKELY(index == m_deque.size())) {
|
||||
push_back(atDefault());
|
||||
}
|
||||
return m_deque[index];
|
||||
}
|
||||
|
|
@ -924,6 +926,9 @@ std::string VL_TO_STRING(const VlQueue<T_Value, N_MaxSize>& obj) {
|
|||
return obj.to_string();
|
||||
}
|
||||
|
||||
template <typename T_Value, size_t N_MaxSize>
|
||||
struct VlContainsCustomStruct<VlQueue<T_Value, N_MaxSize>> : VlContainsCustomStruct<T_Value> {};
|
||||
|
||||
//===================================================================
|
||||
// Verilog associative array container
|
||||
// There are no multithreaded locks on this; the base variable must
|
||||
|
|
@ -964,6 +969,7 @@ public:
|
|||
|
||||
// Size of array. Verilog: function int size(), or int num()
|
||||
int size() const { return m_map.size(); }
|
||||
bool empty() const { return m_map.empty(); }
|
||||
// Clear array. Verilog: function void delete([input index])
|
||||
void clear() { m_map.clear(); }
|
||||
void erase(const T_Key& index) { m_map.erase(index); }
|
||||
|
|
@ -1259,6 +1265,9 @@ std::string VL_TO_STRING(const VlAssocArray<T_Key, T_Value>& obj) {
|
|||
return obj.to_string();
|
||||
}
|
||||
|
||||
template <typename T_Key, typename T_Value>
|
||||
struct VlContainsCustomStruct<VlAssocArray<T_Key, T_Value>> : VlContainsCustomStruct<T_Value> {};
|
||||
|
||||
template <typename T_Key, typename T_Value>
|
||||
void VL_READMEM_N(bool hex, int bits, const std::string& filename,
|
||||
VlAssocArray<T_Key, T_Value>& obj, QData start, QData end) VL_MT_SAFE {
|
||||
|
|
@ -1589,6 +1598,9 @@ std::string VL_TO_STRING(const VlUnpacked<T_Value, N_Depth>& obj) {
|
|||
return obj.to_string();
|
||||
}
|
||||
|
||||
template <typename T_Value, std::size_t N_Depth>
|
||||
struct VlContainsCustomStruct<VlUnpacked<T_Value, N_Depth>> : VlContainsCustomStruct<T_Value> {};
|
||||
|
||||
//===================================================================
|
||||
// Helper to apply the given indices to a target expression
|
||||
|
||||
|
|
|
|||
|
|
@ -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)) {
|
||||
|
|
@ -205,7 +205,7 @@ public:
|
|||
uint32_t size() const override {
|
||||
const int maxDimNum = maxDim(isIndexedDimUnpacked());
|
||||
int size = 1;
|
||||
for (int dim = indexedDim() + 1; dim <= maxDimNum; dim++)
|
||||
for (int dim = indexedDim() + 1; dim <= maxDimNum; ++dim)
|
||||
size *= varp()->range(dim)->elements();
|
||||
return size;
|
||||
}
|
||||
|
|
@ -503,7 +503,7 @@ public:
|
|||
explicit VerilatedVpioRegIter(const VerilatedVpioVar* vop)
|
||||
: m_var{new VerilatedVpioVar(vop)}
|
||||
, m_maxDim{vop->varp()->udims() - 1} {
|
||||
for (auto it = vop->indexedDim() + 1; it <= m_maxDim; it++)
|
||||
for (auto it = vop->indexedDim() + 1; it <= m_maxDim; ++it)
|
||||
m_ranges.push_back(*vop->varp()->range(it));
|
||||
for (auto it : m_ranges) m_nextIndex.push_back(it.right());
|
||||
}
|
||||
|
|
@ -2219,7 +2219,7 @@ vpiHandle vpi_iterate(PLI_INT32 type, vpiHandle object) {
|
|||
|
||||
std::vector<VerilatedRange> ranges;
|
||||
const int maxDim = vop->maxDim(vop->isIndexedDimUnpacked());
|
||||
for (int dim = vop->indexedDim() + 1; dim <= maxDim; dim++)
|
||||
for (int dim = vop->indexedDim() + 1; dim <= maxDim; ++dim)
|
||||
ranges.emplace_back(*vop->varp()->range(dim));
|
||||
|
||||
// allow one more range layer (regbit)
|
||||
|
|
@ -2574,8 +2574,8 @@ void vl_vpi_put_word(const VerilatedVpioVar* vop, QData word, size_t bitCount, s
|
|||
}
|
||||
|
||||
void vl_vpi_get_value(const VerilatedVpioVarBase* vop, p_vpi_value valuep) {
|
||||
const VerilatedVar* varp = vop->varp();
|
||||
void* varDatap = vop->varDatap();
|
||||
const VerilatedVar* const varp = vop->varp();
|
||||
void* const varDatap = vop->varDatap();
|
||||
const char* fullname = vop->fullname();
|
||||
|
||||
if (!vl_check_format(varp, valuep, fullname, true)) return;
|
||||
|
|
@ -2788,8 +2788,8 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value valuep, p_vpi_time /*time_
|
|||
} else if (valuep->format == vpiOctStrVal) {
|
||||
const int len = std::strlen(valuep->value.str);
|
||||
for (int i = 0; i < len; ++i) {
|
||||
char digit = valuep->value.str[len - i - 1] - '0';
|
||||
if (digit < 0 || digit > 7) {
|
||||
unsigned char digit = valuep->value.str[len - i - 1] - '0';
|
||||
if (digit > 7) { // If str was < '0', then as unsigned, digit > 7
|
||||
VL_VPI_WARNING_(__FILE__, __LINE__,
|
||||
"%s: Non octal character '%c' in '%s' as value %s for %s",
|
||||
__func__, digit + '0', valuep->value.str,
|
||||
|
|
@ -2945,7 +2945,7 @@ void vl_get_value_array_integrals(unsigned index, const unsigned num, const unsi
|
|||
const unsigned packedSize, const bool leftIsLow, const T* src,
|
||||
K* dst) {
|
||||
static_assert(sizeof(K) >= sizeof(T), "size of type K is less than size of type T");
|
||||
for (int i = 0; i < num; i++) {
|
||||
for (int i = 0; i < num; ++i) {
|
||||
dst[i] = src[index];
|
||||
index = leftIsLow ? index == (size - 1) ? 0 : index + 1
|
||||
: index == 0 ? size - 1
|
||||
|
|
@ -2964,7 +2964,7 @@ void vl_put_value_array_integrals(unsigned index, const unsigned num, const unsi
|
|||
const T mask = element_size_bytes == sizeof(T)
|
||||
? static_cast<T>(-1)
|
||||
: ~(static_cast<T>(-1) << (element_size_bytes * 8));
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
for (unsigned i = 0; i < num; ++i) {
|
||||
dst[index] = src[i] & static_cast<T>(mask);
|
||||
index = leftIsLow ? index == (size - 1) ? 0 : index + 1
|
||||
: index == 0 ? size - 1
|
||||
|
|
@ -2980,9 +2980,8 @@ void vl_get_value_array_vectors(unsigned index, const unsigned num, const unsign
|
|||
"type T is not unsigned"); // ensure logical right shift
|
||||
const unsigned element_size_bytes = VL_BYTES_I(packedSize);
|
||||
const unsigned element_size_words = VL_WORDS_I(packedSize);
|
||||
const unsigned element_size_repr = (element_size_bytes + sizeof(T) - 1) / sizeof(T);
|
||||
if (sizeof(T) == sizeof(QData)) {
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
for (unsigned i = 0; i < num; ++i) {
|
||||
dst[i * 2].aval = static_cast<QData>(src[index]);
|
||||
dst[i * 2].bval = 0;
|
||||
dst[(i * 2) + 1].aval = static_cast<QData>(src[index]) >> 32;
|
||||
|
|
@ -2992,10 +2991,10 @@ void vl_get_value_array_vectors(unsigned index, const unsigned num, const unsign
|
|||
: index - 1;
|
||||
}
|
||||
} else {
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
for (unsigned i = 0; i < num; ++i) {
|
||||
const size_t dst_index = i * element_size_words;
|
||||
const size_t src_index = index * element_size_words;
|
||||
for (unsigned j = 0; j < element_size_words; j++) {
|
||||
for (unsigned j = 0; j < element_size_words; ++j) {
|
||||
dst[dst_index + j].aval = src[src_index + j];
|
||||
dst[dst_index + j].bval = 0;
|
||||
}
|
||||
|
|
@ -3018,7 +3017,7 @@ void vl_put_value_array_vectors(unsigned index, const unsigned num, const unsign
|
|||
const QData mask = element_size_bytes == sizeof(T)
|
||||
? static_cast<QData>(-1)
|
||||
: ~(static_cast<QData>(-1) << (element_size_bytes * 8));
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
for (unsigned i = 0; i < num; ++i) {
|
||||
dst[index] = src[i * 2].aval;
|
||||
dst[index]
|
||||
|= (static_cast<QData>(src[(i * 2) + 1].aval) << (sizeof(PLI_UINT32) * 8)) & mask;
|
||||
|
|
@ -3027,9 +3026,9 @@ void vl_put_value_array_vectors(unsigned index, const unsigned num, const unsign
|
|||
: index - 1;
|
||||
}
|
||||
} else {
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
for (unsigned i = 0; i < num; ++i) {
|
||||
unsigned bytes_stored = 0;
|
||||
for (unsigned j = 0; j < element_size_words; j++) {
|
||||
for (unsigned j = 0; j < element_size_words; ++j) {
|
||||
if (bytes_stored >= element_size_bytes) break;
|
||||
const T mask
|
||||
= (element_size_bytes - bytes_stored) >= sizeof(PLI_UINT32)
|
||||
|
|
@ -3058,9 +3057,9 @@ void vl_get_value_array_rawvals(unsigned index, unsigned num, const unsigned siz
|
|||
while (num-- > 0) {
|
||||
const size_t src_offset = index * element_size_repr;
|
||||
unsigned bytes_copied = 0;
|
||||
for (unsigned j = 0; j < element_size_repr; j++) {
|
||||
for (unsigned j = 0; j < element_size_repr; ++j) {
|
||||
const T& src_data = src[src_offset + j];
|
||||
for (unsigned k = 0; k < sizeof(T); k++) {
|
||||
for (unsigned k = 0; k < sizeof(T); ++k) {
|
||||
if (bytes_copied++ == element_size_bytes) break;
|
||||
dst[dst_index++] = src_data >> (k * 8);
|
||||
}
|
||||
|
|
@ -3081,13 +3080,13 @@ void vl_put_value_array_rawvals(unsigned index, const unsigned num, const unsign
|
|||
const bool fourState, const PLI_UBYTE8* src, T* dst) {
|
||||
const unsigned element_size_bytes VL_BYTES_I(packedSize);
|
||||
const unsigned element_size_repr = (element_size_bytes + sizeof(T) - 1) / sizeof(T);
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
for (unsigned i = 0; i < num; ++i) {
|
||||
unsigned bytes_copied = 0;
|
||||
const size_t dst_offset = index * element_size_repr;
|
||||
const size_t src_offset = i * element_size_bytes;
|
||||
for (unsigned j = 0; j < element_size_repr; j++) {
|
||||
for (unsigned j = 0; j < element_size_repr; ++j) {
|
||||
T& dst_data = dst[dst_offset + j];
|
||||
for (unsigned k = 0; k < sizeof(T); k++) {
|
||||
for (unsigned k = 0; k < sizeof(T); ++k) {
|
||||
if (bytes_copied == element_size_bytes) break;
|
||||
const unsigned src_index
|
||||
= fourState ? (src_offset * 2) + bytes_copied : (src_offset) + bytes_copied;
|
||||
|
|
@ -3102,7 +3101,7 @@ void vl_put_value_array_rawvals(unsigned index, const unsigned num, const unsign
|
|||
}
|
||||
}
|
||||
|
||||
void vl_get_value_array(vpiHandle object, p_vpi_arrayvalue arrayvalue_p, PLI_INT32* index_p,
|
||||
void vl_get_value_array(vpiHandle object, p_vpi_arrayvalue arrayvalue_p, const PLI_INT32* index_p,
|
||||
PLI_UINT32 num) {
|
||||
const VerilatedVpioVar* const vop = VerilatedVpioVar::castp(object);
|
||||
if (!vl_check_array_format(vop->varp(), arrayvalue_p, vop->fullname())) return;
|
||||
|
|
@ -3119,7 +3118,7 @@ void vl_get_value_array(vpiHandle object, p_vpi_arrayvalue arrayvalue_p, PLI_INT
|
|||
}
|
||||
|
||||
const bool leftIsLow = vop->rangep()->left() == vop->rangep()->low();
|
||||
int index
|
||||
const int index
|
||||
= leftIsLow ? index_p[0] - vop->rangep()->left() : vop->rangep()->left() - index_p[0];
|
||||
|
||||
if (arrayvalue_p->format == vpiShortIntVal) {
|
||||
|
|
@ -3310,9 +3309,8 @@ void vpi_get_value_array(vpiHandle object, p_vpi_arrayvalue arrayvalue_p, PLI_IN
|
|||
return;
|
||||
}
|
||||
|
||||
int lowRange = vop->rangep()->low();
|
||||
int highRange = vop->rangep()->high();
|
||||
|
||||
const int lowRange = vop->rangep()->low();
|
||||
const int highRange = vop->rangep()->high();
|
||||
if ((index_p[0] > highRange) || (index_p[0] < lowRange)) {
|
||||
VL_VPI_ERROR_(__FILE__, __LINE__, "%s: index %u for object %s is out of bounds [%u,%u]",
|
||||
__func__, index_p[0], vop->fullname(), lowRange, highRange);
|
||||
|
|
@ -3328,14 +3326,14 @@ void vpi_get_value_array(vpiHandle object, p_vpi_arrayvalue arrayvalue_p, PLI_IN
|
|||
vl_get_value_array(object, arrayvalue_p, index_p, num);
|
||||
}
|
||||
|
||||
void vl_put_value_array(vpiHandle object, p_vpi_arrayvalue arrayvalue_p, PLI_INT32* index_p,
|
||||
void vl_put_value_array(vpiHandle object, p_vpi_arrayvalue arrayvalue_p, const PLI_INT32* index_p,
|
||||
PLI_UINT32 num) {
|
||||
const VerilatedVpioVar* const vop = VerilatedVpioVar::castp(object);
|
||||
if (!vl_check_array_format(vop->varp(), arrayvalue_p, vop->fullname())) return;
|
||||
|
||||
const VerilatedVar* const varp = vop->varp();
|
||||
|
||||
int size = vop->size();
|
||||
const int size = vop->size();
|
||||
if (VL_UNCOVERABLE(num > size)) {
|
||||
VL_VPI_ERROR_(__FILE__, __LINE__,
|
||||
"%s: requested elements to set (%u) exceed array size (%u)", __func__, num,
|
||||
|
|
@ -3344,7 +3342,7 @@ void vl_put_value_array(vpiHandle object, p_vpi_arrayvalue arrayvalue_p, PLI_INT
|
|||
}
|
||||
|
||||
const bool leftIsLow = vop->rangep()->left() == vop->rangep()->low();
|
||||
int index
|
||||
const int index
|
||||
= leftIsLow ? index_p[0] - vop->rangep()->left() : vop->rangep()->left() - index_p[0];
|
||||
|
||||
if (arrayvalue_p->format == vpiShortIntVal) {
|
||||
|
|
@ -3492,11 +3490,8 @@ void vpi_put_value_array(vpiHandle object, p_vpi_arrayvalue arrayvalue_p, PLI_IN
|
|||
return;
|
||||
}
|
||||
|
||||
const VerilatedVar* const varp = vop->varp();
|
||||
|
||||
int lowRange = vop->rangep()->low();
|
||||
int highRange = vop->rangep()->high();
|
||||
|
||||
const int lowRange = vop->rangep()->low();
|
||||
const int highRange = vop->rangep()->high();
|
||||
if ((index_p[0] > highRange) || (index_p[0] < lowRange)) {
|
||||
VL_VPI_ERROR_(__FILE__, __LINE__, "%s: index %u for object %s is out of bounds [%u,%u]",
|
||||
__func__, index_p[0], vop->fullname(), lowRange, highRange);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ def process():
|
|||
|
||||
print()
|
||||
print("You may now want to clean up spelling, and commit:")
|
||||
print(" (cd docs ; make spelling | grep -v 'Writing output')")
|
||||
print(" (cd docs ; make spelling | grep -vi 'writing output')")
|
||||
print(" git ci -am 'Commentary: Changes update'")
|
||||
print()
|
||||
|
||||
|
|
|
|||
|
|
@ -178,6 +178,7 @@ set(HEADERS
|
|||
V3Trace.h
|
||||
V3TraceDecl.h
|
||||
V3Tristate.h
|
||||
V3Udp.h
|
||||
V3Undriven.h
|
||||
V3UniqueNames.h
|
||||
V3Unknown.h
|
||||
|
|
@ -326,6 +327,7 @@ set(COMMON_SOURCES
|
|||
V3TraceDecl.cpp
|
||||
V3Tristate.cpp
|
||||
V3TSP.cpp
|
||||
V3Udp.cpp
|
||||
V3Undriven.cpp
|
||||
V3Unknown.cpp
|
||||
V3Unroll.cpp
|
||||
|
|
|
|||
|
|
@ -311,6 +311,7 @@ RAW_OBJS_PCH_ASTNOMT = \
|
|||
V3Trace.o \
|
||||
V3TraceDecl.o \
|
||||
V3Tristate.o \
|
||||
V3Udp.o \
|
||||
V3Undriven.o \
|
||||
V3Unknown.o \
|
||||
V3Unroll.o \
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
//######################################################################
|
||||
|
|
@ -322,7 +324,7 @@ void AstNode::debugTreeChange(const AstNode* nodep, const char* prefix, int line
|
|||
// // Commenting out the section below may crash, as the tree state
|
||||
// // between edits is not always consistent for printing
|
||||
// cout<<"-treeChange: V3Ast.cpp:"<<lineno<<" Tree Change for "<<prefix<<endl;
|
||||
// v3Global.rootp()->dumpTree("- treeChange: ");
|
||||
// if (debug()) v3Global.rootp()->dumpTree("- treeChange: ");
|
||||
// if (next||1) nodep->dumpTreeAndNext(cout, prefix);
|
||||
// else nodep->dumpTree(prefix);
|
||||
// nodep->checkTree();
|
||||
|
|
@ -519,6 +521,10 @@ void AstNode::replaceWith(AstNode* newp) {
|
|||
this->unlinkFrBack(&repHandle);
|
||||
repHandle.relink(newp);
|
||||
}
|
||||
void AstNode::replaceWithKeepDType(AstNode* newp) {
|
||||
newp->dtypeFrom(this);
|
||||
replaceWith(newp);
|
||||
}
|
||||
|
||||
void VNRelinker::dump(std::ostream& str) const {
|
||||
str << " BK=" << reinterpret_cast<uint32_t*>(m_backp);
|
||||
|
|
@ -1340,7 +1346,7 @@ void AstNode::dumpTreeFile(const string& filename, bool doDump) {
|
|||
{ // Write log & close
|
||||
UINFO(2, "Dumping " << filename << endl);
|
||||
const std::unique_ptr<std::ofstream> logsp{V3File::new_ofstream(filename)};
|
||||
if (logsp->fail()) v3fatal("Can't write " << filename);
|
||||
if (logsp->fail()) v3fatal("Can't write file: " << filename);
|
||||
*logsp << "Verilator Tree Dump (format 0x3900) from <e" << std::dec << editCountLast();
|
||||
*logsp << "> to <e" << std::dec << editCountGbl() << ">\n";
|
||||
if (editCountGbl() == editCountLast() && ::dumpTreeLevel() < 9) {
|
||||
|
|
@ -1385,7 +1391,7 @@ void AstNode::dumpTreeJsonFile(const string& filename, bool doDump) {
|
|||
if (!doDump) return;
|
||||
UINFO(2, "Dumping " << filename << endl);
|
||||
const std::unique_ptr<std::ofstream> treejsonp{V3File::new_ofstream(filename)};
|
||||
if (treejsonp->fail()) v3fatal("Can't write " << filename);
|
||||
if (treejsonp->fail()) v3fatal("Can't write file: " << filename);
|
||||
dumpTreeJson(*treejsonp);
|
||||
*treejsonp << '\n';
|
||||
}
|
||||
|
|
@ -1394,7 +1400,7 @@ void AstNode::dumpJsonMetaFileGdb(const char* filename) { dumpJsonMetaFile(filen
|
|||
void AstNode::dumpJsonMetaFile(const string& filename) {
|
||||
UINFO(2, "Dumping " << filename << endl);
|
||||
const std::unique_ptr<std::ofstream> treejsonp{V3File::new_ofstream(filename)};
|
||||
if (treejsonp->fail()) v3fatalStatic("Can't write " << filename);
|
||||
if (treejsonp->fail()) v3fatalStatic("Can't write file: " << filename);
|
||||
*treejsonp << '{';
|
||||
FileLine::fileNameNumMapDumpJson(*treejsonp);
|
||||
*treejsonp << ',';
|
||||
|
|
@ -1408,7 +1414,7 @@ void AstNode::dumpTreeDotFile(const string& filename, bool doDump) {
|
|||
if (doDump) {
|
||||
UINFO(2, "Dumping " << filename << endl);
|
||||
const std::unique_ptr<std::ofstream> treedotp{V3File::new_ofstream(filename)};
|
||||
if (treedotp->fail()) v3fatal("Can't write " << filename);
|
||||
if (treedotp->fail()) v3fatal("Can't write file: " << filename);
|
||||
*treedotp << "digraph vTree{\n";
|
||||
*treedotp << "\tgraph\t[label=\"" << filename + ".dot"
|
||||
<< "\",\n";
|
||||
|
|
|
|||
|
|
@ -336,6 +336,7 @@ public:
|
|||
NO_INLINE_TASK,
|
||||
PUBLIC_MODULE,
|
||||
PUBLIC_TASK,
|
||||
TIMEUNIT_SET,
|
||||
UNROLL_DISABLE,
|
||||
UNROLL_FULL,
|
||||
FULL_CASE,
|
||||
|
|
@ -458,6 +459,7 @@ public:
|
|||
ILLEGAL,
|
||||
//
|
||||
DIM_BITS, // V3Const converts to constant
|
||||
DIM_BITS_OR_NUMBER, // V3Const converts to constant
|
||||
DIM_DIMENSIONS, // V3Width converts to constant
|
||||
DIM_HIGH, // V3Width processes
|
||||
DIM_INCREMENT, // V3Width processes
|
||||
|
|
@ -500,7 +502,8 @@ public:
|
|||
// clang-format off
|
||||
static const char* const names[] = {
|
||||
"%E-AT",
|
||||
"DIM_BITS", "DIM_DIMENSIONS", "DIM_HIGH", "DIM_INCREMENT", "DIM_LEFT",
|
||||
"DIM_BITS", "DIM_BITS_OR_NUMBER", "DIM_DIMENSIONS",
|
||||
"DIM_HIGH", "DIM_INCREMENT", "DIM_LEFT",
|
||||
"DIM_LOW", "DIM_RIGHT", "DIM_SIZE", "DIM_UNPK_DIMENSIONS",
|
||||
"DT_PUBLIC",
|
||||
"ENUM_FIRST", "ENUM_LAST", "ENUM_NUM",
|
||||
|
|
@ -1686,6 +1689,7 @@ public:
|
|||
bool isVlSym() const { return m_strp->find("vlSymsp") != string::npos; }
|
||||
bool hasThis() const { return m_strp == s_thisp || VString::startsWith(*m_strp, "this"); }
|
||||
string protect(bool useSelfForThis, bool protect) const;
|
||||
static string replaceThis(bool useSelfForThis, const string& text);
|
||||
const std::string& asString() const { return *m_strp; }
|
||||
bool operator==(const VSelfPointerText& other) const { return *m_strp == *other.m_strp; }
|
||||
};
|
||||
|
|
@ -2414,6 +2418,7 @@ public:
|
|||
void addNextHere(AstNode* newp); // Insert newp at this->nextp
|
||||
void addHereThisAsNext(AstNode* newp); // Adds at old place of this, this becomes next
|
||||
void replaceWith(AstNode* newp); // Replace current node in tree with new node
|
||||
void replaceWithKeepDType(AstNode* newp); // Replace current node in tree, keep old dtype
|
||||
// Unlink this from whoever points to it.
|
||||
AstNode* unlinkFrBack(VNRelinker* linkerp = nullptr);
|
||||
// Unlink this from whoever points to it, keep entire next list with unlinked node
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ int AstNode::widthInstrs() const {
|
|||
return (!dtypep() ? 1 : (dtypep()->isWide() ? dtypep()->widthWords() : 1));
|
||||
}
|
||||
bool AstNode::isDouble() const VL_MT_STABLE {
|
||||
return dtypep() && VN_IS(dtypep(), BasicDType) && VN_AS(dtypep(), BasicDType)->isDouble();
|
||||
return dtypep() && dtypep()->basicp() && dtypep()->basicp()->isDouble();
|
||||
}
|
||||
bool AstNode::isString() const VL_MT_STABLE {
|
||||
return dtypep() && dtypep()->basicp() && dtypep()->basicp()->isString();
|
||||
|
|
|
|||
|
|
@ -120,15 +120,7 @@ public:
|
|||
// Iff has second dtype, set as generic node function
|
||||
virtual void virtRefDType2p(AstNodeDType* nodep) {}
|
||||
// Assignable equivalence. Calls skipRefToNonRefp() during comparisons.
|
||||
bool similarDType(const AstNodeDType* samep) const {
|
||||
const AstNodeDType* nodep = this;
|
||||
nodep = nodep->skipRefToNonRefp();
|
||||
samep = samep->skipRefToNonRefp();
|
||||
if (nodep == samep) return true;
|
||||
if (nodep->type() != samep->type()) return false;
|
||||
return nodep->similarDTypeNode(samep);
|
||||
}
|
||||
|
||||
bool similarDType(const AstNodeDType* samep) const;
|
||||
// Iff has a non-null subDTypep(), as generic node function
|
||||
virtual AstNodeDType* subDTypep() const VL_MT_STABLE { return nullptr; }
|
||||
virtual bool isFourstate() const;
|
||||
|
|
@ -165,7 +157,7 @@ public:
|
|||
bool generic() const VL_MT_SAFE { return m_generic; }
|
||||
void generic(bool flag) { m_generic = flag; }
|
||||
std::pair<uint32_t, uint32_t> dimensions(bool includeBasic);
|
||||
uint32_t arrayUnpackedElements(); // 1, or total multiplication of all dimensions
|
||||
uint32_t arrayUnpackedElements() const; // 1, or total multiplication of all dimensions
|
||||
static int uniqueNumInc() { return ++s_uniqueNum; }
|
||||
const char* charIQWN() const {
|
||||
return (isString() ? "N" : isWide() ? "W" : isQuad() ? "Q" : "I");
|
||||
|
|
@ -435,6 +427,8 @@ public:
|
|||
string prettyDTypeName(bool full) const override;
|
||||
const char* broken() const override {
|
||||
BROKEN_RTN(dtypep() != this);
|
||||
BROKEN_RTN(v3Global.widthMinUsage() == VWidthMinUsage::VERILOG_WIDTH
|
||||
&& widthMin() > width());
|
||||
return nullptr;
|
||||
}
|
||||
void setSignedState(const VSigning& signst) {
|
||||
|
|
@ -581,7 +575,11 @@ public:
|
|||
const AstClassRefDType* const asamep = VN_DBG_AS(samep, ClassRefDType);
|
||||
return (m_classp == asamep->m_classp && m_classOrPackagep == asamep->m_classOrPackagep);
|
||||
}
|
||||
bool similarDTypeNode(const AstNodeDType* samep) const override { return sameNode(samep); }
|
||||
bool similarDTypeNode(const AstNodeDType* samep) const override {
|
||||
// Doesn't need to compare m_classOrPackagep
|
||||
const AstClassRefDType* const asamep = VN_DBG_AS(samep, ClassRefDType);
|
||||
return m_classp == asamep->m_classp;
|
||||
}
|
||||
void dump(std::ostream& str = std::cout) const override;
|
||||
void dumpJson(std::ostream& str = std::cout) const override;
|
||||
void dumpSmall(std::ostream& str) const override;
|
||||
|
|
@ -668,16 +666,12 @@ class AstDefImplicitDType final : public AstNodeDType {
|
|||
// After link, these become typedefs
|
||||
// @astgen op1 := childDTypep : Optional[AstNodeDType]
|
||||
string m_name;
|
||||
void* m_containerp; // In what scope is the name unique, so we can know what are duplicate
|
||||
// definitions (arbitrary value)
|
||||
const int m_uniqueNum;
|
||||
|
||||
public:
|
||||
AstDefImplicitDType(FileLine* fl, const string& name, void* containerp, VFlagChildDType,
|
||||
AstNodeDType* dtp)
|
||||
AstDefImplicitDType(FileLine* fl, const string& name, VFlagChildDType, AstNodeDType* dtp)
|
||||
: ASTGEN_SUPER_DefImplicitDType(fl)
|
||||
, m_name{name}
|
||||
, m_containerp{containerp}
|
||||
, m_uniqueNum{uniqueNumInc()} {
|
||||
childDTypep(dtp); // Only for parser
|
||||
dtypep(nullptr); // V3Width will resolve
|
||||
|
|
@ -685,7 +679,6 @@ public:
|
|||
AstDefImplicitDType(const AstDefImplicitDType& other)
|
||||
: AstNodeDType(other)
|
||||
, m_name(other.m_name)
|
||||
, m_containerp(other.m_containerp)
|
||||
, m_uniqueNum(uniqueNumInc()) {}
|
||||
ASTGEN_MEMBERS_AstDefImplicitDType;
|
||||
int uniqueNum() const { return m_uniqueNum; }
|
||||
|
|
@ -698,7 +691,6 @@ public:
|
|||
AstNodeDType* subDTypep() const override VL_MT_STABLE {
|
||||
return dtypep() ? dtypep() : childDTypep();
|
||||
}
|
||||
void* containerp() const { return m_containerp; }
|
||||
// METHODS
|
||||
// op1 = Range of variable
|
||||
AstNodeDType* dtypeSkipRefp() const { return dtypep()->skipRefp(); }
|
||||
|
|
@ -1392,13 +1384,20 @@ public:
|
|||
string verilogKwd() const override { return "struct"; }
|
||||
};
|
||||
class AstUnionDType final : public AstNodeUOrStructDType {
|
||||
bool m_isSoft; // Is a "union soft"
|
||||
|
||||
public:
|
||||
// UNSUP: bool isTagged;
|
||||
// VSigning below is mispurposed to indicate if packed or not
|
||||
AstUnionDType(FileLine* fl, VSigning numericUnpack)
|
||||
: ASTGEN_SUPER_UnionDType(fl, numericUnpack) {}
|
||||
// isSoft implies packed
|
||||
AstUnionDType(FileLine* fl, bool isSoft, VSigning numericUnpack)
|
||||
: ASTGEN_SUPER_UnionDType(fl, numericUnpack)
|
||||
, m_isSoft(isSoft) {
|
||||
packed(packed() | m_isSoft);
|
||||
}
|
||||
ASTGEN_MEMBERS_AstUnionDType;
|
||||
string verilogKwd() const override { return "union"; }
|
||||
bool isSoft() const { return m_isSoft; }
|
||||
};
|
||||
|
||||
#endif // Guard
|
||||
|
|
|
|||
|
|
@ -953,7 +953,7 @@ class AstConst final : public AstNodeExpr {
|
|||
} else if (m_num.isString()) {
|
||||
dtypeSetString();
|
||||
} else {
|
||||
dtypeSetLogicUnsized(m_num.width(), (m_num.sized() ? 0 : m_num.widthMin()),
|
||||
dtypeSetLogicUnsized(m_num.width(), (m_num.sized() ? 0 : m_num.widthToFit()),
|
||||
VSigning::fromBool(m_num.isSigned()));
|
||||
}
|
||||
m_num.nodep(this);
|
||||
|
|
@ -987,7 +987,7 @@ public:
|
|||
class VerilogStringLiteral {}; // for creator type-overload selection
|
||||
AstConst(FileLine* fl, VerilogStringLiteral, const string& str)
|
||||
: ASTGEN_SUPER_Const(fl)
|
||||
, m_num(V3Number::VerilogStringLiteral{}, this, str) {
|
||||
, m_num{V3Number::VerilogStringLiteral{}, this, str} {
|
||||
initWithNumber();
|
||||
}
|
||||
AstConst(FileLine* fl, uint32_t num)
|
||||
|
|
@ -1000,14 +1000,14 @@ public:
|
|||
: ASTGEN_SUPER_Const(fl)
|
||||
, m_num(this, 32, num) {
|
||||
m_num.width(32, false);
|
||||
dtypeSetLogicUnsized(32, m_num.widthMin(), VSigning::UNSIGNED);
|
||||
dtypeSetLogicUnsized(32, m_num.widthToFit(), VSigning::UNSIGNED);
|
||||
}
|
||||
class Signed32 {}; // for creator type-overload selection
|
||||
AstConst(FileLine* fl, Signed32, int32_t num) // Signed 32-bit integer of specified value
|
||||
: ASTGEN_SUPER_Const(fl)
|
||||
, m_num(this, 32, num) {
|
||||
m_num.width(32, true);
|
||||
dtypeSetLogicUnsized(32, m_num.widthMin(), VSigning::SIGNED);
|
||||
dtypeSetLogicUnsized(32, m_num.widthToFit(), VSigning::SIGNED);
|
||||
}
|
||||
class Unsized64 {}; // for creator type-overload selection
|
||||
AstConst(FileLine* fl, Unsized64, uint64_t num)
|
||||
|
|
@ -1033,7 +1033,7 @@ public:
|
|||
class String {}; // for creator type-overload selection
|
||||
AstConst(FileLine* fl, String, const string& num)
|
||||
: ASTGEN_SUPER_Const(fl)
|
||||
, m_num(V3Number::String{}, this, num) {
|
||||
, m_num{V3Number::String{}, this, num} {
|
||||
dtypeSetString();
|
||||
}
|
||||
class BitFalse {};
|
||||
|
|
@ -1066,14 +1066,14 @@ public:
|
|||
class Null {};
|
||||
AstConst(FileLine* fl, Null)
|
||||
: ASTGEN_SUPER_Const(fl)
|
||||
, m_num(V3Number::Null{}, this) {
|
||||
, m_num{V3Number::Null{}, this} {
|
||||
dtypeSetBit(); // Events 1 bit, objects 64 bits, so autoExtend=1 and use bit here
|
||||
initWithNumber();
|
||||
}
|
||||
class OneStep {};
|
||||
AstConst(FileLine* fl, OneStep)
|
||||
: ASTGEN_SUPER_Const(fl)
|
||||
, m_num(V3Number::OneStep{}, this) {
|
||||
, m_num{V3Number::OneStep{}, this} {
|
||||
dtypeSetLogicSized(64, VSigning::UNSIGNED);
|
||||
initWithNumber();
|
||||
}
|
||||
|
|
@ -1156,6 +1156,20 @@ public:
|
|||
string emitC() override { V3ERROR_NA_RETURN(""); }
|
||||
bool cleanOut() const override { return true; }
|
||||
};
|
||||
class AstCvtUnpackedToQueue final : public AstNodeExpr {
|
||||
// Cast from unpacked array to dynamic/unpacked queue data type
|
||||
// @astgen op1 := fromp : AstNodeExpr
|
||||
public:
|
||||
AstCvtUnpackedToQueue(FileLine* fl, AstNodeExpr* fromp, AstNodeDType* dtp)
|
||||
: ASTGEN_SUPER_CvtUnpackedToQueue(fl) {
|
||||
this->fromp(fromp);
|
||||
dtypeFrom(dtp);
|
||||
}
|
||||
ASTGEN_MEMBERS_AstCvtUnpackedToQueue;
|
||||
string emitVerilog() override { V3ERROR_NA_RETURN(""); }
|
||||
string emitC() override { return "VL_CVT_UNPACK_TO_Q(%P, %li)"; }
|
||||
bool cleanOut() const override { return true; }
|
||||
};
|
||||
class AstDist final : public AstNodeExpr {
|
||||
// @astgen op1 := exprp : AstNodeExpr
|
||||
// @astgen op2 := itemsp : List[AstDistItem]
|
||||
|
|
@ -1913,6 +1927,7 @@ public:
|
|||
}
|
||||
ASTGEN_MEMBERS_AstSFormatF;
|
||||
string name() const override VL_MT_STABLE { return m_text; }
|
||||
void name(const string& name) override { m_text = name; }
|
||||
int instrCount() const override { return INSTR_COUNT_PLI; }
|
||||
bool sameNode(const AstNode* samep) const override {
|
||||
return text() == VN_DBG_AS(samep, SFormatF)->text();
|
||||
|
|
@ -4407,12 +4422,15 @@ public:
|
|||
class AstNew final : public AstNodeFTaskRef {
|
||||
// New as constructor
|
||||
// Don't need the class we are extracting from, as the "fromp()"'s datatype can get us to it
|
||||
bool m_isImplicit = false; // Implicitly generated from extends args
|
||||
public:
|
||||
AstNew(FileLine* fl, AstNodeExpr* pinsp)
|
||||
: ASTGEN_SUPER_New(fl, "new", pinsp) {}
|
||||
ASTGEN_MEMBERS_AstNew;
|
||||
bool sameNode(const AstNode* /*samep*/) const override { return true; }
|
||||
int instrCount() const override { return widthInstrs(); }
|
||||
bool isImplicit() const { return m_isImplicit; }
|
||||
void isImplicit(bool flag) { m_isImplicit = flag; }
|
||||
};
|
||||
class AstTaskRef final : public AstNodeFTaskRef {
|
||||
// A reference to a task
|
||||
|
|
@ -5742,6 +5760,7 @@ class AstVarXRef final : public AstNodeVarRef {
|
|||
string m_name;
|
||||
string m_dotted; // Dotted part of scope the name()'ed reference is under or ""
|
||||
string m_inlinedDots; // Dotted hierarchy flattened out
|
||||
bool m_containsGenBlock = false; // Contains gen block reference
|
||||
public:
|
||||
AstVarXRef(FileLine* fl, const string& name, const string& dotted, const VAccess& access)
|
||||
: ASTGEN_SUPER_VarXRef(fl, nullptr, access)
|
||||
|
|
@ -5757,6 +5776,8 @@ public:
|
|||
void dotted(const string& dotted) { m_dotted = dotted; }
|
||||
string inlinedDots() const { return m_inlinedDots; }
|
||||
void inlinedDots(const string& flag) { m_inlinedDots = flag; }
|
||||
bool containsGenBlock() const { return m_containsGenBlock; }
|
||||
void containsGenBlock(const bool flag) { m_containsGenBlock = flag; }
|
||||
string emitVerilog() override { V3ERROR_NA_RETURN(""); }
|
||||
string emitC() override { V3ERROR_NA_RETURN(""); }
|
||||
bool cleanOut() const override { return true; }
|
||||
|
|
|
|||
|
|
@ -631,8 +631,10 @@ class AstCFunc final : public AstNode {
|
|||
bool m_isConstructor : 1; // Is C class constructor
|
||||
bool m_isDestructor : 1; // Is C class destructor
|
||||
bool m_isMethod : 1; // Is inside a class definition
|
||||
bool m_isLoose : 1; // Semantically this is a method, but is implemented as a function
|
||||
// with an explicitly passed 'self' pointer as the first argument
|
||||
bool m_isLoose : 1; // Semantically this is a method, but is implemented as a function with
|
||||
// an explicitly passed 'self' pointer as the first argument. This can
|
||||
// be slightly faster due to __restrict, and we do not declare in header
|
||||
// so adding/removing loose functions doesn't recompile everything.
|
||||
bool m_isInline : 1; // Inline function
|
||||
bool m_isVirtual : 1; // Virtual function
|
||||
bool m_entryPoint : 1; // User may call into this top level function
|
||||
|
|
@ -915,6 +917,7 @@ class AstClassExtends final : public AstNode {
|
|||
// during early parse, then moves to dtype
|
||||
// @astgen op1 := childDTypep : Optional[AstNodeDType]
|
||||
// @astgen op2 := classOrPkgsp : Optional[AstNode]
|
||||
// @astgen op3 := argsp : List[AstNodeExpr]
|
||||
const bool m_isImplements = false; // class implements
|
||||
bool m_parameterized = false; // has parameters in its statement
|
||||
|
||||
|
|
@ -1491,18 +1494,24 @@ public:
|
|||
};
|
||||
class AstPragma final : public AstNode {
|
||||
const VPragmaType m_pragType; // Type of pragma
|
||||
const VTimescale m_timescale; // For TIMEUNIT_SET
|
||||
public:
|
||||
// Pragmas don't result in any output code, they're just flags that affect
|
||||
// other processing in verilator.
|
||||
AstPragma(FileLine* fl, VPragmaType pragType)
|
||||
: ASTGEN_SUPER_Pragma(fl)
|
||||
, m_pragType{pragType} {}
|
||||
AstPragma(FileLine* fl, VPragmaType pragType, const VTimescale& timescale)
|
||||
: ASTGEN_SUPER_Pragma(fl)
|
||||
, m_pragType{pragType}
|
||||
, m_timescale(timescale) {}
|
||||
ASTGEN_MEMBERS_AstPragma;
|
||||
VPragmaType pragType() const { return m_pragType; } // *=type of the pragma
|
||||
bool isPredictOptimizable() const override { return false; }
|
||||
bool sameNode(const AstNode* samep) const override {
|
||||
return pragType() == VN_DBG_AS(samep, Pragma)->pragType();
|
||||
}
|
||||
VTimescale timescale() const { return m_timescale; }
|
||||
};
|
||||
class AstPropSpec final : public AstNode {
|
||||
// A clocked property
|
||||
|
|
@ -1797,19 +1806,48 @@ class AstUdpTable final : public AstNode {
|
|||
public:
|
||||
AstUdpTable(FileLine* fl, AstUdpTableLine* linesp)
|
||||
: ASTGEN_SUPER_UdpTable(fl) {
|
||||
addLinesp(linesp);
|
||||
this->addLinesp(linesp);
|
||||
if (!v3Global.hasTable()) v3Global.setHasTable();
|
||||
}
|
||||
ASTGEN_MEMBERS_AstUdpTable;
|
||||
};
|
||||
class AstUdpTableLine final : public AstNode {
|
||||
string m_text;
|
||||
// @astgen op1 := iFieldsp : List[AstUdpTableLineVal] // Input fields
|
||||
// @astgen op2 := oFieldsp : List[AstUdpTableLineVal] // Output fields
|
||||
private:
|
||||
const bool m_udpIsCombo; // Combinational or sequential UDP
|
||||
|
||||
public:
|
||||
AstUdpTableLine(FileLine* fl, const string& text)
|
||||
class UdpCombo {};
|
||||
AstUdpTableLine(UdpCombo, FileLine* fl, AstUdpTableLineVal* iFieldsp,
|
||||
AstUdpTableLineVal* oFieldsp)
|
||||
: ASTGEN_SUPER_UdpTableLine(fl)
|
||||
, m_text{text} {}
|
||||
, m_udpIsCombo{true} {
|
||||
addIFieldsp(iFieldsp);
|
||||
addOFieldsp(oFieldsp);
|
||||
}
|
||||
class UdpSequential {};
|
||||
AstUdpTableLine(UdpSequential, FileLine* fl, AstUdpTableLineVal* iFieldsp,
|
||||
AstUdpTableLineVal* oFieldsp1, AstUdpTableLineVal* oFieldsp2)
|
||||
: ASTGEN_SUPER_UdpTableLine(fl)
|
||||
, m_udpIsCombo{false} {
|
||||
addIFieldsp(iFieldsp);
|
||||
addOFieldsp(oFieldsp1);
|
||||
addOFieldsp(oFieldsp2);
|
||||
}
|
||||
ASTGEN_MEMBERS_AstUdpTableLine;
|
||||
int udpIsCombo() const { return m_udpIsCombo; }
|
||||
};
|
||||
class AstUdpTableLineVal final : public AstNode {
|
||||
string m_text; // Value character
|
||||
|
||||
public:
|
||||
AstUdpTableLineVal(FileLine* fl, const string& text)
|
||||
: ASTGEN_SUPER_UdpTableLineVal(fl)
|
||||
, m_text{text} {}
|
||||
ASTGEN_MEMBERS_AstUdpTableLineVal;
|
||||
string name() const override VL_MT_STABLE { return m_text; }
|
||||
void name(std::string const& text) override VL_MT_STABLE { m_text = text; }
|
||||
string text() const VL_MT_SAFE { return m_text; }
|
||||
};
|
||||
class AstVar final : public AstNode {
|
||||
|
|
@ -2489,14 +2527,28 @@ public:
|
|||
};
|
||||
class AstModule final : public AstNodeModule {
|
||||
// A module declaration
|
||||
const bool m_isProgram; // Module represents a program
|
||||
const bool m_isChecker = false; // Module represents a checker
|
||||
const bool m_isProgram = false; // Module represents a program
|
||||
public:
|
||||
AstModule(FileLine* fl, const string& name, bool program = false)
|
||||
class Checker {}; // for constructor type-overload selection
|
||||
class Program {}; // for constructor type-overload selection
|
||||
AstModule(FileLine* fl, const string& name)
|
||||
: ASTGEN_SUPER_Module(fl, name) {}
|
||||
AstModule(FileLine* fl, const string& name, Checker)
|
||||
: ASTGEN_SUPER_Module(fl, name)
|
||||
, m_isProgram{program} {}
|
||||
, m_isChecker{true} {}
|
||||
AstModule(FileLine* fl, const string& name, Program)
|
||||
: ASTGEN_SUPER_Module(fl, name)
|
||||
, m_isProgram{true} {}
|
||||
ASTGEN_MEMBERS_AstModule;
|
||||
string verilogKwd() const override { return m_isProgram ? "program" : "module"; }
|
||||
string verilogKwd() const override {
|
||||
return m_isChecker ? "checker" : m_isProgram ? "program" : "module";
|
||||
}
|
||||
bool timescaleMatters() const override { return true; }
|
||||
bool isChecker() const { return m_isChecker; }
|
||||
bool isProgram() const { return m_isProgram; }
|
||||
void dump(std::ostream& str) const override;
|
||||
void dumpJson(std::ostream& str) const override;
|
||||
};
|
||||
class AstNotFoundModule final : public AstNodeModule {
|
||||
// A missing module declaration
|
||||
|
|
@ -3339,6 +3391,24 @@ public:
|
|||
int instrCount() const override { return INSTR_COUNT_PLI; }
|
||||
bool sameNode(const AstNode* /*samep*/) const override { return true; }
|
||||
};
|
||||
class AstSetuphold final : public AstNodeStmt {
|
||||
// Verilog $setuphold
|
||||
// @astgen op1 := refevp : AstNodeExpr
|
||||
// @astgen op2 := dataevp : AstNodeExpr
|
||||
// @astgen op3 := delrefp : Optional[AstNodeExpr]
|
||||
// @astgen op4 := deldatap : Optional[AstNodeExpr]
|
||||
public:
|
||||
AstSetuphold(FileLine* fl, AstNodeExpr* refevp, AstNodeExpr* dataevp,
|
||||
AstNodeExpr* delrefp = nullptr, AstNodeExpr* deldatap = nullptr)
|
||||
: ASTGEN_SUPER_Setuphold(fl) {
|
||||
this->refevp(refevp);
|
||||
this->dataevp(dataevp);
|
||||
this->delrefp(delrefp);
|
||||
this->deldatap(deldatap);
|
||||
}
|
||||
ASTGEN_MEMBERS_AstSetuphold;
|
||||
bool sameNode(const AstNode* /*samep*/) const override { return true; }
|
||||
};
|
||||
class AstStackTraceT final : public AstNodeStmt {
|
||||
// $stacktrace used as task
|
||||
public:
|
||||
|
|
@ -3898,6 +3968,14 @@ public:
|
|||
bool isPure() override { return false; } // SPECIAL: User may order w/other sigs
|
||||
bool isOutputter() override { return true; }
|
||||
};
|
||||
class AstScHdrPost final : public AstNodeText {
|
||||
public:
|
||||
AstScHdrPost(FileLine* fl, const string& textp)
|
||||
: ASTGEN_SUPER_ScHdrPost(fl, textp) {}
|
||||
ASTGEN_MEMBERS_AstScHdrPost;
|
||||
bool isPure() override { return false; } // SPECIAL: User may order w/other sigs
|
||||
bool isOutputter() override { return true; }
|
||||
};
|
||||
class AstScImp final : public AstNodeText {
|
||||
public:
|
||||
AstScImp(FileLine* fl, const string& textp)
|
||||
|
|
|
|||
|
|
@ -848,6 +848,15 @@ const AstNodeDType* AstNodeDType::skipRefIterp(bool skipConst, bool skipEnum,
|
|||
}
|
||||
}
|
||||
|
||||
bool AstNodeDType::similarDType(const AstNodeDType* samep) const {
|
||||
const AstNodeDType* nodep = this;
|
||||
nodep = nodep->skipRefToNonRefp();
|
||||
samep = samep->skipRefToNonRefp();
|
||||
if (nodep == samep) return true;
|
||||
if (nodep->type() != samep->type()) return false;
|
||||
return nodep->similarDTypeNode(samep);
|
||||
}
|
||||
|
||||
bool AstNodeDType::isFourstate() const { return basicp() && basicp()->isFourstate(); }
|
||||
|
||||
class AstNodeDType::CTypeRecursed final {
|
||||
|
|
@ -1007,11 +1016,11 @@ AstNodeDType::CTypeRecursed AstNodeDType::cTypeRecurse(bool compound, bool packe
|
|||
return info;
|
||||
}
|
||||
|
||||
uint32_t AstNodeDType::arrayUnpackedElements() {
|
||||
uint32_t AstNodeDType::arrayUnpackedElements() const {
|
||||
uint32_t entries = 1;
|
||||
for (AstNodeDType* dtypep = this; dtypep;) {
|
||||
for (const AstNodeDType* dtypep = this; dtypep;) {
|
||||
dtypep = dtypep->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node
|
||||
if (AstUnpackArrayDType* const adtypep = VN_CAST(dtypep, UnpackArrayDType)) {
|
||||
if (const AstUnpackArrayDType* const adtypep = VN_CAST(dtypep, UnpackArrayDType)) {
|
||||
entries *= adtypep->elementsConst();
|
||||
dtypep = adtypep->subDTypep();
|
||||
} else {
|
||||
|
|
@ -1852,10 +1861,10 @@ void AstIfaceRefDType::dump(std::ostream& str) const {
|
|||
if (ifaceName() != "") str << " if=" << ifaceName();
|
||||
if (modportName() != "") str << " mp=" << modportName();
|
||||
if (cellp()) {
|
||||
str << " -> ";
|
||||
str << " c-> ";
|
||||
cellp()->dump(str);
|
||||
} else if (ifacep()) {
|
||||
str << " -> ";
|
||||
str << " i-> ";
|
||||
ifacep()->dump(str);
|
||||
} else {
|
||||
str << " -> UNLINKED";
|
||||
|
|
@ -2039,6 +2048,16 @@ void AstModportVarRef::dumpJson(std::ostream& str) const {
|
|||
dumpJsonStr(str, "direction", direction().ascii());
|
||||
dumpJsonGen(str);
|
||||
}
|
||||
void AstModule::dump(std::ostream& str) const {
|
||||
this->AstNodeModule::dump(str);
|
||||
if (isChecker()) str << " [CHECKER]";
|
||||
if (isProgram()) str << " [PROGRAM]";
|
||||
}
|
||||
void AstModule::dumpJson(std::ostream& str) const {
|
||||
dumpJsonBoolFunc(str, isChecker);
|
||||
dumpJsonBoolFunc(str, isProgram);
|
||||
dumpJsonGen(str);
|
||||
}
|
||||
void AstPin::dump(std::ostream& str) const {
|
||||
this->AstNode::dump(str);
|
||||
if (modVarp()) {
|
||||
|
|
@ -2500,6 +2519,7 @@ AstNodeVarRef* AstNodeVarRef::varRefLValueRecurse(AstNode* nodep) {
|
|||
|
||||
void AstVarXRef::dump(std::ostream& str) const {
|
||||
this->AstNodeVarRef::dump(str);
|
||||
if (containsGenBlock()) str << " [GENBLK]";
|
||||
str << ".=" << dotted() << " ";
|
||||
if (inlinedDots() != "") str << " inline.=" << inlinedDots() << " - ";
|
||||
if (varScopep()) {
|
||||
|
|
@ -2511,6 +2531,7 @@ void AstVarXRef::dump(std::ostream& str) const {
|
|||
}
|
||||
}
|
||||
void AstVarXRef::dumpJson(std::ostream& str) const {
|
||||
dumpJsonBoolFunc(str, containsGenBlock);
|
||||
dumpJsonStrFunc(str, dotted);
|
||||
dumpJsonStrFunc(str, inlinedDots);
|
||||
dumpJsonGen(str);
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ public:
|
|||
callp->argTypes("vlSymsp");
|
||||
} else {
|
||||
if (m_type.isCoverage()) callp->argTypes("first");
|
||||
callp->selfPointer(VSelfPointerText{VSelfPointerText::This()});
|
||||
callp->selfPointer(VSelfPointerText{VSelfPointerText::This{}});
|
||||
}
|
||||
rootFuncp->addStmtsp(callp->makeStmt());
|
||||
}
|
||||
|
|
@ -132,12 +132,22 @@ private:
|
|||
class CCtorsVisitor final : public VNVisitor {
|
||||
// NODE STATE
|
||||
|
||||
// STATE
|
||||
// STATE - for current visit position (use VL_RESTORER)
|
||||
AstNodeModule* m_modp = nullptr; // Current module
|
||||
AstCFunc* m_cfuncp = nullptr; // Current function
|
||||
V3CCtorsBuilder* m_varResetp = nullptr; // Builder of _ctor_var_reset
|
||||
|
||||
// VISITs
|
||||
// METHODS
|
||||
static void insertSc(AstCFunc* cfuncp, const AstNodeModule* modp, VNType type) {
|
||||
auto textAndFileline = EmitCBaseVisitorConst::textSection(modp, type);
|
||||
if (!textAndFileline.first.empty()) {
|
||||
AstTextBlock* const newp
|
||||
= new AstTextBlock{textAndFileline.second, textAndFileline.first, false, false};
|
||||
cfuncp->addStmtsp(newp);
|
||||
}
|
||||
}
|
||||
|
||||
// VISITORS
|
||||
void visit(AstNodeModule* nodep) override {
|
||||
VL_RESTORER(m_modp);
|
||||
VL_RESTORER(m_varResetp);
|
||||
|
|
@ -167,6 +177,7 @@ class CCtorsVisitor final : public VNVisitor {
|
|||
// If can be referred to by base pointer, need virtual delete
|
||||
funcp->isVirtual(classp->isExtended());
|
||||
funcp->slow(false);
|
||||
insertSc(funcp, classp, VNType::atScDtor);
|
||||
classp->addStmtsp(funcp);
|
||||
}
|
||||
}
|
||||
|
|
@ -177,6 +188,7 @@ class CCtorsVisitor final : public VNVisitor {
|
|||
m_varResetp = nullptr;
|
||||
m_cfuncp = nodep;
|
||||
iterateChildren(nodep);
|
||||
if (nodep->name() == "new") insertSc(nodep, m_modp, VNType::atScCtor);
|
||||
}
|
||||
void visit(AstVar* nodep) override {
|
||||
if (nodep->needsCReset()) {
|
||||
|
|
@ -223,7 +235,7 @@ void V3CCtors::evalAsserts() {
|
|||
// if (signal & CONST(upper_non_clean_mask)) { fail; }
|
||||
AstVarRef* const vrefp
|
||||
= new AstVarRef{varp->fileline(), varp, VAccess::READ};
|
||||
vrefp->selfPointer(VSelfPointerText{VSelfPointerText::This()});
|
||||
vrefp->selfPointer(VSelfPointerText{VSelfPointerText::This{}});
|
||||
AstNodeExpr* newp = vrefp;
|
||||
if (varp->isWide()) {
|
||||
newp = new AstWordSel{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ class ClassVisitor final : public VNVisitor {
|
|||
const VNUser1InUse m_inuser1;
|
||||
|
||||
// MEMBERS
|
||||
string m_prefix; // String prefix to add to name based on hier
|
||||
string m_prefix; // String prefix to add to class name based on hier
|
||||
V3UniqueNames m_names; // For unique naming of structs and unions
|
||||
AstNodeModule* m_modp = nullptr; // Current module
|
||||
AstNodeModule* m_classPackagep = nullptr; // Package moving into
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ class CleanVisitor final : public VNVisitor {
|
|||
// TYPES
|
||||
enum CleanState : uint8_t { CS_UNKNOWN, CS_CLEAN, CS_DIRTY };
|
||||
|
||||
// STATE
|
||||
// STATE - for current visit position (use VL_RESTORER)
|
||||
const AstNodeModule* m_modp = nullptr;
|
||||
|
||||
// METHODS
|
||||
|
|
|
|||
|
|
@ -68,8 +68,9 @@ public:
|
|||
|
||||
class ClockVisitor final : public VNVisitor {
|
||||
// NODE STATE
|
||||
|
||||
// STATE
|
||||
AstCFunc* m_evalp = nullptr; // The '_eval' function
|
||||
AstCFunc* const m_evalp = nullptr; // The '_eval' function
|
||||
AstSenTree* m_lastSenp = nullptr; // Last sensitivity match, so we can detect duplicates.
|
||||
AstIf* m_lastIfp = nullptr; // Last sensitivity if active to add more under
|
||||
|
||||
|
|
@ -96,7 +97,7 @@ class ClockVisitor final : public VNVisitor {
|
|||
}
|
||||
// VISITORS
|
||||
void visit(AstCoverToggle* nodep) override {
|
||||
// nodep->dumpTree("- ct: ");
|
||||
// if (debug()) nodep->dumpTree("- ct: ");
|
||||
// COVERTOGGLE(INC, ORIG, CHANGE) ->
|
||||
// IF(ORIG ^ CHANGE) { INC; CHANGE = ORIG; }
|
||||
AstNode* const incp = nodep->incp()->unlinkFrBack();
|
||||
|
|
@ -174,8 +175,8 @@ class ClockVisitor final : public VNVisitor {
|
|||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit ClockVisitor(AstNetlist* netlistp) {
|
||||
m_evalp = netlistp->evalp();
|
||||
explicit ClockVisitor(AstNetlist* netlistp)
|
||||
: m_evalp{netlistp->evalp()} {
|
||||
// Simplify all SenTrees
|
||||
for (AstSenTree* senTreep = netlistp->topScopep()->senTreesp(); senTreep;
|
||||
senTreep = VN_AS(senTreep->nextp(), SenTree)) {
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue