Merge from master for release.
This commit is contained in:
commit
0dc93c1d5c
|
|
@ -9,7 +9,7 @@ assignees: ''
|
||||||
|
|
||||||
Thanks for taking the time to report this.
|
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?
|
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?
|
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?
|
May we assist you in trying to fix this in Verilator yourself?
|
||||||
|
|
|
||||||
|
|
@ -12,15 +12,6 @@ on:
|
||||||
schedule:
|
schedule:
|
||||||
- cron: '0 0 * * 0' # weekly
|
- 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:
|
defaults:
|
||||||
run:
|
run:
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|
@ -32,134 +23,155 @@ concurrency:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
|
||||||
build:
|
build-2404-gcc:
|
||||||
|
name: Build
|
||||||
|
uses: ./.github/workflows/reusable-build.yml
|
||||||
|
with:
|
||||||
|
os: ${{ matrix.os }}
|
||||||
|
cc: ${{ matrix.cc }}
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
os: [ubuntu-24.04, ubuntu-22.04, ubuntu-20.04]
|
|
||||||
compiler:
|
|
||||||
- {cc: clang, cxx: clang++}
|
|
||||||
- {cc: gcc, cxx: g++}
|
|
||||||
include:
|
include:
|
||||||
# Build GCC 10 on ubuntu-20.04
|
- {os: ubuntu-24.04, cc: gcc}
|
||||||
- os: ubuntu-20.04
|
|
||||||
compiler: {cc: gcc-10, cxx: g++-10}
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
name: Build | ${{ matrix.os }} | ${{ matrix.compiler.cc }}
|
|
||||||
env:
|
|
||||||
CI_BUILD_STAGE_NAME: build
|
|
||||||
CI_RUNS_ON: ${{ matrix.os }}
|
|
||||||
CC: ${{ matrix.compiler.cc }}
|
|
||||||
CXX: ${{ matrix.compiler.cxx }}
|
|
||||||
CACHE_BASE_KEY: build-${{ matrix.os }}-${{ matrix.compiler.cc }}
|
|
||||||
CCACHE_MAXSIZE: 1000M # Per build matrix entry (* 5 = 5000M in total)
|
|
||||||
VERILATOR_ARCHIVE: verilator-${{ github.sha }}-${{ matrix.os }}-${{ matrix.compiler.cc }}.tar.gz
|
|
||||||
steps:
|
|
||||||
|
|
||||||
- name: Checkout
|
build-2404-clang:
|
||||||
uses: actions/checkout@v4
|
name: Build
|
||||||
|
uses: ./.github/workflows/reusable-build.yml
|
||||||
with:
|
with:
|
||||||
path: repo
|
os: ${{ matrix.os }}
|
||||||
|
cc: ${{ matrix.cc }}
|
||||||
- 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
|
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
os: [ubuntu-22.04, ubuntu-20.04]
|
|
||||||
compiler:
|
|
||||||
- {cc: clang, cxx: clang++}
|
|
||||||
- {cc: gcc, cxx: g++}
|
|
||||||
reloc: [0]
|
|
||||||
suite: [dist-vlt-0, dist-vlt-1, dist-vlt-2, dist-vlt-3, vltmt-0, vltmt-1]
|
|
||||||
include:
|
include:
|
||||||
# Test with GCC 10 on ubuntu-20.04, also test relocation
|
- {os: ubuntu-24.04, cc: clang}
|
||||||
- {os: ubuntu-20.04, compiler: {cc: gcc-10, cxx: g++-10}, reloc: 1, suite: dist-vlt-0}
|
|
||||||
- {os: ubuntu-20.04, compiler: {cc: gcc-10, cxx: g++-10}, reloc: 1, suite: dist-vlt-1}
|
|
||||||
- {os: ubuntu-20.04, compiler: {cc: gcc-10, cxx: g++-10}, reloc: 1, suite: dist-vlt-2}
|
|
||||||
- {os: ubuntu-20.04, compiler: {cc: gcc-10, cxx: g++-10}, reloc: 1, suite: dist-vlt-3}
|
|
||||||
- {os: ubuntu-20.04, compiler: {cc: gcc-10, cxx: g++-10}, reloc: 1, suite: vltmt-0}
|
|
||||||
- {os: ubuntu-20.04, compiler: {cc: gcc-10, cxx: g++-10}, reloc: 1, suite: vltmt-1}
|
|
||||||
# Ubuntu 24.04 only on GCC; not passing on clang yet
|
|
||||||
- {os: ubuntu-24.04, compiler: {cc: gcc, cxx: g++}, suite: dist-vlt-0}
|
|
||||||
- {os: ubuntu-24.04, compiler: {cc: gcc, cxx: g++}, suite: dist-vlt-1}
|
|
||||||
- {os: ubuntu-24.04, compiler: {cc: gcc, cxx: g++}, suite: dist-vlt-2}
|
|
||||||
- {os: ubuntu-24.04, compiler: {cc: gcc, cxx: g++}, suite: dist-vlt-3}
|
|
||||||
- {os: ubuntu-24.04, compiler: {cc: gcc, cxx: g++}, suite: vltmt-0}
|
|
||||||
- {os: ubuntu-24.04, compiler: {cc: gcc, cxx: g++}, suite: vltmt-1}
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
name: Test | ${{ matrix.os }} | ${{ matrix.compiler.cc }} | ${{ matrix.reloc && 'reloc | ' || '' }} ${{ matrix.suite }}
|
|
||||||
env:
|
|
||||||
CI_BUILD_STAGE_NAME: test
|
|
||||||
CI_RUNS_ON: ${{ matrix.os }}
|
|
||||||
CI_RELOC: ${{ matrix.reloc }}
|
|
||||||
CC: ${{ matrix.compiler.cc }}
|
|
||||||
CXX: ${{ matrix.compiler.cxx }}
|
|
||||||
CACHE_BASE_KEY: test-${{ matrix.os }}-${{ matrix.compiler.cc }}-${{ matrix.reloc }}-${{ matrix.suite }}
|
|
||||||
CCACHE_MAXSIZE: 100M # Per build per suite (* 5 * 5 = 2500M in total)
|
|
||||||
VERILATOR_ARCHIVE: verilator-${{ github.sha }}-${{ matrix.os }}-${{ matrix.compiler.cc }}.tar.gz
|
|
||||||
steps:
|
|
||||||
|
|
||||||
- name: Download tar archive
|
build-2204-gcc:
|
||||||
uses: actions/download-artifact@v4
|
name: Build
|
||||||
|
uses: ./.github/workflows/reusable-build.yml
|
||||||
with:
|
with:
|
||||||
name: ${{ env.VERILATOR_ARCHIVE }}
|
os: ${{ matrix.os }}
|
||||||
path: ${{ github.workspace }}
|
cc: ${{ matrix.cc }}
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- {os: ubuntu-22.04, cc: gcc}
|
||||||
|
|
||||||
- name: Unpack tar archive
|
build-2204-clang:
|
||||||
working-directory: ${{ github.workspace }}
|
name: Build
|
||||||
run: tar -x -z -f ${{ env.VERILATOR_ARCHIVE }}
|
uses: ./.github/workflows/reusable-build.yml
|
||||||
|
|
||||||
- name: Cache $CCACHE_DIR
|
|
||||||
uses: actions/cache@v4
|
|
||||||
env:
|
|
||||||
CACHE_KEY: ${{ env.CACHE_BASE_KEY }}-ccache2
|
|
||||||
with:
|
with:
|
||||||
path: ${{ env.CCACHE_DIR }}
|
os: ${{ matrix.os }}
|
||||||
key: ${{ env.CACHE_KEY }}-${{ github.sha }}
|
cc: ${{ matrix.cc }}
|
||||||
restore-keys: |
|
strategy:
|
||||||
${{ env.CACHE_KEY }}-
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- {os: ubuntu-22.04, cc: clang}
|
||||||
|
|
||||||
- name: Install test dependencies
|
test-2404-gcc:
|
||||||
run: ./ci/ci-install.bash
|
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
|
test-2404-clang:
|
||||||
env:
|
name: Test | ${{ matrix.os }} | ${{ matrix.cc }}
|
||||||
TESTS: ${{ matrix.suite }}
|
needs: build-2404-clang
|
||||||
run: ./ci/ci-script.bash
|
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:
|
lint-py:
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
name: Lint Python
|
name: Lint Python
|
||||||
env:
|
env:
|
||||||
|
CI_OS_NAME: linux
|
||||||
|
CI_COMMIT: ${{ github.sha }}
|
||||||
CI_BUILD_STAGE_NAME: build
|
CI_BUILD_STAGE_NAME: build
|
||||||
CI_RUNS_ON: ubuntu-22.04
|
CI_RUNS_ON: ubuntu-22.04
|
||||||
|
CCACHE_COMPRESS: 1
|
||||||
|
CCACHE_DIR: ${{ github.workspace }}/.ccache
|
||||||
|
CCACHE_LIMIT_MULTIPLE: 0.95
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
|
||||||
|
|
@ -76,11 +76,11 @@ jobs:
|
||||||
|
|
||||||
- name: Build and Push to Docker
|
- name: Build and Push to Docker
|
||||||
uses: docker/build-push-action@v4
|
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:
|
with:
|
||||||
context: ${{ env.build_context }}
|
context: ${{ env.build_context }}
|
||||||
build-args: SOURCE_COMMIT=${{ env.git_tag }}
|
build-args: SOURCE_COMMIT=${{ env.git_tag }}
|
||||||
platforms: linux/arm64,linux/amd64
|
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 }}
|
tags: ${{ steps.docker_meta.outputs.tags }}
|
||||||
labels: ${{ steps.docker_meta.outputs.labels }}
|
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
|
cmake_policy(SET CMP0091 NEW) # Use MSVC_RUNTIME_LIBRARY to select the runtime
|
||||||
project(
|
project(
|
||||||
Verilator
|
Verilator
|
||||||
VERSION 5.034
|
VERSION 5.036
|
||||||
HOMEPAGE_URL https://verilator.org
|
HOMEPAGE_URL https://verilator.org
|
||||||
LANGUAGES CXX
|
LANGUAGES CXX
|
||||||
)
|
)
|
||||||
|
|
@ -134,10 +134,7 @@ configure_package_config_file(
|
||||||
INSTALL_DESTINATION .
|
INSTALL_DESTINATION .
|
||||||
)
|
)
|
||||||
|
|
||||||
install(
|
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/verilator-config.cmake DESTINATION .)
|
||||||
FILES ${CMAKE_CURRENT_BINARY_DIR}/verilator-config.cmake
|
|
||||||
DESTINATION .
|
|
||||||
)
|
|
||||||
|
|
||||||
configure_package_config_file(
|
configure_package_config_file(
|
||||||
verilator-config-version.cmake.in
|
verilator-config-version.cmake.in
|
||||||
|
|
|
||||||
117
Changes
117
Changes
|
|
@ -8,6 +8,87 @@ The changes in each Verilator version are described below. The
|
||||||
contributors that suggested a given feature are shown in []. Thanks!
|
contributors that suggested a given feature are shown in []. Thanks!
|
||||||
|
|
||||||
|
|
||||||
|
Verilator 5.036 2025-04-27
|
||||||
|
==========================
|
||||||
|
|
||||||
|
**Important:**
|
||||||
|
|
||||||
|
* Change `--output-groups` to default to value of `--build-jobs` (#5751).
|
||||||
|
Those using build farms may need to now use `--output-groups 0` or otherwise.
|
||||||
|
* Support user-defined primitives (UDPs) (#468) (#5807) (#5936). [Zhou Shen, Krzysztof Sychla, et al]
|
||||||
|
* Add `--trace-saif` for SAIF power traces (#5812) (#5914). [Mateusz Gancarz]
|
||||||
|
|
||||||
|
**Other:**
|
||||||
|
|
||||||
|
* Change `--trace` to `--trace-vcd`.
|
||||||
|
* Support simple `checker` blocks (#4066). [Srinivasan Venkataramanan]
|
||||||
|
* Support force/release with a variable reference (#5721) (#5810). [Bartłomiej Chmiel, Antmicro Ltd.]
|
||||||
|
* Support constraint random for StructArray (#5805) (#5937). [Yilou Wang]
|
||||||
|
* Support command-line overriding `define (#5900) (#5908). [Brian Li]
|
||||||
|
* Support soft unions (#5912) (#5932). [Robin Heinemann]
|
||||||
|
* Support `$setuphold` (#5884). [Krzysztof Sychla]
|
||||||
|
* Support assigning unpacked arrays to queues (#5924) (#5928). [Brian Li]
|
||||||
|
* Support `systemc_interface and related inside `class`.
|
||||||
|
* Support class extends with arguments.
|
||||||
|
* Add multi-thread hierarchical simulation (#2583) (#5871). [Bartłomiej Chmiel, Antmicro Ltd.]
|
||||||
|
* Add check for `let` misused in statement context (#5733).
|
||||||
|
* Add used language to `--preproc-resolve` output (#5795). [Kamil Rakoczy, Antmicro Ltd.]
|
||||||
|
* Add `--make json` to enable integration with non-make/cmake build systems (#5799). [Andrew Voznytsa]
|
||||||
|
* Add numactl-like automatic assignment of processor affinity (#5911).
|
||||||
|
* Add ccache support for generated cmake files (#5926) (#5930). [Andrew Voznytsa]
|
||||||
|
* Add visualization of multi-threaded waiting time with verilator_gantt (#5929). [Bartłomiej Chmiel, Antmicro Ltd.]
|
||||||
|
* Add suggesting isolate_assignments to UNOPTFLAT (#5942). [John Khoo]
|
||||||
|
* Add profiling of hierarchical mtasks with verilator_gantt (#5956). [Bartłomiej Chmiel, Antmicro Ltd.]
|
||||||
|
* Add empty veriuser.h for legacy compatibility.
|
||||||
|
* Add DEPRECATED warning on `--xml-only` and `--xml-output`.
|
||||||
|
* Remove unused gtkwave/wavealloca.h. [Geza Lore]
|
||||||
|
* Optimize automatic splitting of some packed variables (#5843). [Geza Lore]
|
||||||
|
* Optimize trigger vector in whole words (#5857). [Geza Lore]
|
||||||
|
* Fix parameters referencing interface fields (#1593) (#5910). [Ryszard Rozak, Antmicro Ltd.]
|
||||||
|
* Fix interface array assignments (#5270) (#5633) (#5869). [Nick Brereton]
|
||||||
|
* Fix change detection at time 0 (#5499) (#5864). [Geza Lore]
|
||||||
|
* Fix foreach of associative array inside a constraint block (#5727) (#5841). [Yilou Wang]
|
||||||
|
* Fix reset of automatic function variables (#5747). [Augustin Fabre]
|
||||||
|
* Fix invalid code motion over branches (#5811) (#5814). [Geza Lore]
|
||||||
|
* Fix sorting of wide SenItems (#5816). [Geza Lore]
|
||||||
|
* Fix tcmalloc static link and non-22.04 builds (#5817) (#5818). [Geza Lore]
|
||||||
|
* Fix error on out-of-range lvalue part select (#5820).
|
||||||
|
* Fix UNOPTFLAT warnings with `--coverage-trace` and always_comb (#5821).
|
||||||
|
* Fix function locals in SenExprBuilder (#5822). [Geza Lore]
|
||||||
|
* Fix type_id package scope resolution (#5826). [Krzysztof Bieganski, Antmicro Ltd.]
|
||||||
|
* Fix `rand_mode` method with cast (#5831).
|
||||||
|
* Fix invalidating variable caches in SenExprBulider (#5834) (#5835). [Geza Lore]
|
||||||
|
* Fix assignment pattern as function argument (#5839).
|
||||||
|
* Fix checking built-in method arguments (#5839).
|
||||||
|
* Fix splitting of packed ports with non-zero based ranges (#5842). [Geza Lore]
|
||||||
|
* Fix delays inside interface functions, and classes inside interfaces (#5846).
|
||||||
|
* Fix NBA shared flag reuse (#5848). [Geza Lore]
|
||||||
|
* Fix multiple expression coverage issues (#5849 partial) (#5867) (#5870). [Todd Strader]
|
||||||
|
* Fix unresolved typedefs as parameters (#5850). [Eugene Feinberg, Brian Li]
|
||||||
|
* Fix removal of callbacks no longer in current list (#5851) (#5852). [Gilberto Abram]
|
||||||
|
* Fix segmentation fault on member compare (#5853).
|
||||||
|
* Fix recursive error on virtual interfaces (#5854). [Yilou Wang]
|
||||||
|
* Fix streaming of unpacked arrays concatenations (#5856). [Ryszard Rozak, Antmicro Ltd.]
|
||||||
|
* Fix Windows paths in Perl (#5858) (#5860). [Tobias Jensen]
|
||||||
|
* Fix algorithm header portability in V3Os.cpp (for std::replace) (#5861). [William D. Jones]
|
||||||
|
* Fix `$fscanf` not returning -1 on EOF (#5881).
|
||||||
|
* Fix PGO profiling for multi-threaded hierarchical scenarios (#5888). [Bartłomiej Chmiel, Antmicro Ltd.]
|
||||||
|
* Fix V3Gate assertion on eliminated circular logic (#5889) (#5898). [Geza Lore]
|
||||||
|
* Fix process comparisons (#5896).
|
||||||
|
* Fix ccache with clang (#5899). [Geza Lore]
|
||||||
|
* Fix delayed assignment malformed LHS assertion (#5904).
|
||||||
|
* Fix segfault in fork synchronization (#5906). [Krzysztof Bieganski, Antmicro Ltd.]
|
||||||
|
* Fix `new this` (#5909).
|
||||||
|
* Fix assignments with stream expressions and unpacked arrays (#5915). [Ryszard Rozak, Antmicro Ltd.]
|
||||||
|
* Fix LATCH warning for automatic variables (#5918). [Yutetsu TAKATSUKASA]
|
||||||
|
* Fix %% on elaboration severity tasks (#5922). [Ethan Sifferman]
|
||||||
|
* Fix port default values with `--coverage-line` creating `0=0` (#5920). [Drew Ranck]
|
||||||
|
* Fix vlSelf error on fork repeats (#5927). [Drew Ranck]
|
||||||
|
* Fix missing C++ regeneration when Verilog files are updated (#5934). [Zhouyi Shen]
|
||||||
|
* Fix stream expressions (#5938). [Ryszard Rozak, Antmicro Ltd.]
|
||||||
|
* Fix packed selection using over 32-bit index (#5957).
|
||||||
|
|
||||||
|
|
||||||
Verilator 5.034 2025-02-24
|
Verilator 5.034 2025-02-24
|
||||||
==========================
|
==========================
|
||||||
|
|
||||||
|
|
@ -195,7 +276,7 @@ Verilator 5.030 2024-10-27
|
||||||
* Fix short-circuiting with associative array access (#5484). [Ethan Sifferman]
|
* Fix short-circuiting with associative array access (#5484). [Ethan Sifferman]
|
||||||
* Fix short-circuiting on method calls (#5486). [Ethan Sifferman]
|
* Fix short-circuiting on method calls (#5486). [Ethan Sifferman]
|
||||||
* Fix exponential concatenate performance (#5488). [Arkadiusz Kozdra, Antmicro Ltd.]
|
* Fix exponential concatenate performance (#5488). [Arkadiusz Kozdra, Antmicro Ltd.]
|
||||||
* Fix V3Table trying to generate 'x' bits in the lookup table. (#5491). [Geza Lore]
|
* Fix V3Table trying to generate 'x' bits in the lookup table (#5491). [Geza Lore]
|
||||||
* Fix randomize with foreach constraints (#5492). [Arkadiusz Kozdra, Antmicro Ltd.]
|
* Fix randomize with foreach constraints (#5492). [Arkadiusz Kozdra, Antmicro Ltd.]
|
||||||
* Fix explicit CMAKE_INSTALL_PREFIX usages (#5500). [Fabian Keßler]
|
* Fix explicit CMAKE_INSTALL_PREFIX usages (#5500). [Fabian Keßler]
|
||||||
* Fix configure inserting absolute paths for Python and Perl (#5504) (#5505). [Nathan Graybeal]
|
* Fix configure inserting absolute paths for Python and Perl (#5504) (#5505). [Nathan Graybeal]
|
||||||
|
|
@ -253,7 +334,7 @@ Verilator 5.028 2024-08-21
|
||||||
* Add parsing but otherwise ignore std::randomize (#5354). [Arkadiusz Kozdra, Antmicro Ltd.]
|
* Add parsing but otherwise ignore std::randomize (#5354). [Arkadiusz Kozdra, Antmicro Ltd.]
|
||||||
* Add Verilated cc define when `--timing` used (#5383). [Kaleb Barrett]
|
* Add Verilated cc define when `--timing` used (#5383). [Kaleb Barrett]
|
||||||
* Improve emitted code to use a reference for VlSelf (#5254). [Yangyu Chen]
|
* 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 fusing macro arguments to not ignore whitespace (#5061). [Tudor Timi]
|
||||||
* Fix optimized-out sensitivity trees with `--timing` (#5080) (#5349). [Krzysztof Bieganski, Antmicro Ltd.]
|
* Fix optimized-out sensitivity trees with `--timing` (#5080) (#5349). [Krzysztof Bieganski, Antmicro Ltd.]
|
||||||
* Fix classes/modules of case-similar names (#5109). [Arkadiusz Kozdra]
|
* Fix classes/modules of case-similar names (#5109). [Arkadiusz Kozdra]
|
||||||
|
|
@ -280,7 +361,7 @@ Verilator 5.028 2024-08-21
|
||||||
* Fix static variable initializers in procedures (#5296). [Bartłomiej Chmiel, Antmicro Ltd.]
|
* Fix static variable initializers in procedures (#5296). [Bartłomiej Chmiel, Antmicro Ltd.]
|
||||||
* Fix randomizing current object with `rand` class instance member (#5292). [Krzysztof Bieganski, Antmicro Ltd.]
|
* Fix randomizing current object with `rand` class instance member (#5292). [Krzysztof Bieganski, Antmicro Ltd.]
|
||||||
* Fix handling of rand fields not referenced in constraints (#5305). [Ryszard Rozak, Antmicro Ltd.]
|
* Fix handling of rand fields not referenced in constraints (#5305). [Ryszard Rozak, Antmicro Ltd.]
|
||||||
* Fix Python3 path discovery in make flows to avoid mixing system and user python interpreters (#5307) [Markus Krause]
|
* Fix Python3 path discovery in make flows to avoid mixing system and user python interpreters (#5307). [Markus Krause]
|
||||||
* Fix make flows to pass PYTHON3 (like PERL) (#5307) (#5308). [Markus Krause]
|
* Fix make flows to pass PYTHON3 (like PERL) (#5307) (#5308). [Markus Krause]
|
||||||
* Fix assert on wide expression (#5319) (#5324). [Varun Koyyalagunta]
|
* Fix assert on wide expression (#5319) (#5324). [Varun Koyyalagunta]
|
||||||
* Fix output clock variable overwriting signal (#5320) (#5347). [Krzysztof Bieganski, Antmicro Ltd.]
|
* Fix output clock variable overwriting signal (#5320) (#5347). [Krzysztof Bieganski, Antmicro Ltd.]
|
||||||
|
|
@ -459,7 +540,7 @@ Verilator 5.022 2024-02-24
|
||||||
* Fix `vpi_get()` and `vpi_get64()` to return vpiUndefined on errors (#4795). [Marlon James]
|
* Fix `vpi_get()` and `vpi_get64()` to return vpiUndefined on errors (#4795). [Marlon James]
|
||||||
* Fix VPI parameter iteration (#4798). [Marlon James]
|
* Fix VPI parameter iteration (#4798). [Marlon James]
|
||||||
* Fix delays using wrong timeunit when modules inlined (#4806). [Paul Wright]
|
* Fix delays using wrong timeunit when modules inlined (#4806). [Paul Wright]
|
||||||
* Fix warnings in verilated_sc_trace.h for Clang. (#4807) (#4827). [Anthony Donlon]
|
* Fix warnings in verilated_sc_trace.h for Clang (#4807) (#4827). [Anthony Donlon]
|
||||||
* Fix null pointer dereference (#4810) (#4825). [Adrian Sampson]
|
* Fix null pointer dereference (#4810) (#4825). [Adrian Sampson]
|
||||||
* Fix compilation error on multi-inherited interface class usage (#4819).
|
* Fix compilation error on multi-inherited interface class usage (#4819).
|
||||||
* Fix maybe-uninitialized compiler warning (#4820) (#4822). [Larry Doolittle]
|
* Fix maybe-uninitialized compiler warning (#4820) (#4822). [Larry Doolittle]
|
||||||
|
|
@ -537,7 +618,7 @@ Verilator 5.020 2024-01-01
|
||||||
* Fix conflicted namespace for coroutines (#4701) (#4707). [Jinyan Xu]
|
* Fix conflicted namespace for coroutines (#4701) (#4707). [Jinyan Xu]
|
||||||
* Fix compilers seeing empty input due to file system races (#4708). [Flavien Solt]
|
* Fix compilers seeing empty input due to file system races (#4708). [Flavien Solt]
|
||||||
* Fix shift of > 32-bit number (#4719). [Flavien Solt]
|
* Fix shift of > 32-bit number (#4719). [Flavien Solt]
|
||||||
* Fix Windows include gates in filesystem Flush implementation. (#4720). [William D. Jones]
|
* Fix Windows include gates in filesystem Flush implementation (#4720). [William D. Jones]
|
||||||
* Fix power operator with wide numbers and constants (#4721) (#4763). [Flavien Solt]
|
* Fix power operator with wide numbers and constants (#4721) (#4763). [Flavien Solt]
|
||||||
* Fix parameter passing to ports (#4723). [Ryszard Rozak, Antmicro Ltd.]
|
* Fix parameter passing to ports (#4723). [Ryszard Rozak, Antmicro Ltd.]
|
||||||
* Fix block names of nested do..while loops (#4728). [Ryszard Rozak, Antmicro Ltd.]
|
* Fix block names of nested do..while loops (#4728). [Ryszard Rozak, Antmicro Ltd.]
|
||||||
|
|
@ -546,7 +627,7 @@ Verilator 5.020 2024-01-01
|
||||||
* Fix $finish twice to no longer exit (#4757). [Tim Hutt]
|
* Fix $finish twice to no longer exit (#4757). [Tim Hutt]
|
||||||
* Fix dynamic NBA conditions (#4773). [Krzysztof Bieganski, Antmicro Ltd.]
|
* Fix dynamic NBA conditions (#4773). [Krzysztof Bieganski, Antmicro Ltd.]
|
||||||
* Fix `V3Fork` stage to run only if `--timing` is set (#4778). [Krzysztof Bieganski, Antmicro Ltd.]
|
* Fix `V3Fork` stage to run only if `--timing` is set (#4778). [Krzysztof Bieganski, Antmicro Ltd.]
|
||||||
* Fix max multiply width and add runtime assertions if too small. (#4781)
|
* Fix max multiply width and add runtime assertions if too small (#4781).
|
||||||
* Fix select value too wide (#5148) (#5153). [Dercury]
|
* Fix select value too wide (#5148) (#5153). [Dercury]
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1211,7 +1292,7 @@ Verilator 4.218 2022-01-17
|
||||||
|
|
||||||
* Support class static members (#2233).
|
* Support class static members (#2233).
|
||||||
* Support force/release (#2431) (#2593). [Shunyao CAD]
|
* Support force/release (#2431) (#2593). [Shunyao CAD]
|
||||||
* Add 'forceable' attribute to allow forcing from C++. (#3272). [Geza Lore, Shunyao CAD]
|
* Add 'forceable' attribute to allow forcing from C++ (#3272). [Geza Lore, Shunyao CAD]
|
||||||
* Support lower dimension looping in foreach loops (#3172). [Ehab Ibrahim]
|
* Support lower dimension looping in foreach loops (#3172). [Ehab Ibrahim]
|
||||||
* Support up to 64 bit enums for .next/.prev/.name (#3244). [Alexander Grobman]
|
* Support up to 64 bit enums for .next/.prev/.name (#3244). [Alexander Grobman]
|
||||||
* Reduce .rodata footprint of trace initialization (#3250). [Geza Lore, Shunyao CAD]
|
* Reduce .rodata footprint of trace initialization (#3250). [Geza Lore, Shunyao CAD]
|
||||||
|
|
@ -1435,7 +1516,7 @@ Verilator 4.200 2021-03-12
|
||||||
**Major:**
|
**Major:**
|
||||||
|
|
||||||
* Add simulation context (VerilatedContext) to allow multiple fully independent
|
* Add simulation context (VerilatedContext) to allow multiple fully independent
|
||||||
models to be in the same process. Please see the updated examples. (#2660)
|
models to be in the same process. Please see the updated examples (#2660).
|
||||||
* Add context->time() and context->timeInc() API calls, to set simulation time.
|
* Add context->time() and context->timeInc() API calls, to set simulation time.
|
||||||
These now are recommended in place of the legacy sc_time_stamp().
|
These now are recommended in place of the legacy sc_time_stamp().
|
||||||
|
|
||||||
|
|
@ -1446,7 +1527,7 @@ Verilator 4.200 2021-03-12
|
||||||
* Fix slice-assign overflow (#2803) (#2811). [David Turner]
|
* Fix slice-assign overflow (#2803) (#2811). [David Turner]
|
||||||
* Fix interface array connection ordering broken in v4.110 (#2827). [Don Owen]
|
* Fix interface array connection ordering broken in v4.110 (#2827). [Don Owen]
|
||||||
* Fix or-reduction on different scopes broken in 4.110 (#2828). [Yinan Xu]
|
* Fix or-reduction on different scopes broken in 4.110 (#2828). [Yinan Xu]
|
||||||
* Fix MSVC++ compile error. (#2831) (#2833) [Drew Taussig]
|
* Fix MSVC++ compile error (#2831) (#2833). [Drew Taussig]
|
||||||
|
|
||||||
|
|
||||||
Verilator 4.110 2021-02-25
|
Verilator 4.110 2021-02-25
|
||||||
|
|
@ -1501,7 +1582,7 @@ Verilator 4.108 2021-01-10
|
||||||
* Fix vpiLeftRange on little-endian memories (#2696). [Marlon James]
|
* Fix vpiLeftRange on little-endian memories (#2696). [Marlon James]
|
||||||
* Fix VPI module tree (#2704). [Todd Strader]
|
* Fix VPI module tree (#2704). [Todd Strader]
|
||||||
* Fix vpi_release_handle to be called implicitly per IEEE (#2706).
|
* Fix vpi_release_handle to be called implicitly per IEEE (#2706).
|
||||||
* Fix to allow inheriting 'VerilatedVcdFile' class. (#2720) [HyungKi Jeong]
|
* Fix to allow inheriting 'VerilatedVcdFile' class (#2720). [HyungKi Jeong]
|
||||||
* Fix $urandom_range maximum value (#2723). [Nandu Raj]
|
* Fix $urandom_range maximum value (#2723). [Nandu Raj]
|
||||||
* Fix tracing empty sc module (#2729).
|
* Fix tracing empty sc module (#2729).
|
||||||
* Fix generate for unrolling to be signed (#2730). [yanx21]
|
* Fix generate for unrolling to be signed (#2730). [yanx21]
|
||||||
|
|
@ -1607,11 +1688,11 @@ Verilator 4.040 2020-08-15
|
||||||
**Minor:**
|
**Minor:**
|
||||||
|
|
||||||
* Fix arrayed interfaces, broke in 4.038 (#2468). [Josh Redford]
|
* Fix arrayed interfaces, broke in 4.038 (#2468). [Josh Redford]
|
||||||
* Support $stable, $rose and $fell. (#2148) (#2501) [Peter Monsson]
|
* Support $stable, $rose and $fell (#2148) (#2501). [Peter Monsson]
|
||||||
* Support simple function localparams (#2461). [James Hanlon]
|
* Support simple function localparams (#2461). [James Hanlon]
|
||||||
* Miscellaneous parsing error changes towards UVM support.
|
* Miscellaneous parsing error changes towards UVM support.
|
||||||
* Fix arrayed interfaces (#2469). [Josh Redford]
|
* Fix arrayed interfaces (#2469). [Josh Redford]
|
||||||
* Fix protect lib VCS warning. (#2479) [Julien Margetts]
|
* Fix protect lib VCS warning (#2479). [Julien Margetts]
|
||||||
* Fix combining different-width parameters (#2484). [abirkmanis]
|
* Fix combining different-width parameters (#2484). [abirkmanis]
|
||||||
* Fix protect-lib without sequential logic (#2492). [Yutetsu TAKATSUKASA]
|
* Fix protect-lib without sequential logic (#2492). [Yutetsu TAKATSUKASA]
|
||||||
* Fix V3Unknown from running with flat XML output (#2494). [James Hanlon]
|
* Fix V3Unknown from running with flat XML output (#2494). [James Hanlon]
|
||||||
|
|
@ -1667,16 +1748,16 @@ Verilator 4.036 2020-06-06
|
||||||
waivers to the warnings emitted during a Verilator run.
|
waivers to the warnings emitted during a Verilator run.
|
||||||
* Support verilator_coverage --write-info for lcov HTML reports.
|
* Support verilator_coverage --write-info for lcov HTML reports.
|
||||||
* Line Coverage now tracks all statement lines, not just branch lines.
|
* Line Coverage now tracks all statement lines, not just branch lines.
|
||||||
* The run-time library is now compiled with -Os by default. (#2369, #2373)
|
* The run-time library is now compiled with -Os by default (#2369, #2373).
|
||||||
* Support multi channel descriptor I/O (#2190) [Stephen Henry]
|
* Support multi channel descriptor I/O (#2190) [Stephen Henry]
|
||||||
* Support $countbits. (#2287) [Yossi Nivin]
|
* Support $countbits (#2287). [Yossi Nivin]
|
||||||
* Support $isunbounded and parameter $. (#2104)
|
* Support $isunbounded and parameter $ (#2104).
|
||||||
* Support unpacked array .sum and .product.
|
* Support unpacked array .sum and .product.
|
||||||
* Support prefix/postfix increment/decrement. (#2223) [Maciej Sobkowski]
|
* Support prefix/postfix increment/decrement (#2223). [Maciej Sobkowski]
|
||||||
* Fix FST tracing of little bit endian signals. [Geza Lore]
|
* Fix FST tracing of little bit endian signals. [Geza Lore]
|
||||||
* Fix +: and -: on unpacked arrays. (#2304) [engr248]
|
* Fix +: and -: on unpacked arrays (#2304). [engr248]
|
||||||
* Fix $isunknown with constant Z's.
|
* Fix $isunknown with constant Z's.
|
||||||
* Fix queues and dynamic array wide ops. (#2352) [Vassilis Papaefstathiou]
|
* Fix queues and dynamic array wide ops (#2352). [Vassilis Papaefstathiou]
|
||||||
|
|
||||||
|
|
||||||
Verilator 4.034 2020-05-03
|
Verilator 4.034 2020-05-03
|
||||||
|
|
|
||||||
|
|
@ -528,6 +528,8 @@ GERSEMI_FLAGS = -i
|
||||||
format-cmake:
|
format-cmake:
|
||||||
$(GERSEMI) $(GERSEMI_FLAGS) $(CMAKE_FILES)
|
$(GERSEMI) $(GERSEMI_FLAGS) $(CMAKE_FILES)
|
||||||
|
|
||||||
|
format-yaml: yamlfix
|
||||||
|
|
||||||
PYLINT = pylint
|
PYLINT = pylint
|
||||||
PYLINT_FLAGS = --recursive=n --score=n --disable=R0801
|
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
|
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 -f *.tex
|
||||||
rm -rf examples/*/obj_dir* examples/*/logs
|
rm -rf examples/*/obj_dir* examples/*/logs
|
||||||
rm -rf test_*/obj_dir
|
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/fuzzer/dictionary
|
||||||
rm -rf nodist/obj_dir
|
rm -rf nodist/obj_dir
|
||||||
rm -rf verilator.txt
|
rm -rf verilator.txt
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
.. Github doesn't render images unless absolute URL
|
.. Github doesn't render images unless absolute URL
|
||||||
.. Do not know of a conditional tag, "only: github" nor "github display" works
|
.. Do not know of a conditional tag, "only: github" nor "github display" works
|
||||||
|
|
||||||
|badge1| |badge2| |badge3| |badge4| |badge5| |badge6| |badge7|
|
|badge1| |badge2| |badge3| |badge4| |badge5| |badge7|
|
||||||
|
|
||||||
.. |badge1| image:: https://img.shields.io/badge/Website-Verilator.org-181717.svg
|
.. |badge1| image:: https://img.shields.io/badge/Website-Verilator.org-181717.svg
|
||||||
:target: https://verilator.org
|
:target: https://verilator.org
|
||||||
|
|
@ -13,8 +13,6 @@
|
||||||
:target: https://repology.org/project/verilator/versions
|
:target: https://repology.org/project/verilator/versions
|
||||||
.. |badge5| image:: https://img.shields.io/docker/pulls/verilator/verilator
|
.. |badge5| image:: https://img.shields.io/docker/pulls/verilator/verilator
|
||||||
:target: https://hub.docker.com/r/verilator/verilator
|
:target: https://hub.docker.com/r/verilator/verilator
|
||||||
.. |badge6| image:: https://api.codacy.com/project/badge/Grade/fa78caa433c84a4ab9049c43e9debc6f
|
|
||||||
:target: https://www.codacy.com/gh/verilator/verilator
|
|
||||||
.. |badge7| image:: https://github.com/verilator/verilator/workflows/build/badge.svg
|
.. |badge7| image:: https://github.com/verilator/verilator/workflows/build/badge.svg
|
||||||
:target: https://github.com/verilator/verilator/actions?query=workflow%3Abuild
|
:target: https://github.com/verilator/verilator/actions?query=workflow%3Abuild
|
||||||
|
|
||||||
|
|
@ -134,7 +132,7 @@ Related Projects
|
||||||
- `GTKwave <http://gtkwave.sourceforge.net/>`_ - Waveform viewer for
|
- `GTKwave <http://gtkwave.sourceforge.net/>`_ - Waveform viewer for
|
||||||
Verilator traces.
|
Verilator traces.
|
||||||
|
|
||||||
- `Icarus Verilog`_ - Icarus is a full-featured interpreted Verilog
|
- `Icarus Verilog`_ - Icarus is a highly-featured interpreted Verilog
|
||||||
simulator. If Verilator does not support your needs, perhaps Icarus may.
|
simulator. If Verilator does not support your needs, perhaps Icarus may.
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -256,7 +256,7 @@ sub sh_escape {
|
||||||
# This is similar to quotemeta() but less aggressive.
|
# This is similar to quotemeta() but less aggressive.
|
||||||
# There's no need to escape hyphens, periods, or forward slashes
|
# There's no need to escape hyphens, periods, or forward slashes
|
||||||
# for the shell as these have no special meaning to the shell.
|
# for the shell as these have no special meaning to the shell.
|
||||||
$arg =~ s/([^0-9a-zA-Z_\-\+\=\.\/])/\\$1/g;
|
$arg =~ s/([^0-9a-zA-Z_\-\+\=\.\/:])/\\$1/g;
|
||||||
return $arg;
|
return $arg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -341,11 +341,12 @@ detailed descriptions of these arguments.
|
||||||
--no-debug-leak Disable leaking memory in --debug mode
|
--no-debug-leak Disable leaking memory in --debug mode
|
||||||
--debugi <level> Enable debugging at a specified level
|
--debugi <level> Enable debugging at a specified level
|
||||||
--debugi-<srcfile> <level> Enable debugging a source file at a 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
|
--no-decoration Disable comments and lower spacing level
|
||||||
|
--decorations <level> Set output comment and spacing level
|
||||||
--default-language <lang> Default language to parse
|
--default-language <lang> Default language to parse
|
||||||
+define+<var>=<value> Set preprocessor define
|
+define+<var>=<value> Set preprocessor define
|
||||||
--dpi-hdr-only Only produce the DPI header file
|
--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-defines Show preprocessor defines with -E
|
||||||
--dump-dfg Enable dumping DfgGraphs to .dot files
|
--dump-dfg Enable dumping DfgGraphs to .dot files
|
||||||
--dump-graph Enable dumping V3Graphs 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-addrids Use short identifiers instead of addresses
|
||||||
--dump-tree-dot Enable dumping Ast .tree.dot debug files
|
--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-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-dfg <level> Enable dumping DfgGraphs to .dot files at level
|
||||||
--dumpi-graph <level> Enable dumping V3Graphs 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 <level> Enable dumping Ast .tree files at level
|
||||||
--dumpi-tree-json <level> Enable dumping Ast .tree.json 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
|
-E Preprocess, but do not compile
|
||||||
--emit-accessors Emit getter and setter methods for model top class
|
--emit-accessors Emit getter and setter methods for model top class
|
||||||
--error-limit <value> Abort after this number of errors
|
--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-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
|
--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 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-meta-output .tree.meta.json output filename
|
||||||
|
--json-only-output .tree.json output filename
|
||||||
--l2-name <value> Verilog scope name of the top module
|
--l2-name <value> Verilog scope name of the top module
|
||||||
--language <lang> Default language standard to parse
|
--language <lang> Default language standard to parse
|
||||||
-LDFLAGS <flags> Linker pre-object arguments for makefile
|
-LDFLAGS <flags> Linker pre-object arguments for makefile
|
||||||
|
|
@ -399,20 +399,20 @@ detailed descriptions of these arguments.
|
||||||
+libext+<ext>+[ext]... Extensions for finding modules
|
+libext+<ext>+[ext]... Extensions for finding modules
|
||||||
--lint-only Lint, but do not make output
|
--lint-only Lint, but do not make output
|
||||||
--localize-max-size <value> Tune localize optimization variable size
|
--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 Generate C++ main() file
|
||||||
--main-top-name Specify top name passed to Verilated model in generated C++ main
|
--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)
|
--max-num-width <value> Maximum number width (default: 64K)
|
||||||
--Mdir <directory> Name of output object directory
|
--Mdir <directory> Name of output object directory
|
||||||
--MMD Create .d dependency files
|
--MMD Create .d dependency files
|
||||||
--mod-prefix <topname> Name to prepend to lower classes
|
--mod-prefix <topname> Name to prepend to lower classes
|
||||||
--MP Create phony dependency targets
|
--MP Create phony dependency targets
|
||||||
+notimingchecks Ignored
|
+notimingchecks Ignored
|
||||||
|
-o <executable> Name of final executable
|
||||||
-O0 Disable optimizations
|
-O0 Disable optimizations
|
||||||
-O3 High-performance optimizations
|
-O3 High-performance optimizations
|
||||||
-O<optimization-letter> Selectable optimizations
|
-O<optimization-letter> Selectable optimizations
|
||||||
-o <executable> Name of final executable
|
|
||||||
--output-groups <numfiles> Group .cpp files into larger ones
|
--output-groups <numfiles> Group .cpp files into larger ones
|
||||||
--output-split <statements> Split .cpp files into pieces
|
--output-split <statements> Split .cpp files into pieces
|
||||||
--output-split-cfuncs <statements> Split model functions
|
--output-split-cfuncs <statements> Split model functions
|
||||||
|
|
@ -467,23 +467,25 @@ detailed descriptions of these arguments.
|
||||||
--threads <threads> Enable multithreading
|
--threads <threads> Enable multithreading
|
||||||
--threads-dpi <mode> Enable multithreaded DPI
|
--threads-dpi <mode> Enable multithreaded DPI
|
||||||
--threads-max-mtasks <mtasks> Tune maximum mtask partitioning
|
--threads-max-mtasks <mtasks> Tune maximum mtask partitioning
|
||||||
--timing Enable timing support
|
|
||||||
--no-timing Disable timing support
|
|
||||||
--timescale <timescale> Sets default timescale
|
--timescale <timescale> Sets default timescale
|
||||||
--timescale-override <timescale> Overrides all timescales
|
--timescale-override <timescale> Overrides all timescales
|
||||||
|
--timing Enable timing support
|
||||||
|
--no-timing Disable timing support
|
||||||
--top <topname> Alias of --top-module
|
--top <topname> Alias of --top-module
|
||||||
--top-module <topname> Name of top-level input 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-coverage Enable tracing of coverage
|
||||||
--trace-depth <levels> Depth of tracing
|
--trace-depth <levels> Depth of tracing
|
||||||
--trace-fst Enable FST waveform creation
|
--trace-fst Enable FST waveform creation
|
||||||
--trace-max-array <depth> Maximum array depth for tracing
|
--trace-max-array <depth> Maximum array depth for tracing
|
||||||
--trace-max-width <width> Maximum bit width for tracing
|
--trace-max-width <width> Maximum bit width for tracing
|
||||||
--trace-params Enable tracing of parameters
|
--trace-params Enable tracing of parameters
|
||||||
|
--trace-saif Enable SAIF file creation
|
||||||
--trace-structs Enable tracing structure names
|
--trace-structs Enable tracing structure names
|
||||||
--trace-threads <threads> Enable FST waveform creation on separate threads
|
--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
|
--no-trace-top Do not emit traces for signals in the top module generated by verilator
|
||||||
--trace-underscore Enable tracing of _signals
|
--trace-underscore Enable tracing of _signals
|
||||||
|
--trace-vcd Enable VCD waveform creation
|
||||||
-U<var> Undefine preprocessor define
|
-U<var> Undefine preprocessor define
|
||||||
--no-unlimited-stack Don't disable stack size limit
|
--no-unlimited-stack Don't disable stack size limit
|
||||||
--unroll-count <loops> Tune maximum loop iterations
|
--unroll-count <loops> Tune maximum loop iterations
|
||||||
|
|
@ -492,8 +494,8 @@ detailed descriptions of these arguments.
|
||||||
-V Verbose version and config
|
-V Verbose version and config
|
||||||
-v <filename> Verilog library
|
-v <filename> Verilog library
|
||||||
--valgrind Run Verilator under valgrind
|
--valgrind Run Verilator under valgrind
|
||||||
--verilate-jobs Job threads for Verilation stage
|
|
||||||
--no-verilate Skip Verilation and just compile previously Verilated code
|
--no-verilate Skip Verilation and just compile previously Verilated code
|
||||||
|
--verilate-jobs Job threads for Verilation stage
|
||||||
+verilog1995ext+<ext> Synonym for +1364-1995ext+<ext>
|
+verilog1995ext+<ext> Synonym for +1364-1995ext+<ext>
|
||||||
+verilog2001ext+<ext> Synonym for +1364-2001ext+<ext>
|
+verilog2001ext+<ext> Synonym for +1364-2001ext+<ext>
|
||||||
--version Show program version and exits
|
--version Show program version and exits
|
||||||
|
|
@ -526,9 +528,9 @@ description of these arguments.
|
||||||
|
|
||||||
=for VL_SPHINX_EXTRACT "_build/gen/args_verilated.rst"
|
=for VL_SPHINX_EXTRACT "_build/gen/args_verilated.rst"
|
||||||
|
|
||||||
|
+verilator+coverage+file+<filename> Set coverage output filename
|
||||||
+verilator+debug Enable debugging
|
+verilator+debug Enable debugging
|
||||||
+verilator+debugi+<value> Enable debugging at a level
|
+verilator+debugi+<value> Enable debugging at a level
|
||||||
+verilator+coverage+file+<filename> Set coverage output filename
|
|
||||||
+verilator+error+limit+<value> Set error limit
|
+verilator+error+limit+<value> Set error limit
|
||||||
+verilator+help Show help
|
+verilator+help Show help
|
||||||
+verilator+noassert Disable assert checking
|
+verilator+noassert Disable assert checking
|
||||||
|
|
|
||||||
|
|
@ -8,17 +8,27 @@ import collections
|
||||||
import math
|
import math
|
||||||
import re
|
import re
|
||||||
import statistics
|
import statistics
|
||||||
|
from collections import OrderedDict
|
||||||
# from pprint import pprint
|
# from pprint import pprint
|
||||||
|
|
||||||
Sections = []
|
Sections = OrderedDict()
|
||||||
LongestVcdStrValueLength = 0
|
LongestVcdStrValueLength = 0
|
||||||
Threads = collections.defaultdict(lambda: []) # List of records per thread id
|
Threads = collections.defaultdict(lambda: []) # List of records per thread id
|
||||||
Mtasks = collections.defaultdict(lambda: {'elapsed': 0, 'end': 0})
|
Mtasks = collections.defaultdict(lambda: {'elapsed': 0, 'end': 0})
|
||||||
Cpus = collections.defaultdict(lambda: {'mtask_time': 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
|
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
|
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:
|
with open(filename, "r", encoding="utf8") as fh:
|
||||||
re_thread = re.compile(r'^VLPROFTHREAD (\d+)$')
|
re_thread = re.compile(r'^VLPROFTHREAD (\d+)$')
|
||||||
re_record = re.compile(r'^VLPROFEXEC (\S+) (\d+)(.*)$')
|
re_record = re.compile(r'^VLPROFEXEC (\S+) (\d+)(.*)$')
|
||||||
re_payload_mtaskBegin = re.compile(r'id (\d+) predictStart (\d+) cpu (\d+)')
|
# The hierBlock argument is optional
|
||||||
re_payload_mtaskEnd = re.compile(r'id (\d+) predictCost (\d+)')
|
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_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_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_cpu = re.compile(r'VLPROFPROC processor\s*:\s*(\d+)\s*$')
|
||||||
re_proc_dat = re.compile(r'VLPROFPROC ([a-z_ ]+)\s*:\s*(.*)$')
|
re_proc_dat = re.compile(r'VLPROFPROC ([a-z_ ]+)\s*:\s*(.*)$')
|
||||||
cpu = None
|
cpu = None
|
||||||
thread = 0
|
thread = 0
|
||||||
execGraphStart = None
|
|
||||||
|
|
||||||
global LongestVcdStrValueLength
|
global LongestVcdStrValueLength
|
||||||
global ExecGraphTime
|
global ExecGraphTime
|
||||||
|
global WaitingTime
|
||||||
|
|
||||||
|
ExecGraphStack = []
|
||||||
SectionStack = []
|
SectionStack = []
|
||||||
mTaskThread = {}
|
MtasksStack = []
|
||||||
|
ThreadScheduleWait = collections.defaultdict(list)
|
||||||
|
|
||||||
for line in fh:
|
for line in fh:
|
||||||
recordMatch = re_record.match(line)
|
recordMatch = re_record.match(line)
|
||||||
|
|
@ -60,44 +76,57 @@ def read_data(filename):
|
||||||
SectionStack.pop()
|
SectionStack.pop()
|
||||||
Sections[thread].append((tick, tuple(SectionStack)))
|
Sections[thread].append((tick, tuple(SectionStack)))
|
||||||
elif kind == "MTASK_BEGIN":
|
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)
|
mtask = int(mtask)
|
||||||
predict_start = int(predict_start)
|
predict_start = int(predict_start)
|
||||||
ecpu = int(ecpu)
|
ecpu = int(ecpu)
|
||||||
mTaskThread[mtask] = thread
|
|
||||||
records = Threads[thread]
|
records = Threads[thread]
|
||||||
assert not records or records[-1]['start'] <= records[-1]['end'] <= tick
|
|
||||||
records.append({
|
records.append({
|
||||||
'start': tick,
|
'start': tick,
|
||||||
'mtask': mtask,
|
'mtask': mtask,
|
||||||
'predict_start': predict_start,
|
'predict_start': predict_start,
|
||||||
|
'hier_block': hier_block,
|
||||||
'cpu': ecpu
|
'cpu': ecpu
|
||||||
})
|
})
|
||||||
Mtasks[mtask]['begin'] = tick
|
Mtasks[(hier_block, mtask)]['begin'] = tick
|
||||||
Mtasks[mtask]['thread'] = thread
|
Mtasks[(hier_block, mtask)]['predict_start'] = predict_start
|
||||||
Mtasks[mtask]['predict_start'] = predict_start
|
Mtasks[(hier_block, mtask)]['thread'] = thread
|
||||||
|
MtasksStack.append((hier_block, mtask, records[-1]))
|
||||||
elif kind == "MTASK_END":
|
elif kind == "MTASK_END":
|
||||||
mtask, predict_cost = re_payload_mtaskEnd.match(payload).groups()
|
predict_cost, = re_payload_mtaskEnd.match(payload).groups()
|
||||||
mtask = int(mtask)
|
mtask = int(mtask)
|
||||||
|
hier_block, mtask, record = MtasksStack.pop()
|
||||||
predict_cost = int(predict_cost)
|
predict_cost = int(predict_cost)
|
||||||
begin = Mtasks[mtask]['begin']
|
begin = Mtasks[(hier_block, mtask)]['begin']
|
||||||
record = Threads[mTaskThread[mtask]][-1]
|
|
||||||
record['end'] = tick
|
record['end'] = tick
|
||||||
|
assert record and records[-1]['start'] <= records[-1]['end'] <= tick
|
||||||
record['predict_cost'] = predict_cost
|
record['predict_cost'] = predict_cost
|
||||||
Mtasks[mtask]['elapsed'] += tick - begin
|
Mtasks[(hier_block, mtask)]['elapsed'] += tick - begin
|
||||||
Mtasks[mtask]['predict_cost'] = predict_cost
|
Mtasks[(hier_block, mtask)]['predict_cost'] = predict_cost
|
||||||
Mtasks[mtask]['end'] = max(Mtasks[mtask]['end'], tick)
|
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":
|
elif kind == "EXEC_GRAPH_BEGIN":
|
||||||
execGraphStart = tick
|
ExecGraphStack.append(tick)
|
||||||
elif kind == "EXEC_GRAPH_END":
|
elif kind == "EXEC_GRAPH_END":
|
||||||
|
assert ExecGraphStack, "EXEC_GRAPH_END without EXEC_GRAPH_BEGIN"
|
||||||
|
execGraphStart = ExecGraphStack.pop()
|
||||||
ExecGraphTime += tick - execGraphStart
|
ExecGraphTime += tick - execGraphStart
|
||||||
ExecGraphIntervals.append((execGraphStart, tick))
|
ExecGraphIntervals.append((execGraphStart, tick))
|
||||||
execGraphStart = None
|
|
||||||
elif Args.debug:
|
elif Args.debug:
|
||||||
print("-Unknown execution trace record: %s" % line)
|
print("-Unknown execution trace record: %s" % line)
|
||||||
elif re_thread.match(line):
|
elif re_thread.match(line):
|
||||||
thread = int(re_thread.match(line).group(1))
|
thread = int(re_thread.match(line).group(1))
|
||||||
Sections.append([])
|
Sections[thread] = []
|
||||||
elif re.match(r'^VLPROF(THREAD|VERSION)', line):
|
elif re.match(r'^VLPROF(THREAD|VERSION)', line):
|
||||||
pass
|
pass
|
||||||
elif re_arg1.match(line):
|
elif re_arg1.match(line):
|
||||||
|
|
@ -106,6 +135,9 @@ def read_data(filename):
|
||||||
elif re_arg2.match(line):
|
elif re_arg2.match(line):
|
||||||
match = re_arg2.match(line)
|
match = re_arg2.match(line)
|
||||||
Global['args'][match.group(1)] = match.group(2)
|
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):
|
elif re_stat.match(line):
|
||||||
match = re_stat.match(line)
|
match = re_stat.match(line)
|
||||||
Global['stats'][match.group(1)] = match.group(2)
|
Global['stats'][match.group(1)] = match.group(2)
|
||||||
|
|
@ -156,11 +188,13 @@ def report():
|
||||||
print("\nSummary:")
|
print("\nSummary:")
|
||||||
print(" Total elapsed time = {} rdtsc ticks".format(ElapsedTime))
|
print(" Total elapsed time = {} rdtsc ticks".format(ElapsedTime))
|
||||||
print(" Parallelized code = {:.2%} of elapsed time".format(ExecGraphTime / 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 threads = %d" % nthreads)
|
||||||
print(" Total CPUs used = %d" % ncpus)
|
print(" Total CPUs used = %d" % ncpus)
|
||||||
print(" Total mtasks = %d" % len(Mtasks))
|
print(" Total mtasks = %d" % len(Mtasks))
|
||||||
print(" Total yields = %d" % int(Global['stats'].get('yields', 0)))
|
print(" Total yields = %d" % int(Global['stats'].get('yields', 0)))
|
||||||
|
|
||||||
|
report_numa()
|
||||||
report_mtasks()
|
report_mtasks()
|
||||||
report_cpus()
|
report_cpus()
|
||||||
report_sections()
|
report_sections()
|
||||||
|
|
@ -181,6 +215,11 @@ def report():
|
||||||
print()
|
print()
|
||||||
|
|
||||||
|
|
||||||
|
def report_numa():
|
||||||
|
print("\nNUMA assignment:")
|
||||||
|
print(" NUMA status = %s" % Global['info']['numa'])
|
||||||
|
|
||||||
|
|
||||||
def report_mtasks():
|
def report_mtasks():
|
||||||
if not Mtasks:
|
if not Mtasks:
|
||||||
return
|
return
|
||||||
|
|
@ -201,8 +240,8 @@ def report_mtasks():
|
||||||
long_mtask = None
|
long_mtask = None
|
||||||
predict_mtask_time = 0
|
predict_mtask_time = 0
|
||||||
predict_elapsed = 0
|
predict_elapsed = 0
|
||||||
for mtaskId in Mtasks:
|
for (hier_block, mtask_id) in Mtasks:
|
||||||
record = Mtasks[mtaskId]
|
record = Mtasks[(hier_block, mtask_id)]
|
||||||
predict_mtask_time += record['predict_cost']
|
predict_mtask_time += record['predict_cost']
|
||||||
total_mtask_time += record['elapsed']
|
total_mtask_time += record['elapsed']
|
||||||
thread_mtask_time[record['thread']] += record['elapsed']
|
thread_mtask_time[record['thread']] += record['elapsed']
|
||||||
|
|
@ -210,7 +249,8 @@ def report_mtasks():
|
||||||
predict_elapsed = max(predict_elapsed, predict_end)
|
predict_elapsed = max(predict_elapsed, predict_end)
|
||||||
if record['elapsed'] > long_mtask_time:
|
if record['elapsed'] > long_mtask_time:
|
||||||
long_mtask_time = record['elapsed']
|
long_mtask_time = record['elapsed']
|
||||||
long_mtask = mtaskId
|
long_mtask = mtask_id
|
||||||
|
long_mtask_hier_block = hier_block
|
||||||
Global['predict_last_end'] = predict_elapsed
|
Global['predict_last_end'] = predict_elapsed
|
||||||
|
|
||||||
serialTime = ElapsedTime - ExecGraphTime
|
serialTime = ElapsedTime - ExecGraphTime
|
||||||
|
|
@ -239,31 +279,52 @@ def report_mtasks():
|
||||||
max_p2e = -1000000
|
max_p2e = -1000000
|
||||||
max_mtask = None
|
max_mtask = None
|
||||||
|
|
||||||
for mtask in sorted(Mtasks.keys()):
|
for (hier_block, mtask_id) in sorted(Mtasks.keys()):
|
||||||
if Mtasks[mtask]['elapsed'] > 0:
|
mtask = Mtasks[(hier_block, mtask_id)]
|
||||||
if Mtasks[mtask]['predict_cost'] == 0:
|
if mtask['elapsed'] > 0:
|
||||||
Mtasks[mtask]['predict_cost'] = 1 # don't log(0) below
|
if mtask['predict_cost'] == 0:
|
||||||
p2e_ratio = math.log(Mtasks[mtask]['predict_cost'] / Mtasks[mtask]['elapsed'])
|
mtask['predict_cost'] = 1 # don't log(0) below
|
||||||
|
p2e_ratio = math.log(mtask['predict_cost'] / mtask['elapsed'])
|
||||||
p2e_ratios.append(p2e_ratio)
|
p2e_ratios.append(p2e_ratio)
|
||||||
|
|
||||||
if p2e_ratio > max_p2e:
|
if p2e_ratio > max_p2e:
|
||||||
max_p2e = p2e_ratio
|
max_p2e = p2e_ratio
|
||||||
max_mtask = mtask
|
max_mtask = mtask_id
|
||||||
|
max_hier_block = hier_block
|
||||||
if p2e_ratio < min_p2e:
|
if p2e_ratio < min_p2e:
|
||||||
min_p2e = p2e_ratio
|
min_p2e = p2e_ratio
|
||||||
min_mtask = mtask
|
min_mtask = mtask_id
|
||||||
|
min_hier_block = hier_block
|
||||||
|
|
||||||
print("\nMTask statistics:")
|
print("\nMTask statistics:")
|
||||||
|
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 id = {}".format(long_mtask))
|
||||||
print(" Longest mtask time = {:.2%} of time elapsed in parallelized code".format(
|
print(" Longest mtask time = {:.2%} of time elapsed in parallelized code".format(
|
||||||
long_mtask_time / ExecGraphTime))
|
long_mtask_time / ExecGraphTime))
|
||||||
print(" min log(p2e) = %0.3f" % min_p2e, end="")
|
print(" min log(p2e) = %0.3f" % min_p2e, end="")
|
||||||
|
|
||||||
print(" from mtask %d (predict %d," % (min_mtask, Mtasks[min_mtask]['predict_cost']), end="")
|
if min_hier_block:
|
||||||
print(" elapsed %d)" % Mtasks[min_mtask]['elapsed'])
|
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(" max log(p2e) = %0.3f" % max_p2e, end="")
|
||||||
print(" from mtask %d (predict %d," % (max_mtask, Mtasks[max_mtask]['predict_cost']), end="")
|
if max_hier_block:
|
||||||
print(" elapsed %d)" % Mtasks[max_mtask]['elapsed'])
|
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)
|
stddev = statistics.pstdev(p2e_ratios)
|
||||||
mean = statistics.mean(p2e_ratios)
|
mean = statistics.mean(p2e_ratios)
|
||||||
|
|
@ -308,7 +369,7 @@ def report_cpus():
|
||||||
|
|
||||||
|
|
||||||
def report_sections():
|
def report_sections():
|
||||||
for thread, section in enumerate(Sections):
|
for thread, section in Sections.items():
|
||||||
if section:
|
if section:
|
||||||
print(f"\nSection profile for thread {thread}:")
|
print(f"\nSection profile for thread {thread}:")
|
||||||
report_section(section)
|
report_section(section)
|
||||||
|
|
@ -403,6 +464,9 @@ def write_vcd(filename):
|
||||||
val = buf.ljust(LongestVcdStrValueLength * 8, "0")
|
val = buf.ljust(LongestVcdStrValueLength * 8, "0")
|
||||||
values[time][code] = val
|
values[time][code] = val
|
||||||
|
|
||||||
|
def addXValue(code, time):
|
||||||
|
values[time][code] = 'x'
|
||||||
|
|
||||||
# Measured graph
|
# Measured graph
|
||||||
for thread in sorted(Threads):
|
for thread in sorted(Threads):
|
||||||
mcode = getCode(32, 'measured', 't%d_mtask' % thread)
|
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)
|
tStart = sorted(_['start'] for records in Threads.values() for _ in records)
|
||||||
tEnd = sorted(_['end'] 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
|
# Predicted graph
|
||||||
for start, end in ExecGraphIntervals:
|
for start, end in ExecGraphIntervals:
|
||||||
# Find the earliest MTask start after the start point, and the
|
# Find the earliest MTask start after the start point, and the
|
||||||
# latest MTask end before the end point, so we can scale to the
|
# latest MTask end before the end point, so we can scale to the
|
||||||
# same range
|
# 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]
|
end = tEnd[bisect.bisect_right(tEnd, end) - 1]
|
||||||
# Compute scale so predicted graph is of same width as interval
|
# Compute scale so predicted graph is of same width as interval
|
||||||
measured_scaling = (end - start) / Global['predict_last_end']
|
measured_scaling = (end - start) / Global['predict_last_end']
|
||||||
# Predict mtasks that fill the time the execution occupied
|
# Predict mtasks that fill the time the execution occupied
|
||||||
for mtask in Mtasks:
|
for (hier_block, mtask_id) in Mtasks:
|
||||||
thread = Mtasks[mtask]['thread']
|
mtask = Mtasks[(hier_block, mtask_id)]
|
||||||
pred_scaled_start = start + int(Mtasks[mtask]['predict_start'] * measured_scaling)
|
thread = mtask['thread']
|
||||||
|
pred_scaled_start = start + int(mtask['predict_start'] * measured_scaling)
|
||||||
pred_scaled_end = start + int(
|
pred_scaled_end = start + int(
|
||||||
(Mtasks[mtask]['predict_start'] + Mtasks[mtask]['predict_cost']) *
|
(mtask['predict_start'] + mtask['predict_cost']) * measured_scaling)
|
||||||
measured_scaling)
|
|
||||||
if pred_scaled_start == pred_scaled_end:
|
if pred_scaled_start == pred_scaled_end:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
mcode = getCode(32, 'predicted', 't%d_mtask' % thread)
|
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)
|
addValue(mcode, pred_scaled_end, None)
|
||||||
|
|
||||||
parallelism['predicted'][pred_scaled_start] += 1
|
parallelism['predicted'][pred_scaled_start] += 1
|
||||||
|
|
@ -462,7 +535,7 @@ def write_vcd(filename):
|
||||||
addValue(pcode, time, value)
|
addValue(pcode, time, value)
|
||||||
|
|
||||||
# Section graph
|
# Section graph
|
||||||
for thread, section in enumerate(Sections):
|
for thread, section in Sections.items():
|
||||||
if section:
|
if section:
|
||||||
scode = getCode(LongestVcdStrValueLength * 8, "section", f"t{thread}_trace")
|
scode = getCode(LongestVcdStrValueLength * 8, "section", f"t{thread}_trace")
|
||||||
dcode = getCode(32, "section", f"t{thread}_depth")
|
dcode = getCode(32, "section", f"t{thread}_depth")
|
||||||
|
|
@ -510,6 +583,8 @@ def write_vcd(filename):
|
||||||
value = values[time][code]
|
value = values[time][code]
|
||||||
if value is None:
|
if value is None:
|
||||||
fh.write("bz v%x\n" % code)
|
fh.write("bz v%x\n" % code)
|
||||||
|
elif value == 'x':
|
||||||
|
fh.write("bx v%x\n" % code)
|
||||||
elif isinstance(value, str):
|
elif isinstance(value, str):
|
||||||
fh.write("b%s v%x\n" % (value, code))
|
fh.write("b%s v%x\n" % (value, code))
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ fi
|
||||||
install-vcddiff() {
|
install-vcddiff() {
|
||||||
TMP_DIR="$(mktemp -d)"
|
TMP_DIR="$(mktemp -d)"
|
||||||
git clone https://github.com/veripool/vcddiff "$TMP_DIR"
|
git clone https://github.com/veripool/vcddiff "$TMP_DIR"
|
||||||
git -C "${TMP_DIR}" checkout e5664be5fe39d353bf3fcb50aa05214ab7ed4ac4
|
git -C "${TMP_DIR}" checkout dca845020668887fd13498c772939814d9264fd5
|
||||||
"$MAKE" -C "${TMP_DIR}"
|
"$MAKE" -C "${TMP_DIR}"
|
||||||
sudo cp "${TMP_DIR}/vcddiff" /usr/local/bin
|
sudo cp "${TMP_DIR}/vcddiff" /usr/local/bin
|
||||||
}
|
}
|
||||||
|
|
@ -55,16 +55,16 @@ if [ "$CI_BUILD_STAGE_NAME" = "build" ]; then
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get install ccache help2man libfl-dev ||
|
sudo apt-get install ccache help2man libfl-dev ||
|
||||||
sudo apt-get install ccache help2man libfl-dev
|
sudo apt-get install ccache help2man libfl-dev
|
||||||
if [ "$CI_RUNS_ON" = "ubuntu-20.04" ]; then
|
if [[ ! "$CI_RUNS_ON" =~ "ubuntu-22.04" ]]; then
|
||||||
# Some conflict of libunwind verison on 22.04, can live without it for now
|
# 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 ||
|
||||||
sudo apt-get install libgoogle-perftools-dev
|
sudo apt-get install libgoogle-perftools-dev
|
||||||
fi
|
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 ||
|
||||||
sudo apt-get install libsystemc libsystemc-dev
|
sudo apt-get install libsystemc libsystemc-dev
|
||||||
fi
|
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 ||
|
||||||
sudo apt-get install bear mold
|
sudo apt-get install bear mold
|
||||||
fi
|
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 ||
|
||||||
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
|
# 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 ||
|
||||||
sudo apt-get install python3-clang mold
|
sudo apt-get install python3-clang mold
|
||||||
fi
|
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 ||
|
||||||
sudo apt-get install libsystemc-dev
|
sudo apt-get install libsystemc-dev
|
||||||
fi
|
fi
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,7 @@ elif [ "$CI_BUILD_STAGE_NAME" = "test" ]; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Run sanitize on Ubuntu 22.04 only
|
# 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
|
TEST_REGRESS=test_regress
|
||||||
if [ "$CI_RELOC" == 1 ]; then
|
if [ "$CI_RELOC" == 1 ]; then
|
||||||
|
|
@ -98,6 +98,8 @@ elif [ "$CI_BUILD_STAGE_NAME" = "test" ]; then
|
||||||
export VERILATOR_ROOT="$RELOC_DIR/relocated-install/share/verilator"
|
export VERILATOR_ROOT="$RELOC_DIR/relocated-install/share/verilator"
|
||||||
TEST_REGRESS="$RELOC_DIR/test_regress"
|
TEST_REGRESS="$RELOC_DIR/test_regress"
|
||||||
mv test_regress "$TEST_REGRESS"
|
mv test_regress "$TEST_REGRESS"
|
||||||
|
NODIST="$RELOC_DIR/nodist"
|
||||||
|
mv nodist "$NODIST"
|
||||||
# Feeling brave?
|
# Feeling brave?
|
||||||
find . -delete
|
find . -delete
|
||||||
ls -la .
|
ls -la .
|
||||||
|
|
@ -107,22 +109,25 @@ elif [ "$CI_BUILD_STAGE_NAME" = "test" ]; then
|
||||||
ccache -z
|
ccache -z
|
||||||
case $TESTS in
|
case $TESTS in
|
||||||
dist-vlt-0)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
coverage-all)
|
||||||
nodist/code_coverage --stages 1-
|
nodist/code_coverage --stages 1-
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
# Then 'make maintainer-dist'
|
# Then 'make maintainer-dist'
|
||||||
#AC_INIT([Verilator],[#.### YYYY-MM-DD])
|
#AC_INIT([Verilator],[#.### YYYY-MM-DD])
|
||||||
#AC_INIT([Verilator],[#.### devel])
|
#AC_INIT([Verilator],[#.### devel])
|
||||||
AC_INIT([Verilator],[5.034 2025-02-24],
|
AC_INIT([Verilator],[5.036 2025-04-27],
|
||||||
[https://verilator.org],
|
[https://verilator.org],
|
||||||
[verilator],[https://verilator.org])
|
[verilator],[https://verilator.org])
|
||||||
|
|
||||||
|
|
@ -432,6 +432,7 @@ AC_SUBST(HAVE_COROUTINES)
|
||||||
|
|
||||||
# Flags for compiling Verilator internals including parser always
|
# Flags for compiling Verilator internals including parser always
|
||||||
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-Qunused-arguments)
|
_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,-faligned-new)
|
||||||
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-Wno-unused-parameter)
|
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-Wno-unused-parameter)
|
||||||
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-Wno-shadow)
|
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-Wno-shadow)
|
||||||
|
|
@ -469,6 +470,7 @@ CFG_CXX_FLAGS_CMAKE="-faligned-new"
|
||||||
m4_foreach([cflag],[
|
m4_foreach([cflag],[
|
||||||
[-fbracket-depth=4096],
|
[-fbracket-depth=4096],
|
||||||
[-fcf-protection=none],
|
[-fcf-protection=none],
|
||||||
|
[-Xclang -fno-pch-timestamp],
|
||||||
[-mno-cet],
|
[-mno-cet],
|
||||||
[-Qunused-arguments],
|
[-Qunused-arguments],
|
||||||
[-Wno-bool-operation],
|
[-Wno-bool-operation],
|
||||||
|
|
@ -515,7 +517,7 @@ if test "$CFG_ENABLE_PARTIAL_STATIC" = "yes"; then
|
||||||
_MY_LDLIBS_CHECK_OPT(CFG_LDFLAGS_SRC, -static-libgcc)
|
_MY_LDLIBS_CHECK_OPT(CFG_LDFLAGS_SRC, -static-libgcc)
|
||||||
_MY_LDLIBS_CHECK_OPT(CFG_LDFLAGS_SRC, -static-libstdc++)
|
_MY_LDLIBS_CHECK_OPT(CFG_LDFLAGS_SRC, -static-libstdc++)
|
||||||
_MY_LDLIBS_CHECK_OPT(CFG_LDFLAGS_SRC, -Xlinker -gc-sections)
|
_MY_LDLIBS_CHECK_OPT(CFG_LDFLAGS_SRC, -Xlinker -gc-sections)
|
||||||
LTCMALLOC=-l:libtcmalloc_minimal.a
|
LTCMALLOC="-Wl,--whole-archive -l:libtcmalloc_minimal.a -Wl,--no-whole-archive"
|
||||||
else
|
else
|
||||||
LTCMALLOC=-ltcmalloc_minimal
|
LTCMALLOC=-ltcmalloc_minimal
|
||||||
fi
|
fi
|
||||||
|
|
|
||||||
|
|
@ -19,12 +19,14 @@ Andreas Kuster
|
||||||
Andrei Kostovski
|
Andrei Kostovski
|
||||||
Andrew Miloradovsky
|
Andrew Miloradovsky
|
||||||
Andrew Nolte
|
Andrew Nolte
|
||||||
|
Andrew Voznytsa
|
||||||
Anthony Donlon
|
Anthony Donlon
|
||||||
Anthony Moore
|
Anthony Moore
|
||||||
Arkadiusz Kozdra
|
Arkadiusz Kozdra
|
||||||
Arthur Rosa
|
Arthur Rosa
|
||||||
Aylon Chaim Porat
|
Aylon Chaim Porat
|
||||||
Bartłomiej Chmiel
|
Bartłomiej Chmiel
|
||||||
|
Brian Li
|
||||||
Cameron Kirk
|
Cameron Kirk
|
||||||
Chih-Mao Chen
|
Chih-Mao Chen
|
||||||
Chris Bachhuber
|
Chris Bachhuber
|
||||||
|
|
@ -65,6 +67,7 @@ Garrett Smith
|
||||||
Geza Lore
|
Geza Lore
|
||||||
Gianfranco Costamagna
|
Gianfranco Costamagna
|
||||||
Gijs Burghoorn
|
Gijs Burghoorn
|
||||||
|
Gilberto Abram
|
||||||
Glen Gibb
|
Glen Gibb
|
||||||
Gökçe Aydos
|
Gökçe Aydos
|
||||||
Graham Rushton
|
Graham Rushton
|
||||||
|
|
@ -107,6 +110,7 @@ Jiuyang Liu
|
||||||
Joey Liu
|
Joey Liu
|
||||||
John Coiner
|
John Coiner
|
||||||
John Demme
|
John Demme
|
||||||
|
John Khoo
|
||||||
John Wehle
|
John Wehle
|
||||||
Jonathan Drolet
|
Jonathan Drolet
|
||||||
Jonathan Schröter
|
Jonathan Schröter
|
||||||
|
|
@ -132,6 +136,7 @@ Krzysztof Boronski
|
||||||
Krzysztof Boroński
|
Krzysztof Boroński
|
||||||
Krzysztof Obłonczek
|
Krzysztof Obłonczek
|
||||||
Krzysztof Starecki
|
Krzysztof Starecki
|
||||||
|
Krzysztof Sychla
|
||||||
Kuba Ober
|
Kuba Ober
|
||||||
Larry Doolittle
|
Larry Doolittle
|
||||||
Liam Braun
|
Liam Braun
|
||||||
|
|
@ -148,6 +153,7 @@ Marlon James
|
||||||
Marshal Qiao
|
Marshal Qiao
|
||||||
Martin Schmidt
|
Martin Schmidt
|
||||||
Martin Stadler
|
Martin Stadler
|
||||||
|
Mateusz Gancarz
|
||||||
Matthew Ballance
|
Matthew Ballance
|
||||||
Michael Bikovitsky
|
Michael Bikovitsky
|
||||||
Michael Killough
|
Michael Killough
|
||||||
|
|
@ -191,6 +197,7 @@ Ricardo Barbedo
|
||||||
Richard Myers
|
Richard Myers
|
||||||
Risto Pejašinović
|
Risto Pejašinović
|
||||||
Robert Balas
|
Robert Balas
|
||||||
|
Robin Heinemann
|
||||||
Rupert Swarbrick
|
Rupert Swarbrick
|
||||||
Ryan Ziegler
|
Ryan Ziegler
|
||||||
Ryszard Rozak
|
Ryszard Rozak
|
||||||
|
|
@ -243,6 +250,8 @@ Yutetsu TAKATSUKASA
|
||||||
Yves Mathieu
|
Yves Mathieu
|
||||||
Zhanglei Wang
|
Zhanglei Wang
|
||||||
Zhou Shen
|
Zhou Shen
|
||||||
|
Zhouyi Shen
|
||||||
Zixi Li
|
Zixi Li
|
||||||
أحمد المحمودي
|
أحمد المحمودي
|
||||||
404allen404
|
404allen404
|
||||||
|
Tobias Jensen
|
||||||
|
|
|
||||||
|
|
@ -77,6 +77,7 @@ help:
|
||||||
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS)
|
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS)
|
||||||
|
|
||||||
clean mostlyclean distclean maintainer-clean::
|
clean mostlyclean distclean maintainer-clean::
|
||||||
|
rm -rf _build
|
||||||
rm -f $(SCRIPTS) *.tmp
|
rm -f $(SCRIPTS) *.tmp
|
||||||
rm -f *.aux *.cp *.cps *.dvi *.fn *.fns *.ky *.kys *.log
|
rm -f *.aux *.cp *.cps *.dvi *.fn *.fns *.ky *.kys *.log
|
||||||
rm -f *.pg *.pgs *.toc *.tp *.tps *.vr *.vrs *.idx
|
rm -f *.pg *.pgs *.toc *.tp *.tps *.vr *.vrs *.idx
|
||||||
|
|
|
||||||
|
|
@ -169,15 +169,7 @@ latex_elements = {
|
||||||
# Grouping the document tree into LaTeX files. List of tuples
|
# Grouping the document tree into LaTeX files. List of tuples
|
||||||
# (source start file, target name, title,
|
# (source start file, target name, title,
|
||||||
# author, documentclass [howto, manual, or own class]).
|
# author, documentclass [howto, manual, or own class]).
|
||||||
# latex_documents = [
|
# latex_documents = [ ... ]
|
||||||
# (
|
|
||||||
# master_doc,
|
|
||||||
# "Verilog-to-Routing.tex",
|
|
||||||
# "Verilog-to-Routing Documentation",
|
|
||||||
# "VTR Developers",
|
|
||||||
# "manual",
|
|
||||||
# ),
|
|
||||||
# ]
|
|
||||||
|
|
||||||
# For "manual" documents, if this is true, then toplevel headings are parts,
|
# For "manual" documents, if this is true, then toplevel headings are parts,
|
||||||
# not chapters.
|
# 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
|
:code:`$` character, i.e.: :code:`rootp` points to the Verilated
|
||||||
SystemVerilog :code:`$root` scope.
|
SystemVerilog :code:`$root` scope.
|
||||||
|
|
||||||
* Replace :code:`modelp->internal->member->lookup` references with
|
* Replace :code:`modelp->internal->member` references with
|
||||||
:code:`modelp->rootp->internal->member->lookup` references, which
|
:code:`modelp->rootp->internal->member` references, which
|
||||||
contain one additional indirection via the :code:`rootp` pointer.
|
contain one additional indirection via the :code:`rootp` pointer.
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -72,13 +72,17 @@ and the design can be easily manually reduced. In other cases, the bug is
|
||||||
caused by a complex interaction of many parts of the design, and it is not
|
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
|
clear which parts are necessary to reproduce the bug. In these cases, an
|
||||||
Open Source tool called `sv-bugpoint
|
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.
|
reduce a SystemVerilog design to the smallest possible reproducer.
|
||||||
It can be used to automatically reduce a design with hundreds of thousands of
|
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.
|
lines to a minimal test case while preserving the bug-inducing behavior.
|
||||||
|
|
||||||
Please refer to the `README
|
With :vlopt:`--debug`, Verilator will write a *{prefix}*\ __inputs\ .vpp
|
||||||
<https://github.com/antmicro/sv-bugpoint/blob/main/README.md>`_ file for more
|
file which has all of the individual input files combined and
|
||||||
|
pre-processed, this is often useful as the input design into `sv-bugpoint`.
|
||||||
|
|
||||||
|
Please refer to `sv-bugpoint README
|
||||||
|
<https://github.com/antmicro/sv-bugpoint/blob/main/README.md>`_ for more
|
||||||
information on how to use `sv-bugpoint`.
|
information on how to use `sv-bugpoint`.
|
||||||
|
|
||||||
.. Contributing
|
.. Contributing
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,11 @@ Summary:
|
||||||
|
|
||||||
Display help and exit.
|
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>
|
.. option:: +verilator+prof+exec+file+<filename>
|
||||||
|
|
||||||
When a model was Verilated using :vlopt:`--prof-exec`, sets the
|
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
|
simulation runtime random seed value. If zero or not specified picks a
|
||||||
value from the system random number generator.
|
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
|
.. option:: +verilator+V
|
||||||
|
|
||||||
Shows the verbose version, including configuration information.
|
Shows the verbose version, including configuration information.
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
.. Copyright 2003-2025 by Wilson Snyder.
|
.. Copyright 2003-2025 by Wilson Snyder.
|
||||||
.. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
.. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||||
|
|
||||||
|
=====================
|
||||||
verilator Arguments
|
verilator Arguments
|
||||||
===================
|
=====================
|
||||||
|
|
||||||
The following arguments may be passed to the "verilator" executable.
|
The following arguments may be passed to the "verilator" executable.
|
||||||
|
|
||||||
|
|
@ -11,20 +12,6 @@ Summary:
|
||||||
.. include:: ../_build/gen/args_verilator.rst
|
.. 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>
|
.. option:: <file.a/.o/.so>
|
||||||
|
|
||||||
Specifies optional object or library files to be linked with the
|
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
|
rule that uses these files when linking the module's executable. This
|
||||||
generally is only useful when used with the :vlopt:`--exe` option.
|
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-1995ext+<ext>
|
||||||
|
|
||||||
.. option:: +1364-2001ext+<ext>
|
.. option:: +1364-2001ext+<ext>
|
||||||
|
|
@ -146,13 +147,16 @@ Summary:
|
||||||
|
|
||||||
This option was named `--bin` before version 4.228.
|
This option was named `--bin` before version 4.228.
|
||||||
|
|
||||||
.. option:: --build-jobs [<value>]
|
.. option:: --build-jobs <value>
|
||||||
|
|
||||||
Specify the level of parallelism for :vlopt:`--build`. If zero, uses the
|
Specify the level of parallelism for :vlopt:`--build`. If zero, uses the
|
||||||
number of threads in the current hardware. Otherwise, the <value> must
|
number of threads in the current hardware. Otherwise, the <value> must
|
||||||
be a positive integer specifying the maximum number of parallel build
|
be a positive integer specifying the maximum number of parallel build
|
||||||
jobs.
|
jobs.
|
||||||
|
|
||||||
|
If not provided, and :vlopt:`-j` is provided, the :vlopt:`-j` value is
|
||||||
|
used.
|
||||||
|
|
||||||
This forms the :command:`make` option ``-j`` value, unless the
|
This forms the :command:`make` option ``-j`` value, unless the
|
||||||
:option:`MAKEFLAGS` environment variable contains ``-jobserver-auth``,
|
:option:`MAKEFLAGS` environment variable contains ``-jobserver-auth``,
|
||||||
in which case Verilator assumes that make's jobserver is being used.
|
in which case Verilator assumes that make's jobserver is being used.
|
||||||
|
|
@ -328,11 +332,11 @@ Summary:
|
||||||
detailed messages. See :vlopt:`--debug` for other implications of
|
detailed messages. See :vlopt:`--debug` for other implications of
|
||||||
enabling debug.
|
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
|
When creating output Verilated code, set level of comment and whitespace
|
||||||
decoration.
|
decoration.
|
||||||
|
|
@ -359,10 +363,6 @@ Summary:
|
||||||
between different Verilator runs, this may harm compile caching and
|
between different Verilator runs, this may harm compile caching and
|
||||||
should only be used for debug.
|
should only be used for debug.
|
||||||
|
|
||||||
.. option:: --no-decoration
|
|
||||||
|
|
||||||
Alias for ``--decorations none``.
|
|
||||||
|
|
||||||
.. option:: --default-language <value>
|
.. option:: --default-language <value>
|
||||||
|
|
||||||
Select the language used by default when first processing each
|
Select the language used by default when first processing each
|
||||||
|
|
@ -399,6 +399,11 @@ Summary:
|
||||||
name or location of the emitted DPI header file, it is output in
|
name or location of the emitted DPI header file, it is output in
|
||||||
:vlopt:`--Mdir` as it would be without this option.
|
: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
|
.. option:: --dump-defines
|
||||||
|
|
||||||
With :vlopt:`-E`, suppress normal output, and instead print a list of
|
With :vlopt:`-E`, suppress normal output, and instead print a list of
|
||||||
|
|
@ -430,18 +435,6 @@ Summary:
|
||||||
:vlopt:`--debug --no-dump-tree <--dump-tree>` may be useful if the dump
|
:vlopt:`--debug --no-dump-tree <--dump-tree>` may be useful if the dump
|
||||||
files are large and not desired.
|
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
|
.. option:: --dump-tree-addrids
|
||||||
|
|
||||||
Rarely needed - for developer use. Replace AST node addresses with
|
Rarely needed - for developer use. Replace AST node addresses with
|
||||||
|
|
@ -451,10 +444,24 @@ Summary:
|
||||||
by a newly allocated node after a node with the same address has been
|
by a newly allocated node after a node with the same address has been
|
||||||
dumped and then freed.
|
dumped and then freed.
|
||||||
|
|
||||||
.. option:: --dump-<srcfile>
|
.. option:: --dump-tree-dot
|
||||||
|
|
||||||
Rarely needed - for developer use. Enable all dumping in the given
|
Rarely needed. Enable dumping Ast .tree.dot debug files in Graphviz
|
||||||
source file at level 3.
|
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>
|
.. option:: --dumpi-dfg <level>
|
||||||
|
|
||||||
|
|
@ -476,13 +483,6 @@ Summary:
|
||||||
Rarely needed - for developer use. Set internal Ast JSON dumping level
|
Rarely needed - for developer use. Set internal Ast JSON dumping level
|
||||||
globally to the specified value.
|
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
|
.. option:: -E
|
||||||
|
|
||||||
Preprocess the source code, but do not compile, similar to C++
|
Preprocess the source code, but do not compile, similar to C++
|
||||||
|
|
@ -566,7 +566,7 @@ Summary:
|
||||||
|
|
||||||
.. option:: -fno-const
|
.. 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
|
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
|
option is solely for the purpose of DFG testing and should not be used
|
||||||
|
|
@ -589,14 +589,14 @@ Summary:
|
||||||
|
|
||||||
Disable individual DFG peephole optimizer pattern.
|
Disable individual DFG peephole optimizer pattern.
|
||||||
|
|
||||||
.. option:: -fno-dfg-pre-inline
|
|
||||||
|
|
||||||
Do not apply the DFG optimizer before inlining.
|
|
||||||
|
|
||||||
.. option:: -fno-dfg-post-inline
|
.. option:: -fno-dfg-post-inline
|
||||||
|
|
||||||
Do not apply the DFG optimizer after inlining.
|
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-expand
|
||||||
|
|
||||||
.. option:: -fno-func-opt
|
.. option:: -fno-func-opt
|
||||||
|
|
@ -641,6 +641,11 @@ Summary:
|
||||||
are typically used only when recommended by a maintainer to help debug
|
are typically used only when recommended by a maintainer to help debug
|
||||||
or work around an issue.
|
or work around an issue.
|
||||||
|
|
||||||
|
.. option:: -fno-var-split
|
||||||
|
|
||||||
|
Do not attempt to split variables automatically. Variables explicitly
|
||||||
|
annotated with :option:`/*verilator&32;split_var*/` are still split.
|
||||||
|
|
||||||
.. option:: -future0 <option>
|
.. option:: -future0 <option>
|
||||||
|
|
||||||
Rarely needed. Suppress an unknown Verilator option for an option that
|
Rarely needed. Suppress an unknown Verilator option for an option that
|
||||||
|
|
@ -716,14 +721,6 @@ Summary:
|
||||||
Generate a true-random key suitable for use with :vlopt:`--protect-key`,
|
Generate a true-random key suitable for use with :vlopt:`--protect-key`,
|
||||||
print it, and exit immediately.
|
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>
|
.. option:: --get-supported <feature>
|
||||||
|
|
||||||
If the given feature is supported, print "1" and exit
|
If the given feature is supported, print "1" and exit
|
||||||
|
|
@ -733,6 +730,14 @@ Summary:
|
||||||
|
|
||||||
Feature may be one of the following: COROUTINES, SYSTEMC.
|
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
|
.. option:: --help
|
||||||
|
|
||||||
Displays this message and program version and exits.
|
Displays this message and program version and exits.
|
||||||
|
|
@ -788,9 +793,21 @@ Summary:
|
||||||
|
|
||||||
Specify the level of parallelism for :vlopt:`--build` if
|
Specify the level of parallelism for :vlopt:`--build` if
|
||||||
:vlopt:`--build-jobs` isn't provided, and the internal compilation steps
|
:vlopt:`--build-jobs` isn't provided, and the internal compilation steps
|
||||||
of Verilator if :vlopt:`--verilate-jobs` isn't provided. If zero, uses
|
of Verilator if :vlopt:`--verilate-jobs` isn't provided. Also sets
|
||||||
the number of threads in the current hardware. Otherwise, must be a
|
:vlopt:`--output-groups` if isn't provided.
|
||||||
positive integer specifying the maximum number of parallel build jobs.
|
|
||||||
|
If zero, uses the number of threads in the current hardware. Otherwise,
|
||||||
|
must be a positive integer specifying the maximum number of parallel
|
||||||
|
build jobs.
|
||||||
|
|
||||||
|
.. option:: --no-json-edit-nums
|
||||||
|
|
||||||
|
Don't dump edit number in .tree.json files. This may make the file more
|
||||||
|
run-to-run stable for easier comparison.
|
||||||
|
|
||||||
|
.. option:: --no-json-ids
|
||||||
|
|
||||||
|
Don't use short identifiers instead of addresses/paths in .tree.json.
|
||||||
|
|
||||||
.. option:: --json-only
|
.. option:: --json-only
|
||||||
|
|
||||||
|
|
@ -815,15 +832,6 @@ Summary:
|
||||||
Specifies the filename for the main output file (`.tree.json`) of --json-only.
|
Specifies the filename for the main output file (`.tree.json`) of --json-only.
|
||||||
Using this option automatically sets :vlopt:`--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>
|
.. option:: --l2-name <value>
|
||||||
|
|
||||||
Instead of using the module name when showing Verilog scope, use the
|
Instead of using the module name when showing Verilog scope, use the
|
||||||
|
|
@ -897,28 +905,6 @@ Summary:
|
||||||
Rarely needed. Set the maximum variable size in bytes for it to be
|
Rarely needed. Set the maximum variable size in bytes for it to be
|
||||||
subject to localizing-to-stack optimization. Defaults to 1024.
|
subject to localizing-to-stack optimization. Defaults to 1024.
|
||||||
|
|
||||||
.. option:: --make <build-tool>
|
|
||||||
|
|
||||||
Generates a script for the specified build tool.
|
|
||||||
|
|
||||||
Supported values are ``gmake`` for GNU Make and ``cmake`` for CMake.
|
|
||||||
Both can be specified together. If no build tool is specified, gmake is
|
|
||||||
assumed. The executable of gmake can be configured via the environment
|
|
||||||
variable :option:`MAKE`.
|
|
||||||
|
|
||||||
When using :vlopt:`--build`, Verilator takes over the responsibility of
|
|
||||||
building the model library/executable. For this reason :option:`--make`
|
|
||||||
cannot be specified when using :vlopt:`--build`.
|
|
||||||
|
|
||||||
.. option:: -MAKEFLAGS <string>
|
|
||||||
|
|
||||||
When using :vlopt:`--build`, add the specified argument to the invoked
|
|
||||||
make command line. For multiple flags, either pass them as a single
|
|
||||||
argument with space separators quoted in the shell (e.g. ``-MAKEFLAGS
|
|
||||||
"-a -b"``), or use multiple -MAKEFLAGS arguments
|
|
||||||
(e.g. ``-MAKEFLAGS -l -MAKEFLAGS -k``). Use of this option should not be
|
|
||||||
required for simple builds using the host toolchain.
|
|
||||||
|
|
||||||
.. option:: --main
|
.. option:: --main
|
||||||
|
|
||||||
Generates a top-level C++ main() file that supports parsing arguments,
|
Generates a top-level C++ main() file that supports parsing arguments,
|
||||||
|
|
@ -944,6 +930,30 @@ Summary:
|
||||||
|
|
||||||
If the string ``"-"`` is used, no top level scope is added.
|
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>
|
.. option:: --max-num-width <value>
|
||||||
|
|
||||||
Set the maximum number literal width (e.g., in 1024'd22 this
|
Set the maximum number literal width (e.g., in 1024'd22 this
|
||||||
|
|
@ -978,6 +988,11 @@ Summary:
|
||||||
|
|
||||||
Ignored for compatibility with other simulators.
|
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
|
.. option:: -O0
|
||||||
|
|
||||||
Disables optimization of the model.
|
Disables optimization of the model.
|
||||||
|
|
@ -998,11 +1013,6 @@ Summary:
|
||||||
is deprecated and the various `-f<optimization>` arguments should be
|
is deprecated and the various `-f<optimization>` arguments should be
|
||||||
used instead.
|
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
|
.. option:: --no-order-clock-delay
|
||||||
|
|
||||||
Deprecated and has no effect (ignored).
|
Deprecated and has no effect (ignored).
|
||||||
|
|
@ -1016,18 +1026,24 @@ Summary:
|
||||||
.. option:: --output-groups <numfiles>
|
.. option:: --output-groups <numfiles>
|
||||||
|
|
||||||
Enables concatenating the output .cpp files into the given number of
|
Enables concatenating the output .cpp files into the given number of
|
||||||
effective output .cpp files. This is useful if the compiler startup
|
effective output .cpp files. This minimizes the compiler startup
|
||||||
overhead from compiling many small files becomes unacceptable,
|
overhead from compiling many small files, which can happen in designs
|
||||||
which can happen in designs making extensive use of SystemVerilog classes,
|
making extensive use of SystemVerilog classes, templates or generate
|
||||||
templates or generate blocks.
|
blocks.
|
||||||
|
|
||||||
Using :vlopt:`--output-groups` can adversely impact caching and stability
|
Using :vlopt:`--output-groups` can adversely impact caching and stability
|
||||||
(as in reproducibility) of compiled code. Compilation of larger .cpp
|
(as in reproducibility) of compiled code. Compilation of larger .cpp
|
||||||
files also has higher memory requirements. Too low values might result in
|
files also has higher memory requirements. Too low values might result in
|
||||||
swap thrashing with large designs, high values give no benefits. The
|
swap thrashing with large designs, high values give no benefits.
|
||||||
value should range from 2 to 20 for small to medium designs.
|
|
||||||
|
|
||||||
Default is zero, which disables this feature.
|
Typically setting the number of files to the hardware thread count,
|
||||||
|
corresponding to number of compiler jobs that can run in parallel, will
|
||||||
|
lead to fastest build times. (e.g. for small to medium designs the value
|
||||||
|
should range from 2 to 20.)
|
||||||
|
|
||||||
|
Zero disables this feature. Negative one, the default, sets the groups
|
||||||
|
to the value from :vlopt:`--build-jobs`, or from :vlopt:`-j`, or zero in
|
||||||
|
that priority.
|
||||||
|
|
||||||
.. option:: --output-split <statements>
|
.. option:: --output-split <statements>
|
||||||
|
|
||||||
|
|
@ -1088,6 +1104,14 @@ Summary:
|
||||||
position to indicate the corresponding bit of the __out variable has
|
position to indicate the corresponding bit of the __out variable has
|
||||||
a value being driven from within the Verilated model.
|
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
|
.. option:: --pins-sc-uint
|
||||||
|
|
||||||
Specifies SystemC inputs/outputs greater than 2 bits wide should use
|
Specifies SystemC inputs/outputs greater than 2 bits wide should use
|
||||||
|
|
@ -1099,14 +1123,6 @@ Summary:
|
||||||
|
|
||||||
Specifies SystemC inputs/outputs one bit wide should use sc_uint<1>.
|
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
|
.. option:: --pins-uint8
|
||||||
|
|
||||||
Specifies SystemC inputs/outputs smaller than the
|
Specifies SystemC inputs/outputs smaller than the
|
||||||
|
|
@ -1468,25 +1484,21 @@ Summary:
|
||||||
|
|
||||||
A synonym for :vlopt:`+1800-2023ext+\<ext\>`.
|
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
|
.. option:: --no-threads
|
||||||
|
|
||||||
Deprecated and has no effect (ignored).
|
Deprecated and has no effect (ignored).
|
||||||
|
|
||||||
In versions before 5.004, created a model which was not thread-safe.
|
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
|
When using :vlopt:`--threads`, controls which DPI imported tasks and
|
||||||
functions are considered thread-safe.
|
functions are considered thread-safe.
|
||||||
|
|
@ -1520,10 +1532,10 @@ Summary:
|
||||||
does not occur before a given module. Default is "1ps/1ps" (to match
|
does not occur before a given module. Default is "1ps/1ps" (to match
|
||||||
SystemC). This is overridden by :vlopt:`--timescale-override`.
|
SystemC). This is overridden by :vlopt:`--timescale-override`.
|
||||||
|
|
||||||
.. option:: --timescale-override <timeunit>/<timeprecision>
|
|
||||||
|
|
||||||
.. option:: --timescale-override /<timeprecision>
|
.. option:: --timescale-override /<timeprecision>
|
||||||
|
|
||||||
|
.. option:: --timescale-override <timeunit>/<timeprecision>
|
||||||
|
|
||||||
Overrides all "\`timescale"s in sources. The timeunit may be left empty
|
Overrides all "\`timescale"s in sources. The timeunit may be left empty
|
||||||
to specify only to override the timeprecision, e.g. "/1fs".
|
to specify only to override the timeprecision, e.g. "/1fs".
|
||||||
|
|
||||||
|
|
@ -1555,26 +1567,19 @@ Summary:
|
||||||
|
|
||||||
.. option:: --trace
|
.. option:: --trace
|
||||||
|
|
||||||
Adds waveform tracing code to the model using VCD format. This overrides
|
Deprecated; use :vlopt:`--trace-fst`, :vlopt:`--trace-saif` or
|
||||||
:vlopt:`--trace-fst`.
|
:vlopt:`--trace-vcd` instead.
|
||||||
|
|
||||||
Verilator will generate additional :file:`<prefix>__Trace*.cpp` files
|
Using :vlopt:`--trace` without :vlopt:`--trace-fst` nor
|
||||||
must be compiled. In addition :file:`verilated_vcd_sc.cpp`
|
:vlopt:`--trace-fst` requests VCD traces.
|
||||||
(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,
|
Using :vlopt:`--trace` :vlopt:`--trace-fst` requests FST traces.
|
||||||
even when tracing is not turned on during model execution.
|
|
||||||
|
|
||||||
When using :vlopt:`--threads`, VCD tracing is parallelized, using the
|
Using :vlopt:`--trace` :vlopt:`--trace-saif` requests SAIF traces.
|
||||||
same number of threads as passed to :vlopt:`--threads`.
|
|
||||||
|
|
||||||
.. option:: --trace-coverage
|
.. 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
|
traced signal for every :vlopt:`--coverage-line` or
|
||||||
:vlopt:`--coverage-user`\ -inserted coverage point, to assist in
|
:vlopt:`--coverage-user`\ -inserted coverage point, to assist in
|
||||||
debugging coverage items. Note :vlopt:`--coverage-toggle` does not get
|
debugging coverage items. Note :vlopt:`--coverage-toggle` does not get
|
||||||
|
|
@ -1614,6 +1619,12 @@ Summary:
|
||||||
|
|
||||||
Disable tracing of parameters.
|
Disable tracing of parameters.
|
||||||
|
|
||||||
|
.. option:: --trace-saif
|
||||||
|
|
||||||
|
Enable SAIF tracing in the model. This overrides :vlopt:`--trace`.
|
||||||
|
Specification of this format can be found in `IEEE 1801-2018
|
||||||
|
<https://ieeexplore.ieee.org/document/8686430>`_ (see Annex I).
|
||||||
|
|
||||||
.. option:: --trace-structs
|
.. option:: --trace-structs
|
||||||
|
|
||||||
Enable tracing to show the name of packed structure, union, and packed
|
Enable tracing to show the name of packed structure, union, and packed
|
||||||
|
|
@ -1648,6 +1659,24 @@ Summary:
|
||||||
underscore. Otherwise, these signals are not output during tracing. See
|
underscore. Otherwise, these signals are not output during tracing. See
|
||||||
also :vlopt:`--coverage-underscore` option.
|
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>
|
.. option:: -U<var>
|
||||||
|
|
||||||
Undefines the given preprocessor symbol.
|
Undefines the given preprocessor symbol.
|
||||||
|
|
@ -1700,13 +1729,16 @@ Summary:
|
||||||
execute only the build. This can be useful for rebuilding the Verilated code
|
execute only the build. This can be useful for rebuilding the Verilated code
|
||||||
produced by a previous invocation of Verilator.
|
produced by a previous invocation of Verilator.
|
||||||
|
|
||||||
.. option:: --verilate-jobs [<value>]
|
.. option:: --verilate-jobs <value>
|
||||||
|
|
||||||
Specify the level of parallelism for the internal compilation steps of
|
Specify the level of parallelism for the internal compilation steps of
|
||||||
Verilator. If zero, uses the number of threads in the current hardware.
|
Verilator. If zero, uses the number of threads in the current hardware.
|
||||||
Otherwise, must be a positive integer specifying the maximum number of
|
Otherwise, must be a positive integer specifying the maximum number of
|
||||||
parallel build jobs.
|
parallel build jobs.
|
||||||
|
|
||||||
|
If not provided, and :vlopt:`-j` is provided, the :vlopt:`-j` value is
|
||||||
|
used.
|
||||||
|
|
||||||
See also :vlopt:`-j`.
|
See also :vlopt:`-j`.
|
||||||
|
|
||||||
.. option:: +verilog1995ext+<ext>
|
.. option:: +verilog1995ext+<ext>
|
||||||
|
|
@ -1852,33 +1884,36 @@ Summary:
|
||||||
``-Wwarn-UNUSEDGENVAR`` ``-Wwarn-UNUSEDLOOP`` ``-Wwarn-UNUSEDPARAM``
|
``-Wwarn-UNUSEDGENVAR`` ``-Wwarn-UNUSEDLOOP`` ``-Wwarn-UNUSEDPARAM``
|
||||||
``-Wwarn-UNUSEDSIGNAL`` ``-Wwarn-VARHIDDEN``.
|
``-Wwarn-UNUSEDSIGNAL`` ``-Wwarn-VARHIDDEN``.
|
||||||
|
|
||||||
.. option:: --x-assign 0
|
.. option:: --x-assign <mode>
|
||||||
|
|
||||||
.. option:: --x-assign 1
|
|
||||||
|
|
||||||
.. option:: --x-assign fast (default)
|
|
||||||
|
|
||||||
.. option:: --x-assign unique
|
|
||||||
|
|
||||||
Controls the two-state value that is substituted when an explicit X
|
Controls the two-state value that is substituted when an explicit X
|
||||||
value is encountered in the source. "--x-assign fast", the default,
|
value is encountered in the source.
|
||||||
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.
|
|
||||||
|
|
||||||
If using "--x-assign unique", you may want to seed your random number
|
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
|
generator such that each regression run gets a different randomization
|
||||||
sequence. The simplest is to use the :vlopt:`+verilator+seed+\<value\>`
|
sequence. The simplest is to use the
|
||||||
runtime option. Alternatively, use the system's :code:`srand48()` or for
|
:vlopt:`+verilator+seed+\<value\>` runtime option. Alternatively, use
|
||||||
Windows :code:`srand()` function to do this. You'll probably also want
|
the system's :code:`srand48()` or for Windows :code:`srand()` function
|
||||||
to print any seeds selected, and code to enable rerunning with that same
|
to do this. You'll probably also want to print any seeds selected,
|
||||||
seed so you can reproduce bugs.
|
and code to enable rerunning with that same seed so you can reproduce
|
||||||
|
bugs.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
|
|
@ -1888,24 +1923,20 @@ Summary:
|
||||||
specified. Initial values of all other state holding variables are
|
specified. Initial values of all other state holding variables are
|
||||||
controlled with `--x-initial`.
|
controlled with `--x-initial`.
|
||||||
|
|
||||||
.. option:: --x-initial 0
|
.. option:: --x-initial <mode>
|
||||||
|
|
||||||
.. option:: --x-initial fast
|
|
||||||
|
|
||||||
.. option:: --x-initial unique (default)
|
|
||||||
|
|
||||||
Controls the two-state value used to initialize variables that
|
Controls the two-state value used to initialize variables that
|
||||||
are not otherwise initialized.
|
are not otherwise initialized.
|
||||||
|
|
||||||
"--x-initial 0",
|
With "--x-initial 0",
|
||||||
initializes all otherwise uninitialized variables to zero.
|
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
|
initializes variables using a function, which determines the value to
|
||||||
use for each initialization. This gives the greatest flexibility and
|
use for each initialization. This gives the greatest flexibility and
|
||||||
allows for finding reset bugs. See :ref:`Unknown states`.
|
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
|
is best for performance, and initializes all variables to a state
|
||||||
Verilator determines is optimal. This may allow further code
|
Verilator determines is optimal. This may allow further code
|
||||||
optimizations, but will likely hide any code bugs relating to missing
|
optimizations, but will likely hide any code bugs relating to missing
|
||||||
|
|
@ -1986,8 +2017,9 @@ Summary:
|
||||||
|
|
||||||
.. _Configuration Files:
|
.. _Configuration Files:
|
||||||
|
|
||||||
|
=====================
|
||||||
Configuration Files
|
Configuration Files
|
||||||
===================
|
=====================
|
||||||
|
|
||||||
In addition to the command line, warnings and other features for the
|
In addition to the command line, warnings and other features for the
|
||||||
:command:`verilator` command may be controlled with configuration files,
|
:command:`verilator` command may be controlled with configuration files,
|
||||||
|
|
@ -2020,15 +2052,6 @@ The grammar of configuration commands is as follows:
|
||||||
|
|
||||||
Take the remaining text and treat it as Verilator configuration commands.
|
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>"
|
.. option:: clock_enable -module "<modulename>" -var "<signame>"
|
||||||
|
|
||||||
Deprecated and has no effect (ignored).
|
Deprecated and has no effect (ignored).
|
||||||
|
|
@ -2040,30 +2063,42 @@ The grammar of configuration commands is as follows:
|
||||||
|
|
||||||
Same as :option:`/*verilator&32;clock_enable*/` metacomment.
|
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:: 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>" [-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
|
Indicates whether the signal is used as clock or not. Verilator uses
|
||||||
this information to mark the signal and any derived signals as clocker.
|
this information to mark the signal and any derived signals as clocker.
|
||||||
See :vlopt:`--clk`.
|
See :vlopt:`--clk`.
|
||||||
|
|
||||||
Same as :option:`/*verilator&32;clocker*/` metacomment.
|
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 -file "<filename>" -line <lineno>
|
||||||
|
|
||||||
|
.. option:: coverage_block_off -module "<modulename>" -block "<blockname>"
|
||||||
|
|
||||||
Specifies the entire begin/end block should be ignored for coverage
|
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
|
analysis purposes. It can either be specified as a named block or as a
|
||||||
filename and line number.
|
filename and line number.
|
||||||
|
|
||||||
Same as :option:`/*verilator&32;coverage_block_off*/` metacomment.
|
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>"
|
.. option:: forceable -module "<modulename>" -var "<signame>"
|
||||||
|
|
||||||
Generate public `<signame>__VforceEn` and `<signame>__VforceVal` signals
|
Generate public `<signame>__VforceEn` and `<signame>__VforceVal` signals
|
||||||
|
|
@ -2074,11 +2109,8 @@ The grammar of configuration commands is as follows:
|
||||||
|
|
||||||
.. option:: full_case -file "<filename>" -lines <lineno>
|
.. option:: full_case -file "<filename>" -lines <lineno>
|
||||||
|
|
||||||
.. option:: parallel_case -file "<filename>" -lines <lineno>
|
Same as :code:`//synthesis full_case`. When these synthesis directives
|
||||||
|
are discovered, Verilator will either formally prove the directive to be
|
||||||
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
|
|
||||||
true, or, failing that, will insert the appropriate code to detect
|
true, or, failing that, will insert the appropriate code to detect
|
||||||
failing cases at simulation runtime and print an "Assertion failed"
|
failing cases at simulation runtime and print an "Assertion failed"
|
||||||
error message.
|
error message.
|
||||||
|
|
@ -2096,20 +2128,27 @@ The grammar of configuration commands is as follows:
|
||||||
This option should not be used directly.
|
This option should not be used directly.
|
||||||
See :ref:`Hierarchical Verilation`.
|
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>"
|
.. option:: inline -module "<modulename>"
|
||||||
|
|
||||||
Specifies the module may be inlined into any modules that use this
|
Specifies the module may be inlined into any modules that use this
|
||||||
module. Same as :option:`/*verilator&32;inline_module*/` metacomment.
|
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>"
|
.. t_dist_docs_style ignore no_inline
|
||||||
|
|
||||||
.. 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.
|
|
||||||
|
|
||||||
.. option:: no_inline -module "<modulename>"
|
.. option:: no_inline -module "<modulename>"
|
||||||
|
|
||||||
|
|
@ -2117,10 +2156,10 @@ The grammar of configuration commands is as follows:
|
||||||
this module. Same as :option:`/*verilator&32;no_inline_module*/`
|
this module. Same as :option:`/*verilator&32;no_inline_module*/`
|
||||||
metacomment.
|
metacomment.
|
||||||
|
|
||||||
.. option:: no_inline [-module "<modulename>"] -task "<taskname>"
|
|
||||||
|
|
||||||
.. option:: no_inline [-module "<modulename>"] -function "<funcname>"
|
.. 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
|
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. 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
|
used a very large number of times. For this flag to work, the task and
|
||||||
|
|
@ -2129,12 +2168,22 @@ The grammar of configuration commands is as follows:
|
||||||
|
|
||||||
Same as :option:`/*verilator&32;no_inline_task*/` metacomment.
|
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>" [-lines <line> [ - <line>]]]
|
||||||
|
|
||||||
.. option:: lint_off [-rule <message>] [-file "<filename>"] [-contents "<wildcard>"] [-match "<wildcard>"]
|
.. 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
|
Enable/disables the specified lint warning, in the specified filename
|
||||||
(or wildcard with '\*' or '?', or all files if omitted) and range of
|
(or wildcard with '\*' or '?', or all files if omitted) and range of
|
||||||
line numbers (or all lines if omitted).
|
line numbers (or all lines if omitted).
|
||||||
|
|
@ -2165,18 +2214,13 @@ The grammar of configuration commands is as follows:
|
||||||
Before version 4.026, :code:`-rule` was named :code:`-msg`, and
|
Before version 4.026, :code:`-rule` was named :code:`-msg`, and
|
||||||
:code:`-msg` remained a deprecated alias until Version 5.000.
|
: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>"
|
Same as :code:`//synthesis parallel_case`. When these synthesis
|
||||||
|
directives are discovered, Verilator will either formally prove the
|
||||||
.. option:: public_flat_rd [-module "<modulename>"] [-task/-function "<taskname>"] -var "<signame>"
|
directive to be true, or, failing that, will insert the appropriate code
|
||||||
|
to detect failing cases at simulation runtime and print an "Assertion
|
||||||
.. option:: public_flat_rw [-module "<modulename>"] [-task/-function "<taskname>"] -var "<signame>" "@(edge)"
|
failed" error message.
|
||||||
|
|
||||||
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:: profile_data -hier-dpi "<function_name>" -cost <cost_value>
|
.. option:: profile_data -hier-dpi "<function_name>" -cost <cost_value>
|
||||||
|
|
||||||
|
|
@ -2191,18 +2235,31 @@ The grammar of configuration commands is as follows:
|
||||||
order to improve model runtime performance. This option is not expected
|
order to improve model runtime performance. This option is not expected
|
||||||
to be used by users directly. See :ref:`Thread PGO`.
|
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>" [-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,
|
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*/`
|
uint32_t, or uint64_t. Same as :option:`/*verilator&32;sc_bv*/`
|
||||||
metacomment.
|
metacomment.
|
||||||
|
|
||||||
.. option:: sformat [-module "<modulename>"] [-task "<taskname>"] -var "<signame>"
|
|
||||||
|
|
||||||
.. option:: sformat [-module "<modulename>"] [-function "<funcname>"] -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
|
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
|
function or task to indicate that the function or task should pass all
|
||||||
remaining arguments through $sformatf. This allows the creation of DPI
|
remaining arguments through $sformatf. This allows the creation of DPI
|
||||||
|
|
@ -2211,20 +2268,20 @@ The grammar of configuration commands is as follows:
|
||||||
|
|
||||||
Same as :option:`/*verilator&32;sformat*/` metacomment.
|
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>"] [-function "<funcname>"] -var "<varname>"
|
||||||
|
|
||||||
|
.. option:: split_var [-module "<modulename>"] [-task "<taskname>"] -var "<varname>"
|
||||||
|
|
||||||
Break the variable into multiple pieces typically to resolve UNOPTFLAT
|
Break the variable into multiple pieces typically to resolve UNOPTFLAT
|
||||||
performance issues. Typically the variables to attach this to are
|
performance issues. Typically the variables to attach this to are
|
||||||
recommended by Verilator itself; see :option:`UNOPTFLAT`.
|
recommended by Verilator itself; see :option:`UNOPTFLAT`.
|
||||||
|
|
||||||
Same as :option:`/*verilator&32;split_var*/` metacomment.
|
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_off [-file "<filename>" [-lines <line> [ - <line>]]]
|
||||||
|
|
||||||
|
.. option:: timing_on [-file "<filename>" [-lines <line> [ - <line>]]]
|
||||||
|
|
||||||
Enables/disables timing constructs for the specified file and lines.
|
Enables/disables timing constructs for the specified file and lines.
|
||||||
When disabled, all timing control constructs in the specified source
|
When disabled, all timing control constructs in the specified source
|
||||||
code locations are ignored the same way as with the
|
code locations are ignored the same way as with the
|
||||||
|
|
@ -2234,14 +2291,17 @@ The grammar of configuration commands is as follows:
|
||||||
Same as :option:`/*verilator&32;timing_on*/`,
|
Same as :option:`/*verilator&32;timing_on*/`,
|
||||||
:option:`/*verilator&32;timing_off*/` metacomments.
|
: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_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_off [-scope "<scopename>" [-levels <levels> ]]
|
||||||
|
|
||||||
|
.. option:: tracing_on [-scope "<scopename>" [-levels <levels> ]]
|
||||||
|
|
||||||
Enable/disable waveform tracing for all future signals declared in
|
Enable/disable waveform tracing for all future signals declared in
|
||||||
all files.
|
all files.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -49,24 +49,25 @@ verilator_coverage Arguments
|
||||||
|
|
||||||
.. option:: <filename>
|
.. option:: <filename>
|
||||||
|
|
||||||
Specifies the input coverage data file. Multiple filenames may be provided
|
Specifies the input coverage data file. Multiple filenames may be
|
||||||
to read multiple inputs. If no data file is specified, by default,
|
provided to read multiple inputs. If no data file is specified, by
|
||||||
"coverage.dat" will be read.
|
default, "coverage.dat" will be read.
|
||||||
|
|
||||||
.. option:: --annotate <output_directory>
|
.. option:: --annotate <output_directory>
|
||||||
|
|
||||||
Specifies the directory name to which source files with annotated coverage
|
Specifies the directory name to which source files with annotated
|
||||||
data should be written.
|
coverage data should be written.
|
||||||
|
|
||||||
Points are children of each line coverage- branches, expressions or toggle points.
|
Points are children of each line coverage- branches, expressions or
|
||||||
When point counts are aggregated into a line, the minimum and maximum counts
|
toggle points. When point counts are aggregated into a line, the
|
||||||
are used to determine the status of the line (complete, partial, failing)
|
minimum and maximum counts are used to determine the status of the line
|
||||||
The count is equal to the maximum of the points.
|
(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
|
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
|
as a special character followed by the number of coverage hits. The
|
||||||
characters " ,%,~,+,-" indicate summary of the coverage, and allow use of grep
|
special characters " ,%,~,+,-" indicate summary of the coverage, and
|
||||||
to filter the report.
|
allow use of grep to filter the report.
|
||||||
|
|
||||||
* " " (whitespace) indicates that all points on the line are above the coverage min.
|
* " " (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 all points on the line are below the coverage min.
|
||||||
|
|
@ -91,16 +92,17 @@ to filter the report.
|
||||||
|
|
||||||
.. option:: --annotate-all
|
.. option:: --annotate-all
|
||||||
|
|
||||||
Specifies all files should be shown. By default, only those source files
|
Specifies all files should be shown. By default, only those source
|
||||||
with low coverage are written to the output directory.
|
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>
|
.. option:: --annotate-min <count>
|
||||||
|
|
||||||
Specifies the threshold (<count>) below which coverage point is considered
|
Specifies the threshold (<count>) below which coverage point is
|
||||||
sufficient. If the threshold is not exceeded, then the annotation will begin
|
considered sufficient. If the threshold is not exceeded, then the
|
||||||
with a "%" symbol to indicate the coverage is insufficient.
|
annotation will begin with a "%" symbol to indicate the coverage is
|
||||||
|
insufficient.
|
||||||
|
|
||||||
The <count> threshold defaults to 10.
|
The <count> threshold defaults to 10.
|
||||||
|
|
||||||
|
|
@ -128,19 +130,20 @@ Displays a help summary, the program version, and exits.
|
||||||
|
|
||||||
.. option:: --rank
|
.. option:: --rank
|
||||||
|
|
||||||
Prints an experimental report listing the relative importance of each test
|
Prints an experimental report listing the relative importance of each
|
||||||
in covering all of the coverage points. The report shows "Covered" which
|
test in covering all of the coverage points. The report shows "Covered"
|
||||||
indicates the number of points the test covers; a test is considered to
|
which indicates the number of points the test covers; a test is
|
||||||
cover a point if it has a bucket count of at least 1. The "rank" column has
|
considered to cover a point if it has a bucket count of at least 1. The
|
||||||
a higher number t indicate the test is more critical, and rank 0 means the
|
"rank" column has a higher number t indicate the test is more critical,
|
||||||
test does not need to be run to cover the points. "RankPts" indicates the
|
and rank 0 means the test does not need to be run to cover the points.
|
||||||
number of coverage points this test will contribute to overall coverage if
|
"RankPts" indicates the number of coverage points this test will
|
||||||
all tests are run in the order of highest to the lowest rank.
|
contribute to overall coverage if all tests are run in the order of
|
||||||
|
highest to the lowest rank.
|
||||||
|
|
||||||
.. option:: --unlink
|
.. option:: --unlink
|
||||||
|
|
||||||
With :option:`--write`, unlink all input files after the output
|
With :option:`--write`, unlink all input files after the output has been
|
||||||
has been successfully created.
|
successfully created.
|
||||||
|
|
||||||
.. option:: --version
|
.. option:: --version
|
||||||
|
|
||||||
|
|
@ -149,9 +152,9 @@ Displays program version and exits.
|
||||||
.. option:: --write <filename>
|
.. option:: --write <filename>
|
||||||
|
|
||||||
Specifies the aggregate coverage results, summed across all the files,
|
Specifies the aggregate coverage results, summed across all the files,
|
||||||
should be written to the given filename in verilator_coverage data format.
|
should be written to the given filename in verilator_coverage data
|
||||||
This is useful in scripts to combine many coverage data files (likely
|
format. This is useful in scripts to combine many coverage data files
|
||||||
generated from random test runs) into one master coverage file.
|
(likely generated from random test runs) into one master coverage file.
|
||||||
|
|
||||||
.. option:: --write-info <filename.info>
|
.. option:: --write-info <filename.info>
|
||||||
|
|
||||||
|
|
@ -159,6 +162,6 @@ Specifies the aggregate coverage results, summed across all the files,
|
||||||
should be written to the given filename in :command:`lcov` .info format.
|
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
|
This may be used to feed into :command:`lcov` to aggregate or generate
|
||||||
reports. This format lacks the comments for cover points that the
|
reports. This format lacks the comments for cover points that the
|
||||||
verilator_coverage format has. It can be used with :command:`genhtml`
|
verilator_coverage format has. It can be used with :command:`genhtml` to
|
||||||
to generate an HTML report. :command:`genhtml --branch-coverage` will
|
generate an HTML report. :command:`genhtml --branch-coverage` will also
|
||||||
also display the branch coverage, analogous to :option:`--annotate-points`
|
display the branch coverage, analogous to :option:`--annotate-points`.
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,10 @@ predicted_parallelism
|
||||||
cpu#_thread
|
cpu#_thread
|
||||||
For the given CPU number, the thread number measured to be executing.
|
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
|
mtask#_cpu
|
||||||
For the given mtask id, the CPU it was measured to execute on.
|
For the given mtask id, the CPU it was measured to execute on.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,19 @@
|
||||||
.. Copyright 2003-2025 by Wilson Snyder.
|
.. Copyright 2003-2025 by Wilson Snyder.
|
||||||
.. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
.. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||||
|
|
||||||
*******************
|
=====================
|
||||||
Language Extensions
|
Language Extensions
|
||||||
*******************
|
=====================
|
||||||
|
|
||||||
The following additional constructs are the extensions Verilator supports
|
The following additional constructs are the extensions Verilator supports
|
||||||
on top of standard Verilog code. Using these features outside of comments
|
on top of standard Verilog code. Using these features outside of comments
|
||||||
or "`ifdef`"'s may break other tools.
|
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__
|
.. option:: `__FILE__
|
||||||
|
|
||||||
The :option:`\`__FILE__` define expands to the current filename as a
|
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
|
C++'s __LINE__. This Verilator feature added in 2006 was incorporated
|
||||||
into IEEE 1800-2009.
|
into IEEE 1800-2009.
|
||||||
|
|
||||||
|
.. option:: `coverage_block_off
|
||||||
|
|
||||||
|
Specifies the entire begin/end block should be ignored for coverage
|
||||||
|
analysis. Must be inside a code block, e.g., within a begin/end pair.
|
||||||
|
Same as :option:`coverage_block_off` in :ref:`Configuration Files`.
|
||||||
|
|
||||||
.. option:: `error [string]
|
.. option:: `error [string]
|
||||||
|
|
||||||
This will report an error when the preprocessor emits it, similar to
|
This will report an error when the preprocessor emits it, similar to
|
||||||
|
|
@ -33,10 +44,116 @@ or "`ifdef`"'s may break other tools.
|
||||||
internal tests, so that debugging can leave the line numbers correctly
|
internal tests, so that debugging can leave the line numbers correctly
|
||||||
referring to the test file's line numbers.
|
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
|
Inside one of the :option:`\`systemc_... <\`systemc_header>` text
|
||||||
single quotes. This extension was standardized in IEEE 1800-2023.
|
blocks, replaced with the C++ class name generated for the given
|
||||||
|
containing SystemVerilog class or module. Currently this is replaced
|
||||||
|
blindly, ignoring quoting or other escapes; this behavior may change in
|
||||||
|
the future. This attribute is indented only to be used internally in
|
||||||
|
`verilated_std.sv`.
|
||||||
|
|
||||||
|
.. option:: `systemc_ctor
|
||||||
|
|
||||||
|
Take the remaining text up to the next :option:`\`verilog` or
|
||||||
|
:option:`\`systemc_... <\`systemc_header>` mode switch and place it
|
||||||
|
verbatim into the C++ class constructor. Must be placed as a module or
|
||||||
|
class item, e.g., directly inside a module/endmodule or class/endclass
|
||||||
|
pair. Despite the name of this macro, this also works in pure C++ code.
|
||||||
|
|
||||||
|
.. option:: `systemc_dtor
|
||||||
|
|
||||||
|
Take the remaining text up to the next :option:`\`verilog` or
|
||||||
|
:option:`\`systemc_... <\`systemc_header>` mode switch and place it
|
||||||
|
verbatim into the C++ class destructor. Must be placed as a module or
|
||||||
|
class item, e.g., directly inside a module/endmodule or class/endclass
|
||||||
|
pair. Despite the name of this macro, this also works in pure C++ code.
|
||||||
|
|
||||||
|
.. option:: `systemc_header
|
||||||
|
|
||||||
|
Take the remaining text up to the next :option:`\`verilog` or
|
||||||
|
:option:`\`systemc_... <\`systemc_header>` mode switch and place it
|
||||||
|
verbatim into the output .h file's header. Must be placed as a module
|
||||||
|
or class item, e.g., directly inside a module/endmodule or
|
||||||
|
class/endclass pair. Despite the name of this macro, this also works in
|
||||||
|
pure C++ code.
|
||||||
|
|
||||||
|
.. option:: `systemc_header_post
|
||||||
|
|
||||||
|
Take the remaining text up to the next :option:`\`verilog` or
|
||||||
|
:option:`\`systemc_... <\`systemc_header>` mode switch and place it
|
||||||
|
verbatim into the output .h file's header after the class definition.
|
||||||
|
Must be placed as a module or class item, e.g., directly inside a
|
||||||
|
module/endmodule or class/endclass pair. Despite the name of this macro,
|
||||||
|
this also works in pure C++ code.
|
||||||
|
|
||||||
|
.. option:: `systemc_imp_header
|
||||||
|
|
||||||
|
Take the remaining text up to the next :option:`\`verilog` or
|
||||||
|
:option:`\`systemc_... <\`systemc_header>` mode switch and place it
|
||||||
|
verbatim into the header of all files for this C++ class implementation.
|
||||||
|
Must be placed as a module or class item, e.g., directly inside a
|
||||||
|
module/endmodule or class/endclass pair. Despite the name of this macro,
|
||||||
|
this also works in pure C++ code.
|
||||||
|
|
||||||
|
.. option:: `systemc_implementation
|
||||||
|
|
||||||
|
Take the remaining text up to the next :option:`\`verilog` or
|
||||||
|
:option:`\`systemc_... <\`systemc_header>` mode switch and place it
|
||||||
|
verbatim into a single file of the C++ class implementation. Must be
|
||||||
|
placed as a module or class item, e.g., directly inside a
|
||||||
|
module/endmodule or class/endclass pair. Despite the name of this macro,
|
||||||
|
this also works in pure C++ code.
|
||||||
|
|
||||||
|
If you will be reading or writing any Verilog variables in the C++
|
||||||
|
functions, the Verilog signals must be declared with a
|
||||||
|
:option:`/*verilator&32;public*/` metacomment. See also the public task
|
||||||
|
feature; writing an accessor may result in cleaner code.
|
||||||
|
|
||||||
|
.. option:: `systemc_interface
|
||||||
|
|
||||||
|
Take the remaining text up to the next :option:`\`verilog` or
|
||||||
|
:option:`\`systemc_... <\`systemc_header>` mode switch and place it
|
||||||
|
verbatim into the C++ class interface. Must be placed as a module or
|
||||||
|
class item, e.g., directly inside a module/endmodule or class/endclass
|
||||||
|
pair. Despite the name of this macro, this also works in pure C++ code.
|
||||||
|
|
||||||
|
.. option:: `SYSTEMVERILOG
|
||||||
|
|
||||||
|
The SYSTEMVERILOG, SV_COV_START, and related standard predefined macros
|
||||||
|
are defined by default when :vlopt:`--language <--language>` is
|
||||||
|
"1800-\*".
|
||||||
|
|
||||||
|
.. option:: `VERILATOR
|
||||||
|
|
||||||
|
.. option:: `verilator
|
||||||
|
|
||||||
|
.. option:: `verilator3
|
||||||
|
|
||||||
|
The VERILATOR, verilator and verilator3 predefined macros are defined by
|
||||||
|
default so you may "\`ifdef" around tool specific constructs.
|
||||||
|
|
||||||
|
.. option:: `verilator_config
|
||||||
|
|
||||||
|
Take the remaining text up to the next :option:`\`verilog` mode switch and
|
||||||
|
treat it as Verilator configuration commands. See :ref:`Configuration Files`.
|
||||||
|
|
||||||
|
.. option:: `VERILATOR_TIMING
|
||||||
|
|
||||||
|
The VERILATOR_TIMING define is set when :vlopt:`--timing` is used to
|
||||||
|
allow an "\`ifdef" of code dependent on this feature. Note that this define
|
||||||
|
is not affected by the :option:`timing_off` configuration file option
|
||||||
|
nor timing metacomments.
|
||||||
|
|
||||||
|
.. option:: `verilog
|
||||||
|
|
||||||
|
Switch back to processing Verilog code after a
|
||||||
|
:option:`\`systemc_... <\`systemc_header>` mode switch. The Verilog
|
||||||
|
code returns to the last language mode specified with
|
||||||
|
"\`begin_keywords", or SystemVerilog if none was specified.
|
||||||
|
|
||||||
|
|
||||||
|
.. t_dist_docs_style restart_sort
|
||||||
|
|
||||||
.. option:: $c([string], ...);
|
.. option:: $c([string], ...);
|
||||||
|
|
||||||
|
|
@ -86,6 +203,16 @@ or "`ifdef`"'s may break other tools.
|
||||||
prints 5 digits per the C standard. This extension was standardized into
|
prints 5 digits per the C standard. This extension was standardized into
|
||||||
1800-2009.
|
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
|
.. option:: $timeprecision
|
||||||
|
|
||||||
Returns the timeprecision of the model as an integer. This extension is
|
Returns the timeprecision of the model as an integer. This extension is
|
||||||
|
|
@ -96,98 +223,6 @@ or "`ifdef`"'s may break other tools.
|
||||||
Returns the timeunit of the current module as an integer. This
|
Returns the timeunit of the current module as an integer. This
|
||||||
extension is experimental and may be removed without deprecation.
|
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*/
|
.. option:: /*verilator&32;clock_enable*/
|
||||||
|
|
||||||
Deprecated and has no effect (ignored).
|
Deprecated and has no effect (ignored).
|
||||||
|
|
@ -212,6 +247,9 @@ or "`ifdef`"'s may break other tools.
|
||||||
|
|
||||||
Same as :option:`clock_enable` configuration file option.
|
Same as :option:`clock_enable` configuration file option.
|
||||||
|
|
||||||
|
|
||||||
|
.. t_dist_docs_style ignore /*verilator&32;no_clocker*/
|
||||||
|
|
||||||
.. option:: /*verilator&32;clocker*/
|
.. option:: /*verilator&32;clocker*/
|
||||||
|
|
||||||
.. option:: /*verilator&32;no_clocker*/
|
.. option:: /*verilator&32;no_clocker*/
|
||||||
|
|
@ -379,29 +417,6 @@ or "`ifdef`"'s may break other tools.
|
||||||
|
|
||||||
parameter [2:0] PARAM /*verilator public*/ = 2'b0;
|
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)
|
.. option:: /*verilator&32;public*/ (on task/function)
|
||||||
|
|
||||||
Used inside the declaration section of a function or task declaration to
|
Used inside the declaration section of a function or task declaration to
|
||||||
|
|
@ -426,6 +441,52 @@ or "`ifdef`"'s may break other tools.
|
||||||
|
|
||||||
Same as :option:`public` configuration file option.
|
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)
|
.. option:: /*verilator&32;public_flat*/ (on variable)
|
||||||
|
|
||||||
Used after an input, output, register, or wire declaration to indicate
|
Used after an input, output, register, or wire declaration to indicate
|
||||||
|
|
@ -453,33 +514,6 @@ or "`ifdef`"'s may break other tools.
|
||||||
|
|
||||||
Same as :option:`public_flat_rw` configuration file option.
|
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*/
|
.. option:: /*verilator&32;public_module*/
|
||||||
|
|
||||||
Used after a module statement to indicate the module should not be
|
Used after a module statement to indicate the module should not be
|
||||||
|
|
@ -490,13 +524,9 @@ or "`ifdef`"'s may break other tools.
|
||||||
|
|
||||||
Same as :option:`public` configuration file option.
|
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
|
Terminates the previous `/*verilator public*_on*/` directive; see above.
|
||||||
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;sc_bv*/
|
.. option:: /*verilator&32;sc_bv*/
|
||||||
|
|
||||||
|
|
@ -509,6 +539,14 @@ or "`ifdef`"'s may break other tools.
|
||||||
|
|
||||||
Same as :option:`sc_bv` configuration file option.
|
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*/
|
.. option:: /*verilator&32;sformat*/
|
||||||
|
|
||||||
Attached to the final argument of type "input string" of a function or
|
Attached to the final argument of type "input string" of a function or
|
||||||
|
|
@ -550,6 +588,20 @@ or "`ifdef`"'s may break other tools.
|
||||||
large arrays may slow down the Verilation speed, so use this only on
|
large arrays may slow down the Verilation speed, so use this only on
|
||||||
variables that require it.
|
variables that require it.
|
||||||
|
|
||||||
|
Packed variables that are only referenced locally (without hierarchical
|
||||||
|
references) via non-overlapping, constant-indexed bit or part select
|
||||||
|
expressions are split automatically. This covers the somewhat common
|
||||||
|
usage pattern:
|
||||||
|
|
||||||
|
.. code-block:: sv
|
||||||
|
|
||||||
|
logic [1:0][31:0] tmp;
|
||||||
|
|
||||||
|
assign tmp[0] = foo + a;
|
||||||
|
assign tmp[1] = tmp[1] + b;
|
||||||
|
assign bar = tmp[1] + c;
|
||||||
|
|
||||||
|
|
||||||
Same as :option:`split_var` configuration file option.
|
Same as :option:`split_var` configuration file option.
|
||||||
|
|
||||||
.. option:: /*verilator&32;tag <text...>*/
|
.. option:: /*verilator&32;tag <text...>*/
|
||||||
|
|
@ -583,7 +635,7 @@ or "`ifdef`"'s may break other tools.
|
||||||
Attached to a DPI import to indicate that function should be called when
|
Attached to a DPI import to indicate that function should be called when
|
||||||
initializing tracing. This attribute is indented only to be used
|
initializing tracing. This attribute is indented only to be used
|
||||||
internally in code that Verilator generates when :vlopt:`--lib-create`
|
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*/
|
.. option:: /*verilator&32;tracing_off*/
|
||||||
|
|
||||||
|
|
@ -613,13 +665,3 @@ or "`ifdef`"'s may break other tools.
|
||||||
following loop at the same statement level should always be fully
|
following loop at the same statement level should always be fully
|
||||||
unrolled by Verilator, ignoring :vlopt:`--unroll-count`. This is
|
unrolled by Verilator, ignoring :vlopt:`--unroll-count`. This is
|
||||||
similar to clang's ``#pragma clang loop unroll(full)``.
|
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.
|
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,
|
``$dumpvars`` to enable traces, the same as with any Verilog simulator,
|
||||||
although Verilator ignores the arguments to ``$dumpvars``. See
|
although Verilator ignores the arguments to ``$dumpvars``. See
|
||||||
``examples/make_tracing_c`` in the distribution.
|
``examples/make_tracing_c`` in the distribution.
|
||||||
|
|
@ -177,7 +177,7 @@ file.
|
||||||
How do I generate waveforms (traces) in SystemC?
|
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
|
:code:`sc_main()`, call :code:`Verilated::traceEverOn(true)`. Then you
|
||||||
may use :code:`$dumpfile` and code:`$dumpvars` to enable traces, as
|
may use :code:`$dumpfile` and code:`$dumpvars` to enable traces, as
|
||||||
with any Verilog simulator; see the non-SystemC example in
|
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
|
* - *{prefix}*\ ___024root\ *{__DepSet_hash__n}*\ .cpp
|
||||||
- Infrequent cold routines (hashed to reduce build times)
|
- Infrequent cold routines (hashed to reduce build times)
|
||||||
* - *{prefix}*\ ___024root__Trace\ *{__n}*\ .cpp
|
* - *{prefix}*\ ___024root__Trace\ *{__n}*\ .cpp
|
||||||
- Wave file generation code (from --trace)
|
- Wave file generation code (from --trace-\*)
|
||||||
* - *{prefix}*\ ___024root__Trace__Slow\ *{__n}*\ .cpp
|
* - *{prefix}*\ ___024root__Trace__Slow\ *{__n}*\ .cpp
|
||||||
- Wave file generation code (from --trace)
|
- Wave file generation code (from --trace-\*)
|
||||||
* - *{prefix}*\ __Dpi.h
|
* - *{prefix}*\ __Dpi.h
|
||||||
- DPI import and export declarations (from --dpi)
|
- DPI import and export declarations (from --dpi)
|
||||||
* - *{prefix}*\ __Dpi.cpp
|
* - *{prefix}*\ __Dpi.cpp
|
||||||
|
|
|
||||||
|
|
@ -15,9 +15,9 @@ Package Manager Quick Install
|
||||||
=============================
|
=============================
|
||||||
|
|
||||||
Using a distribution's package manager is the easiest way to get
|
Using a distribution's package manager is the easiest way to get
|
||||||
started. (Note packages are unlikely to have the most recent version, so
|
started. (Note distribution packages almost never have the most recent
|
||||||
:ref:`Git Install` might be a better alternative.) To install as a
|
Verilator version, so we recommend following :ref:`Git Install` below,
|
||||||
package:
|
instead.) To install as a package:
|
||||||
|
|
||||||
.. code-block:: shell
|
.. 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 libfl-dev # Ubuntu only (ignore if gives error)
|
||||||
sudo apt-get install zlibc zlib1g zlib1g-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
|
To build or run Verilator, the following are optional but should be installed
|
||||||
for good performance:
|
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 mold # If present at build, needed for run
|
||||||
sudo apt-get install libgoogle-perftools-dev numactl
|
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
|
To build Verilator you will need to install these packages; these do not
|
||||||
need to be present to run Verilator:
|
need to be present to run Verilator:
|
||||||
|
|
||||||
|
|
@ -146,7 +158,7 @@ Those developing Verilator itself may also want these (see internals.rst):
|
||||||
.. code-block:: shell
|
.. code-block:: shell
|
||||||
|
|
||||||
sudo apt-get install clang clang-format-14 cmake gdb gprof graphviz lcov
|
sudo apt-get install clang clang-format-14 cmake gdb gprof graphviz lcov
|
||||||
sudo apt-get install python3-clang yapf3 bear jq
|
sudo apt-get install python3-clang python3-distro yapf3 bear jq
|
||||||
sudo pip3 install sphinx sphinx_rtd_theme sphinxcontrib-spelling breathe ruff
|
sudo pip3 install sphinx sphinx_rtd_theme sphinxcontrib-spelling breathe ruff
|
||||||
sudo pip3 install git+https://github.com/antmicro/astsee.git
|
sudo pip3 install git+https://github.com/antmicro/astsee.git
|
||||||
cpan install Pod::Perldoc
|
cpan install Pod::Perldoc
|
||||||
|
|
@ -155,7 +167,10 @@ Those developing Verilator itself may also want these (see internals.rst):
|
||||||
Install SystemC
|
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
|
<https://www.accellera.org/downloads/standards/systemc>`__. Follow their
|
||||||
installation instructions. You will need to set the
|
installation instructions. You will need to set the
|
||||||
:option:`SYSTEMC_INCLUDE` environment variable to point to the include
|
: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
|
<http://gtkwave.sourceforge.net/>`__ installed, however this is not
|
||||||
required at Verilator build time.
|
required at Verilator build time.
|
||||||
|
|
||||||
|
.. code-block:: shell
|
||||||
|
|
||||||
|
sudo apt-get install gtkwave # Optional Waveform viewer
|
||||||
|
|
||||||
|
|
||||||
Install Z3
|
Install Z3
|
||||||
^^^^^^^^^^
|
^^^^^^^^^^
|
||||||
|
|
|
||||||
|
|
@ -334,7 +334,8 @@ Gate Primitives
|
||||||
|
|
||||||
The 2-state gate primitives (and, buf, nand, nor, not, or, xnor, xor) are
|
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
|
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
|
Specify blocks
|
||||||
|
|
@ -396,8 +397,8 @@ This section describes specific limitations for each language keyword.
|
||||||
\`begin_keywords, \`begin_keywords, \`begin_keywords, \`begin_keywords,
|
\`begin_keywords, \`begin_keywords, \`begin_keywords, \`begin_keywords,
|
||||||
\`define, \`else, \`elsif, \`end_keywords, \`endif, \`error, \`ifdef,
|
\`define, \`else, \`elsif, \`end_keywords, \`endif, \`error, \`ifdef,
|
||||||
\`ifndef, \`include, \`line, \`systemc_ctor, \`systemc_dtor,
|
\`ifndef, \`include, \`line, \`systemc_ctor, \`systemc_dtor,
|
||||||
\`systemc_header, \`systemc_imp_header, \`systemc_implementation,
|
\`systemc_header, \`systemc_header_post, \`systemc_imp_header,
|
||||||
\`systemc_interface, \`undef, \`verilog
|
\`systemc_implementation, \`systemc_interface, \`undef, \`verilog
|
||||||
|
|
||||||
|cmdslong1|
|
|cmdslong1|
|
||||||
Fully supported.
|
Fully supported.
|
||||||
|
|
@ -451,17 +452,17 @@ disable
|
||||||
force, release
|
force, release
|
||||||
Verilator supports the procedural `force` (and corresponding `release`)
|
Verilator supports the procedural `force` (and corresponding `release`)
|
||||||
statement. However, the behavior of the `force` statement does not
|
statement. However, the behavior of the `force` statement does not
|
||||||
entirely comply with IEEE 1800. According to the standard, when a
|
entirely comply with IEEE 1800-2023:
|
||||||
procedural statement of the form `force a = b;` is executed, the
|
|
||||||
simulation should behave as if, from that point forwards, a continuous
|
#. Using forced variable as a value to another force statement is
|
||||||
assignment `assign a = b;` has been added to override the drivers of `a`.
|
currently not supported. The dependent force statement is forced by an
|
||||||
More specifically: the value of `a` should be updated whenever the value
|
initial constant value.
|
||||||
of `b` changes, until a `release a;` statement is executed. Verilator
|
|
||||||
instead evaluates the current value of `b` when the `force` statement is
|
#. Force/release with procedural continuous assignment is not supported.
|
||||||
executed, and forces `a` to that value, without updating it until a new
|
The assignment is treated as procedural.
|
||||||
`force` or `release` statement is encountered that applies to `a`. This
|
|
||||||
non-standard behavior is nevertheless consistent with some other
|
#. Expressions using multiple variable references or function calls on
|
||||||
simulators.
|
forced right-hand side are not sensitive to dependency changes.
|
||||||
|
|
||||||
inside
|
inside
|
||||||
Inside expressions may not include unpacked array traversal or $ as an
|
Inside expressions may not include unpacked array traversal or $ as an
|
||||||
|
|
@ -488,7 +489,7 @@ $bits, $countbits, $countones, $finish, $isunknown, $onehot, $onehot0, $signed,
|
||||||
|
|
||||||
$dump/$dumpports and related
|
$dump/$dumpports and related
|
||||||
$dumpfile or $dumpports will create a VCD or FST file (based on
|
$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
|
will take effect starting at the next eval() call. If you have multiple
|
||||||
Verilated designs under the same C model, this will dump signals
|
Verilated designs under the same C model, this will dump signals
|
||||||
only from the design containing the $dumpvars.
|
only from the design containing the $dumpvars.
|
||||||
|
|
|
||||||
|
|
@ -83,9 +83,10 @@ option will require a longer time to run Verilator, and
|
||||||
may increase the risk of reset bugs in trade for performance; see the above
|
may increase the risk of reset bugs in trade for performance; see the above
|
||||||
documentation for these options.
|
documentation for these options.
|
||||||
|
|
||||||
If using Verilated multithreaded, use ``numactl`` to ensure you use
|
If using Verilated multithreaded, consider overriding Verilator's default
|
||||||
non-conflicting hardware resources. See :ref:`Multithreading`. Also,
|
thread-to-processor assignment by using ``numactl``; see
|
||||||
consider using profile-guided optimization; see :ref:`Thread PGO`.
|
: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
|
Minor Verilog code changes can also give big wins. You should not have any
|
||||||
:option:`UNOPTFLAT` warnings from Verilator. Fixing these warnings can
|
:option:`UNOPTFLAT` warnings from Verilator. Fixing these warnings can
|
||||||
|
|
|
||||||
|
|
@ -221,7 +221,7 @@ model, it may be beneficial to performance to adjust the
|
||||||
influences the partitioning of the model by adjusting the assumed execution
|
influences the partitioning of the model by adjusting the assumed execution
|
||||||
time of DPI imports.
|
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
|
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.
|
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.
|
of setting :vlopt:`--trace-threads` higher than 2 at the moment.
|
||||||
|
|
||||||
When running a multithreaded model, the default Linux task scheduler often
|
When running a multithreaded model, the default Linux task scheduler often
|
||||||
works against the model by assuming short-lived threads and thus
|
works against the model by assuming short-lived threads and thus it often
|
||||||
it often schedules threads using multiple hyperthreads within the same
|
schedules threads using multiple hyperthreads within the same physical
|
||||||
physical core. For best performance, use the :command:`numactl` program to
|
core. If there is no affinity already set, on Linux only, Verilator
|
||||||
(when the threading count fits) select unique physical cores on the same
|
attempts to set thread-to-processor affinity in a reasonable way.
|
||||||
socket. The same applies for :vlopt:`--trace-threads` as well.
|
|
||||||
|
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
|
As an example, if a model was Verilated with
|
||||||
:vlopt:`--threads 4 <--threads>`, we consult:
|
: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,
|
If using :vlopt:`--sc`, the SystemC kernel is not thread-safe; therefore,
|
||||||
the eval thread and main thread must be the same.
|
the eval thread and main thread must be the same.
|
||||||
|
|
||||||
If using :vlopt:`--trace`, the tracing classes must be constructed and
|
If using :vlopt:`--trace-vcd` or other trace options, the tracing classes
|
||||||
called from the main thread.
|
must be constructed and called from the main thread.
|
||||||
|
|
||||||
If using :vlopt:`--vpi`, since SystemVerilog VPI was not architected by
|
If using :vlopt:`--vpi`, since SystemVerilog VPI was not architected by
|
||||||
IEEE to be multithreaded, Verilator requires all VPI calls are only made
|
IEEE to be multithreaded, Verilator requires all VPI calls are only made
|
||||||
|
|
@ -367,10 +370,11 @@ Verilate in CMake
|
||||||
.. code-block:: CMake
|
.. code-block:: CMake
|
||||||
|
|
||||||
verilate(target SOURCES source ... [TOP_MODULE top] [PREFIX name]
|
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 ...]
|
[INCLUDE_DIRS dir ...] [OPT_SLOW ...] [OPT_FAST ...]
|
||||||
[OPT_GLOBAL ..] [DIRECTORY dir] [THREADS num]
|
[OPT_GLOBAL ..] [DIRECTORY dir] [THREADS num]
|
||||||
[TRACE_THREADS num] [VERILATOR_ARGS ...])
|
[VERILATOR_ARGS ...])
|
||||||
|
|
||||||
Lowercase and ... should be replaced with arguments; the uppercase parts
|
Lowercase and ... should be replaced with arguments; the uppercase parts
|
||||||
delimit the arguments and can be passed in any order or left out entirely
|
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`.
|
Optional. Enable a multithreaded model; see :vlopt:`--threads`.
|
||||||
|
|
||||||
.. describe:: TRACE_THREADS
|
|
||||||
|
|
||||||
Optional. Enable multithreaded FST trace; see :vlopt:`--trace-threads`.
|
|
||||||
|
|
||||||
.. describe:: TOP_MODULE
|
.. describe:: TOP_MODULE
|
||||||
|
|
||||||
Optional. Sets the name of the top module. Defaults to the name of the
|
Optional. Sets the name of the top module. Defaults to the name of the
|
||||||
|
|
@ -454,14 +454,27 @@ SystemC include directories and link to the SystemC libraries.
|
||||||
|
|
||||||
.. describe:: TRACE
|
.. describe:: TRACE
|
||||||
|
|
||||||
Optional. Enables VCD tracing if present, equivalent to "VERILATOR_ARGS
|
Deprecated. Same as TRACE_VCD, which should be used instead.
|
||||||
--trace".
|
|
||||||
|
|
||||||
.. describe:: TRACE_FST
|
.. describe:: TRACE_FST
|
||||||
|
|
||||||
Optional. Enables FST tracing if present, equivalent to "VERILATOR_ARGS
|
Optional. Enables FST tracing if present, equivalent to "VERILATOR_ARGS
|
||||||
--trace-fst".
|
--trace-fst".
|
||||||
|
|
||||||
|
.. describe:: TRACE_SAIF
|
||||||
|
|
||||||
|
Optional. Enables SAIF tracing if present, equivalent to "VERILATOR_ARGS
|
||||||
|
--trace-saif".
|
||||||
|
|
||||||
|
.. describe:: TRACE_THREADS
|
||||||
|
|
||||||
|
Optional. Enable multithreaded FST trace; see :vlopt:`--trace-threads`.
|
||||||
|
|
||||||
|
.. describe:: TRACE_VCD
|
||||||
|
|
||||||
|
Optional. Enables VCD tracing if present, equivalent to "VERILATOR_ARGS
|
||||||
|
--trace-vcd".
|
||||||
|
|
||||||
.. describe:: VERILATOR_ARGS
|
.. describe:: VERILATOR_ARGS
|
||||||
|
|
||||||
Optional. Extra arguments to Verilator. Do not specify :vlopt:`--Mdir`
|
Optional. Extra arguments to Verilator. Do not specify :vlopt:`--Mdir`
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
.. Copyright 2003-2025 by Wilson Snyder.
|
.. Copyright 2003-2025 by Wilson Snyder.
|
||||||
.. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
.. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||||
|
|
||||||
*******************
|
=====================
|
||||||
Errors and Warnings
|
Errors and Warnings
|
||||||
*******************
|
=====================
|
||||||
|
|
||||||
.. _Disabling Warnings:
|
.. _Disabling Warnings:
|
||||||
|
|
||||||
|
|
@ -86,6 +86,8 @@ List Of Warnings
|
||||||
Limitations`.
|
Limitations`.
|
||||||
|
|
||||||
|
|
||||||
|
.. t_dist_docs_style restart_sort
|
||||||
|
|
||||||
.. option:: ALWCOMBORDER
|
.. option:: ALWCOMBORDER
|
||||||
|
|
||||||
.. TODO better example
|
.. TODO better example
|
||||||
|
|
@ -472,6 +474,31 @@ List Of Warnings
|
||||||
correctly.
|
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
|
.. option:: DEFPARAM
|
||||||
|
|
||||||
Warns that the :code:`defparam` statement was deprecated in IEEE 1364-2001,
|
Warns that the :code:`defparam` statement was deprecated in IEEE 1364-2001,
|
||||||
|
|
@ -1222,13 +1249,6 @@ List Of Warnings
|
||||||
simulate correctly.
|
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
|
.. option:: NONSTD
|
||||||
|
|
||||||
Warns when a non-standard language feature is used that has a standard
|
Warns when a non-standard language feature is used that has a standard
|
||||||
|
|
@ -1237,6 +1257,13 @@ List Of Warnings
|
||||||
:code:`$sformatf`.
|
: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
|
.. option:: NULLPORT
|
||||||
|
|
||||||
Warns that a null port was detected in the module definition port
|
Warns that a null port was detected in the module definition port
|
||||||
|
|
@ -1261,6 +1288,7 @@ List Of Warnings
|
||||||
Ignoring this warning will only suppress the lint check; it will
|
Ignoring this warning will only suppress the lint check; it will
|
||||||
simulate correctly.
|
simulate correctly.
|
||||||
|
|
||||||
|
|
||||||
.. option:: PINCONNECTEMPTY
|
.. option:: PINCONNECTEMPTY
|
||||||
|
|
||||||
.. TODO better example
|
.. TODO better example
|
||||||
|
|
@ -1349,6 +1377,26 @@ List Of Warnings
|
||||||
This error may be disabled with a lint_off PINNOTFOUND metacomment.
|
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
|
.. option:: PORTSHORT
|
||||||
|
|
||||||
Warns that an output port is connected to a constant.
|
Warns that an output port is connected to a constant.
|
||||||
|
|
@ -1372,26 +1420,6 @@ List Of Warnings
|
||||||
This error may be disabled with a lint_off PORTSHORT metacomment.
|
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
|
.. option:: PREPROCZERO
|
||||||
|
|
||||||
Warns that a preprocessor \`ifdef/\`ifndef expression (added in IEEE
|
Warns that a preprocessor \`ifdef/\`ifndef expression (added in IEEE
|
||||||
|
|
@ -2181,21 +2209,6 @@ List Of Warnings
|
||||||
.. include:: ../../docs/gen/ex_WIDTHEXPAND_1_fixed.rst
|
.. 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
|
.. option:: WIDTHCONCAT
|
||||||
|
|
||||||
Warns that based on the width rules of Verilog, a concatenate, or
|
Warns that based on the width rules of Verilog, a concatenate, or
|
||||||
|
|
@ -2221,6 +2234,21 @@ List Of Warnings
|
||||||
width to the parameter usage (:code:`{PAR[31:0], PAR[31:0]}`).
|
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
|
.. option:: ZERODLY
|
||||||
|
|
||||||
Warns that `#0` delays do not schedule the process to be resumed in the
|
Warns that `#0` delays do not schedule the process to be resumed in the
|
||||||
|
|
|
||||||
|
|
@ -2046,6 +2046,11 @@ driver.py Non-Scenario Arguments
|
||||||
Same as ``verilator --debugi level``: Set Verilator internal debugging
|
Same as ``verilator --debugi level``: Set Verilator internal debugging
|
||||||
level globally to the specified debug level (1-10).
|
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
|
--dump-tree
|
||||||
Same as ``verilator --dump-tree``: Enable Verilator writing .tree debug
|
Same as ``verilator --dump-tree``: Enable Verilator writing .tree debug
|
||||||
files with dumping level 3, which dumps the standard critical stages.
|
files with dumping level 3, which dumps the standard critical stages.
|
||||||
|
|
@ -2077,7 +2082,10 @@ driver.py Non-Scenario Arguments
|
||||||
|
|
||||||
--j #
|
--j #
|
||||||
Run number of parallel tests, or 0 to determine the count based on the
|
Run number of parallel tests, or 0 to determine the count based on the
|
||||||
number of cores installed. Requires Perl's Parallel::Forker package.
|
number of cores installed.
|
||||||
|
|
||||||
|
--obj-suffix <name>
|
||||||
|
Append the argument to the name of the ``test_regress/obj_`` directories.
|
||||||
|
|
||||||
--quiet
|
--quiet
|
||||||
Suppress all output except for failures and progress messages every 15
|
Suppress all output except for failures and progress messages every 15
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ Asciidoc
|
||||||
Ashutosh
|
Ashutosh
|
||||||
Ast
|
Ast
|
||||||
Atmel
|
Atmel
|
||||||
|
Augustin
|
||||||
Aurelien
|
Aurelien
|
||||||
Badáň
|
Badáň
|
||||||
Bagri
|
Bagri
|
||||||
|
|
@ -109,6 +110,7 @@ Embecosm
|
||||||
Engstrom
|
Engstrom
|
||||||
Enzo
|
Enzo
|
||||||
Eugen
|
Eugen
|
||||||
|
Fabre
|
||||||
Fabrizio
|
Fabrizio
|
||||||
Faucher
|
Faucher
|
||||||
Faure
|
Faure
|
||||||
|
|
@ -650,6 +652,7 @@ elike
|
||||||
elsif
|
elsif
|
||||||
endcase
|
endcase
|
||||||
endcelldefine
|
endcelldefine
|
||||||
|
endclass
|
||||||
endfunction
|
endfunction
|
||||||
endgenerate
|
endgenerate
|
||||||
endian
|
endian
|
||||||
|
|
@ -860,6 +863,7 @@ noprivate
|
||||||
noreturn
|
noreturn
|
||||||
notif
|
notif
|
||||||
nullptr
|
nullptr
|
||||||
|
numactl
|
||||||
onehot
|
onehot
|
||||||
ooo
|
ooo
|
||||||
oprofile
|
oprofile
|
||||||
|
|
@ -960,6 +964,7 @@ runtime
|
||||||
runtimes
|
runtimes
|
||||||
rw
|
rw
|
||||||
sVerilator
|
sVerilator
|
||||||
|
saif
|
||||||
sawatzke
|
sawatzke
|
||||||
sc
|
sc
|
||||||
scalared
|
scalared
|
||||||
|
|
@ -1018,6 +1023,7 @@ swrite
|
||||||
synthesizeable
|
synthesizeable
|
||||||
sys
|
sys
|
||||||
systemc
|
systemc
|
||||||
|
tcmalloc
|
||||||
tenghtt
|
tenghtt
|
||||||
testbench
|
testbench
|
||||||
threadsafe
|
threadsafe
|
||||||
|
|
@ -1093,7 +1099,9 @@ verilator
|
||||||
verilog
|
verilog
|
||||||
verilogmod
|
verilogmod
|
||||||
verimake
|
verimake
|
||||||
|
veriuser
|
||||||
vl
|
vl
|
||||||
|
vlSelf
|
||||||
vlopt
|
vlopt
|
||||||
vlt
|
vlt
|
||||||
vltstd
|
vltstd
|
||||||
|
|
@ -1113,6 +1121,7 @@ vpiUndefined
|
||||||
vpm
|
vpm
|
||||||
vpp
|
vpp
|
||||||
warmup
|
warmup
|
||||||
|
wavealloca
|
||||||
waveforms
|
waveforms
|
||||||
whitespace
|
whitespace
|
||||||
widthed
|
widthed
|
||||||
|
|
|
||||||
|
|
@ -20,9 +20,11 @@
|
||||||
# binary relative to $VERILATOR_ROOT (such as when inside the git sources).
|
# binary relative to $VERILATOR_ROOT (such as when inside the git sources).
|
||||||
|
|
||||||
ifeq ($(VERILATOR_ROOT),)
|
ifeq ($(VERILATOR_ROOT),)
|
||||||
|
VERILATOR = verilator
|
||||||
VERILATOR_COVERAGE = verilator_coverage
|
VERILATOR_COVERAGE = verilator_coverage
|
||||||
else
|
else
|
||||||
export VERILATOR_ROOT
|
export VERILATOR_ROOT
|
||||||
|
VERILATOR = $(VERILATOR_ROOT)/bin/verilator
|
||||||
VERILATOR_COVERAGE = $(VERILATOR_ROOT)/bin/verilator_coverage
|
VERILATOR_COVERAGE = $(VERILATOR_ROOT)/bin/verilator_coverage
|
||||||
endif
|
endif
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
|
||||||
|
|
@ -20,9 +20,11 @@
|
||||||
# binary relative to $VERILATOR_ROOT (such as when inside the git sources).
|
# binary relative to $VERILATOR_ROOT (such as when inside the git sources).
|
||||||
|
|
||||||
ifeq ($(VERILATOR_ROOT),)
|
ifeq ($(VERILATOR_ROOT),)
|
||||||
|
VERILATOR = verilator
|
||||||
VERILATOR_COVERAGE = verilator_coverage
|
VERILATOR_COVERAGE = verilator_coverage
|
||||||
else
|
else
|
||||||
export VERILATOR_ROOT
|
export VERILATOR_ROOT
|
||||||
|
VERILATOR = $(VERILATOR_ROOT)/bin/verilator
|
||||||
VERILATOR_COVERAGE = $(VERILATOR_ROOT)/bin/verilator_coverage
|
VERILATOR_COVERAGE = $(VERILATOR_ROOT)/bin/verilator_coverage
|
||||||
endif
|
endif
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
|
||||||
|
|
@ -20,9 +20,11 @@
|
||||||
# binary relative to $VERILATOR_ROOT (such as when inside the git sources).
|
# binary relative to $VERILATOR_ROOT (such as when inside the git sources).
|
||||||
|
|
||||||
ifeq ($(VERILATOR_ROOT),)
|
ifeq ($(VERILATOR_ROOT),)
|
||||||
|
VERILATOR = verilator
|
||||||
VERILATOR_COVERAGE = verilator_coverage
|
VERILATOR_COVERAGE = verilator_coverage
|
||||||
else
|
else
|
||||||
export VERILATOR_ROOT
|
export VERILATOR_ROOT
|
||||||
|
VERILATOR = $(VERILATOR_ROOT)/bin/verilator
|
||||||
VERILATOR_COVERAGE = $(VERILATOR_ROOT)/bin/verilator_coverage
|
VERILATOR_COVERAGE = $(VERILATOR_ROOT)/bin/verilator_coverage
|
||||||
endif
|
endif
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ add_executable(example ../make_tracing_c/sim_main.cpp)
|
||||||
target_compile_features(example PUBLIC cxx_std_14)
|
target_compile_features(example PUBLIC cxx_std_14)
|
||||||
|
|
||||||
# Add the Verilated circuit to the target
|
# Add the Verilated circuit to the target
|
||||||
verilate(example COVERAGE TRACE
|
verilate(example COVERAGE TRACE_VCD
|
||||||
INCLUDE_DIRS "../make_tracing_c"
|
INCLUDE_DIRS "../make_tracing_c"
|
||||||
VERILATOR_ARGS -f ../make_tracing_c/input.vc -x-assign fast
|
VERILATOR_ARGS -f ../make_tracing_c/input.vc -x-assign fast
|
||||||
SOURCES ../make_tracing_c/top.v
|
SOURCES ../make_tracing_c/top.v
|
||||||
|
|
|
||||||
|
|
@ -20,9 +20,11 @@
|
||||||
# binary relative to $VERILATOR_ROOT (such as when inside the git sources).
|
# binary relative to $VERILATOR_ROOT (such as when inside the git sources).
|
||||||
|
|
||||||
ifeq ($(VERILATOR_ROOT),)
|
ifeq ($(VERILATOR_ROOT),)
|
||||||
|
VERILATOR = verilator
|
||||||
VERILATOR_COVERAGE = verilator_coverage
|
VERILATOR_COVERAGE = verilator_coverage
|
||||||
else
|
else
|
||||||
export VERILATOR_ROOT
|
export VERILATOR_ROOT
|
||||||
|
VERILATOR = $(VERILATOR_ROOT)/bin/verilator
|
||||||
VERILATOR_COVERAGE = $(VERILATOR_ROOT)/bin/verilator_coverage
|
VERILATOR_COVERAGE = $(VERILATOR_ROOT)/bin/verilator_coverage
|
||||||
endif
|
endif
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
@ -59,7 +61,7 @@ run:
|
||||||
@echo
|
@echo
|
||||||
@echo "-- RUN ---------------------"
|
@echo "-- RUN ---------------------"
|
||||||
@mkdir -p logs
|
@mkdir -p logs
|
||||||
build/example +trace
|
build/example +trace_vcd
|
||||||
|
|
||||||
@echo
|
@echo
|
||||||
@echo "-- COVERAGE ----------------"
|
@echo "-- COVERAGE ----------------"
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ target_compile_features(example PUBLIC cxx_std_14)
|
||||||
set_property(TARGET example PROPERTY CXX_STANDARD ${SystemC_CXX_STANDARD})
|
set_property(TARGET example PROPERTY CXX_STANDARD ${SystemC_CXX_STANDARD})
|
||||||
|
|
||||||
# Add the Verilated circuit to the target
|
# Add the Verilated circuit to the target
|
||||||
verilate(example SYSTEMC COVERAGE TRACE
|
verilate(example COVERAGE SYSTEMC TRACE_VCD
|
||||||
INCLUDE_DIRS "../make_tracing_sc"
|
INCLUDE_DIRS "../make_tracing_sc"
|
||||||
VERILATOR_ARGS -f ../make_tracing_sc/input.vc -x-assign fast
|
VERILATOR_ARGS -f ../make_tracing_sc/input.vc -x-assign fast
|
||||||
SOURCES ../make_tracing_sc/top.v
|
SOURCES ../make_tracing_sc/top.v
|
||||||
|
|
|
||||||
|
|
@ -20,9 +20,11 @@
|
||||||
# binary relative to $VERILATOR_ROOT (such as when inside the git sources).
|
# binary relative to $VERILATOR_ROOT (such as when inside the git sources).
|
||||||
|
|
||||||
ifeq ($(VERILATOR_ROOT),)
|
ifeq ($(VERILATOR_ROOT),)
|
||||||
|
VERILATOR = verilator
|
||||||
VERILATOR_COVERAGE = verilator_coverage
|
VERILATOR_COVERAGE = verilator_coverage
|
||||||
else
|
else
|
||||||
export VERILATOR_ROOT
|
export VERILATOR_ROOT
|
||||||
|
VERILATOR = $(VERILATOR_ROOT)/bin/verilator
|
||||||
VERILATOR_COVERAGE = $(VERILATOR_ROOT)/bin/verilator_coverage
|
VERILATOR_COVERAGE = $(VERILATOR_ROOT)/bin/verilator_coverage
|
||||||
endif
|
endif
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
@ -77,7 +79,7 @@ run:
|
||||||
@echo
|
@echo
|
||||||
@echo "-- RUN ---------------------"
|
@echo "-- RUN ---------------------"
|
||||||
@mkdir -p logs
|
@mkdir -p logs
|
||||||
build/example +trace
|
build/example +trace_vcd
|
||||||
|
|
||||||
@echo
|
@echo
|
||||||
@echo "-- COVERAGE ----------------"
|
@echo "-- COVERAGE ----------------"
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ VERILATOR_FLAGS += -Wall
|
||||||
VERILATOR_FLAGS += -CFLAGS -DVL_TIME_CONTEXT
|
VERILATOR_FLAGS += -CFLAGS -DVL_TIME_CONTEXT
|
||||||
|
|
||||||
# Make waveforms
|
# Make waveforms
|
||||||
TOP_VERILATOR_FLAGS = $(VERILATOR_FLAGS) --trace
|
TOP_VERILATOR_FLAGS = $(VERILATOR_FLAGS) --trace-vcd
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
default: run
|
default: run
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ VERILATOR_FLAGS += -x-assign fast
|
||||||
# Warn abount lint issues; may not want this on less solid designs
|
# Warn abount lint issues; may not want this on less solid designs
|
||||||
VERILATOR_FLAGS += -Wall
|
VERILATOR_FLAGS += -Wall
|
||||||
# Make waveforms
|
# Make waveforms
|
||||||
VERILATOR_FLAGS += --trace
|
VERILATOR_FLAGS += --trace-vcd
|
||||||
# Check SystemVerilog assertions
|
# Check SystemVerilog assertions
|
||||||
VERILATOR_FLAGS += --assert
|
VERILATOR_FLAGS += --assert
|
||||||
# Generate coverage analysis
|
# Generate coverage analysis
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ VERILATOR_FLAGS += -x-assign fast
|
||||||
# Warn abount lint issues; may not want this on less solid designs
|
# Warn abount lint issues; may not want this on less solid designs
|
||||||
VERILATOR_FLAGS += -Wall
|
VERILATOR_FLAGS += -Wall
|
||||||
# Make waveforms
|
# Make waveforms
|
||||||
VERILATOR_FLAGS += --trace
|
VERILATOR_FLAGS += --trace-vcd
|
||||||
# Check SystemVerilog assertions
|
# Check SystemVerilog assertions
|
||||||
VERILATOR_FLAGS += --assert
|
VERILATOR_FLAGS += --assert
|
||||||
# Generate coverage analysis
|
# Generate coverage analysis
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -26,7 +26,8 @@
|
||||||
#define FST_API_H
|
#define FST_API_H
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C"
|
||||||
|
{
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
@ -42,18 +43,18 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
#define FST_RDLOAD "FSTLOAD | "
|
|
||||||
|
|
||||||
typedef uint32_t fstHandle;
|
typedef uint32_t fstHandle;
|
||||||
typedef uint32_t fstEnumHandle;
|
typedef uint32_t fstEnumHandle;
|
||||||
|
|
||||||
enum fstWriterPackType {
|
enum fstWriterPackType
|
||||||
|
{
|
||||||
FST_WR_PT_ZLIB = 0,
|
FST_WR_PT_ZLIB = 0,
|
||||||
FST_WR_PT_FASTLZ = 1,
|
FST_WR_PT_FASTLZ = 1,
|
||||||
FST_WR_PT_LZ4 = 2
|
FST_WR_PT_LZ4 = 2
|
||||||
};
|
};
|
||||||
|
|
||||||
enum fstFileType {
|
enum fstFileType
|
||||||
|
{
|
||||||
FST_FT_MIN = 0,
|
FST_FT_MIN = 0,
|
||||||
|
|
||||||
FST_FT_VERILOG = 0,
|
FST_FT_VERILOG = 0,
|
||||||
|
|
@ -63,7 +64,8 @@ enum fstFileType {
|
||||||
FST_FT_MAX = 2
|
FST_FT_MAX = 2
|
||||||
};
|
};
|
||||||
|
|
||||||
enum fstBlockType {
|
enum fstBlockType
|
||||||
|
{
|
||||||
FST_BL_HDR = 0,
|
FST_BL_HDR = 0,
|
||||||
FST_BL_VCDATA = 1,
|
FST_BL_VCDATA = 1,
|
||||||
FST_BL_BLACKOUT = 2,
|
FST_BL_BLACKOUT = 2,
|
||||||
|
|
@ -78,7 +80,8 @@ enum fstBlockType {
|
||||||
FST_BL_SKIP = 255 /* used while block is being written */
|
FST_BL_SKIP = 255 /* used while block is being written */
|
||||||
};
|
};
|
||||||
|
|
||||||
enum fstScopeType {
|
enum fstScopeType
|
||||||
|
{
|
||||||
FST_ST_MIN = 0,
|
FST_ST_MIN = 0,
|
||||||
|
|
||||||
FST_ST_VCD_MODULE = 0,
|
FST_ST_VCD_MODULE = 0,
|
||||||
|
|
@ -114,7 +117,8 @@ enum fstScopeType {
|
||||||
FST_ST_VCD_UPSCOPE = 255
|
FST_ST_VCD_UPSCOPE = 255
|
||||||
};
|
};
|
||||||
|
|
||||||
enum fstVarType {
|
enum fstVarType
|
||||||
|
{
|
||||||
FST_VT_MIN = 0, /* start of vartypes */
|
FST_VT_MIN = 0, /* start of vartypes */
|
||||||
|
|
||||||
FST_VT_VCD_EVENT = 0,
|
FST_VT_VCD_EVENT = 0,
|
||||||
|
|
@ -139,7 +143,8 @@ enum fstVarType {
|
||||||
FST_VT_VCD_SPARRAY = 19, /* used to define the rownum (index) port for a sparse array */
|
FST_VT_VCD_SPARRAY = 19, /* used to define the rownum (index) port for a sparse array */
|
||||||
FST_VT_VCD_REALTIME = 20,
|
FST_VT_VCD_REALTIME = 20,
|
||||||
|
|
||||||
FST_VT_GEN_STRING = 21, /* generic string type (max len is defined dynamically via fstWriterEmitVariableLengthValueChange) */
|
FST_VT_GEN_STRING = 21, /* generic string type (max len is defined dynamically via
|
||||||
|
fstWriterEmitVariableLengthValueChange) */
|
||||||
|
|
||||||
FST_VT_SV_BIT = 22,
|
FST_VT_SV_BIT = 22,
|
||||||
FST_VT_SV_LOGIC = 23,
|
FST_VT_SV_LOGIC = 23,
|
||||||
|
|
@ -148,12 +153,14 @@ enum fstVarType {
|
||||||
FST_VT_SV_LONGINT = 26, /* declare as size = 64 */
|
FST_VT_SV_LONGINT = 26, /* declare as size = 64 */
|
||||||
FST_VT_SV_BYTE = 27, /* declare as size = 8 */
|
FST_VT_SV_BYTE = 27, /* declare as size = 8 */
|
||||||
FST_VT_SV_ENUM = 28, /* declare as appropriate type range */
|
FST_VT_SV_ENUM = 28, /* declare as appropriate type range */
|
||||||
FST_VT_SV_SHORTREAL = 29, /* declare and emit same as FST_VT_VCD_REAL (needs to be emitted as double, not a float) */
|
FST_VT_SV_SHORTREAL = 29, /* declare and emit same as FST_VT_VCD_REAL (needs to be emitted
|
||||||
|
as double, not a float) */
|
||||||
|
|
||||||
FST_VT_MAX = 29 /* end of vartypes */
|
FST_VT_MAX = 29 /* end of vartypes */
|
||||||
};
|
};
|
||||||
|
|
||||||
enum fstVarDir {
|
enum fstVarDir
|
||||||
|
{
|
||||||
FST_VD_MIN = 0,
|
FST_VD_MIN = 0,
|
||||||
|
|
||||||
FST_VD_IMPLICIT = 0,
|
FST_VD_IMPLICIT = 0,
|
||||||
|
|
@ -166,7 +173,8 @@ enum fstVarDir {
|
||||||
FST_VD_MAX = 5
|
FST_VD_MAX = 5
|
||||||
};
|
};
|
||||||
|
|
||||||
enum fstHierType {
|
enum fstHierType
|
||||||
|
{
|
||||||
FST_HT_MIN = 0,
|
FST_HT_MIN = 0,
|
||||||
|
|
||||||
FST_HT_SCOPE = 0,
|
FST_HT_SCOPE = 0,
|
||||||
|
|
@ -175,14 +183,16 @@ enum fstHierType {
|
||||||
FST_HT_ATTRBEGIN = 3,
|
FST_HT_ATTRBEGIN = 3,
|
||||||
FST_HT_ATTREND = 4,
|
FST_HT_ATTREND = 4,
|
||||||
|
|
||||||
/* FST_HT_TREEBEGIN and FST_HT_TREEEND are not yet used by FST but are currently used when fstHier bridges other formats */
|
/* FST_HT_TREEBEGIN and FST_HT_TREEEND are not yet used by FST but are currently used when
|
||||||
|
fstHier bridges other formats */
|
||||||
FST_HT_TREEBEGIN = 5,
|
FST_HT_TREEBEGIN = 5,
|
||||||
FST_HT_TREEEND = 6,
|
FST_HT_TREEEND = 6,
|
||||||
|
|
||||||
FST_HT_MAX = 6
|
FST_HT_MAX = 6
|
||||||
};
|
};
|
||||||
|
|
||||||
enum fstAttrType {
|
enum fstAttrType
|
||||||
|
{
|
||||||
FST_AT_MIN = 0,
|
FST_AT_MIN = 0,
|
||||||
|
|
||||||
FST_AT_MISC = 0, /* self-contained: does not need matching FST_HT_ATTREND */
|
FST_AT_MISC = 0, /* self-contained: does not need matching FST_HT_ATTREND */
|
||||||
|
|
@ -193,7 +203,8 @@ enum fstAttrType {
|
||||||
FST_AT_MAX = 3
|
FST_AT_MAX = 3
|
||||||
};
|
};
|
||||||
|
|
||||||
enum fstMiscType {
|
enum fstMiscType
|
||||||
|
{
|
||||||
FST_MT_MIN = 0,
|
FST_MT_MIN = 0,
|
||||||
|
|
||||||
FST_MT_COMMENT = 0, /* use fstWriterSetComment() to emit */
|
FST_MT_COMMENT = 0, /* use fstWriterSetComment() to emit */
|
||||||
|
|
@ -202,14 +213,17 @@ enum fstMiscType {
|
||||||
FST_MT_PATHNAME = 3, /* reserved for fstWriterSetSourceStem() string -> number management */
|
FST_MT_PATHNAME = 3, /* reserved for fstWriterSetSourceStem() string -> number management */
|
||||||
FST_MT_SOURCESTEM = 4, /* use fstWriterSetSourceStem() to emit */
|
FST_MT_SOURCESTEM = 4, /* use fstWriterSetSourceStem() to emit */
|
||||||
FST_MT_SOURCEISTEM = 5, /* use fstWriterSetSourceInstantiationStem() to emit */
|
FST_MT_SOURCEISTEM = 5, /* use fstWriterSetSourceInstantiationStem() to emit */
|
||||||
FST_MT_VALUELIST = 6, /* use fstWriterSetValueList() to emit, followed by fstWriterCreateVar*() */
|
FST_MT_VALUELIST =
|
||||||
FST_MT_ENUMTABLE = 7, /* use fstWriterCreateEnumTable() and fstWriterEmitEnumTableRef() to emit */
|
6, /* use fstWriterSetValueList() to emit, followed by fstWriterCreateVar*() */
|
||||||
|
FST_MT_ENUMTABLE =
|
||||||
|
7, /* use fstWriterCreateEnumTable() and fstWriterEmitEnumTableRef() to emit */
|
||||||
FST_MT_UNKNOWN = 8,
|
FST_MT_UNKNOWN = 8,
|
||||||
|
|
||||||
FST_MT_MAX = 8
|
FST_MT_MAX = 8
|
||||||
};
|
};
|
||||||
|
|
||||||
enum fstArrayType {
|
enum fstArrayType
|
||||||
|
{
|
||||||
FST_AR_MIN = 0,
|
FST_AR_MIN = 0,
|
||||||
|
|
||||||
FST_AR_NONE = 0,
|
FST_AR_NONE = 0,
|
||||||
|
|
@ -220,7 +234,8 @@ enum fstArrayType {
|
||||||
FST_AR_MAX = 3
|
FST_AR_MAX = 3
|
||||||
};
|
};
|
||||||
|
|
||||||
enum fstEnumValueType {
|
enum fstEnumValueType
|
||||||
|
{
|
||||||
FST_EV_SV_INTEGER = 0,
|
FST_EV_SV_INTEGER = 0,
|
||||||
FST_EV_SV_BIT = 1,
|
FST_EV_SV_BIT = 1,
|
||||||
FST_EV_SV_LOGIC = 2,
|
FST_EV_SV_LOGIC = 2,
|
||||||
|
|
@ -242,7 +257,8 @@ enum fstEnumValueType {
|
||||||
FST_EV_MAX = 15
|
FST_EV_MAX = 15
|
||||||
};
|
};
|
||||||
|
|
||||||
enum fstPackType {
|
enum fstPackType
|
||||||
|
{
|
||||||
FST_PT_NONE = 0,
|
FST_PT_NONE = 0,
|
||||||
FST_PT_UNPACKED = 1,
|
FST_PT_UNPACKED = 1,
|
||||||
FST_PT_PACKED = 2,
|
FST_PT_PACKED = 2,
|
||||||
|
|
@ -251,7 +267,8 @@ enum fstPackType {
|
||||||
FST_PT_MAX = 3
|
FST_PT_MAX = 3
|
||||||
};
|
};
|
||||||
|
|
||||||
enum fstSupplementalVarType {
|
enum fstSupplementalVarType
|
||||||
|
{
|
||||||
FST_SVT_MIN = 0,
|
FST_SVT_MIN = 0,
|
||||||
|
|
||||||
FST_SVT_NONE = 0,
|
FST_SVT_NONE = 0,
|
||||||
|
|
@ -265,7 +282,8 @@ enum fstSupplementalVarType {
|
||||||
FST_SVT_MAX = 5
|
FST_SVT_MAX = 5
|
||||||
};
|
};
|
||||||
|
|
||||||
enum fstSupplementalDataType {
|
enum fstSupplementalDataType
|
||||||
|
{
|
||||||
FST_SDT_MIN = 0,
|
FST_SDT_MIN = 0,
|
||||||
|
|
||||||
FST_SDT_NONE = 0,
|
FST_SDT_NONE = 0,
|
||||||
|
|
@ -289,18 +307,20 @@ enum fstSupplementalDataType {
|
||||||
|
|
||||||
FST_SDT_MAX = 16,
|
FST_SDT_MAX = 16,
|
||||||
|
|
||||||
FST_SDT_SVT_SHIFT_COUNT = 10, /* FST_SVT_* is ORed in by fstWriterCreateVar2() to the left after shifting FST_SDT_SVT_SHIFT_COUNT */
|
FST_SDT_SVT_SHIFT_COUNT = 10, /* FST_SVT_* is ORed in by fstWriterCreateVar2() to the left
|
||||||
|
after shifting FST_SDT_SVT_SHIFT_COUNT */
|
||||||
FST_SDT_ABS_MAX = ((1 << (FST_SDT_SVT_SHIFT_COUNT)) - 1)
|
FST_SDT_ABS_MAX = ((1 << (FST_SDT_SVT_SHIFT_COUNT)) - 1)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct fstHier
|
struct fstHier
|
||||||
{
|
{
|
||||||
unsigned char htyp;
|
unsigned char htyp;
|
||||||
|
|
||||||
union {
|
union
|
||||||
|
{
|
||||||
/* if htyp == FST_HT_SCOPE */
|
/* if htyp == FST_HT_SCOPE */
|
||||||
struct fstHierScope {
|
struct fstHierScope
|
||||||
|
{
|
||||||
unsigned char typ; /* FST_ST_MIN ... FST_ST_MAX */
|
unsigned char typ; /* FST_ST_MIN ... FST_ST_MAX */
|
||||||
const char *name;
|
const char *name;
|
||||||
const char *component;
|
const char *component;
|
||||||
|
|
@ -309,7 +329,8 @@ union {
|
||||||
} scope;
|
} scope;
|
||||||
|
|
||||||
/* if htyp == FST_HT_VAR */
|
/* if htyp == FST_HT_VAR */
|
||||||
struct fstHierVar {
|
struct fstHierVar
|
||||||
|
{
|
||||||
unsigned char typ; /* FST_VT_MIN ... FST_VT_MAX */
|
unsigned char typ; /* FST_VT_MIN ... FST_VT_MAX */
|
||||||
unsigned char direction; /* FST_VD_MIN ... FST_VD_MAX */
|
unsigned char direction; /* FST_VD_MIN ... FST_VD_MAX */
|
||||||
unsigned char svt_workspace; /* zeroed out by FST reader, for client code use */
|
unsigned char svt_workspace; /* zeroed out by FST reader, for client code use */
|
||||||
|
|
@ -323,18 +344,21 @@ union {
|
||||||
} var;
|
} var;
|
||||||
|
|
||||||
/* if htyp == FST_HT_ATTRBEGIN */
|
/* if htyp == FST_HT_ATTRBEGIN */
|
||||||
struct fstHierAttr {
|
struct fstHierAttr
|
||||||
|
{
|
||||||
unsigned char typ; /* FST_AT_MIN ... FST_AT_MAX */
|
unsigned char typ; /* FST_AT_MIN ... FST_AT_MAX */
|
||||||
unsigned char subtype; /* from fstMiscType, fstArrayType, fstEnumValueType, fstPackType */
|
unsigned char
|
||||||
|
subtype; /* from fstMiscType, fstArrayType, fstEnumValueType, fstPackType */
|
||||||
const char *name;
|
const char *name;
|
||||||
uint64_t arg; /* number of array elements, struct members, or some other payload (possibly ignored) */
|
uint64_t arg; /* number of array elements, struct members, or some other payload
|
||||||
uint64_t arg_from_name; /* for when name is overloaded as a variable-length integer (FST_AT_MISC + FST_MT_SOURCESTEM) */
|
(possibly ignored) */
|
||||||
|
uint64_t arg_from_name; /* for when name is overloaded as a variable-length integer
|
||||||
|
(FST_AT_MISC + FST_MT_SOURCESTEM) */
|
||||||
uint32_t name_length; /* strlen(u.attr.name) */
|
uint32_t name_length; /* strlen(u.attr.name) */
|
||||||
} attr;
|
} attr;
|
||||||
} u;
|
} u;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct fstETab
|
struct fstETab
|
||||||
{
|
{
|
||||||
char *name;
|
char *name;
|
||||||
|
|
@ -343,111 +367,169 @@ char **literal_arr;
|
||||||
char **val_arr;
|
char **val_arr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* writer functions
|
* writer functions
|
||||||
*/
|
*/
|
||||||
void fstWriterClose(void *ctx);
|
|
||||||
void * fstWriterCreate(const char *nam, int use_compressed_hier);
|
|
||||||
fstEnumHandle fstWriterCreateEnumTable(void *ctx, const char *name, uint32_t elem_count, unsigned int min_valbits, const char **literal_arr, const char **val_arr);
|
|
||||||
/* used for Verilog/SV */
|
|
||||||
fstHandle fstWriterCreateVar(void *ctx, enum fstVarType vt, enum fstVarDir vd,
|
|
||||||
uint32_t len, const char *nam, fstHandle aliasHandle);
|
|
||||||
/* future expansion for VHDL and other languages. The variable type, data type, etc map onto
|
|
||||||
the current Verilog/SV one. The "type" string is optional for a more verbose or custom description */
|
|
||||||
fstHandle fstWriterCreateVar2(void *ctx, enum fstVarType vt, enum fstVarDir vd,
|
|
||||||
uint32_t len, const char *nam, fstHandle aliasHandle,
|
|
||||||
const char *type, enum fstSupplementalVarType svt, enum fstSupplementalDataType sdt);
|
|
||||||
void fstWriterEmitDumpActive(void *ctx, int enable);
|
|
||||||
void fstWriterEmitEnumTableRef(void *ctx, fstEnumHandle handle);
|
|
||||||
void fstWriterEmitValueChange(void *ctx, fstHandle handle, const void *val);
|
|
||||||
void fstWriterEmitValueChange32(void *ctx, fstHandle handle,
|
|
||||||
uint32_t bits, uint32_t val);
|
|
||||||
void fstWriterEmitValueChange64(void *ctx, fstHandle handle,
|
|
||||||
uint32_t bits, uint64_t val);
|
|
||||||
void fstWriterEmitValueChangeVec32(void *ctx, fstHandle handle,
|
|
||||||
uint32_t bits, const uint32_t *val);
|
|
||||||
void fstWriterEmitValueChangeVec64(void *ctx, fstHandle handle,
|
|
||||||
uint32_t bits, const uint64_t *val);
|
|
||||||
void fstWriterEmitVariableLengthValueChange(void *ctx, fstHandle handle, const void *val, uint32_t len);
|
|
||||||
void fstWriterEmitTimeChange(void *ctx, uint64_t tim);
|
|
||||||
void fstWriterFlushContext(void *ctx);
|
|
||||||
int fstWriterGetDumpSizeLimitReached(void *ctx);
|
|
||||||
int fstWriterGetFseekFailed(void *ctx);
|
|
||||||
void fstWriterSetAttrBegin(void *ctx, enum fstAttrType attrtype, int subtype,
|
|
||||||
const char *attrname, uint64_t arg);
|
|
||||||
void fstWriterSetAttrEnd(void *ctx);
|
|
||||||
void fstWriterSetComment(void *ctx, const char *comm);
|
|
||||||
void fstWriterSetDate(void *ctx, const char *dat);
|
|
||||||
void fstWriterSetDumpSizeLimit(void *ctx, uint64_t numbytes);
|
|
||||||
void fstWriterSetEnvVar(void *ctx, const char *envvar);
|
|
||||||
void fstWriterSetFileType(void *ctx, enum fstFileType filetype);
|
|
||||||
void fstWriterSetPackType(void *ctx, enum fstWriterPackType typ);
|
|
||||||
void fstWriterSetParallelMode(void *ctx, int enable);
|
|
||||||
void fstWriterSetRepackOnClose(void *ctx, int enable); /* type = 0 (none), 1 (libz) */
|
|
||||||
void fstWriterSetScope(void *ctx, enum fstScopeType scopetype,
|
|
||||||
const char *scopename, const char *scopecomp);
|
|
||||||
void fstWriterSetSourceInstantiationStem(void *ctx, const char *path, unsigned int line, unsigned int use_realpath);
|
|
||||||
void fstWriterSetSourceStem(void *ctx, const char *path, unsigned int line, unsigned int use_realpath);
|
|
||||||
void fstWriterSetTimescale(void *ctx, int ts);
|
|
||||||
void fstWriterSetTimescaleFromString(void *ctx, const char *s);
|
|
||||||
void fstWriterSetTimezero(void *ctx, int64_t tim);
|
|
||||||
void fstWriterSetUpscope(void *ctx);
|
|
||||||
void fstWriterSetValueList(void *ctx, const char *vl);
|
|
||||||
void fstWriterSetVersion(void *ctx, const char *vers);
|
|
||||||
|
|
||||||
|
typedef struct fstWriterContext fstWriterContext;
|
||||||
|
|
||||||
|
void fstWriterClose(fstWriterContext *ctx);
|
||||||
|
fstWriterContext *fstWriterCreate(const char *nam, int use_compressed_hier);
|
||||||
|
fstEnumHandle fstWriterCreateEnumTable(fstWriterContext *ctx,
|
||||||
|
const char *name,
|
||||||
|
uint32_t elem_count,
|
||||||
|
unsigned int min_valbits,
|
||||||
|
const char **literal_arr,
|
||||||
|
const char **val_arr);
|
||||||
|
/* used for Verilog/SV */
|
||||||
|
fstHandle fstWriterCreateVar(fstWriterContext *ctx,
|
||||||
|
enum fstVarType vt,
|
||||||
|
enum fstVarDir vd,
|
||||||
|
uint32_t len,
|
||||||
|
const char *nam,
|
||||||
|
fstHandle aliasHandle);
|
||||||
|
/* future expansion for VHDL and other languages. The variable type, data type, etc map onto
|
||||||
|
the current Verilog/SV one. The "type" string is optional for a more verbose or custom
|
||||||
|
description */
|
||||||
|
fstHandle fstWriterCreateVar2(fstWriterContext *ctx,
|
||||||
|
enum fstVarType vt,
|
||||||
|
enum fstVarDir vd,
|
||||||
|
uint32_t len,
|
||||||
|
const char *nam,
|
||||||
|
fstHandle aliasHandle,
|
||||||
|
const char *type,
|
||||||
|
enum fstSupplementalVarType svt,
|
||||||
|
enum fstSupplementalDataType sdt);
|
||||||
|
void fstWriterEmitDumpActive(fstWriterContext *ctx, int enable);
|
||||||
|
void fstWriterEmitEnumTableRef(fstWriterContext *ctx, fstEnumHandle handle);
|
||||||
|
void fstWriterEmitValueChange(fstWriterContext *ctx, fstHandle handle, const void *val);
|
||||||
|
void fstWriterEmitValueChange32(fstWriterContext *ctx,
|
||||||
|
fstHandle handle,
|
||||||
|
uint32_t bits,
|
||||||
|
uint32_t val);
|
||||||
|
void fstWriterEmitValueChange64(fstWriterContext *ctx,
|
||||||
|
fstHandle handle,
|
||||||
|
uint32_t bits,
|
||||||
|
uint64_t val);
|
||||||
|
void fstWriterEmitValueChangeVec32(fstWriterContext *ctx,
|
||||||
|
fstHandle handle,
|
||||||
|
uint32_t bits,
|
||||||
|
const uint32_t *val);
|
||||||
|
void fstWriterEmitValueChangeVec64(fstWriterContext *ctx,
|
||||||
|
fstHandle handle,
|
||||||
|
uint32_t bits,
|
||||||
|
const uint64_t *val);
|
||||||
|
void fstWriterEmitVariableLengthValueChange(fstWriterContext *ctx,
|
||||||
|
fstHandle handle,
|
||||||
|
const void *val,
|
||||||
|
uint32_t len);
|
||||||
|
void fstWriterEmitTimeChange(fstWriterContext *ctx, uint64_t tim);
|
||||||
|
void fstWriterFlushContext(fstWriterContext *ctx);
|
||||||
|
int fstWriterGetDumpSizeLimitReached(fstWriterContext *ctx);
|
||||||
|
int fstWriterGetFseekFailed(fstWriterContext *ctx);
|
||||||
|
int fstWriterGetFlushContextPending(fstWriterContext *ctx);
|
||||||
|
void fstWriterSetAttrBegin(fstWriterContext *ctx,
|
||||||
|
enum fstAttrType attrtype,
|
||||||
|
int subtype,
|
||||||
|
const char *attrname,
|
||||||
|
uint64_t arg);
|
||||||
|
void fstWriterSetAttrEnd(fstWriterContext *ctx);
|
||||||
|
void fstWriterSetComment(fstWriterContext *ctx, const char *comm);
|
||||||
|
void fstWriterSetDate(fstWriterContext *ctx, const char *dat);
|
||||||
|
void fstWriterSetDumpSizeLimit(fstWriterContext *ctx, uint64_t numbytes);
|
||||||
|
void fstWriterSetEnvVar(fstWriterContext *ctx, const char *envvar);
|
||||||
|
void fstWriterSetFileType(fstWriterContext *ctx, enum fstFileType filetype);
|
||||||
|
void fstWriterSetPackType(fstWriterContext *ctx, enum fstWriterPackType typ);
|
||||||
|
void fstWriterSetParallelMode(fstWriterContext *ctx, int enable);
|
||||||
|
void fstWriterSetRepackOnClose(fstWriterContext *ctx,
|
||||||
|
int enable); /* type = 0 (none), 1 (libz) */
|
||||||
|
void fstWriterSetScope(fstWriterContext *ctx,
|
||||||
|
enum fstScopeType scopetype,
|
||||||
|
const char *scopename,
|
||||||
|
const char *scopecomp);
|
||||||
|
void fstWriterSetSourceInstantiationStem(fstWriterContext *ctx,
|
||||||
|
const char *path,
|
||||||
|
unsigned int line,
|
||||||
|
unsigned int use_realpath);
|
||||||
|
void fstWriterSetSourceStem(fstWriterContext *ctx,
|
||||||
|
const char *path,
|
||||||
|
unsigned int line,
|
||||||
|
unsigned int use_realpath);
|
||||||
|
void fstWriterSetTimescale(fstWriterContext *ctx, int ts);
|
||||||
|
void fstWriterSetTimescaleFromString(fstWriterContext *ctx, const char *s);
|
||||||
|
void fstWriterSetTimezero(fstWriterContext *ctx, int64_t tim);
|
||||||
|
void fstWriterSetUpscope(fstWriterContext *ctx);
|
||||||
|
void fstWriterSetValueList(fstWriterContext *ctx, const char *vl);
|
||||||
|
void fstWriterSetVersion(fstWriterContext *ctx, const char *vers);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* reader functions
|
* reader functions
|
||||||
*/
|
*/
|
||||||
void fstReaderClose(void *ctx);
|
|
||||||
void fstReaderClrFacProcessMask(void *ctx, fstHandle facidx);
|
|
||||||
void fstReaderClrFacProcessMaskAll(void *ctx);
|
|
||||||
uint64_t fstReaderGetAliasCount(void *ctx);
|
|
||||||
const char * fstReaderGetCurrentFlatScope(void *ctx);
|
|
||||||
void * fstReaderGetCurrentScopeUserInfo(void *ctx);
|
|
||||||
int fstReaderGetCurrentScopeLen(void *ctx);
|
|
||||||
const char * fstReaderGetDateString(void *ctx);
|
|
||||||
int fstReaderGetDoubleEndianMatchState(void *ctx);
|
|
||||||
uint64_t fstReaderGetDumpActivityChangeTime(void *ctx, uint32_t idx);
|
|
||||||
unsigned char fstReaderGetDumpActivityChangeValue(void *ctx, uint32_t idx);
|
|
||||||
uint64_t fstReaderGetEndTime(void *ctx);
|
|
||||||
int fstReaderGetFacProcessMask(void *ctx, fstHandle facidx);
|
|
||||||
int fstReaderGetFileType(void *ctx);
|
|
||||||
int fstReaderGetFseekFailed(void *ctx);
|
|
||||||
fstHandle fstReaderGetMaxHandle(void *ctx);
|
|
||||||
uint64_t fstReaderGetMemoryUsedByWriter(void *ctx);
|
|
||||||
uint32_t fstReaderGetNumberDumpActivityChanges(void *ctx);
|
|
||||||
uint64_t fstReaderGetScopeCount(void *ctx);
|
|
||||||
uint64_t fstReaderGetStartTime(void *ctx);
|
|
||||||
signed char fstReaderGetTimescale(void *ctx);
|
|
||||||
int64_t fstReaderGetTimezero(void *ctx);
|
|
||||||
uint64_t fstReaderGetValueChangeSectionCount(void *ctx);
|
|
||||||
char * fstReaderGetValueFromHandleAtTime(void *ctx, uint64_t tim, fstHandle facidx, char *buf);
|
|
||||||
uint64_t fstReaderGetVarCount(void *ctx);
|
|
||||||
const char * fstReaderGetVersionString(void *ctx);
|
|
||||||
struct fstHier *fstReaderIterateHier(void *ctx);
|
|
||||||
int fstReaderIterateHierRewind(void *ctx);
|
|
||||||
int fstReaderIterBlocks(void *ctx,
|
|
||||||
void (*value_change_callback)(void *user_callback_data_pointer, uint64_t time, fstHandle facidx, const unsigned char *value),
|
|
||||||
void *user_callback_data_pointer, FILE *vcdhandle);
|
|
||||||
int fstReaderIterBlocks2(void *ctx,
|
|
||||||
void (*value_change_callback)(void *user_callback_data_pointer, uint64_t time, fstHandle facidx, const unsigned char *value),
|
|
||||||
void (*value_change_callback_varlen)(void *user_callback_data_pointer, uint64_t time, fstHandle facidx, const unsigned char *value, uint32_t len),
|
|
||||||
void *user_callback_data_pointer, FILE *vcdhandle);
|
|
||||||
void fstReaderIterBlocksSetNativeDoublesOnCallback(void *ctx, int enable);
|
|
||||||
void * fstReaderOpen(const char *nam);
|
|
||||||
void * fstReaderOpenForUtilitiesOnly(void);
|
|
||||||
const char * fstReaderPopScope(void *ctx);
|
|
||||||
int fstReaderProcessHier(void *ctx, FILE *vcdhandle);
|
|
||||||
const char * fstReaderPushScope(void *ctx, const char *nam, void *user_info);
|
|
||||||
void fstReaderResetScope(void *ctx);
|
|
||||||
void fstReaderSetFacProcessMask(void *ctx, fstHandle facidx);
|
|
||||||
void fstReaderSetFacProcessMaskAll(void *ctx);
|
|
||||||
void fstReaderSetLimitTimeRange(void *ctx, uint64_t start_time, uint64_t end_time);
|
|
||||||
void fstReaderSetUnlimitedTimeRange(void *ctx);
|
|
||||||
void fstReaderSetVcdExtensions(void *ctx, int enable);
|
|
||||||
|
|
||||||
|
typedef struct fstReaderContext fstReaderContext;
|
||||||
|
|
||||||
|
void fstReaderClose(fstReaderContext *ctx);
|
||||||
|
void fstReaderClrFacProcessMask(fstReaderContext *ctx, fstHandle facidx);
|
||||||
|
void fstReaderClrFacProcessMaskAll(fstReaderContext *ctx);
|
||||||
|
uint64_t fstReaderGetAliasCount(fstReaderContext *ctx);
|
||||||
|
const char *fstReaderGetCurrentFlatScope(fstReaderContext *ctx);
|
||||||
|
void *fstReaderGetCurrentScopeUserInfo(fstReaderContext *ctx);
|
||||||
|
int fstReaderGetCurrentScopeLen(fstReaderContext *ctx);
|
||||||
|
const char *fstReaderGetDateString(fstReaderContext *ctx);
|
||||||
|
int fstReaderGetDoubleEndianMatchState(fstReaderContext *ctx);
|
||||||
|
uint64_t fstReaderGetDumpActivityChangeTime(fstReaderContext *ctx, uint32_t idx);
|
||||||
|
unsigned char fstReaderGetDumpActivityChangeValue(fstReaderContext *ctx, uint32_t idx);
|
||||||
|
uint64_t fstReaderGetEndTime(fstReaderContext *ctx);
|
||||||
|
int fstReaderGetFacProcessMask(fstReaderContext *ctx, fstHandle facidx);
|
||||||
|
int fstReaderGetFileType(fstReaderContext *ctx);
|
||||||
|
int fstReaderGetFseekFailed(fstReaderContext *ctx);
|
||||||
|
fstHandle fstReaderGetMaxHandle(fstReaderContext *ctx);
|
||||||
|
uint64_t fstReaderGetMemoryUsedByWriter(fstReaderContext *ctx);
|
||||||
|
uint32_t fstReaderGetNumberDumpActivityChanges(fstReaderContext *ctx);
|
||||||
|
uint64_t fstReaderGetScopeCount(fstReaderContext *ctx);
|
||||||
|
uint64_t fstReaderGetStartTime(fstReaderContext *ctx);
|
||||||
|
signed char fstReaderGetTimescale(fstReaderContext *ctx);
|
||||||
|
int64_t fstReaderGetTimezero(fstReaderContext *ctx);
|
||||||
|
uint64_t fstReaderGetValueChangeSectionCount(fstReaderContext *ctx);
|
||||||
|
char *fstReaderGetValueFromHandleAtTime(fstReaderContext *ctx,
|
||||||
|
uint64_t tim,
|
||||||
|
fstHandle facidx,
|
||||||
|
char *buf);
|
||||||
|
uint64_t fstReaderGetVarCount(fstReaderContext *ctx);
|
||||||
|
const char *fstReaderGetVersionString(fstReaderContext *ctx);
|
||||||
|
struct fstHier *fstReaderIterateHier(fstReaderContext *ctx);
|
||||||
|
int fstReaderIterateHierRewind(fstReaderContext *ctx);
|
||||||
|
int fstReaderIterBlocks(fstReaderContext *ctx,
|
||||||
|
void (*value_change_callback)(void *user_callback_data_pointer,
|
||||||
|
uint64_t time,
|
||||||
|
fstHandle facidx,
|
||||||
|
const unsigned char *value),
|
||||||
|
void *user_callback_data_pointer,
|
||||||
|
FILE *vcdhandle);
|
||||||
|
int fstReaderIterBlocks2(fstReaderContext *ctx,
|
||||||
|
void (*value_change_callback)(void *user_callback_data_pointer,
|
||||||
|
uint64_t time,
|
||||||
|
fstHandle facidx,
|
||||||
|
const unsigned char *value),
|
||||||
|
void (*value_change_callback_varlen)(void *user_callback_data_pointer,
|
||||||
|
uint64_t time,
|
||||||
|
fstHandle facidx,
|
||||||
|
const unsigned char *value,
|
||||||
|
uint32_t len),
|
||||||
|
void *user_callback_data_pointer,
|
||||||
|
FILE *vcdhandle);
|
||||||
|
void fstReaderIterBlocksSetNativeDoublesOnCallback(fstReaderContext *ctx, int enable);
|
||||||
|
fstReaderContext *fstReaderOpen(const char *nam);
|
||||||
|
fstReaderContext *fstReaderOpenForUtilitiesOnly(void);
|
||||||
|
const char *fstReaderPopScope(fstReaderContext *ctx);
|
||||||
|
int fstReaderProcessHier(fstReaderContext *ctx, FILE *vcdhandle);
|
||||||
|
const char *fstReaderPushScope(fstReaderContext *ctx, const char *nam, void *user_info);
|
||||||
|
void fstReaderResetScope(fstReaderContext *ctx);
|
||||||
|
void fstReaderSetFacProcessMask(fstReaderContext *ctx, fstHandle facidx);
|
||||||
|
void fstReaderSetFacProcessMaskAll(fstReaderContext *ctx);
|
||||||
|
void fstReaderSetLimitTimeRange(fstReaderContext *ctx, uint64_t start_time, uint64_t end_time);
|
||||||
|
void fstReaderSetUnlimitedTimeRange(fstReaderContext *ctx);
|
||||||
|
void fstReaderSetVcdExtensions(fstReaderContext *ctx, int enable);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* utility functions
|
* utility functions
|
||||||
|
|
@ -458,7 +540,6 @@ int fstUtilityEscToBin(unsigned char *d, unsigned char *s, int len);
|
||||||
struct fstETab *fstUtilityExtractEnumTableFromString(const char *s);
|
struct fstETab *fstUtilityExtractEnumTableFromString(const char *s);
|
||||||
void fstUtilityFreeEnumTable(struct fstETab *etab); /* must use to free fstETab properly */
|
void fstUtilityFreeEnumTable(struct fstETab *etab); /* must use to free fstETab properly */
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 1999 Tony Bybell.
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
* copy of this software and associated documentation files (the "Software"),
|
|
||||||
* to deal in the Software without restriction, including without limitation
|
|
||||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
* and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
* Software is furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
||||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
* DEALINGS IN THE SOFTWARE.
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef WAVE_ALLOCA_H
|
|
||||||
#define WAVE_ALLOCA_H
|
|
||||||
#include <stdlib.h>
|
|
||||||
#ifdef HAVE_ALLOCA_H
|
|
||||||
#include <alloca.h>
|
|
||||||
#elif defined(__GNUC__)
|
|
||||||
#ifndef __MINGW32__
|
|
||||||
#ifndef alloca
|
|
||||||
#define alloca __builtin_alloca
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
#include <malloc.h>
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#define wave_alloca alloca
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
@ -56,6 +56,7 @@
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
#include <iostream>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
@ -916,6 +917,21 @@ void _vl_vsformat(std::string& output, const std::string& format, va_list ap) VL
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 'p': { // 'x' but parameter is string
|
||||||
|
const int lbits = va_arg(ap, int);
|
||||||
|
(void)lbits;
|
||||||
|
const std::string* const cstr = va_arg(ap, const std::string*);
|
||||||
|
std::ostringstream oss;
|
||||||
|
for (unsigned char c : *cstr) oss << std::hex << static_cast<int>(c);
|
||||||
|
std::string hex_str = oss.str();
|
||||||
|
if (width > 0 && widthSet) {
|
||||||
|
hex_str = hex_str.size() > width
|
||||||
|
? hex_str.substr(0, width)
|
||||||
|
: std::string(width - hex_str.size(), '0') + hex_str;
|
||||||
|
output += hex_str;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
default: {
|
default: {
|
||||||
// Deal with all read-and-print somethings
|
// Deal with all read-and-print somethings
|
||||||
const int lbits = va_arg(ap, int);
|
const int lbits = va_arg(ap, int);
|
||||||
|
|
@ -1234,9 +1250,9 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
|
||||||
bool inPct = false;
|
bool inPct = false;
|
||||||
bool inIgnore = false;
|
bool inIgnore = false;
|
||||||
std::string::const_iterator pos = format.cbegin();
|
std::string::const_iterator pos = format.cbegin();
|
||||||
for (; pos != format.cend() && !_vl_vsss_eof(fp, floc); ++pos) {
|
for (; pos != format.cend(); ++pos) {
|
||||||
// VL_DBG_MSGF("_vlscan fmt='"<<pos[0]<<"' floc="<<floc<<" file='"<<_vl_vsss_peek(fp, floc,
|
// VL_DBG_MSGF("_vlscan fmt='%c' floc=%d file='%c'\n", pos[0], floc,
|
||||||
// fromp, fstr)<<"'\n");
|
// _vl_vsss_peek(fp, floc, fromp, fstr));
|
||||||
if (!inPct && pos[0] == '%') {
|
if (!inPct && pos[0] == '%') {
|
||||||
inPct = true;
|
inPct = true;
|
||||||
inIgnore = false;
|
inIgnore = false;
|
||||||
|
|
@ -1420,7 +1436,12 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
|
||||||
} // switch
|
} // switch
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Processed all arguments
|
||||||
|
return got;
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
// Scan stopped early, return parsed or EOF
|
||||||
|
if (_vl_vsss_eof(fp, floc)) return -1;
|
||||||
return got;
|
return got;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3017,7 +3038,7 @@ void VerilatedContext::trace(VerilatedTraceBaseC* tfp, int levels, int options)
|
||||||
if (m_ns.m_traceBaseModelCbs.empty())
|
if (m_ns.m_traceBaseModelCbs.empty())
|
||||||
VL_FATAL_MT("", 0, "",
|
VL_FATAL_MT("", 0, "",
|
||||||
"Testbench C call to 'VerilatedContext::trace()' requires model(s) Verilated"
|
"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);
|
for (auto& cbr : m_ns.m_traceBaseModelCbs) cbr(tfp, levels, options);
|
||||||
}
|
}
|
||||||
void VerilatedContext::traceBaseModelCbAdd(traceBaseModelCb_t cb) VL_MT_SAFE {
|
void VerilatedContext::traceBaseModelCbAdd(traceBaseModelCb_t cb) VL_MT_SAFE {
|
||||||
|
|
@ -3455,7 +3476,7 @@ void VerilatedHierarchy::remove(VerilatedScope* fromp, VerilatedScope* top) {
|
||||||
void VerilatedAssertOneThread::fatal_different() VL_MT_SAFE {
|
void VerilatedAssertOneThread::fatal_different() VL_MT_SAFE {
|
||||||
VL_FATAL_MT(__FILE__, __LINE__, "",
|
VL_FATAL_MT(__FILE__, __LINE__, "",
|
||||||
"Routine called that is single threaded, but called from"
|
"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
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -175,9 +175,14 @@ enum class VerilatedAssertDirectiveType : uint8_t {
|
||||||
using VerilatedAssertType_t = std::underlying_type<VerilatedAssertType>::type;
|
using VerilatedAssertType_t = std::underlying_type<VerilatedAssertType>::type;
|
||||||
using VerilatedAssertDirectiveType_t = std::underlying_type<VerilatedAssertDirectiveType>::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>
|
template <typename>
|
||||||
struct VlIsCustomStruct : public std::false_type {};
|
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
|
// Utility functions
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -90,6 +90,7 @@ VK_CPPFLAGS_ALWAYS += \
|
||||||
-DVM_TRACE=$(VM_TRACE) \
|
-DVM_TRACE=$(VM_TRACE) \
|
||||||
-DVM_TRACE_FST=$(VM_TRACE_FST) \
|
-DVM_TRACE_FST=$(VM_TRACE_FST) \
|
||||||
-DVM_TRACE_VCD=$(VM_TRACE_VCD) \
|
-DVM_TRACE_VCD=$(VM_TRACE_VCD) \
|
||||||
|
-DVM_TRACE_SAIF=$(VM_TRACE_SAIF) \
|
||||||
$(CFG_CXXFLAGS_NO_UNUSED) \
|
$(CFG_CXXFLAGS_NO_UNUSED) \
|
||||||
|
|
||||||
ifeq ($(CFG_WITH_CCWARN),yes) # Local... Else don't burden users
|
ifeq ($(CFG_WITH_CCWARN),yes) # Local... Else don't burden users
|
||||||
|
|
|
||||||
|
|
@ -101,6 +101,7 @@ void VerilatedFst::open(const char* filename) VL_MT_SAFE_EXCLUDES(m_mutex) {
|
||||||
void VerilatedFst::close() VL_MT_SAFE_EXCLUDES(m_mutex) {
|
void VerilatedFst::close() VL_MT_SAFE_EXCLUDES(m_mutex) {
|
||||||
const VerilatedLockGuard lock{m_mutex};
|
const VerilatedLockGuard lock{m_mutex};
|
||||||
Super::closeBase();
|
Super::closeBase();
|
||||||
|
emitTimeChangeMaybe();
|
||||||
fstWriterClose(m_fst);
|
fstWriterClose(m_fst);
|
||||||
m_fst = nullptr;
|
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) {
|
void VerilatedFst::flush() VL_MT_SAFE_EXCLUDES(m_mutex) {
|
||||||
const VerilatedLockGuard lock{m_mutex};
|
const VerilatedLockGuard lock{m_mutex};
|
||||||
Super::flushBase();
|
Super::flushBase();
|
||||||
|
emitTimeChangeMaybe();
|
||||||
fstWriterFlushContext(m_fst);
|
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
|
// Decl
|
||||||
|
|
@ -311,12 +324,14 @@ void VerilatedFst::configure(const VerilatedTraceConfig& config) {
|
||||||
VL_ATTR_ALWINLINE
|
VL_ATTR_ALWINLINE
|
||||||
void VerilatedFstBuffer::emitEvent(uint32_t code) {
|
void VerilatedFstBuffer::emitEvent(uint32_t code) {
|
||||||
VL_DEBUG_IFDEF(assert(m_symbolp[code]););
|
VL_DEBUG_IFDEF(assert(m_symbolp[code]););
|
||||||
|
m_owner.emitTimeChangeMaybe();
|
||||||
fstWriterEmitValueChange(m_fst, m_symbolp[code], "1");
|
fstWriterEmitValueChange(m_fst, m_symbolp[code], "1");
|
||||||
}
|
}
|
||||||
|
|
||||||
VL_ATTR_ALWINLINE
|
VL_ATTR_ALWINLINE
|
||||||
void VerilatedFstBuffer::emitBit(uint32_t code, CData newval) {
|
void VerilatedFstBuffer::emitBit(uint32_t code, CData newval) {
|
||||||
VL_DEBUG_IFDEF(assert(m_symbolp[code]););
|
VL_DEBUG_IFDEF(assert(m_symbolp[code]););
|
||||||
|
m_owner.emitTimeChangeMaybe();
|
||||||
fstWriterEmitValueChange(m_fst, m_symbolp[code], newval ? "1" : "0");
|
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];
|
char buf[VL_BYTESIZE];
|
||||||
VL_DEBUG_IFDEF(assert(m_symbolp[code]););
|
VL_DEBUG_IFDEF(assert(m_symbolp[code]););
|
||||||
cvtCDataToStr(buf, newval << (VL_BYTESIZE - bits));
|
cvtCDataToStr(buf, newval << (VL_BYTESIZE - bits));
|
||||||
|
m_owner.emitTimeChangeMaybe();
|
||||||
fstWriterEmitValueChange(m_fst, m_symbolp[code], buf);
|
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];
|
char buf[VL_SHORTSIZE];
|
||||||
VL_DEBUG_IFDEF(assert(m_symbolp[code]););
|
VL_DEBUG_IFDEF(assert(m_symbolp[code]););
|
||||||
cvtSDataToStr(buf, newval << (VL_SHORTSIZE - bits));
|
cvtSDataToStr(buf, newval << (VL_SHORTSIZE - bits));
|
||||||
|
m_owner.emitTimeChangeMaybe();
|
||||||
fstWriterEmitValueChange(m_fst, m_symbolp[code], buf);
|
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];
|
char buf[VL_IDATASIZE];
|
||||||
VL_DEBUG_IFDEF(assert(m_symbolp[code]););
|
VL_DEBUG_IFDEF(assert(m_symbolp[code]););
|
||||||
cvtIDataToStr(buf, newval << (VL_IDATASIZE - bits));
|
cvtIDataToStr(buf, newval << (VL_IDATASIZE - bits));
|
||||||
|
m_owner.emitTimeChangeMaybe();
|
||||||
fstWriterEmitValueChange(m_fst, m_symbolp[code], buf);
|
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];
|
char buf[VL_QUADSIZE];
|
||||||
VL_DEBUG_IFDEF(assert(m_symbolp[code]););
|
VL_DEBUG_IFDEF(assert(m_symbolp[code]););
|
||||||
cvtQDataToStr(buf, newval << (VL_QUADSIZE - bits));
|
cvtQDataToStr(buf, newval << (VL_QUADSIZE - bits));
|
||||||
|
m_owner.emitTimeChangeMaybe();
|
||||||
fstWriterEmitValueChange(m_fst, m_symbolp[code], buf);
|
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]);
|
cvtEDataToStr(wp, newvalp[--words]);
|
||||||
wp += VL_EDATASIZE;
|
wp += VL_EDATASIZE;
|
||||||
}
|
}
|
||||||
|
m_owner.emitTimeChangeMaybe();
|
||||||
fstWriterEmitValueChange(m_fst, m_symbolp[code], m_strbufp);
|
fstWriterEmitValueChange(m_fst, m_symbolp[code], m_strbufp);
|
||||||
}
|
}
|
||||||
|
|
||||||
VL_ATTR_ALWINLINE
|
VL_ATTR_ALWINLINE
|
||||||
void VerilatedFstBuffer::emitDouble(uint32_t code, double newval) {
|
void VerilatedFstBuffer::emitDouble(uint32_t code, double newval) {
|
||||||
|
m_owner.emitTimeChangeMaybe();
|
||||||
fstWriterEmitValueChange(m_fst, m_symbolp[code], &newval);
|
fstWriterEmitValueChange(m_fst, m_symbolp[code], &newval);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,8 @@ typedef uint32_t vlFstEnumHandle;
|
||||||
|
|
||||||
class VerilatedFstBuffer;
|
class VerilatedFstBuffer;
|
||||||
|
|
||||||
|
struct fstWriterContext;
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
// VerilatedFst
|
// VerilatedFst
|
||||||
// Base class to create a Verilator FST dump
|
// Base class to create a Verilator FST dump
|
||||||
|
|
@ -49,11 +51,12 @@ private:
|
||||||
//=========================================================================
|
//=========================================================================
|
||||||
// FST-specific internals
|
// FST-specific internals
|
||||||
|
|
||||||
void* m_fst = nullptr;
|
fstWriterContext* m_fst = nullptr;
|
||||||
std::map<uint32_t, vlFstHandle> m_code2symbol;
|
std::map<uint32_t, vlFstHandle> m_code2symbol;
|
||||||
std::map<int, vlFstEnumHandle> m_local2fstdtype;
|
std::map<int, vlFstEnumHandle> m_local2fstdtype;
|
||||||
vlFstHandle* m_symbolp = nullptr; // same as m_code2symbol, but as an array
|
vlFstHandle* m_symbolp = nullptr; // same as m_code2symbol, but as an array
|
||||||
char* m_strbufp = nullptr; // String buffer long enough to hold maxBits() chars
|
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
|
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
|
// Called when the trace moves forward to a new time point
|
||||||
void emitTimeChange(uint64_t timeui) override;
|
void emitTimeChange(uint64_t timeui) override;
|
||||||
|
void emitTimeChangeMaybe();
|
||||||
|
|
||||||
// Hooks called from VerilatedTrace
|
// Hooks called from VerilatedTrace
|
||||||
bool preFullDump() override { return isOpen(); }
|
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.
|
VerilatedFst& m_owner; // Trace file owning this buffer. Required by subclasses.
|
||||||
|
|
||||||
// The FST file handle
|
// 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
|
// code to fstHande map, as an array
|
||||||
const vlFstHandle* const m_symbolp = m_owner.m_symbolp;
|
const vlFstHandle* const m_symbolp = m_owner.m_symbolp;
|
||||||
// String buffer long enough to hold maxBits() chars
|
// 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 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
|
// Return double from lhs (numeric) unsigned
|
||||||
double VL_ITOR_D_W(int lbits, WDataInP const lwp) VL_PURE;
|
double VL_ITOR_D_W(int lbits, WDataInP const lwp) VL_PURE;
|
||||||
static inline double VL_ITOR_D_I(int, IData lhs) VL_PURE {
|
static inline double VL_ITOR_D_I(int, IData lhs) VL_PURE {
|
||||||
|
|
|
||||||
|
|
@ -34,28 +34,6 @@ thread_local VlExecutionProfiler::ExecutionTrace VlExecutionProfiler::t_trace;
|
||||||
|
|
||||||
constexpr const char* const VlExecutionRecord::s_ascii[];
|
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
|
// VlExecutionProfiler implementation
|
||||||
|
|
||||||
|
|
@ -157,15 +135,21 @@ void VlExecutionProfiler::dump(const char* filenamep, uint64_t tickEnd)
|
||||||
VL_DEBUG_IF(VL_DBG_MSGF("+prof+exec writing to '%s'\n", filenamep););
|
VL_DEBUG_IF(VL_DBG_MSGF("+prof+exec writing to '%s'\n", filenamep););
|
||||||
|
|
||||||
FILE* const fp = std::fopen(filenamep, "w");
|
FILE* const fp = std::fopen(filenamep, "w");
|
||||||
if (VL_UNLIKELY(!fp)) { VL_FATAL_MT(filenamep, 0, "", "+prof+exec+file file not writable"); }
|
if (VL_UNLIKELY(!fp)) VL_FATAL_MT(filenamep, 0, "", "+prof+exec+file file not writable");
|
||||||
|
|
||||||
// TODO Perhaps merge with verilated_coverage output format, so can
|
// TODO Perhaps merge with verilated_coverage output format, so can
|
||||||
// have a common merging and reporting tool, etc.
|
// 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",
|
fprintf(fp, "VLPROF arg +verilator+prof+exec+start+%" PRIu64 "\n",
|
||||||
Verilated::threadContextp()->profExecStart());
|
Verilated::threadContextp()->profExecStart());
|
||||||
fprintf(fp, "VLPROF arg +verilator+prof+exec+window+%u\n",
|
fprintf(fp, "VLPROF arg +verilator+prof+exec+window+%u\n",
|
||||||
Verilated::threadContextp()->profExecWindow());
|
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
|
// 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
|
// processors, but not all of them might be utilized. Report the actual number that has trace
|
||||||
// entries to avoid over-counting.
|
// entries to avoid over-counting.
|
||||||
|
|
@ -206,13 +190,24 @@ void VlExecutionProfiler::dump(const char* filenamep, uint64_t tickEnd)
|
||||||
break;
|
break;
|
||||||
case VlExecutionRecord::Type::MTASK_BEGIN: {
|
case VlExecutionRecord::Type::MTASK_BEGIN: {
|
||||||
const auto& payload = er.m_payload.mtaskBegin;
|
const auto& payload = er.m_payload.mtaskBegin;
|
||||||
|
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,
|
fprintf(fp, " id %u predictStart %u cpu %u\n", payload.m_id,
|
||||||
payload.m_predictStart, payload.m_cpu);
|
payload.m_predictStart, payload.m_cpu);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case VlExecutionRecord::Type::MTASK_END: {
|
case VlExecutionRecord::Type::MTASK_END: {
|
||||||
const auto& payload = er.m_payload.mtaskEnd;
|
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;
|
break;
|
||||||
}
|
}
|
||||||
case VlExecutionRecord::Type::SECTION_PUSH: {
|
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, SECTION_POP) \
|
||||||
_VL_FOREACH_APPLY(macro, MTASK_BEGIN) \
|
_VL_FOREACH_APPLY(macro, MTASK_BEGIN) \
|
||||||
_VL_FOREACH_APPLY(macro, MTASK_END) \
|
_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_BEGIN) \
|
||||||
_VL_FOREACH_APPLY(macro, EXEC_GRAPH_END)
|
_VL_FOREACH_APPLY(macro, EXEC_GRAPH_END)
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
@ -90,11 +92,14 @@ class VlExecutionRecord final {
|
||||||
uint32_t m_id; // MTask id
|
uint32_t m_id; // MTask id
|
||||||
uint32_t m_predictStart; // Time scheduler predicted would start
|
uint32_t m_predictStart; // Time scheduler predicted would start
|
||||||
uint32_t m_cpu; // Executing CPU id
|
uint32_t m_cpu; // Executing CPU id
|
||||||
|
const char* m_hierBlock; // Name of a hier block with this mtask
|
||||||
} mtaskBegin;
|
} mtaskBegin;
|
||||||
struct {
|
struct {
|
||||||
uint32_t m_id; // MTask id
|
|
||||||
uint32_t m_predictCost; // How long scheduler predicted would take
|
uint32_t m_predictCost; // How long scheduler predicted would take
|
||||||
} mtaskEnd;
|
} mtaskEnd;
|
||||||
|
struct {
|
||||||
|
uint32_t m_cpu; // Executing CPU id
|
||||||
|
} threadScheduleWait;
|
||||||
};
|
};
|
||||||
|
|
||||||
// STATE
|
// STATE
|
||||||
|
|
@ -105,8 +110,6 @@ class VlExecutionRecord final {
|
||||||
static_assert(alignof(uint64_t) >= alignof(Payload), "Padding not allowed");
|
static_assert(alignof(uint64_t) >= alignof(Payload), "Padding not allowed");
|
||||||
static_assert(alignof(Payload) >= alignof(Type), "Padding not allowed");
|
static_assert(alignof(Payload) >= alignof(Type), "Padding not allowed");
|
||||||
|
|
||||||
static uint16_t getcpu(); // Return currently executing CPU id
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// CONSTRUCTOR
|
// CONSTRUCTOR
|
||||||
VlExecutionRecord() = default;
|
VlExecutionRecord() = default;
|
||||||
|
|
@ -117,17 +120,25 @@ public:
|
||||||
m_type = Type::SECTION_PUSH;
|
m_type = Type::SECTION_PUSH;
|
||||||
}
|
}
|
||||||
void sectionPop() { m_type = Type::SECTION_POP; }
|
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_id = id;
|
||||||
m_payload.mtaskBegin.m_predictStart = predictStart;
|
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;
|
m_type = Type::MTASK_BEGIN;
|
||||||
}
|
}
|
||||||
void mtaskEnd(uint32_t id, uint32_t predictCost) {
|
void mtaskEnd(uint32_t predictCost) {
|
||||||
m_payload.mtaskEnd.m_id = id;
|
|
||||||
m_payload.mtaskEnd.m_predictCost = predictCost;
|
m_payload.mtaskEnd.m_predictCost = predictCost;
|
||||||
m_type = Type::MTASK_END;
|
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 execGraphBegin() { m_type = Type::EXEC_GRAPH_BEGIN; }
|
||||||
void execGraphEnd() { m_type = Type::EXEC_GRAPH_END; }
|
void execGraphEnd() { m_type = Type::EXEC_GRAPH_END; }
|
||||||
};
|
};
|
||||||
|
|
@ -214,7 +225,7 @@ public:
|
||||||
// METHODS
|
// METHODS
|
||||||
VlPgoProfiler() = default;
|
VlPgoProfiler() = default;
|
||||||
~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) {
|
void addCounter(size_t counter, const std::string& name) {
|
||||||
VL_DEBUG_IF(assert(counter < N_Entries););
|
VL_DEBUG_IF(assert(counter < N_Entries););
|
||||||
m_records.emplace_back(Record{name, counter});
|
m_records.emplace_back(Record{name, counter});
|
||||||
|
|
@ -228,7 +239,8 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
template <std::size_t N_Entries>
|
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;
|
static VerilatedMutex s_mutex;
|
||||||
const VerilatedLockGuard lock{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
|
// each will collect is own data correctly. However when each is
|
||||||
// destroyed we need to get all the data, not keep overwriting and only
|
// destroyed we need to get all the data, not keep overwriting and only
|
||||||
// get the last model's data.
|
// 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()););
|
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)) {
|
if (VL_UNLIKELY(!fp)) {
|
||||||
VL_FATAL_MT(filename.c_str(), 0, "", "+prof+vlt+file file not writable");
|
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
|
// TODO Perhaps merge with verilated_coverage output format, so can
|
||||||
// have a common merging and reporting tool, etc.
|
// have a common merging and reporting tool, etc.
|
||||||
fprintf(fp, "// Verilated model profile-guided optimization data dump file\n");
|
fprintf(fp, "// Verilated model profile-guided optimization data dump file\n");
|
||||||
fprintf(fp, "`verilator_config\n");
|
fprintf(fp, "`verilator_config\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
s_firstCall = false;
|
||||||
|
|
||||||
for (const Record& rec : m_records) {
|
for (const Record& rec : m_records) {
|
||||||
fprintf(fp, "profile_data -model \"%s\" -mtask \"%s\" -cost 64'd%" PRIu64 "\n", modelp,
|
fprintf(fp, "profile_data -model \"%s\" -mtask \"%s\" -cost 64'd%" PRIu64 "\n", modelp,
|
||||||
|
|
|
||||||
|
|
@ -166,7 +166,7 @@ public:
|
||||||
s << "(Array (_ BitVec " << idxWidths[i] << ") ";
|
s << "(Array (_ BitVec " << idxWidths[i] << ") ";
|
||||||
}
|
}
|
||||||
s << "(_ BitVec " << width() << ")";
|
s << "(_ BitVec " << width() << ")";
|
||||||
for (int i = 0; i < dimension(); ++i) { s << ")"; }
|
for (int i = 0; i < dimension(); ++i) s << ")";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
VL_FATAL_MT(__FILE__, __LINE__, "randomize", "indexed_name not found in m_arr_vars");
|
VL_FATAL_MT(__FILE__, __LINE__, "randomize", "indexed_name not found in m_arr_vars");
|
||||||
|
|
@ -200,8 +200,8 @@ class VlRandomizer final {
|
||||||
std::map<std::string, std::shared_ptr<const VlRandomVar>> m_vars; // Solver-dependent
|
std::map<std::string, std::shared_ptr<const VlRandomVar>> m_vars; // Solver-dependent
|
||||||
// variables
|
// variables
|
||||||
ArrayInfoMap m_arr_vars; // Tracks each element in array structures for iteration
|
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;
|
const VlQueue<CData>* m_randmode; // rand_mode state;
|
||||||
|
int m_index = 0; // Internal counter for key generation
|
||||||
|
|
||||||
// PRIVATE METHODS
|
// PRIVATE METHODS
|
||||||
void randomConstraint(std::ostream& os, VlRNG& rngr, int bits);
|
void randomConstraint(std::ostream& os, VlRNG& rngr, int bits);
|
||||||
|
|
@ -216,6 +216,11 @@ public:
|
||||||
// Finds the next solution satisfying the constraints
|
// Finds the next solution satisfying the constraints
|
||||||
bool next(VlRNG& rngr);
|
bool next(VlRNG& rngr);
|
||||||
|
|
||||||
|
// -----------------------------------------------
|
||||||
|
// --- Process the key for associative array ---
|
||||||
|
// -----------------------------------------------
|
||||||
|
|
||||||
|
// process_key: Handle integral keys (<= 32-bit)
|
||||||
template <typename T_Key>
|
template <typename T_Key>
|
||||||
typename std::enable_if<std::is_integral<T_Key>::value && (sizeof(T_Key) <= 4)>::type
|
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,
|
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]) + "]";
|
= base_name + "[" + std::to_string(integral_index[integral_index.size() - 1]) + "]";
|
||||||
idx_width = sizeof(T_Key) * 8;
|
idx_width = sizeof(T_Key) * 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// process_key: Handle integral keys (> 32-bit), split into 2 x 32-bit segments
|
||||||
template <typename T_Key>
|
template <typename T_Key>
|
||||||
typename std::enable_if<std::is_integral<T_Key>::value && (sizeof(T_Key) > 4)>::type
|
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,
|
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;
|
idx_width = sizeof(T_Key) * 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// process_key: Handle wide keys (VlWide-like), segment is 32-bit per element
|
||||||
template <typename T_Key>
|
template <typename T_Key>
|
||||||
typename std::enable_if<VlIsVlWide<T_Key>::value>::type
|
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,
|
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 + "]";
|
indexed_name = base_name + "[" + index_string + "]";
|
||||||
idx_width = key.size() * 32;
|
idx_width = key.size() * 32;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// process_key: Handle string key, encoded as 128-bit hex
|
||||||
template <typename T_Key>
|
template <typename T_Key>
|
||||||
typename std::enable_if<std::is_same<T_Key, std::string>::value>::type
|
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,
|
process_key(const T_Key& key, std::string& indexed_name, std::vector<size_t>& integral_index,
|
||||||
|
|
@ -289,6 +300,8 @@ public:
|
||||||
|
|
||||||
idx_width = 128;
|
idx_width = 128;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// process_key: Unsupported key type fallback
|
||||||
template <typename T_Key>
|
template <typename T_Key>
|
||||||
typename std::enable_if<!std::is_integral<T_Key>::value
|
typename std::enable_if<!std::is_integral<T_Key>::value
|
||||||
&& !std::is_same<T_Key, std::string>::value
|
&& !std::is_same<T_Key, std::string>::value
|
||||||
|
|
@ -300,8 +313,13 @@ public:
|
||||||
"supported currently.");
|
"supported currently.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------
|
||||||
|
// --- write_var to register variables ---
|
||||||
|
// -----------------------------------------
|
||||||
|
|
||||||
|
// Register scalar variable (non-struct, basic type)
|
||||||
template <typename T>
|
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,
|
write_var(T& var, int width, const char* name, int dimension,
|
||||||
std::uint32_t randmodeIdx = std::numeric_limits<std::uint32_t>::max()) {
|
std::uint32_t randmodeIdx = std::numeric_limits<std::uint32_t>::max()) {
|
||||||
if (m_vars.find(name) != m_vars.end()) return;
|
if (m_vars.find(name) != m_vars.end()) return;
|
||||||
|
|
@ -309,28 +327,60 @@ public:
|
||||||
m_vars[name]
|
m_vars[name]
|
||||||
= std::make_shared<const VlRandomVar>(name, width, &var, dimension, randmodeIdx);
|
= std::make_shared<const VlRandomVar>(name, width, &var, dimension, randmodeIdx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Register user-defined struct variable by recursively writing members
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void write_var(VlQueue<T>& var, int width, const char* name, int dimension,
|
typename std::enable_if<VlIsCustomStruct<T>::value, void>::type
|
||||||
|
write_var(T& var, int width, const char* name, int dimension,
|
||||||
|
std::uint32_t randmodeIdx = std::numeric_limits<std::uint32_t>::max()) {
|
||||||
|
modifyMembers(var, var.memberIndices(), name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register queue of non-struct types
|
||||||
|
template <typename T>
|
||||||
|
typename std::enable_if<!VlContainsCustomStruct<T>::value, void>::type
|
||||||
|
write_var(VlQueue<T>& var, int width, const char* name, int dimension,
|
||||||
std::uint32_t randmodeIdx = std::numeric_limits<std::uint32_t>::max()) {
|
std::uint32_t randmodeIdx = std::numeric_limits<std::uint32_t>::max()) {
|
||||||
if (m_vars.find(name) != m_vars.end()) return;
|
if (m_vars.find(name) != m_vars.end()) return;
|
||||||
m_vars[name] = std::make_shared<const VlRandomArrayVarTemplate<VlQueue<T>>>(
|
m_vars[name] = std::make_shared<const VlRandomArrayVarTemplate<VlQueue<T>>>(
|
||||||
name, width, &var, dimension, randmodeIdx);
|
name, width, &var, dimension, randmodeIdx);
|
||||||
if (dimension > 0) {
|
if (dimension > 0) {
|
||||||
idx = 0;
|
m_index = 0;
|
||||||
record_arr_table(var, name, dimension, {}, {});
|
record_arr_table(var, name, dimension, {}, {});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Register queue of structs
|
||||||
|
template <typename T>
|
||||||
|
typename std::enable_if<VlContainsCustomStruct<T>::value, void>::type
|
||||||
|
write_var(VlQueue<T>& var, int width, const char* name, int dimension,
|
||||||
|
std::uint32_t randmodeIdx = std::numeric_limits<std::uint32_t>::max()) {
|
||||||
|
if (dimension > 0) record_struct_arr(var, name, dimension, {}, {});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register unpacked array of non-struct types
|
||||||
template <typename T, std::size_t N_Depth>
|
template <typename T, std::size_t N_Depth>
|
||||||
void write_var(VlUnpacked<T, N_Depth>& var, int width, const char* name, int dimension,
|
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()) {
|
std::uint32_t randmodeIdx = std::numeric_limits<std::uint32_t>::max()) {
|
||||||
if (m_vars.find(name) != m_vars.end()) return;
|
if (m_vars.find(name) != m_vars.end()) return;
|
||||||
m_vars[name] = std::make_shared<const VlRandomArrayVarTemplate<VlUnpacked<T, N_Depth>>>(
|
m_vars[name] = std::make_shared<const VlRandomArrayVarTemplate<VlUnpacked<T, N_Depth>>>(
|
||||||
name, width, &var, dimension, randmodeIdx);
|
name, width, &var, dimension, randmodeIdx);
|
||||||
if (dimension > 0) {
|
if (dimension > 0) {
|
||||||
idx = 0;
|
m_index = 0;
|
||||||
record_arr_table(var, name, dimension, {}, {});
|
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>
|
template <typename T_Key, typename T_Value>
|
||||||
void write_var(VlAssocArray<T_Key, T_Value>& var, int width, const char* name, int dimension,
|
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()) {
|
std::uint32_t randmodeIdx = std::numeric_limits<std::uint32_t>::max()) {
|
||||||
|
|
@ -339,59 +389,28 @@ public:
|
||||||
= std::make_shared<const VlRandomArrayVarTemplate<VlAssocArray<T_Key, T_Value>>>(
|
= std::make_shared<const VlRandomArrayVarTemplate<VlAssocArray<T_Key, T_Value>>>(
|
||||||
name, width, &var, dimension, randmodeIdx);
|
name, width, &var, dimension, randmodeIdx);
|
||||||
if (dimension > 0) {
|
if (dimension > 0) {
|
||||||
idx = 0;
|
m_index = 0;
|
||||||
record_arr_table(var, name, dimension, {}, {});
|
record_arr_table(var, name, dimension, {}, {});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
template <typename T, std::size_t... I>
|
|
||||||
void modifyMembers(T& obj, std::index_sequence<I...>, std::string baseName) {
|
|
||||||
// Use the indices to access each member via std::get
|
|
||||||
(void)std::initializer_list<int>{
|
|
||||||
(write_var(std::get<I>(obj.getMembers(obj)), obj.memberWidth()[I],
|
|
||||||
(baseName + "." + obj.memberNames()[I]).c_str(), obj.memberDimension()[I]),
|
|
||||||
0)...};
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
// TODO: Register associative array of structs
|
||||||
typename std::enable_if<VlIsCustomStruct<T>::value, void>::type
|
|
||||||
write_var(T& var, int width, const char* name, int dimension,
|
|
||||||
std::uint32_t randmodeIdx = std::numeric_limits<std::uint32_t>::max()) {
|
|
||||||
modifyMembers(var, var.memberIndices(), name);
|
|
||||||
}
|
|
||||||
|
|
||||||
int idx;
|
// ----------------------------------------
|
||||||
std::string generateKey(const std::string& name, int idx) {
|
// --- Record Arrays: flat and struct ---
|
||||||
if (!name.empty() && name[0] == '\\') {
|
// ----------------------------------------
|
||||||
const size_t space_pos = name.find(' ');
|
|
||||||
return (space_pos != std::string::npos ? name.substr(0, space_pos) : name)
|
|
||||||
+ std::to_string(idx);
|
|
||||||
}
|
|
||||||
const size_t bracket_pos = name.find('[');
|
|
||||||
return (bracket_pos != std::string::npos ? name.substr(0, bracket_pos) : name)
|
|
||||||
+ std::to_string(idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Record a flat (non-class) element into the array variable table
|
||||||
template <typename T>
|
template <typename T>
|
||||||
typename std::enable_if<!std::is_class<T>::value, void>::type
|
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,
|
record_arr_table(T& var, const std::string name, int dimension, std::vector<IData> indices,
|
||||||
std::vector<size_t> idxWidths) {
|
std::vector<size_t> idxWidths) {
|
||||||
const std::string key = generateKey(name, idx);
|
const std::string key = generateKey(name, m_index);
|
||||||
m_arr_vars[key] = std::make_shared<ArrayInfo>(name, &var, idx, indices, idxWidths);
|
m_arr_vars[key] = std::make_shared<ArrayInfo>(name, &var, m_index, indices, idxWidths);
|
||||||
++idx;
|
++m_index;
|
||||||
}
|
|
||||||
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 unpacked array
|
||||||
template <typename T, std::size_t N_Depth>
|
template <typename T, std::size_t N_Depth>
|
||||||
void record_arr_table(VlUnpacked<T, N_Depth>& var, const std::string name, int dimension,
|
void record_arr_table(VlUnpacked<T, N_Depth>& var, const std::string name, int dimension,
|
||||||
std::vector<IData> indices, std::vector<size_t> idxWidths) {
|
std::vector<IData> indices, std::vector<size_t> idxWidths) {
|
||||||
|
|
@ -406,6 +425,23 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Recursively record all elements in a queue
|
||||||
|
template <typename T>
|
||||||
|
void record_arr_table(VlQueue<T>& var, const std::string name, int dimension,
|
||||||
|
std::vector<IData> indices, std::vector<size_t> idxWidths) {
|
||||||
|
if ((dimension > 0) && (var.size() != 0)) {
|
||||||
|
idxWidths.push_back(32);
|
||||||
|
for (size_t i = 0; i < var.size(); ++i) {
|
||||||
|
const std::string indexed_name = name + "[" + std::to_string(i) + "]";
|
||||||
|
indices.push_back(i);
|
||||||
|
record_arr_table(var.atWrite(i), indexed_name, dimension - 1, indices, idxWidths);
|
||||||
|
indices.pop_back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recursively record all elements in an associative array
|
||||||
template <typename T_Key, typename T_Value>
|
template <typename T_Key, typename T_Value>
|
||||||
void record_arr_table(VlAssocArray<T_Key, T_Value>& var, const std::string name, int dimension,
|
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) {
|
std::vector<IData> indices, std::vector<size_t> idxWidths) {
|
||||||
|
|
@ -433,6 +469,76 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Register a single structArray element via write_var
|
||||||
|
template <typename T>
|
||||||
|
typename std::enable_if<VlContainsCustomStruct<T>::value, void>::type
|
||||||
|
record_struct_arr(T& var, const std::string name, int dimension, std::vector<IData> indices,
|
||||||
|
std::vector<size_t> idxWidths) {
|
||||||
|
std::ostringstream oss;
|
||||||
|
for (size_t i = 0; i < indices.size(); ++i) {
|
||||||
|
oss << std::hex << static_cast<int>(indices[i]);
|
||||||
|
if (i < indices.size() - 1) oss << ".";
|
||||||
|
}
|
||||||
|
write_var(var, 1ULL, (name + "." + oss.str()).c_str(), 1ULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recursively process VlUnpacked of structs
|
||||||
|
template <typename T, std::size_t N_Depth>
|
||||||
|
void record_struct_arr(VlUnpacked<T, N_Depth>& var, const std::string name, int dimension,
|
||||||
|
std::vector<IData> indices, std::vector<size_t> idxWidths) {
|
||||||
|
if (dimension > 0 && N_Depth != 0) {
|
||||||
|
idxWidths.push_back(32);
|
||||||
|
for (size_t i = 0; i < N_Depth; ++i) {
|
||||||
|
indices.push_back(i);
|
||||||
|
record_struct_arr(var.operator[](i), name, dimension - 1, indices, idxWidths);
|
||||||
|
indices.pop_back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recursively process VlQueue of structs
|
||||||
|
template <typename T>
|
||||||
|
void record_struct_arr(VlQueue<T>& var, const std::string name, int dimension,
|
||||||
|
std::vector<IData> indices, std::vector<size_t> idxWidths) {
|
||||||
|
if ((dimension > 0) && (var.size() != 0)) {
|
||||||
|
idxWidths.push_back(32);
|
||||||
|
for (size_t i = 0; i < var.size(); ++i) {
|
||||||
|
indices.push_back(i);
|
||||||
|
record_struct_arr(var.atWrite(i), name, dimension - 1, indices, idxWidths);
|
||||||
|
indices.pop_back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Add support for associative arrays of structs
|
||||||
|
// Recursively process associative arrays of structs
|
||||||
|
|
||||||
|
// --------------------------
|
||||||
|
// --- Helper functions ---
|
||||||
|
// --------------------------
|
||||||
|
|
||||||
|
// Helper: Register all members of a user-defined struct
|
||||||
|
template <typename T, std::size_t... I>
|
||||||
|
void modifyMembers(T& obj, std::index_sequence<I...>, std::string baseName) {
|
||||||
|
// Use the indices to access each member via std::get
|
||||||
|
(void)std::initializer_list<int>{
|
||||||
|
(write_var(std::get<I>(obj.getMembers(obj)), obj.memberWidth()[I],
|
||||||
|
(baseName + "." + obj.memberNames()[I]).c_str(), obj.memberDimension()[I]),
|
||||||
|
0)...};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper: Generate unique variable key from name and index
|
||||||
|
std::string generateKey(const std::string& name, int idx) {
|
||||||
|
if (!name.empty() && name[0] == '\\') {
|
||||||
|
const size_t space_pos = name.find(' ');
|
||||||
|
return (space_pos != std::string::npos ? name.substr(0, space_pos) : name)
|
||||||
|
+ std::to_string(idx);
|
||||||
|
}
|
||||||
|
const size_t bracket_pos = name.find('[');
|
||||||
|
return (bracket_pos != std::string::npos ? name.substr(0, bracket_pos) : name)
|
||||||
|
+ std::to_string(idx);
|
||||||
|
}
|
||||||
|
|
||||||
void hard(std::string&& constraint);
|
void hard(std::string&& constraint);
|
||||||
void clear();
|
void clear();
|
||||||
void set_randmode(const VlQueue<CData>& randmode) { m_randmode = &randmode; }
|
void set_randmode(const VlQueue<CData>& randmode) { m_randmode = &randmode; }
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,662 @@
|
||||||
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
// Code available from: https://verilator.org
|
||||||
|
//
|
||||||
|
// Copyright 2001-2025 by Wilson Snyder. This program is free software; you
|
||||||
|
// can redistribute it and/or modify it under the terms of either the GNU
|
||||||
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
|
// Version 2.0.
|
||||||
|
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
///
|
||||||
|
/// \file
|
||||||
|
/// \brief Verilated C++ tracing in SAIF format implementation code
|
||||||
|
///
|
||||||
|
/// This file must be compiled and linked against all Verilated objects
|
||||||
|
/// that use --trace-saif.
|
||||||
|
///
|
||||||
|
/// Use "verilator --trace-saif" to add this to the Makefile for the linker.
|
||||||
|
///
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
|
||||||
|
#include "verilatedos.h"
|
||||||
|
#include "verilated.h"
|
||||||
|
#include "verilated_saif_c.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cerrno>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#if defined(_WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__)
|
||||||
|
# include <io.h>
|
||||||
|
#else
|
||||||
|
# include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef O_LARGEFILE // WIN32 headers omit this
|
||||||
|
# define O_LARGEFILE 0
|
||||||
|
#endif
|
||||||
|
#ifndef O_NONBLOCK // WIN32 headers omit this
|
||||||
|
# define O_NONBLOCK 0
|
||||||
|
#endif
|
||||||
|
#ifndef O_CLOEXEC // WIN32 headers omit this
|
||||||
|
# define O_CLOEXEC 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
// Specialization of the generics for this trace format
|
||||||
|
|
||||||
|
#define VL_SUB_T VerilatedSaif
|
||||||
|
#define VL_BUF_T VerilatedSaifBuffer
|
||||||
|
#include "verilated_trace_imp.h"
|
||||||
|
#undef VL_SUB_T
|
||||||
|
#undef VL_BUF_T
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
// VerilatedSaifActivityBit
|
||||||
|
|
||||||
|
class VerilatedSaifActivityBit final {
|
||||||
|
// MEMBERS
|
||||||
|
bool m_lastVal = false; // Last emitted activity bit value
|
||||||
|
uint64_t m_highTime = 0; // Total time when bit was high
|
||||||
|
size_t m_transitions = 0; // Total number of bit transitions
|
||||||
|
|
||||||
|
public:
|
||||||
|
// METHODS
|
||||||
|
VL_ATTR_ALWINLINE
|
||||||
|
void aggregateVal(uint64_t dt, bool newVal) {
|
||||||
|
m_transitions += newVal != m_lastVal ? 1 : 0;
|
||||||
|
m_highTime += m_lastVal ? dt : 0;
|
||||||
|
m_lastVal = newVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ACCESSORS
|
||||||
|
VL_ATTR_ALWINLINE bool bitValue() const { return m_lastVal; }
|
||||||
|
VL_ATTR_ALWINLINE uint64_t highTime() const { return m_highTime; }
|
||||||
|
VL_ATTR_ALWINLINE uint64_t toggleCount() const { return m_transitions; }
|
||||||
|
};
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
// VerilatedSaifActivityVar
|
||||||
|
|
||||||
|
class VerilatedSaifActivityVar final {
|
||||||
|
// MEMBERS
|
||||||
|
uint64_t m_lastTime = 0; // Last time when variable value was updated
|
||||||
|
VerilatedSaifActivityBit* m_bits; // Pointer to variable bits objects
|
||||||
|
uint32_t m_width; // Width of variable (in bits)
|
||||||
|
|
||||||
|
public:
|
||||||
|
// CONSTRUCTORS
|
||||||
|
VerilatedSaifActivityVar(uint32_t width, VerilatedSaifActivityBit* bits)
|
||||||
|
: m_bits{bits}
|
||||||
|
, m_width{width} {}
|
||||||
|
|
||||||
|
VerilatedSaifActivityVar(VerilatedSaifActivityVar&&) = default;
|
||||||
|
VerilatedSaifActivityVar& operator=(VerilatedSaifActivityVar&&) = default;
|
||||||
|
|
||||||
|
// METHODS
|
||||||
|
VL_ATTR_ALWINLINE void emitBit(uint64_t time, CData newval);
|
||||||
|
|
||||||
|
template <typename DataType>
|
||||||
|
VL_ATTR_ALWINLINE void emitData(uint64_t time, DataType newval, uint32_t bits) {
|
||||||
|
static_assert(std::is_integral<DataType>::value,
|
||||||
|
"The emitted value must be of integral type");
|
||||||
|
|
||||||
|
const uint64_t dt = time - m_lastTime;
|
||||||
|
for (size_t i = 0; i < std::min(m_width, bits); i++) {
|
||||||
|
m_bits[i].aggregateVal(dt, (newval >> i) & 1);
|
||||||
|
}
|
||||||
|
updateLastTime(time);
|
||||||
|
}
|
||||||
|
|
||||||
|
VL_ATTR_ALWINLINE void emitWData(uint64_t time, const WData* newvalp, uint32_t bits);
|
||||||
|
VL_ATTR_ALWINLINE void updateLastTime(uint64_t val) { m_lastTime = val; }
|
||||||
|
|
||||||
|
// ACCESSORS
|
||||||
|
VL_ATTR_ALWINLINE uint32_t width() const { return m_width; }
|
||||||
|
VL_ATTR_ALWINLINE VerilatedSaifActivityBit& bit(std::size_t index);
|
||||||
|
VL_ATTR_ALWINLINE uint64_t lastUpdateTime() const { return m_lastTime; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
// CONSTRUCTORS
|
||||||
|
VL_UNCOPYABLE(VerilatedSaifActivityVar);
|
||||||
|
};
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
// VerilatedSaifActivityScope
|
||||||
|
|
||||||
|
class VerilatedSaifActivityScope final {
|
||||||
|
// MEMBERS
|
||||||
|
// Absolute path to the scope
|
||||||
|
std::string m_scopePath;
|
||||||
|
// Name of the activity scope
|
||||||
|
std::string m_scopeName;
|
||||||
|
// Array indices of child scopes
|
||||||
|
std::vector<std::unique_ptr<VerilatedSaifActivityScope>> m_childScopes{};
|
||||||
|
// Children signals codes mapped to their names in the current scope
|
||||||
|
std::vector<std::pair<uint32_t, std::string>> m_childActivities{};
|
||||||
|
// Parent scope pointer
|
||||||
|
VerilatedSaifActivityScope* m_parentScope = nullptr;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// CONSTRUCTORS
|
||||||
|
VerilatedSaifActivityScope(std::string scopePath, std::string name,
|
||||||
|
VerilatedSaifActivityScope* parentScope = nullptr)
|
||||||
|
: m_scopePath{std::move(scopePath)}
|
||||||
|
, m_scopeName{std::move(name)}
|
||||||
|
, m_parentScope{parentScope} {}
|
||||||
|
|
||||||
|
VerilatedSaifActivityScope(VerilatedSaifActivityScope&&) = default;
|
||||||
|
VerilatedSaifActivityScope& operator=(VerilatedSaifActivityScope&&) = default;
|
||||||
|
|
||||||
|
// METHODS
|
||||||
|
VL_ATTR_ALWINLINE void addChildScope(std::unique_ptr<VerilatedSaifActivityScope> childScope) {
|
||||||
|
m_childScopes.emplace_back(std::move(childScope));
|
||||||
|
}
|
||||||
|
VL_ATTR_ALWINLINE void addActivityVar(uint32_t code, std::string name) {
|
||||||
|
m_childActivities.emplace_back(code, std::move(name));
|
||||||
|
}
|
||||||
|
VL_ATTR_ALWINLINE bool hasParent() const { return m_parentScope; }
|
||||||
|
|
||||||
|
// ACCESSORS
|
||||||
|
VL_ATTR_ALWINLINE const std::string& path() const { return m_scopePath; }
|
||||||
|
VL_ATTR_ALWINLINE const std::string& name() const { return m_scopeName; }
|
||||||
|
VL_ATTR_ALWINLINE const std::vector<std::unique_ptr<VerilatedSaifActivityScope>>&
|
||||||
|
childScopes() const {
|
||||||
|
return m_childScopes;
|
||||||
|
}
|
||||||
|
VL_ATTR_ALWINLINE
|
||||||
|
const std::vector<std::pair<uint32_t, std::string>>& childActivities() const {
|
||||||
|
return m_childActivities;
|
||||||
|
}
|
||||||
|
VL_ATTR_ALWINLINE VerilatedSaifActivityScope* parentScope() const { return m_parentScope; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
// CONSTRUCTORS
|
||||||
|
VL_UNCOPYABLE(VerilatedSaifActivityScope);
|
||||||
|
};
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
// VerilatedSaifActivityAccumulator
|
||||||
|
|
||||||
|
class VerilatedSaifActivityAccumulator final {
|
||||||
|
// Give access to the private activities
|
||||||
|
friend class VerilatedSaifBuffer;
|
||||||
|
friend class VerilatedSaif;
|
||||||
|
|
||||||
|
// MEMBERS
|
||||||
|
// Map of scopes paths to codes of activities inside
|
||||||
|
std::unordered_map<std::string, std::vector<std::pair<uint32_t, std::string>>>
|
||||||
|
m_scopeToActivities;
|
||||||
|
// Map of variables codes mapped to their activity objects
|
||||||
|
std::unordered_map<uint32_t, VerilatedSaifActivityVar> m_activity;
|
||||||
|
// Memory pool for signals bits objects
|
||||||
|
std::vector<std::vector<VerilatedSaifActivityBit>> m_activityArena;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// METHODS
|
||||||
|
void declare(uint32_t code, const std::string& absoluteScopePath, std::string variableName,
|
||||||
|
int bits, bool array, int arraynum);
|
||||||
|
|
||||||
|
// CONSTRUCTORS
|
||||||
|
VerilatedSaifActivityAccumulator() = default;
|
||||||
|
|
||||||
|
VerilatedSaifActivityAccumulator(VerilatedSaifActivityAccumulator&&) = default;
|
||||||
|
VerilatedSaifActivityAccumulator& operator=(VerilatedSaifActivityAccumulator&&) = default;
|
||||||
|
|
||||||
|
private:
|
||||||
|
VL_UNCOPYABLE(VerilatedSaifActivityAccumulator);
|
||||||
|
};
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//=============================================================================
|
||||||
|
//=============================================================================
|
||||||
|
// VerilatedSaifActivityVar implementation
|
||||||
|
|
||||||
|
VL_ATTR_ALWINLINE
|
||||||
|
void VerilatedSaifActivityVar::emitBit(const uint64_t time, const CData newval) {
|
||||||
|
assert(m_lastTime <= time);
|
||||||
|
m_bits[0].aggregateVal(time - m_lastTime, newval);
|
||||||
|
updateLastTime(time);
|
||||||
|
}
|
||||||
|
|
||||||
|
VL_ATTR_ALWINLINE
|
||||||
|
void VerilatedSaifActivityVar::emitWData(const uint64_t time, const WData* newvalp,
|
||||||
|
const uint32_t bits) {
|
||||||
|
assert(m_lastTime <= time);
|
||||||
|
const uint64_t dt = time - m_lastTime;
|
||||||
|
for (std::size_t i = 0; i < std::min(m_width, bits); ++i) {
|
||||||
|
const size_t wordIndex = i / VL_EDATASIZE;
|
||||||
|
m_bits[i].aggregateVal(dt, (newvalp[wordIndex] >> VL_BITBIT_E(i)) & 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateLastTime(time);
|
||||||
|
}
|
||||||
|
|
||||||
|
VerilatedSaifActivityBit& VerilatedSaifActivityVar::bit(const std::size_t index) {
|
||||||
|
assert(index < m_width);
|
||||||
|
return m_bits[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//=============================================================================
|
||||||
|
//=============================================================================
|
||||||
|
// VerilatedSaifActivityAccumulator implementation
|
||||||
|
|
||||||
|
void VerilatedSaifActivityAccumulator::declare(uint32_t code, const std::string& absoluteScopePath,
|
||||||
|
std::string variableName, int bits, bool array,
|
||||||
|
int arraynum) {
|
||||||
|
const size_t block_size = 1024;
|
||||||
|
if (m_activityArena.empty()
|
||||||
|
|| m_activityArena.back().size() + bits > m_activityArena.back().capacity()) {
|
||||||
|
m_activityArena.emplace_back();
|
||||||
|
m_activityArena.back().reserve(block_size);
|
||||||
|
}
|
||||||
|
const size_t bitsIdx = m_activityArena.back().size();
|
||||||
|
m_activityArena.back().resize(m_activityArena.back().size() + bits);
|
||||||
|
|
||||||
|
if (array) {
|
||||||
|
variableName += '[';
|
||||||
|
variableName += std::to_string(arraynum);
|
||||||
|
variableName += ']';
|
||||||
|
}
|
||||||
|
m_scopeToActivities[absoluteScopePath].emplace_back(code, variableName);
|
||||||
|
m_activity.emplace(code, VerilatedSaifActivityVar{static_cast<uint32_t>(bits),
|
||||||
|
m_activityArena.back().data() + bitsIdx});
|
||||||
|
}
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//=============================================================================
|
||||||
|
//=============================================================================
|
||||||
|
// VerilatedSaif implementation
|
||||||
|
|
||||||
|
VerilatedSaif::VerilatedSaif(void* filep) {
|
||||||
|
m_activityAccumulators.emplace_back(std::make_unique<VerilatedSaifActivityAccumulator>());
|
||||||
|
}
|
||||||
|
|
||||||
|
void VerilatedSaif::open(const char* filename) VL_MT_SAFE_EXCLUDES(m_mutex) {
|
||||||
|
const VerilatedLockGuard lock{m_mutex};
|
||||||
|
if (isOpen()) return;
|
||||||
|
|
||||||
|
m_filename = filename; // "" is ok, as someone may overload open
|
||||||
|
m_filep = ::open(m_filename.c_str(),
|
||||||
|
O_CREAT | O_WRONLY | O_TRUNC | O_LARGEFILE | O_NONBLOCK | O_CLOEXEC, 0666);
|
||||||
|
m_isOpen = true;
|
||||||
|
|
||||||
|
initializeSaifFileContents();
|
||||||
|
|
||||||
|
Super::traceInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VerilatedSaif::initializeSaifFileContents() {
|
||||||
|
printStr("// Generated by verilated_saif\n");
|
||||||
|
printStr("(SAIFILE\n");
|
||||||
|
printStr("(SAIFVERSION \"2.0\")\n");
|
||||||
|
printStr("(DIRECTION \"backward\")\n");
|
||||||
|
printStr("(PROGRAM_NAME \"Verilator\")\n");
|
||||||
|
printStr("(DIVIDER / )\n");
|
||||||
|
printStr("(TIMESCALE ");
|
||||||
|
printStr(timeResStr());
|
||||||
|
printStr(")\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void VerilatedSaif::emitTimeChange(uint64_t timeui) { m_time = timeui; }
|
||||||
|
|
||||||
|
VerilatedSaif::~VerilatedSaif() { close(); }
|
||||||
|
|
||||||
|
void VerilatedSaif::close() VL_MT_SAFE_EXCLUDES(m_mutex) {
|
||||||
|
// This function is on the flush() call path
|
||||||
|
const VerilatedLockGuard lock{m_mutex};
|
||||||
|
if (!isOpen()) return;
|
||||||
|
|
||||||
|
finalizeSaifFileContents();
|
||||||
|
clearCurrentlyCollectedData();
|
||||||
|
|
||||||
|
writeBuffered(true);
|
||||||
|
::close(m_filep);
|
||||||
|
m_isOpen = false;
|
||||||
|
|
||||||
|
Super::closeBase();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VerilatedSaif::finalizeSaifFileContents() {
|
||||||
|
printStr("(DURATION ");
|
||||||
|
printStr(std::to_string(currentTime()));
|
||||||
|
printStr(")\n");
|
||||||
|
|
||||||
|
incrementIndent();
|
||||||
|
for (const auto& topScope : m_scopes) recursivelyPrintScopes(*topScope);
|
||||||
|
decrementIndent();
|
||||||
|
|
||||||
|
printStr(")\n"); // SAIFILE
|
||||||
|
}
|
||||||
|
|
||||||
|
void VerilatedSaif::recursivelyPrintScopes(const VerilatedSaifActivityScope& scope) {
|
||||||
|
openInstanceScope(scope.name());
|
||||||
|
printScopeActivities(scope);
|
||||||
|
for (const auto& childScope : scope.childScopes()) recursivelyPrintScopes(*childScope);
|
||||||
|
closeInstanceScope();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VerilatedSaif::openInstanceScope(const std::string& instanceName) {
|
||||||
|
printIndent();
|
||||||
|
printStr("(INSTANCE ");
|
||||||
|
printStr(instanceName);
|
||||||
|
printStr("\n");
|
||||||
|
incrementIndent();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VerilatedSaif::closeInstanceScope() {
|
||||||
|
decrementIndent();
|
||||||
|
printIndent();
|
||||||
|
printStr(")\n"); // INSTANCE
|
||||||
|
}
|
||||||
|
|
||||||
|
void VerilatedSaif::printScopeActivities(const VerilatedSaifActivityScope& scope) {
|
||||||
|
bool anyNetWritten = false;
|
||||||
|
|
||||||
|
for (auto& accumulator : m_activityAccumulators) {
|
||||||
|
anyNetWritten |= printScopeActivitiesFromAccumulatorIfPresent(scope.path(), *accumulator,
|
||||||
|
anyNetWritten);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (anyNetWritten) closeNetScope();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VerilatedSaif::printScopeActivitiesFromAccumulatorIfPresent(
|
||||||
|
const std::string& absoluteScopePath, VerilatedSaifActivityAccumulator& accumulator,
|
||||||
|
bool anyNetWritten) {
|
||||||
|
if (accumulator.m_scopeToActivities.count(absoluteScopePath) == 0) return false;
|
||||||
|
|
||||||
|
for (const auto& childSignal : accumulator.m_scopeToActivities.at(absoluteScopePath)) {
|
||||||
|
VerilatedSaifActivityVar& activityVariable = accumulator.m_activity.at(childSignal.first);
|
||||||
|
anyNetWritten
|
||||||
|
= printActivityStats(activityVariable, childSignal.second.c_str(), anyNetWritten);
|
||||||
|
}
|
||||||
|
|
||||||
|
return anyNetWritten;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VerilatedSaif::openNetScope() {
|
||||||
|
printIndent();
|
||||||
|
printStr("(NET\n");
|
||||||
|
incrementIndent();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VerilatedSaif::closeNetScope() {
|
||||||
|
decrementIndent();
|
||||||
|
printIndent();
|
||||||
|
printStr(")\n"); // NET
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VerilatedSaif::printActivityStats(VerilatedSaifActivityVar& activity,
|
||||||
|
const std::string& activityName, bool anyNetWritten) {
|
||||||
|
for (size_t i = 0; i < activity.width(); ++i) {
|
||||||
|
VerilatedSaifActivityBit& bit = activity.bit(i);
|
||||||
|
|
||||||
|
bit.aggregateVal(currentTime() - activity.lastUpdateTime(), bit.bitValue());
|
||||||
|
|
||||||
|
if (!anyNetWritten) {
|
||||||
|
openNetScope();
|
||||||
|
anyNetWritten = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
printIndent();
|
||||||
|
printStr("(");
|
||||||
|
printStr(activityName);
|
||||||
|
if (activity.width() > 1) {
|
||||||
|
printStr("\\[");
|
||||||
|
printStr(std::to_string(i));
|
||||||
|
printStr("\\]");
|
||||||
|
}
|
||||||
|
|
||||||
|
// We only have two-value logic so TZ, TX and TB will always be 0
|
||||||
|
printStr(" (T0 ");
|
||||||
|
printStr(std::to_string(currentTime() - bit.highTime()));
|
||||||
|
printStr(") (T1 ");
|
||||||
|
printStr(std::to_string(bit.highTime()));
|
||||||
|
printStr(") (TZ 0) (TX 0) (TB 0) (TC ");
|
||||||
|
printStr(std::to_string(bit.toggleCount()));
|
||||||
|
printStr("))\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
activity.updateLastTime(currentTime());
|
||||||
|
|
||||||
|
return anyNetWritten;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VerilatedSaif::clearCurrentlyCollectedData() {
|
||||||
|
m_currentScope = nullptr;
|
||||||
|
m_scopes.clear();
|
||||||
|
m_activityAccumulators.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VerilatedSaif::printStr(const char* str) {
|
||||||
|
m_buffer.append(str);
|
||||||
|
writeBuffered(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VerilatedSaif::printStr(const std::string& str) {
|
||||||
|
m_buffer.append(str);
|
||||||
|
writeBuffered(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VerilatedSaif::writeBuffered(bool force) {
|
||||||
|
if (VL_UNLIKELY(m_buffer.size() >= WRITE_BUFFER_SIZE || force)) {
|
||||||
|
if (VL_UNLIKELY(!m_buffer.empty())) {
|
||||||
|
::write(m_filep, m_buffer.data(), m_buffer.size());
|
||||||
|
m_buffer = "";
|
||||||
|
m_buffer.reserve(WRITE_BUFFER_SIZE * 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
// Definitions
|
||||||
|
|
||||||
|
void VerilatedSaif::flush() VL_MT_SAFE_EXCLUDES(m_mutex) {
|
||||||
|
const VerilatedLockGuard lock{m_mutex};
|
||||||
|
Super::flushBase();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VerilatedSaif::incrementIndent() { m_indent += 1; }
|
||||||
|
|
||||||
|
void VerilatedSaif::decrementIndent() { m_indent -= 1; }
|
||||||
|
|
||||||
|
void VerilatedSaif::printIndent() {
|
||||||
|
printStr(std::string(m_indent, ' ')); // Must use () constructor
|
||||||
|
}
|
||||||
|
|
||||||
|
void VerilatedSaif::pushPrefix(const std::string& name, VerilatedTracePrefixType type) {
|
||||||
|
std::string pname = name;
|
||||||
|
|
||||||
|
if (m_prefixStack.back().second == VerilatedTracePrefixType::ROOTIO_MODULE) popPrefix();
|
||||||
|
if (pname.empty()) {
|
||||||
|
pname = "$rootio";
|
||||||
|
type = VerilatedTracePrefixType::ROOTIO_MODULE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type != VerilatedTracePrefixType::ARRAY_UNPACKED
|
||||||
|
&& type != VerilatedTracePrefixType::ARRAY_PACKED) {
|
||||||
|
|
||||||
|
std::string scopePath = m_prefixStack.back().first + pname;
|
||||||
|
std::string scopeName = lastWord(scopePath);
|
||||||
|
|
||||||
|
auto newScope = std::make_unique<VerilatedSaifActivityScope>(
|
||||||
|
std::move(scopePath), std::move(scopeName), m_currentScope);
|
||||||
|
VerilatedSaifActivityScope* newScopePtr = newScope.get();
|
||||||
|
|
||||||
|
if (m_currentScope) {
|
||||||
|
m_currentScope->addChildScope(std::move(newScope));
|
||||||
|
} else {
|
||||||
|
m_scopes.emplace_back(std::move(newScope));
|
||||||
|
}
|
||||||
|
|
||||||
|
m_currentScope = newScopePtr;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string newPrefix = m_prefixStack.back().first + pname;
|
||||||
|
if (type != VerilatedTracePrefixType::ARRAY_UNPACKED
|
||||||
|
&& type != VerilatedTracePrefixType::ARRAY_PACKED) {
|
||||||
|
newPrefix += ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
m_prefixStack.emplace_back(newPrefix, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VerilatedSaif::popPrefix() {
|
||||||
|
if (m_prefixStack.back().second != VerilatedTracePrefixType::ARRAY_UNPACKED
|
||||||
|
&& m_prefixStack.back().second != VerilatedTracePrefixType::ARRAY_PACKED
|
||||||
|
&& m_currentScope != nullptr) {
|
||||||
|
m_currentScope = m_currentScope->parentScope();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_prefixStack.pop_back();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VerilatedSaif::declare(const uint32_t code, uint32_t fidx, const char* name,
|
||||||
|
const char* wirep, const bool array, const int arraynum,
|
||||||
|
const bool bussed, const int msb, const int lsb) {
|
||||||
|
assert(m_activityAccumulators.size() > fidx);
|
||||||
|
VerilatedSaifActivityAccumulator& accumulator = *m_activityAccumulators.at(fidx);
|
||||||
|
|
||||||
|
const int bits = ((msb > lsb) ? (msb - lsb) : (lsb - msb)) + 1;
|
||||||
|
|
||||||
|
const std::string hierarchicalName = m_prefixStack.back().first + name;
|
||||||
|
|
||||||
|
if (!Super::declCode(code, hierarchicalName, bits)) return;
|
||||||
|
|
||||||
|
std::string variableName = lastWord(hierarchicalName);
|
||||||
|
m_currentScope->addActivityVar(code, variableName);
|
||||||
|
|
||||||
|
accumulator.declare(code, m_currentScope->path(), std::move(variableName), bits, array,
|
||||||
|
arraynum);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VerilatedSaif::declEvent(const uint32_t code, const uint32_t fidx, const char* name,
|
||||||
|
const int dtypenum, const VerilatedTraceSigDirection,
|
||||||
|
const VerilatedTraceSigKind, const VerilatedTraceSigType,
|
||||||
|
const bool array, const int arraynum) {
|
||||||
|
declare(code, fidx, name, "event", array, arraynum, false, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VerilatedSaif::declBit(const uint32_t code, const uint32_t fidx, const char* name,
|
||||||
|
const int dtypenum, const VerilatedTraceSigDirection,
|
||||||
|
const VerilatedTraceSigKind, const VerilatedTraceSigType,
|
||||||
|
const bool array, const int arraynum) {
|
||||||
|
declare(code, fidx, name, "wire", array, arraynum, false, 0, 0);
|
||||||
|
}
|
||||||
|
void VerilatedSaif::declBus(const uint32_t code, const uint32_t fidx, const char* name,
|
||||||
|
const int dtypenum, const VerilatedTraceSigDirection,
|
||||||
|
const VerilatedTraceSigKind, const VerilatedTraceSigType,
|
||||||
|
const bool array, const int arraynum, const int msb, const int lsb) {
|
||||||
|
declare(code, fidx, name, "wire", array, arraynum, true, msb, lsb);
|
||||||
|
}
|
||||||
|
void VerilatedSaif::declQuad(const uint32_t code, const uint32_t fidx, const char* name,
|
||||||
|
const int dtypenum, const VerilatedTraceSigDirection,
|
||||||
|
const VerilatedTraceSigKind, const VerilatedTraceSigType,
|
||||||
|
const bool array, const int arraynum, const int msb, const int lsb) {
|
||||||
|
declare(code, fidx, name, "wire", array, arraynum, true, msb, lsb);
|
||||||
|
}
|
||||||
|
void VerilatedSaif::declArray(const uint32_t code, const uint32_t fidx, const char* name,
|
||||||
|
const int dtypenum, const VerilatedTraceSigDirection,
|
||||||
|
const VerilatedTraceSigKind, const VerilatedTraceSigType,
|
||||||
|
const bool array, const int arraynum, const int msb, const int lsb) {
|
||||||
|
declare(code, fidx, name, "wire", array, arraynum, true, msb, lsb);
|
||||||
|
}
|
||||||
|
void VerilatedSaif::declDouble(const uint32_t code, const uint32_t fidx, const char* name,
|
||||||
|
const int dtypenum, const VerilatedTraceSigDirection,
|
||||||
|
const VerilatedTraceSigKind, const VerilatedTraceSigType,
|
||||||
|
const bool array, const int arraynum) {
|
||||||
|
declare(code, fidx, name, "real", array, arraynum, false, 63, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
// Get/commit trace buffer
|
||||||
|
|
||||||
|
VerilatedSaif::Buffer* VerilatedSaif::getTraceBuffer(uint32_t fidx) { return new Buffer{*this}; }
|
||||||
|
|
||||||
|
void VerilatedSaif::commitTraceBuffer(VerilatedSaif::Buffer* bufp) { delete bufp; }
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//=============================================================================
|
||||||
|
//=============================================================================
|
||||||
|
// VerilatedSaifBuffer implementation
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
// emit* trace routines
|
||||||
|
|
||||||
|
// Note: emit* are only ever called from one place (full* in
|
||||||
|
// verilated_trace_imp.h, which is included in this file at the top),
|
||||||
|
// so always inline them.
|
||||||
|
|
||||||
|
VL_ATTR_ALWINLINE
|
||||||
|
void VerilatedSaifBuffer::emitEvent(const uint32_t code) {
|
||||||
|
// NOP
|
||||||
|
}
|
||||||
|
|
||||||
|
VL_ATTR_ALWINLINE
|
||||||
|
void VerilatedSaifBuffer::emitBit(const uint32_t code, const CData newval) {
|
||||||
|
assert(m_owner.m_activityAccumulators.at(m_fidx)->m_activity.count(code)
|
||||||
|
&& "Activity must be declared earlier");
|
||||||
|
VerilatedSaifActivityVar& activity
|
||||||
|
= m_owner.m_activityAccumulators.at(m_fidx)->m_activity.at(code);
|
||||||
|
activity.emitBit(m_owner.currentTime(), newval);
|
||||||
|
}
|
||||||
|
|
||||||
|
VL_ATTR_ALWINLINE
|
||||||
|
void VerilatedSaifBuffer::emitCData(const uint32_t code, const CData newval, const int bits) {
|
||||||
|
assert(m_owner.m_activityAccumulators.at(m_fidx)->m_activity.count(code)
|
||||||
|
&& "Activity must be declared earlier");
|
||||||
|
VerilatedSaifActivityVar& activity
|
||||||
|
= m_owner.m_activityAccumulators.at(m_fidx)->m_activity.at(code);
|
||||||
|
activity.emitData<CData>(m_owner.currentTime(), newval, bits);
|
||||||
|
}
|
||||||
|
|
||||||
|
VL_ATTR_ALWINLINE
|
||||||
|
void VerilatedSaifBuffer::emitSData(const uint32_t code, const SData newval, const int bits) {
|
||||||
|
assert(m_owner.m_activityAccumulators.at(m_fidx)->m_activity.count(code)
|
||||||
|
&& "Activity must be declared earlier");
|
||||||
|
VerilatedSaifActivityVar& activity
|
||||||
|
= m_owner.m_activityAccumulators.at(m_fidx)->m_activity.at(code);
|
||||||
|
activity.emitData<SData>(m_owner.currentTime(), newval, bits);
|
||||||
|
}
|
||||||
|
|
||||||
|
VL_ATTR_ALWINLINE
|
||||||
|
void VerilatedSaifBuffer::emitIData(const uint32_t code, const IData newval, const int bits) {
|
||||||
|
assert(m_owner.m_activityAccumulators.at(m_fidx)->m_activity.count(code)
|
||||||
|
&& "Activity must be declared earlier");
|
||||||
|
VerilatedSaifActivityVar& activity
|
||||||
|
= m_owner.m_activityAccumulators.at(m_fidx)->m_activity.at(code);
|
||||||
|
activity.emitData<IData>(m_owner.currentTime(), newval, bits);
|
||||||
|
}
|
||||||
|
|
||||||
|
VL_ATTR_ALWINLINE
|
||||||
|
void VerilatedSaifBuffer::emitQData(const uint32_t code, const QData newval, const int bits) {
|
||||||
|
assert(m_owner.m_activityAccumulators.at(m_fidx)->m_activity.count(code)
|
||||||
|
&& "Activity must be declared earlier");
|
||||||
|
VerilatedSaifActivityVar& activity
|
||||||
|
= m_owner.m_activityAccumulators.at(m_fidx)->m_activity.at(code);
|
||||||
|
activity.emitData<QData>(m_owner.currentTime(), newval, bits);
|
||||||
|
}
|
||||||
|
|
||||||
|
VL_ATTR_ALWINLINE
|
||||||
|
void VerilatedSaifBuffer::emitWData(const uint32_t code, const WData* newvalp, const int bits) {
|
||||||
|
assert(m_owner.m_activityAccumulators.at(m_fidx)->m_activity.count(code)
|
||||||
|
&& "Activity must be declared earlier");
|
||||||
|
VerilatedSaifActivityVar& activity
|
||||||
|
= m_owner.m_activityAccumulators.at(m_fidx)->m_activity.at(code);
|
||||||
|
activity.emitWData(m_owner.currentTime(), newvalp, bits);
|
||||||
|
}
|
||||||
|
|
||||||
|
VL_ATTR_ALWINLINE
|
||||||
|
void VerilatedSaifBuffer::emitDouble(const uint32_t code, const double newval) {
|
||||||
|
// NOP
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,292 @@
|
||||||
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
// Code available from: https://verilator.org
|
||||||
|
//
|
||||||
|
// Copyright 2001-2025 by Wilson Snyder. This program is free software; you
|
||||||
|
// can redistribute it and/or modify it under the terms of either the GNU
|
||||||
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
|
// Version 2.0.
|
||||||
|
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
///
|
||||||
|
/// \file
|
||||||
|
/// \brief Verilated tracing in SAIF format header
|
||||||
|
///
|
||||||
|
/// User wrapper code should use this header when creating SAIF traces.
|
||||||
|
///
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
#ifndef VERILATOR_VERILATED_SAIF_C_H_
|
||||||
|
#define VERILATOR_VERILATED_SAIF_C_H_
|
||||||
|
|
||||||
|
#include "verilated.h"
|
||||||
|
#include "verilated_trace.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class VerilatedSaifBuffer;
|
||||||
|
class VerilatedSaifActivityAccumulator;
|
||||||
|
class VerilatedSaifActivityScope;
|
||||||
|
class VerilatedSaifActivityVar;
|
||||||
|
class VerilatedSaifActivityBit;
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
// VerilatedSaif
|
||||||
|
// Base class to create a Verilator SAIF dump
|
||||||
|
// This is an internally used class - see VerilatedSaifC for what to call from applications
|
||||||
|
|
||||||
|
class VerilatedSaif VL_NOT_FINAL : public VerilatedTrace<VerilatedSaif, VerilatedSaifBuffer> {
|
||||||
|
public:
|
||||||
|
using Super = VerilatedTrace<VerilatedSaif, VerilatedSaifBuffer>;
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend VerilatedSaifBuffer; // Give the buffer access to the private bits
|
||||||
|
|
||||||
|
//=========================================================================
|
||||||
|
// SAIF-specific internals
|
||||||
|
|
||||||
|
int m_filep = 0; // File we're writing to
|
||||||
|
bool m_isOpen = false; // True indicates open file
|
||||||
|
std::string m_filename; // Filename we're writing to (if open)
|
||||||
|
std::string m_buffer; // Write data buffer
|
||||||
|
|
||||||
|
int m_indent = 0; // Indentation size in spaces
|
||||||
|
static constexpr size_t WRITE_BUFFER_SIZE = 256 * 1024; // Bytes between write calls
|
||||||
|
|
||||||
|
// Currently active scope
|
||||||
|
VerilatedSaifActivityScope* m_currentScope = nullptr;
|
||||||
|
// Array of declared scopes
|
||||||
|
std::vector<std::unique_ptr<VerilatedSaifActivityScope>> m_scopes{};
|
||||||
|
// Activity accumulators used to store variables statistics over simulation time
|
||||||
|
std::vector<std::unique_ptr<VerilatedSaifActivityAccumulator>> m_activityAccumulators{};
|
||||||
|
// Total time of the currently traced simulation
|
||||||
|
uint64_t m_time = 0;
|
||||||
|
|
||||||
|
// Stack of declared scopes combined names
|
||||||
|
std::vector<std::pair<std::string, VerilatedTracePrefixType>> m_prefixStack{
|
||||||
|
{"", VerilatedTracePrefixType::SCOPE_MODULE}};
|
||||||
|
|
||||||
|
// METHODS
|
||||||
|
VL_ATTR_ALWINLINE uint64_t currentTime() const { return m_time; }
|
||||||
|
|
||||||
|
void initializeSaifFileContents();
|
||||||
|
void finalizeSaifFileContents();
|
||||||
|
void recursivelyPrintScopes(const VerilatedSaifActivityScope& scope);
|
||||||
|
void openInstanceScope(const std::string& instanceName);
|
||||||
|
void closeInstanceScope();
|
||||||
|
void printScopeActivities(const VerilatedSaifActivityScope& scope);
|
||||||
|
bool
|
||||||
|
printScopeActivitiesFromAccumulatorIfPresent(const std::string& absoluteScopePath,
|
||||||
|
VerilatedSaifActivityAccumulator& accumulator,
|
||||||
|
bool anyNetWritten);
|
||||||
|
void openNetScope();
|
||||||
|
void closeNetScope();
|
||||||
|
bool printActivityStats(VerilatedSaifActivityVar& activity, const std::string& activityName,
|
||||||
|
bool anyNetWritten);
|
||||||
|
|
||||||
|
void incrementIndent();
|
||||||
|
void decrementIndent();
|
||||||
|
void printIndent();
|
||||||
|
|
||||||
|
void printStr(const char* str);
|
||||||
|
void printStr(const std::string& str);
|
||||||
|
void writeBuffered(bool force);
|
||||||
|
|
||||||
|
void clearCurrentlyCollectedData();
|
||||||
|
|
||||||
|
void declare(uint32_t code, uint32_t fidx, const char* name, const char* wirep, bool array,
|
||||||
|
int arraynum, bool bussed, int msb, int lsb);
|
||||||
|
|
||||||
|
// CONSTRUCTORS
|
||||||
|
VL_UNCOPYABLE(VerilatedSaif);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
//=========================================================================
|
||||||
|
// Implementation of VerilatedTrace interface
|
||||||
|
|
||||||
|
// Called when the trace moves forward to a new time point
|
||||||
|
void emitTimeChange(uint64_t timeui) override;
|
||||||
|
|
||||||
|
// Hooks called from VerilatedTrace
|
||||||
|
bool preFullDump() override { return isOpen(); }
|
||||||
|
bool preChangeDump() override { return isOpen(); }
|
||||||
|
|
||||||
|
// Trace buffer management
|
||||||
|
Buffer* getTraceBuffer(uint32_t fidx) override;
|
||||||
|
void commitTraceBuffer(Buffer*) override;
|
||||||
|
|
||||||
|
// Configure sub-class
|
||||||
|
void configure(const VerilatedTraceConfig&) override {}
|
||||||
|
|
||||||
|
public:
|
||||||
|
//=========================================================================
|
||||||
|
// External interface to client code
|
||||||
|
|
||||||
|
// CONSTRUCTOR
|
||||||
|
explicit VerilatedSaif(void* filep = nullptr);
|
||||||
|
~VerilatedSaif();
|
||||||
|
|
||||||
|
// METHODS - All must be thread safe
|
||||||
|
// Open the file; call isOpen() to see if errors
|
||||||
|
void open(const char* filename) VL_MT_SAFE_EXCLUDES(m_mutex);
|
||||||
|
// Close the file
|
||||||
|
void close() VL_MT_SAFE_EXCLUDES(m_mutex);
|
||||||
|
// Flush any remaining data to this file
|
||||||
|
void flush() VL_MT_SAFE_EXCLUDES(m_mutex);
|
||||||
|
// Return if file is open
|
||||||
|
bool isOpen() const VL_MT_SAFE { return m_isOpen; }
|
||||||
|
|
||||||
|
//=========================================================================
|
||||||
|
// Internal interface to Verilator generated code
|
||||||
|
|
||||||
|
void pushPrefix(const std::string&, VerilatedTracePrefixType);
|
||||||
|
void popPrefix();
|
||||||
|
|
||||||
|
void declEvent(uint32_t code, uint32_t fidx, const char* name, int dtypenum,
|
||||||
|
VerilatedTraceSigDirection, VerilatedTraceSigKind, VerilatedTraceSigType,
|
||||||
|
bool array, int arraynum);
|
||||||
|
void declBit(uint32_t code, uint32_t fidx, const char* name, int dtypenum,
|
||||||
|
VerilatedTraceSigDirection, VerilatedTraceSigKind, VerilatedTraceSigType,
|
||||||
|
bool array, int arraynum);
|
||||||
|
void declBus(uint32_t code, uint32_t fidx, const char* name, int dtypenum,
|
||||||
|
VerilatedTraceSigDirection, VerilatedTraceSigKind, VerilatedTraceSigType,
|
||||||
|
bool array, int arraynum, int msb, int lsb);
|
||||||
|
void declQuad(uint32_t code, uint32_t fidx, const char* name, int dtypenum,
|
||||||
|
VerilatedTraceSigDirection, VerilatedTraceSigKind, VerilatedTraceSigType,
|
||||||
|
bool array, int arraynum, int msb, int lsb);
|
||||||
|
void declArray(uint32_t code, uint32_t fidx, const char* name, int dtypenum,
|
||||||
|
VerilatedTraceSigDirection, VerilatedTraceSigKind, VerilatedTraceSigType,
|
||||||
|
bool array, int arraynum, int msb, int lsb);
|
||||||
|
void declDouble(uint32_t code, uint32_t fidx, const char* name, int dtypenum,
|
||||||
|
VerilatedTraceSigDirection, VerilatedTraceSigKind, VerilatedTraceSigType,
|
||||||
|
bool array, int arraynum);
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifndef DOXYGEN
|
||||||
|
// Declare specialization here as it's used in VerilatedSaifC just below
|
||||||
|
template <>
|
||||||
|
void VerilatedSaif::Super::dump(uint64_t time);
|
||||||
|
template <>
|
||||||
|
void VerilatedSaif::Super::set_time_unit(const char* unitp);
|
||||||
|
template <>
|
||||||
|
void VerilatedSaif::Super::set_time_unit(const std::string& unit);
|
||||||
|
template <>
|
||||||
|
void VerilatedSaif::Super::set_time_resolution(const char* unitp);
|
||||||
|
template <>
|
||||||
|
void VerilatedSaif::Super::set_time_resolution(const std::string& unit);
|
||||||
|
template <>
|
||||||
|
void VerilatedSaif::Super::dumpvars(int level, const std::string& hier);
|
||||||
|
#endif // DOXYGEN
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
// VerilatedSaifBuffer
|
||||||
|
|
||||||
|
class VerilatedSaifBuffer VL_NOT_FINAL {
|
||||||
|
// Give the trace file and sub-classes access to the private bits
|
||||||
|
friend VerilatedSaif;
|
||||||
|
friend VerilatedSaif::Super;
|
||||||
|
friend VerilatedSaif::Buffer;
|
||||||
|
friend VerilatedSaif::OffloadBuffer;
|
||||||
|
|
||||||
|
VerilatedSaif& m_owner; // Trace file owning this buffer. Required by subclasses.
|
||||||
|
uint32_t m_fidx; // Index of target activity accumulator
|
||||||
|
|
||||||
|
// CONSTRUCTORS
|
||||||
|
explicit VerilatedSaifBuffer(VerilatedSaif& owner)
|
||||||
|
: m_owner{owner}
|
||||||
|
, m_fidx{0} {}
|
||||||
|
explicit VerilatedSaifBuffer(VerilatedSaif& owner, uint32_t fidx)
|
||||||
|
: m_owner{owner}
|
||||||
|
, m_fidx{fidx} {}
|
||||||
|
virtual ~VerilatedSaifBuffer() = default;
|
||||||
|
|
||||||
|
//=========================================================================
|
||||||
|
// Implementation of VerilatedTraceBuffer interface
|
||||||
|
// Implementations of duck-typed methods for VerilatedTraceBuffer. These are
|
||||||
|
// called from only one place (the full* methods), so always inline them.
|
||||||
|
VL_ATTR_ALWINLINE void emitEvent(uint32_t code);
|
||||||
|
VL_ATTR_ALWINLINE void emitBit(uint32_t code, CData newval);
|
||||||
|
VL_ATTR_ALWINLINE void emitCData(uint32_t code, CData newval, int bits);
|
||||||
|
VL_ATTR_ALWINLINE void emitSData(uint32_t code, SData newval, int bits);
|
||||||
|
VL_ATTR_ALWINLINE void emitIData(uint32_t code, IData newval, int bits);
|
||||||
|
VL_ATTR_ALWINLINE void emitQData(uint32_t code, QData newval, int bits);
|
||||||
|
VL_ATTR_ALWINLINE void emitWData(uint32_t code, const WData* newvalp, int bits);
|
||||||
|
VL_ATTR_ALWINLINE void emitDouble(uint32_t code, double newval);
|
||||||
|
};
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
// VerilatedSaifC
|
||||||
|
// Class representing a SAIF dump file in C standalone (no SystemC)
|
||||||
|
// simulations. Also derived for use in SystemC simulations.
|
||||||
|
|
||||||
|
class VerilatedSaifC VL_NOT_FINAL : public VerilatedTraceBaseC {
|
||||||
|
VerilatedSaif m_sptrace; // Trace file being created
|
||||||
|
|
||||||
|
// CONSTRUCTORS
|
||||||
|
VL_UNCOPYABLE(VerilatedSaifC);
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Construct the dump. Optional argument is ignored
|
||||||
|
explicit VerilatedSaifC(void* filep = nullptr)
|
||||||
|
: m_sptrace{filep} {}
|
||||||
|
// Destruct, flush, and close the dump
|
||||||
|
virtual ~VerilatedSaifC() { close(); }
|
||||||
|
|
||||||
|
// METHODS - User called
|
||||||
|
|
||||||
|
// Return if file is open
|
||||||
|
bool isOpen() const override VL_MT_SAFE { return m_sptrace.isOpen(); }
|
||||||
|
// Open a new SAIF file
|
||||||
|
// This includes a complete header dump each time it is called,
|
||||||
|
// just as if this object was deleted and reconstructed.
|
||||||
|
virtual void open(const char* filename) VL_MT_SAFE { m_sptrace.open(filename); }
|
||||||
|
|
||||||
|
void rolloverSize(size_t size) VL_MT_SAFE {} // NOP
|
||||||
|
|
||||||
|
// Close dump
|
||||||
|
void close() VL_MT_SAFE {
|
||||||
|
m_sptrace.close();
|
||||||
|
modelConnected(false);
|
||||||
|
}
|
||||||
|
// Flush dump
|
||||||
|
void flush() VL_MT_SAFE { m_sptrace.flush(); }
|
||||||
|
// Write one cycle of dump data
|
||||||
|
// Call with the current context's time just after eval'ed,
|
||||||
|
// e.g. ->dump(contextp->time())
|
||||||
|
void dump(uint64_t timeui) VL_MT_SAFE { m_sptrace.dump(timeui); }
|
||||||
|
// Write one cycle of dump data - backward compatible and to reduce
|
||||||
|
// conversion warnings. It's better to use a uint64_t time instead.
|
||||||
|
void dump(double timestamp) { dump(static_cast<uint64_t>(timestamp)); }
|
||||||
|
void dump(uint32_t timestamp) { dump(static_cast<uint64_t>(timestamp)); }
|
||||||
|
void dump(int timestamp) { dump(static_cast<uint64_t>(timestamp)); }
|
||||||
|
|
||||||
|
// METHODS - Internal/backward compatible
|
||||||
|
// \protectedsection
|
||||||
|
|
||||||
|
// Set time units (s/ms, defaults to ns)
|
||||||
|
// Users should not need to call this, as for Verilated models, these
|
||||||
|
// propagate from the Verilated default timeunit
|
||||||
|
void set_time_unit(const char* unit) VL_MT_SAFE { m_sptrace.set_time_unit(unit); }
|
||||||
|
void set_time_unit(const std::string& unit) VL_MT_SAFE { m_sptrace.set_time_unit(unit); }
|
||||||
|
// Set time resolution (s/ms, defaults to ns)
|
||||||
|
// Users should not need to call this, as for Verilated models, these
|
||||||
|
// propagate from the Verilated default timeprecision
|
||||||
|
void set_time_resolution(const char* unit) VL_MT_SAFE { m_sptrace.set_time_resolution(unit); }
|
||||||
|
void set_time_resolution(const std::string& unit) VL_MT_SAFE {
|
||||||
|
m_sptrace.set_time_resolution(unit);
|
||||||
|
}
|
||||||
|
// Set variables to dump, using $dumpvars format
|
||||||
|
// If level = 0, dump everything and hier is then ignored
|
||||||
|
void dumpvars(int level, const std::string& hier) VL_MT_SAFE {
|
||||||
|
m_sptrace.dumpvars(level, hier);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Internal class access
|
||||||
|
VerilatedSaif* spTrace() { return &m_sptrace; }
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // guard
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
// Copyright 2001-2025 by Wilson Snyder. This program is free software; you can
|
||||||
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
|
// Version 2.0.
|
||||||
|
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
///
|
||||||
|
/// \file
|
||||||
|
/// \brief Verilated tracing in SAIF format for SystemC header
|
||||||
|
///
|
||||||
|
/// User wrapper code should use this header when creating SAIF SystemC traces.
|
||||||
|
///
|
||||||
|
/// This class is not threadsafe, as the SystemC kernel is not threadsafe.
|
||||||
|
///
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
#ifndef VERILATOR_VERILATED_SAIF_SC_H_
|
||||||
|
#define VERILATOR_VERILATED_SAIF_SC_H_
|
||||||
|
|
||||||
|
#include "verilatedos.h"
|
||||||
|
|
||||||
|
#include "verilated_saif_c.h"
|
||||||
|
#include "verilated_sc_trace.h"
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
// VerilatedSaifSc
|
||||||
|
/// Trace file used to create SAIF dump for SystemC version of Verilated models. It's very similar
|
||||||
|
/// to its C version (see the class VerilatedSaifC)
|
||||||
|
|
||||||
|
class VerilatedSaifSc final : VerilatedScTraceBase, public VerilatedSaifC {
|
||||||
|
// CONSTRUCTORS
|
||||||
|
VL_UNCOPYABLE(VerilatedSaifSc);
|
||||||
|
|
||||||
|
public:
|
||||||
|
VerilatedSaifSc() {
|
||||||
|
spTrace()->set_time_unit(VerilatedScTraceBase::getScTimeUnit());
|
||||||
|
spTrace()->set_time_resolution(VerilatedScTraceBase::getScTimeResolution());
|
||||||
|
}
|
||||||
|
|
||||||
|
// METHODS
|
||||||
|
// Override VerilatedSaifC. Must be called after starting simulation.
|
||||||
|
void open(const char* filename) override VL_MT_SAFE {
|
||||||
|
VerilatedScTraceBase::checkScElaborationDone();
|
||||||
|
VerilatedSaifC::open(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
// METHODS - for SC kernel
|
||||||
|
// Called from SystemC kernel
|
||||||
|
void cycle() override { VerilatedSaifC::dump(sc_core::sc_time_stamp().to_double()); }
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // Guard
|
||||||
|
|
@ -175,6 +175,32 @@ package std;
|
||||||
`endif
|
`endif
|
||||||
endtask
|
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
|
// When really implemented, srandom must operate on the process, but for
|
||||||
// now rely on the srandom() that is automatically generated for all
|
// now rely on the srandom() that is automatically generated for all
|
||||||
// classes.
|
// classes.
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,8 @@
|
||||||
#include "verilated_threads.h"
|
#include "verilated_threads.h"
|
||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
|
@ -100,10 +102,153 @@ void VlWorkerThread::startWorker(VlWorkerThread* workerp, VerilatedContext* cont
|
||||||
// VlThreadPool
|
// VlThreadPool
|
||||||
|
|
||||||
VlThreadPool::VlThreadPool(VerilatedContext* contextp, unsigned nThreads) {
|
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() {
|
VlThreadPool::~VlThreadPool() {
|
||||||
// Each ~WorkerThread will wait for its thread to exit.
|
// Each ~WorkerThread will wait for its thread to exit.
|
||||||
for (auto& i : m_workers) delete i;
|
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 <atomic>
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
#include <stack>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <vector>
|
#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 VlExecutionProfiler;
|
||||||
class VlThreadPool;
|
class VlThreadPool;
|
||||||
|
|
||||||
|
|
@ -155,6 +147,10 @@ private:
|
||||||
|
|
||||||
VL_UNCOPYABLE(VlWorkerThread);
|
VL_UNCOPYABLE(VlWorkerThread);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
friend class VlThreadPool;
|
||||||
|
const std::thread& cthread() const { return m_cthread; }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// CONSTRUCTORS
|
// CONSTRUCTORS
|
||||||
explicit VlWorkerThread(VerilatedContext* contextp);
|
explicit VlWorkerThread(VerilatedContext* contextp);
|
||||||
|
|
@ -205,6 +201,13 @@ class VlThreadPool final : public VerilatedVirtualBase {
|
||||||
// MEMBERS
|
// MEMBERS
|
||||||
std::vector<VlWorkerThread*> m_workers; // our workers
|
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:
|
public:
|
||||||
// CONSTRUCTORS
|
// CONSTRUCTORS
|
||||||
// Construct a thread pool with 'nThreads' dedicated threads. The thread
|
// Construct a thread pool with 'nThreads' dedicated threads. The thread
|
||||||
|
|
@ -214,7 +217,21 @@ public:
|
||||||
~VlThreadPool() override;
|
~VlThreadPool() override;
|
||||||
|
|
||||||
// METHODS
|
// 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()); }
|
int numThreads() const { return static_cast<int>(m_workers.size()); }
|
||||||
|
std::string numaStatus() const { return m_numaStatus; }
|
||||||
VlWorkerThread* workerp(int index) {
|
VlWorkerThread* workerp(int index) {
|
||||||
assert(index >= 0);
|
assert(index >= 0);
|
||||||
assert(index < static_cast<int>(m_workers.size()));
|
assert(index < static_cast<int>(m_workers.size()));
|
||||||
|
|
@ -223,6 +240,9 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
VL_UNCOPYABLE(VlThreadPool);
|
VL_UNCOPYABLE(VlThreadPool);
|
||||||
|
|
||||||
|
static bool isNumactlRunning();
|
||||||
|
std::string numaAssign();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -184,8 +184,11 @@ public:
|
||||||
// Word at given 'wordIndex'
|
// Word at given 'wordIndex'
|
||||||
uint64_t word(size_t wordIndex) const { return m_flags[wordIndex]; }
|
uint64_t word(size_t wordIndex) const { return m_flags[wordIndex]; }
|
||||||
|
|
||||||
// Set specified flag to given value
|
// Set specified word to given value
|
||||||
void set(size_t index, bool value) {
|
void setWord(size_t wordIndex, uint64_t value) { m_flags[wordIndex] = value; }
|
||||||
|
|
||||||
|
// Set specified bit to given value
|
||||||
|
void setBit(size_t index, bool value) {
|
||||||
uint64_t& w = m_flags[index / 64];
|
uint64_t& w = m_flags[index / 64];
|
||||||
const size_t bitIndex = index % 64;
|
const size_t bitIndex = index % 64;
|
||||||
w &= ~(1ULL << bitIndex);
|
w &= ~(1ULL << bitIndex);
|
||||||
|
|
@ -618,11 +621,13 @@ public:
|
||||||
T_Value& atWriteAppend(int32_t index) {
|
T_Value& atWriteAppend(int32_t index) {
|
||||||
// cppcheck-suppress variableScope
|
// cppcheck-suppress variableScope
|
||||||
static thread_local T_Value t_throwAway;
|
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();
|
t_throwAway = atDefault();
|
||||||
return t_throwAway;
|
return t_throwAway;
|
||||||
} else if (VL_UNLIKELY(index == m_deque.size())) {
|
|
||||||
push_back(atDefault());
|
|
||||||
}
|
}
|
||||||
return m_deque[index];
|
return m_deque[index];
|
||||||
}
|
}
|
||||||
|
|
@ -921,6 +926,9 @@ std::string VL_TO_STRING(const VlQueue<T_Value, N_MaxSize>& obj) {
|
||||||
return obj.to_string();
|
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
|
// Verilog associative array container
|
||||||
// There are no multithreaded locks on this; the base variable must
|
// There are no multithreaded locks on this; the base variable must
|
||||||
|
|
@ -1256,6 +1264,9 @@ std::string VL_TO_STRING(const VlAssocArray<T_Key, T_Value>& obj) {
|
||||||
return obj.to_string();
|
return obj.to_string();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T_Key, typename T_Value>
|
||||||
|
struct VlContainsCustomStruct<VlAssocArray<T_Key, T_Value>> : VlContainsCustomStruct<T_Key> {};
|
||||||
|
|
||||||
template <typename T_Key, typename T_Value>
|
template <typename T_Key, typename T_Value>
|
||||||
void VL_READMEM_N(bool hex, int bits, const std::string& filename,
|
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 {
|
VlAssocArray<T_Key, T_Value>& obj, QData start, QData end) VL_MT_SAFE {
|
||||||
|
|
@ -1586,6 +1597,9 @@ std::string VL_TO_STRING(const VlUnpacked<T_Value, N_Depth>& obj) {
|
||||||
return obj.to_string();
|
return obj.to_string();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T, int N>
|
||||||
|
struct VlContainsCustomStruct<VlUnpacked<T, N>> : VlContainsCustomStruct<T> {};
|
||||||
|
|
||||||
//===================================================================
|
//===================================================================
|
||||||
// Helper to apply the given indices to a target expression
|
// Helper to apply the given indices to a target expression
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,9 +15,9 @@
|
||||||
/// \brief Verilated C++ tracing in VCD format implementation code
|
/// \brief Verilated C++ tracing in VCD format implementation code
|
||||||
///
|
///
|
||||||
/// This file must be compiled and linked against all Verilated objects
|
/// 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_wrBufp = new char[m_wrChunkSize * 8];
|
||||||
m_wrFlushp = m_wrBufp + m_wrChunkSize * 6;
|
m_wrFlushp = m_wrBufp + m_wrChunkSize * 6;
|
||||||
m_writep = m_wrBufp;
|
m_writep = m_wrBufp;
|
||||||
|
m_wrTimeBeginp = nullptr;
|
||||||
|
m_wrTimeEndp = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VerilatedVcd::open(const char* filename) VL_MT_SAFE_EXCLUDES(m_mutex) {
|
void VerilatedVcd::open(const char* filename) VL_MT_SAFE_EXCLUDES(m_mutex) {
|
||||||
|
|
@ -187,11 +189,20 @@ bool VerilatedVcd::preChangeDump() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void VerilatedVcd::emitTimeChange(uint64_t timeui) {
|
void VerilatedVcd::emitTimeChange(uint64_t timeui) {
|
||||||
|
// 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("#");
|
printStr("#");
|
||||||
const std::string str = std::to_string(timeui);
|
const std::string str = std::to_string(timeui);
|
||||||
printStr(str.c_str());
|
printStr(str.c_str());
|
||||||
printStr("\n");
|
printStr("\n");
|
||||||
}
|
}
|
||||||
|
m_wrTimeEndp = m_writep;
|
||||||
|
}
|
||||||
|
|
||||||
VerilatedVcd::~VerilatedVcd() {
|
VerilatedVcd::~VerilatedVcd() {
|
||||||
close();
|
close();
|
||||||
|
|
@ -257,6 +268,10 @@ void VerilatedVcd::bufferResize(size_t minsize) {
|
||||||
m_wrBufp = new char[m_wrChunkSize * 8];
|
m_wrBufp = new char[m_wrChunkSize * 8];
|
||||||
std::memcpy(m_wrBufp, oldbufp, m_writep - oldbufp);
|
std::memcpy(m_wrBufp, oldbufp, m_writep - oldbufp);
|
||||||
m_writep = m_wrBufp + (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;
|
m_wrFlushp = m_wrBufp + m_wrChunkSize * 6;
|
||||||
VL_DO_CLEAR(delete[] oldbufp, oldbufp = nullptr);
|
VL_DO_CLEAR(delete[] oldbufp, oldbufp = nullptr);
|
||||||
}
|
}
|
||||||
|
|
@ -293,6 +308,8 @@ void VerilatedVcd::bufferFlush() VL_MT_UNSAFE_ONE {
|
||||||
|
|
||||||
// Reset buffer
|
// Reset buffer
|
||||||
m_writep = m_wrBufp;
|
m_writep = m_wrBufp;
|
||||||
|
m_wrTimeBeginp = nullptr;
|
||||||
|
m_wrTimeEndp = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,8 @@ private:
|
||||||
char* m_wrBufp; // Output buffer
|
char* m_wrBufp; // Output buffer
|
||||||
char* m_wrFlushp; // Output buffer flush trigger location
|
char* m_wrFlushp; // Output buffer flush trigger location
|
||||||
char* m_writep; // Write pointer into output buffer
|
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_wrChunkSize; // Output buffer size
|
||||||
size_t m_maxSignalBytes = 0; // Upper bound on number of bytes a single signal can generate
|
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
|
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
|
// 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
|
// We reserve word zero for the next pointer, as that's safer in case a
|
||||||
// dangling reference to the original remains around.
|
// 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))
|
if (VL_UNCOVERABLE(size > CHUNK_SIZE))
|
||||||
VL_FATAL_MT(__FILE__, __LINE__, "", "increase CHUNK_SIZE");
|
VL_FATAL_MT(__FILE__, __LINE__, "", "increase CHUNK_SIZE");
|
||||||
if (VL_LIKELY(t_freeHeadp)) {
|
if (VL_LIKELY(t_freeHeadp)) {
|
||||||
|
|
@ -421,7 +421,7 @@ public:
|
||||||
const char* fullname() const override {
|
const char* fullname() const override {
|
||||||
static thread_local std::string t_out;
|
static thread_local std::string t_out;
|
||||||
t_out = std::string{scopep()->name()} + "." + name();
|
t_out = std::string{scopep()->name()} + "." + name();
|
||||||
for (auto idx : index()) { t_out += "[" + std::to_string(idx) + "]"; }
|
for (auto idx : index()) t_out += "[" + std::to_string(idx) + "]";
|
||||||
return t_out.c_str();
|
return t_out.c_str();
|
||||||
}
|
}
|
||||||
void* prevDatap() const { return m_prevDatap; }
|
void* prevDatap() const { return m_prevDatap; }
|
||||||
|
|
@ -873,6 +873,7 @@ class VerilatedVpiImp final {
|
||||||
// All only medium-speed, so use singleton function
|
// All only medium-speed, so use singleton function
|
||||||
// Callbacks that are past or at current timestamp
|
// Callbacks that are past or at current timestamp
|
||||||
std::array<VpioCbList, CB_ENUM_MAX_VALUE> m_cbCurrentLists;
|
std::array<VpioCbList, CB_ENUM_MAX_VALUE> m_cbCurrentLists;
|
||||||
|
VpioCbList m_cbCallList; // List of callbacks currently being called by callCbs
|
||||||
VpioFutureCbs m_futureCbs; // Time based callbacks for future timestamps
|
VpioFutureCbs m_futureCbs; // Time based callbacks for future timestamps
|
||||||
VpioFutureCbs m_nextCbs; // cbNextSimTime callbacks
|
VpioFutureCbs m_nextCbs; // cbNextSimTime callbacks
|
||||||
std::list<VerilatedVpiPutHolder> m_inertialPuts; // Pending vpi puts due to vpiInertialDelay
|
std::list<VerilatedVpiPutHolder> m_inertialPuts; // Pending vpi puts due to vpiInertialDelay
|
||||||
|
|
@ -925,7 +926,13 @@ public:
|
||||||
for (auto& ir : s().m_cbCurrentLists[reason]) {
|
for (auto& ir : s().m_cbCurrentLists[reason]) {
|
||||||
if (ir.id() == id) {
|
if (ir.id() == id) {
|
||||||
ir.invalidate();
|
ir.invalidate();
|
||||||
return; // Once found, it won't also be in m_futureCbs
|
return; // Once found, it won't also be in m_cbCallList, m_futureCbs, or m_nextCbs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (auto& ir : s().m_cbCallList) {
|
||||||
|
if (ir.id() == id) {
|
||||||
|
ir.invalidate();
|
||||||
|
return; // Once found, it won't also be in m_futureCbs or m_nextCbs
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{ // Remove from cbFuture queue
|
{ // Remove from cbFuture queue
|
||||||
|
|
@ -985,10 +992,9 @@ public:
|
||||||
moveFutureCbs();
|
moveFutureCbs();
|
||||||
if (s().m_cbCurrentLists[reason].empty()) return false;
|
if (s().m_cbCurrentLists[reason].empty()) return false;
|
||||||
// Iterate on old list, making new list empty, to prevent looping over newly added elements
|
// Iterate on old list, making new list empty, to prevent looping over newly added elements
|
||||||
VpioCbList cbObjList;
|
std::swap(s().m_cbCurrentLists[reason], s().m_cbCallList);
|
||||||
std::swap(s().m_cbCurrentLists[reason], cbObjList);
|
|
||||||
bool called = false;
|
bool called = false;
|
||||||
for (VerilatedVpiCbHolder& ihor : cbObjList) {
|
for (VerilatedVpiCbHolder& ihor : s().m_cbCallList) {
|
||||||
// cbReasonRemove sets to nullptr, so we know on removal the old end() will still exist
|
// cbReasonRemove sets to nullptr, so we know on removal the old end() will still exist
|
||||||
if (VL_LIKELY(!ihor.invalid())) { // Not deleted earlier
|
if (VL_LIKELY(!ihor.invalid())) { // Not deleted earlier
|
||||||
VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: reason_callback reason=%d id=%" PRId64 "\n",
|
VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: reason_callback reason=%d id=%" PRId64 "\n",
|
||||||
|
|
@ -998,6 +1004,7 @@ public:
|
||||||
called = true;
|
called = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
s().m_cbCallList.clear();
|
||||||
return called;
|
return called;
|
||||||
}
|
}
|
||||||
static bool callValueCbs() VL_MT_UNSAFE_ONE {
|
static bool callValueCbs() VL_MT_UNSAFE_ONE {
|
||||||
|
|
@ -2567,8 +2574,8 @@ void vl_vpi_put_word(const VerilatedVpioVar* vop, QData word, size_t bitCount, s
|
||||||
}
|
}
|
||||||
|
|
||||||
void vl_vpi_get_value(const VerilatedVpioVarBase* vop, p_vpi_value valuep) {
|
void vl_vpi_get_value(const VerilatedVpioVarBase* vop, p_vpi_value valuep) {
|
||||||
const VerilatedVar* varp = vop->varp();
|
const VerilatedVar* const varp = vop->varp();
|
||||||
void* varDatap = vop->varDatap();
|
void* const varDatap = vop->varDatap();
|
||||||
const char* fullname = vop->fullname();
|
const char* fullname = vop->fullname();
|
||||||
|
|
||||||
if (!vl_check_format(varp, valuep, fullname, true)) return;
|
if (!vl_check_format(varp, valuep, fullname, true)) return;
|
||||||
|
|
@ -2781,8 +2788,8 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value valuep, p_vpi_time /*time_
|
||||||
} else if (valuep->format == vpiOctStrVal) {
|
} else if (valuep->format == vpiOctStrVal) {
|
||||||
const int len = std::strlen(valuep->value.str);
|
const int len = std::strlen(valuep->value.str);
|
||||||
for (int i = 0; i < len; ++i) {
|
for (int i = 0; i < len; ++i) {
|
||||||
char digit = valuep->value.str[len - i - 1] - '0';
|
unsigned char digit = valuep->value.str[len - i - 1] - '0';
|
||||||
if (digit < 0 || digit > 7) {
|
if (digit > 7) { // If str was < '0', then as unsigned, digit > 7
|
||||||
VL_VPI_WARNING_(__FILE__, __LINE__,
|
VL_VPI_WARNING_(__FILE__, __LINE__,
|
||||||
"%s: Non octal character '%c' in '%s' as value %s for %s",
|
"%s: Non octal character '%c' in '%s' as value %s for %s",
|
||||||
__func__, digit + '0', valuep->value.str,
|
__func__, digit + '0', valuep->value.str,
|
||||||
|
|
@ -2973,7 +2980,6 @@ void vl_get_value_array_vectors(unsigned index, const unsigned num, const unsign
|
||||||
"type T is not unsigned"); // ensure logical right shift
|
"type T is not unsigned"); // ensure logical right shift
|
||||||
const unsigned element_size_bytes = VL_BYTES_I(packedSize);
|
const unsigned element_size_bytes = VL_BYTES_I(packedSize);
|
||||||
const unsigned element_size_words = VL_WORDS_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)) {
|
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].aval = static_cast<QData>(src[index]);
|
||||||
|
|
@ -3095,7 +3101,7 @@ void vl_put_value_array_rawvals(unsigned index, const unsigned num, const unsign
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void vl_get_value_array(vpiHandle object, p_vpi_arrayvalue arrayvalue_p, PLI_INT32* index_p,
|
void vl_get_value_array(vpiHandle object, p_vpi_arrayvalue arrayvalue_p, const PLI_INT32* index_p,
|
||||||
PLI_UINT32 num) {
|
PLI_UINT32 num) {
|
||||||
const VerilatedVpioVar* const vop = VerilatedVpioVar::castp(object);
|
const VerilatedVpioVar* const vop = VerilatedVpioVar::castp(object);
|
||||||
if (!vl_check_array_format(vop->varp(), arrayvalue_p, vop->fullname())) return;
|
if (!vl_check_array_format(vop->varp(), arrayvalue_p, vop->fullname())) return;
|
||||||
|
|
@ -3112,7 +3118,7 @@ void vl_get_value_array(vpiHandle object, p_vpi_arrayvalue arrayvalue_p, PLI_INT
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool leftIsLow = vop->rangep()->left() == vop->rangep()->low();
|
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];
|
= leftIsLow ? index_p[0] - vop->rangep()->left() : vop->rangep()->left() - index_p[0];
|
||||||
|
|
||||||
if (arrayvalue_p->format == vpiShortIntVal) {
|
if (arrayvalue_p->format == vpiShortIntVal) {
|
||||||
|
|
@ -3303,9 +3309,8 @@ void vpi_get_value_array(vpiHandle object, p_vpi_arrayvalue arrayvalue_p, PLI_IN
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int lowRange = vop->rangep()->low();
|
const int lowRange = vop->rangep()->low();
|
||||||
int highRange = vop->rangep()->high();
|
const int highRange = vop->rangep()->high();
|
||||||
|
|
||||||
if ((index_p[0] > highRange) || (index_p[0] < lowRange)) {
|
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]",
|
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);
|
__func__, index_p[0], vop->fullname(), lowRange, highRange);
|
||||||
|
|
@ -3321,14 +3326,14 @@ void vpi_get_value_array(vpiHandle object, p_vpi_arrayvalue arrayvalue_p, PLI_IN
|
||||||
vl_get_value_array(object, arrayvalue_p, index_p, num);
|
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) {
|
PLI_UINT32 num) {
|
||||||
const VerilatedVpioVar* const vop = VerilatedVpioVar::castp(object);
|
const VerilatedVpioVar* const vop = VerilatedVpioVar::castp(object);
|
||||||
if (!vl_check_array_format(vop->varp(), arrayvalue_p, vop->fullname())) return;
|
if (!vl_check_array_format(vop->varp(), arrayvalue_p, vop->fullname())) return;
|
||||||
|
|
||||||
const VerilatedVar* const varp = vop->varp();
|
const VerilatedVar* const varp = vop->varp();
|
||||||
|
|
||||||
int size = vop->size();
|
const int size = vop->size();
|
||||||
if (VL_UNCOVERABLE(num > size)) {
|
if (VL_UNCOVERABLE(num > size)) {
|
||||||
VL_VPI_ERROR_(__FILE__, __LINE__,
|
VL_VPI_ERROR_(__FILE__, __LINE__,
|
||||||
"%s: requested elements to set (%u) exceed array size (%u)", __func__, num,
|
"%s: requested elements to set (%u) exceed array size (%u)", __func__, num,
|
||||||
|
|
@ -3337,7 +3342,7 @@ void vl_put_value_array(vpiHandle object, p_vpi_arrayvalue arrayvalue_p, PLI_INT
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool leftIsLow = vop->rangep()->left() == vop->rangep()->low();
|
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];
|
= leftIsLow ? index_p[0] - vop->rangep()->left() : vop->rangep()->left() - index_p[0];
|
||||||
|
|
||||||
if (arrayvalue_p->format == vpiShortIntVal) {
|
if (arrayvalue_p->format == vpiShortIntVal) {
|
||||||
|
|
@ -3485,11 +3490,8 @@ void vpi_put_value_array(vpiHandle object, p_vpi_arrayvalue arrayvalue_p, PLI_IN
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const VerilatedVar* const varp = vop->varp();
|
const int lowRange = vop->rangep()->low();
|
||||||
|
const int highRange = vop->rangep()->high();
|
||||||
int lowRange = vop->rangep()->low();
|
|
||||||
int highRange = vop->rangep()->high();
|
|
||||||
|
|
||||||
if ((index_p[0] > highRange) || (index_p[0] < lowRange)) {
|
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]",
|
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);
|
__func__, index_p[0], vop->fullname(), lowRange, highRange);
|
||||||
|
|
|
||||||
|
|
@ -632,7 +632,12 @@ namespace VlOs {
|
||||||
/// Get environment variable
|
/// Get environment variable
|
||||||
extern std::string getenvStr(const std::string& envvar,
|
extern std::string getenvStr(const std::string& envvar,
|
||||||
const std::string& defaultValue) VL_MT_SAFE;
|
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
|
// Internal: Record CPU time, starting point on construction, and current delta from that
|
||||||
class DeltaCpuTime final {
|
class DeltaCpuTime final {
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,13 @@
|
||||||
# include <processthreadsapi.h> // GetProcessTimes
|
# include <processthreadsapi.h> // GetProcessTimes
|
||||||
# include <psapi.h> // GetProcessMemoryInfo
|
# include <psapi.h> // GetProcessMemoryInfo
|
||||||
#endif
|
#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
|
// clang-format on
|
||||||
|
|
||||||
namespace VlOs {
|
namespace VlOs {
|
||||||
|
|
@ -72,6 +79,28 @@ double DeltaWallTime::gettime() VL_MT_SAFE {
|
||||||
#endif
|
#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
|
// VlOs::memUsageBytes implementation
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
|
//*************************************************************************
|
||||||
|
//
|
||||||
|
// Code available from: https://verilator.org
|
||||||
|
//
|
||||||
|
// Copyright 2009-2025 by Wilson Snyder. This program is free software; you can
|
||||||
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
|
// Version 2.0.
|
||||||
|
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||||
|
//
|
||||||
|
//=========================================================================
|
||||||
|
///
|
||||||
|
/// \file
|
||||||
|
/// \brief Verilated user tf_routines
|
||||||
|
///
|
||||||
|
/// This file contains routines to interface user VPI/PLI C++ code with
|
||||||
|
/// Verilator. Traditionally the veriuser.h code has been used for only
|
||||||
|
/// tf_ routines, which verilator does not implement, so this file is
|
||||||
|
/// empty.
|
||||||
|
///
|
||||||
|
/// User code relying on tf_ routines should migrate to VPI (vpi_user.h) or
|
||||||
|
/// DPI (svdpi.h) routines.
|
||||||
|
///
|
||||||
|
/// This file is only provided for backwards compatibility for applications
|
||||||
|
/// which include veriuser.h even though they use only vpi_ or dpi_
|
||||||
|
/// routines.
|
||||||
|
///
|
||||||
|
//=========================================================================
|
||||||
|
|
||||||
|
// Intentionally empty, see above.
|
||||||
|
|
@ -90,7 +90,7 @@ def process():
|
||||||
|
|
||||||
print()
|
print()
|
||||||
print("You may now want to clean up spelling, and commit:")
|
print("You may now want to clean up spelling, and commit:")
|
||||||
print(" (cd docs ; make spelling)")
|
print(" (cd docs ; make spelling | grep -vi 'writing output')")
|
||||||
print(" git ci -am 'Commentary: Changes update'")
|
print(" git ci -am 'Commentary: Changes update'")
|
||||||
print()
|
print()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,241 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# pylint: disable=C0114,C0115,C0116,R0902,R0903,R0912,R0915,W0719,W0718
|
||||||
|
######################################################################
|
||||||
|
#
|
||||||
|
# Copyright 2025 by Wilson Snyder. This program is free software; you
|
||||||
|
# can redistribute it and/or modify it under the terms of either the GNU
|
||||||
|
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
|
# Version 2.0.
|
||||||
|
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import re
|
||||||
|
|
||||||
|
SUCCESS_CODE = 0
|
||||||
|
FAILURE_CODE = 1
|
||||||
|
INSTANCE_TYPE = "INSTANCE"
|
||||||
|
NET_LIST_TYPE = "NET"
|
||||||
|
SIGNAL_TYPE = "SIGNAL"
|
||||||
|
EOF_ERROR = "Unexpected EOF"
|
||||||
|
|
||||||
|
|
||||||
|
def saif_assert(expression, message):
|
||||||
|
if not expression:
|
||||||
|
raise Exception(message)
|
||||||
|
|
||||||
|
|
||||||
|
def saif_error(message):
|
||||||
|
raise Exception(message)
|
||||||
|
|
||||||
|
|
||||||
|
class SAIFSignalBit:
|
||||||
|
name: str
|
||||||
|
high_time: int
|
||||||
|
low_time: int
|
||||||
|
transitions: int
|
||||||
|
|
||||||
|
def __init__(self, name):
|
||||||
|
self.name = name
|
||||||
|
self.high_time = 0
|
||||||
|
self.low_time = 0
|
||||||
|
self.transitions = 0
|
||||||
|
|
||||||
|
|
||||||
|
class SAIFInstance:
|
||||||
|
|
||||||
|
def __init__(self, scope_name):
|
||||||
|
self.scope_name = scope_name
|
||||||
|
self.parent_instance = None
|
||||||
|
self.nets = {}
|
||||||
|
self.child_instances = {}
|
||||||
|
|
||||||
|
|
||||||
|
class SAIFToken:
|
||||||
|
|
||||||
|
def __init__(self, token):
|
||||||
|
self.token = token
|
||||||
|
self.type = ''
|
||||||
|
self.value = ''
|
||||||
|
|
||||||
|
|
||||||
|
class SAIFParser:
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.token_stack = []
|
||||||
|
# For parsing simplicity
|
||||||
|
self.token_stack.append(SAIFToken('saif_root'))
|
||||||
|
self.current_instance = None
|
||||||
|
self.has_saifile_header = False
|
||||||
|
self.direction = ''
|
||||||
|
self.saif_version = ''
|
||||||
|
self.top_instances = {}
|
||||||
|
self.duration = 0
|
||||||
|
self.divider = ''
|
||||||
|
self.timescale = ''
|
||||||
|
|
||||||
|
def parse(self, saif_filename):
|
||||||
|
file_contents = ''
|
||||||
|
with open(saif_filename, 'r', encoding="utf8") as saif_file:
|
||||||
|
content = saif_file.readlines()
|
||||||
|
filtered_lines = [line for line in content if not line.strip().startswith('//')]
|
||||||
|
file_contents = ''.join(filtered_lines)
|
||||||
|
tokens = file_contents.replace('(', ' ( ').replace(')', ' ) ').split()
|
||||||
|
num_of_tokens = len(tokens)
|
||||||
|
index = 0
|
||||||
|
while index < num_of_tokens:
|
||||||
|
token = tokens[index]
|
||||||
|
index += 1
|
||||||
|
if token == '(':
|
||||||
|
self.token_stack.append(SAIFToken(token))
|
||||||
|
self.token_stack[-1].type = self.token_stack[-2].type
|
||||||
|
self.token_stack[-1].value = self.token_stack[-2].value
|
||||||
|
continue
|
||||||
|
if token == ')':
|
||||||
|
if self.token_stack[-1].type == INSTANCE_TYPE:
|
||||||
|
self.current_instance = self.current_instance.parent_instance
|
||||||
|
self.token_stack.pop()
|
||||||
|
continue
|
||||||
|
if re.match(r'SAIFILE', token):
|
||||||
|
self.has_saifile_header = True
|
||||||
|
continue
|
||||||
|
if re.match(r'DIRECTION', token):
|
||||||
|
saif_assert(index < num_of_tokens, EOF_ERROR)
|
||||||
|
self.direction = tokens[index].replace('\"', '')
|
||||||
|
index += 1
|
||||||
|
continue
|
||||||
|
if re.match(r'SAIFVERSION', token):
|
||||||
|
saif_assert(index < num_of_tokens, EOF_ERROR)
|
||||||
|
self.saif_version = tokens[index].replace('\"', '')
|
||||||
|
index += 1
|
||||||
|
continue
|
||||||
|
if re.match(r'DESIGN|DATE|VENDOR|PROGRAM_NAME|VERSION', token):
|
||||||
|
# NOP, only skip value
|
||||||
|
saif_assert(index < num_of_tokens, EOF_ERROR)
|
||||||
|
index += 1
|
||||||
|
continue
|
||||||
|
if re.match(r'DIVIDER', token):
|
||||||
|
saif_assert(index < num_of_tokens, EOF_ERROR)
|
||||||
|
self.divider = tokens[index]
|
||||||
|
index += 1
|
||||||
|
continue
|
||||||
|
if re.match(r'TIMESCALE', token):
|
||||||
|
saif_assert(index < num_of_tokens, EOF_ERROR)
|
||||||
|
self.timescale = tokens[index]
|
||||||
|
index += 1
|
||||||
|
continue
|
||||||
|
if re.match(r'DURATION', token):
|
||||||
|
saif_assert(index < num_of_tokens, EOF_ERROR)
|
||||||
|
self.duration = tokens[index]
|
||||||
|
index += 1
|
||||||
|
continue
|
||||||
|
if re.match(r'INSTANCE', token):
|
||||||
|
saif_assert(index < num_of_tokens, EOF_ERROR)
|
||||||
|
instance_name = tokens[index]
|
||||||
|
index += 1
|
||||||
|
self.token_stack[-1].type = INSTANCE_TYPE
|
||||||
|
self.token_stack[-1].value = instance_name
|
||||||
|
instance = SAIFInstance(instance_name)
|
||||||
|
if self.current_instance is None:
|
||||||
|
self.top_instances[instance_name] = instance
|
||||||
|
else:
|
||||||
|
self.current_instance.child_instances[instance_name] = instance
|
||||||
|
instance.parent_instance = self.current_instance
|
||||||
|
self.current_instance = instance
|
||||||
|
continue
|
||||||
|
if re.match(r'NET', token):
|
||||||
|
self.token_stack[-1].type = NET_LIST_TYPE
|
||||||
|
continue
|
||||||
|
if re.match(r'T1', token):
|
||||||
|
net_name = self.token_stack[-1].value
|
||||||
|
saif_assert(index < num_of_tokens, EOF_ERROR)
|
||||||
|
self.current_instance.nets[net_name].high_time = tokens[index]
|
||||||
|
index += 1
|
||||||
|
continue
|
||||||
|
if re.match(r'T0', token):
|
||||||
|
net_name = self.token_stack[-1].value
|
||||||
|
saif_assert(index < num_of_tokens, EOF_ERROR)
|
||||||
|
self.current_instance.nets[net_name].low_time = tokens[index]
|
||||||
|
index += 1
|
||||||
|
continue
|
||||||
|
if re.match(r'TC', token):
|
||||||
|
net_name = self.token_stack[-1].value
|
||||||
|
saif_assert(index < num_of_tokens, EOF_ERROR)
|
||||||
|
self.current_instance.nets[net_name].transitions = tokens[index]
|
||||||
|
index += 1
|
||||||
|
continue
|
||||||
|
if re.match(r'TZ|TX|TB|TG|IG|IK', token):
|
||||||
|
# NOP, only skip value
|
||||||
|
index += 1
|
||||||
|
continue
|
||||||
|
if self.token_stack[-2].type == NET_LIST_TYPE:
|
||||||
|
self.token_stack[-1].type = SIGNAL_TYPE
|
||||||
|
self.token_stack[-1].value = token
|
||||||
|
self.current_instance.nets[token] = SAIFSignalBit(token)
|
||||||
|
saif_assert(self.has_saifile_header, "SAIF file doesn't contain a SAIFILE keyword")
|
||||||
|
saif_assert(self.direction == "backward",
|
||||||
|
f"SAIF file doesn't have a valid/compatible direction: {self.direction}")
|
||||||
|
saif_assert(self.saif_version == "2.0",
|
||||||
|
f"SAIF file doesn't have a valid/compatible version: {self.saif_version}")
|
||||||
|
# Only 'saif_root' token should be left
|
||||||
|
saif_assert(len(self.token_stack) == 1, "Incorrect nesting of scopes")
|
||||||
|
|
||||||
|
|
||||||
|
def compare_saif_instances(first: SAIFInstance, second: SAIFInstance):
|
||||||
|
if len(first.nets) != len(second.nets):
|
||||||
|
saif_error(f"Number of nets doesn't match in {first.scope_name}: "
|
||||||
|
f"{len(first.nets)} != {len(second.nets)}")
|
||||||
|
for signal_name, saif_signal in first.nets.items():
|
||||||
|
if signal_name not in second.nets:
|
||||||
|
saif_error(f"Signal {signal_name} doesn't exist in the second object\n")
|
||||||
|
other_signal = second.nets[signal_name]
|
||||||
|
if (saif_signal.high_time != other_signal.high_time
|
||||||
|
or saif_signal.low_time != other_signal.low_time
|
||||||
|
or saif_signal.transitions != other_signal.transitions):
|
||||||
|
saif_error("Incompatible signal bit parameters in "
|
||||||
|
f"{signal_name}\n")
|
||||||
|
if len(first.child_instances) != len(second.child_instances):
|
||||||
|
saif_error(f"Number of child instances doesn't match in {first.scope_name}: "
|
||||||
|
f"{len(first.child_instances)} != {len(second.child_instances)}")
|
||||||
|
for instance_name, instance in first.child_instances.items():
|
||||||
|
if instance_name not in second.child_instances:
|
||||||
|
saif_error(f"Instance {instance_name} doesn't exist in the second object\n")
|
||||||
|
compare_saif_instances(instance, second.child_instances[instance_name])
|
||||||
|
|
||||||
|
|
||||||
|
def compare_saif_contents(first_file: str, second_file: str):
|
||||||
|
"""Test if second SAIF file has the same values as the first"""
|
||||||
|
first_saif = SAIFParser()
|
||||||
|
first_saif.parse(first_file)
|
||||||
|
second_saif = SAIFParser()
|
||||||
|
second_saif.parse(second_file)
|
||||||
|
if first_saif.duration != second_saif.duration:
|
||||||
|
saif_error("Duration of trace doesn't match: "
|
||||||
|
f"{first_saif.duration} != {second_saif.duration}")
|
||||||
|
if first_saif.divider != second_saif.divider:
|
||||||
|
saif_error(f"Dividers don't match: {first_saif.divider} != {second_saif.divider}")
|
||||||
|
if first_saif.timescale != second_saif.timescale:
|
||||||
|
saif_error(f"Timescale doesn't match: {first_saif.timescale} != {second_saif.timescale}")
|
||||||
|
if len(first_saif.top_instances) != len(second_saif.top_instances):
|
||||||
|
saif_error("Number of top instances doesn't match: "
|
||||||
|
f"{len(first_saif.top_instances)} != {len(second_saif.top_instances)}")
|
||||||
|
for top_instance_name, top_instance in first_saif.top_instances.items():
|
||||||
|
if top_instance_name not in second_saif.top_instances:
|
||||||
|
saif_error(f"Top instance {top_instance_name} missing in other SAIF")
|
||||||
|
compare_saif_instances(top_instance, second_saif.top_instances[top_instance_name])
|
||||||
|
return SUCCESS_CODE
|
||||||
|
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(allow_abbrev=False,
|
||||||
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||||
|
description="""verilator_saif_diff checks if two SAIF files are logically-identical. It returns first encountered difference as output.
|
||||||
|
Run as:
|
||||||
|
cd $VERILATOR_ROOT
|
||||||
|
nodist/code_coverage --first example.saif --second other.saif""")
|
||||||
|
parser.add_argument('--first', action='store', help='First SAIF file')
|
||||||
|
parser.add_argument('--second', action='store', help='Second SAIF file')
|
||||||
|
parser.set_defaults(stop=True)
|
||||||
|
args = parser.parse_args()
|
||||||
|
try:
|
||||||
|
compare_saif_contents(args.first, args.second)
|
||||||
|
except Exception as error:
|
||||||
|
print(error)
|
||||||
|
|
@ -85,6 +85,7 @@ set(HEADERS
|
||||||
V3EmitCMain.h
|
V3EmitCMain.h
|
||||||
V3EmitCMake.h
|
V3EmitCMake.h
|
||||||
V3EmitMk.h
|
V3EmitMk.h
|
||||||
|
V3EmitMkJson.h
|
||||||
V3EmitV.h
|
V3EmitV.h
|
||||||
V3EmitXml.h
|
V3EmitXml.h
|
||||||
V3Error.h
|
V3Error.h
|
||||||
|
|
@ -177,6 +178,7 @@ set(HEADERS
|
||||||
V3Trace.h
|
V3Trace.h
|
||||||
V3TraceDecl.h
|
V3TraceDecl.h
|
||||||
V3Tristate.h
|
V3Tristate.h
|
||||||
|
V3Udp.h
|
||||||
V3Undriven.h
|
V3Undriven.h
|
||||||
V3UniqueNames.h
|
V3UniqueNames.h
|
||||||
V3Unknown.h
|
V3Unknown.h
|
||||||
|
|
@ -246,6 +248,7 @@ set(COMMON_SOURCES
|
||||||
V3EmitCPch.cpp
|
V3EmitCPch.cpp
|
||||||
V3EmitCSyms.cpp
|
V3EmitCSyms.cpp
|
||||||
V3EmitMk.cpp
|
V3EmitMk.cpp
|
||||||
|
V3EmitMkJson.cpp
|
||||||
V3EmitV.cpp
|
V3EmitV.cpp
|
||||||
V3EmitXml.cpp
|
V3EmitXml.cpp
|
||||||
V3Error.cpp
|
V3Error.cpp
|
||||||
|
|
@ -324,6 +327,7 @@ set(COMMON_SOURCES
|
||||||
V3TraceDecl.cpp
|
V3TraceDecl.cpp
|
||||||
V3Tristate.cpp
|
V3Tristate.cpp
|
||||||
V3TSP.cpp
|
V3TSP.cpp
|
||||||
|
V3Udp.cpp
|
||||||
V3Undriven.cpp
|
V3Undriven.cpp
|
||||||
V3Unknown.cpp
|
V3Unknown.cpp
|
||||||
V3Unroll.cpp
|
V3Unroll.cpp
|
||||||
|
|
|
||||||
|
|
@ -253,6 +253,7 @@ RAW_OBJS_PCH_ASTNOMT = \
|
||||||
V3EmitCModel.o \
|
V3EmitCModel.o \
|
||||||
V3EmitCSyms.o \
|
V3EmitCSyms.o \
|
||||||
V3EmitMk.o \
|
V3EmitMk.o \
|
||||||
|
V3EmitMkJson.o \
|
||||||
V3EmitXml.o \
|
V3EmitXml.o \
|
||||||
V3ExecGraph.o \
|
V3ExecGraph.o \
|
||||||
V3Expand.o \
|
V3Expand.o \
|
||||||
|
|
@ -310,6 +311,7 @@ RAW_OBJS_PCH_ASTNOMT = \
|
||||||
V3Trace.o \
|
V3Trace.o \
|
||||||
V3TraceDecl.o \
|
V3TraceDecl.o \
|
||||||
V3Tristate.o \
|
V3Tristate.o \
|
||||||
|
V3Udp.o \
|
||||||
V3Undriven.o \
|
V3Undriven.o \
|
||||||
V3Unknown.o \
|
V3Unknown.o \
|
||||||
V3Unroll.o \
|
V3Unroll.o \
|
||||||
|
|
|
||||||
|
|
@ -239,7 +239,7 @@ public:
|
||||||
|
|
||||||
// Make a new AstActive sensitive to the given sentree and return it
|
// Make a new AstActive sensitive to the given sentree and return it
|
||||||
AstActive* makeActive(FileLine* const fl, AstSenTree* const senTreep) {
|
AstActive* makeActive(FileLine* const fl, AstSenTree* const senTreep) {
|
||||||
auto* const activep = new AstActive{fl, "", senTreep};
|
AstActive* const activep = new AstActive{fl, "", senTreep};
|
||||||
activep->sensesStorep(activep->sensesp());
|
activep->sensesStorep(activep->sensesp());
|
||||||
addActive(activep);
|
addActive(activep);
|
||||||
return activep;
|
return activep;
|
||||||
|
|
@ -314,7 +314,7 @@ class ActiveLatchCheckVisitor final : public VNVisitorConst {
|
||||||
void visit(AstVarRef* nodep) override {
|
void visit(AstVarRef* nodep) override {
|
||||||
const AstVar* const varp = nodep->varp();
|
const AstVar* const varp = nodep->varp();
|
||||||
if (nodep->access().isWriteOrRW() && varp->isSignal() && !varp->isUsedLoopIdx()
|
if (nodep->access().isWriteOrRW() && varp->isSignal() && !varp->isUsedLoopIdx()
|
||||||
&& !varp->isFuncLocalSticky()) {
|
&& !varp->isFuncLocalSticky() && !varp->lifetime().isAutomatic()) {
|
||||||
m_graph.addAssignment(nodep);
|
m_graph.addAssignment(nodep);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -572,8 +572,8 @@ class ActiveVisitor final : public VNVisitor {
|
||||||
m_clockedProcess = true;
|
m_clockedProcess = true;
|
||||||
if (nodep->edgeType() != VEdgeType::ET_CHANGED) m_allChanged = false;
|
if (nodep->edgeType() != VEdgeType::ET_CHANGED) m_allChanged = false;
|
||||||
|
|
||||||
if (const auto* const dtypep = nodep->sensp()->dtypep()) {
|
if (const AstNodeDType* const dtypep = nodep->sensp()->dtypep()) {
|
||||||
if (const auto* const basicp = dtypep->basicp()) {
|
if (const AstBasicDType* const basicp = dtypep->basicp()) {
|
||||||
if (basicp->isEvent()) nodep->edgeType(VEdgeType::ET_EVENT);
|
if (basicp->isEvent()) nodep->edgeType(VEdgeType::ET_EVENT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -143,7 +143,7 @@ class AssertVisitor final : public VNVisitor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AstSampled* newSampledExpr(AstNodeExpr* nodep) {
|
AstSampled* newSampledExpr(AstNodeExpr* nodep) {
|
||||||
const auto sampledp = new AstSampled{nodep->fileline(), nodep};
|
AstSampled* const sampledp = new AstSampled{nodep->fileline(), nodep};
|
||||||
sampledp->dtypeFrom(nodep);
|
sampledp->dtypeFrom(nodep);
|
||||||
return sampledp;
|
return sampledp;
|
||||||
}
|
}
|
||||||
|
|
@ -153,7 +153,7 @@ class AssertVisitor final : public VNVisitor {
|
||||||
nodep->findUInt64DType()};
|
nodep->findUInt64DType()};
|
||||||
v3Global.rootp()->dollarUnitPkgAddp()->addStmtsp(m_monitorNumVarp);
|
v3Global.rootp()->dollarUnitPkgAddp()->addStmtsp(m_monitorNumVarp);
|
||||||
}
|
}
|
||||||
const auto varrefp = new AstVarRef{nodep->fileline(), m_monitorNumVarp, access};
|
AstVarRef* const varrefp = new AstVarRef{nodep->fileline(), m_monitorNumVarp, access};
|
||||||
varrefp->classOrPackagep(v3Global.rootp()->dollarUnitPkgAddp());
|
varrefp->classOrPackagep(v3Global.rootp()->dollarUnitPkgAddp());
|
||||||
return varrefp;
|
return varrefp;
|
||||||
}
|
}
|
||||||
|
|
@ -163,7 +163,7 @@ class AssertVisitor final : public VNVisitor {
|
||||||
nodep->findBitDType()};
|
nodep->findBitDType()};
|
||||||
v3Global.rootp()->dollarUnitPkgAddp()->addStmtsp(m_monitorOffVarp);
|
v3Global.rootp()->dollarUnitPkgAddp()->addStmtsp(m_monitorOffVarp);
|
||||||
}
|
}
|
||||||
const auto varrefp = new AstVarRef{nodep->fileline(), m_monitorOffVarp, access};
|
AstVarRef* const varrefp = new AstVarRef{nodep->fileline(), m_monitorOffVarp, access};
|
||||||
varrefp->classOrPackagep(v3Global.rootp()->dollarUnitPkgAddp());
|
varrefp->classOrPackagep(v3Global.rootp()->dollarUnitPkgAddp());
|
||||||
return varrefp;
|
return varrefp;
|
||||||
}
|
}
|
||||||
|
|
@ -528,7 +528,7 @@ class AssertVisitor final : public VNVisitor {
|
||||||
replaceDisplay(nodep, "%%Fatal");
|
replaceDisplay(nodep, "%%Fatal");
|
||||||
} else if (nodep->displayType() == VDisplayType::DT_MONITOR) {
|
} else if (nodep->displayType() == VDisplayType::DT_MONITOR) {
|
||||||
nodep->displayType(VDisplayType::DT_DISPLAY);
|
nodep->displayType(VDisplayType::DT_DISPLAY);
|
||||||
const auto fl = nodep->fileline();
|
FileLine* const fl = nodep->fileline();
|
||||||
AstNode* monExprsp = nodep->fmtp()->exprsp();
|
AstNode* monExprsp = nodep->fmtp()->exprsp();
|
||||||
AstSenItem* monSenItemsp = nullptr;
|
AstSenItem* monSenItemsp = nullptr;
|
||||||
while (monExprsp) {
|
while (monExprsp) {
|
||||||
|
|
@ -548,8 +548,8 @@ class AssertVisitor final : public VNVisitor {
|
||||||
AstSenTree* const monSenTree = new AstSenTree{fl, monSenItemsp};
|
AstSenTree* const monSenTree = new AstSenTree{fl, monSenItemsp};
|
||||||
const auto monNum = ++m_monitorNum;
|
const auto monNum = ++m_monitorNum;
|
||||||
// Where $monitor was we do "__VmonitorNum = N;"
|
// Where $monitor was we do "__VmonitorNum = N;"
|
||||||
const auto newsetp = new AstAssign{fl, newMonitorNumVarRefp(nodep, VAccess::WRITE),
|
AstAssign* const newsetp = new AstAssign{
|
||||||
new AstConst{fl, monNum}};
|
fl, newMonitorNumVarRefp(nodep, VAccess::WRITE), new AstConst{fl, monNum}};
|
||||||
nodep->replaceWith(newsetp);
|
nodep->replaceWith(newsetp);
|
||||||
// Add "always_comb if (__VmonitorOn && __VmonitorNum==N) $display(...);"
|
// Add "always_comb if (__VmonitorOn && __VmonitorNum==N) $display(...);"
|
||||||
AstNode* const stmtsp = nodep;
|
AstNode* const stmtsp = nodep;
|
||||||
|
|
@ -566,13 +566,13 @@ class AssertVisitor final : public VNVisitor {
|
||||||
} else if (nodep->displayType() == VDisplayType::DT_STROBE) {
|
} else if (nodep->displayType() == VDisplayType::DT_STROBE) {
|
||||||
nodep->displayType(VDisplayType::DT_DISPLAY);
|
nodep->displayType(VDisplayType::DT_DISPLAY);
|
||||||
// Need one-shot
|
// Need one-shot
|
||||||
const auto fl = nodep->fileline();
|
FileLine* const fl = nodep->fileline();
|
||||||
const auto varp
|
AstVar* const varp
|
||||||
= new AstVar{fl, VVarType::MODULETEMP, "__Vstrobe" + cvtToStr(m_modStrobeNum++),
|
= new AstVar{fl, VVarType::MODULETEMP, "__Vstrobe" + cvtToStr(m_modStrobeNum++),
|
||||||
nodep->findBitDType()};
|
nodep->findBitDType()};
|
||||||
m_modp->addStmtsp(varp);
|
m_modp->addStmtsp(varp);
|
||||||
// Where $strobe was we do "__Vstrobe = '1;"
|
// Where $strobe was we do "__Vstrobe = '1;"
|
||||||
const auto newsetp = new AstAssign{fl, new AstVarRef{fl, varp, VAccess::WRITE},
|
AstAssign* const newsetp = new AstAssign{fl, new AstVarRef{fl, varp, VAccess::WRITE},
|
||||||
new AstConst{fl, AstConst::BitTrue{}}};
|
new AstConst{fl, AstConst::BitTrue{}}};
|
||||||
nodep->replaceWith(newsetp);
|
nodep->replaceWith(newsetp);
|
||||||
// Add "always_comb if (__Vstrobe) begin $display(...); __Vstrobe = '0; end"
|
// Add "always_comb if (__Vstrobe) begin $display(...); __Vstrobe = '0; end"
|
||||||
|
|
@ -587,7 +587,7 @@ class AssertVisitor final : public VNVisitor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void visit(AstMonitorOff* nodep) override {
|
void visit(AstMonitorOff* nodep) override {
|
||||||
const auto newp
|
AstAssign* const newp
|
||||||
= new AstAssign{nodep->fileline(), newMonitorOffVarRefp(nodep, VAccess::WRITE),
|
= new AstAssign{nodep->fileline(), newMonitorOffVarRefp(nodep, VAccess::WRITE),
|
||||||
new AstConst{nodep->fileline(), AstConst::BitTrue{}, nodep->off()}};
|
new AstConst{nodep->fileline(), AstConst::BitTrue{}, nodep->off()}};
|
||||||
nodep->replaceWith(newp);
|
nodep->replaceWith(newp);
|
||||||
|
|
|
||||||
|
|
@ -95,10 +95,10 @@ private:
|
||||||
if (const AstVarRef* varrefp = VN_CAST(nodep, VarRef)) {
|
if (const AstVarRef* varrefp = VN_CAST(nodep, VarRef)) {
|
||||||
if (varp == varrefp->varp()) nodep->replaceWith(exprp->cloneTree(false));
|
if (varp == varrefp->varp()) nodep->replaceWith(exprp->cloneTree(false));
|
||||||
}
|
}
|
||||||
replaceVarRefsWithExprRecurse(nodep->op1p(), varp, exprp);
|
if (AstNode* const refp = nodep->op1p()) replaceVarRefsWithExprRecurse(refp, varp, exprp);
|
||||||
replaceVarRefsWithExprRecurse(nodep->op2p(), varp, exprp);
|
if (AstNode* const refp = nodep->op2p()) replaceVarRefsWithExprRecurse(refp, varp, exprp);
|
||||||
replaceVarRefsWithExprRecurse(nodep->op3p(), varp, exprp);
|
if (AstNode* const refp = nodep->op3p()) replaceVarRefsWithExprRecurse(refp, varp, exprp);
|
||||||
replaceVarRefsWithExprRecurse(nodep->op4p(), varp, exprp);
|
if (AstNode* const refp = nodep->op4p()) replaceVarRefsWithExprRecurse(refp, varp, exprp);
|
||||||
}
|
}
|
||||||
AstPropSpec* substitutePropertyCall(AstPropSpec* nodep) {
|
AstPropSpec* substitutePropertyCall(AstPropSpec* nodep) {
|
||||||
if (AstFuncRef* const funcrefp = VN_CAST(nodep->propp(), FuncRef)) {
|
if (AstFuncRef* const funcrefp = VN_CAST(nodep->propp(), FuncRef)) {
|
||||||
|
|
@ -295,7 +295,7 @@ private:
|
||||||
popp->makeStmt()});
|
popp->makeStmt()});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
nodep->v3fatal("Invalid direction");
|
nodep->v3fatalSrc("Invalid direction");
|
||||||
}
|
}
|
||||||
VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep);
|
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_emptyp = std::make_shared<string>("");
|
||||||
const std::shared_ptr<const string> VSelfPointerText::s_thisp = std::make_shared<string>("this");
|
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 {
|
string VSelfPointerText::protect(bool useSelfForThis, bool protect) const {
|
||||||
const string& sp
|
return VIdProtect::protectWordsIf(replaceThis(useSelfForThis, asString()), protect);
|
||||||
= useSelfForThis ? VString::replaceWord(asString(), "this", "vlSelf") : asString();
|
|
||||||
return VIdProtect::protectWordsIf(sp, protect);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
|
|
@ -228,7 +230,7 @@ string AstNode::vpiName(const string& namein) {
|
||||||
// we change that identifier to an escaped identifier, wrapping it with '\' and ' '
|
// we change that identifier to an escaped identifier, wrapping it with '\' and ' '
|
||||||
// as specified in LRM 23.6
|
// as specified in LRM 23.6
|
||||||
string name = namein;
|
string name = namein;
|
||||||
if (0 == namein.substr(0, 7).compare("__SYM__")) { name = namein.substr(7); }
|
if (0 == namein.substr(0, 7).compare("__SYM__")) name = namein.substr(7);
|
||||||
string pretty;
|
string pretty;
|
||||||
pretty.reserve(name.length());
|
pretty.reserve(name.length());
|
||||||
bool inEscapedIdent = false;
|
bool inEscapedIdent = false;
|
||||||
|
|
@ -1340,7 +1342,7 @@ void AstNode::dumpTreeFile(const string& filename, bool doDump) {
|
||||||
{ // Write log & close
|
{ // Write log & close
|
||||||
UINFO(2, "Dumping " << filename << endl);
|
UINFO(2, "Dumping " << filename << endl);
|
||||||
const std::unique_ptr<std::ofstream> logsp{V3File::new_ofstream(filename)};
|
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 << "Verilator Tree Dump (format 0x3900) from <e" << std::dec << editCountLast();
|
||||||
*logsp << "> to <e" << std::dec << editCountGbl() << ">\n";
|
*logsp << "> to <e" << std::dec << editCountGbl() << ">\n";
|
||||||
if (editCountGbl() == editCountLast() && ::dumpTreeLevel() < 9) {
|
if (editCountGbl() == editCountLast() && ::dumpTreeLevel() < 9) {
|
||||||
|
|
@ -1385,7 +1387,7 @@ void AstNode::dumpTreeJsonFile(const string& filename, bool doDump) {
|
||||||
if (!doDump) return;
|
if (!doDump) return;
|
||||||
UINFO(2, "Dumping " << filename << endl);
|
UINFO(2, "Dumping " << filename << endl);
|
||||||
const std::unique_ptr<std::ofstream> treejsonp{V3File::new_ofstream(filename)};
|
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);
|
dumpTreeJson(*treejsonp);
|
||||||
*treejsonp << '\n';
|
*treejsonp << '\n';
|
||||||
}
|
}
|
||||||
|
|
@ -1394,7 +1396,7 @@ void AstNode::dumpJsonMetaFileGdb(const char* filename) { dumpJsonMetaFile(filen
|
||||||
void AstNode::dumpJsonMetaFile(const string& filename) {
|
void AstNode::dumpJsonMetaFile(const string& filename) {
|
||||||
UINFO(2, "Dumping " << filename << endl);
|
UINFO(2, "Dumping " << filename << endl);
|
||||||
const std::unique_ptr<std::ofstream> treejsonp{V3File::new_ofstream(filename)};
|
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 << '{';
|
*treejsonp << '{';
|
||||||
FileLine::fileNameNumMapDumpJson(*treejsonp);
|
FileLine::fileNameNumMapDumpJson(*treejsonp);
|
||||||
*treejsonp << ',';
|
*treejsonp << ',';
|
||||||
|
|
@ -1408,7 +1410,7 @@ void AstNode::dumpTreeDotFile(const string& filename, bool doDump) {
|
||||||
if (doDump) {
|
if (doDump) {
|
||||||
UINFO(2, "Dumping " << filename << endl);
|
UINFO(2, "Dumping " << filename << endl);
|
||||||
const std::unique_ptr<std::ofstream> treedotp{V3File::new_ofstream(filename)};
|
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 << "digraph vTree{\n";
|
||||||
*treedotp << "\tgraph\t[label=\"" << filename + ".dot"
|
*treedotp << "\tgraph\t[label=\"" << filename + ".dot"
|
||||||
<< "\",\n";
|
<< "\",\n";
|
||||||
|
|
|
||||||
|
|
@ -1686,6 +1686,7 @@ public:
|
||||||
bool isVlSym() const { return m_strp->find("vlSymsp") != string::npos; }
|
bool isVlSym() const { return m_strp->find("vlSymsp") != string::npos; }
|
||||||
bool hasThis() const { return m_strp == s_thisp || VString::startsWith(*m_strp, "this"); }
|
bool hasThis() const { return m_strp == s_thisp || VString::startsWith(*m_strp, "this"); }
|
||||||
string protect(bool useSelfForThis, bool protect) const;
|
string protect(bool useSelfForThis, bool protect) const;
|
||||||
|
static string replaceThis(bool useSelfForThis, const string& text);
|
||||||
const std::string& asString() const { return *m_strp; }
|
const std::string& asString() const { return *m_strp; }
|
||||||
bool operator==(const VSelfPointerText& other) const { return *m_strp == *other.m_strp; }
|
bool operator==(const VSelfPointerText& other) const { return *m_strp == *other.m_strp; }
|
||||||
};
|
};
|
||||||
|
|
@ -2359,6 +2360,7 @@ public:
|
||||||
AstNodeDType* findBitDType() const { return findBasicDType(VBasicDTypeKwd::LOGIC); }
|
AstNodeDType* findBitDType() const { return findBasicDType(VBasicDTypeKwd::LOGIC); }
|
||||||
AstNodeDType* findDoubleDType() const { return findBasicDType(VBasicDTypeKwd::DOUBLE); }
|
AstNodeDType* findDoubleDType() const { return findBasicDType(VBasicDTypeKwd::DOUBLE); }
|
||||||
AstNodeDType* findStringDType() const { return findBasicDType(VBasicDTypeKwd::STRING); }
|
AstNodeDType* findStringDType() const { return findBasicDType(VBasicDTypeKwd::STRING); }
|
||||||
|
AstNodeDType* findSigned8DType() const { return findBasicDType(VBasicDTypeKwd::BYTE); }
|
||||||
AstNodeDType* findSigned32DType() const { return findBasicDType(VBasicDTypeKwd::INTEGER); }
|
AstNodeDType* findSigned32DType() const { return findBasicDType(VBasicDTypeKwd::INTEGER); }
|
||||||
AstNodeDType* findUInt32DType() const { return findBasicDType(VBasicDTypeKwd::UINT32); }
|
AstNodeDType* findUInt32DType() const { return findBasicDType(VBasicDTypeKwd::UINT32); }
|
||||||
AstNodeDType* findUInt64DType() const { return findBasicDType(VBasicDTypeKwd::UINT64); }
|
AstNodeDType* findUInt64DType() const { return findBasicDType(VBasicDTypeKwd::UINT64); }
|
||||||
|
|
@ -2485,6 +2487,8 @@ public:
|
||||||
virtual bool isGateOptimizable() const { return !isTimingControl(); }
|
virtual bool isGateOptimizable() const { return !isTimingControl(); }
|
||||||
// GateDedupable is a slightly larger superset of GateOptimzable (eg, AstNodeIf)
|
// GateDedupable is a slightly larger superset of GateOptimzable (eg, AstNodeIf)
|
||||||
virtual bool isGateDedupable() const { return isGateOptimizable(); }
|
virtual bool isGateDedupable() const { return isGateOptimizable(); }
|
||||||
|
// Whether the node can be used in expression coverage
|
||||||
|
virtual bool isExprCoverageEligible() const { return isGateDedupable(); }
|
||||||
// Else creates output or exits, etc, not unconsumed
|
// Else creates output or exits, etc, not unconsumed
|
||||||
virtual bool isOutputter() { return false; }
|
virtual bool isOutputter() { return false; }
|
||||||
// Else a AstTime etc which output can't be predicted from input
|
// Else a AstTime etc which output can't be predicted from input
|
||||||
|
|
|
||||||
|
|
@ -189,8 +189,8 @@ bool AstVarRef::sameNode(const AstVarRef* samep) const {
|
||||||
return (varScopep() == samep->varScopep() && access() == samep->access());
|
return (varScopep() == samep->varScopep() && access() == samep->access());
|
||||||
} else {
|
} else {
|
||||||
return (selfPointer() == samep->selfPointer()
|
return (selfPointer() == samep->selfPointer()
|
||||||
&& classOrPackagep() == samep->classOrPackagep()
|
&& classOrPackagep() == samep->classOrPackagep() && access() == samep->access()
|
||||||
&& varp()->name() == samep->varp()->name() && access() == samep->access());
|
&& (varp() && samep->varp() && varp()->name() == samep->varp()->name()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool AstVarRef::sameNoLvalue(AstVarRef* samep) const {
|
bool AstVarRef::sameNoLvalue(AstVarRef* samep) const {
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,8 @@ protected:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// METHODS
|
// METHODS
|
||||||
const AstNodeDType* skipRefIterp(bool skipConst, bool skipEnum) const VL_MT_STABLE;
|
const AstNodeDType* skipRefIterp(bool skipConst, bool skipEnum,
|
||||||
|
bool assertOn = true) const VL_MT_STABLE;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// METHODS
|
// METHODS
|
||||||
|
|
@ -78,6 +79,15 @@ public:
|
||||||
return const_cast<AstNodeDType*>(
|
return const_cast<AstNodeDType*>(
|
||||||
static_cast<const AstNodeDType*>(this)->skipRefIterp(true, true));
|
static_cast<const AstNodeDType*>(this)->skipRefIterp(true, true));
|
||||||
}
|
}
|
||||||
|
// (Slow) Recurse over MemberDType|ParamTypeDType|RefDType|ConstDType|EnumDType to other type,
|
||||||
|
// Returns null if not resolved
|
||||||
|
const AstNodeDType* skipRefOrNullp() const VL_MT_STABLE {
|
||||||
|
return skipRefIterp(true, true, false);
|
||||||
|
}
|
||||||
|
AstNodeDType* skipRefOrNullp() VL_MT_STABLE {
|
||||||
|
return const_cast<AstNodeDType*>(
|
||||||
|
static_cast<const AstNodeDType*>(this)->skipRefIterp(true, true, false));
|
||||||
|
}
|
||||||
// (Slow) Recurse over MemberDType|ParamTypeDType|RefDType|EnumDType to ConstDType
|
// (Slow) Recurse over MemberDType|ParamTypeDType|RefDType|EnumDType to ConstDType
|
||||||
const AstNodeDType* skipRefToConstp() const { return skipRefIterp(false, true); }
|
const AstNodeDType* skipRefToConstp() const { return skipRefIterp(false, true); }
|
||||||
AstNodeDType* skipRefToConstp() {
|
AstNodeDType* skipRefToConstp() {
|
||||||
|
|
@ -110,15 +120,7 @@ public:
|
||||||
// Iff has second dtype, set as generic node function
|
// Iff has second dtype, set as generic node function
|
||||||
virtual void virtRefDType2p(AstNodeDType* nodep) {}
|
virtual void virtRefDType2p(AstNodeDType* nodep) {}
|
||||||
// Assignable equivalence. Calls skipRefToNonRefp() during comparisons.
|
// Assignable equivalence. Calls skipRefToNonRefp() during comparisons.
|
||||||
bool similarDType(const AstNodeDType* samep) const {
|
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Iff has a non-null subDTypep(), as generic node function
|
// Iff has a non-null subDTypep(), as generic node function
|
||||||
virtual AstNodeDType* subDTypep() const VL_MT_STABLE { return nullptr; }
|
virtual AstNodeDType* subDTypep() const VL_MT_STABLE { return nullptr; }
|
||||||
virtual bool isFourstate() const;
|
virtual bool isFourstate() const;
|
||||||
|
|
@ -155,7 +157,7 @@ public:
|
||||||
bool generic() const VL_MT_SAFE { return m_generic; }
|
bool generic() const VL_MT_SAFE { return m_generic; }
|
||||||
void generic(bool flag) { m_generic = flag; }
|
void generic(bool flag) { m_generic = flag; }
|
||||||
std::pair<uint32_t, uint32_t> dimensions(bool includeBasic);
|
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; }
|
static int uniqueNumInc() { return ++s_uniqueNum; }
|
||||||
const char* charIQWN() const {
|
const char* charIQWN() const {
|
||||||
return (isString() ? "N" : isWide() ? "W" : isQuad() ? "Q" : "I");
|
return (isString() ? "N" : isWide() ? "W" : isQuad() ? "Q" : "I");
|
||||||
|
|
@ -522,7 +524,7 @@ public:
|
||||||
AstCDType(FileLine* fl, const string& name)
|
AstCDType(FileLine* fl, const string& name)
|
||||||
: ASTGEN_SUPER_CDType(fl)
|
: ASTGEN_SUPER_CDType(fl)
|
||||||
, m_name{name} {
|
, m_name{name} {
|
||||||
this->dtypep(this);
|
dtypep(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
@ -562,8 +564,8 @@ public:
|
||||||
AstClassRefDType(FileLine* fl, AstClass* classp, AstPin* paramsp)
|
AstClassRefDType(FileLine* fl, AstClass* classp, AstPin* paramsp)
|
||||||
: ASTGEN_SUPER_ClassRefDType(fl)
|
: ASTGEN_SUPER_ClassRefDType(fl)
|
||||||
, m_classp{classp} {
|
, m_classp{classp} {
|
||||||
this->dtypep(this);
|
dtypep(this);
|
||||||
this->addParamsp(paramsp);
|
addParamsp(paramsp);
|
||||||
}
|
}
|
||||||
ASTGEN_MEMBERS_AstClassRefDType;
|
ASTGEN_MEMBERS_AstClassRefDType;
|
||||||
// METHODS
|
// METHODS
|
||||||
|
|
@ -571,7 +573,11 @@ public:
|
||||||
const AstClassRefDType* const asamep = VN_DBG_AS(samep, ClassRefDType);
|
const AstClassRefDType* const asamep = VN_DBG_AS(samep, ClassRefDType);
|
||||||
return (m_classp == asamep->m_classp && m_classOrPackagep == asamep->m_classOrPackagep);
|
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 dump(std::ostream& str = std::cout) const override;
|
||||||
void dumpJson(std::ostream& str = std::cout) const override;
|
void dumpJson(std::ostream& str = std::cout) const override;
|
||||||
void dumpSmall(std::ostream& str) const override;
|
void dumpSmall(std::ostream& str) const override;
|
||||||
|
|
@ -1065,7 +1071,7 @@ class AstQueueDType final : public AstNodeDType {
|
||||||
public:
|
public:
|
||||||
AstQueueDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp, AstNodeExpr* boundp)
|
AstQueueDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp, AstNodeExpr* boundp)
|
||||||
: ASTGEN_SUPER_QueueDType(fl) {
|
: ASTGEN_SUPER_QueueDType(fl) {
|
||||||
this->childDTypep(dtp);
|
childDTypep(dtp);
|
||||||
this->boundp(boundp);
|
this->boundp(boundp);
|
||||||
refDTypep(nullptr);
|
refDTypep(nullptr);
|
||||||
dtypep(nullptr); // V3Width will resolve
|
dtypep(nullptr); // V3Width will resolve
|
||||||
|
|
@ -1125,7 +1131,7 @@ public:
|
||||||
AstRefDType(FileLine* fl, const string& name, AstNodeExpr* classOrPackagep, AstPin* paramsp)
|
AstRefDType(FileLine* fl, const string& name, AstNodeExpr* classOrPackagep, AstPin* paramsp)
|
||||||
: ASTGEN_SUPER_RefDType(fl)
|
: ASTGEN_SUPER_RefDType(fl)
|
||||||
, m_name{name} {
|
, m_name{name} {
|
||||||
this->classOrPackageOpp(classOrPackagep);
|
classOrPackageOpp(classOrPackagep);
|
||||||
addParamsp(paramsp);
|
addParamsp(paramsp);
|
||||||
}
|
}
|
||||||
class FlagTypeOfExpr {}; // type(expr) for parser only
|
class FlagTypeOfExpr {}; // type(expr) for parser only
|
||||||
|
|
@ -1342,7 +1348,7 @@ class AstUnpackArrayDType final : public AstNodeArrayDType {
|
||||||
public:
|
public:
|
||||||
AstUnpackArrayDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp, AstRange* rangep)
|
AstUnpackArrayDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp, AstRange* rangep)
|
||||||
: ASTGEN_SUPER_UnpackArrayDType(fl) {
|
: ASTGEN_SUPER_UnpackArrayDType(fl) {
|
||||||
this->childDTypep(dtp); // Only for parser
|
childDTypep(dtp); // Only for parser
|
||||||
this->rangep(rangep);
|
this->rangep(rangep);
|
||||||
refDTypep(nullptr);
|
refDTypep(nullptr);
|
||||||
dtypep(nullptr); // V3Width will resolve
|
dtypep(nullptr); // V3Width will resolve
|
||||||
|
|
@ -1382,13 +1388,20 @@ public:
|
||||||
string verilogKwd() const override { return "struct"; }
|
string verilogKwd() const override { return "struct"; }
|
||||||
};
|
};
|
||||||
class AstUnionDType final : public AstNodeUOrStructDType {
|
class AstUnionDType final : public AstNodeUOrStructDType {
|
||||||
|
bool m_isSoft; // Is a "union soft"
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// UNSUP: bool isTagged;
|
// UNSUP: bool isTagged;
|
||||||
// VSigning below is mispurposed to indicate if packed or not
|
// VSigning below is mispurposed to indicate if packed or not
|
||||||
AstUnionDType(FileLine* fl, VSigning numericUnpack)
|
// isSoft implies packed
|
||||||
: ASTGEN_SUPER_UnionDType(fl, numericUnpack) {}
|
AstUnionDType(FileLine* fl, bool isSoft, VSigning numericUnpack)
|
||||||
|
: ASTGEN_SUPER_UnionDType(fl, numericUnpack)
|
||||||
|
, m_isSoft(isSoft) {
|
||||||
|
packed(packed() | m_isSoft);
|
||||||
|
}
|
||||||
ASTGEN_MEMBERS_AstUnionDType;
|
ASTGEN_MEMBERS_AstUnionDType;
|
||||||
string verilogKwd() const override { return "union"; }
|
string verilogKwd() const override { return "union"; }
|
||||||
|
bool isSoft() const { return m_isSoft; }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // Guard
|
#endif // Guard
|
||||||
|
|
|
||||||
|
|
@ -243,12 +243,12 @@ protected:
|
||||||
AstNodeFTaskRef(VNType t, FileLine* fl, AstNode* namep, AstNodeExpr* pinsp)
|
AstNodeFTaskRef(VNType t, FileLine* fl, AstNode* namep, AstNodeExpr* pinsp)
|
||||||
: AstNodeExpr{t, fl} {
|
: AstNodeExpr{t, fl} {
|
||||||
this->namep(namep);
|
this->namep(namep);
|
||||||
this->addPinsp(pinsp);
|
addPinsp(pinsp);
|
||||||
}
|
}
|
||||||
AstNodeFTaskRef(VNType t, FileLine* fl, const string& name, AstNodeExpr* pinsp)
|
AstNodeFTaskRef(VNType t, FileLine* fl, const string& name, AstNodeExpr* pinsp)
|
||||||
: AstNodeExpr{t, fl}
|
: AstNodeExpr{t, fl}
|
||||||
, m_name{name} {
|
, m_name{name} {
|
||||||
this->addPinsp(pinsp);
|
addPinsp(pinsp);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
@ -542,6 +542,7 @@ public:
|
||||||
// Know no children, and hot function, so skip iterator for speed
|
// Know no children, and hot function, so skip iterator for speed
|
||||||
// cppcheck-suppress functionConst
|
// cppcheck-suppress functionConst
|
||||||
void iterateChildren(VNVisitorConst& v) {}
|
void iterateChildren(VNVisitorConst& v) {}
|
||||||
|
static AstNodeVarRef* varRefLValueRecurse(AstNode* nodep);
|
||||||
};
|
};
|
||||||
|
|
||||||
// === Concrete node types =====================================================
|
// === Concrete node types =====================================================
|
||||||
|
|
@ -647,7 +648,7 @@ public:
|
||||||
: ASTGEN_SUPER_CMethodHard(fl)
|
: ASTGEN_SUPER_CMethodHard(fl)
|
||||||
, m_name{name} {
|
, m_name{name} {
|
||||||
this->fromp(fromp);
|
this->fromp(fromp);
|
||||||
this->addPinsp(pinsp);
|
addPinsp(pinsp);
|
||||||
setPurity();
|
setPurity();
|
||||||
}
|
}
|
||||||
ASTGEN_MEMBERS_AstCMethodHard;
|
ASTGEN_MEMBERS_AstCMethodHard;
|
||||||
|
|
@ -674,7 +675,7 @@ public:
|
||||||
AstCast(FileLine* fl, AstNodeExpr* fromp, VFlagChildDType, AstNodeDType* dtp)
|
AstCast(FileLine* fl, AstNodeExpr* fromp, VFlagChildDType, AstNodeDType* dtp)
|
||||||
: ASTGEN_SUPER_Cast(fl) {
|
: ASTGEN_SUPER_Cast(fl) {
|
||||||
this->fromp(fromp);
|
this->fromp(fromp);
|
||||||
this->childDTypep(dtp);
|
childDTypep(dtp);
|
||||||
dtypeFrom(dtp);
|
dtypeFrom(dtp);
|
||||||
}
|
}
|
||||||
AstCast(FileLine* fl, AstNodeExpr* fromp, AstNodeDType* dtp)
|
AstCast(FileLine* fl, AstNodeExpr* fromp, AstNodeDType* dtp)
|
||||||
|
|
@ -728,7 +729,7 @@ public:
|
||||||
AstCellArrayRef(FileLine* fl, const string& name, AstNodeExpr* selp)
|
AstCellArrayRef(FileLine* fl, const string& name, AstNodeExpr* selp)
|
||||||
: ASTGEN_SUPER_CellArrayRef(fl)
|
: ASTGEN_SUPER_CellArrayRef(fl)
|
||||||
, m_name{name} {
|
, m_name{name} {
|
||||||
this->addSelp(selp);
|
addSelp(selp);
|
||||||
}
|
}
|
||||||
ASTGEN_MEMBERS_AstCellArrayRef;
|
ASTGEN_MEMBERS_AstCellArrayRef;
|
||||||
// ACCESSORS
|
// ACCESSORS
|
||||||
|
|
@ -769,7 +770,7 @@ public:
|
||||||
: ASTGEN_SUPER_ClassOrPackageRef(fl)
|
: ASTGEN_SUPER_ClassOrPackageRef(fl)
|
||||||
, m_name{name}
|
, m_name{name}
|
||||||
, m_classOrPackageNodep{classOrPackageNodep} {
|
, m_classOrPackageNodep{classOrPackageNodep} {
|
||||||
this->addParamsp(paramsp);
|
addParamsp(paramsp);
|
||||||
}
|
}
|
||||||
ASTGEN_MEMBERS_AstClassOrPackageRef;
|
ASTGEN_MEMBERS_AstClassOrPackageRef;
|
||||||
// METHODS
|
// METHODS
|
||||||
|
|
@ -876,7 +877,7 @@ public:
|
||||||
AstConsPackMember* membersp = nullptr)
|
AstConsPackMember* membersp = nullptr)
|
||||||
: ASTGEN_SUPER_ConsPackUOrStruct(fl) {
|
: ASTGEN_SUPER_ConsPackUOrStruct(fl) {
|
||||||
this->dtypep(dtypep);
|
this->dtypep(dtypep);
|
||||||
this->addMembersp(membersp);
|
addMembersp(membersp);
|
||||||
}
|
}
|
||||||
ASTGEN_MEMBERS_AstConsPackUOrStruct;
|
ASTGEN_MEMBERS_AstConsPackUOrStruct;
|
||||||
const char* broken() const override {
|
const char* broken() const override {
|
||||||
|
|
@ -1155,6 +1156,20 @@ public:
|
||||||
string emitC() override { V3ERROR_NA_RETURN(""); }
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
||||||
bool cleanOut() const override { return true; }
|
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 {
|
class AstDist final : public AstNodeExpr {
|
||||||
// @astgen op1 := exprp : AstNodeExpr
|
// @astgen op1 := exprp : AstNodeExpr
|
||||||
// @astgen op2 := itemsp : List[AstDistItem]
|
// @astgen op2 := itemsp : List[AstDistItem]
|
||||||
|
|
@ -1162,7 +1177,7 @@ public:
|
||||||
AstDist(FileLine* fl, AstNodeExpr* exprp, AstDistItem* itemsp)
|
AstDist(FileLine* fl, AstNodeExpr* exprp, AstDistItem* itemsp)
|
||||||
: ASTGEN_SUPER_Inside(fl) {
|
: ASTGEN_SUPER_Inside(fl) {
|
||||||
this->exprp(exprp);
|
this->exprp(exprp);
|
||||||
this->addItemsp(itemsp);
|
addItemsp(itemsp);
|
||||||
dtypeSetBit();
|
dtypeSetBit();
|
||||||
}
|
}
|
||||||
ASTGEN_MEMBERS_AstDist;
|
ASTGEN_MEMBERS_AstDist;
|
||||||
|
|
@ -1552,7 +1567,7 @@ public:
|
||||||
AstInside(FileLine* fl, AstNodeExpr* exprp, AstNodeExpr* itemsp)
|
AstInside(FileLine* fl, AstNodeExpr* exprp, AstNodeExpr* itemsp)
|
||||||
: ASTGEN_SUPER_Inside(fl) {
|
: ASTGEN_SUPER_Inside(fl) {
|
||||||
this->exprp(exprp);
|
this->exprp(exprp);
|
||||||
this->addItemsp(itemsp);
|
addItemsp(itemsp);
|
||||||
dtypeSetBit();
|
dtypeSetBit();
|
||||||
}
|
}
|
||||||
ASTGEN_MEMBERS_AstInside;
|
ASTGEN_MEMBERS_AstInside;
|
||||||
|
|
@ -1599,6 +1614,7 @@ public:
|
||||||
string name() const override VL_MT_STABLE { return m_name; } // * = Var name
|
string name() const override VL_MT_STABLE { return m_name; } // * = Var name
|
||||||
void name(const string& name) override { m_name = name; }
|
void name(const string& name) override { m_name = name; }
|
||||||
bool index() const { return m_index; }
|
bool index() const { return m_index; }
|
||||||
|
bool isExprCoverageEligible() const override { return false; }
|
||||||
};
|
};
|
||||||
class AstMemberSel final : public AstNodeExpr {
|
class AstMemberSel final : public AstNodeExpr {
|
||||||
// @astgen op1 := fromp : AstNodeExpr
|
// @astgen op1 := fromp : AstNodeExpr
|
||||||
|
|
@ -1744,7 +1760,7 @@ class AstPatMember final : public AstNodeExpr {
|
||||||
public:
|
public:
|
||||||
AstPatMember(FileLine* fl, AstNodeExpr* lhssp, AstNode* keyp, AstNodeExpr* repp)
|
AstPatMember(FileLine* fl, AstNodeExpr* lhssp, AstNode* keyp, AstNodeExpr* repp)
|
||||||
: ASTGEN_SUPER_PatMember(fl) {
|
: ASTGEN_SUPER_PatMember(fl) {
|
||||||
this->addLhssp(lhssp);
|
addLhssp(lhssp);
|
||||||
this->keyp(keyp);
|
this->keyp(keyp);
|
||||||
this->repp(repp);
|
this->repp(repp);
|
||||||
}
|
}
|
||||||
|
|
@ -1911,6 +1927,7 @@ public:
|
||||||
}
|
}
|
||||||
ASTGEN_MEMBERS_AstSFormatF;
|
ASTGEN_MEMBERS_AstSFormatF;
|
||||||
string name() const override VL_MT_STABLE { return m_text; }
|
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; }
|
int instrCount() const override { return INSTR_COUNT_PLI; }
|
||||||
bool sameNode(const AstNode* samep) const override {
|
bool sameNode(const AstNode* samep) const override {
|
||||||
return text() == VN_DBG_AS(samep, SFormatF)->text();
|
return text() == VN_DBG_AS(samep, SFormatF)->text();
|
||||||
|
|
@ -1941,7 +1958,7 @@ public:
|
||||||
AstSScanF(FileLine* fl, const string& text, AstNode* fromp, AstNode* exprsp)
|
AstSScanF(FileLine* fl, const string& text, AstNode* fromp, AstNode* exprsp)
|
||||||
: ASTGEN_SUPER_SScanF(fl)
|
: ASTGEN_SUPER_SScanF(fl)
|
||||||
, m_text{text} {
|
, m_text{text} {
|
||||||
this->addExprsp(exprsp);
|
addExprsp(exprsp);
|
||||||
this->fromp(fromp);
|
this->fromp(fromp);
|
||||||
}
|
}
|
||||||
ASTGEN_MEMBERS_AstSScanF;
|
ASTGEN_MEMBERS_AstSScanF;
|
||||||
|
|
@ -2029,7 +2046,7 @@ public:
|
||||||
AstSelLoopVars(FileLine* fl, AstNodeExpr* fromp, AstNode* elementsp)
|
AstSelLoopVars(FileLine* fl, AstNodeExpr* fromp, AstNode* elementsp)
|
||||||
: ASTGEN_SUPER_SelLoopVars(fl) {
|
: ASTGEN_SUPER_SelLoopVars(fl) {
|
||||||
this->fromp(fromp);
|
this->fromp(fromp);
|
||||||
this->addElementsp(elementsp);
|
addElementsp(elementsp);
|
||||||
}
|
}
|
||||||
ASTGEN_MEMBERS_AstSelLoopVars;
|
ASTGEN_MEMBERS_AstSelLoopVars;
|
||||||
bool sameNode(const AstNode* /*samep*/) const override { return true; }
|
bool sameNode(const AstNode* /*samep*/) const override { return true; }
|
||||||
|
|
@ -2150,7 +2167,7 @@ class AstSysIgnore final : public AstNodeExpr {
|
||||||
public:
|
public:
|
||||||
AstSysIgnore(FileLine* fl, AstNode* exprsp)
|
AstSysIgnore(FileLine* fl, AstNode* exprsp)
|
||||||
: ASTGEN_SUPER_SysIgnore(fl) {
|
: ASTGEN_SUPER_SysIgnore(fl) {
|
||||||
this->addExprsp(exprsp);
|
addExprsp(exprsp);
|
||||||
}
|
}
|
||||||
ASTGEN_MEMBERS_AstSysIgnore;
|
ASTGEN_MEMBERS_AstSysIgnore;
|
||||||
string verilogKwd() const override { return "$ignored"; }
|
string verilogKwd() const override { return "$ignored"; }
|
||||||
|
|
@ -2261,7 +2278,7 @@ class AstUCFunc final : public AstNodeExpr {
|
||||||
public:
|
public:
|
||||||
AstUCFunc(FileLine* fl, AstNode* exprsp)
|
AstUCFunc(FileLine* fl, AstNode* exprsp)
|
||||||
: ASTGEN_SUPER_UCFunc(fl) {
|
: ASTGEN_SUPER_UCFunc(fl) {
|
||||||
this->addExprsp(exprsp);
|
addExprsp(exprsp);
|
||||||
}
|
}
|
||||||
ASTGEN_MEMBERS_AstUCFunc;
|
ASTGEN_MEMBERS_AstUCFunc;
|
||||||
bool cleanOut() const override { return false; }
|
bool cleanOut() const override { return false; }
|
||||||
|
|
@ -2343,7 +2360,7 @@ public:
|
||||||
: ASTGEN_SUPER_With(fl) {
|
: ASTGEN_SUPER_With(fl) {
|
||||||
this->indexArgRefp(indexArgRefp);
|
this->indexArgRefp(indexArgRefp);
|
||||||
this->valueArgRefp(valueArgRefp);
|
this->valueArgRefp(valueArgRefp);
|
||||||
this->addExprp(exprp);
|
addExprp(exprp);
|
||||||
}
|
}
|
||||||
ASTGEN_MEMBERS_AstWith;
|
ASTGEN_MEMBERS_AstWith;
|
||||||
bool sameNode(const AstNode* /*samep*/) const override { return true; }
|
bool sameNode(const AstNode* /*samep*/) const override { return true; }
|
||||||
|
|
@ -2368,7 +2385,7 @@ public:
|
||||||
AstWithParse(FileLine* fl, AstNodeExpr* funcrefp, AstNode* exprsp)
|
AstWithParse(FileLine* fl, AstNodeExpr* funcrefp, AstNode* exprsp)
|
||||||
: ASTGEN_SUPER_WithParse(fl) {
|
: ASTGEN_SUPER_WithParse(fl) {
|
||||||
this->funcrefp(funcrefp);
|
this->funcrefp(funcrefp);
|
||||||
this->addExprsp(exprsp);
|
addExprsp(exprsp);
|
||||||
}
|
}
|
||||||
ASTGEN_MEMBERS_AstWithParse;
|
ASTGEN_MEMBERS_AstWithParse;
|
||||||
bool sameNode(const AstNode* /*samep*/) const override { return true; }
|
bool sameNode(const AstNode* /*samep*/) const override { return true; }
|
||||||
|
|
@ -4405,12 +4422,15 @@ public:
|
||||||
class AstNew final : public AstNodeFTaskRef {
|
class AstNew final : public AstNodeFTaskRef {
|
||||||
// New as constructor
|
// New as constructor
|
||||||
// Don't need the class we are extracting from, as the "fromp()"'s datatype can get us to it
|
// 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:
|
public:
|
||||||
AstNew(FileLine* fl, AstNodeExpr* pinsp)
|
AstNew(FileLine* fl, AstNodeExpr* pinsp)
|
||||||
: ASTGEN_SUPER_New(fl, "new", pinsp) {}
|
: ASTGEN_SUPER_New(fl, "new", pinsp) {}
|
||||||
ASTGEN_MEMBERS_AstNew;
|
ASTGEN_MEMBERS_AstNew;
|
||||||
bool sameNode(const AstNode* /*samep*/) const override { return true; }
|
bool sameNode(const AstNode* /*samep*/) const override { return true; }
|
||||||
int instrCount() const override { return widthInstrs(); }
|
int instrCount() const override { return widthInstrs(); }
|
||||||
|
bool isImplicit() const { return m_isImplicit; }
|
||||||
|
void isImplicit(bool flag) { m_isImplicit = flag; }
|
||||||
};
|
};
|
||||||
class AstTaskRef final : public AstNodeFTaskRef {
|
class AstTaskRef final : public AstNodeFTaskRef {
|
||||||
// A reference to a task
|
// A reference to a task
|
||||||
|
|
@ -5740,6 +5760,7 @@ class AstVarXRef final : public AstNodeVarRef {
|
||||||
string m_name;
|
string m_name;
|
||||||
string m_dotted; // Dotted part of scope the name()'ed reference is under or ""
|
string m_dotted; // Dotted part of scope the name()'ed reference is under or ""
|
||||||
string m_inlinedDots; // Dotted hierarchy flattened out
|
string m_inlinedDots; // Dotted hierarchy flattened out
|
||||||
|
bool m_containsGenBlock = false; // Contains gen block reference
|
||||||
public:
|
public:
|
||||||
AstVarXRef(FileLine* fl, const string& name, const string& dotted, const VAccess& access)
|
AstVarXRef(FileLine* fl, const string& name, const string& dotted, const VAccess& access)
|
||||||
: ASTGEN_SUPER_VarXRef(fl, nullptr, access)
|
: ASTGEN_SUPER_VarXRef(fl, nullptr, access)
|
||||||
|
|
@ -5755,6 +5776,8 @@ public:
|
||||||
void dotted(const string& dotted) { m_dotted = dotted; }
|
void dotted(const string& dotted) { m_dotted = dotted; }
|
||||||
string inlinedDots() const { return m_inlinedDots; }
|
string inlinedDots() const { return m_inlinedDots; }
|
||||||
void inlinedDots(const string& flag) { m_inlinedDots = flag; }
|
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 emitVerilog() override { V3ERROR_NA_RETURN(""); }
|
||||||
string emitC() override { V3ERROR_NA_RETURN(""); }
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
||||||
bool cleanOut() const override { return true; }
|
bool cleanOut() const override { return true; }
|
||||||
|
|
|
||||||
|
|
@ -388,7 +388,7 @@ protected:
|
||||||
AstNodeCase(VNType t, FileLine* fl, AstNodeExpr* exprp, AstCaseItem* itemsp)
|
AstNodeCase(VNType t, FileLine* fl, AstNodeExpr* exprp, AstCaseItem* itemsp)
|
||||||
: AstNodeStmt{t, fl} {
|
: AstNodeStmt{t, fl} {
|
||||||
this->exprp(exprp);
|
this->exprp(exprp);
|
||||||
this->addItemsp(itemsp);
|
addItemsp(itemsp);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
@ -414,7 +414,7 @@ public:
|
||||||
, m_type{type}
|
, m_type{type}
|
||||||
, m_directive{directive} {
|
, m_directive{directive} {
|
||||||
this->propp(propp);
|
this->propp(propp);
|
||||||
this->addPasssp(passsp);
|
addPasssp(passsp);
|
||||||
}
|
}
|
||||||
ASTGEN_MEMBERS_AstNodeCoverOrAssert;
|
ASTGEN_MEMBERS_AstNodeCoverOrAssert;
|
||||||
string name() const override VL_MT_STABLE { return m_name; } // * = Var name
|
string name() const override VL_MT_STABLE { return m_name; } // * = Var name
|
||||||
|
|
@ -440,10 +440,10 @@ protected:
|
||||||
AstNodeFor(VNType t, FileLine* fl, AstNode* initsp, AstNodeExpr* condp, AstNode* incsp,
|
AstNodeFor(VNType t, FileLine* fl, AstNode* initsp, AstNodeExpr* condp, AstNode* incsp,
|
||||||
AstNode* stmtsp)
|
AstNode* stmtsp)
|
||||||
: AstNodeStmt{t, fl} {
|
: AstNodeStmt{t, fl} {
|
||||||
this->addInitsp(initsp);
|
addInitsp(initsp);
|
||||||
this->condp(condp);
|
this->condp(condp);
|
||||||
this->addIncsp(incsp);
|
addIncsp(incsp);
|
||||||
this->addStmtsp(stmtsp);
|
addStmtsp(stmtsp);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
@ -459,7 +459,7 @@ public:
|
||||||
AstNodeForeach(VNType t, FileLine* fl, AstNode* arrayp, AstNode* stmtsp)
|
AstNodeForeach(VNType t, FileLine* fl, AstNode* arrayp, AstNode* stmtsp)
|
||||||
: AstNodeStmt(t, fl) {
|
: AstNodeStmt(t, fl) {
|
||||||
this->arrayp(arrayp);
|
this->arrayp(arrayp);
|
||||||
this->addStmtsp(stmtsp);
|
addStmtsp(stmtsp);
|
||||||
}
|
}
|
||||||
ASTGEN_MEMBERS_AstNodeForeach;
|
ASTGEN_MEMBERS_AstNodeForeach;
|
||||||
bool isGateOptimizable() const override { return false; }
|
bool isGateOptimizable() const override { return false; }
|
||||||
|
|
@ -477,8 +477,8 @@ protected:
|
||||||
AstNodeIf(VNType t, FileLine* fl, AstNodeExpr* condp, AstNode* thensp, AstNode* elsesp)
|
AstNodeIf(VNType t, FileLine* fl, AstNodeExpr* condp, AstNode* thensp, AstNode* elsesp)
|
||||||
: AstNodeStmt{t, fl} {
|
: AstNodeStmt{t, fl} {
|
||||||
this->condp(condp);
|
this->condp(condp);
|
||||||
this->addThensp(thensp);
|
addThensp(thensp);
|
||||||
this->addElsesp(elsesp);
|
addElsesp(elsesp);
|
||||||
isBoundsCheck(false);
|
isBoundsCheck(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -598,7 +598,7 @@ public:
|
||||||
: ASTGEN_SUPER_Bind(fl)
|
: ASTGEN_SUPER_Bind(fl)
|
||||||
, m_name{name} {
|
, m_name{name} {
|
||||||
UASSERT_OBJ(VN_IS(cellsp, Cell), cellsp, "Only instances allowed to be bound");
|
UASSERT_OBJ(VN_IS(cellsp, Cell), cellsp, "Only instances allowed to be bound");
|
||||||
this->addCellsp(cellsp);
|
addCellsp(cellsp);
|
||||||
}
|
}
|
||||||
ASTGEN_MEMBERS_AstBind;
|
ASTGEN_MEMBERS_AstBind;
|
||||||
// ACCESSORS
|
// ACCESSORS
|
||||||
|
|
@ -631,8 +631,10 @@ class AstCFunc final : public AstNode {
|
||||||
bool m_isConstructor : 1; // Is C class constructor
|
bool m_isConstructor : 1; // Is C class constructor
|
||||||
bool m_isDestructor : 1; // Is C class destructor
|
bool m_isDestructor : 1; // Is C class destructor
|
||||||
bool m_isMethod : 1; // Is inside a class definition
|
bool m_isMethod : 1; // Is inside a class definition
|
||||||
bool m_isLoose : 1; // Semantically this is a method, but is implemented as a function
|
bool m_isLoose : 1; // Semantically this is a method, but is implemented as a function with
|
||||||
// with an explicitly passed 'self' pointer as the first argument
|
// 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_isInline : 1; // Inline function
|
||||||
bool m_isVirtual : 1; // Virtual function
|
bool m_isVirtual : 1; // Virtual function
|
||||||
bool m_entryPoint : 1; // User may call into this top level function
|
bool m_entryPoint : 1; // User may call into this top level function
|
||||||
|
|
@ -762,7 +764,7 @@ class AstCLocalScope final : public AstNode {
|
||||||
public:
|
public:
|
||||||
AstCLocalScope(FileLine* fl, AstNode* stmtsp)
|
AstCLocalScope(FileLine* fl, AstNode* stmtsp)
|
||||||
: ASTGEN_SUPER_CLocalScope(fl) {
|
: ASTGEN_SUPER_CLocalScope(fl) {
|
||||||
this->addStmtsp(stmtsp);
|
addStmtsp(stmtsp);
|
||||||
}
|
}
|
||||||
ASTGEN_MEMBERS_AstCLocalScope;
|
ASTGEN_MEMBERS_AstCLocalScope;
|
||||||
};
|
};
|
||||||
|
|
@ -790,8 +792,8 @@ class AstCaseItem final : public AstNode {
|
||||||
public:
|
public:
|
||||||
AstCaseItem(FileLine* fl, AstNodeExpr* condsp, AstNode* stmtsp)
|
AstCaseItem(FileLine* fl, AstNodeExpr* condsp, AstNode* stmtsp)
|
||||||
: ASTGEN_SUPER_CaseItem(fl) {
|
: ASTGEN_SUPER_CaseItem(fl) {
|
||||||
this->addCondsp(condsp);
|
addCondsp(condsp);
|
||||||
this->addStmtsp(stmtsp);
|
addStmtsp(stmtsp);
|
||||||
}
|
}
|
||||||
ASTGEN_MEMBERS_AstCaseItem;
|
ASTGEN_MEMBERS_AstCaseItem;
|
||||||
int instrCount() const override { return widthInstrs() + INSTR_COUNT_BRANCH; }
|
int instrCount() const override { return widthInstrs() + INSTR_COUNT_BRANCH; }
|
||||||
|
|
@ -824,8 +826,8 @@ public:
|
||||||
, m_hasIfaceVar{false}
|
, m_hasIfaceVar{false}
|
||||||
, m_recursive{false}
|
, m_recursive{false}
|
||||||
, m_trace{true} {
|
, m_trace{true} {
|
||||||
this->addPinsp(pinsp);
|
addPinsp(pinsp);
|
||||||
this->addParamsp(paramsp);
|
addParamsp(paramsp);
|
||||||
this->rangep(rangep);
|
this->rangep(rangep);
|
||||||
}
|
}
|
||||||
ASTGEN_MEMBERS_AstCell;
|
ASTGEN_MEMBERS_AstCell;
|
||||||
|
|
@ -915,6 +917,7 @@ class AstClassExtends final : public AstNode {
|
||||||
// during early parse, then moves to dtype
|
// during early parse, then moves to dtype
|
||||||
// @astgen op1 := childDTypep : Optional[AstNodeDType]
|
// @astgen op1 := childDTypep : Optional[AstNodeDType]
|
||||||
// @astgen op2 := classOrPkgsp : Optional[AstNode]
|
// @astgen op2 := classOrPkgsp : Optional[AstNode]
|
||||||
|
// @astgen op3 := argsp : List[AstNodeExpr]
|
||||||
const bool m_isImplements = false; // class implements
|
const bool m_isImplements = false; // class implements
|
||||||
bool m_parameterized = false; // has parameters in its statement
|
bool m_parameterized = false; // has parameters in its statement
|
||||||
|
|
||||||
|
|
@ -1037,7 +1040,7 @@ public:
|
||||||
AstConstraint(FileLine* fl, const string& name, AstNode* itemsp)
|
AstConstraint(FileLine* fl, const string& name, AstNode* itemsp)
|
||||||
: ASTGEN_SUPER_Constraint(fl)
|
: ASTGEN_SUPER_Constraint(fl)
|
||||||
, m_name(name) {
|
, m_name(name) {
|
||||||
this->addItemsp(itemsp);
|
addItemsp(itemsp);
|
||||||
}
|
}
|
||||||
ASTGEN_MEMBERS_AstConstraint;
|
ASTGEN_MEMBERS_AstConstraint;
|
||||||
void dump(std::ostream& str) const override;
|
void dump(std::ostream& str) const override;
|
||||||
|
|
@ -1067,8 +1070,8 @@ class AstConstraintBefore final : public AstNode {
|
||||||
public:
|
public:
|
||||||
AstConstraintBefore(FileLine* fl, AstNodeExpr* lhssp, AstNodeExpr* rhssp)
|
AstConstraintBefore(FileLine* fl, AstNodeExpr* lhssp, AstNodeExpr* rhssp)
|
||||||
: ASTGEN_SUPER_ConstraintBefore(fl) {
|
: ASTGEN_SUPER_ConstraintBefore(fl) {
|
||||||
this->addLhssp(lhssp);
|
addLhssp(lhssp);
|
||||||
this->addRhssp(rhssp);
|
addRhssp(rhssp);
|
||||||
}
|
}
|
||||||
ASTGEN_MEMBERS_AstConstraintBefore;
|
ASTGEN_MEMBERS_AstConstraintBefore;
|
||||||
bool isGateOptimizable() const override { return false; }
|
bool isGateOptimizable() const override { return false; }
|
||||||
|
|
@ -1187,7 +1190,7 @@ class AstImplicit final : public AstNode {
|
||||||
public:
|
public:
|
||||||
AstImplicit(FileLine* fl, AstNode* exprsp)
|
AstImplicit(FileLine* fl, AstNode* exprsp)
|
||||||
: ASTGEN_SUPER_Implicit(fl) {
|
: ASTGEN_SUPER_Implicit(fl) {
|
||||||
this->addExprsp(exprsp);
|
addExprsp(exprsp);
|
||||||
}
|
}
|
||||||
ASTGEN_MEMBERS_AstImplicit;
|
ASTGEN_MEMBERS_AstImplicit;
|
||||||
};
|
};
|
||||||
|
|
@ -1250,7 +1253,7 @@ public:
|
||||||
AstModport(FileLine* fl, const string& name, AstNode* varsp)
|
AstModport(FileLine* fl, const string& name, AstNode* varsp)
|
||||||
: ASTGEN_SUPER_Modport(fl)
|
: ASTGEN_SUPER_Modport(fl)
|
||||||
, m_name{name} {
|
, m_name{name} {
|
||||||
this->addVarsp(varsp);
|
addVarsp(varsp);
|
||||||
}
|
}
|
||||||
string verilogKwd() const override { return "modport"; }
|
string verilogKwd() const override { return "modport"; }
|
||||||
string name() const override VL_MT_STABLE { return m_name; }
|
string name() const override VL_MT_STABLE { return m_name; }
|
||||||
|
|
@ -1645,7 +1648,7 @@ class AstSenTree final : public AstNode {
|
||||||
public:
|
public:
|
||||||
AstSenTree(FileLine* fl, AstSenItem* sensesp)
|
AstSenTree(FileLine* fl, AstSenItem* sensesp)
|
||||||
: ASTGEN_SUPER_SenTree(fl) {
|
: ASTGEN_SUPER_SenTree(fl) {
|
||||||
this->addSensesp(sensesp);
|
addSensesp(sensesp);
|
||||||
}
|
}
|
||||||
ASTGEN_MEMBERS_AstSenTree;
|
ASTGEN_MEMBERS_AstSenTree;
|
||||||
void dump(std::ostream& str) const override;
|
void dump(std::ostream& str) const override;
|
||||||
|
|
@ -1798,18 +1801,47 @@ public:
|
||||||
AstUdpTable(FileLine* fl, AstUdpTableLine* linesp)
|
AstUdpTable(FileLine* fl, AstUdpTableLine* linesp)
|
||||||
: ASTGEN_SUPER_UdpTable(fl) {
|
: ASTGEN_SUPER_UdpTable(fl) {
|
||||||
this->addLinesp(linesp);
|
this->addLinesp(linesp);
|
||||||
|
if (!v3Global.hasTable()) v3Global.setHasTable();
|
||||||
}
|
}
|
||||||
ASTGEN_MEMBERS_AstUdpTable;
|
ASTGEN_MEMBERS_AstUdpTable;
|
||||||
};
|
};
|
||||||
class AstUdpTableLine final : public AstNode {
|
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:
|
public:
|
||||||
AstUdpTableLine(FileLine* fl, const string& text)
|
class UdpCombo {};
|
||||||
|
AstUdpTableLine(UdpCombo, FileLine* fl, AstUdpTableLineVal* iFieldsp,
|
||||||
|
AstUdpTableLineVal* oFieldsp)
|
||||||
: ASTGEN_SUPER_UdpTableLine(fl)
|
: 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;
|
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; }
|
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; }
|
string text() const VL_MT_SAFE { return m_text; }
|
||||||
};
|
};
|
||||||
class AstVar final : public AstNode {
|
class AstVar final : public AstNode {
|
||||||
|
|
@ -1878,6 +1910,7 @@ class AstVar final : public AstNode {
|
||||||
bool m_isWrittenByDpi : 1; // This variable can be written by a DPI Export
|
bool m_isWrittenByDpi : 1; // This variable can be written by a DPI Export
|
||||||
bool m_isWrittenBySuspendable : 1; // This variable can be written by a suspendable process
|
bool m_isWrittenBySuspendable : 1; // This variable can be written by a suspendable process
|
||||||
bool m_ignorePostWrite : 1; // Ignore writes in 'Post' blocks during ordering
|
bool m_ignorePostWrite : 1; // Ignore writes in 'Post' blocks during ordering
|
||||||
|
bool m_ignoreSchedWrite : 1; // Ignore writes in scheduling (for coverage increments)
|
||||||
|
|
||||||
void init() {
|
void init() {
|
||||||
m_ansi = false;
|
m_ansi = false;
|
||||||
|
|
@ -1923,6 +1956,7 @@ class AstVar final : public AstNode {
|
||||||
m_isWrittenByDpi = false;
|
m_isWrittenByDpi = false;
|
||||||
m_isWrittenBySuspendable = false;
|
m_isWrittenBySuspendable = false;
|
||||||
m_ignorePostWrite = false;
|
m_ignorePostWrite = false;
|
||||||
|
m_ignoreSchedWrite = false;
|
||||||
m_attrClocker = VVarAttrClocker::CLOCKER_UNKNOWN;
|
m_attrClocker = VVarAttrClocker::CLOCKER_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2080,6 +2114,8 @@ public:
|
||||||
void setWrittenBySuspendable() { m_isWrittenBySuspendable = true; }
|
void setWrittenBySuspendable() { m_isWrittenBySuspendable = true; }
|
||||||
bool ignorePostWrite() const { return m_ignorePostWrite; }
|
bool ignorePostWrite() const { return m_ignorePostWrite; }
|
||||||
void setIgnorePostWrite() { m_ignorePostWrite = true; }
|
void setIgnorePostWrite() { m_ignorePostWrite = true; }
|
||||||
|
bool ignoreSchedWrite() const { return m_ignoreSchedWrite; }
|
||||||
|
void setIgnoreSchedWrite() { m_ignoreSchedWrite = true; }
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
void name(const string& name) override { m_name = name; }
|
void name(const string& name) override { m_name = name; }
|
||||||
|
|
@ -2165,6 +2201,8 @@ public:
|
||||||
string verilogKwd() const override;
|
string verilogKwd() const override;
|
||||||
void lifetime(const VLifetime& flag) { m_lifetime = flag; }
|
void lifetime(const VLifetime& flag) { m_lifetime = flag; }
|
||||||
VLifetime lifetime() const { return m_lifetime; }
|
VLifetime lifetime() const { return m_lifetime; }
|
||||||
|
void pinNum(int id) { m_pinNum = id; }
|
||||||
|
int pinNum() const { return m_pinNum; }
|
||||||
void propagateAttrFrom(const AstVar* fromp) {
|
void propagateAttrFrom(const AstVar* fromp) {
|
||||||
// This is getting connected to fromp; keep attributes
|
// This is getting connected to fromp; keep attributes
|
||||||
// Note the method below too
|
// Note the method below too
|
||||||
|
|
@ -2197,9 +2235,11 @@ public:
|
||||||
m_direction = VDirection::NONE;
|
m_direction = VDirection::NONE;
|
||||||
m_name = name;
|
m_name = name;
|
||||||
}
|
}
|
||||||
|
bool needsCReset() const {
|
||||||
|
return !isIfaceParent() && !isIfaceRef() && !noReset() && !isParam() && !isStatementTemp()
|
||||||
|
&& !(basicp() && (basicp()->isEvent() || basicp()->isTriggerVec()));
|
||||||
|
}
|
||||||
static AstVar* scVarRecurse(AstNode* nodep);
|
static AstVar* scVarRecurse(AstNode* nodep);
|
||||||
void pinNum(int id) { m_pinNum = id; }
|
|
||||||
int pinNum() const { return m_pinNum; }
|
|
||||||
};
|
};
|
||||||
class AstVarScope final : public AstNode {
|
class AstVarScope final : public AstNode {
|
||||||
// A particular scoped usage of a variable
|
// A particular scoped usage of a variable
|
||||||
|
|
@ -2302,7 +2342,7 @@ public:
|
||||||
class AstLet final : public AstNodeFTask {
|
class AstLet final : public AstNodeFTask {
|
||||||
// Verilog "let" statement
|
// Verilog "let" statement
|
||||||
// Parents: MODULE
|
// Parents: MODULE
|
||||||
// stmtp is always a StmtExpr as Let always returns AstNodeExpr
|
// stmtp list first item is returned StmtExpr, as Let always returns AstNodeExpr
|
||||||
public:
|
public:
|
||||||
AstLet(FileLine* fl, const string& name)
|
AstLet(FileLine* fl, const string& name)
|
||||||
: ASTGEN_SUPER_Let(fl, name, nullptr) {}
|
: ASTGEN_SUPER_Let(fl, name, nullptr) {}
|
||||||
|
|
@ -2382,7 +2422,6 @@ class AstClass final : public AstNodeModule {
|
||||||
bool m_extended = false; // Is extension or extended by other classes
|
bool m_extended = false; // Is extension or extended by other classes
|
||||||
bool m_interfaceClass = false; // Interface class
|
bool m_interfaceClass = false; // Interface class
|
||||||
bool m_needRNG = false; // Need RNG, uses srandom/randomize
|
bool m_needRNG = false; // Need RNG, uses srandom/randomize
|
||||||
bool m_parameterized = false; // Parameterized class
|
|
||||||
bool m_useVirtualPublic = false; // Subclasses need virtual public as uses interface class
|
bool m_useVirtualPublic = false; // Subclasses need virtual public as uses interface class
|
||||||
bool m_virtual = false; // Virtual class
|
bool m_virtual = false; // Virtual class
|
||||||
|
|
||||||
|
|
@ -2403,8 +2442,6 @@ public:
|
||||||
void isExtended(bool flag) { m_extended = flag; }
|
void isExtended(bool flag) { m_extended = flag; }
|
||||||
bool isInterfaceClass() const { return m_interfaceClass; }
|
bool isInterfaceClass() const { return m_interfaceClass; }
|
||||||
void isInterfaceClass(bool flag) { m_interfaceClass = flag; }
|
void isInterfaceClass(bool flag) { m_interfaceClass = flag; }
|
||||||
bool isParameterized() const { return m_parameterized; }
|
|
||||||
void isParameterized(bool flag) { m_parameterized = flag; }
|
|
||||||
bool isVirtual() const { return m_virtual; }
|
bool isVirtual() const { return m_virtual; }
|
||||||
void isVirtual(bool flag) { m_virtual = flag; }
|
void isVirtual(bool flag) { m_virtual = flag; }
|
||||||
bool needRNG() const { return m_needRNG; }
|
bool needRNG() const { return m_needRNG; }
|
||||||
|
|
@ -2484,14 +2521,28 @@ public:
|
||||||
};
|
};
|
||||||
class AstModule final : public AstNodeModule {
|
class AstModule final : public AstNodeModule {
|
||||||
// A module declaration
|
// 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:
|
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)
|
: 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;
|
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 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 {
|
class AstNotFoundModule final : public AstNodeModule {
|
||||||
// A missing module declaration
|
// A missing module declaration
|
||||||
|
|
@ -2740,15 +2791,22 @@ public:
|
||||||
class AstCReset final : public AstNodeStmt {
|
class AstCReset final : public AstNodeStmt {
|
||||||
// Reset variable at startup
|
// Reset variable at startup
|
||||||
// @astgen op1 := varrefp : AstVarRef
|
// @astgen op1 := varrefp : AstVarRef
|
||||||
|
const bool m_constructing; // Previously cleared by constructor
|
||||||
public:
|
public:
|
||||||
AstCReset(FileLine* fl, AstVarRef* varrefp)
|
AstCReset(FileLine* fl, AstVarRef* varrefp, bool constructing)
|
||||||
: ASTGEN_SUPER_CReset(fl) {
|
: ASTGEN_SUPER_CReset(fl)
|
||||||
|
, m_constructing(constructing) {
|
||||||
this->varrefp(varrefp);
|
this->varrefp(varrefp);
|
||||||
}
|
}
|
||||||
ASTGEN_MEMBERS_AstCReset;
|
ASTGEN_MEMBERS_AstCReset;
|
||||||
|
void dump(std::ostream& str) const override;
|
||||||
|
void dumpJson(std::ostream& str) const override;
|
||||||
bool isGateOptimizable() const override { return false; }
|
bool isGateOptimizable() const override { return false; }
|
||||||
bool isPredictOptimizable() const override { return false; }
|
bool isPredictOptimizable() const override { return false; }
|
||||||
bool sameNode(const AstNode* /*samep*/) const override { return true; }
|
bool sameNode(const AstNode* samep) const override {
|
||||||
|
return constructing() == VN_DBG_AS(samep, CReset)->constructing();
|
||||||
|
}
|
||||||
|
bool constructing() const { return m_constructing; }
|
||||||
};
|
};
|
||||||
class AstCReturn final : public AstNodeStmt {
|
class AstCReturn final : public AstNodeStmt {
|
||||||
// C++ return from a function
|
// C++ return from a function
|
||||||
|
|
@ -2768,7 +2826,7 @@ class AstCStmt final : public AstNodeStmt {
|
||||||
public:
|
public:
|
||||||
AstCStmt(FileLine* fl, AstNode* exprsp)
|
AstCStmt(FileLine* fl, AstNode* exprsp)
|
||||||
: ASTGEN_SUPER_CStmt(fl) {
|
: ASTGEN_SUPER_CStmt(fl) {
|
||||||
this->addExprsp(exprsp);
|
addExprsp(exprsp);
|
||||||
}
|
}
|
||||||
inline AstCStmt(FileLine* fl, const string& textStmt);
|
inline AstCStmt(FileLine* fl, const string& textStmt);
|
||||||
ASTGEN_MEMBERS_AstCStmt;
|
ASTGEN_MEMBERS_AstCStmt;
|
||||||
|
|
@ -2817,7 +2875,7 @@ class AstConstraintUnique final : public AstNodeStmt {
|
||||||
public:
|
public:
|
||||||
AstConstraintUnique(FileLine* fl, AstNode* rangesp)
|
AstConstraintUnique(FileLine* fl, AstNode* rangesp)
|
||||||
: ASTGEN_SUPER_ConstraintUnique(fl) {
|
: ASTGEN_SUPER_ConstraintUnique(fl) {
|
||||||
this->addRangesp(rangesp);
|
addRangesp(rangesp);
|
||||||
}
|
}
|
||||||
ASTGEN_MEMBERS_AstConstraintUnique;
|
ASTGEN_MEMBERS_AstConstraintUnique;
|
||||||
bool isGateOptimizable() const override { return false; }
|
bool isGateOptimizable() const override { return false; }
|
||||||
|
|
@ -2983,14 +3041,14 @@ public:
|
||||||
AstNodeExpr* exprsp, char missingArgChar = 'd')
|
AstNodeExpr* exprsp, char missingArgChar = 'd')
|
||||||
: ASTGEN_SUPER_Display(fl)
|
: ASTGEN_SUPER_Display(fl)
|
||||||
, m_displayType{dispType} {
|
, m_displayType{dispType} {
|
||||||
this->fmtp(new AstSFormatF{fl, text, true, exprsp, missingArgChar});
|
fmtp(new AstSFormatF{fl, text, true, exprsp, missingArgChar});
|
||||||
this->filep(filep);
|
this->filep(filep);
|
||||||
}
|
}
|
||||||
AstDisplay(FileLine* fl, VDisplayType dispType, AstNodeExpr* filep, AstNodeExpr* exprsp,
|
AstDisplay(FileLine* fl, VDisplayType dispType, AstNodeExpr* filep, AstNodeExpr* exprsp,
|
||||||
char missingArgChar = 'd')
|
char missingArgChar = 'd')
|
||||||
: ASTGEN_SUPER_Display(fl)
|
: ASTGEN_SUPER_Display(fl)
|
||||||
, m_displayType{dispType} {
|
, m_displayType{dispType} {
|
||||||
this->fmtp(new AstSFormatF{fl, AstSFormatF::NoFormat{}, exprsp, missingArgChar});
|
fmtp(new AstSFormatF{fl, AstSFormatF::NoFormat{}, exprsp, missingArgChar});
|
||||||
this->filep(filep);
|
this->filep(filep);
|
||||||
}
|
}
|
||||||
ASTGEN_MEMBERS_AstDisplay;
|
ASTGEN_MEMBERS_AstDisplay;
|
||||||
|
|
@ -3063,7 +3121,7 @@ public:
|
||||||
AstEventControl(FileLine* fl, AstSenTree* sensesp, AstNode* stmtsp)
|
AstEventControl(FileLine* fl, AstSenTree* sensesp, AstNode* stmtsp)
|
||||||
: ASTGEN_SUPER_EventControl(fl) {
|
: ASTGEN_SUPER_EventControl(fl) {
|
||||||
this->sensesp(sensesp);
|
this->sensesp(sensesp);
|
||||||
this->addStmtsp(stmtsp);
|
addStmtsp(stmtsp);
|
||||||
}
|
}
|
||||||
ASTGEN_MEMBERS_AstEventControl;
|
ASTGEN_MEMBERS_AstEventControl;
|
||||||
string verilogKwd() const override { return "@(%l) %r"; }
|
string verilogKwd() const override { return "@(%l) %r"; }
|
||||||
|
|
@ -3144,7 +3202,7 @@ public:
|
||||||
// After construction must call ->labelp to associate with appropriate label
|
// After construction must call ->labelp to associate with appropriate label
|
||||||
AstJumpBlock(FileLine* fl, AstNode* stmtsp)
|
AstJumpBlock(FileLine* fl, AstNode* stmtsp)
|
||||||
: ASTGEN_SUPER_JumpBlock(fl) {
|
: ASTGEN_SUPER_JumpBlock(fl) {
|
||||||
this->addStmtsp(stmtsp);
|
addStmtsp(stmtsp);
|
||||||
}
|
}
|
||||||
ASTGEN_MEMBERS_AstJumpBlock;
|
ASTGEN_MEMBERS_AstJumpBlock;
|
||||||
const char* broken() const override;
|
const char* broken() const override;
|
||||||
|
|
@ -3276,7 +3334,7 @@ public:
|
||||||
AstRepeat(FileLine* fl, AstNodeExpr* countp, AstNode* stmtsp)
|
AstRepeat(FileLine* fl, AstNodeExpr* countp, AstNode* stmtsp)
|
||||||
: ASTGEN_SUPER_Repeat(fl) {
|
: ASTGEN_SUPER_Repeat(fl) {
|
||||||
this->countp(countp);
|
this->countp(countp);
|
||||||
this->addStmtsp(stmtsp);
|
addStmtsp(stmtsp);
|
||||||
}
|
}
|
||||||
ASTGEN_MEMBERS_AstRepeat;
|
ASTGEN_MEMBERS_AstRepeat;
|
||||||
bool isGateOptimizable() const override { return false; } // Not relevant - converted to FOR
|
bool isGateOptimizable() const override { return false; } // Not relevant - converted to FOR
|
||||||
|
|
@ -3305,12 +3363,12 @@ public:
|
||||||
AstSFormat(FileLine* fl, AstNodeExpr* lhsp, const string& text, AstNodeExpr* exprsp,
|
AstSFormat(FileLine* fl, AstNodeExpr* lhsp, const string& text, AstNodeExpr* exprsp,
|
||||||
char missingArgChar = 'd')
|
char missingArgChar = 'd')
|
||||||
: ASTGEN_SUPER_SFormat(fl) {
|
: ASTGEN_SUPER_SFormat(fl) {
|
||||||
this->fmtp(new AstSFormatF{fl, text, true, exprsp, missingArgChar});
|
fmtp(new AstSFormatF{fl, text, true, exprsp, missingArgChar});
|
||||||
this->lhsp(lhsp);
|
this->lhsp(lhsp);
|
||||||
}
|
}
|
||||||
AstSFormat(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* exprsp, char missingArgChar = 'd')
|
AstSFormat(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* exprsp, char missingArgChar = 'd')
|
||||||
: ASTGEN_SUPER_SFormat(fl) {
|
: ASTGEN_SUPER_SFormat(fl) {
|
||||||
this->fmtp(new AstSFormatF{fl, AstSFormatF::NoFormat{}, exprsp, missingArgChar});
|
fmtp(new AstSFormatF{fl, AstSFormatF::NoFormat{}, exprsp, missingArgChar});
|
||||||
this->lhsp(lhsp);
|
this->lhsp(lhsp);
|
||||||
}
|
}
|
||||||
ASTGEN_MEMBERS_AstSFormat;
|
ASTGEN_MEMBERS_AstSFormat;
|
||||||
|
|
@ -3327,6 +3385,24 @@ public:
|
||||||
int instrCount() const override { return INSTR_COUNT_PLI; }
|
int instrCount() const override { return INSTR_COUNT_PLI; }
|
||||||
bool sameNode(const AstNode* /*samep*/) const override { return true; }
|
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 {
|
class AstStackTraceT final : public AstNodeStmt {
|
||||||
// $stacktrace used as task
|
// $stacktrace used as task
|
||||||
public:
|
public:
|
||||||
|
|
@ -3540,7 +3616,7 @@ class AstUCStmt final : public AstNodeStmt {
|
||||||
public:
|
public:
|
||||||
AstUCStmt(FileLine* fl, AstNode* exprsp)
|
AstUCStmt(FileLine* fl, AstNode* exprsp)
|
||||||
: ASTGEN_SUPER_UCStmt(fl) {
|
: ASTGEN_SUPER_UCStmt(fl) {
|
||||||
this->addExprsp(exprsp);
|
addExprsp(exprsp);
|
||||||
}
|
}
|
||||||
ASTGEN_MEMBERS_AstUCStmt;
|
ASTGEN_MEMBERS_AstUCStmt;
|
||||||
bool isGateOptimizable() const override { return false; }
|
bool isGateOptimizable() const override { return false; }
|
||||||
|
|
@ -3556,7 +3632,7 @@ public:
|
||||||
AstWait(FileLine* fl, AstNodeExpr* condp, AstNode* stmtsp)
|
AstWait(FileLine* fl, AstNodeExpr* condp, AstNode* stmtsp)
|
||||||
: ASTGEN_SUPER_Wait(fl) {
|
: ASTGEN_SUPER_Wait(fl) {
|
||||||
this->condp(condp);
|
this->condp(condp);
|
||||||
this->addStmtsp(stmtsp);
|
addStmtsp(stmtsp);
|
||||||
}
|
}
|
||||||
ASTGEN_MEMBERS_AstWait;
|
ASTGEN_MEMBERS_AstWait;
|
||||||
bool isFirstInMyListOfStatements(AstNode* n) const override { return n == stmtsp(); }
|
bool isFirstInMyListOfStatements(AstNode* n) const override { return n == stmtsp(); }
|
||||||
|
|
@ -3580,8 +3656,8 @@ public:
|
||||||
AstWhile(FileLine* fl, AstNodeExpr* condp, AstNode* stmtsp = nullptr, AstNode* incsp = nullptr)
|
AstWhile(FileLine* fl, AstNodeExpr* condp, AstNode* stmtsp = nullptr, AstNode* incsp = nullptr)
|
||||||
: ASTGEN_SUPER_While(fl) {
|
: ASTGEN_SUPER_While(fl) {
|
||||||
this->condp(condp);
|
this->condp(condp);
|
||||||
this->addStmtsp(stmtsp);
|
addStmtsp(stmtsp);
|
||||||
this->addIncsp(incsp);
|
addIncsp(incsp);
|
||||||
}
|
}
|
||||||
ASTGEN_MEMBERS_AstWhile;
|
ASTGEN_MEMBERS_AstWhile;
|
||||||
void dump(std::ostream& str) const override;
|
void dump(std::ostream& str) const override;
|
||||||
|
|
@ -3756,7 +3832,7 @@ public:
|
||||||
AstAssert(FileLine* fl, AstNode* propp, AstNode* passsp, AstNode* failsp, VAssertType type,
|
AstAssert(FileLine* fl, AstNode* propp, AstNode* passsp, AstNode* failsp, VAssertType type,
|
||||||
VAssertDirectiveType directive, const string& name = "")
|
VAssertDirectiveType directive, const string& name = "")
|
||||||
: ASTGEN_SUPER_Assert(fl, propp, passsp, type, directive, name) {
|
: ASTGEN_SUPER_Assert(fl, propp, passsp, type, directive, name) {
|
||||||
this->addFailsp(failsp);
|
addFailsp(failsp);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
class AstAssertIntrinsic final : public AstNodeCoverOrAssert {
|
class AstAssertIntrinsic final : public AstNodeCoverOrAssert {
|
||||||
|
|
@ -3769,7 +3845,7 @@ public:
|
||||||
// Intrinsic asserts are always enabled thus 'type' field is set to INTERNAL.
|
// Intrinsic asserts are always enabled thus 'type' field is set to INTERNAL.
|
||||||
: ASTGEN_SUPER_AssertIntrinsic(fl, propp, passsp, VAssertType::INTERNAL,
|
: ASTGEN_SUPER_AssertIntrinsic(fl, propp, passsp, VAssertType::INTERNAL,
|
||||||
VAssertDirectiveType::INTRINSIC, name) {
|
VAssertDirectiveType::INTRINSIC, name) {
|
||||||
this->addFailsp(failsp);
|
addFailsp(failsp);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
class AstCover final : public AstNodeCoverOrAssert {
|
class AstCover final : public AstNodeCoverOrAssert {
|
||||||
|
|
@ -3886,6 +3962,14 @@ public:
|
||||||
bool isPure() override { return false; } // SPECIAL: User may order w/other sigs
|
bool isPure() override { return false; } // SPECIAL: User may order w/other sigs
|
||||||
bool isOutputter() override { return true; }
|
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 {
|
class AstScImp final : public AstNodeText {
|
||||||
public:
|
public:
|
||||||
AstScImp(FileLine* fl, const string& textp)
|
AstScImp(FileLine* fl, const string& textp)
|
||||||
|
|
|
||||||
|
|
@ -327,6 +327,15 @@ AstNodeExpr* AstInsideRange::newAndFromInside(AstNodeExpr* exprp, AstNodeExpr* l
|
||||||
return new AstLogAnd{fileline(), ap, bp};
|
return new AstLogAnd{fileline(), ap, bp};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AstCReset::dump(std::ostream& str) const {
|
||||||
|
this->AstNode::dump(str);
|
||||||
|
if (constructing()) str << " [CONS]";
|
||||||
|
}
|
||||||
|
void AstCReset::dumpJson(std::ostream& str) const {
|
||||||
|
dumpJsonBoolFunc(str, constructing);
|
||||||
|
dumpJsonGen(str);
|
||||||
|
}
|
||||||
|
|
||||||
AstVar* AstClocking::ensureEventp(bool childDType) {
|
AstVar* AstClocking::ensureEventp(bool childDType) {
|
||||||
if (!eventp()) {
|
if (!eventp()) {
|
||||||
AstVar* const evp
|
AstVar* const evp
|
||||||
|
|
@ -815,12 +824,12 @@ AstVar* AstVar::scVarRecurse(AstNode* nodep) {
|
||||||
}
|
}
|
||||||
} else if (AstArraySel* const arraySelp = VN_CAST(nodep, ArraySel)) {
|
} else if (AstArraySel* const arraySelp = VN_CAST(nodep, ArraySel)) {
|
||||||
if (AstVar* const p = scVarRecurse(arraySelp->fromp())) return p;
|
if (AstVar* const p = scVarRecurse(arraySelp->fromp())) return p;
|
||||||
if (AstVar* const p = scVarRecurse(arraySelp->bitp())) return p;
|
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
const AstNodeDType* AstNodeDType::skipRefIterp(bool skipConst, bool skipEnum) const VL_MT_STABLE {
|
const AstNodeDType* AstNodeDType::skipRefIterp(bool skipConst, bool skipEnum,
|
||||||
|
bool assertOn) const VL_MT_STABLE {
|
||||||
const AstNodeDType* nodep = this;
|
const AstNodeDType* nodep = this;
|
||||||
while (true) {
|
while (true) {
|
||||||
if (VL_UNLIKELY(VN_IS(nodep, MemberDType) || VN_IS(nodep, ParamTypeDType)
|
if (VL_UNLIKELY(VN_IS(nodep, MemberDType) || VN_IS(nodep, ParamTypeDType)
|
||||||
|
|
@ -831,7 +840,7 @@ const AstNodeDType* AstNodeDType::skipRefIterp(bool skipConst, bool skipEnum) co
|
||||||
nodep = subp;
|
nodep = subp;
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
nodep->v3fatalSrc(nodep->prettyTypeName() << " not linked to type");
|
if (assertOn) nodep->v3fatalSrc(nodep->prettyTypeName() << " not linked to type");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -839,6 +848,15 @@ const AstNodeDType* AstNodeDType::skipRefIterp(bool skipConst, bool skipEnum) co
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AstNodeDType::similarDType(const AstNodeDType* samep) const {
|
||||||
|
const AstNodeDType* nodep = this;
|
||||||
|
nodep = nodep->skipRefToNonRefp();
|
||||||
|
samep = samep->skipRefToNonRefp();
|
||||||
|
if (nodep == samep) return true;
|
||||||
|
if (nodep->type() != samep->type()) return false;
|
||||||
|
return nodep->similarDTypeNode(samep);
|
||||||
|
}
|
||||||
|
|
||||||
bool AstNodeDType::isFourstate() const { return basicp() && basicp()->isFourstate(); }
|
bool AstNodeDType::isFourstate() const { return basicp() && basicp()->isFourstate(); }
|
||||||
|
|
||||||
class AstNodeDType::CTypeRecursed final {
|
class AstNodeDType::CTypeRecursed final {
|
||||||
|
|
@ -998,11 +1016,11 @@ AstNodeDType::CTypeRecursed AstNodeDType::cTypeRecurse(bool compound, bool packe
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t AstNodeDType::arrayUnpackedElements() {
|
uint32_t AstNodeDType::arrayUnpackedElements() const {
|
||||||
uint32_t entries = 1;
|
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
|
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();
|
entries *= adtypep->elementsConst();
|
||||||
dtypep = adtypep->subDTypep();
|
dtypep = adtypep->subDTypep();
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1986,8 +2004,8 @@ AstMemberSel::AstMemberSel(FileLine* fl, AstNodeExpr* fromp, AstVar* varp)
|
||||||
}
|
}
|
||||||
bool AstMemberSel::sameNode(const AstNode* samep) const {
|
bool AstMemberSel::sameNode(const AstNode* samep) const {
|
||||||
const AstMemberSel* const sp = VN_DBG_AS(samep, MemberSel);
|
const AstMemberSel* const sp = VN_DBG_AS(samep, MemberSel);
|
||||||
return sp != nullptr && access() == sp->access() && fromp()->isSame(sp->fromp())
|
return sp && access() == sp->access() && fromp()->isSame(sp->fromp()) && name() == sp->name()
|
||||||
&& name() == sp->name() && varp()->sameNode(sp->varp());
|
&& (varp() && sp->varp() && varp()->sameNode(sp->varp()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void AstMemberSel::dump(std::ostream& str) const {
|
void AstMemberSel::dump(std::ostream& str) const {
|
||||||
|
|
@ -2030,6 +2048,16 @@ void AstModportVarRef::dumpJson(std::ostream& str) const {
|
||||||
dumpJsonStr(str, "direction", direction().ascii());
|
dumpJsonStr(str, "direction", direction().ascii());
|
||||||
dumpJsonGen(str);
|
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 {
|
void AstPin::dump(std::ostream& str) const {
|
||||||
this->AstNode::dump(str);
|
this->AstNode::dump(str);
|
||||||
if (modVarp()) {
|
if (modVarp()) {
|
||||||
|
|
@ -2474,8 +2502,24 @@ void AstNodeVarRef::dumpJson(std::ostream& str) const {
|
||||||
dumpJsonStr(str, "access", access().ascii());
|
dumpJsonStr(str, "access", access().ascii());
|
||||||
dumpJsonGen(str);
|
dumpJsonGen(str);
|
||||||
}
|
}
|
||||||
|
AstNodeVarRef* AstNodeVarRef::varRefLValueRecurse(AstNode* nodep) {
|
||||||
|
// Given a (possible) lvalue expression, recurse to find the being-set NodeVarRef, else nullptr
|
||||||
|
if (AstNodeVarRef* const anodep = VN_CAST(nodep, NodeVarRef)) return anodep;
|
||||||
|
if (AstNodeSel* const anodep = VN_CAST(nodep, NodeSel))
|
||||||
|
return varRefLValueRecurse(anodep->fromp());
|
||||||
|
if (AstSel* const anodep = VN_CAST(nodep, Sel)) return varRefLValueRecurse(anodep->fromp());
|
||||||
|
if (AstArraySel* const anodep = VN_CAST(nodep, ArraySel))
|
||||||
|
return varRefLValueRecurse(anodep->fromp());
|
||||||
|
if (AstMemberSel* const anodep = VN_CAST(nodep, MemberSel))
|
||||||
|
return varRefLValueRecurse(anodep->fromp());
|
||||||
|
if (AstStructSel* const anodep = VN_CAST(nodep, StructSel))
|
||||||
|
return varRefLValueRecurse(anodep->fromp());
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
void AstVarXRef::dump(std::ostream& str) const {
|
void AstVarXRef::dump(std::ostream& str) const {
|
||||||
this->AstNodeVarRef::dump(str);
|
this->AstNodeVarRef::dump(str);
|
||||||
|
if (containsGenBlock()) str << " [GENBLK]";
|
||||||
str << ".=" << dotted() << " ";
|
str << ".=" << dotted() << " ";
|
||||||
if (inlinedDots() != "") str << " inline.=" << inlinedDots() << " - ";
|
if (inlinedDots() != "") str << " inline.=" << inlinedDots() << " - ";
|
||||||
if (varScopep()) {
|
if (varScopep()) {
|
||||||
|
|
@ -2487,6 +2531,7 @@ void AstVarXRef::dump(std::ostream& str) const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void AstVarXRef::dumpJson(std::ostream& str) const {
|
void AstVarXRef::dumpJson(std::ostream& str) const {
|
||||||
|
dumpJsonBoolFunc(str, containsGenBlock);
|
||||||
dumpJsonStrFunc(str, dotted);
|
dumpJsonStrFunc(str, dotted);
|
||||||
dumpJsonStrFunc(str, inlinedDots);
|
dumpJsonStrFunc(str, inlinedDots);
|
||||||
dumpJsonGen(str);
|
dumpJsonGen(str);
|
||||||
|
|
@ -2538,6 +2583,8 @@ void AstVar::dump(std::ostream& str) const {
|
||||||
str << " [FUNC]";
|
str << " [FUNC]";
|
||||||
}
|
}
|
||||||
if (isDpiOpenArray()) str << " [DPIOPENA]";
|
if (isDpiOpenArray()) str << " [DPIOPENA]";
|
||||||
|
if (ignorePostWrite()) str << " [IGNPWR]";
|
||||||
|
if (ignoreSchedWrite()) str << " [IGNWR]";
|
||||||
if (!attrClocker().unknown()) str << " [" << attrClocker().ascii() << "] ";
|
if (!attrClocker().unknown()) str << " [" << attrClocker().ascii() << "] ";
|
||||||
if (!lifetime().isNone()) str << " [" << lifetime().ascii() << "] ";
|
if (!lifetime().isNone()) str << " [" << lifetime().ascii() << "] ";
|
||||||
str << " " << varType();
|
str << " " << varType();
|
||||||
|
|
@ -2570,6 +2617,8 @@ void AstVar::dumpJson(std::ostream& str) const {
|
||||||
dumpJsonBoolFunc(str, isParam);
|
dumpJsonBoolFunc(str, isParam);
|
||||||
dumpJsonBoolFunc(str, attrScBv);
|
dumpJsonBoolFunc(str, attrScBv);
|
||||||
dumpJsonBoolFunc(str, attrSFormat);
|
dumpJsonBoolFunc(str, attrSFormat);
|
||||||
|
dumpJsonBoolFunc(str, ignorePostWrite);
|
||||||
|
dumpJsonBoolFunc(str, ignoreSchedWrite);
|
||||||
dumpJsonGen(str);
|
dumpJsonGen(str);
|
||||||
}
|
}
|
||||||
bool AstVar::sameNode(const AstNode* samep) const {
|
bool AstVar::sameNode(const AstNode* samep) const {
|
||||||
|
|
@ -2656,7 +2705,9 @@ AstNodeModule* AstClassOrPackageRef::classOrPackageSkipp() const {
|
||||||
AstNode* lastp = nullptr;
|
AstNode* lastp = nullptr;
|
||||||
while (foundp != lastp) {
|
while (foundp != lastp) {
|
||||||
lastp = foundp;
|
lastp = foundp;
|
||||||
if (AstNodeDType* const anodep = VN_CAST(foundp, NodeDType)) foundp = anodep->skipRefp();
|
if (AstNodeDType* const anodep = VN_CAST(foundp, NodeDType)) {
|
||||||
|
foundp = anodep->skipRefOrNullp();
|
||||||
|
}
|
||||||
if (AstTypedef* const anodep = VN_CAST(foundp, Typedef)) foundp = anodep->subDTypep();
|
if (AstTypedef* const anodep = VN_CAST(foundp, Typedef)) foundp = anodep->subDTypep();
|
||||||
if (AstClassRefDType* const anodep = VN_CAST(foundp, ClassRefDType))
|
if (AstClassRefDType* const anodep = VN_CAST(foundp, ClassRefDType))
|
||||||
foundp = anodep->classp();
|
foundp = anodep->classp();
|
||||||
|
|
@ -2988,7 +3039,8 @@ void AstCMethodHard::setPurity() {
|
||||||
{"resume", false},
|
{"resume", false},
|
||||||
{"reverse", false},
|
{"reverse", false},
|
||||||
{"rsort", false},
|
{"rsort", false},
|
||||||
{"set", false},
|
{"setBit", false},
|
||||||
|
{"setWord", false},
|
||||||
{"set_randmode", false},
|
{"set_randmode", false},
|
||||||
{"shuffle", false},
|
{"shuffle", false},
|
||||||
{"size", true},
|
{"size", true},
|
||||||
|
|
@ -3055,7 +3107,7 @@ AstAlways* AstAssignW::convertToAlways() {
|
||||||
if (hasTimingControl) {
|
if (hasTimingControl) {
|
||||||
// If there's a timing control, put the assignment in a fork..join_none. This process won't
|
// If there's a timing control, put the assignment in a fork..join_none. This process won't
|
||||||
// get marked as suspendable and thus will be scheduled normally
|
// get marked as suspendable and thus will be scheduled normally
|
||||||
auto* forkp = new AstFork{flp, "", bodysp};
|
AstFork* forkp = new AstFork{flp, "", bodysp};
|
||||||
forkp->joinType(VJoinType::JOIN_NONE);
|
forkp->joinType(VJoinType::JOIN_NONE);
|
||||||
bodysp = forkp;
|
bodysp = forkp;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -99,7 +99,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get a pointer to the user data if exists, otherwise nullptr
|
// Get a pointer to the user data if exists, otherwise nullptr
|
||||||
T_Data* tryGet(const T_Node* nodep) { return getUserp(nodep); }
|
T_Data* tryGet(const T_Node* nodep) const { return getUserp(nodep); }
|
||||||
|
|
||||||
void clear() { m_allocated.clear(); }
|
void clear() { m_allocated.clear(); }
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -377,7 +377,7 @@ void V3Begin::debeginAll(AstNetlist* nodep) {
|
||||||
{
|
{
|
||||||
BeginState state;
|
BeginState state;
|
||||||
{ BeginVisitor{nodep, &state}; }
|
{ BeginVisitor{nodep, &state}; }
|
||||||
if (state.anyFuncInBegin()) { BeginRelinkVisitor{nodep, &state}; }
|
if (state.anyFuncInBegin()) BeginRelinkVisitor{nodep, &state};
|
||||||
} // Destruct before checking
|
} // Destruct before checking
|
||||||
V3Global::dumpCheckGlobalTree("begin", 0, dumpTreeEitherLevel() >= 3);
|
V3Global::dumpCheckGlobalTree("begin", 0, dumpTreeEitherLevel() >= 3);
|
||||||
}
|
}
|
||||||
|
|
@ -506,7 +506,8 @@ AstNode* V3Begin::convertToWhile(AstForeach* nodep) {
|
||||||
AstNode* const first_clearp
|
AstNode* const first_clearp
|
||||||
= new AstAssign{fl, new AstVarRef{fl, first_varp, VAccess::WRITE},
|
= new AstAssign{fl, new AstVarRef{fl, first_varp, VAccess::WRITE},
|
||||||
new AstConst{fl, AstConst::BitFalse{}}};
|
new AstConst{fl, AstConst::BitFalse{}}};
|
||||||
auto* const orp = new AstLogOr{fl, new AstVarRef{fl, first_varp, VAccess::READ},
|
AstLogOr* const orp
|
||||||
|
= new AstLogOr{fl, new AstVarRef{fl, first_varp, VAccess::READ},
|
||||||
new AstNeq{fl, new AstConst{fl, 0}, nextp}};
|
new AstNeq{fl, new AstConst{fl, 0}, nextp}};
|
||||||
AstNode* const whilep = new AstWhile{fl, orp, first_clearp};
|
AstNode* const whilep = new AstWhile{fl, orp, first_clearp};
|
||||||
first_clearp->addNext(bodyPointp);
|
first_clearp->addNext(bodyPointp);
|
||||||
|
|
|
||||||
|
|
@ -114,7 +114,7 @@ public:
|
||||||
callp->argTypes("vlSymsp");
|
callp->argTypes("vlSymsp");
|
||||||
} else {
|
} else {
|
||||||
if (m_type.isCoverage()) callp->argTypes("first");
|
if (m_type.isCoverage()) callp->argTypes("first");
|
||||||
callp->selfPointer(VSelfPointerText{VSelfPointerText::This()});
|
callp->selfPointer(VSelfPointerText{VSelfPointerText::This{}});
|
||||||
}
|
}
|
||||||
rootFuncp->addStmtsp(callp->makeStmt());
|
rootFuncp->addStmtsp(callp->makeStmt());
|
||||||
}
|
}
|
||||||
|
|
@ -137,7 +137,17 @@ class CCtorsVisitor final : public VNVisitor {
|
||||||
AstCFunc* m_cfuncp = nullptr; // Current function
|
AstCFunc* m_cfuncp = nullptr; // Current function
|
||||||
V3CCtorsBuilder* m_varResetp = nullptr; // Builder of _ctor_var_reset
|
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 {
|
void visit(AstNodeModule* nodep) override {
|
||||||
VL_RESTORER(m_modp);
|
VL_RESTORER(m_modp);
|
||||||
VL_RESTORER(m_varResetp);
|
VL_RESTORER(m_varResetp);
|
||||||
|
|
@ -167,6 +177,7 @@ class CCtorsVisitor final : public VNVisitor {
|
||||||
// If can be referred to by base pointer, need virtual delete
|
// If can be referred to by base pointer, need virtual delete
|
||||||
funcp->isVirtual(classp->isExtended());
|
funcp->isVirtual(classp->isExtended());
|
||||||
funcp->slow(false);
|
funcp->slow(false);
|
||||||
|
insertSc(funcp, classp, VNType::atScDtor);
|
||||||
classp->addStmtsp(funcp);
|
classp->addStmtsp(funcp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -177,18 +188,16 @@ class CCtorsVisitor final : public VNVisitor {
|
||||||
m_varResetp = nullptr;
|
m_varResetp = nullptr;
|
||||||
m_cfuncp = nodep;
|
m_cfuncp = nodep;
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
|
if (nodep->name() == "new") insertSc(nodep, m_modp, VNType::atScCtor);
|
||||||
}
|
}
|
||||||
void visit(AstVar* nodep) override {
|
void visit(AstVar* nodep) override {
|
||||||
if (!nodep->isIfaceParent() && !nodep->isIfaceRef() && !nodep->noReset()
|
if (nodep->needsCReset()) {
|
||||||
&& !nodep->isParam() && !nodep->isStatementTemp()
|
|
||||||
&& !(nodep->basicp()
|
|
||||||
&& (nodep->basicp()->isEvent() || nodep->basicp()->isTriggerVec()))) {
|
|
||||||
if (m_varResetp) {
|
if (m_varResetp) {
|
||||||
const auto vrefp = new AstVarRef{nodep->fileline(), nodep, VAccess::WRITE};
|
AstVarRef* const vrefp = new AstVarRef{nodep->fileline(), nodep, VAccess::WRITE};
|
||||||
m_varResetp->add(new AstCReset{nodep->fileline(), vrefp});
|
m_varResetp->add(new AstCReset{nodep->fileline(), vrefp, true});
|
||||||
} else if (m_cfuncp) {
|
} else if (m_cfuncp) {
|
||||||
const auto vrefp = new AstVarRef{nodep->fileline(), nodep, VAccess::WRITE};
|
AstVarRef* const vrefp = new AstVarRef{nodep->fileline(), nodep, VAccess::WRITE};
|
||||||
nodep->addNextHere(new AstCReset{nodep->fileline(), vrefp});
|
nodep->addNextHere(new AstCReset{nodep->fileline(), vrefp, true});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -226,7 +235,7 @@ void V3CCtors::evalAsserts() {
|
||||||
// if (signal & CONST(upper_non_clean_mask)) { fail; }
|
// if (signal & CONST(upper_non_clean_mask)) { fail; }
|
||||||
AstVarRef* const vrefp
|
AstVarRef* const vrefp
|
||||||
= new AstVarRef{varp->fileline(), varp, VAccess::READ};
|
= new AstVarRef{varp->fileline(), varp, VAccess::READ};
|
||||||
vrefp->selfPointer(VSelfPointerText{VSelfPointerText::This()});
|
vrefp->selfPointer(VSelfPointerText{VSelfPointerText::This{}});
|
||||||
AstNodeExpr* newp = vrefp;
|
AstNodeExpr* newp = vrefp;
|
||||||
if (varp->isWide()) {
|
if (varp->isWide()) {
|
||||||
newp = new AstWordSel{
|
newp = new AstWordSel{
|
||||||
|
|
|
||||||
|
|
@ -72,13 +72,13 @@ class CaseLintVisitor final : public VNVisitorConst {
|
||||||
|
|
||||||
// Check for X/Z in non-casex statements
|
// Check for X/Z in non-casex statements
|
||||||
{
|
{
|
||||||
|
VL_RESTORER(m_caseExprp);
|
||||||
m_caseExprp = nodep;
|
m_caseExprp = nodep;
|
||||||
iterateConst(nodep->exprp());
|
iterateConst(nodep->exprp());
|
||||||
for (AstCaseItem* itemp = nodep->itemsp(); itemp;
|
for (AstCaseItem* itemp = nodep->itemsp(); itemp;
|
||||||
itemp = VN_AS(itemp->nextp(), CaseItem)) {
|
itemp = VN_AS(itemp->nextp(), CaseItem)) {
|
||||||
iterateAndNextConstNull(itemp->condsp());
|
iterateAndNextConstNull(itemp->condsp());
|
||||||
}
|
}
|
||||||
m_caseExprp = nullptr;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void visit(AstConst* nodep) override {
|
void visit(AstConst* nodep) override {
|
||||||
|
|
@ -578,7 +578,7 @@ class CaseVisitor final : public VNVisitor {
|
||||||
}
|
}
|
||||||
//--------------------
|
//--------------------
|
||||||
void visit(AstAlways* nodep) override {
|
void visit(AstAlways* nodep) override {
|
||||||
VL_RESTORER(m_alwaysp)
|
VL_RESTORER(m_alwaysp);
|
||||||
m_alwaysp = nodep;
|
m_alwaysp = nodep;
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -188,9 +188,9 @@ class CombineVisitor final : VNVisitor {
|
||||||
}
|
}
|
||||||
void visit(AstNodeModule* nodep) override {
|
void visit(AstNodeModule* nodep) override {
|
||||||
UASSERT_OBJ(!m_modp, nodep, "Should not nest");
|
UASSERT_OBJ(!m_modp, nodep, "Should not nest");
|
||||||
|
VL_RESTORER(m_modp);
|
||||||
m_modp = nodep;
|
m_modp = nodep;
|
||||||
iterateChildrenConst(nodep);
|
iterateChildrenConst(nodep);
|
||||||
m_modp = nullptr;
|
|
||||||
}
|
}
|
||||||
void visit(AstCFunc* nodep) override {
|
void visit(AstCFunc* nodep) override {
|
||||||
iterateChildrenConst(nodep);
|
iterateChildrenConst(nodep);
|
||||||
|
|
|
||||||
|
|
@ -540,6 +540,8 @@ class V3ConfigResolver final {
|
||||||
std::unordered_map<string, std::unordered_map<string, uint64_t>>
|
std::unordered_map<string, std::unordered_map<string, uint64_t>>
|
||||||
m_profileData; // Access to profile_data records
|
m_profileData; // Access to profile_data records
|
||||||
uint8_t m_mode = NONE;
|
uint8_t m_mode = NONE;
|
||||||
|
std::unordered_map<string, int> m_hierWorkers;
|
||||||
|
FileLine* m_hierWorkersFileLine = nullptr;
|
||||||
FileLine* m_profileFileLine = nullptr;
|
FileLine* m_profileFileLine = nullptr;
|
||||||
|
|
||||||
V3ConfigResolver() = default;
|
V3ConfigResolver() = default;
|
||||||
|
|
@ -570,6 +572,16 @@ public:
|
||||||
// Empty key for hierarchical DPI wrapper costs.
|
// Empty key for hierarchical DPI wrapper costs.
|
||||||
return getProfileData(hierDpi, "");
|
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 {
|
uint64_t getProfileData(const string& model, const string& key) const {
|
||||||
const auto mit = m_profileData.find(model);
|
const auto mit = m_profileData.find(model);
|
||||||
if (mit == m_profileData.cend()) return 0;
|
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);
|
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) {
|
void V3Config::addIgnore(V3ErrorCode code, bool on, const string& filename, int min, int max) {
|
||||||
if (filename == "*") {
|
if (filename == "*") {
|
||||||
FileLine::globalWarnOff(code, !on);
|
FileLine::globalWarnOff(code, !on);
|
||||||
|
|
@ -741,6 +757,12 @@ void V3Config::applyVarAttr(AstNodeModule* modulep, AstNodeFTask* ftaskp, AstVar
|
||||||
if (vp) vp->apply(varp);
|
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) {
|
uint64_t V3Config::getProfileData(const string& hierDpi) {
|
||||||
return V3ConfigResolver::s().getProfileData(hierDpi);
|
return V3ConfigResolver::s().getProfileData(hierDpi);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ public:
|
||||||
static void addCaseParallel(const string& file, int lineno);
|
static void addCaseParallel(const string& file, int lineno);
|
||||||
static void addCoverageBlockOff(const string& file, int lineno);
|
static void addCoverageBlockOff(const string& file, int lineno);
|
||||||
static void addCoverageBlockOff(const string& module, const string& blockname);
|
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 addIgnore(V3ErrorCode code, bool on, const string& filename, int min, int max);
|
||||||
static void addIgnoreMatch(V3ErrorCode code, const string& filename, const string& contents,
|
static void addIgnoreMatch(V3ErrorCode code, const string& filename, const string& contents,
|
||||||
const string& match);
|
const string& match);
|
||||||
|
|
@ -52,6 +53,8 @@ public:
|
||||||
static void applyModule(AstNodeModule* modulep);
|
static void applyModule(AstNodeModule* modulep);
|
||||||
static void applyVarAttr(AstNodeModule* modulep, AstNodeFTask* ftaskp, AstVar* varp);
|
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& hierDpi);
|
||||||
static uint64_t getProfileData(const string& model, const string& key);
|
static uint64_t getProfileData(const string& model, const string& key);
|
||||||
static FileLine* getProfileDataFileLine();
|
static FileLine* getProfileDataFileLine();
|
||||||
|
|
|
||||||
|
|
@ -2169,7 +2169,7 @@ class ConstVisitor final : public VNVisitor {
|
||||||
// Add a cast if needed.
|
// Add a cast if needed.
|
||||||
AstStreamR* const streamp = VN_AS(nodep->rhsp(), StreamR)->unlinkFrBack();
|
AstStreamR* const streamp = VN_AS(nodep->rhsp(), StreamR)->unlinkFrBack();
|
||||||
AstNodeExpr* srcp = streamp->lhsp()->unlinkFrBack();
|
AstNodeExpr* srcp = streamp->lhsp()->unlinkFrBack();
|
||||||
AstNodeDType* const srcDTypep = srcp->dtypep();
|
AstNodeDType* const srcDTypep = srcp->dtypep()->skipRefp();
|
||||||
if (VN_IS(srcDTypep, QueueDType) || VN_IS(srcDTypep, DynArrayDType)) {
|
if (VN_IS(srcDTypep, QueueDType) || VN_IS(srcDTypep, DynArrayDType)) {
|
||||||
srcp = new AstCvtArrayToPacked{srcp->fileline(), srcp, nodep->dtypep()};
|
srcp = new AstCvtArrayToPacked{srcp->fileline(), srcp, nodep->dtypep()};
|
||||||
} else if (VN_IS(srcDTypep, UnpackArrayDType)) {
|
} else if (VN_IS(srcDTypep, UnpackArrayDType)) {
|
||||||
|
|
@ -2191,30 +2191,32 @@ class ConstVisitor final : public VNVisitor {
|
||||||
// Push the stream operator to the rhs of the assignment statement
|
// Push the stream operator to the rhs of the assignment statement
|
||||||
AstNodeExpr* streamp = nodep->lhsp()->unlinkFrBack();
|
AstNodeExpr* streamp = nodep->lhsp()->unlinkFrBack();
|
||||||
AstNodeExpr* const dstp = VN_AS(streamp, StreamL)->lhsp()->unlinkFrBack();
|
AstNodeExpr* const dstp = VN_AS(streamp, StreamL)->lhsp()->unlinkFrBack();
|
||||||
|
AstNodeDType* const dstDTypep = dstp->dtypep()->skipRefp();
|
||||||
AstNodeExpr* const srcp = nodep->rhsp()->unlinkFrBack();
|
AstNodeExpr* const srcp = nodep->rhsp()->unlinkFrBack();
|
||||||
|
AstNodeDType* const srcDTypep = srcp->dtypep()->skipRefp();
|
||||||
const int sWidth = srcp->width();
|
const int sWidth = srcp->width();
|
||||||
const int dWidth = dstp->width();
|
const int dWidth = dstp->width();
|
||||||
// Connect the rhs to the stream operator and update its width
|
// Connect the rhs to the stream operator and update its width
|
||||||
VN_AS(streamp, StreamL)->lhsp(srcp);
|
VN_AS(streamp, StreamL)->lhsp(srcp);
|
||||||
if (VN_IS(srcp->dtypep(), DynArrayDType) || VN_IS(srcp->dtypep(), QueueDType)
|
if (VN_IS(srcDTypep, DynArrayDType) || VN_IS(srcDTypep, QueueDType)
|
||||||
|| VN_IS(srcp->dtypep(), UnpackArrayDType)) {
|
|| VN_IS(srcDTypep, UnpackArrayDType)) {
|
||||||
streamp->dtypeSetStream();
|
streamp->dtypeSetStream();
|
||||||
} else {
|
} else {
|
||||||
streamp->dtypeSetLogicUnsized(srcp->width(), srcp->widthMin(), VSigning::UNSIGNED);
|
streamp->dtypeSetLogicUnsized(srcp->width(), srcp->widthMin(), VSigning::UNSIGNED);
|
||||||
}
|
}
|
||||||
if (VN_IS(dstp->dtypep(), UnpackArrayDType)) {
|
if (VN_IS(dstDTypep, UnpackArrayDType)) {
|
||||||
streamp = new AstCvtPackedToArray{nodep->fileline(), streamp, dstp->dtypep()};
|
streamp = new AstCvtPackedToArray{nodep->fileline(), streamp, dstDTypep};
|
||||||
} else {
|
} else {
|
||||||
UASSERT(sWidth >= dWidth, "sWidth >= dWidth should have caused an error earlier");
|
UASSERT(sWidth >= dWidth, "sWidth >= dWidth should have caused an error earlier");
|
||||||
if (dWidth == 0) {
|
if (dWidth == 0) {
|
||||||
streamp = new AstCvtPackedToArray{nodep->fileline(), streamp, dstp->dtypep()};
|
streamp = new AstCvtPackedToArray{nodep->fileline(), streamp, dstDTypep};
|
||||||
} else if (sWidth >= dWidth) {
|
} else if (sWidth >= dWidth) {
|
||||||
streamp = new AstSel{streamp->fileline(), streamp, sWidth - dWidth, dWidth};
|
streamp = new AstSel{streamp->fileline(), streamp, sWidth - dWidth, dWidth};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
nodep->lhsp(dstp);
|
nodep->lhsp(dstp);
|
||||||
nodep->rhsp(streamp);
|
nodep->rhsp(streamp);
|
||||||
nodep->dtypep(dstp->dtypep());
|
nodep->dtypep(dstDTypep);
|
||||||
return true;
|
return true;
|
||||||
} else if (m_doV && VN_IS(nodep->lhsp(), StreamR)) {
|
} else if (m_doV && VN_IS(nodep->lhsp(), StreamR)) {
|
||||||
// The right stream operator on lhs of assignment statement does
|
// The right stream operator on lhs of assignment statement does
|
||||||
|
|
@ -2222,12 +2224,13 @@ class ConstVisitor final : public VNVisitor {
|
||||||
// then we select bits from the left-most, not the right-most.
|
// then we select bits from the left-most, not the right-most.
|
||||||
AstNodeExpr* const streamp = nodep->lhsp()->unlinkFrBack();
|
AstNodeExpr* const streamp = nodep->lhsp()->unlinkFrBack();
|
||||||
AstNodeExpr* const dstp = VN_AS(streamp, StreamR)->lhsp()->unlinkFrBack();
|
AstNodeExpr* const dstp = VN_AS(streamp, StreamR)->lhsp()->unlinkFrBack();
|
||||||
|
AstNodeDType* const dstDTypep = dstp->dtypep()->skipRefp();
|
||||||
AstNodeExpr* srcp = nodep->rhsp()->unlinkFrBack();
|
AstNodeExpr* srcp = nodep->rhsp()->unlinkFrBack();
|
||||||
const int sWidth = srcp->width();
|
const int sWidth = srcp->width();
|
||||||
const int dWidth = dstp->width();
|
const int dWidth = dstp->width();
|
||||||
if (VN_IS(dstp->dtypep(), UnpackArrayDType)) {
|
if (VN_IS(dstDTypep, UnpackArrayDType)) {
|
||||||
const int dstBitWidth
|
const int dstBitWidth
|
||||||
= dWidth * VN_AS(dstp->dtypep(), UnpackArrayDType)->arrayUnpackedElements();
|
= dWidth * VN_AS(dstDTypep, UnpackArrayDType)->arrayUnpackedElements();
|
||||||
// Handling the case where rhs is wider than lhs. StreamL does not require this
|
// Handling the case where rhs is wider than lhs. StreamL does not require this
|
||||||
// since the combination of the left streaming operation and the implicit
|
// since the combination of the left streaming operation and the implicit
|
||||||
// truncation in VL_ASSIGN_UNPACK automatically selects the left-most bits.
|
// truncation in VL_ASSIGN_UNPACK automatically selects the left-most bits.
|
||||||
|
|
@ -2235,30 +2238,30 @@ class ConstVisitor final : public VNVisitor {
|
||||||
srcp
|
srcp
|
||||||
= new AstSel{streamp->fileline(), srcp, sWidth - dstBitWidth, dstBitWidth};
|
= new AstSel{streamp->fileline(), srcp, sWidth - dstBitWidth, dstBitWidth};
|
||||||
}
|
}
|
||||||
srcp = new AstCvtPackedToArray{nodep->fileline(), srcp, dstp->dtypep()};
|
srcp = new AstCvtPackedToArray{nodep->fileline(), srcp, dstDTypep};
|
||||||
} else {
|
} else {
|
||||||
UASSERT(sWidth >= dWidth, "sWidth >= dWidth should have caused an error earlier");
|
UASSERT(sWidth >= dWidth, "sWidth >= dWidth should have caused an error earlier");
|
||||||
if (dWidth == 0) {
|
if (dWidth == 0) {
|
||||||
srcp = new AstCvtPackedToArray{nodep->fileline(), srcp, dstp->dtypep()};
|
srcp = new AstCvtPackedToArray{nodep->fileline(), srcp, dstDTypep};
|
||||||
} else if (sWidth >= dWidth) {
|
} else if (sWidth >= dWidth) {
|
||||||
srcp = new AstSel{streamp->fileline(), srcp, sWidth - dWidth, dWidth};
|
srcp = new AstSel{streamp->fileline(), srcp, sWidth - dWidth, dWidth};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
nodep->lhsp(dstp);
|
nodep->lhsp(dstp);
|
||||||
nodep->rhsp(srcp);
|
nodep->rhsp(srcp);
|
||||||
nodep->dtypep(dstp->dtypep());
|
nodep->dtypep(dstDTypep);
|
||||||
VL_DO_DANGLING(pushDeletep(streamp), streamp);
|
VL_DO_DANGLING(pushDeletep(streamp), streamp);
|
||||||
// Further reduce, any of the nodes may have more reductions.
|
// Further reduce, any of the nodes may have more reductions.
|
||||||
return true;
|
return true;
|
||||||
} else if (m_doV && VN_IS(nodep->rhsp(), StreamL)) {
|
} else if (m_doV && VN_IS(nodep->rhsp(), StreamL)) {
|
||||||
AstNodeDType* const lhsDtypep = nodep->lhsp()->dtypep();
|
AstNodeDType* const lhsDtypep = nodep->lhsp()->dtypep()->skipRefp();
|
||||||
AstStreamL* streamp = VN_AS(nodep->rhsp(), StreamL);
|
AstStreamL* streamp = VN_AS(nodep->rhsp(), StreamL);
|
||||||
AstNodeExpr* const srcp = streamp->lhsp();
|
AstNodeExpr* const srcp = streamp->lhsp();
|
||||||
const AstNodeDType* const srcDTypep = srcp->dtypep();
|
const AstNodeDType* const srcDTypep = srcp->dtypep()->skipRefp();
|
||||||
if (VN_IS(srcDTypep, QueueDType) || VN_IS(srcDTypep, DynArrayDType)
|
if (VN_IS(srcDTypep, QueueDType) || VN_IS(srcDTypep, DynArrayDType)
|
||||||
|| VN_IS(srcDTypep, UnpackArrayDType)) {
|
|| VN_IS(srcDTypep, UnpackArrayDType)) {
|
||||||
streamp->lhsp(new AstCvtArrayToPacked{srcp->fileline(), srcp->unlinkFrBack(),
|
streamp->lhsp(
|
||||||
nodep->dtypep()});
|
new AstCvtArrayToPacked{srcp->fileline(), srcp->unlinkFrBack(), lhsDtypep});
|
||||||
streamp->dtypeFrom(lhsDtypep);
|
streamp->dtypeFrom(lhsDtypep);
|
||||||
}
|
}
|
||||||
} else if (m_doV && replaceAssignMultiSel(nodep)) {
|
} else if (m_doV && replaceAssignMultiSel(nodep)) {
|
||||||
|
|
@ -2896,8 +2899,8 @@ class ConstVisitor final : public VNVisitor {
|
||||||
|
|
||||||
if (const AstConst* const aConstp = VN_CAST(ap, Const)) {
|
if (const AstConst* const aConstp = VN_CAST(ap, Const)) {
|
||||||
const AstConst* const bConstp = VN_AS(bp, Const);
|
const AstConst* const bConstp = VN_AS(bp, Const);
|
||||||
if (aConstp->toUQuad() < bConstp->toUQuad()) return -1;
|
if (aConstp->num().isLtXZ(bConstp->num())) return -1;
|
||||||
if (aConstp->toUQuad() > bConstp->toUQuad()) return 1;
|
if (bConstp->num().isLtXZ(aConstp->num())) return 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3265,9 +3268,9 @@ class ConstVisitor final : public VNVisitor {
|
||||||
inPct = false;
|
inPct = false;
|
||||||
fmt += ch;
|
fmt += ch;
|
||||||
switch (std::tolower(ch)) {
|
switch (std::tolower(ch)) {
|
||||||
case '%': break; // %% - just output a %
|
case '%': break; // %% - still %%
|
||||||
case 'm': break; // %m - auto insert "name"
|
case 'm': break; // %m - still %m - auto insert "name"
|
||||||
case 'l': break; // %l - auto insert "library"
|
case 'l': break; // %l - still %l - auto insert "library"
|
||||||
case 't': // FALLTHRU
|
case 't': // FALLTHRU
|
||||||
case '^': // %t/%^ - don't know $timeformat so can't constify
|
case '^': // %t/%^ - don't know $timeformat so can't constify
|
||||||
if (argp) argp = argp->nextp();
|
if (argp) argp = argp->nextp();
|
||||||
|
|
@ -3871,7 +3874,7 @@ AstNode* V3Const::constifyParamsEdit(AstNode* nodep) {
|
||||||
} else {
|
} else {
|
||||||
nodep = visitor.mainAcceptEdit(nodep);
|
nodep = visitor.mainAcceptEdit(nodep);
|
||||||
}
|
}
|
||||||
// Because we do edits, nodep links may get trashed and core dump this.
|
// Because we do edits, nodep links may get trashed and core dump if have next line
|
||||||
// if (debug() > 0) nodep->dumpTree("- forceConDONE: ");
|
// if (debug() > 0) nodep->dumpTree("- forceConDONE: ");
|
||||||
return nodep;
|
return nodep;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,40 @@
|
||||||
|
|
||||||
VL_DEFINE_DEBUG_FUNCTIONS;
|
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||||
|
|
||||||
|
class ExprCoverageEligibleVisitor final : public VNVisitor {
|
||||||
|
// STATE
|
||||||
|
bool m_eligible = true;
|
||||||
|
|
||||||
|
void visit(AstNodeVarRef* nodep) override {
|
||||||
|
AstNodeDType* dtypep = nodep->varp()->dtypep();
|
||||||
|
// Class objecs and references not supported for expression coverage
|
||||||
|
// because the object may not persist until the point at which
|
||||||
|
// coverage data is gathered
|
||||||
|
// This could be resolved in the future by protecting against dereferrencing
|
||||||
|
// null pointers when cloning the expression for expression coverage
|
||||||
|
if (VN_CAST(dtypep, ClassRefDType)) {
|
||||||
|
m_eligible = false;
|
||||||
|
} else {
|
||||||
|
iterateChildren(nodep);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void visit(AstNode* nodep) override {
|
||||||
|
if (!nodep->isExprCoverageEligible()) {
|
||||||
|
m_eligible = false;
|
||||||
|
} else {
|
||||||
|
iterateChildren(nodep);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
// CONSTRUCTORS
|
||||||
|
explicit ExprCoverageEligibleVisitor(AstNode* nodep) { iterateChildren(nodep); }
|
||||||
|
~ExprCoverageEligibleVisitor() override = default;
|
||||||
|
|
||||||
|
bool eligible() { return m_eligible; }
|
||||||
|
};
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
// Coverage state, as a visitor of each AstNode
|
// Coverage state, as a visitor of each AstNode
|
||||||
|
|
||||||
|
|
@ -159,6 +193,7 @@ class CoverageVisitor final : public VNVisitor {
|
||||||
fl_nowarn->modifyWarnOff(V3ErrorCode::UNUSEDSIGNAL, true);
|
fl_nowarn->modifyWarnOff(V3ErrorCode::UNUSEDSIGNAL, true);
|
||||||
AstVar* const varp = new AstVar{fl_nowarn, VVarType::MODULETEMP, trace_var_name,
|
AstVar* const varp = new AstVar{fl_nowarn, VVarType::MODULETEMP, trace_var_name,
|
||||||
incp->findUInt32DType()};
|
incp->findUInt32DType()};
|
||||||
|
varp->setIgnoreSchedWrite(); // Ignore the increment output, so no UNOPTFLAT
|
||||||
varp->trace(true);
|
varp->trace(true);
|
||||||
m_modp->addStmtsp(varp);
|
m_modp->addStmtsp(varp);
|
||||||
UINFO(5, "New coverage trace: " << varp << endl);
|
UINFO(5, "New coverage trace: " << varp << endl);
|
||||||
|
|
@ -668,6 +703,7 @@ class CoverageVisitor final : public VNVisitor {
|
||||||
m_objective = true;
|
m_objective = true;
|
||||||
iterate(nodep);
|
iterate(nodep);
|
||||||
if (checkMaxExprs(falseExprs.size())) return;
|
if (checkMaxExprs(falseExprs.size())) return;
|
||||||
|
if (m_seeking == ABORTED) return;
|
||||||
|
|
||||||
addExprCoverInc(nodep);
|
addExprCoverInc(nodep);
|
||||||
const int start = m_exprs.size();
|
const int start = m_exprs.size();
|
||||||
|
|
@ -871,19 +907,20 @@ class CoverageVisitor final : public VNVisitor {
|
||||||
lineTrack(nodep);
|
lineTrack(nodep);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lambdas not supported for expression coverage
|
void visit(AstFuncRef* nodep) override {
|
||||||
void visit(AstWith* nodep) override {
|
if (nodep->taskp()->lifetime().isAutomatic()) {
|
||||||
VL_RESTORER(m_seeking);
|
visit(static_cast<AstNodeExpr*>(nodep));
|
||||||
if (m_seeking == SEEKING) abortExprCoverage();
|
} else {
|
||||||
m_seeking = ABORTED;
|
exprUnsupported(nodep, "non-automatic function");
|
||||||
iterateChildren(nodep);
|
}
|
||||||
lineTrack(nodep);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void visit(AstNodeExpr* nodep) override {
|
void visit(AstNodeExpr* nodep) override {
|
||||||
if (m_seeking != SEEKING) {
|
if (m_seeking != SEEKING) {
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
} else {
|
} else {
|
||||||
|
ExprCoverageEligibleVisitor elgibleVisitor(nodep);
|
||||||
|
if (elgibleVisitor.eligible()) {
|
||||||
std::stringstream emitV;
|
std::stringstream emitV;
|
||||||
V3EmitV::verilogForTree(nodep, emitV);
|
V3EmitV::verilogForTree(nodep, emitV);
|
||||||
// Add new expression with a single term
|
// Add new expression with a single term
|
||||||
|
|
@ -891,6 +928,9 @@ class CoverageVisitor final : public VNVisitor {
|
||||||
expr.emplace_back(nodep, m_objective, emitV.str());
|
expr.emplace_back(nodep, m_objective, emitV.str());
|
||||||
m_exprs.push_back(std::move(expr));
|
m_exprs.push_back(std::move(expr));
|
||||||
checkMaxExprs();
|
checkMaxExprs();
|
||||||
|
} else {
|
||||||
|
exprUnsupported(nodep, "not coverage eligible");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
lineTrack(nodep);
|
lineTrack(nodep);
|
||||||
}
|
}
|
||||||
|
|
@ -901,6 +941,17 @@ class CoverageVisitor final : public VNVisitor {
|
||||||
lineTrack(nodep);
|
lineTrack(nodep);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void exprUnsupported(AstNode* nodep, const string& why) {
|
||||||
|
UINFO(9, "unsupported: " << why << " " << nodep << endl);
|
||||||
|
bool wasSeeking = m_seeking == SEEKING;
|
||||||
|
Objective oldSeeking = m_seeking;
|
||||||
|
if (wasSeeking) abortExprCoverage();
|
||||||
|
m_seeking = ABORTED;
|
||||||
|
iterateChildren(nodep);
|
||||||
|
lineTrack(nodep);
|
||||||
|
if (!wasSeeking) m_seeking = oldSeeking;
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// CONSTRUCTORS
|
// CONSTRUCTORS
|
||||||
explicit CoverageVisitor(AstNetlist* rootp) { iterateChildren(rootp); }
|
explicit CoverageVisitor(AstNetlist* rootp) { iterateChildren(rootp); }
|
||||||
|
|
|
||||||
|
|
@ -155,6 +155,7 @@ class DelayedVisitor final : public VNVisitor {
|
||||||
struct { // Stuff needed for Scheme::FlagShared
|
struct { // Stuff needed for Scheme::FlagShared
|
||||||
AstActive* activep; // The active block for the Pre/Post logic
|
AstActive* activep; // The active block for the Pre/Post logic
|
||||||
AstAlwaysPost* postp; // The post block for commiting results
|
AstAlwaysPost* postp; // The post block for commiting results
|
||||||
|
AstVarScope* commitFlagp; // The commit flag variable, for reuse
|
||||||
AstIf* commitIfp; // The previous if statement for committing, for reuse
|
AstIf* commitIfp; // The previous if statement for committing, for reuse
|
||||||
} m_flagSharedKit;
|
} m_flagSharedKit;
|
||||||
struct { // Stuff needed for Scheme::FlagUnique
|
struct { // Stuff needed for Scheme::FlagUnique
|
||||||
|
|
@ -346,8 +347,8 @@ class DelayedVisitor final : public VNVisitor {
|
||||||
arrSelp->bitp(captureVal(scopep, insertp, arrSelp->bitp()->unlinkFrBack(), tmpName));
|
arrSelp->bitp(captureVal(scopep, insertp, arrSelp->bitp()->unlinkFrBack(), tmpName));
|
||||||
nodep = arrSelp->fromp();
|
nodep = arrSelp->fromp();
|
||||||
}
|
}
|
||||||
// What remains must be an AstVarRef
|
// What remains must be an AstVarRef, or some sort of select, we assume can reuse it.
|
||||||
UASSERT_OBJ(VN_IS(nodep, VarRef), lhsp, "Malformed LHS in NBA");
|
UASSERT_OBJ(nodep->isPure(), lhsp, "Malformed LHS in NBA");
|
||||||
// Now have been converted to use the captured values
|
// Now have been converted to use the captured values
|
||||||
return lhsp;
|
return lhsp;
|
||||||
}
|
}
|
||||||
|
|
@ -421,6 +422,9 @@ class DelayedVisitor final : public VNVisitor {
|
||||||
AstAlwaysPost* const postp = new AstAlwaysPost{flp};
|
AstAlwaysPost* const postp = new AstAlwaysPost{flp};
|
||||||
activep->addStmtsp(postp);
|
activep->addStmtsp(postp);
|
||||||
vscpInfo.flagSharedKit().postp = postp;
|
vscpInfo.flagSharedKit().postp = postp;
|
||||||
|
// Initialize
|
||||||
|
vscpInfo.flagSharedKit().commitFlagp = nullptr;
|
||||||
|
vscpInfo.flagSharedKit().commitIfp = nullptr;
|
||||||
}
|
}
|
||||||
void convertSchemeFlagShared(AstAssignDly* nodep, AstVarScope* vscp, VarScopeInfo& vscpInfo) {
|
void convertSchemeFlagShared(AstAssignDly* nodep, AstVarScope* vscp, VarScopeInfo& vscpInfo) {
|
||||||
UASSERT_OBJ(vscpInfo.m_scheme == Scheme::FlagShared, vscp, "Inconsistent NBA scheme");
|
UASSERT_OBJ(vscpInfo.m_scheme == Scheme::FlagShared, vscp, "Inconsistent NBA scheme");
|
||||||
|
|
@ -443,14 +447,16 @@ class DelayedVisitor final : public VNVisitor {
|
||||||
const bool consecutive = nodep == m_nextDlyp;
|
const bool consecutive = nodep == m_nextDlyp;
|
||||||
m_nextDlyp = VN_CAST(nodep->nextp(), AssignDly);
|
m_nextDlyp = VN_CAST(nodep->nextp(), AssignDly);
|
||||||
|
|
||||||
|
VarScopeInfo* const prevVscpInfop = consecutive ? &m_vscpInfo(m_prevVscp) : nullptr;
|
||||||
|
|
||||||
// We can reuse the flag of the previous assignment if:
|
// We can reuse the flag of the previous assignment if:
|
||||||
const bool reuseTheFlag =
|
const bool reuseTheFlag =
|
||||||
// Consecutive NBAs
|
// Consecutive NBAs
|
||||||
consecutive
|
consecutive
|
||||||
// ... that use the same scheme
|
// ... that use the same scheme
|
||||||
&& m_vscpInfo(m_prevVscp).m_scheme == Scheme::FlagShared
|
&& prevVscpInfop->m_scheme == Scheme::FlagShared
|
||||||
// ... and share the same overall update domain
|
// ... and share the same overall update domain
|
||||||
&& m_vscpInfo(m_prevVscp).senTreep()->sameTree(vscpInfo.senTreep());
|
&& prevVscpInfop->senTreep()->sameTree(vscpInfo.senTreep());
|
||||||
|
|
||||||
if (!reuseTheFlag) {
|
if (!reuseTheFlag) {
|
||||||
// Create new flag
|
// Create new flag
|
||||||
|
|
@ -466,10 +472,25 @@ class DelayedVisitor final : public VNVisitor {
|
||||||
// Add the 'Post' scheduled commit
|
// Add the 'Post' scheduled commit
|
||||||
AstIf* const ifp = new AstIf{flp, new AstVarRef{flp, flagVscp, VAccess::READ}};
|
AstIf* const ifp = new AstIf{flp, new AstVarRef{flp, flagVscp, VAccess::READ}};
|
||||||
vscpInfo.flagSharedKit().postp->addStmtsp(ifp);
|
vscpInfo.flagSharedKit().postp->addStmtsp(ifp);
|
||||||
|
vscpInfo.flagSharedKit().commitFlagp = flagVscp;
|
||||||
vscpInfo.flagSharedKit().commitIfp = ifp;
|
vscpInfo.flagSharedKit().commitIfp = ifp;
|
||||||
} else {
|
} else {
|
||||||
// Reuse the commit block of the previous assignment
|
if (vscp != m_prevVscp) {
|
||||||
vscpInfo.flagSharedKit().commitIfp = m_vscpInfo(m_prevVscp).flagSharedKit().commitIfp;
|
// Different variable, ensure the commit block exists for this variable,
|
||||||
|
// can reuse existing one with the same flag, otherwise create a new one.
|
||||||
|
AstVarScope* const flagVscp = prevVscpInfop->flagSharedKit().commitFlagp;
|
||||||
|
UASSERT_OBJ(flagVscp, nodep, "Commit flag of previous assignment should exist");
|
||||||
|
if (vscpInfo.flagSharedKit().commitFlagp != flagVscp) {
|
||||||
|
AstIf* const ifp = new AstIf{flp, new AstVarRef{flp, flagVscp, VAccess::READ}};
|
||||||
|
vscpInfo.flagSharedKit().postp->addStmtsp(ifp);
|
||||||
|
vscpInfo.flagSharedKit().commitFlagp = flagVscp;
|
||||||
|
vscpInfo.flagSharedKit().commitIfp = ifp;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Same variable, reuse the commit block of the previous assignment
|
||||||
|
vscpInfo.flagSharedKit().commitFlagp = prevVscpInfop->flagSharedKit().commitFlagp;
|
||||||
|
vscpInfo.flagSharedKit().commitIfp = prevVscpInfop->flagSharedKit().commitIfp;
|
||||||
|
}
|
||||||
++m_nSharedSetFlags;
|
++m_nSharedSetFlags;
|
||||||
}
|
}
|
||||||
// Commit the captured value to the captured destination
|
// Commit the captured value to the captured destination
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,7 @@ class DescopeVisitor final : public VNVisitor {
|
||||||
string name = scopep->name();
|
string name = scopep->name();
|
||||||
string::size_type pos;
|
string::size_type pos;
|
||||||
if ((pos = name.rfind('.')) != string::npos) name.erase(0, pos + 1);
|
if ((pos = name.rfind('.')) != string::npos) name.erase(0, pos + 1);
|
||||||
ret.thisPtr = VSelfPointerText{VSelfPointerText::This(), name};
|
ret.thisPtr = VSelfPointerText{VSelfPointerText::This{}, name};
|
||||||
}
|
}
|
||||||
return ret.thisPtr;
|
return ret.thisPtr;
|
||||||
}
|
}
|
||||||
|
|
@ -104,9 +104,9 @@ class DescopeVisitor final : public VNVisitor {
|
||||||
if (VN_IS(scopep->modp(), Class)) {
|
if (VN_IS(scopep->modp(), Class)) {
|
||||||
// Direct reference to class members are from within the class itself, references from
|
// Direct reference to class members are from within the class itself, references from
|
||||||
// outside the class must go via AstMemberSel
|
// outside the class must go via AstMemberSel
|
||||||
return VSelfPointerText{VSelfPointerText::This()};
|
return VSelfPointerText{VSelfPointerText::This{}};
|
||||||
} else if (relativeRefOk && scopep == m_scopep) {
|
} else if (relativeRefOk && scopep == m_scopep) {
|
||||||
return VSelfPointerText{VSelfPointerText::This()};
|
return VSelfPointerText{VSelfPointerText::This{}};
|
||||||
} else if (relativeRefOk && !m_modSingleton && scopep->aboveScopep() == m_scopep
|
} else if (relativeRefOk && !m_modSingleton && scopep->aboveScopep() == m_scopep
|
||||||
&& VN_IS(scopep->modp(), Module)) {
|
&& VN_IS(scopep->modp(), Module)) {
|
||||||
// Reference to scope of instance directly under this module, can just "this->cell",
|
// Reference to scope of instance directly under this module, can just "this->cell",
|
||||||
|
|
@ -215,9 +215,9 @@ class DescopeVisitor final : public VNVisitor {
|
||||||
makePublicFuncWrappers();
|
makePublicFuncWrappers();
|
||||||
}
|
}
|
||||||
void visit(AstScope* nodep) override {
|
void visit(AstScope* nodep) override {
|
||||||
|
VL_RESTORER(m_scopep);
|
||||||
m_scopep = nodep;
|
m_scopep = nodep;
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
m_scopep = nullptr;
|
|
||||||
}
|
}
|
||||||
void visit(AstVarScope* nodep) override {
|
void visit(AstVarScope* nodep) override {
|
||||||
// Delete the varscope when we're finished
|
// Delete the varscope when we're finished
|
||||||
|
|
|
||||||
|
|
@ -193,7 +193,7 @@ void DfgGraph::dumpDotFile(const string& filename, const string& label) const {
|
||||||
// This generates a file used by graphviz, https://www.graphviz.org
|
// This generates a file used by graphviz, https://www.graphviz.org
|
||||||
// "hardcoded" parameters:
|
// "hardcoded" parameters:
|
||||||
const std::unique_ptr<std::ofstream> os{V3File::new_ofstream(filename)};
|
const std::unique_ptr<std::ofstream> os{V3File::new_ofstream(filename)};
|
||||||
if (os->fail()) v3fatal("Cannot write to file: " << filename);
|
if (os->fail()) v3fatal("Can't write file: " << filename);
|
||||||
dumpDot(*os.get(), label);
|
dumpDot(*os.get(), label);
|
||||||
os->close();
|
os->close();
|
||||||
}
|
}
|
||||||
|
|
@ -244,7 +244,7 @@ void DfgGraph::dumpDotUpstreamCone(const string& fileName, const DfgVertex& vtx,
|
||||||
const string& name) const {
|
const string& name) const {
|
||||||
// Open output file
|
// Open output file
|
||||||
const std::unique_ptr<std::ofstream> os{V3File::new_ofstream(fileName)};
|
const std::unique_ptr<std::ofstream> os{V3File::new_ofstream(fileName)};
|
||||||
if (os->fail()) v3fatal("Cannot write to file: " << fileName);
|
if (os->fail()) v3fatal("Can't write file: " << fileName);
|
||||||
|
|
||||||
// Header
|
// Header
|
||||||
*os << "digraph dfg {\n";
|
*os << "digraph dfg {\n";
|
||||||
|
|
@ -278,7 +278,7 @@ void DfgGraph::dumpDotAllVarConesPrefixed(const string& label) const {
|
||||||
const string coneName{prefix + sinkp->varp()->name()};
|
const string coneName{prefix + sinkp->varp()->name()};
|
||||||
const string fileName{v3Global.debugFilename(coneName) + ".dot"};
|
const string fileName{v3Global.debugFilename(coneName) + ".dot"};
|
||||||
const std::unique_ptr<std::ofstream> os{V3File::new_ofstream(fileName)};
|
const std::unique_ptr<std::ofstream> os{V3File::new_ofstream(fileName)};
|
||||||
if (os->fail()) v3fatal("Cannot write to file: " << fileName);
|
if (os->fail()) v3fatal("Can't write file: " << fileName);
|
||||||
|
|
||||||
// Header
|
// Header
|
||||||
*os << "digraph dfg {\n";
|
*os << "digraph dfg {\n";
|
||||||
|
|
|
||||||
|
|
@ -199,7 +199,7 @@ class DfgToAstVisitor final : DfgVisitor {
|
||||||
|
|
||||||
// VISITORS
|
// VISITORS
|
||||||
void visit(DfgVertex* vtxp) override { // LCOV_EXCL_START
|
void visit(DfgVertex* vtxp) override { // LCOV_EXCL_START
|
||||||
vtxp->v3fatal("Unhandled DfgVertex: " << vtxp->typeName());
|
vtxp->v3fatalSrc("Unhandled DfgVertex: " << vtxp->typeName());
|
||||||
} // LCOV_EXCL_STOP
|
} // LCOV_EXCL_STOP
|
||||||
|
|
||||||
void visit(DfgVarPacked* vtxp) override {
|
void visit(DfgVarPacked* vtxp) override {
|
||||||
|
|
|
||||||
|
|
@ -85,7 +85,7 @@ V3DfgOptimizationContext::~V3DfgOptimizationContext() {
|
||||||
+ "__stats_dfg_patterns__" + ident + ".txt";
|
+ "__stats_dfg_patterns__" + ident + ".txt";
|
||||||
// Open, write, close
|
// Open, write, close
|
||||||
const std::unique_ptr<std::ofstream> ofp{V3File::new_ofstream(filename)};
|
const std::unique_ptr<std::ofstream> ofp{V3File::new_ofstream(filename)};
|
||||||
if (ofp->fail()) v3fatal("Can't write " << filename);
|
if (ofp->fail()) v3fatal("Can't write file: " << filename);
|
||||||
m_patternStats.dump(m_label, *ofp);
|
m_patternStats.dump(m_label, *ofp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue