mirror of
https://github.com/verilator/verilator.git
synced 2026-10-02 16:13:34 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
484b76e5b3 | ||
|
|
801d850724 | ||
|
|
769c0fa318 | ||
|
|
a11700271f | ||
|
|
6d80e8f856 | ||
|
|
f57c72e5db | ||
|
|
7eeb930c72 | ||
|
|
5b280c1911 | ||
|
|
1a073fbf5e | ||
|
|
83d978c2cd | ||
|
|
a17e2375b3 | ||
|
|
c0a6858c42 | ||
|
|
7a18adc716 | ||
|
|
bd602d0e2d | ||
|
|
72b2df30f8 | ||
|
|
d6c5d31dcd | ||
|
|
84c323188e | ||
|
|
cbd1bd5dad | ||
|
|
97255dc835 | ||
|
|
9f8b17230a | ||
|
|
93476a7372 | ||
|
|
b8b9170f9d | ||
|
|
575539996b | ||
|
|
922eab5f93 | ||
|
|
b7a533109d | ||
|
|
941e5c659a | ||
|
|
e37a93bffb | ||
|
|
6e3de7bfd1 | ||
|
|
1124829500 | ||
|
|
4096dee598 | ||
|
|
36f41e08a5 | ||
|
|
28ff71b1bf | ||
|
|
db276946b4 | ||
|
|
beb03be731 | ||
|
|
b93e409f0e | ||
|
|
788de3ad24 | ||
|
|
cb4ddd3213 | ||
|
|
7e94b3a4fa | ||
|
|
ca9bdc6e70 | ||
|
|
37ebc6e634 | ||
|
|
457e926168 | ||
|
|
ec4e408b2b | ||
|
|
a16ebaf79c | ||
|
|
1e34ae31d2 | ||
|
|
43811821d6 | ||
|
|
3797b5bca1 | ||
|
|
7deac509c6 | ||
|
|
c39a8b439a | ||
|
|
d0c4aee7b5 | ||
|
|
a88965a124 | ||
|
|
c18cbca813 | ||
|
|
e4eab56495 | ||
|
|
deb5531e54 | ||
|
|
9bb353c577 | ||
|
|
a816c2b75e | ||
|
|
ff702174d8 | ||
|
|
d5d6598d75 | ||
|
|
0abf18f618 | ||
|
|
6adda241c9 | ||
|
|
ce9293fcb3 | ||
|
|
d6168f654e | ||
|
|
738ee3d4eb | ||
|
|
b75901b3eb | ||
|
|
f98782c061 | ||
|
|
3039735648 | ||
|
|
c00c26c705 | ||
|
|
084ba6711b | ||
|
|
c54360485e | ||
|
|
d9ef4ac435 | ||
|
|
176cc5a196 | ||
|
|
7821da6ad5 | ||
|
|
5ee30e271e | ||
|
|
4ce48788c5 | ||
|
|
3590f7e206 | ||
|
|
882b310897 | ||
|
|
82fc142c1c | ||
|
|
5898c22b3b | ||
|
|
13e88106da | ||
|
|
457d1a66f2 | ||
|
|
b04a1caeac | ||
|
|
53c4c7d540 | ||
|
|
fb689bbb19 | ||
|
|
e2e3cc8463 | ||
|
|
6061744c4d | ||
|
|
8e25d2c61d | ||
|
|
18f8c8a14f | ||
|
|
44765e03a3 | ||
|
|
3f119f5647 | ||
|
|
517fdb7587 | ||
|
|
0ca72f8098 | ||
|
|
28d139149a | ||
|
|
81ce2cbc05 | ||
|
|
d7af6436a2 | ||
|
|
c80ca8d03e | ||
|
|
93304f3b82 | ||
|
|
30546afdab | ||
|
|
82d8fe0c27 | ||
|
|
4db673b2ff | ||
|
|
a5fa468343 | ||
|
|
2df1b72ce2 | ||
|
|
2998890647 | ||
|
|
8e178ca4a9 | ||
|
|
d94a8a28fa | ||
|
|
9a32158b5e | ||
|
|
b15dd3f898 | ||
|
|
af0e535015 | ||
|
|
5b2844e1be | ||
|
|
53ce708294 | ||
|
|
a1322635fd | ||
|
|
ab4ad9965c | ||
|
|
2273fa62d9 | ||
|
|
cca874dc83 | ||
|
|
274475aefd | ||
|
|
a91cf18d09 | ||
|
|
a7723ee9a5 | ||
|
|
28ee80c310 | ||
|
|
26da90ffce | ||
|
|
9eb211a8d4 | ||
|
|
75c2884fea | ||
|
|
f49f86c7ce | ||
|
|
a1989161d8 | ||
|
|
f11fa61ecf | ||
|
|
9a904b97b2 | ||
|
|
7d05be802d | ||
|
|
5e7b0d526d | ||
|
|
ff3d35ca61 | ||
|
|
c23de458ed | ||
|
|
90e0c9bdcd | ||
|
|
7892c5af13 | ||
|
|
0a0e4dce09 | ||
|
|
8e06b1e925 | ||
|
|
a15540dfdd | ||
|
|
3c680ddf22 | ||
|
|
47eeef485d | ||
|
|
251812638d | ||
|
|
cf7ea06b5d | ||
|
|
cd248f6bd7 | ||
|
|
b32d530000 | ||
|
|
570631380b | ||
|
|
d5f88cbf78 | ||
|
|
74ef35d3b3 | ||
|
|
8b8ebb0e43 | ||
|
|
301b4ff1ad | ||
|
|
5476ff93e2 | ||
|
|
375ea169b9 | ||
|
|
9c2785b49b | ||
|
|
8582aed66a | ||
|
|
9bd5cd4ef3 | ||
|
|
f858dd44ac | ||
|
|
e69736124f | ||
|
|
f0e691a1b8 | ||
|
|
5fb834e41e | ||
|
|
7f6d4ac359 | ||
|
|
666d0ab552 | ||
|
|
b9f2400d17 | ||
|
|
85b2c6b6c7 | ||
|
|
73a7595335 | ||
|
|
38c6085f54 | ||
|
|
b350b6a0ff | ||
|
|
80564a8f89 | ||
|
|
016611021d | ||
|
|
fa20614277 | ||
|
|
1e69167191 | ||
|
|
faa5edc068 | ||
|
|
e3c32adad4 | ||
|
|
b054d937cb | ||
|
|
212e8fb14b | ||
|
|
014e43f0ef | ||
|
|
d21b4e3fc7 | ||
|
|
0818d88113 | ||
|
|
77ec2dc875 | ||
|
|
665e8edaff | ||
|
|
67103d346b | ||
|
|
aebb54444e | ||
|
|
a54ac52a35 | ||
|
|
aa360052a8 | ||
|
|
e09f039a36 | ||
|
|
ff262fc4fb | ||
|
|
9a9931fb9d | ||
|
|
30686d8550 | ||
|
|
05f3fd7c6e | ||
|
|
e14319b401 | ||
|
|
1299b70945 | ||
|
|
cf2810db8b | ||
|
|
d77beecc6e | ||
|
|
0c6bd42da3 | ||
|
|
5091298fae | ||
|
|
cef7610b14 | ||
|
|
ed268805ce | ||
|
|
123d1af29d | ||
|
|
cc307626c0 | ||
|
|
963fd0664d | ||
|
|
4643d6e883 | ||
|
|
d89fc05da1 | ||
|
|
84d7380588 | ||
|
|
04febb1944 | ||
|
|
d56b923eaa | ||
|
|
a37866ee92 | ||
|
|
1a92a44c7d | ||
|
|
60a1d25a96 | ||
|
|
ad21f2e850 | ||
|
|
ffbae97a3d | ||
|
|
380137a402 | ||
|
|
ac2058c7ec | ||
|
|
de931d6a97 | ||
|
|
f2d8e45d72 | ||
|
|
085ef5fc05 | ||
|
|
6095efd84e | ||
|
|
114ab1378f | ||
|
|
8622c754b7 | ||
|
|
bf24fa9478 | ||
|
|
e1c45440fc | ||
|
|
b0cb43b2f2 | ||
|
|
dc1f44840d | ||
|
|
fd21a41acd | ||
|
|
cf09a9b6d2 | ||
|
|
dc306cf371 | ||
|
|
35374f09b4 | ||
|
|
e85a2e860e | ||
|
|
103ba1fb6d | ||
|
|
b684995292 | ||
|
|
c371a63d41 | ||
|
|
0102efd4ea | ||
|
|
abfee1270f | ||
|
|
5992d678be | ||
|
|
b6ded59c2b | ||
|
|
c0888c1b0f | ||
|
|
fa77141519 | ||
|
|
b3760911e7 | ||
|
|
b500e57991 | ||
|
|
19e4013ab5 | ||
|
|
82b2af3b83 | ||
|
|
e6f7510895 | ||
|
|
2f718b9ea0 | ||
|
|
899e7bacb2 | ||
|
|
5b3717b369 | ||
|
|
1e7c61b23e | ||
|
|
0e1e380a55 | ||
|
|
1b0a48ea02 | ||
|
|
70b3a599ce | ||
|
|
26c0e6ba00 | ||
|
|
efc6fb7fc3 | ||
|
|
b68038a73f | ||
|
|
f4ef4ad9f3 | ||
|
|
f6f7684ccd | ||
|
|
e74cc32f2d | ||
|
|
c64cc989f0 | ||
|
|
f94fcaa8e4 | ||
|
|
297b297bc7 | ||
|
|
02cb3d17a2 | ||
|
|
c3cfaf55ed | ||
|
|
3e7013af31 | ||
|
|
f7a5883205 | ||
|
|
5d3482734a | ||
|
|
e8c03650ae | ||
|
|
7eac788306 | ||
|
|
6a58e67699 | ||
|
|
b49be06a5a | ||
|
|
87b2adb6a1 | ||
|
|
5634a18f78 | ||
|
|
b84c9bb4c0 | ||
|
|
6dfce882a1 | ||
|
|
79d33bf1ee | ||
|
|
44eb362a18 | ||
|
|
8664aac225 | ||
|
|
6965e138aa | ||
|
|
fc52fb9093 | ||
|
|
cef7708f38 | ||
|
|
438fb01665 | ||
|
|
67d5b1a11a | ||
|
|
d78941885b | ||
|
|
6e7b07c794 | ||
|
|
9655e287ab | ||
|
|
917ca2bad7 | ||
|
|
c3f5dd7414 | ||
|
|
04c7fd1696 | ||
|
|
152689776d | ||
|
|
778f133118 | ||
|
|
ff5465308b | ||
|
|
602750b1ee | ||
|
|
2a24bb4759 | ||
|
|
7c4259bc0a | ||
|
|
1c2384cb3d | ||
|
|
75881754a9 | ||
|
|
0505816d31 | ||
|
|
48bcf66ac7 | ||
|
|
0145d9d514 | ||
|
|
2ce86eddfa | ||
|
|
b663d1a230 | ||
|
|
5821048df7 | ||
|
|
80284c437e | ||
|
|
2aedc91151 | ||
|
|
c1e8337fc1 | ||
|
|
1858cc8ff1 | ||
|
|
5e6aca59ab | ||
|
|
726e78fdda | ||
|
|
085e8454b8 | ||
|
|
85b05366bc | ||
|
|
e6b0479b80 | ||
|
|
3a53b32a32 | ||
|
|
cf7b5c091a | ||
|
|
51b0963e61 | ||
|
|
0c949ceba2 | ||
|
|
5c070558ae | ||
|
|
0c328b6eaf | ||
|
|
f670eccf8c | ||
|
|
23140aeff0 | ||
|
|
d44426b3f3 | ||
|
|
05ff96bea3 | ||
|
|
77ac9bfcc6 | ||
|
|
34b8ed4cf0 | ||
|
|
95d1272269 | ||
|
|
046c0a7aa1 | ||
|
|
835905bdae | ||
|
|
51d1235cda | ||
|
|
2f21b3385a | ||
|
|
9d0a7d5e70 | ||
|
|
4cec3ff2a0 | ||
|
|
25593c0ee2 | ||
|
|
5d3dd52f13 | ||
|
|
ec36d0d772 | ||
|
|
3d2503f9aa | ||
|
|
4576644591 | ||
|
|
d8df216a8d | ||
|
|
964dcd5b7c | ||
|
|
f62c070d06 | ||
|
|
a56e0a6e89 | ||
|
|
451e961e03 | ||
|
|
cb550e5357 | ||
|
|
829db3eefa | ||
|
|
44f938e507 | ||
|
|
4849c0530b | ||
|
|
f4ed367850 | ||
|
|
d4df94d866 | ||
|
|
5d8019f941 | ||
|
|
48597bebaf | ||
|
|
470859f929 |
+1
-1
@@ -1,4 +1,4 @@
|
||||
Checks: 'clang-diagnostic-*,clang-analyzer-*,*,-modernize*,-hicpp*,-android-cloexec-fopen,-cert-dcl50-cpp,-cert-env33-c,-cert-err34-c,-cert-err58-cpp,-clang-analyzer-core.UndefinedBinaryOperatorResult,-clang-analyzer-security*,-cppcoreguidelines-no-malloc,-cppcoreguidelines-owning-memory,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-cppcoreguidelines-pro-bounds-constant-array-index,-cppcoreguidelines-pro-bounds-pointer-arithmetic,-cppcoreguidelines-pro-type-const-cast,-cppcoreguidelines-pro-type-reinterpret-cast,-cppcoreguidelines-pro-type-static-cast-downcast,-cppcoreguidelines-pro-type-union-access,-cppcoreguidelines-pro-type-vararg,-cppcoreguidelines-special-member-functions,-fuchsia-default-arguments,-fuchsia-overloaded-operator,-google-default-arguments,-google-readability-todo,-google-runtime-references,-llvm-header-guard,-llvm-include-order,-misc-string-integer-assignment,-misc-string-literal-with-embedded-nul,-readability-braces-around-statements,-readability-container-size-empty,-readability-delete-null-pointer,-readability-else-after-return,-readability-implicit-bool-conversion,-readability-named-parameter,-readability-static-accessed-through-instance'
|
||||
Checks: '*,-hicpp*,-android-cloexec-fopen,-cert-dcl50-cpp,-cert-env33-c,-cert-err34-c,-cert-err58-cpp,-clang-analyzer-core.UndefinedBinaryOperatorResult,-clang-analyzer-security*,-cppcoreguidelines-avoid-magic-numbers,-cppcoreguidelines-no-malloc,-cppcoreguidelines-owning-memory,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-cppcoreguidelines-pro-bounds-constant-array-index,-cppcoreguidelines-pro-bounds-pointer-arithmetic,-cppcoreguidelines-pro-type-const-cast,-cppcoreguidelines-pro-type-reinterpret-cast,-cppcoreguidelines-pro-type-static-cast-downcast,-cppcoreguidelines-pro-type-union-access,-cppcoreguidelines-pro-type-vararg,-cppcoreguidelines-special-member-functions,-fuchsia-*,-google-default-arguments,-google-readability-todo,-google-runtime-references,-llvm-header-guard,-llvm-include-order,-misc-string-integer-assignment,-misc-string-literal-with-embedded-nul,-modernize-use-auto,-modernize-use-trailing-return-type,-readability-braces-around-statements,-readability-container-size-empty,-readability-delete-null-pointer,-readability-else-after-return,-readability-implicit-bool-conversion,-readability-named-parameter,-readability-static-accessed-through-instance'
|
||||
WarningsAsErrors: ''
|
||||
HeaderFilterRegex: ''
|
||||
FormatStyle: none
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Something isn't working as expected, and it isn't "Unsupported." (Note our contributor agreement at https://github.com/verilator/verilator/.github/blob/master/CONTRIBUTING.adoc)
|
||||
about: Something isn't working as expected, and it isn't "Unsupported." (Note our contributor agreement at https://github.com/verilator/verilator/blob/master/docs/CONTRIBUTING.adoc)
|
||||
title: ''
|
||||
labels: new
|
||||
assignees: ''
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: Feature Request
|
||||
about: Request something should be supported, or a new feature added. (Note our contributor agreement at https://github.com/verilator/verilator/.github/blob/master/CONTRIBUTING.adoc)
|
||||
about: Request something should be supported, or a new feature added. (Note our contributor agreement at https://github.com/verilator/verilator/blob/master/docs/CONTRIBUTING.adoc)
|
||||
title: ''
|
||||
labels: new
|
||||
assignees: ''
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: Q and A, or Other
|
||||
about: Ask a question, not related to a specific bug or feature request. (Note our contributor agreement at https://github.com/verilator/verilator/.github/blob/master/CONTRIBUTING.adoc)
|
||||
about: Ask a question, not related to a specific bug or feature request. (Note our contributor agreement at https://github.com/verilator/verilator/blob/master/docs/CONTRIBUTING.adoc)
|
||||
title: ''
|
||||
labels: new
|
||||
assignees: ''
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
# DESCRIPTION: Github actions config
|
||||
# This name is key to badges in README.adoc, so we use the name build
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
name: build
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '0 0 * * 0' # weekly
|
||||
|
||||
env:
|
||||
CI_OS_NAME: linux
|
||||
CI_COMMIT: ${{ github.sha }}
|
||||
CCACHE_COMPRESS: 1
|
||||
CCACHE_DIR: ${{ github.workspace }}/.ccache
|
||||
CCACHE_MAXSIZE: 2Gi # 2GiB for clang and gcc, 4GiB in total
|
||||
|
||||
jobs:
|
||||
|
||||
|
||||
Matrix:
|
||||
runs-on: ubuntu-latest
|
||||
name: Generate Build matrix
|
||||
outputs:
|
||||
matrix: ${{ steps.generate.outputs.matrix }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- id: generate
|
||||
name: Run 'generate_matrix.sh'
|
||||
run: |
|
||||
if [ '${{ github.event_name}}' = 'pull_request' ]; then
|
||||
matrix='[ "ubuntu-20.04" ]'
|
||||
else
|
||||
matrix='[ "ubuntu-16.04", "ubuntu-18.04", "ubuntu-20.04" ]'
|
||||
fi
|
||||
echo "::set-output name=matrix::$matrix"
|
||||
|
||||
|
||||
Build:
|
||||
needs: Matrix
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: ${{ fromJson(needs.Matrix.outputs.matrix) }}
|
||||
debug: [ opt, dbg ]
|
||||
compiler:
|
||||
- { cc: clang, cxx: clang++ }
|
||||
- { cc: gcc, cxx: g++ }
|
||||
runs-on: ${{ matrix.os }}
|
||||
name: Build | ${{ matrix.os }} | ${{ matrix.compiler.cc }} | ${{ matrix.debug }}
|
||||
env:
|
||||
CI_BUILD_STAGE_NAME: build
|
||||
CI_RUNS_ON: ${{ matrix.os }}
|
||||
CI_MAKE_SRC_TARGET: ${{ matrix.debug }}
|
||||
CC: ${{ matrix.compiler.cc }}
|
||||
CXX: ${{ matrix.compiler.cxx }}
|
||||
CACHE_KEY: ${{ matrix.os }}-${{ matrix.compiler.cc }}
|
||||
steps:
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Cache
|
||||
uses: actions/cache@v2
|
||||
env:
|
||||
cache-name: ccache
|
||||
with:
|
||||
path: ${{ github.workspace }}/.ccache
|
||||
key: ${{ env.CACHE_KEY }}-${{ env.cache-name }}-${{ github.sha }}
|
||||
restore-keys: ${{ env.CACHE_KEY }}-${{ env.cache-name }}
|
||||
|
||||
- name: Install packages for build
|
||||
run: ./ci/ci-install.bash
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
./ci/ci-script.bash
|
||||
tar cvzf verilator-${{ matrix.os}}-${CI_COMMIT}-${{ matrix.compiler.cc }}-${{ matrix.debug }}.tgz ./bin
|
||||
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
path: verilator-${{ matrix.os}}-${{ env.CI_COMMIT }}-${{ matrix.compiler.cc }}-${{ matrix.debug }}.tgz
|
||||
|
||||
|
||||
Test:
|
||||
needs: [ Matrix, Build ]
|
||||
strategy:
|
||||
fail-fast: false
|
||||
max-parallel: 8
|
||||
matrix:
|
||||
os: ${{ fromJson(needs.Matrix.outputs.matrix) }}
|
||||
compiler:
|
||||
- { cc: clang, cxx: clang++ }
|
||||
- { cc: gcc, cxx: g++ }
|
||||
suite:
|
||||
- dist-vlt-0
|
||||
- dist-vlt-1
|
||||
- vltmt-0
|
||||
- vltmt-1
|
||||
runs-on: ${{ matrix.os }}
|
||||
name: Test | ${{ matrix.os }} | ${{ matrix.compiler.cc }} | ${{ matrix.suite }}
|
||||
env:
|
||||
CI_BUILD_STAGE_NAME: test
|
||||
CI_RUNS_ON: ${{ matrix.os }}
|
||||
CC: ${{ matrix.compiler.cc }}
|
||||
CXX: ${{ matrix.compiler.cxx }}
|
||||
CACHE_KEY: ${{ matrix.os }}-${{ matrix.compiler.cc }}
|
||||
steps:
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Cache
|
||||
uses: actions/cache@v2
|
||||
env:
|
||||
cache-name: ccache
|
||||
with:
|
||||
path: ${{ github.workspace }}/.ccache
|
||||
key: ${{ env.CACHE_KEY }}-${{ env.cache-name }}-${{ github.sha }}
|
||||
restore-keys: ${{ env.CACHE_KEY }}-${{ env.cache-name }}
|
||||
|
||||
- uses: actions/download-artifact@v2
|
||||
|
||||
- name: Install Verilator and test dependencies
|
||||
run: |
|
||||
tar xvzf artifact/verilator-${{ matrix.os}}-${CI_COMMIT}-${{ matrix.compiler.cc }}-opt.tgz
|
||||
tar xvzf artifact/verilator-${{ matrix.os}}-${CI_COMMIT}-${{ matrix.compiler.cc }}-dbg.tgz
|
||||
rm -rf artifact
|
||||
./ci/ci-install.bash
|
||||
|
||||
- name: Test
|
||||
env:
|
||||
TESTS: ${{ matrix.suite }}
|
||||
run: ./ci/ci-script.bash
|
||||
@@ -0,0 +1,44 @@
|
||||
# DESCRIPTION: Github actions config
|
||||
# This name is key to badges in README.adoc, so we use the name build
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
name: clang-format
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request_target:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
format:
|
||||
runs-on: ubuntu-20.04
|
||||
name: Ubuntu 20.04 | format
|
||||
env:
|
||||
CI_OS_NAME: linux
|
||||
CI_RUNS_ON: ubuntu-20.04
|
||||
CI_COMMIT: ${{ github.sha }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Install packages for build
|
||||
env:
|
||||
CI_BUILD_STAGE_NAME: build
|
||||
run: |
|
||||
bash ci/ci-install.bash &&
|
||||
sudo apt-get install clang-10 yapf3 &&
|
||||
git config --global user.email "[email protected]" &&
|
||||
git config --global user.name "github action"
|
||||
- name: Format code
|
||||
run: |
|
||||
autoconf &&
|
||||
./configure &&
|
||||
make -j 2 format CLANGFORMAT=clang-format-10 &&
|
||||
git status
|
||||
- name: Push
|
||||
run: |
|
||||
if [ -n "$(git status --porcelain)" ]; then
|
||||
git commit . -m "Apply clang-format" &&
|
||||
git push origin
|
||||
fi
|
||||
@@ -0,0 +1,17 @@
|
||||
# DESCRIPTION: Github actions config
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
name: Contributor Agreement
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
Test:
|
||||
name: "'docs/CONTRIBUTORS' was signed"
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- run: test_regress/t/t_dist_contributors.pl
|
||||
@@ -0,0 +1,98 @@
|
||||
# DESCRIPTION: Github actions config
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
name: coverage
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '0 0 * * 0' # weekly
|
||||
|
||||
env:
|
||||
CI_OS_NAME: linux
|
||||
CI_COMMIT: ${{ github.sha }}
|
||||
CCACHE_COMPRESS: 1
|
||||
CCACHE_DIR: ${{ github.workspace }}/.ccache
|
||||
CCACHE_MAXSIZE: 2Gi # 2GiB for clang and gcc, 4GiB in total
|
||||
COVERAGE: 1
|
||||
|
||||
jobs:
|
||||
|
||||
|
||||
Build:
|
||||
runs-on: ubuntu-20.04
|
||||
env:
|
||||
CI_BUILD_STAGE_NAME: build
|
||||
steps:
|
||||
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- uses: actions/cache@v2
|
||||
env:
|
||||
cache-name: ccache
|
||||
with:
|
||||
path: ${{ github.workspace }}/.ccache
|
||||
key: coverage-${{ env.cache-name }}-${{ github.sha }}
|
||||
restore-keys: coverage-${{ env.cache-name }}
|
||||
|
||||
- name: Install dependencies for build
|
||||
env:
|
||||
CI_BUILD_STAGE_NAME: build
|
||||
run: ./ci/ci-install.bash
|
||||
|
||||
- name: Build Verilator
|
||||
run: |
|
||||
./ci/ci-script.bash
|
||||
|
||||
mkdir tarball/
|
||||
cp -vr bin tarball/
|
||||
cp -vr src/obj*/*.gcno tarball/
|
||||
tar cvzf verilator-${CI_COMMIT}.tgz -C ./tarball .
|
||||
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
path: verilator-${{ env.CI_COMMIT }}.tgz
|
||||
|
||||
|
||||
Test:
|
||||
needs: Build
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
test:
|
||||
- vlt-
|
||||
- vltmt-
|
||||
num:
|
||||
- 0
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
include:
|
||||
- { test: dist, num: '' }
|
||||
name: test-${{ matrix.test }}${{ matrix.num }}
|
||||
runs-on: ubuntu-20.04
|
||||
env:
|
||||
CI_BUILD_STAGE_NAME: test
|
||||
steps:
|
||||
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- uses: actions/cache@v2
|
||||
env:
|
||||
cache-name: ccache
|
||||
with:
|
||||
path: ${{ github.workspace }}/.ccache
|
||||
key: coverage-${{ env.cache-name }}-${{ github.sha }}
|
||||
restore-keys: coverage-${{ env.cache-name }}
|
||||
|
||||
- uses: actions/download-artifact@v2
|
||||
|
||||
- name: Install Verilator and test dependencies
|
||||
run: |
|
||||
tar xvzf artifact/verilator-${CI_COMMIT}.tgz
|
||||
./ci/ci-install.bash
|
||||
|
||||
- name: Test
|
||||
env:
|
||||
TESTS: coverage-${{ matrix.test }}${{ matrix.num }}
|
||||
run: ./ci/ci-script.bash
|
||||
@@ -15,6 +15,8 @@
|
||||
*.tex
|
||||
*.pdf
|
||||
/Makefile
|
||||
/.ccache
|
||||
/artifact/
|
||||
README
|
||||
TAGS
|
||||
autom4te.cache
|
||||
|
||||
-149
@@ -1,149 +0,0 @@
|
||||
# DESCRIPTION: Travis-CI config
|
||||
#
|
||||
# Copyright 2003-2020 by Wilson Snyder. This program is free software; you
|
||||
# can redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
version: ~> 1.0
|
||||
|
||||
language: cpp
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/.ccache
|
||||
|
||||
env:
|
||||
global:
|
||||
- VERILATOR_ROOT=$TRAVIS_BUILD_DIR
|
||||
|
||||
# The list and order of build stages
|
||||
stages:
|
||||
- build # Build Verilator
|
||||
- test # Run tests
|
||||
|
||||
# Dump info about the environment for debugging
|
||||
before_install:
|
||||
# To dump the script that Travis itself is executing, add 'cat $0' here
|
||||
- cd "$TRAVIS_BUILD_DIR" # Skipping the git clone in later stages requires this
|
||||
- export CCACHE_MAXSIZE=$(ci/travis-ccache-size.bash) # Set here after the 'cd'
|
||||
- env | sort
|
||||
- ls -lA .
|
||||
- ls -lA bin
|
||||
- g++ -E -dM -c -x c++ /dev/null | sort
|
||||
- clang++ -E -dM -c -x c++ /dev/null | sort
|
||||
|
||||
# Install all dependencies
|
||||
# We run twice to attempt on failure to recover from temp network problems
|
||||
install:
|
||||
- ./ci/travis-install.bash || ./ci/travis-install.bash
|
||||
|
||||
before_script:
|
||||
# ccache maintenance
|
||||
- ./ci/travis-ccache-maint.bash
|
||||
# Don't produce core dumps (esp. on FreeBSD)
|
||||
- ulimit -c 0
|
||||
# On Focal, set the SystemC installation location
|
||||
- |
|
||||
if [ "$TRAVIS_DIST" = "focal" ] && [ "$M32" != "1" ]; then
|
||||
export SYSTEMC_INCLUDE=/usr/include
|
||||
export SYSTEMC_LIBDIR=/usr/lib/x86_64-linux-gnu
|
||||
fi
|
||||
# Override compiler for M32
|
||||
- |
|
||||
if [ "$M32" = "1" ]; then
|
||||
export CC="$CC -m32"
|
||||
export CXX="$CXX -m32"
|
||||
unset M32 # verilated.mk actually references $(M32) so unset
|
||||
fi
|
||||
|
||||
before_cache:
|
||||
- ccache -s -z
|
||||
|
||||
# All jobs run the same script
|
||||
script: ./ci/travis-script.bash
|
||||
|
||||
# Enumerate all the jobs
|
||||
jobs:
|
||||
include:
|
||||
############################################################################
|
||||
# Jobs in the 'build' stage
|
||||
############################################################################
|
||||
# GCC builds
|
||||
- {stage: build, if: type = cron, os: linux, dist: trusty, compiler: gcc, workspaces: {create: {name: trusty-gcc, paths: .}}}
|
||||
- {stage: build, if: type = cron, os: linux, dist: xenial, compiler: gcc, workspaces: {create: {name: xenial-gcc, paths: .}}}
|
||||
- {stage: build, if: type = cron, os: linux, dist: bionic, compiler: gcc, workspaces: {create: {name: bionic-gcc, paths: .}}}
|
||||
- {stage: build, os: linux, dist: focal, compiler: gcc, workspaces: {create: {name: focal-gcc, paths: .}}}
|
||||
# Clang builds
|
||||
- {stage: build, if: type = cron, os: linux, dist: xenial, compiler: clang, workspaces: {create: {name: xenial-clang, paths: .}}}
|
||||
- {stage: build, os: linux, dist: focal, compiler: clang, workspaces: {create: {name: focal-clang, paths: .}}}
|
||||
# Coverage build
|
||||
- {stage: build, if: type = cron, os: linux, dist: focal, compiler: gcc, workspaces: {create: {name: coverage, paths: .}}, env: COVERAGE=1}
|
||||
# 32-bit build
|
||||
- {stage: build, if: type = cron, os: linux, dist: focal, compiler: gcc, workspaces: {create: {name: focal-gcc-m32, paths: .}}, env: M32=1}
|
||||
# OS X build
|
||||
- {stage: build, if: type = cron, os: osx, osx_image: xcode11.6, compiler: clang, workspaces: {create: {name: osx-xcode11.6, paths: .}}}
|
||||
# FreeBSD build
|
||||
#- {stage: build, if: type = cron, os: freebsd, compiler: clang, workspaces: {create: {name: freebsd, paths: .}}}
|
||||
############################################################################
|
||||
# Jobs in the 'test' stage
|
||||
############################################################################
|
||||
# GCC tests
|
||||
- {stage: test, if: type = cron, os: linux, dist: trusty, compiler: gcc, workspaces: {use: trusty-gcc}, git: {clone: false}, env: TESTS=dist-vlt-0}
|
||||
- {stage: test, if: type = cron, os: linux, dist: trusty, compiler: gcc, workspaces: {use: trusty-gcc}, git: {clone: false}, env: TESTS=dist-vlt-1}
|
||||
- {stage: test, if: type = cron, os: linux, dist: trusty, compiler: gcc, workspaces: {use: trusty-gcc}, git: {clone: false}, env: TESTS=vltmt-0}
|
||||
- {stage: test, if: type = cron, os: linux, dist: trusty, compiler: gcc, workspaces: {use: trusty-gcc}, git: {clone: false}, env: TESTS=vltmt-1}
|
||||
- {stage: test, if: type = cron, os: linux, dist: xenial, compiler: gcc, workspaces: {use: xenial-gcc}, git: {clone: false}, env: TESTS=dist-vlt-0}
|
||||
- {stage: test, if: type = cron, os: linux, dist: xenial, compiler: gcc, workspaces: {use: xenial-gcc}, git: {clone: false}, env: TESTS=dist-vlt-1}
|
||||
- {stage: test, if: type = cron, os: linux, dist: xenial, compiler: gcc, workspaces: {use: xenial-gcc}, git: {clone: false}, env: TESTS=vltmt-0}
|
||||
- {stage: test, if: type = cron, os: linux, dist: xenial, compiler: gcc, workspaces: {use: xenial-gcc}, git: {clone: false}, env: TESTS=vltmt-1}
|
||||
- {stage: test, if: type = cron, os: linux, dist: bionic, compiler: gcc, workspaces: {use: bionic-gcc}, git: {clone: false}, env: TESTS=dist-vlt-0}
|
||||
- {stage: test, if: type = cron, os: linux, dist: bionic, compiler: gcc, workspaces: {use: bionic-gcc}, git: {clone: false}, env: TESTS=dist-vlt-1}
|
||||
- {stage: test, if: type = cron, os: linux, dist: bionic, compiler: gcc, workspaces: {use: bionic-gcc}, git: {clone: false}, env: TESTS=vltmt-0}
|
||||
- {stage: test, if: type = cron, os: linux, dist: bionic, compiler: gcc, workspaces: {use: bionic-gcc}, git: {clone: false}, env: TESTS=vltmt-1}
|
||||
- {stage: test, if: type != cron, os: linux, dist: focal, compiler: gcc, workspaces: {use: focal-gcc}, git: {clone: false}, env: TESTS=dist-vlt-0}
|
||||
- {stage: test, if: type != cron, os: linux, dist: focal, compiler: gcc, workspaces: {use: focal-gcc}, git: {clone: false}, env: TESTS=dist-vlt-1}
|
||||
- {stage: test, if: type = cron, os: linux, dist: focal, compiler: gcc, workspaces: {use: focal-gcc}, git: {clone: false}, env: TESTS=vltmt-0}
|
||||
- {stage: test, if: type = cron, os: linux, dist: focal, compiler: gcc, workspaces: {use: focal-gcc}, git: {clone: false}, env: TESTS=vltmt-1}
|
||||
# Clang tests
|
||||
- {stage: test, if: type = cron, os: linux, dist: xenial, compiler: clang, workspaces: {use: xenial-clang}, git: {clone: false}, env: TESTS=dist-vlt-0}
|
||||
- {stage: test, if: type = cron, os: linux, dist: xenial, compiler: clang, workspaces: {use: xenial-clang}, git: {clone: false}, env: TESTS=dist-vlt-1}
|
||||
- {stage: test, if: type = cron, os: linux, dist: xenial, compiler: clang, workspaces: {use: xenial-clang}, git: {clone: false}, env: TESTS=vltmt-0}
|
||||
- {stage: test, if: type = cron, os: linux, dist: xenial, compiler: clang, workspaces: {use: xenial-clang}, git: {clone: false}, env: TESTS=vltmt-1}
|
||||
- {stage: test, if: type = cron, os: linux, dist: focal, compiler: clang, workspaces: {use: focal-clang}, git: {clone: false}, env: TESTS=dist-vlt-0}
|
||||
- {stage: test, if: type = cron, os: linux, dist: focal, compiler: clang, workspaces: {use: focal-clang}, git: {clone: false}, env: TESTS=dist-vlt-1}
|
||||
- {stage: test, if: type != cron, os: linux, dist: focal, compiler: clang, workspaces: {use: focal-clang}, git: {clone: false}, env: TESTS=vltmt-0}
|
||||
- {stage: test, if: type != cron, os: linux, dist: focal, compiler: clang, workspaces: {use: focal-clang}, git: {clone: false}, env: TESTS=vltmt-1}
|
||||
# Coverage tests
|
||||
- {stage: test, if: type = cron, os: linux, dist: focal, compiler: gcc, workspaces: {use: coverage}, git: {clone: false}, env: TESTS=coverage-dist}
|
||||
- {stage: test, if: type = cron, os: linux, dist: focal, compiler: gcc, workspaces: {use: coverage}, git: {clone: false}, env: TESTS=coverage-vlt-0}
|
||||
- {stage: test, if: type = cron, os: linux, dist: focal, compiler: gcc, workspaces: {use: coverage}, git: {clone: false}, env: TESTS=coverage-vlt-1}
|
||||
- {stage: test, if: type = cron, os: linux, dist: focal, compiler: gcc, workspaces: {use: coverage}, git: {clone: false}, env: TESTS=coverage-vlt-2}
|
||||
- {stage: test, if: type = cron, os: linux, dist: focal, compiler: gcc, workspaces: {use: coverage}, git: {clone: false}, env: TESTS=coverage-vlt-3}
|
||||
- {stage: test, if: type = cron, os: linux, dist: focal, compiler: gcc, workspaces: {use: coverage}, git: {clone: false}, env: TESTS=coverage-vltmt-0}
|
||||
- {stage: test, if: type = cron, os: linux, dist: focal, compiler: gcc, workspaces: {use: coverage}, git: {clone: false}, env: TESTS=coverage-vltmt-1}
|
||||
- {stage: test, if: type = cron, os: linux, dist: focal, compiler: gcc, workspaces: {use: coverage}, git: {clone: false}, env: TESTS=coverage-vltmt-2}
|
||||
- {stage: test, if: type = cron, os: linux, dist: focal, compiler: gcc, workspaces: {use: coverage}, git: {clone: false}, env: TESTS=coverage-vltmt-3}
|
||||
# 32-bit tests
|
||||
- {stage: test, if: type = cron, os: linux, dist: focal, compiler: gcc, workspaces: {use: focal-gcc-m32}, git: {clone: false}, env: [M32=1, TESTS=dist-vlt-0]}
|
||||
- {stage: test, if: type = cron, os: linux, dist: focal, compiler: gcc, workspaces: {use: focal-gcc-m32}, git: {clone: false}, env: [M32=1, TESTS=dist-vlt-1]}
|
||||
- {stage: test, if: type = cron, os: linux, dist: focal, compiler: gcc, workspaces: {use: focal-gcc-m32}, git: {clone: false}, env: [M32=1, TESTS=vltmt-0]}
|
||||
- {stage: test, if: type = cron, os: linux, dist: focal, compiler: gcc, workspaces: {use: focal-gcc-m32}, git: {clone: false}, env: [M32=1, TESTS=vltmt-1]}
|
||||
# OS X tests
|
||||
- {stage: test, if: type = cron, os: osx, osx_image: xcode11.6, compiler: clang, workspaces: {use: osx-xcode11.6}, git: {clone: false}, env: TESTS=dist-vlt-0}
|
||||
- {stage: test, if: type = cron, os: osx, osx_image: xcode11.6, compiler: clang, workspaces: {use: osx-xcode11.6}, git: {clone: false}, env: TESTS=dist-vlt-1}
|
||||
- {stage: test, if: type = cron, os: osx, osx_image: xcode11.6, compiler: clang, workspaces: {use: osx-xcode11.6}, git: {clone: false}, env: TESTS=vltmt-0}
|
||||
- {stage: test, if: type = cron, os: osx, osx_image: xcode11.6, compiler: clang, workspaces: {use: osx-xcode11.6}, git: {clone: false}, env: TESTS=vltmt-1}
|
||||
# FreeBSD tests
|
||||
#- {stage: test, if: type = cron, os: freebsd, compiler: clang, workspaces: {use: freebsd}, git: {clone: false}, env: TESTS=dist-vlt-0}
|
||||
#- {stage: test, if: type = cron, os: freebsd, compiler: clang, workspaces: {use: freebsd}, git: {clone: false}, env: TESTS=dist-vlt-1}
|
||||
#- {stage: test, if: type = cron, os: freebsd, compiler: clang, workspaces: {use: freebsd}, git: {clone: false}, env: TESTS=vltmt-0}
|
||||
#- {stage: test, if: type = cron, os: freebsd, compiler: clang, workspaces: {use: freebsd}, git: {clone: false}, env: TESTS=vltmt-1}
|
||||
|
||||
notifications:
|
||||
email:
|
||||
if: repo = verilator/verilator
|
||||
recipients:
|
||||
- [email protected]
|
||||
- [email protected]
|
||||
@@ -3,6 +3,120 @@ Revision history for Verilator
|
||||
The contributors that suggested a given feature are shown in []. Thanks!
|
||||
|
||||
|
||||
* Verilator 4.108 2021-01-10
|
||||
|
||||
** Many VPI changes for IEEE compatibility, which may alter behavior from previous releases.
|
||||
|
||||
** Support randomize() class method and rand (#2607). [Krzysztof Bieganski]
|
||||
|
||||
*** Support $cast and new CASTCONST warning.
|
||||
|
||||
*** Add --top option as alias of --top-module.
|
||||
|
||||
*** Add LATCH and NOLATCH warnings (#1609) (#2740). [Julien Margetts]
|
||||
|
||||
**** Remove Unix::Processors internal test dependency.
|
||||
|
||||
**** Report UNUSED on parameters, localparam and genvars (#2627). [Charles Eric LaForest]
|
||||
|
||||
**** Add error on real to non-real output pins (#2690). [Peter Monsson]
|
||||
|
||||
**** Support package imports before parameters in interfaces (#2714). [James Hanlon]
|
||||
|
||||
**** Support --sanitize in internal tests (#2705). [Yutetsu TAKATSUKASA]
|
||||
|
||||
**** Fix passing parameter type instantiations by position number.
|
||||
|
||||
**** Fix DPI open array handling issues.
|
||||
|
||||
**** Fix error when dotted refers to missing module (#2095). [Alexander Grobman]
|
||||
|
||||
**** Fix little endian packed array counting (#2499). [phantom-killua]
|
||||
|
||||
**** Fix showing reference locations for BLKANDNBLK (#2170). [Yuri Victorovich]
|
||||
|
||||
**** Fix genblk naming to match IEEE (#2686). [tinshark]
|
||||
|
||||
**** Fix VPI memory word indexing (#2695). [Marlon James]
|
||||
|
||||
**** Fix vpiLeftRange on little-endian memories (#2696). [Marlon James]
|
||||
|
||||
**** Fix VPI module tree (#2704). [Todd Strader]
|
||||
|
||||
**** Fix vpi_release_handle to be called implicitly per IEEE (#2706).
|
||||
|
||||
**** Fix to allow inheriting 'VerilatedVcdFile' class. (#2720) [HyungKi Jeong]
|
||||
|
||||
**** Fix $urandom_range maximum value (#2723). [Nandu Raj]
|
||||
|
||||
**** Fix tracing empty sc module (#2729).
|
||||
|
||||
**** Fix generate for unrolling to be signed (#2730). [yanx21]
|
||||
|
||||
**** Fix to emit timescale in hierarchical blocks (#2735). [Yutetsu TAKATSUKASA]
|
||||
|
||||
**** Fix to ignore coverage on real ports (#2741) (#2745). [Paul Wright]
|
||||
|
||||
|
||||
|
||||
* Verilator 4.106 2020-12-02
|
||||
|
||||
** Change -sv option to select 1800-2017 instead of 1800-2005.
|
||||
|
||||
*** Check for proper 'local' and 'protected' (#2228).
|
||||
|
||||
*** Support $random and $urandom seeds.
|
||||
|
||||
*** Support $monitor and $strobe.
|
||||
|
||||
*** Support complex function arguments.
|
||||
|
||||
*** Support 'super'.
|
||||
|
||||
*** Support 'with item.index'.
|
||||
|
||||
**** Fix the default GNU Make executable name on FreeBSD (#2553). [Yuri Victorovich]
|
||||
|
||||
**** Fix trace signal names getting hashed (#2643). [Barbara Gigerl]
|
||||
|
||||
**** Fix unpacked array parameters near functions (#2639). [Anderson Ignacio da Silva]
|
||||
|
||||
**** Fix access to non-overridden base class variable (#2654). [Tobias Rosenkranz]
|
||||
|
||||
|
||||
* Verilator 4.104 2020-11-14
|
||||
|
||||
*** Support queue and associative array 'with' statements (#2616).
|
||||
|
||||
*** Support queue slicing (#2326).
|
||||
|
||||
*** Support associative array pattern assignments and defaults.
|
||||
|
||||
*** Support static methods and typedefs in classes (#2615). [Krzysztof Bieganski]
|
||||
|
||||
**** Report error on typedef referencing self (#2539). [Cody Piersall]
|
||||
|
||||
**** With --debug, turn off address space layout randomization.
|
||||
|
||||
**** Fix iteration over mutating list bug in VPI (#2588). [Kaleb Barrett]
|
||||
|
||||
**** Fix cast width propagation (#2597). [flex-liu]
|
||||
|
||||
**** Fix return from callValueCbs (#2589) (#2605). [Marlon James]
|
||||
|
||||
**** Fix WIDTH warnings on comparisons with nullptr (#2602). [Rupert Swarbrick]
|
||||
|
||||
**** Fix fault when $fgets, $sscanf, etc used with string (#2604). [Yutetsu TAKATSUKASA]
|
||||
|
||||
**** Fix WIFEXITED missing from MinGW/MSYS2 (#2609). [Jean Berniolles]
|
||||
|
||||
**** Fix queue poping wrong value when otherwise unused (#2512). [nanduraj1]
|
||||
|
||||
**** Fix arrays of modport interfaces (#2614). [Thierry Tambe]
|
||||
|
||||
**** Fix split_var internal error (#2640) (#2641). [Yutetsu TAKATSUKASA]
|
||||
|
||||
|
||||
* Verilator 4.102 2020-10-15
|
||||
|
||||
**** Support const object new() assignments.
|
||||
@@ -3777,7 +3891,7 @@ of input ports exists for tracing.
|
||||
|
||||
This uses outline mode in Emacs. See C-h m [M-x describe-mode].
|
||||
|
||||
Copyright 2001-2020 by Wilson Snyder. This program is free software; you
|
||||
Copyright 2001-2021 by Wilson Snyder. This program is free software; you
|
||||
can redistribute it and/or modify it under the terms of either the GNU
|
||||
Lesser General Public License Version 3 or the Perl Artistic License
|
||||
Version 2.0.
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
\.ccache/
|
||||
\.clang-format
|
||||
\.clang-tidy
|
||||
\.git/
|
||||
@@ -23,6 +24,7 @@
|
||||
/obj_dir/
|
||||
/obj_dist/
|
||||
/obj_iv/
|
||||
/obj_ms/
|
||||
/obj_nc/
|
||||
/obj_opt/
|
||||
/obj_vcs/
|
||||
@@ -45,6 +47,7 @@ src/Makefile$
|
||||
src/Makefile_obj$
|
||||
include/verilated.mk$
|
||||
test_regress/.gdbinit$
|
||||
test_regress/transcript
|
||||
codecov.yml
|
||||
config.cache$
|
||||
config.status$
|
||||
@@ -66,4 +69,5 @@ ci/
|
||||
/csrc/
|
||||
obj_dir.*
|
||||
TAGS
|
||||
gmon.out
|
||||
.*~
|
||||
|
||||
+33
-8
@@ -7,7 +7,7 @@
|
||||
#
|
||||
#*****************************************************************************
|
||||
#
|
||||
# Copyright 2003-2020 by Wilson Snyder. This program is free software; you
|
||||
# Copyright 2003-2021 by Wilson Snyder. This program is free software; you
|
||||
# can redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
@@ -153,6 +153,7 @@ DISTFILES_INC = $(INFOS) .gitignore \
|
||||
.*attributes */.*attributes */*/.*attributes \
|
||||
src/.*ignore src/*.in src/*.cpp src/*.[chly] \
|
||||
src/astgen src/bisonpre src/*fix src/cppcheck_filtered \
|
||||
src/config_rev \
|
||||
src/vlcovgen src/mkinstalldirs \
|
||||
src/.gdbinit \
|
||||
src/*.pl src/*.pod \
|
||||
@@ -219,7 +220,7 @@ all_nomsg: verilator_exe $(VL_INST_MAN_FILES)
|
||||
verilator_exe verilator_bin verilator_bin_dbg verilator_coverage_bin_dbg:
|
||||
@echo ------------------------------------------------------------
|
||||
@echo "making verilator in src"
|
||||
$(MAKE) -C src $(OBJCACHE_JOBS)
|
||||
$(MAKE) -C src $(OBJCACHE_JOBS) $(CI_MAKE_SRC_TARGET)
|
||||
|
||||
.PHONY:msg_test
|
||||
msg_test: all_nomsg
|
||||
@@ -421,6 +422,7 @@ endif
|
||||
|
||||
# Use --xml flag to see the cppcheck code to use for suppression
|
||||
CPPCHECK_CPP = $(wildcard \
|
||||
$(srcdir)/examples/*/*.cpp \
|
||||
$(srcdir)/include/*.cpp \
|
||||
$(srcdir)/src/*.cpp )
|
||||
CPPCHECK_H = $(wildcard \
|
||||
@@ -429,7 +431,7 @@ CPPCHECK_H = $(wildcard \
|
||||
CPPCHECK_YL = $(wildcard \
|
||||
$(srcdir)/src/*.y \
|
||||
$(srcdir)/src/*.l )
|
||||
CPPCHECK = src/cppcheck_filtered
|
||||
CPPCHECK = src/cppcheck_filtered cppcheck
|
||||
CPPCHECK_FLAGS = --enable=all --inline-suppr \
|
||||
--suppress=unusedScopedObject --suppress=cstyleCast --suppress=useInitializationList \
|
||||
--suppress=nullPointerRedundantCheck
|
||||
@@ -442,15 +444,16 @@ cppcheck: $(CPPCHECK_DEP)
|
||||
$(CPPCHECK) $(CPPCHECK_FLAGS) -DVL_DEBUG=1 -DVL_CPPCHECK=1 -DVL_THREADED=1 $(CPPCHECK_INC) $<
|
||||
|
||||
CLANGTIDY = clang-tidy
|
||||
CLANGTIDY_FLAGS = -config=''
|
||||
CLANGTIDY_FLAGS = -config='' -checks='-fuchsia-*,-cppcoreguidelines-avoid-c-arrays,-cppcoreguidelines-init-variables'
|
||||
CLANGTIDY_DEP = $(subst .h,.h.tidy,$(CPPCHECK_H)) \
|
||||
$(subst .cpp,.cpp.tidy,$(CPPCHECK_CPP))
|
||||
CLANGTIDY_DEFS = -DVL_DEBUG=1 -DVL_THREADED=1 -DVL_CPPCHECK=1
|
||||
|
||||
clangtidy: $(CLANGTIDY_DEP)
|
||||
clang-tidy: $(CLANGTIDY_DEP)
|
||||
%.cpp.tidy: %.cpp
|
||||
$(CLANGTIDY) $(CLANGTIDY_FLAGS) $< -- -DVL_DEBUG=1 -DVL_CPPCHECK=1 $(CPPCHECK_INC) | 2>&1 tee $@
|
||||
$(CLANGTIDY) $(CLANGTIDY_FLAGS) $< -- $(CLANGTIDY_DEFS) $(CPPCHECK_INC) | 2>&1 tee $@
|
||||
%.h.tidy: %.h
|
||||
$(CLANGTIDY) $(CLANGTIDY_FLAGS) $< -- -DVL_DEBUG=1 -DVL_CPPCHECK=1 $(CPPCHECK_INC) | 2>&1 tee $@
|
||||
$(CLANGTIDY) $(CLANGTIDY_FLAGS) $< -- $(CLANGTIDY_DEFS) $(CPPCHECK_INC) | 2>&1 tee $@
|
||||
|
||||
analyzer-src:
|
||||
-rm -rf src/obj_dbg
|
||||
@@ -460,13 +463,35 @@ analyzer-include:
|
||||
-rm -rf examples/*/obj*
|
||||
scan-build $(MAKE) -k examples
|
||||
|
||||
format: clang-format yapf
|
||||
|
||||
CLANGFORMAT = clang-format
|
||||
CLANGFORMAT_FLAGS = -i
|
||||
CLANGFORMAT_FILES = $(CPPCHECK_CPP) $(CPPCHECK_H) $(CPPCHECK_YL) test_regress/t/*.c* test_regress/t/*.h
|
||||
|
||||
clang-format:
|
||||
@$(CLANGFORMAT) --version | egrep 10.0 > /dev/null \
|
||||
|| echo "*** You are not using clang-format 10.0, indents may differ from master's ***"
|
||||
$(CLANGFORMAT) $(CLANGFORMAT_FLAGS) $(CPPCHECK_CPP) $(CPPCHECK_H) $(CPPCHECK_YL)
|
||||
$(CLANGFORMAT) $(CLANGFORMAT_FLAGS) $(CLANGFORMAT_FILES)
|
||||
|
||||
YAPF = yapf3
|
||||
YAPF_FLAGS = -i
|
||||
YAPF_FILES = \
|
||||
examples/xml_py/vl_file_copy \
|
||||
examples/xml_py/vl_hier_graph \
|
||||
src/config_rev \
|
||||
src/cppcheck_filtered \
|
||||
src/flexfix \
|
||||
src/vlcovgen \
|
||||
nodist/code_coverage \
|
||||
nodist/code_coverage.dat \
|
||||
nodist/dot_importer \
|
||||
nodist/fuzzer/actual_fail \
|
||||
nodist/fuzzer/generate_dictionary \
|
||||
nodist/install_test \
|
||||
|
||||
yapf:
|
||||
$(YAPF) $(YAPF_FLAGS) $(YAPF_FILES)
|
||||
|
||||
ftp: info
|
||||
|
||||
|
||||
+2
-2
@@ -6,7 +6,7 @@ image:https://img.shields.io/badge/License-LGPL%20v3-blue.svg[license LGPLv3,lin
|
||||
image:https://img.shields.io/badge/License-Artistic%202.0-0298c3.svg[license Artistic-2.0,link=https://opensource.org/licenses/Artistic-2.0]
|
||||
image:https://api.codacy.com/project/badge/Grade/fa78caa433c84a4ab9049c43e9debc6f[Code Quality,link=https://www.codacy.com/gh/verilator/verilator]
|
||||
image:https://codecov.io/gh/verilator/verilator/branch/master/graph/badge.svg[Coverage,link=https://codecov.io/gh/verilator/verilator]
|
||||
image:https://travis-ci.com/verilator/verilator.svg?branch=master[Build Status (Travis CI),link=https://travis-ci.com/verilator/verilator]
|
||||
image:https://github.com/verilator/verilator/workflows/build/badge.svg[Build Status (GitHub),link=https://github.com/verilator/verilator/actions?query=workflow%3Abuild]
|
||||
endif::[]
|
||||
|
||||
ifdef::env-github[]
|
||||
@@ -145,7 +145,7 @@ perhaps Icarus may.
|
||||
|
||||
== Open License
|
||||
|
||||
Verilator is Copyright 2003-2020 by Wilson Snyder. (Report bugs to
|
||||
Verilator is Copyright 2003-2021 by Wilson Snyder. (Report bugs to
|
||||
https://verilator.org/issues[Verilator Issues].)
|
||||
|
||||
Verilator is free software; you can redistribute it and/or modify it under
|
||||
|
||||
+134
-85
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env perl
|
||||
######################################################################
|
||||
#
|
||||
# Copyright 2003-2020 by Wilson Snyder. This program is free software; you
|
||||
# Copyright 2003-2021 by Wilson Snyder. This program is free software; you
|
||||
# can redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
@@ -76,7 +76,8 @@ if ($opt_gdbbt && !gdb_works()) {
|
||||
my @quoted_sw = map {sh_escape($_)} @Opt_Verilator_Sw;
|
||||
if ($opt_gdb) {
|
||||
# Generic GDB interactive
|
||||
run (($ENV{VERILATOR_GDB}||"gdb")
|
||||
run (aslr_off()
|
||||
.($ENV{VERILATOR_GDB}||"gdb")
|
||||
." ".verilator_bin()
|
||||
# Note, uncomment to set breakpoints before running:
|
||||
# ." -ex 'break main'"
|
||||
@@ -91,16 +92,22 @@ if ($opt_gdb) {
|
||||
." -ex 'bt'");
|
||||
} elsif ($opt_rr) {
|
||||
# Record with rr
|
||||
run ("rr record ".verilator_bin()
|
||||
run (aslr_off()
|
||||
."rr record ".verilator_bin()
|
||||
." ".join(' ', @quoted_sw));
|
||||
} elsif ($opt_gdbbt && $Debug) {
|
||||
# Run under GDB to get gdbbt
|
||||
run ("gdb"
|
||||
run (aslr_off()
|
||||
."gdb"
|
||||
." ".verilator_bin()
|
||||
." --batch --quiet --return-child-result"
|
||||
." -ex \"run ".join(' ', @quoted_sw)."\""
|
||||
." -ex 'set width 0'"
|
||||
." -ex 'bt' -ex 'quit'");
|
||||
} elsif ($Debug) {
|
||||
# Debug
|
||||
run(aslr_off()
|
||||
.verilator_bin()." ".join(' ',@quoted_sw));
|
||||
} else {
|
||||
# Normal, non gdb
|
||||
run(verilator_bin()." ".join(' ',@quoted_sw));
|
||||
@@ -165,6 +172,15 @@ sub gdb_works {
|
||||
return $status==0;
|
||||
}
|
||||
|
||||
sub aslr_off {
|
||||
my $ok = `setarch --addr-no-randomize echo ok 2>/dev/null` || "";
|
||||
if ($ok =~ /ok/) {
|
||||
return "setarch --addr-no-randomize ";
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
sub run {
|
||||
# Run command, check errors
|
||||
my $command = shift;
|
||||
@@ -393,6 +409,7 @@ arguments.
|
||||
--threads-max-mtasks <mtasks> Tune maximum mtask partitioning
|
||||
--timescale <timescale> Sets default timescale
|
||||
--timescale-override <timescale> Overrides all timescales
|
||||
--top <topname> Alias of --top-module
|
||||
--top-module <topname> Name of top level input module
|
||||
--trace Enable waveform creation
|
||||
--trace-coverage Enable tracing of coverage
|
||||
@@ -1244,8 +1261,8 @@ With -E, show comments in preprocessor output.
|
||||
=item --prefix I<topname>
|
||||
|
||||
Specifies the name of the top level class and makefile. Defaults to V
|
||||
prepended to the name of the --top-module switch, or V prepended to the
|
||||
first Verilog filename passed on the command line.
|
||||
prepended to the name of the --top switch, or V prepended to the first
|
||||
Verilog filename passed on the command line.
|
||||
|
||||
=item --prof-cfuncs
|
||||
|
||||
@@ -1445,7 +1462,7 @@ future version of Verilator no longer always packs unpacked structures.
|
||||
=item -sv
|
||||
|
||||
Specifies SystemVerilog language features should be enabled; equivalent to
|
||||
"--language 1800-2005". This option is selected by default, it exists for
|
||||
"--language 1800-2017". This option is selected by default, it exists for
|
||||
compatibility with other simulators.
|
||||
|
||||
=item +systemverilogext+I<ext>
|
||||
@@ -1507,6 +1524,8 @@ sc_set_time_resolution, or the C++ code instantiating the Verilated module.
|
||||
As 1fs is the finest time precision it may be desirable to always use a
|
||||
precision of 1fs.
|
||||
|
||||
=item --top I<topname>
|
||||
|
||||
=item --top-module I<topname>
|
||||
|
||||
When the input Verilog contains more than one top level module, specifies
|
||||
@@ -1620,8 +1639,8 @@ into Verilator. (Similar to perl -V.) See also --getenv.
|
||||
=item -v I<filename>
|
||||
|
||||
Read the filename as a Verilog library. Any modules in the file may be
|
||||
used to resolve cell instantiations in the top level module, else ignored.
|
||||
Note -v is fairly standard across Verilog tools.
|
||||
used to resolve instances in the top level module, else ignored. Note -v
|
||||
is fairly standard across Verilog tools.
|
||||
|
||||
=item --no-verilate
|
||||
|
||||
@@ -1698,7 +1717,7 @@ than using this option.
|
||||
|
||||
Disable all lint related warning messages, and all style warnings. This is
|
||||
equivalent to "-Wno-ALWCOMBORDER -Wno-BSSPACE -Wno-CASEINCOMPLETE
|
||||
-Wno-CASEOVERLAP -Wno-CASEX -Wno-CASEWITHX -Wno-CMPCONST -Wno-COLONPLUS
|
||||
-Wno-CASEOVERLAP -Wno-CASEX -Wno-CASTCONST -Wno-CASEWITHX -Wno-CMPCONST -Wno-COLONPLUS
|
||||
-Wno-ENDLABEL -Wno-IMPLICIT -Wno-LITENDIAN -Wno-PINCONNECTEMPTY
|
||||
-Wno-PINMISSING -Wno-SYNCASYNCNET -Wno-UNDRIVEN -Wno-UNSIGNED -Wno-UNUSED
|
||||
-Wno-WIDTH" plus the list shown for Wno-style.
|
||||
@@ -1730,7 +1749,7 @@ Enables the specified warning message.
|
||||
Enable all lint related warning messages (note by default they are already
|
||||
enabled), but do not affect style messages. This is equivalent to
|
||||
"-Wwarn-ALWCOMBORDER -Wwarn-BSSPACE -Wwarn-CASEINCOMPLETE
|
||||
-Wwarn-CASEOVERLAP -Wwarn-CASEX -Wwarn-CASEWITHX -Wwarn-CMPCONST
|
||||
-Wwarn-CASEOVERLAP -Wwarn-CASEX -Wwarn-CASTCONST -Wwarn-CASEWITHX -Wwarn-CMPCONST
|
||||
-Wwarn-COLONPLUS -Wwarn-ENDLABEL -Wwarn-IMPLICIT -Wwarn-LITENDIAN
|
||||
-Wwarn-PINMISSING -Wwarn-REALCVT -Wwarn-UNSIGNED -Wwarn-WIDTH".
|
||||
|
||||
@@ -1980,14 +1999,15 @@ section below for descriptions of some of the files that were created.
|
||||
|
||||
(Verilator included a default compile rule and link rule, since we used
|
||||
--exe and passed a .cpp file on the Verilator command line. Verilator also
|
||||
then used C<make> to build a final executable. You can also write your own
|
||||
compile rules, and run make yourself as we'll show in the SYSTEMC section.)
|
||||
then used C<make> to build a final executable, since we used --build. You
|
||||
can also write your own compile rules, and run make yourself as we'll show
|
||||
in the SYSTEMC section.
|
||||
|
||||
And now we run it
|
||||
And now we run it:
|
||||
|
||||
obj_dir/Vour
|
||||
|
||||
And we get as output
|
||||
And we get as output:
|
||||
|
||||
Hello World
|
||||
- our.v:2: Verilog $finish
|
||||
@@ -3084,8 +3104,8 @@ Enable/disable waveform tracing for all future signals declared in the
|
||||
specified filename (or wildcard with '*' or '?', or all files if omitted)
|
||||
and range of line numbers (or all lines if omitted).
|
||||
|
||||
For tracing_off, cells below any module in the files/ranges specified will
|
||||
also not be traced.
|
||||
For tracing_off, instances below any module in the files/ranges specified
|
||||
will also not be traced.
|
||||
|
||||
=item clock_enable -module "<modulename>" -var "<signame>"
|
||||
|
||||
@@ -3757,13 +3777,13 @@ for use by downstream applications.
|
||||
=item /*verilator tracing_off*/
|
||||
|
||||
Disable waveform tracing for all future signals that are declared in this
|
||||
module, or cells below this module. Often this is placed just after a
|
||||
primitive's module statement, so that the entire module and cells below it
|
||||
are not traced.
|
||||
module, or instances below this module. Often this is placed just after a
|
||||
primitive's module statement, so that the entire module and instances below
|
||||
it are not traced.
|
||||
|
||||
=item /*verilator tracing_on*/
|
||||
|
||||
Re-enable waveform tracing for all future signals or cells that are
|
||||
Re-enable waveform tracing for all future signals or instances that are
|
||||
declared.
|
||||
|
||||
=back
|
||||
@@ -3817,8 +3837,8 @@ for example a[2].b is acceptable, while a[x].b is generally not.
|
||||
|
||||
References into generated and arrayed instances use the instance names
|
||||
specified in the Verilog standard; arrayed instances are named
|
||||
{cellName}[{instanceNumber}] in Verilog, which becomes
|
||||
{cellname}__BRA__{instanceNumber}__KET__ inside the generated C++ code.
|
||||
{instanceName}[{instanceNumber}] in Verilog, which becomes
|
||||
{instanceName}__BRA__{instanceNumber}__KET__ inside the generated C++ code.
|
||||
|
||||
=head2 Latches
|
||||
|
||||
@@ -4075,9 +4095,10 @@ is ignored, only a single trace file may be active at once.
|
||||
$dumpall/$dumpportsall, $dumpon/$dumpportson, $dumpoff/$dumpportsoff, and
|
||||
$dumplimit/$dumpportlimit are currently ignored.
|
||||
|
||||
=item $finish, $stop
|
||||
=item $exit, $finish, $stop
|
||||
|
||||
The rarely used optional parameter to $finish and $stop is ignored.
|
||||
The rarely used optional parameter to $finish and $stop is ignored. $exit
|
||||
is aliased to $finish.
|
||||
|
||||
=item $fopen, $fclose, $fdisplay, $ferror, $feof, $fflush, $fgetc, $fgets,
|
||||
$fscanf, $fwrite, $fscanf, $sscanf
|
||||
@@ -4089,17 +4110,12 @@ $setup, $setuphold, $skew, $timeskew, $width
|
||||
|
||||
All specify blocks and timing checks are ignored.
|
||||
|
||||
=item $monitor, $strobe
|
||||
|
||||
Monitor and strobe are not supported, convert to always_comb $display or
|
||||
similar.
|
||||
|
||||
=item $random, $urandom, $urandom_range
|
||||
|
||||
$random and $urandom do not support the optional argument to set the seed.
|
||||
Use +verilator+seed argument to set the seed. There is one random seed per
|
||||
C thread, not per module for $random, nor per object for random stability
|
||||
of $urandom/$urandom_range.
|
||||
Use +verilator+seed argument to set the seed if there is no $random or
|
||||
$urandom optional argument to set the seed. There is one random seed per C
|
||||
thread, not per module for $random, nor per object for random stability of
|
||||
$urandom/$urandom_range.
|
||||
|
||||
=item $readmemb, $readmemh
|
||||
|
||||
@@ -4301,15 +4317,6 @@ not overlap.
|
||||
Ignoring this warning will only suppress the lint check, it will simulate
|
||||
correctly.
|
||||
|
||||
=item CASEX
|
||||
|
||||
Warns that it is simply better style to use casez, and C<?> in place of
|
||||
C<x>'s. See
|
||||
L<http://www.sunburst-design.com/papers/CummingsSNUG1999Boston_FullParallelCase_rev1_1.pdf>
|
||||
|
||||
Ignoring this warning will only suppress the lint check, it will simulate
|
||||
correctly.
|
||||
|
||||
=item CASEWITHX
|
||||
|
||||
Warns that a case statement contains a constant with a C<x>. Verilator is
|
||||
@@ -4320,6 +4327,25 @@ instead intended is to use a casez with C<?>.
|
||||
Ignoring this warning will only suppress the lint check, it will simulate
|
||||
correctly.
|
||||
|
||||
=item CASEX
|
||||
|
||||
Warns that it is simply better style to use casez, and C<?> in place of
|
||||
C<x>'s. See
|
||||
L<http://www.sunburst-design.com/papers/CummingsSNUG1999Boston_FullParallelCase_rev1_1.pdf>
|
||||
|
||||
Ignoring this warning will only suppress the lint check, it will simulate
|
||||
correctly.
|
||||
|
||||
=item CASTCONST
|
||||
|
||||
Warns that a dynamic cast ($cast) is unnecessary as the $cast will always
|
||||
succeed or fail. If it will always fail, the $cast is useless. If it will
|
||||
always succeed a static cast may be preferred.
|
||||
|
||||
Ignoring this warning will only suppress the lint check, it will simulate
|
||||
correctly. On other simulators, not fixing CASTCONST may result in
|
||||
decreased performance.
|
||||
|
||||
=item CDCRSTLOGIC
|
||||
|
||||
With --cdc only, warns that asynchronous flop reset terms come from other
|
||||
@@ -4497,9 +4523,9 @@ top module statement is processed.
|
||||
Warns that a wire is being implicitly declared (it is a single bit wide
|
||||
output from a sub-module.) While legal in Verilog, implicit declarations
|
||||
only work for single bit wide signals (not buses), do not allow using a
|
||||
signal before it is implicitly declared by a cell, and can lead to dangling
|
||||
nets. A better option is the /*AUTOWIRE*/ feature of Verilog-Mode for
|
||||
Emacs, available from L<https://www.veripool.org/verilog-mode>
|
||||
signal before it is implicitly declared by an instance, and can lead to
|
||||
dangling nets. A better option is the /*AUTOWIRE*/ feature of Verilog-Mode
|
||||
for Emacs, available from L<https://www.veripool.org/verilog-mode>
|
||||
|
||||
Ignoring this warning will only suppress the lint check, it will simulate
|
||||
correctly.
|
||||
@@ -4565,6 +4591,16 @@ exposed is acceptable.
|
||||
Ignoring this warning will only suppress the lint check, it will simulate
|
||||
correctly.
|
||||
|
||||
=item LATCH
|
||||
|
||||
Warns that a signal is not assigned in all control paths of a combinational
|
||||
always block, resulting in the inference of a latch. For intentional
|
||||
latches, consider using the always_latch (SystemVerilog) keyword instead.
|
||||
The warning may be disabled with a lint_off pragma around the always block.
|
||||
|
||||
Ignoring this warning will only suppress the lint check, it will simulate
|
||||
correctly.
|
||||
|
||||
=item LITENDIAN
|
||||
|
||||
Warns that a packed vector is declared with little endian bit numbering
|
||||
@@ -4572,10 +4608,10 @@ Warns that a packed vector is declared with little endian bit numbering
|
||||
and little numbering is now thus often due to simple oversight instead of
|
||||
intent.
|
||||
|
||||
Also warns that a cell is declared with little endian range (i.e. [0:7] or
|
||||
[7]) and is connected to a N-wide signal. Based on IEEE the bits will
|
||||
likely be backwards from what you expect (i.e. cell [0] will connect to
|
||||
signal bit [N-1] not bit [0]).
|
||||
Also warns that an instance is declared with little endian range
|
||||
(i.e. [0:7] or [7]) and is connected to a N-wide signal. Based on IEEE the
|
||||
bits will likely be backwards from what you expect (i.e. instance [0] will
|
||||
connect to signal bit [N-1] not bit [0]).
|
||||
|
||||
Ignoring this warning will only suppress the lint check, it will simulate
|
||||
correctly.
|
||||
@@ -4607,18 +4643,18 @@ instantiated by any other module, and both modules were put on the command
|
||||
line (not in a library). Three likely cases:
|
||||
|
||||
1. A single module is intended to be the top. This warning then occurs
|
||||
because some low level cell is being read in, but is not really needed as
|
||||
part of the design. The best solution for this situation is to ensure that
|
||||
only the top module is put on the command line without any flags, and all
|
||||
remaining library files are read in as libraries with -v, or are
|
||||
because some low level instance is being read in, but is not really needed
|
||||
as part of the design. The best solution for this situation is to ensure
|
||||
that only the top module is put on the command line without any flags, and
|
||||
all remaining library files are read in as libraries with -v, or are
|
||||
automatically resolved by having filenames that match the module names.
|
||||
|
||||
2. A single module is intended to be the top, the name of it is known, and
|
||||
all other modules should be ignored if not part of the design. The best
|
||||
solution is to use the --top-module option to specify the top module's
|
||||
name. All other modules that are not part of the design will be for the
|
||||
most part ignored (they must be clean in syntax and their contents will be
|
||||
removed as part of the Verilog module elaboration process.)
|
||||
solution is to use the --top option to specify the top module's name. All
|
||||
other modules that are not part of the design will be for the most part
|
||||
ignored (they must be clean in syntax and their contents will be removed as
|
||||
part of the Verilog module elaboration process.)
|
||||
|
||||
3. Multiple modules are intended to be design tops, e.g. when linting a
|
||||
library file. As multiple modules are desired, disable the MULTITOP
|
||||
@@ -4628,29 +4664,37 @@ based on the top module name followed by __02E (a Verilator-encoded ASCII
|
||||
".'). This renaming is done even if the two modules' signals seem
|
||||
identical, e.g. multiple modules with a "clk" input.
|
||||
|
||||
=item NOLATCH
|
||||
|
||||
Warns that no latch was detected in an always_latch block. The warning may
|
||||
be disabled with a lint_off pragma around the always block, but recoding
|
||||
using a regular always may be more appropriate.
|
||||
|
||||
Ignoring this warning will only suppress the lint check, it will simulate
|
||||
correctly.
|
||||
|
||||
=item PINCONNECTEMPTY
|
||||
|
||||
Warns that a cell instantiation has a pin which is connected to
|
||||
.pin_name(), e.g. not another signal, but with an explicit mention of the
|
||||
pin. It may be desirable to disable PINCONNECTEMPTY, as this indicates
|
||||
intention to have a no-connect.
|
||||
Warns that an instance has a pin which is connected to .pin_name(),
|
||||
e.g. not another signal, but with an explicit mention of the pin. It may
|
||||
be desirable to disable PINCONNECTEMPTY, as this indicates intention to
|
||||
have a no-connect.
|
||||
|
||||
Disabled by default as this is a code style warning; it will simulate
|
||||
correctly.
|
||||
|
||||
=item PINMISSING
|
||||
|
||||
Warns that a module has a pin which is not mentioned in a cell
|
||||
instantiation. If a pin is not missing it should still be specified on the
|
||||
cell declaration with a empty connection, using "(.pin_name())".
|
||||
Warns that a module has a pin which is not mentioned in an instance. If a
|
||||
pin is not missing it should still be specified on the instance declaration
|
||||
with a empty connection, using "(.pin_name())".
|
||||
|
||||
Ignoring this warning will only suppress the lint check, it will simulate
|
||||
correctly.
|
||||
|
||||
=item PINNOCONNECT
|
||||
|
||||
Warns that a cell instantiation has a pin which is not connected to another
|
||||
signal.
|
||||
Warns that an instance has a pin which is not connected to another signal.
|
||||
|
||||
Disabled by default as this is a code style warning; it will simulate
|
||||
correctly.
|
||||
@@ -4666,6 +4710,11 @@ declared before being used.
|
||||
Error that a procedural assignment is setting a wire. According to IEEE, a
|
||||
var/reg must be used as the target of procedural assignments.
|
||||
|
||||
=item RANDC
|
||||
|
||||
Warns that the 'randc' keyword is currently unsupported, and that it is
|
||||
being converted to 'rand'.
|
||||
|
||||
=item REALCVT
|
||||
|
||||
Warns that a real number is being implicitly rounded to an integer, with
|
||||
@@ -4769,12 +4818,12 @@ correctly.
|
||||
|
||||
=item TASKNSVAR
|
||||
|
||||
Error when a call to a task or function has a output from that task tied to
|
||||
Error when a call to a task or function has an inout from that task tied to
|
||||
a non-simple signal. Instead connect the task output to a temporary signal
|
||||
of the appropriate width, and use that signal to set the appropriate
|
||||
expression as the next statement. For example:
|
||||
|
||||
task foo; output sig; ... endtask
|
||||
task foo(inout sig); ... endtask
|
||||
always @* begin
|
||||
foo(bus_we_select_from[2]); // Will get TASKNSVAR error
|
||||
end
|
||||
@@ -4888,7 +4937,7 @@ potentially resolving the conflict. If you run with --report-unoptflat
|
||||
Verilator will suggest possible candidates for C<split_var>.
|
||||
|
||||
The UNOPTFLAT warning may also be due to clock enables, identified from the
|
||||
reported path going through a clock gating cell. To fix these, use the
|
||||
reported path going through a clock gating instance. To fix these, use the
|
||||
clock_enable meta comment described above.
|
||||
|
||||
The UNOPTFLAT warning may also occur where outputs from a block of logic
|
||||
@@ -4947,10 +4996,10 @@ design simulate incorrectly; see the details under --bbox-unsup.
|
||||
|
||||
=item UNUSED
|
||||
|
||||
Warns that the specified signal is never used/consumed. Verilator is
|
||||
fairly liberal in the usage calculations; making a signal public, a signal
|
||||
matching --unused-regexp ("*unused*") or accessing only a single array
|
||||
element marks the entire signal as used.
|
||||
Warns that the specified signal or parameter is never used/consumed.
|
||||
Verilator is fairly liberal in the usage calculations; making a signal
|
||||
public, a signal matching --unused-regexp ("*unused*") or accessing only a
|
||||
single array element marks the entire signal as used.
|
||||
|
||||
Disabled by default as this is a code style warning; it will simulate
|
||||
correctly.
|
||||
@@ -5463,21 +5512,21 @@ by your code or you'll get strange results.
|
||||
|
||||
=item Should a module be in Verilog or SystemC?
|
||||
|
||||
Sometimes there is a block that just interconnects cells, and have a choice
|
||||
as to if you write it in Verilog or SystemC. Everything else being equal,
|
||||
best performance is when Verilator sees all of the design. So, look at the
|
||||
hierarchy of your design, labeling cells as to if they are SystemC or
|
||||
Verilog. Then:
|
||||
Sometimes there is a block that just interconnects instances, and have a
|
||||
choice as to if you write it in Verilog or SystemC. Everything else being
|
||||
equal, best performance is when Verilator sees all of the design. So, look
|
||||
at the hierarchy of your design, labeling instances as to if they are
|
||||
SystemC or Verilog. Then:
|
||||
|
||||
A module with only SystemC cells below must be SystemC.
|
||||
A module with only SystemC instances below must be SystemC.
|
||||
|
||||
A module with a mix of Verilog and SystemC cells below must be SystemC. (As
|
||||
Verilator cannot connect to lower-level SystemC cells.)
|
||||
A module with a mix of Verilog and SystemC instances below must be
|
||||
SystemC. (As Verilator cannot connect to lower-level SystemC instances.)
|
||||
|
||||
A module with only Verilog cells below can be either, but for best
|
||||
A module with only Verilog instances below can be either, but for best
|
||||
performance should be Verilog. (The exception is if you have a design that
|
||||
is instantiated many times; in this case Verilating one of the lower
|
||||
modules and instantiating that Verilated cells multiple times into a
|
||||
modules and instantiating that Verilated instances multiple times into a
|
||||
SystemC module *may* be faster.)
|
||||
|
||||
=back
|
||||
@@ -5666,7 +5715,7 @@ remain anonymous.
|
||||
|
||||
The latest version is available from L<https://verilator.org>.
|
||||
|
||||
Copyright 2003-2020 by Wilson Snyder. This program is free software; you can
|
||||
Copyright 2003-2021 by Wilson Snyder. This program is free software; you can
|
||||
redistribute it and/or modify the Verilator internals under the terms of
|
||||
either the GNU Lesser General Public License Version 3 or the Perl Artistic
|
||||
License Version 2.0.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env perl
|
||||
######################################################################
|
||||
#
|
||||
# Copyright 2003-2020 by Wilson Snyder. This program is free software; you
|
||||
# Copyright 2003-2021 by Wilson Snyder. This program is free software; you
|
||||
# can redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
@@ -278,7 +278,7 @@ Specifies a module search directory.
|
||||
|
||||
The latest version is available from L<https://verilator.org>.
|
||||
|
||||
Copyright 2003-2020 by Wilson Snyder. This program is free software; you
|
||||
Copyright 2003-2021 by Wilson Snyder. This program is free software; you
|
||||
can redistribute it and/or modify the Verilator internals under the terms
|
||||
of either the GNU Lesser General Public License Version 3 or the Perl
|
||||
Artistic License Version 2.0.
|
||||
|
||||
+1
-26
@@ -9,22 +9,6 @@ use Pod::Usage;
|
||||
use strict;
|
||||
use vars qw($Debug);
|
||||
|
||||
#======================================================================
|
||||
|
||||
# Old version 1 dump nodes with no dtypep's
|
||||
our %Ver1_Non_Dtyped = map {$_ => 1} qw(
|
||||
ACTIVE ALWAYS ALWAYSPOST ALWAYSPUBLIC ATTROF BEGIN BREAK CASE CASEITEM
|
||||
CCALL CELL CELLINLINE CFILE CFUNC CHANGEDET CLOCKING COMMENT CONTINUE
|
||||
COVERDECL COVERINC COVERTOGGLE CRETURN CSTMT DEFPARAM DISABLE DISPLAY DOT
|
||||
DPIEXPORT FCLOSE FFLUSH FINAL FINISH FOPEN GENCASE GENERATE GENFOR GENIF
|
||||
IF IMPLICIT INITARRAY INITIAL JUMPGO JUMPLABEL MODULE NETLIST
|
||||
NOTFOUNDMODULE PACKAGE PACKAGEIMPORT PARSEREF PIN PORT PRAGMA PRIMITIVE
|
||||
PSLASSERT PSLCOVER PSLDEFCLOCK PULL RANGE READMEM REPEAT RETURN SCCTOR
|
||||
SCDTOR SCHDR SCIMP SCIMPHDR SCINT SCOPE SELBIT SELEXTRACT SELMINUS
|
||||
SELPLUS SENGATE SENITEM SENTREE SFORMAT SFORMATF STOP SYSIGNORE SYSTEMT
|
||||
TASK TASKREF TEXT TOPSCOPE TYPEDEFFWD TYPETABLE UCSTMT UDPTABLE
|
||||
UDPTABLELINE UNTILSTABLE VASSERT WHILE );
|
||||
|
||||
#======================================================================
|
||||
# main
|
||||
|
||||
@@ -133,8 +117,6 @@ sub filter {
|
||||
$line =~ s/{[a-z]*\d+}/{}/g if !$Opt_Lineno;
|
||||
if ($verCvt) {
|
||||
next if $line =~ /^ NETLIST/;
|
||||
$line =~ s!\@dt=0x\(G?/?([^)]+)\)!$1!g; # NEW: @dt -> OLD: non @dt format
|
||||
# # Below Ver1_Non_Dtyped may replace above further
|
||||
if ($line =~ /: ([A-Z]+) /) {
|
||||
my $type = $1;
|
||||
next if $type =~ 'DTYPE';
|
||||
@@ -147,14 +129,7 @@ sub filter {
|
||||
}
|
||||
next;
|
||||
}
|
||||
if ($Ver1_Non_Dtyped{$type}) {
|
||||
$line =~ s! w[0-9]+!!g;
|
||||
}
|
||||
}
|
||||
$line =~ s!\@dt=0$!NoW!g; # NEW: dt=null -> common format
|
||||
$line =~ s!\@dt=0 !NoW !g; # NEW: dt=null -> common format
|
||||
$line =~ s! s?w0$! NoW!g; # OLD: no width -> common format
|
||||
$line =~ s! s?w0 ! NoW !g; # OLD: no width -> common format
|
||||
}
|
||||
print $f2 $line;
|
||||
}
|
||||
@@ -233,7 +208,7 @@ Do not show differences in line numbering.
|
||||
|
||||
The latest version is available from L<https://verilator.org>.
|
||||
|
||||
Copyright 2005-2020 by Wilson Snyder. This program is free software; you
|
||||
Copyright 2005-2021 by Wilson Snyder. This program is free software; you
|
||||
can redistribute it and/or modify it under the terms of either the GNU
|
||||
Lesser General Public License Version 3 or the Perl Artistic License
|
||||
Version 2.0.
|
||||
|
||||
+82
-10
@@ -60,6 +60,7 @@ sub process {
|
||||
my $filename = shift;
|
||||
|
||||
read_data($filename);
|
||||
read_cpuinfo();
|
||||
report();
|
||||
}
|
||||
|
||||
@@ -70,7 +71,7 @@ sub read_data {
|
||||
|
||||
%Global = (rdtsc_cycle_time => 0);
|
||||
|
||||
my $fh = IO::File->new ($filename) or die "%Error: $! $filename,";
|
||||
my $fh = IO::File->new("<$filename") or die "%Error: $! $filename,";
|
||||
while (my $line = $fh->getline) {
|
||||
if ($line =~ m/VLPROF mtask\s(\d+)\sstart\s(\d+)\send\s(\d+)\selapsed\s(\d+)\spredict_time\s(\d+)\scpu\s(\d+)\son thread (\d+)/) {
|
||||
my $mtask = $1;
|
||||
@@ -113,6 +114,27 @@ sub read_data {
|
||||
}
|
||||
}
|
||||
|
||||
sub read_cpuinfo {
|
||||
my $filename = "/proc/cpuinfo";
|
||||
my $fh = IO::File->new("<$filename") or return;
|
||||
my $cpu;
|
||||
while (my $line = $fh->getline) {
|
||||
chomp $line;
|
||||
if ($line =~ m/^processor\s*:\s*(\d+)\s*$/) {
|
||||
$cpu = $1;
|
||||
}
|
||||
if ($cpu && $line =~ m/^([a-z_ ]+)\s*:\s*(.*)$/) {
|
||||
my ($term, $value) = ($1, $2);
|
||||
$term =~ s/\s+$//;
|
||||
$term =~ s/\s+/_/;
|
||||
$value =~ s/\s+$//;
|
||||
$Global{cpuinfo}{$cpu}{$term} = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#######################################################################
|
||||
|
||||
sub report {
|
||||
print "Verilator Gantt report\n";
|
||||
|
||||
@@ -162,9 +184,9 @@ sub report {
|
||||
printf " Total eval time = %d rdtsc ticks\n", $Global{last_end};
|
||||
printf " Longest mtask time = %d rdtsc ticks\n", $long_mtask_time;
|
||||
printf " All-thread mtask time = %d rdtsc ticks\n", $mt_mtask_time;
|
||||
my $long_efficiency = $long_mtask_time/($Global{last_end});
|
||||
my $long_efficiency = $long_mtask_time/($Global{last_end} || 1);
|
||||
printf " Longest-thread efficiency = %0.1f%%\n", $long_efficiency*100;
|
||||
my $mt_efficiency = $mt_mtask_time/($Global{last_end}*$nthreads);
|
||||
my $mt_efficiency = $mt_mtask_time/($Global{last_end}*$nthreads || 1);
|
||||
printf " All-thread efficiency = %0.1f%%\n", $mt_efficiency*100;
|
||||
printf " All-thread speedup = %0.1f\n", $mt_efficiency*$nthreads;
|
||||
if ($Global{rdtsc_cycle_time} > 0) {
|
||||
@@ -198,21 +220,70 @@ sub report {
|
||||
}
|
||||
|
||||
print "\nStatistics:\n";
|
||||
print " min log(p2e) = $min_p2e from mtask $min_mtask (predict $Mtasks{$min_mtask}{predict}, elapsed $Mtasks{$min_mtask}{elapsed})\n";
|
||||
print " max log(p2e) = $max_p2e from mtask $max_mtask (predict $Mtasks{$max_mtask}{predict}, elapsed $Mtasks{$max_mtask}{elapsed})\n";
|
||||
printf " min log(p2e) = %0.3f", $min_p2e;
|
||||
print " from mtask $min_mtask (predict $Mtasks{$min_mtask}{predict},";
|
||||
print " elapsed $Mtasks{$min_mtask}{elapsed})\n";
|
||||
printf " max log(p2e) = %0.3f", $max_p2e;
|
||||
print " from mtask $max_mtask (predict $Mtasks{$max_mtask}{predict},";
|
||||
print " elapsed $Mtasks{$max_mtask}{elapsed})\n";
|
||||
|
||||
my $stddev = stddev(\@p2e_ratios);
|
||||
my $mean = mean(\@p2e_ratios);
|
||||
print " mean = " . ($mean) . "\n";
|
||||
print " stddev = " . ($stddev) . "\n";
|
||||
print " e ^ stddev = " . exp($stddev). "\n";
|
||||
print "\n";
|
||||
printf " mean = %0.3f\n", $mean;
|
||||
printf " stddev = %0.3f\n", $stddev;
|
||||
printf " e ^ stddev = %0.3f\n", exp($stddev);
|
||||
|
||||
report_cpus();
|
||||
|
||||
if ($nthreads > $ncpus) {
|
||||
print "\n";
|
||||
print "%Warning: There were fewer CPUs ($ncpus) then threads ($nthreads).\n";
|
||||
print " : See docs on use of numactl.\n";
|
||||
} else {
|
||||
if ($Global{cpu_socket_cores_warning}) {
|
||||
print "\n";
|
||||
print "%Warning: Multiple threads scheduled on same hyperthreaded core.\n";
|
||||
print " : See docs on use of numactl.\n";
|
||||
}
|
||||
if ($Global{cpu_sockets_warning}) {
|
||||
print "\n";
|
||||
print "%Warning: Threads scheduled on multiple sockets.\n";
|
||||
print " : See docs on use of numactl.\n";
|
||||
}
|
||||
}
|
||||
print "\n";
|
||||
}
|
||||
|
||||
sub report_cpus {
|
||||
print "\nCPUs:\n";
|
||||
# Test - show all cores
|
||||
# for (my $i=0; $i<73; ++$i) { $Global{cpus}{$i} ||= {cpu_time => 0}; }
|
||||
|
||||
$Global{cpu_sockets} ||= {};
|
||||
$Global{cpu_socket_cores} ||= {};
|
||||
|
||||
foreach my $cpu (sort {$a <=> $b} keys %{$Global{cpus}}) {
|
||||
printf " cpu %d: ", $cpu;
|
||||
printf "cpu_time=%d", $Global{cpus}{$cpu}{cpu_time};
|
||||
|
||||
my $socket = $Global{cpuinfo}{$cpu}{physical_id};
|
||||
$Global{cpu_sockets}{$socket}++ if defined $socket;
|
||||
printf " socket=%d", $socket if defined $socket;
|
||||
|
||||
my $core = $Global{cpuinfo}{$cpu}{core_id};
|
||||
$Global{cpu_socket_cores}{$socket."__".$core}++ if defined $socket && defined $core;
|
||||
printf " core=%d", $core if defined $core;
|
||||
|
||||
my $model = $Global{cpuinfo}{$cpu}{model_name};
|
||||
printf " %s", $model if defined $model;
|
||||
print "\n";
|
||||
}
|
||||
|
||||
$Global{cpu_sockets_warning} = 1
|
||||
if (scalar keys %{$Global{cpu_sockets}} > 1);
|
||||
foreach my $scn (values %{$Global{cpu_socket_cores}}) {
|
||||
$Global{cpu_socket_cores_warning} = 1 if $scn > 1;
|
||||
}
|
||||
}
|
||||
|
||||
sub report_graph {
|
||||
@@ -226,6 +297,7 @@ sub report_graph {
|
||||
}
|
||||
# One more step so we can fit more labels
|
||||
$time_per = int($time_per/2);
|
||||
$time_per ||= 1;
|
||||
}
|
||||
|
||||
my ($graph, $conflicts) = _make_graph($time_per);
|
||||
@@ -545,7 +617,7 @@ verilator_gantt.vcd.
|
||||
|
||||
The latest version is available from L<https://verilator.org>.
|
||||
|
||||
Copyright 2018-2020 by Wilson Snyder. This program is free software; you
|
||||
Copyright 2018-2021 by Wilson Snyder. This program is free software; you
|
||||
can redistribute it and/or modify it under the terms of either the GNU
|
||||
Lesser General Public License Version 3 or the Perl Artistic License
|
||||
Version 2.0.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env perl
|
||||
# DESCRIPTION: Print include statements for each ARGV
|
||||
#
|
||||
# Copyright 2003-2020 by Wilson Snyder. This program is free software; you
|
||||
# Copyright 2003-2021 by Wilson Snyder. This program is free software; you
|
||||
# can redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
@@ -228,7 +228,7 @@ Displays this message and program version and exits.
|
||||
|
||||
The latest version is available from L<https://verilator.org>.
|
||||
|
||||
Copyright 2007-2020 by Wilson Snyder. This program is free software; you
|
||||
Copyright 2007-2021 by Wilson Snyder. This program is free software; you
|
||||
can redistribute it and/or modify it under the terms of either the GNU
|
||||
Lesser General Public License Version 3 or the Perl Artistic License
|
||||
Version 2.0.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
# DESCRIPTION: Verilator: Travis CI ccache maintenance
|
||||
# DESCRIPTION: Verilator: CI ccache maintenance
|
||||
#
|
||||
# Copyright 2020 by Geza Lore. This program is free software; you
|
||||
# can redistribute it and/or modify it under the terms of either the GNU
|
||||
@@ -19,8 +19,8 @@ set -x
|
||||
ccache --version
|
||||
|
||||
# Flush ccache if requested in commit message
|
||||
COMMIT="${TRAVIS_PULL_REQUEST_SHA:-$TRAVIS_COMMIT}"
|
||||
if git log --format=%B -n 1 "$COMMIT" | grep -q -i '\[travis\s\+ccache\s\+clear\]'; then
|
||||
COMMIT="${CI_PULL_REQUEST_SHA:-$CI_COMMIT}"
|
||||
if git log --format=%B -n 1 "$COMMIT" | grep -q -i '\[CI\s\+ccache\s\+clear\]'; then
|
||||
echo "Flushing ccache due to commit message"
|
||||
ccache -C
|
||||
fi
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
# DESCRIPTION: Verilator: Travis CI dependency install script
|
||||
# DESCRIPTION: Verilator: CI dependency install script
|
||||
#
|
||||
# Copyright 2020 by Geza Lore. This program is free software; you
|
||||
# can redistribute it and/or modify it under the terms of either the GNU
|
||||
@@ -14,25 +14,23 @@
|
||||
# required by the particular build stage.
|
||||
################################################################################
|
||||
|
||||
# Note that Travis runs "apt-get update" when "apt-get install" is used in the
|
||||
# .travis.yml file directly, but since we invoke it via this script, we need to
|
||||
# run it manually where requried, otherwise some packages cannot be found.
|
||||
|
||||
set -e
|
||||
set -x
|
||||
|
||||
cd $(dirname "$0")/..
|
||||
|
||||
fatal() {
|
||||
echo "ERROR: $(basename "$0"): $1" >&2; exit 1;
|
||||
}
|
||||
|
||||
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
|
||||
if [ "$CI_OS_NAME" = "linux" ]; then
|
||||
MAKE=make
|
||||
elif [ "$TRAVIS_OS_NAME" = "osx" ]; then
|
||||
elif [ "$CI_OS_NAME" = "osx" ]; then
|
||||
MAKE=make
|
||||
elif [ "$TRAVIS_OS_NAME" = "freebsd" ]; then
|
||||
elif [ "$CI_OS_NAME" = "freebsd" ]; then
|
||||
MAKE=gmake
|
||||
else
|
||||
fatal "Unknown os: '$TRAVIS_OS_NAME'"
|
||||
fatal "Unknown os: '$CI_OS_NAME'"
|
||||
fi
|
||||
|
||||
install-vcddiff() {
|
||||
@@ -43,62 +41,71 @@ install-vcddiff() {
|
||||
sudo cp "${TMP_DIR}/vcddiff" /usr/local/bin
|
||||
}
|
||||
|
||||
if [ "$TRAVIS_BUILD_STAGE_NAME" = "build" ]; then
|
||||
if [ "$CI_BUILD_STAGE_NAME" = "build" ]; then
|
||||
##############################################################################
|
||||
# Dependencies of jobs in the 'build' stage, i.e.: packages required to
|
||||
# build Verilator
|
||||
|
||||
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
|
||||
if [ "$CI_OS_NAME" = "linux" ]; then
|
||||
sudo apt-get update
|
||||
sudo apt-get install libfl-dev
|
||||
sudo apt-get install libgoogle-perftools-dev
|
||||
sudo apt-get install libfl-dev libgoogle-perftools-dev ccache
|
||||
if [ "$CI_RUNS_ON" = "ubuntu-20.04" ]; then
|
||||
sudo apt-get install libsystemc libsystemc-dev
|
||||
fi
|
||||
if [ "$COVERAGE" = 1 ]; then
|
||||
yes yes | sudo cpan -fi Unix::Processors Parallel::Forker
|
||||
yes yes | sudo cpan -fi Parallel::Forker
|
||||
fi
|
||||
if [ "$M32" = 1 ]; then
|
||||
sudo apt-get install gcc-multilib g++-multilib
|
||||
fi
|
||||
elif [ "$TRAVIS_OS_NAME" = "osx" ]; then
|
||||
elif [ "$CI_OS_NAME" = "osx" ]; then
|
||||
brew update
|
||||
brew install ccache perl gperftools
|
||||
elif [ "$TRAVIS_OS_NAME" = "freebsd" ]; then
|
||||
elif [ "$CI_OS_NAME" = "freebsd" ]; then
|
||||
sudo pkg install -y autoconf bison ccache gmake perl5
|
||||
else
|
||||
fatal "Unknown os: '$TRAVIS_OS_NAME'"
|
||||
fatal "Unknown os: '$CI_OS_NAME'"
|
||||
fi
|
||||
elif [ "$TRAVIS_BUILD_STAGE_NAME" = "test" ]; then
|
||||
|
||||
if [ -n "$CCACHE_DIR" ]; then
|
||||
mkdir -p "$CCACHE_DIR" && ./ci/ci-ccache-maint.bash
|
||||
fi
|
||||
elif [ "$CI_BUILD_STAGE_NAME" = "test" ]; then
|
||||
##############################################################################
|
||||
# Dependencies of jobs in the 'test' stage, i.e.: packages required to
|
||||
# run the tests
|
||||
|
||||
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
|
||||
if [ "$CI_OS_NAME" = "linux" ]; then
|
||||
sudo apt-get update
|
||||
sudo apt-get install gdb gtkwave lcov
|
||||
if [ "$TRAVIS_DIST" = "focal" ]; then
|
||||
# libfl-dev needed for internal coverage's test runs
|
||||
sudo apt-get install gdb gtkwave lcov libfl-dev ccache
|
||||
if [ "$CI_RUNS_ON" = "ubuntu-20.04" ]; then
|
||||
sudo apt-get install libsystemc-dev
|
||||
fi
|
||||
if [ "$M32" = 1 ]; then
|
||||
sudo apt-get install lib32z1-dev gcc-multilib g++-multilib
|
||||
fi
|
||||
elif [ "$TRAVIS_OS_NAME" = "osx" ]; then
|
||||
elif [ "$CI_OS_NAME" = "osx" ]; then
|
||||
brew update
|
||||
# brew cask install gtkwave # fst2vcd hangs at launch, so don't bother
|
||||
brew install ccache perl
|
||||
elif [ "$TRAVIS_OS_NAME" = "freebsd" ]; then
|
||||
elif [ "$CI_OS_NAME" = "freebsd" ]; then
|
||||
# fst2vcd fails with "Could not open '<input file>', exiting."
|
||||
sudo pkg install -y ccache gmake perl5 python3
|
||||
else
|
||||
fatal "Unknown os: '$TRAVIS_OS_NAME'"
|
||||
fatal "Unknown os: '$CI_OS_NAME'"
|
||||
fi
|
||||
# Common installs
|
||||
if [ "$TRAVIS_DIST" != "trusty" ]; then
|
||||
TRAVIS_CPAN_REPO=https://cpan.org
|
||||
if [ "$CI_RUNS_ON" != "ubuntu-14.04" ]; then
|
||||
CI_CPAN_REPO=https://cpan.org
|
||||
fi
|
||||
# Not listing Bit::Vector as slow to install, and only skips one test
|
||||
yes yes | sudo cpan -M $TRAVIS_CPAN_REPO -fi Unix::Processors Parallel::Forker
|
||||
yes yes | sudo cpan -M $CI_CPAN_REPO -fi Parallel::Forker
|
||||
install-vcddiff
|
||||
|
||||
autoconf
|
||||
./configure --enable-longtests --enable-ccwarn
|
||||
else
|
||||
##############################################################################
|
||||
# Unknown build stage
|
||||
fatal "Unknown build stage: '$TRAVIS_BUILD_STAGE_NAME'"
|
||||
fatal "Unknown build stage: '$CI_BUILD_STAGE_NAME'"
|
||||
fi
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
# DESCRIPTION: Verilator: Travis CI main job script
|
||||
# DESCRIPTION: Verilator: CI main job script
|
||||
#
|
||||
# Copyright 2020 by Geza Lore. This program is free software; you
|
||||
# can redistribute it and/or modify it under the terms of either the GNU
|
||||
@@ -10,9 +10,8 @@
|
||||
|
||||
################################################################################
|
||||
# This is the main script executed in the 'script' phase by all jobs. We use a
|
||||
# single script to keep the .travis.yml spec simple. We pass job parameters via
|
||||
# environment variables using 'env' keys. Having different 'env' keys in jobs
|
||||
# ensures they use different Travis build caches.
|
||||
# single script to keep the CI setting simple. We pass job parameters via
|
||||
# environment variables using 'env' keys.
|
||||
################################################################################
|
||||
|
||||
set -e
|
||||
@@ -22,20 +21,20 @@ fatal() {
|
||||
echo "ERROR: $(basename "$0"): $1" >&2; exit 1;
|
||||
}
|
||||
|
||||
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
|
||||
if [ "$CI_OS_NAME" = "linux" ]; then
|
||||
export MAKE=make
|
||||
NPROC=$(nproc)
|
||||
elif [ "$TRAVIS_OS_NAME" = "osx" ]; then
|
||||
elif [ "$CI_OS_NAME" = "osx" ]; then
|
||||
export MAKE=make
|
||||
NPROC=$(sysctl -n hw.logicalcpu)
|
||||
elif [ "$TRAVIS_OS_NAME" = "freebsd" ]; then
|
||||
elif [ "$CI_OS_NAME" = "freebsd" ]; then
|
||||
export MAKE=gmake
|
||||
NPROC=$(sysctl -n hw.ncpu)
|
||||
else
|
||||
fatal "Unknown os: '$TRAVIS_OS_NAME'"
|
||||
fatal "Unknown os: '$CI_OS_NAME'"
|
||||
fi
|
||||
|
||||
if [ "$TRAVIS_BUILD_STAGE_NAME" = "build" ]; then
|
||||
if [ "$CI_BUILD_STAGE_NAME" = "build" ]; then
|
||||
##############################################################################
|
||||
# Build verilator
|
||||
|
||||
@@ -43,7 +42,7 @@ if [ "$TRAVIS_BUILD_STAGE_NAME" = "build" ]; then
|
||||
autoconf
|
||||
./configure --enable-longtests --enable-ccwarn
|
||||
"$MAKE" -j "$NPROC" -k
|
||||
if [ "$TRAVIS_OS_NAME" = "osx" ]; then
|
||||
if [ "$CI_OS_NAME" = "osx" ]; then
|
||||
file bin/verilator_bin
|
||||
file bin/verilator_bin_dbg
|
||||
md5 bin/verilator_bin
|
||||
@@ -54,13 +53,15 @@ if [ "$TRAVIS_BUILD_STAGE_NAME" = "build" ]; then
|
||||
else
|
||||
nodist/code_coverage --stages 1-2
|
||||
fi
|
||||
elif [ "$TRAVIS_BUILD_STAGE_NAME" = "test" ]; then
|
||||
elif [ "$CI_BUILD_STAGE_NAME" = "test" ]; then
|
||||
##############################################################################
|
||||
# Run tests
|
||||
|
||||
if [ "$TRAVIS_OS_NAME" = "osx" ]; then
|
||||
export VERILATOR_TEST_NO_GDB=1 # Pain to get GDB to work on OS X
|
||||
export VERILATOR_TEST_NO_GPROF=1 # Apple Clang has no -pg
|
||||
export VERILATOR_TEST_NO_CONTRIBUTORS=1 # Separate workflow check
|
||||
|
||||
if [ "$CI_OS_NAME" = "osx" ]; then
|
||||
export VERILATOR_TEST_NO_GDB=1 # Pain to get GDB to work on OS X
|
||||
export VERILATOR_TEST_NO_GPROF=1 # Apple Clang has no -pg
|
||||
# export PATH="/Applications/gtkwave.app/Contents/Resources/bin:$PATH" # fst2vcd
|
||||
file bin/verilator_bin
|
||||
file bin/verilator_bin_dbg
|
||||
@@ -70,21 +71,24 @@ elif [ "$TRAVIS_BUILD_STAGE_NAME" = "test" ]; then
|
||||
stat bin/verilator_bin_dbg
|
||||
# For some reason, the dbg exe is corrupted by this point ('file' reports
|
||||
# it as data rather than a Mach-O). Unclear if this is an OS X issue or
|
||||
# one for Travis. Remove the file and re-link...
|
||||
# CI's. Remove the file and re-link...
|
||||
rm bin/verilator_bin_dbg
|
||||
"$MAKE" -j "$NPROC" -k
|
||||
elif [ "$TRAVIS_OS_NAME" = "freebsd" ]; then
|
||||
elif [ "$CI_OS_NAME" = "freebsd" ]; then
|
||||
export VERILATOR_TEST_NO_GDB=1 # Disable for now, ideally should run
|
||||
export VERILATOR_TEST_NO_GPROF=1 # gprof is a bit different on FreeBSD, disable
|
||||
fi
|
||||
|
||||
# Run sanitize on Ubuntu 20.04 only
|
||||
[ "$CI_RUNS_ON" = 'ubuntu-20.04' ] && sanitize='--sanitize' || sanitize=''
|
||||
|
||||
# Run the specified test
|
||||
case $TESTS in
|
||||
dist-vlt-0)
|
||||
"$MAKE" -C test_regress SCENARIOS="--dist --vlt" DRIVER_HASHSET=--hashset=0/2
|
||||
"$MAKE" -C test_regress SCENARIOS="--dist --vlt $sanitize" DRIVER_HASHSET=--hashset=0/2
|
||||
;;
|
||||
dist-vlt-1)
|
||||
"$MAKE" -C test_regress SCENARIOS="--dist --vlt" DRIVER_HASHSET=--hashset=1/2
|
||||
"$MAKE" -C test_regress SCENARIOS="--dist --vlt $sanitize" DRIVER_HASHSET=--hashset=1/2
|
||||
;;
|
||||
vltmt-0)
|
||||
"$MAKE" -C test_regress SCENARIOS=--vltmt DRIVER_HASHSET=--hashset=0/2
|
||||
@@ -92,6 +96,9 @@ elif [ "$TRAVIS_BUILD_STAGE_NAME" = "test" ]; then
|
||||
vltmt-1)
|
||||
"$MAKE" -C test_regress SCENARIOS=--vltmt DRIVER_HASHSET=--hashset=1/2
|
||||
;;
|
||||
coverage-all)
|
||||
nodist/code_coverage --stages 3-
|
||||
;;
|
||||
coverage-dist)
|
||||
nodist/code_coverage --stages 3- --scenarios=--dist
|
||||
;;
|
||||
@@ -130,5 +137,5 @@ elif [ "$TRAVIS_BUILD_STAGE_NAME" = "test" ]; then
|
||||
else
|
||||
##############################################################################
|
||||
# Unknown build stage
|
||||
fatal "Unknown build stage: '$TRAVIS_BUILD_STAGE_NAME'"
|
||||
fatal "Unknown build stage: '$CI_BUILD_STAGE_NAME'"
|
||||
fi
|
||||
@@ -40,7 +40,7 @@ RUN apt-get update \
|
||||
|
||||
WORKDIR /tmp
|
||||
|
||||
RUN cpan install -fi Unix::Processors Parallel::Forker Bit::Vector
|
||||
RUN cpan install -fi Parallel::Forker
|
||||
|
||||
RUN git clone https://github.com/veripool/vcddiff.git && \
|
||||
make -C vcddiff && \
|
||||
|
||||
@@ -27,5 +27,5 @@ if [ -e ${obj_dir} ]; then
|
||||
cp -r /usr/local/share/verilator/bin ${obj_dir}/vlt
|
||||
cp -r /usr/local/share/verilator/include ${obj_dir}/vlt
|
||||
# Point Makefile to that folder
|
||||
perl -i -pe 's/VERILATOR_ROOT = \/usr\/local\/share\/verilator/VERILATOR_ROOT = vlt/g' ${obj_dir}/*.mk
|
||||
sed -i 's/VERILATOR_ROOT = \/usr\/local\/share\/verilator/VERILATOR_ROOT = vlt/g' ${obj_dir}/*.mk
|
||||
fi
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# DESCRIPTION: Verilator: Travis CI ccache sizer
|
||||
#
|
||||
# Copyright 2020 by Geza Lore. This program is free software; you
|
||||
# can redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
#
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
################################################################################
|
||||
# This script computes the size of the ccache to be used for a job. We want the
|
||||
# ccache to be just big enough to be able to hold a whole build so a re-build
|
||||
# of the same does not miss in the cache due to capacity, but we don't want the
|
||||
# ccache too big as pulling it down from the network takes time, and it is
|
||||
# unlikely objects from much earlier builds would be useful.
|
||||
################################################################################
|
||||
|
||||
fatal() {
|
||||
echo "ERROR: $(basename "$0"): $1" >&2; exit 1;
|
||||
}
|
||||
|
||||
if [ "$TRAVIS_BUILD_STAGE_NAME" = "build" ]; then
|
||||
if [ "$COVERAGE" == 1 ]; then
|
||||
echo "1024M"
|
||||
else
|
||||
echo "768M"
|
||||
fi
|
||||
elif [ "$TRAVIS_BUILD_STAGE_NAME" = "test" ]; then
|
||||
if [[ $TESTS == coverage-* ]]; then
|
||||
echo "1536M"
|
||||
else
|
||||
echo "256M"
|
||||
fi
|
||||
else
|
||||
fatal "Unknown build stage: '$TRAVIS_BUILD_STAGE_NAME'"
|
||||
fi
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
# DESCRIPTION: codecov.io config
|
||||
#
|
||||
# Copyright 2020-2020 by Wilson Snyder. This program is free software; you
|
||||
# Copyright 2020-2021 by Wilson Snyder. This program is free software; you
|
||||
# can redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
@@ -15,7 +15,7 @@ codecov:
|
||||
coverage:
|
||||
precision: 2
|
||||
round: down
|
||||
range: "70...100"
|
||||
range: "50...100"
|
||||
ignore:
|
||||
- "ci"
|
||||
- "docs"
|
||||
|
||||
+7
-2
@@ -1,13 +1,13 @@
|
||||
# DESCRIPTION: Process this file with autoconf to produce a configure script.
|
||||
#
|
||||
# Copyright 2003-2020 by Wilson Snyder. Verilator is free software; you
|
||||
# Copyright 2003-2021 by Wilson Snyder. Verilator is free software; you
|
||||
# can redistribute it and/or modify it under the terms of either the GNU Lesser
|
||||
# General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
#AC_INIT([Verilator],[#.### YYYY-MM-DD])
|
||||
#AC_INIT([Verilator],[#.### devel])
|
||||
AC_INIT([Verilator],[4.102 2020-10-15],
|
||||
AC_INIT([Verilator],[4.108 2021-01-10],
|
||||
[https://verilator.org],
|
||||
[verilator],[https://verilator.org])
|
||||
# When releasing, also update header of Changes file
|
||||
@@ -139,6 +139,11 @@ if test "x$PERL" = "x" ; then
|
||||
AC_MSG_ERROR([Cannot find "perl" in your PATH, please install it])
|
||||
fi
|
||||
|
||||
AC_PATH_PROG(PYTHON3,python3)
|
||||
if test "x$PYTHON3" = "x" ; then
|
||||
AC_MSG_ERROR([Cannot find "python3" in your PATH, please install it])
|
||||
fi
|
||||
|
||||
AC_PATH_PROG(LEX,flex)
|
||||
if test "x$LEX" = "x" ; then
|
||||
AC_MSG_ERROR([Cannot find "flex" in your PATH, please install it])
|
||||
|
||||
@@ -27,8 +27,8 @@ contributions flow more efficiently.
|
||||
* You may attach a patch to the issue, or (preferred) may request a GitHub
|
||||
pull request.
|
||||
|
||||
** Verilator uses Travis CI to provide continuous integration. You may
|
||||
want to setup Travis CI on your GitHub branch to ensure your changes
|
||||
** Verilator uses GitHub Actions to provide continuous integration. You may
|
||||
want to enable Actions on your GitHub branch to ensure your changes
|
||||
keep the tests passing. See link:internals.adoc[docs/internals].
|
||||
|
||||
* Your source-code contributions must be certified as open source, under
|
||||
|
||||
@@ -27,13 +27,16 @@ James Hutchinson
|
||||
Jamey Hicks
|
||||
James Pallister
|
||||
Jan Van Winkel
|
||||
Jean Berniolles
|
||||
Jeremy Bennett
|
||||
John Coiner
|
||||
John Demme
|
||||
Josh Redford
|
||||
Julien Margetts
|
||||
Kaleb Barrett
|
||||
Kanad Kanhere
|
||||
Kevin Kiningham
|
||||
Krzysztof Bieganski
|
||||
Kuba Ober
|
||||
Ludwig Rogiers
|
||||
Lukasz Dalek
|
||||
@@ -41,13 +44,16 @@ Maarten De Braekeleer
|
||||
Maciej Sobkowski
|
||||
Marco Widmer
|
||||
Markus Krause
|
||||
Marlon James
|
||||
Marshal Qiao
|
||||
Matthew Ballance
|
||||
Michael Killough
|
||||
Mike Popoloski
|
||||
Nandu Raj
|
||||
Nathan Kohagen
|
||||
Nathan Myers
|
||||
Patrick Stewart
|
||||
Paul Wright
|
||||
Peter Horvath
|
||||
Peter Monsson
|
||||
Philipp Wagner
|
||||
@@ -68,6 +74,7 @@ Tobias Wölfel
|
||||
Todd Strader
|
||||
Tomasz Gorochowik
|
||||
Tymoteusz Blazejczyk
|
||||
Unai Martinez-Corral
|
||||
Victor Besyakov
|
||||
Vassilis Papaefstathiou
|
||||
Veripool API Bot
|
||||
@@ -76,3 +83,4 @@ Yossi Nivin
|
||||
Yuri Victorovich
|
||||
Yutetsu TAKATSUKASA
|
||||
Yves Mathieu
|
||||
HyungKi Jeong
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
#
|
||||
#*****************************************************************************
|
||||
#
|
||||
# Copyright 2003-2020 by Wilson Snyder. This program is free software; you
|
||||
# Copyright 2003-2021 by Wilson Snyder. This program is free software; you
|
||||
# can redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// DESCRIPTION: Verilator: List of To Do issues.
|
||||
//
|
||||
// Copyright 2004-2020 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2004-2021 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -84,7 +84,7 @@
|
||||
"if (a) { ... b=2; } else { ... b=2;}" -> "b=2; if ..."
|
||||
Careful though, as b could appear in the statement or multiple times in statement
|
||||
(Could just require exatly two 'b's in statement)
|
||||
** Simplify XOR/XNOR/AND/OR bit selection trees
|
||||
** Simplify XOR/AND/OR bit selection trees
|
||||
Foo = A[1] ^ A[2] ^ A[3] etc are better as ^ ( A & 32'b...1110 )
|
||||
** Combine variables into wider elements
|
||||
Parallel statements on different bits should become single signal
|
||||
|
||||
+1
-3
@@ -100,9 +100,7 @@ Those developing Verilator itself may also want these (see internals.adoc):
|
||||
|
||||
sudo apt-get install gdb asciidoctor graphviz cmake clang clang-format gprof lcov
|
||||
cpan install Pod::Perldoc
|
||||
cpan install Unix::Processors
|
||||
cpan install Parallel::Forker
|
||||
cpan install Bit::Vector
|
||||
|
||||
==== Install SystemC
|
||||
|
||||
@@ -299,7 +297,7 @@ or https://verilator.org/verilator_doc.pdf[Verilator manual (PDF)].
|
||||
|
||||
== License
|
||||
|
||||
Copyright 2008-2020 by Wilson Snyder. Verilator is free software; you can
|
||||
Copyright 2008-2021 by Wilson Snyder. Verilator is free software; you can
|
||||
redistribute it and/or modify it under the terms of either the GNU Lesser
|
||||
General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
+16
-20
@@ -409,8 +409,9 @@ style indentation; the `c-set-style` undoes that.)
|
||||
|
||||
* Comment every member variable.
|
||||
|
||||
Indentation is automatically maintained with "make clang-format" (using
|
||||
clang-format version 10.0.0). For those manually formatting:
|
||||
Indentation is automatically maintained with "make format" using
|
||||
clang-format version 10.0.0, and yapf for python, and is automatically
|
||||
corrected in the CI actions. For those manually formatting C++ code:
|
||||
|
||||
* Use 4 spaces per level, and no tabs.
|
||||
|
||||
@@ -628,8 +629,6 @@ https://github.com/veripool/vcddiff
|
||||
|
||||
* Cmake for build paths that use it.
|
||||
|
||||
* Bit::Vector to test vgen.pl
|
||||
|
||||
=== Controlling the Test Driver
|
||||
|
||||
Test drivers are written in PERL. All invoke the main test driver script,
|
||||
@@ -698,7 +697,7 @@ Verilator problem.
|
||||
When enabling the long tests, some additional PERL modules are needed,
|
||||
which you can install using cpan.
|
||||
|
||||
cpan install Unix::Processors
|
||||
cpan install Parallel::Forker
|
||||
|
||||
There are some traps to avoid when running regression tests
|
||||
|
||||
@@ -730,20 +729,17 @@ test, run the following command.
|
||||
|
||||
=== Continuous Integration
|
||||
|
||||
Verilator has a https://travis-ci.com/verilator/verilator[Travis CI environment]
|
||||
which automatically tests the master branch for test failures on new commits. It
|
||||
also runs a daily cron job to validate all of the tests against different OS and
|
||||
compiler versions.
|
||||
Verilator uses GitHub Actions which automatically tests the master branch
|
||||
for test failures on new commits. It also runs a daily cron job to validate
|
||||
all of the tests against different OS and compiler versions.
|
||||
|
||||
Developers can connect Travis CI to their GitHub account so that the CI
|
||||
environment can check their branches too by doing the following:
|
||||
Developers can enable Actions on their GitHub repository so that the CI
|
||||
environment can check their branches too by enabling the build workflow:
|
||||
|
||||
* Go to https://github.com/marketplace/travis-ci and follow the prompts
|
||||
|
||||
* Only the Open Source (FREE) version of Travis CI is required
|
||||
|
||||
* Under a Travis CI project click More options > Settings in order to set up a
|
||||
cron job on a particular branch
|
||||
* On GitHub, navigate to the main page of the repository.
|
||||
* Under your repository name, click Actions.
|
||||
* In the left sidebar, click the workflow you want to enable ("build").
|
||||
* Click Enable workflow.
|
||||
|
||||
=== Fuzzing
|
||||
|
||||
@@ -959,9 +955,9 @@ Then, when the watch fires, to break at every following change to that node:
|
||||
To print a node:
|
||||
|
||||
pn nodep
|
||||
# or: call nodep->dumpGdb() # aliased to "pn" in src/.gdbinit
|
||||
# or: call dumpGdb(nodep) # aliased to "pn" in src/.gdbinit
|
||||
pnt nodep
|
||||
# or: call nodep->dumpTreeGdb() # aliased to "pnt" in src/.gdbinit
|
||||
# or: call dumpTreeGdb(nodep) # aliased to "pnt" in src/.gdbinit
|
||||
|
||||
When GDB halts, it is useful to understand that the backtrace will commonly
|
||||
show the iterator functions between each invocation of `visit` in the
|
||||
@@ -1028,7 +1024,7 @@ IEEE 1800-2017 33 Config:: Little/no tool support or industry use.
|
||||
|
||||
== Distribution
|
||||
|
||||
Copyright 2008-2020 by Wilson Snyder. Verilator is free software; you can
|
||||
Copyright 2008-2021 by Wilson Snyder. Verilator is free software; you can
|
||||
redistribute it and/or modify it under the terms of either the GNU Lesser
|
||||
General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
+1
-1
@@ -66,7 +66,7 @@ elements in the `<module>` elements using the `dtype_id` attribute.
|
||||
|
||||
== Distribution
|
||||
|
||||
Copyright 2020-2020 by Wilson Snyder. Verilator is free software; you can
|
||||
Copyright 2020-2021 by Wilson Snyder. Verilator is free software; you can
|
||||
redistribute it and/or modify it under the terms of either the GNU Lesser
|
||||
General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
@@ -37,6 +37,6 @@ int main(int argc, char** argv, char** env) {
|
||||
// Destroy model
|
||||
delete top;
|
||||
|
||||
// Fin
|
||||
// Return good completion status
|
||||
exit(0);
|
||||
}
|
||||
|
||||
@@ -33,12 +33,13 @@ int sc_main(int argc, char* argv[]) {
|
||||
|
||||
// Simulate until $finish
|
||||
while (!Verilated::gotFinish()) {
|
||||
// Simulate 1ns
|
||||
sc_start(1, SC_NS);
|
||||
}
|
||||
|
||||
// Final model cleanup
|
||||
top->final();
|
||||
|
||||
// Fin
|
||||
// Return good completion status
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#include "Vtop.h"
|
||||
|
||||
#if VM_TRACE
|
||||
# include <verilated_vcd_c.h>
|
||||
#include <verilated_vcd_c.h>
|
||||
#endif
|
||||
|
||||
vluint64_t main_time = 0;
|
||||
@@ -70,6 +70,6 @@ int main(int argc, char** argv, char** env) {
|
||||
delete top;
|
||||
top = nullptr;
|
||||
|
||||
// Fin
|
||||
// Return good completion status
|
||||
exit(0);
|
||||
}
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
//======================================================================
|
||||
|
||||
// For std::unique_ptr
|
||||
#include <memory>
|
||||
|
||||
// Include common routines
|
||||
#include <verilated.h>
|
||||
|
||||
@@ -43,7 +46,8 @@ int main(int argc, char** argv, char** env) {
|
||||
Verilated::mkdir("logs");
|
||||
|
||||
// Construct the Verilated model, from Vtop.h generated from Verilating "top.v"
|
||||
Vtop* top = new Vtop; // Or use a const unique_ptr, or the VL_UNIQUE_PTR wrapper
|
||||
// Using unique_ptr is similar to "Vtop* top = new Vtop" then deleting at end
|
||||
const std::unique_ptr<Vtop> top{new Vtop};
|
||||
|
||||
// Set some inputs
|
||||
top->reset_l = !0;
|
||||
@@ -97,10 +101,6 @@ int main(int argc, char** argv, char** env) {
|
||||
VerilatedCov::write("logs/coverage.dat");
|
||||
#endif
|
||||
|
||||
// Destroy model
|
||||
delete top;
|
||||
top = nullptr;
|
||||
|
||||
// Fin
|
||||
// Return good completion status
|
||||
exit(0);
|
||||
}
|
||||
|
||||
@@ -6,6 +6,9 @@
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
//======================================================================
|
||||
|
||||
// For std::unique_ptr
|
||||
#include <memory>
|
||||
|
||||
// SystemC global header
|
||||
#include <systemc.h>
|
||||
|
||||
@@ -45,20 +48,22 @@ int sc_main(int argc, char* argv[]) {
|
||||
ios::sync_with_stdio();
|
||||
|
||||
// Define clocks
|
||||
sc_clock clk("clk", 10, SC_NS, 0.5, 3, SC_NS, true);
|
||||
sc_clock fastclk("fastclk", 2, SC_NS, 0.5, 2, SC_NS, true);
|
||||
sc_clock clk{"clk", 10, SC_NS, 0.5, 3, SC_NS, true};
|
||||
sc_clock fastclk{"fastclk", 2, SC_NS, 0.5, 2, SC_NS, true};
|
||||
|
||||
// Define interconnect
|
||||
sc_signal<bool> reset_l;
|
||||
sc_signal<vluint32_t> in_small;
|
||||
sc_signal<vluint64_t> in_quad;
|
||||
sc_signal<sc_bv<70> > in_wide;
|
||||
sc_signal<sc_bv<70>> in_wide;
|
||||
sc_signal<vluint32_t> out_small;
|
||||
sc_signal<vluint64_t> out_quad;
|
||||
sc_signal<sc_bv<70> > out_wide;
|
||||
sc_signal<sc_bv<70>> out_wide;
|
||||
|
||||
// Construct the Verilated model, from inside Vtop.h
|
||||
Vtop* top = new Vtop("top");
|
||||
// Using unique_ptr is similar to "Vtop* top = new Vtop" then deleting at end
|
||||
const std::unique_ptr<Vtop> top{new Vtop{"top"}};
|
||||
|
||||
// Attach signals to the model
|
||||
top->clk(clk);
|
||||
top->fastclk(fastclk);
|
||||
@@ -129,10 +134,6 @@ int sc_main(int argc, char* argv[]) {
|
||||
VerilatedCov::write("logs/coverage.dat");
|
||||
#endif
|
||||
|
||||
// Destroy model
|
||||
delete top;
|
||||
top = nullptr;
|
||||
|
||||
// Fin
|
||||
// Return good completion status
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -22,9 +22,9 @@ VERILATOR = $(VERILATOR_ROOT)/bin/verilator
|
||||
endif
|
||||
|
||||
DOT = dot
|
||||
PYTHON = python3
|
||||
PYTHON3 = python3
|
||||
|
||||
PYTHON_VERSION := $(shell ${PYTHON} --version 2>&1)
|
||||
PYTHON_VERSION := $(shell ${PYTHON3} --version 2>&1)
|
||||
PYTHON_VERSION_FULL := $(wordlist 2,4,$(subst ., ,${PYTHON_VERSION}))
|
||||
PYTHON_VERSION_MAJOR := $(word 1,${PYTHON_VERSION_FULL})
|
||||
PYTHON_VERSION_MINOR := $(word 2,${PYTHON_VERSION_FULL})
|
||||
@@ -45,13 +45,13 @@ test: \
|
||||
|
||||
test-vl_file_copy:
|
||||
@echo "-- vl_file_copy example"
|
||||
$(PYTHON) vl_file_copy -odir copied top.v
|
||||
$(PYTHON3) vl_file_copy -odir copied top.v
|
||||
@cmp copied/top.v top.v
|
||||
@cmp copied/sub.v sub.v
|
||||
|
||||
test-vl_hier_graph:
|
||||
@echo "-- vl_hier_graph example"
|
||||
$(PYTHON) vl_hier_graph -o graph.dot top.v
|
||||
$(PYTHON3) vl_hier_graph -o graph.dot top.v
|
||||
@echo "Manually run: " $(DOT) -Tpdf -o graph.pdf graph.dot
|
||||
|
||||
######################################################################
|
||||
|
||||
@@ -10,24 +10,29 @@ import sys
|
||||
import tempfile
|
||||
import xml.etree.ElementTree as ET
|
||||
from shutil import copy2
|
||||
from pprint import pprint,pformat
|
||||
from pprint import pprint, pformat
|
||||
|
||||
#######################################################################
|
||||
|
||||
|
||||
class VlFileCopy:
|
||||
def __init__(self,
|
||||
verilator_args, # presently all verilator options are passed-thru
|
||||
# ideally this script would check against options mentioned in help
|
||||
debug=0,
|
||||
output_dir='copied'): # directory name we output file uses
|
||||
def __init__(
|
||||
self,
|
||||
verilator_args, # presently all verilator options are passed-thru
|
||||
# ideally this script would check against options mentioned in help
|
||||
debug=0,
|
||||
output_dir='copied'): # directory name we output file uses
|
||||
self.debug = debug
|
||||
|
||||
xml_temp = tempfile.NamedTemporaryFile()
|
||||
|
||||
args = ['--xml-output', xml_temp.name,
|
||||
'--bbox-sys', # Parse some stuff can't translate
|
||||
'--bbox-unsup',
|
||||
'--prefix vlxml'] # So we know name of .xml output
|
||||
args = [
|
||||
'--xml-output',
|
||||
xml_temp.name,
|
||||
'--bbox-sys', # Parse some stuff can't translate
|
||||
'--bbox-unsup',
|
||||
'--prefix vlxml'
|
||||
] # So we know name of .xml output
|
||||
args += verilator_args
|
||||
self.run_verilator(args)
|
||||
self.tree = ET.parse(xml_temp.name)
|
||||
@@ -55,16 +60,18 @@ class VlFileCopy:
|
||||
print("\t%s " % command)
|
||||
status = subprocess.call(command, shell=True)
|
||||
if status != 0:
|
||||
raise Exception("Command failed running Verilator with '"+command+"', stopped")
|
||||
raise Exception("Command failed running Verilator with '" +
|
||||
command + "', stopped")
|
||||
|
||||
|
||||
#######################################################################
|
||||
|
||||
if __name__=='__main__':
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(
|
||||
allow_abbrev=False,
|
||||
formatter_class=argparse.RawTextHelpFormatter,
|
||||
description=
|
||||
"""Example of using Verilator XML output to copy a list of files to an
|
||||
"""Example of using Verilator XML output to copy a list of files to an
|
||||
output directory (-odir, defaults to 'copied'), e.g. to easily create a
|
||||
tarball of the design to pass to others.
|
||||
|
||||
@@ -72,8 +79,7 @@ Example usage:
|
||||
vl_file_copy -f input.vc top.v -odir mycopy
|
||||
# This will make at least mycopy/top.v
|
||||
""",
|
||||
epilog=
|
||||
"""All other arguments are pass-thru to Verilator: e.g.:
|
||||
epilog="""All other arguments are pass-thru to Verilator: e.g.:
|
||||
|
||||
+define+<var>=<value> Set preprocessor define
|
||||
-F <file> Parse options from a file, relatively
|
||||
@@ -87,26 +93,30 @@ Example usage:
|
||||
This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
any use, without warranty, 2019 by Wilson Snyder.
|
||||
SPDX-License-Identifier: CC0-1.0
|
||||
"""
|
||||
)
|
||||
parser.add_argument('-debug', '--debug',
|
||||
action='store_const', const=9,
|
||||
""")
|
||||
parser.add_argument('-debug',
|
||||
'--debug',
|
||||
action='store_const',
|
||||
const=9,
|
||||
help='enable debug')
|
||||
parser.add_argument('-odir', '--odir',
|
||||
action='store', metavar='directory', required=True,
|
||||
parser.add_argument('-odir',
|
||||
'--odir',
|
||||
action='store',
|
||||
metavar='directory',
|
||||
required=True,
|
||||
help='target output directory')
|
||||
(args, rem) = parser.parse_known_args()
|
||||
|
||||
print("NOTE: vl_file_copy is only an example starting point for writing your own tool.")
|
||||
print(
|
||||
"NOTE: vl_file_copy is only an example starting point for writing your own tool."
|
||||
)
|
||||
# That is:
|
||||
# 1. We will accept basic patches
|
||||
# 2. We are not expecting to make this globally useful. (e.g. we don't cleanup obj_dir)
|
||||
# 3. "make install" will not install this.
|
||||
# 4. This has not had production-worthy validation.
|
||||
|
||||
fc = VlFileCopy(output_dir = args.odir,
|
||||
debug = args.debug,
|
||||
verilator_args = rem)
|
||||
fc = VlFileCopy(output_dir=args.odir, debug=args.debug, verilator_args=rem)
|
||||
|
||||
######################################################################
|
||||
### Local Variables:
|
||||
|
||||
@@ -10,26 +10,31 @@ import sys
|
||||
import tempfile
|
||||
import xml.etree.ElementTree as ET
|
||||
from shutil import copy2
|
||||
from pprint import pprint,pformat
|
||||
from pprint import pprint, pformat
|
||||
|
||||
#######################################################################
|
||||
|
||||
|
||||
class VlHierGraph:
|
||||
def __init__(self,
|
||||
verilator_args, # presently all verilator options are passed-thru
|
||||
# ideally this script would check against options mentioned in help
|
||||
debug=0,
|
||||
output_filename='graph.dot'): # output filename
|
||||
def __init__(
|
||||
self,
|
||||
verilator_args, # presently all verilator options are passed-thru
|
||||
# ideally this script would check against options mentioned in help
|
||||
debug=0,
|
||||
output_filename='graph.dot'): # output filename
|
||||
self.debug = debug
|
||||
self.next_vertex_number = 0
|
||||
self.name_to_number = {}
|
||||
|
||||
xml_temp = tempfile.NamedTemporaryFile()
|
||||
|
||||
args = ['--xml-output', xml_temp.name,
|
||||
'--bbox-sys', # Parse some stuff can't translate
|
||||
'--bbox-unsup',
|
||||
'--prefix vlxml'] # So we know name of .xml output
|
||||
args = [
|
||||
'--xml-output',
|
||||
xml_temp.name,
|
||||
'--bbox-sys', # Parse some stuff can't translate
|
||||
'--bbox-unsup',
|
||||
'--prefix vlxml'
|
||||
] # So we know name of .xml output
|
||||
args += verilator_args
|
||||
self.run_verilator(args)
|
||||
self.tree = ET.parse(xml_temp.name)
|
||||
@@ -39,7 +44,9 @@ class VlHierGraph:
|
||||
fh.write("digraph {\n")
|
||||
fh.write(" dpi=300;\n")
|
||||
fh.write(" order=LR;\n")
|
||||
fh.write(" node [fontsize=8 shape=\"box\" margin=0.01 width=0 height=0]")
|
||||
fh.write(
|
||||
" node [fontsize=8 shape=\"box\" margin=0.01 width=0 height=0]"
|
||||
)
|
||||
fh.write(" edge [fontsize=6]")
|
||||
# Find cells
|
||||
root = self.tree.getroot()
|
||||
@@ -48,8 +55,7 @@ class VlHierGraph:
|
||||
# origNames are before parameterization, name if after
|
||||
mod_name = module.get('name')
|
||||
mod_number = self.name_to_vertex_number(mod_name)
|
||||
fh.write(" n%d [label=\"%s\""
|
||||
% (mod_number, mod_name))
|
||||
fh.write(" n%d [label=\"%s\"" % (mod_number, mod_name))
|
||||
if module.get('topModule'):
|
||||
fh.write(" color=\"red\" rank=1")
|
||||
fh.write("];\n")
|
||||
@@ -58,8 +64,8 @@ class VlHierGraph:
|
||||
inst_name = instance.get('name')
|
||||
def_name = instance.get('defName')
|
||||
def_number = self.name_to_vertex_number(def_name)
|
||||
fh.write(" n%d->n%d [label=\"%s\"];\n"
|
||||
% (mod_number, def_number, inst_name));
|
||||
fh.write(" n%d->n%d [label=\"%s\"];\n" %
|
||||
(mod_number, def_number, inst_name))
|
||||
|
||||
fh.write("}\n")
|
||||
|
||||
@@ -80,24 +86,25 @@ class VlHierGraph:
|
||||
print("\t%s " % command)
|
||||
status = subprocess.call(command, shell=True)
|
||||
if status != 0:
|
||||
raise Exception("Command failed running Verilator with '"+command+"', stopped")
|
||||
raise Exception("Command failed running Verilator with '" +
|
||||
command + "', stopped")
|
||||
|
||||
|
||||
#######################################################################
|
||||
|
||||
if __name__=='__main__':
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(
|
||||
allow_abbrev=False,
|
||||
formatter_class=argparse.RawTextHelpFormatter,
|
||||
description=
|
||||
"""Example of using Verilator XML output to create a .dot file showing the
|
||||
"""Example of using Verilator XML output to create a .dot file showing the
|
||||
design module hierarchy.
|
||||
|
||||
Example usage:
|
||||
vl_hier_graph -f input.vc top.v -o graph.dot
|
||||
dot -Tpdf -o graph.pdf graph.dot
|
||||
""",
|
||||
epilog=
|
||||
"""All other arguments are pass-thru to Verilator: e.g.:
|
||||
epilog="""All other arguments are pass-thru to Verilator: e.g.:
|
||||
|
||||
+define+<var>=<value> Set preprocessor define
|
||||
-F <file> Parse options from a file, relatively
|
||||
@@ -111,26 +118,32 @@ Example usage:
|
||||
This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
any use, without warranty, 2019 by Wilson Snyder.
|
||||
SPDX-License-Identifier: CC0-1.0
|
||||
"""
|
||||
)
|
||||
parser.add_argument('-debug', '--debug',
|
||||
action='store_const', const=9,
|
||||
""")
|
||||
parser.add_argument('-debug',
|
||||
'--debug',
|
||||
action='store_const',
|
||||
const=9,
|
||||
help='enable debug')
|
||||
parser.add_argument('-o', '--o',
|
||||
action='store', metavar='filename', required=True,
|
||||
parser.add_argument('-o',
|
||||
'--o',
|
||||
action='store',
|
||||
metavar='filename',
|
||||
required=True,
|
||||
help='output filename')
|
||||
(args, rem) = parser.parse_known_args()
|
||||
|
||||
print("NOTE: vl_hier_graph is only an example starting point for writing your own tool.")
|
||||
print(
|
||||
"NOTE: vl_hier_graph is only an example starting point for writing your own tool."
|
||||
)
|
||||
# That is:
|
||||
# 1. We will accept basic patches
|
||||
# 2. We are not expecting to make this globally useful. (e.g. we don't cleanup obj_dir)
|
||||
# 3. "make install" will not install this.
|
||||
# 4. This has not had production-worthy validation.
|
||||
|
||||
fc = VlHierGraph(output_filename = args.o,
|
||||
debug = args.debug,
|
||||
verilator_args = rem)
|
||||
fc = VlHierGraph(output_filename=args.o,
|
||||
debug=args.debug,
|
||||
verilator_args=rem)
|
||||
|
||||
######################################################################
|
||||
### Local Variables:
|
||||
|
||||
@@ -1806,6 +1806,7 @@ xc->already_in_flush = 0;
|
||||
static void *fstWriterFlushContextPrivate1(void *ctx)
|
||||
{
|
||||
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
|
||||
struct fstWriterContext *xc_parent;
|
||||
|
||||
pthread_mutex_lock(&(xc->xc_parent->mutex));
|
||||
fstWriterFlushContextPrivate2(xc);
|
||||
@@ -1816,10 +1817,11 @@ free(xc->curval_mem);
|
||||
free(xc->valpos_mem);
|
||||
free(xc->vchg_mem);
|
||||
tmpfile_close(&xc->tchn_handle, &xc->tchn_handle_nam);
|
||||
xc_parent = xc->xc_parent;
|
||||
free(xc);
|
||||
|
||||
xc->xc_parent->in_pthread = 0;
|
||||
pthread_mutex_unlock(&(xc->xc_parent->mutex));
|
||||
xc_parent->in_pthread = 0;
|
||||
pthread_mutex_unlock(&(xc_parent->mutex));
|
||||
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
+244
-205
@@ -1,7 +1,7 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2020 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2021 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -61,7 +61,7 @@ typedef union {
|
||||
// Global variables
|
||||
|
||||
// Slow path variables
|
||||
VerilatedMutex Verilated::m_mutex;
|
||||
VerilatedMutex Verilated::s_mutex;
|
||||
|
||||
// Keep below together in one cache line
|
||||
Verilated::Serialized Verilated::s_s;
|
||||
@@ -72,10 +72,27 @@ Verilated::CommandArgValues Verilated::s_args;
|
||||
|
||||
VerilatedImp::VerilatedImpU VerilatedImp::s_s;
|
||||
|
||||
struct VerilatedImpInitializer {
|
||||
VerilatedImpInitializer() { VerilatedImp::setup(); }
|
||||
~VerilatedImpInitializer() { VerilatedImp::teardown(); }
|
||||
} g_VerilatedImpInitializer;
|
||||
// Guarantees to call setup() and teardown() just once.
|
||||
struct VerilatedInitializer {
|
||||
VerilatedInitializer() { setup(); }
|
||||
~VerilatedInitializer() { teardown(); }
|
||||
void setup() {
|
||||
static bool done = false;
|
||||
if (!done) {
|
||||
VerilatedImp::setup();
|
||||
Verilated::s_ns.setup();
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
void teardown() {
|
||||
static bool done = false;
|
||||
if (!done) {
|
||||
VerilatedImp::teardown();
|
||||
Verilated::s_ns.teardown();
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
} s_VerilatedInitializer;
|
||||
|
||||
//===========================================================================
|
||||
// User definable functions
|
||||
@@ -256,14 +273,13 @@ Verilated::Serialized::Serialized() {
|
||||
s_errorLimit = 1;
|
||||
s_randReset = 0;
|
||||
s_randSeed = 0;
|
||||
s_randSeedEpoch = 1;
|
||||
s_timeunit = VL_TIME_UNIT; // Initial value until overriden by _Vconfigure
|
||||
s_timeprecision = VL_TIME_PRECISION; // Initial value until overriden by _Vconfigure
|
||||
}
|
||||
|
||||
Verilated::NonSerialized::NonSerialized() {
|
||||
s_profThreadsFilenamep = strdup("profile_threads.dat");
|
||||
}
|
||||
Verilated::NonSerialized::~NonSerialized() {
|
||||
void Verilated::NonSerialized::setup() { s_profThreadsFilenamep = strdup("profile_threads.dat"); }
|
||||
void Verilated::NonSerialized::teardown() {
|
||||
if (s_profThreadsFilenamep) {
|
||||
VL_DO_CLEAR(free(const_cast<char*>(s_profThreadsFilenamep)),
|
||||
s_profThreadsFilenamep = nullptr);
|
||||
@@ -279,6 +295,8 @@ void* Verilated::serialized2Ptr() VL_MT_UNSAFE { return &VerilatedImp::s_s.v.m_s
|
||||
static vluint32_t vl_sys_rand32() VL_MT_UNSAFE {
|
||||
// Return random 32-bits using system library.
|
||||
// Used only to construct seed for Verilator's PNRG.
|
||||
static VerilatedMutex s_mutex;
|
||||
const VerilatedLockGuard lock(s_mutex); // Otherwise rand is unsafe
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
// Windows doesn't have lrand48(), although Cygwin does.
|
||||
return (rand() << 16) ^ rand();
|
||||
@@ -288,29 +306,18 @@ static vluint32_t vl_sys_rand32() VL_MT_UNSAFE {
|
||||
}
|
||||
|
||||
vluint64_t vl_rand64() VL_MT_SAFE {
|
||||
static VerilatedMutex s_mutex;
|
||||
static VL_THREAD_LOCAL bool t_seeded = false;
|
||||
static VL_THREAD_LOCAL vluint32_t t_seedEpoch = 0;
|
||||
static VL_THREAD_LOCAL vluint64_t t_state[2];
|
||||
if (VL_UNLIKELY(!t_seeded)) {
|
||||
t_seeded = true;
|
||||
{
|
||||
const VerilatedLockGuard lock(s_mutex);
|
||||
if (Verilated::randSeed() != 0) {
|
||||
t_state[0] = ((static_cast<vluint64_t>(Verilated::randSeed()) << 32)
|
||||
^ (static_cast<vluint64_t>(Verilated::randSeed())));
|
||||
t_state[1] = ((static_cast<vluint64_t>(Verilated::randSeed()) << 32)
|
||||
^ (static_cast<vluint64_t>(Verilated::randSeed())));
|
||||
} else {
|
||||
t_state[0] = ((static_cast<vluint64_t>(vl_sys_rand32()) << 32)
|
||||
^ (static_cast<vluint64_t>(vl_sys_rand32())));
|
||||
t_state[1] = ((static_cast<vluint64_t>(vl_sys_rand32()) << 32)
|
||||
^ (static_cast<vluint64_t>(vl_sys_rand32())));
|
||||
}
|
||||
// Fix state as algorithm is slow to randomize if many zeros
|
||||
// This causes a loss of ~ 1 bit of seed entropy, no big deal
|
||||
if (VL_COUNTONES_I(t_state[0]) < 10) t_state[0] = ~t_state[0];
|
||||
if (VL_COUNTONES_I(t_state[1]) < 10) t_state[1] = ~t_state[1];
|
||||
}
|
||||
// For speed, we use a thread-local epoch number to know when to reseed
|
||||
if (VL_UNLIKELY(t_seedEpoch != Verilated::randSeedEpoch())) {
|
||||
// Set epoch before state, in case races with new seeding
|
||||
t_seedEpoch = Verilated::randSeedEpoch();
|
||||
t_state[0] = Verilated::randSeedDefault64();
|
||||
t_state[1] = t_state[0];
|
||||
// Fix state as algorithm is slow to randomize if many zeros
|
||||
// This causes a loss of ~ 1 bit of seed entropy, no big deal
|
||||
if (VL_COUNTONES_I(t_state[0]) < 10) t_state[0] = ~t_state[0];
|
||||
if (VL_COUNTONES_I(t_state[1]) < 10) t_state[1] = ~t_state[1];
|
||||
}
|
||||
// Xoroshiro128+ algorithm
|
||||
vluint64_t result = t_state[0] + t_state[1];
|
||||
@@ -334,6 +341,11 @@ WDataOutP VL_RANDOM_W(int obits, WDataOutP outwp) VL_MT_SAFE {
|
||||
}
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
IData VL_RANDOM_SEEDED_II(int obits, IData seed) VL_MT_SAFE {
|
||||
Verilated::randSeed(static_cast<int>(seed));
|
||||
return VL_RANDOM_I(obits);
|
||||
}
|
||||
|
||||
IData VL_RAND_RESET_I(int obits) VL_MT_SAFE {
|
||||
if (Verilated::randReset() == 0) return 0;
|
||||
IData data = ~0;
|
||||
@@ -556,7 +568,7 @@ WDataOutP VL_POWSS_WWW(int obits, int, int rbits, WDataOutP owp, WDataInP lwp, W
|
||||
return owp;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return owp;
|
||||
}
|
||||
return VL_POW_WWW(obits, rbits, rbits, owp, lwp, rwp);
|
||||
}
|
||||
@@ -688,7 +700,7 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
|
||||
// Note uses a single buffer internally; presumes only one usage per printf
|
||||
// Note also assumes variables < 64 are not wide, this assumption is
|
||||
// sometimes not true in low-level routines written here in verilated.cpp
|
||||
static VL_THREAD_LOCAL char tmp[VL_VALUE_STRING_MAX_WIDTH];
|
||||
static VL_THREAD_LOCAL char t_tmp[VL_VALUE_STRING_MAX_WIDTH];
|
||||
const char* pctp = nullptr; // Most recent %##.##g format
|
||||
bool inPct = false;
|
||||
bool widthSet = false;
|
||||
@@ -766,11 +778,11 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
|
||||
if (lbits) {} // UNUSED - always 64
|
||||
if (fmt == '^') { // Realtime
|
||||
if (!widthSet) width = VerilatedImp::timeFormatWidth();
|
||||
output += _vl_vsformat_time(tmp, d, left, width);
|
||||
output += _vl_vsformat_time(t_tmp, d, left, width);
|
||||
} else {
|
||||
std::string fmts(pctp, pos - pctp + 1);
|
||||
sprintf(tmp, fmts.c_str(), d);
|
||||
output += tmp;
|
||||
sprintf(t_tmp, fmts.c_str(), d);
|
||||
output += t_tmp;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -814,9 +826,9 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
|
||||
int digits = 0;
|
||||
std::string append;
|
||||
if (lbits <= VL_QUADSIZE) {
|
||||
digits = sprintf(tmp, "%" VL_PRI64 "d",
|
||||
digits = sprintf(t_tmp, "%" VL_PRI64 "d",
|
||||
static_cast<vlsint64_t>(VL_EXTENDS_QQ(lbits, lbits, ld)));
|
||||
append = tmp;
|
||||
append = t_tmp;
|
||||
} else {
|
||||
if (VL_SIGN_E(lbits, lwp[VL_WORDS_I(lbits) - 1])) {
|
||||
WData neg[VL_VALUE_STRING_MAX_WIDTH / 4 + 2];
|
||||
@@ -843,8 +855,8 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
|
||||
int digits = 0;
|
||||
std::string append;
|
||||
if (lbits <= VL_QUADSIZE) {
|
||||
digits = sprintf(tmp, "%" VL_PRI64 "u", ld);
|
||||
append = tmp;
|
||||
digits = sprintf(t_tmp, "%" VL_PRI64 "u", ld);
|
||||
append = t_tmp;
|
||||
} else {
|
||||
append = VL_DECIMAL_NW(lbits, lwp);
|
||||
digits = append.length();
|
||||
@@ -863,7 +875,7 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
|
||||
}
|
||||
case 't': { // Time
|
||||
if (!widthSet) width = VerilatedImp::timeFormatWidth();
|
||||
output += _vl_vsformat_time(tmp, static_cast<double>(ld), left, width);
|
||||
output += _vl_vsformat_time(t_tmp, static_cast<double>(ld), left, width);
|
||||
break;
|
||||
}
|
||||
case 'b':
|
||||
@@ -1037,7 +1049,7 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
|
||||
// Read a Verilog $sscanf/$fscanf style format into the output list
|
||||
// The format must be pre-processed (and lower cased) by Verilator
|
||||
// Arguments are in "width, arg-value (or WDataIn* if wide)" form
|
||||
static VL_THREAD_LOCAL char tmp[VL_VALUE_STRING_MAX_WIDTH];
|
||||
static VL_THREAD_LOCAL char t_tmp[VL_VALUE_STRING_MAX_WIDTH];
|
||||
int floc = fbits - 1;
|
||||
IData got = 0;
|
||||
bool inPct = false;
|
||||
@@ -1045,7 +1057,7 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
|
||||
const char* pos = formatp;
|
||||
for (; *pos && !_vl_vsss_eof(fp, floc); ++pos) {
|
||||
// VL_DBG_MSGF("_vlscan fmt='"<<pos[0]<<"' floc="<<floc<<" file='"<<_vl_vsss_peek(fp, floc,
|
||||
// fromp, fstr)<<"'"<<endl);
|
||||
// fromp, fstr)<<"'\n");
|
||||
if (!inPct && pos[0] == '%') {
|
||||
inPct = true;
|
||||
inIgnore = false;
|
||||
@@ -1079,7 +1091,17 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
|
||||
WData qowp[VL_WQ_WORDS_E];
|
||||
VL_SET_WQ(qowp, 0ULL);
|
||||
WDataOutP owp = qowp;
|
||||
if (obits > VL_QUADSIZE) owp = va_arg(ap, WDataOutP);
|
||||
if (obits == -1) { // string
|
||||
owp = nullptr;
|
||||
if (VL_UNCOVERABLE(fmt != 's')) {
|
||||
VL_FATAL_MT(
|
||||
__FILE__, __LINE__, "",
|
||||
"Internal: format other than %s is passed to string"); // LCOV_EXCL_LINE
|
||||
}
|
||||
} else if (obits > VL_QUADSIZE) {
|
||||
owp = va_arg(ap, WDataOutP);
|
||||
}
|
||||
|
||||
for (int i = 0; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
|
||||
switch (fmt) {
|
||||
case 'c': {
|
||||
@@ -1091,22 +1113,24 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
|
||||
}
|
||||
case 's': {
|
||||
_vl_vsss_skipspace(fp, floc, fromp, fstr);
|
||||
_vl_vsss_read_str(fp, floc, fromp, fstr, tmp, nullptr);
|
||||
if (!tmp[0]) goto done;
|
||||
int lpos = (static_cast<int>(strlen(tmp))) - 1;
|
||||
int lsb = 0;
|
||||
for (int i = 0; i < obits && lpos >= 0; --lpos) {
|
||||
_vl_vsss_setbit(owp, obits, lsb, 8, tmp[lpos]);
|
||||
lsb += 8;
|
||||
_vl_vsss_read_str(fp, floc, fromp, fstr, t_tmp, nullptr);
|
||||
if (!t_tmp[0]) goto done;
|
||||
if (owp) {
|
||||
int lpos = (static_cast<int>(strlen(t_tmp))) - 1;
|
||||
int lsb = 0;
|
||||
for (int i = 0; i < obits && lpos >= 0; --lpos) {
|
||||
_vl_vsss_setbit(owp, obits, lsb, 8, t_tmp[lpos]);
|
||||
lsb += 8;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'd': { // Signed decimal
|
||||
_vl_vsss_skipspace(fp, floc, fromp, fstr);
|
||||
_vl_vsss_read_str(fp, floc, fromp, fstr, tmp, "0123456789+-xXzZ?_");
|
||||
if (!tmp[0]) goto done;
|
||||
_vl_vsss_read_str(fp, floc, fromp, fstr, t_tmp, "0123456789+-xXzZ?_");
|
||||
if (!t_tmp[0]) goto done;
|
||||
vlsint64_t ld = 0;
|
||||
sscanf(tmp, "%30" VL_PRI64 "d", &ld);
|
||||
sscanf(t_tmp, "%30" VL_PRI64 "d", &ld);
|
||||
VL_SET_WQ(owp, ld);
|
||||
break;
|
||||
}
|
||||
@@ -1114,46 +1138,47 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
|
||||
case 'e':
|
||||
case 'g': { // Real number
|
||||
_vl_vsss_skipspace(fp, floc, fromp, fstr);
|
||||
_vl_vsss_read_str(fp, floc, fromp, fstr, tmp, "+-.0123456789eE");
|
||||
if (!tmp[0]) goto done;
|
||||
_vl_vsss_read_str(fp, floc, fromp, fstr, t_tmp, "+-.0123456789eE");
|
||||
if (!t_tmp[0]) goto done;
|
||||
// cppcheck-suppress unusedStructMember // It's used
|
||||
union {
|
||||
double r;
|
||||
vlsint64_t ld;
|
||||
} u;
|
||||
u.r = strtod(tmp, nullptr);
|
||||
u.r = strtod(t_tmp, nullptr);
|
||||
VL_SET_WQ(owp, u.ld);
|
||||
break;
|
||||
}
|
||||
case 't': // FALLTHRU // Time
|
||||
case '#': { // Unsigned decimal
|
||||
_vl_vsss_skipspace(fp, floc, fromp, fstr);
|
||||
_vl_vsss_read_str(fp, floc, fromp, fstr, tmp, "0123456789+-xXzZ?_");
|
||||
if (!tmp[0]) goto done;
|
||||
_vl_vsss_read_str(fp, floc, fromp, fstr, t_tmp, "0123456789+-xXzZ?_");
|
||||
if (!t_tmp[0]) goto done;
|
||||
QData ld = 0;
|
||||
sscanf(tmp, "%30" VL_PRI64 "u", &ld);
|
||||
sscanf(t_tmp, "%30" VL_PRI64 "u", &ld);
|
||||
VL_SET_WQ(owp, ld);
|
||||
break;
|
||||
}
|
||||
case 'b': {
|
||||
_vl_vsss_skipspace(fp, floc, fromp, fstr);
|
||||
_vl_vsss_read_str(fp, floc, fromp, fstr, tmp, "01xXzZ?_");
|
||||
if (!tmp[0]) goto done;
|
||||
_vl_vsss_based(owp, obits, 1, tmp, 0, strlen(tmp));
|
||||
_vl_vsss_read_str(fp, floc, fromp, fstr, t_tmp, "01xXzZ?_");
|
||||
if (!t_tmp[0]) goto done;
|
||||
_vl_vsss_based(owp, obits, 1, t_tmp, 0, strlen(t_tmp));
|
||||
break;
|
||||
}
|
||||
case 'o': {
|
||||
_vl_vsss_skipspace(fp, floc, fromp, fstr);
|
||||
_vl_vsss_read_str(fp, floc, fromp, fstr, tmp, "01234567xXzZ?_");
|
||||
if (!tmp[0]) goto done;
|
||||
_vl_vsss_based(owp, obits, 3, tmp, 0, strlen(tmp));
|
||||
_vl_vsss_read_str(fp, floc, fromp, fstr, t_tmp, "01234567xXzZ?_");
|
||||
if (!t_tmp[0]) goto done;
|
||||
_vl_vsss_based(owp, obits, 3, t_tmp, 0, strlen(t_tmp));
|
||||
break;
|
||||
}
|
||||
case 'x': {
|
||||
_vl_vsss_skipspace(fp, floc, fromp, fstr);
|
||||
_vl_vsss_read_str(fp, floc, fromp, fstr, tmp, "0123456789abcdefABCDEFxXzZ?_");
|
||||
if (!tmp[0]) goto done;
|
||||
_vl_vsss_based(owp, obits, 4, tmp, 0, strlen(tmp));
|
||||
_vl_vsss_read_str(fp, floc, fromp, fstr, t_tmp,
|
||||
"0123456789abcdefABCDEFxXzZ?_");
|
||||
if (!t_tmp[0]) goto done;
|
||||
_vl_vsss_based(owp, obits, 4, t_tmp, 0, strlen(t_tmp));
|
||||
break;
|
||||
}
|
||||
case 'u': {
|
||||
@@ -1194,6 +1219,9 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
|
||||
if (!inIgnore) ++got;
|
||||
// Reload data if non-wide (if wide, we put it in the right place directly)
|
||||
if (obits == 0) { // Due to inIgnore
|
||||
} else if (obits == -1) { // string
|
||||
std::string* p = va_arg(ap, std::string*);
|
||||
*p = t_tmp;
|
||||
} else if (obits <= VL_BYTESIZE) {
|
||||
CData* p = va_arg(ap, CData*);
|
||||
*p = owp[0];
|
||||
@@ -1252,36 +1280,44 @@ void _VL_STRING_TO_VINT(int obits, void* destp, size_t srclen, const char* srcp)
|
||||
for (; i < bytes; ++i) { *op++ = 0; }
|
||||
}
|
||||
|
||||
IData VL_FGETS_IXI(int obits, void* destp, IData fpi) VL_MT_SAFE {
|
||||
static IData getLine(std::string& str, IData fpi, size_t maxLen) VL_MT_SAFE {
|
||||
str.clear();
|
||||
|
||||
// While threadsafe, each thread can only access different file handles
|
||||
FILE* fp = VL_CVT_I_FP(fpi);
|
||||
if (VL_UNLIKELY(!fp)) return 0;
|
||||
|
||||
// The string needs to be padded with 0's in unused spaces in front of
|
||||
// any read data. This means we can't know in what location the first
|
||||
// character will finally live, so we need to copy. Yuk.
|
||||
IData bytes = VL_BYTES_I(obits);
|
||||
char buffer[VL_TO_STRING_MAX_WORDS * VL_EDATASIZE + 1];
|
||||
// We don't use fgets, as we must read \0s.
|
||||
while (str.size() < maxLen) {
|
||||
const int c = getc(fp); // getc() is threadsafe
|
||||
if (c == EOF) break;
|
||||
str.push_back(c);
|
||||
if (c == '\n') break;
|
||||
}
|
||||
return str.size();
|
||||
}
|
||||
|
||||
IData VL_FGETS_IXI(int obits, void* destp, IData fpi) VL_MT_SAFE {
|
||||
std::string str;
|
||||
const IData bytes = VL_BYTES_I(obits);
|
||||
IData got = getLine(str, fpi, bytes);
|
||||
|
||||
if (VL_UNLIKELY(str.empty())) return 0;
|
||||
|
||||
// V3Emit has static check that bytes < VL_TO_STRING_MAX_WORDS, but be safe
|
||||
if (VL_UNCOVERABLE(bytes > VL_TO_STRING_MAX_WORDS * VL_EDATASIZE)) {
|
||||
if (VL_UNCOVERABLE(bytes < str.size())) {
|
||||
VL_FATAL_MT(__FILE__, __LINE__, "", "Internal: fgets buffer overrun"); // LCOV_EXCL_LINE
|
||||
}
|
||||
|
||||
// We don't use fgets, as we must read \0s.
|
||||
IData got = 0;
|
||||
char* cp = buffer;
|
||||
while (got < bytes) {
|
||||
int c = getc(fp); // getc() is threadsafe
|
||||
if (c == EOF) break;
|
||||
*cp++ = c;
|
||||
got++;
|
||||
if (c == '\n') break;
|
||||
}
|
||||
|
||||
_VL_STRING_TO_VINT(obits, destp, got, buffer);
|
||||
_VL_STRING_TO_VINT(obits, destp, got, str.data());
|
||||
return got;
|
||||
}
|
||||
|
||||
// declared in verilated_heavy.h
|
||||
IData VL_FGETS_NI(std::string& dest, IData fpi) VL_MT_SAFE {
|
||||
return getLine(dest, fpi, std::numeric_limits<size_t>::max());
|
||||
}
|
||||
|
||||
IData VL_FERROR_IN(IData, std::string& outputr) VL_MT_SAFE {
|
||||
// We ignore lhs/fpi - IEEE says "most recent error" so probably good enough
|
||||
IData ret = errno;
|
||||
@@ -1309,58 +1345,58 @@ void VL_FCLOSE_I(IData fdi) VL_MT_SAFE {
|
||||
void VL_FFLUSH_ALL() VL_MT_SAFE { fflush(stdout); }
|
||||
|
||||
void VL_SFORMAT_X(int obits, CData& destr, const char* formatp, ...) VL_MT_SAFE {
|
||||
static VL_THREAD_LOCAL std::string output; // static only for speed
|
||||
output = "";
|
||||
static VL_THREAD_LOCAL std::string t_output; // static only for speed
|
||||
t_output = "";
|
||||
va_list ap;
|
||||
va_start(ap, formatp);
|
||||
_vl_vsformat(output, formatp, ap);
|
||||
_vl_vsformat(t_output, formatp, ap);
|
||||
va_end(ap);
|
||||
|
||||
_VL_STRING_TO_VINT(obits, &destr, output.length(), output.c_str());
|
||||
_VL_STRING_TO_VINT(obits, &destr, t_output.length(), t_output.c_str());
|
||||
}
|
||||
|
||||
void VL_SFORMAT_X(int obits, SData& destr, const char* formatp, ...) VL_MT_SAFE {
|
||||
static VL_THREAD_LOCAL std::string output; // static only for speed
|
||||
output = "";
|
||||
static VL_THREAD_LOCAL std::string t_output; // static only for speed
|
||||
t_output = "";
|
||||
va_list ap;
|
||||
va_start(ap, formatp);
|
||||
_vl_vsformat(output, formatp, ap);
|
||||
_vl_vsformat(t_output, formatp, ap);
|
||||
va_end(ap);
|
||||
|
||||
_VL_STRING_TO_VINT(obits, &destr, output.length(), output.c_str());
|
||||
_VL_STRING_TO_VINT(obits, &destr, t_output.length(), t_output.c_str());
|
||||
}
|
||||
|
||||
void VL_SFORMAT_X(int obits, IData& destr, const char* formatp, ...) VL_MT_SAFE {
|
||||
static VL_THREAD_LOCAL std::string output; // static only for speed
|
||||
output = "";
|
||||
static VL_THREAD_LOCAL std::string t_output; // static only for speed
|
||||
t_output = "";
|
||||
va_list ap;
|
||||
va_start(ap, formatp);
|
||||
_vl_vsformat(output, formatp, ap);
|
||||
_vl_vsformat(t_output, formatp, ap);
|
||||
va_end(ap);
|
||||
|
||||
_VL_STRING_TO_VINT(obits, &destr, output.length(), output.c_str());
|
||||
_VL_STRING_TO_VINT(obits, &destr, t_output.length(), t_output.c_str());
|
||||
}
|
||||
|
||||
void VL_SFORMAT_X(int obits, QData& destr, const char* formatp, ...) VL_MT_SAFE {
|
||||
static VL_THREAD_LOCAL std::string output; // static only for speed
|
||||
output = "";
|
||||
static VL_THREAD_LOCAL std::string t_output; // static only for speed
|
||||
t_output = "";
|
||||
va_list ap;
|
||||
va_start(ap, formatp);
|
||||
_vl_vsformat(output, formatp, ap);
|
||||
_vl_vsformat(t_output, formatp, ap);
|
||||
va_end(ap);
|
||||
|
||||
_VL_STRING_TO_VINT(obits, &destr, output.length(), output.c_str());
|
||||
_VL_STRING_TO_VINT(obits, &destr, t_output.length(), t_output.c_str());
|
||||
}
|
||||
|
||||
void VL_SFORMAT_X(int obits, void* destp, const char* formatp, ...) VL_MT_SAFE {
|
||||
static VL_THREAD_LOCAL std::string output; // static only for speed
|
||||
output = "";
|
||||
static VL_THREAD_LOCAL std::string t_output; // static only for speed
|
||||
t_output = "";
|
||||
va_list ap;
|
||||
va_start(ap, formatp);
|
||||
_vl_vsformat(output, formatp, ap);
|
||||
_vl_vsformat(t_output, formatp, ap);
|
||||
va_end(ap);
|
||||
|
||||
_VL_STRING_TO_VINT(obits, destp, output.length(), output.c_str());
|
||||
_VL_STRING_TO_VINT(obits, destp, t_output.length(), t_output.c_str());
|
||||
}
|
||||
|
||||
void VL_SFORMAT_X(int obits_ignored, std::string& output, const char* formatp, ...) VL_MT_SAFE {
|
||||
@@ -1373,38 +1409,38 @@ void VL_SFORMAT_X(int obits_ignored, std::string& output, const char* formatp, .
|
||||
}
|
||||
|
||||
std::string VL_SFORMATF_NX(const char* formatp, ...) VL_MT_SAFE {
|
||||
static VL_THREAD_LOCAL std::string output; // static only for speed
|
||||
output = "";
|
||||
static VL_THREAD_LOCAL std::string t_output; // static only for speed
|
||||
t_output = "";
|
||||
va_list ap;
|
||||
va_start(ap, formatp);
|
||||
_vl_vsformat(output, formatp, ap);
|
||||
_vl_vsformat(t_output, formatp, ap);
|
||||
va_end(ap);
|
||||
|
||||
return output;
|
||||
return t_output;
|
||||
}
|
||||
|
||||
void VL_WRITEF(const char* formatp, ...) VL_MT_SAFE {
|
||||
static VL_THREAD_LOCAL std::string output; // static only for speed
|
||||
output = "";
|
||||
static VL_THREAD_LOCAL std::string t_output; // static only for speed
|
||||
t_output = "";
|
||||
va_list ap;
|
||||
va_start(ap, formatp);
|
||||
_vl_vsformat(output, formatp, ap);
|
||||
_vl_vsformat(t_output, formatp, ap);
|
||||
va_end(ap);
|
||||
|
||||
VL_PRINTF_MT("%s", output.c_str());
|
||||
VL_PRINTF_MT("%s", t_output.c_str());
|
||||
}
|
||||
|
||||
void VL_FWRITEF(IData fpi, const char* formatp, ...) VL_MT_SAFE {
|
||||
// While threadsafe, each thread can only access different file handles
|
||||
static VL_THREAD_LOCAL std::string output; // static only for speed
|
||||
output = "";
|
||||
static VL_THREAD_LOCAL std::string t_output; // static only for speed
|
||||
t_output = "";
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, formatp);
|
||||
_vl_vsformat(output, formatp, ap);
|
||||
_vl_vsformat(t_output, formatp, ap);
|
||||
va_end(ap);
|
||||
|
||||
VerilatedImp::fdWrite(fpi, output);
|
||||
VerilatedImp::fdWrite(fpi, t_output);
|
||||
}
|
||||
|
||||
IData VL_FSCANF_IX(IData fpi, const char* formatp, ...) VL_MT_SAFE {
|
||||
@@ -1625,12 +1661,12 @@ IData VL_VALUEPLUSARGS_INN(int, const std::string& ld, std::string& rdr) VL_MT_S
|
||||
|
||||
const char* vl_mc_scan_plusargs(const char* prefixp) VL_MT_SAFE {
|
||||
const std::string& match = VerilatedImp::argPlusMatch(prefixp);
|
||||
static VL_THREAD_LOCAL char outstr[VL_VALUE_STRING_MAX_WIDTH];
|
||||
static VL_THREAD_LOCAL char t_outstr[VL_VALUE_STRING_MAX_WIDTH];
|
||||
if (match.empty()) return nullptr;
|
||||
outstr[0] = '\0';
|
||||
strncat(outstr, match.c_str() + strlen(prefixp) + 1, // +1 to skip the "+"
|
||||
t_outstr[0] = '\0';
|
||||
strncat(t_outstr, match.c_str() + strlen(prefixp) + 1, // +1 to skip the "+"
|
||||
VL_VALUE_STRING_MAX_WIDTH - 1);
|
||||
return outstr;
|
||||
return t_outstr;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
@@ -1736,31 +1772,31 @@ const char* vl_dumpctl_filenamep(bool setit, const std::string& filename) VL_MT_
|
||||
static const char* memhFormat(int nBits) {
|
||||
assert((nBits >= 1) && (nBits <= 32));
|
||||
|
||||
static VL_THREAD_LOCAL char buf[32];
|
||||
static VL_THREAD_LOCAL char t_buf[32];
|
||||
switch ((nBits - 1) / 4) {
|
||||
case 0: VL_SNPRINTF(buf, 32, "%%01x"); break;
|
||||
case 1: VL_SNPRINTF(buf, 32, "%%02x"); break;
|
||||
case 2: VL_SNPRINTF(buf, 32, "%%03x"); break;
|
||||
case 3: VL_SNPRINTF(buf, 32, "%%04x"); break;
|
||||
case 4: VL_SNPRINTF(buf, 32, "%%05x"); break;
|
||||
case 5: VL_SNPRINTF(buf, 32, "%%06x"); break;
|
||||
case 6: VL_SNPRINTF(buf, 32, "%%07x"); break;
|
||||
case 7: VL_SNPRINTF(buf, 32, "%%08x"); break;
|
||||
case 0: VL_SNPRINTF(t_buf, 32, "%%01x"); break;
|
||||
case 1: VL_SNPRINTF(t_buf, 32, "%%02x"); break;
|
||||
case 2: VL_SNPRINTF(t_buf, 32, "%%03x"); break;
|
||||
case 3: VL_SNPRINTF(t_buf, 32, "%%04x"); break;
|
||||
case 4: VL_SNPRINTF(t_buf, 32, "%%05x"); break;
|
||||
case 5: VL_SNPRINTF(t_buf, 32, "%%06x"); break;
|
||||
case 6: VL_SNPRINTF(t_buf, 32, "%%07x"); break;
|
||||
case 7: VL_SNPRINTF(t_buf, 32, "%%08x"); break;
|
||||
default: assert(false); break; // LCOV_EXCL_LINE
|
||||
}
|
||||
return buf;
|
||||
return t_buf;
|
||||
}
|
||||
|
||||
static const char* formatBinary(int nBits, vluint32_t bits) {
|
||||
assert((nBits >= 1) && (nBits <= 32));
|
||||
|
||||
static VL_THREAD_LOCAL char buf[64];
|
||||
static VL_THREAD_LOCAL char t_buf[64];
|
||||
for (int i = 0; i < nBits; i++) {
|
||||
bool isOne = bits & (1 << (nBits - 1 - i));
|
||||
buf[i] = (isOne ? '1' : '0');
|
||||
t_buf[i] = (isOne ? '1' : '0');
|
||||
}
|
||||
buf[nBits] = '\0';
|
||||
return buf;
|
||||
t_buf[nBits] = '\0';
|
||||
return t_buf;
|
||||
}
|
||||
|
||||
VlReadMem::VlReadMem(bool hex, int bits, const std::string& filename, QData start, QData end)
|
||||
@@ -2179,11 +2215,8 @@ void VL_TIMEFORMAT_IINI(int units, int precision, const std::string& suffix,
|
||||
//===========================================================================
|
||||
// Verilated:: Methods
|
||||
|
||||
Verilated::ThreadLocal::ThreadLocal() {}
|
||||
Verilated::ThreadLocal::~ThreadLocal() {}
|
||||
|
||||
void Verilated::debug(int level) VL_MT_SAFE {
|
||||
const VerilatedLockGuard lock(m_mutex);
|
||||
const VerilatedLockGuard lock(s_mutex);
|
||||
s_s.s_debug = level;
|
||||
if (level) {
|
||||
#ifdef VL_DEBUG
|
||||
@@ -2197,49 +2230,65 @@ void Verilated::debug(int level) VL_MT_SAFE {
|
||||
}
|
||||
}
|
||||
void Verilated::randReset(int val) VL_MT_SAFE {
|
||||
const VerilatedLockGuard lock(m_mutex);
|
||||
const VerilatedLockGuard lock(s_mutex);
|
||||
s_s.s_randReset = val;
|
||||
}
|
||||
void Verilated::randSeed(int val) VL_MT_SAFE {
|
||||
const VerilatedLockGuard lock(m_mutex);
|
||||
const VerilatedLockGuard lock(s_mutex);
|
||||
s_s.s_randSeed = val;
|
||||
vluint64_t newEpoch = s_s.s_randSeedEpoch + 1;
|
||||
if (VL_UNLIKELY(newEpoch == 0)) newEpoch = 1;
|
||||
// Obververs must see new epoch AFTER seed updated
|
||||
#ifdef VL_THREADED
|
||||
std::atomic_signal_fence(std::memory_order_release);
|
||||
#endif
|
||||
s_s.s_randSeedEpoch = newEpoch;
|
||||
}
|
||||
vluint64_t Verilated::randSeedDefault64() VL_MT_SAFE {
|
||||
if (Verilated::randSeed() != 0) {
|
||||
return ((static_cast<vluint64_t>(Verilated::randSeed()) << 32)
|
||||
^ (static_cast<vluint64_t>(Verilated::randSeed())));
|
||||
} else {
|
||||
return ((static_cast<vluint64_t>(vl_sys_rand32()) << 32)
|
||||
^ (static_cast<vluint64_t>(vl_sys_rand32())));
|
||||
}
|
||||
}
|
||||
void Verilated::calcUnusedSigs(bool flag) VL_MT_SAFE {
|
||||
const VerilatedLockGuard lock(m_mutex);
|
||||
const VerilatedLockGuard lock(s_mutex);
|
||||
s_s.s_calcUnusedSigs = flag;
|
||||
}
|
||||
void Verilated::errorCount(int val) VL_MT_SAFE {
|
||||
const VerilatedLockGuard lock(m_mutex);
|
||||
const VerilatedLockGuard lock(s_mutex);
|
||||
s_s.s_errorCount = val;
|
||||
}
|
||||
void Verilated::errorCountInc() VL_MT_SAFE {
|
||||
const VerilatedLockGuard lock(m_mutex);
|
||||
const VerilatedLockGuard lock(s_mutex);
|
||||
++s_s.s_errorCount;
|
||||
}
|
||||
void Verilated::errorLimit(int val) VL_MT_SAFE {
|
||||
const VerilatedLockGuard lock(m_mutex);
|
||||
const VerilatedLockGuard lock(s_mutex);
|
||||
s_s.s_errorLimit = val;
|
||||
}
|
||||
void Verilated::gotFinish(bool flag) VL_MT_SAFE {
|
||||
const VerilatedLockGuard lock(m_mutex);
|
||||
const VerilatedLockGuard lock(s_mutex);
|
||||
s_s.s_gotFinish = flag;
|
||||
}
|
||||
void Verilated::assertOn(bool flag) VL_MT_SAFE {
|
||||
const VerilatedLockGuard lock(m_mutex);
|
||||
const VerilatedLockGuard lock(s_mutex);
|
||||
s_s.s_assertOn = flag;
|
||||
}
|
||||
void Verilated::fatalOnVpiError(bool flag) VL_MT_SAFE {
|
||||
const VerilatedLockGuard lock(m_mutex);
|
||||
const VerilatedLockGuard lock(s_mutex);
|
||||
s_s.s_fatalOnVpiError = flag;
|
||||
}
|
||||
void Verilated::timeunit(int value) VL_MT_SAFE {
|
||||
if (value < 0) value = -value; // Stored as 0..15
|
||||
const VerilatedLockGuard lock(m_mutex);
|
||||
const VerilatedLockGuard lock(s_mutex);
|
||||
s_s.s_timeunit = value;
|
||||
}
|
||||
void Verilated::timeprecision(int value) VL_MT_SAFE {
|
||||
if (value < 0) value = -value; // Stored as 0..15
|
||||
const VerilatedLockGuard lock(m_mutex);
|
||||
const VerilatedLockGuard lock(s_mutex);
|
||||
s_s.s_timeprecision = value;
|
||||
#ifdef SYSTEMC_VERSION
|
||||
sc_time sc_res = sc_get_time_resolution();
|
||||
@@ -2270,15 +2319,15 @@ void Verilated::timeprecision(int value) VL_MT_SAFE {
|
||||
#endif
|
||||
}
|
||||
void Verilated::profThreadsStart(vluint64_t flag) VL_MT_SAFE {
|
||||
const VerilatedLockGuard lock(m_mutex);
|
||||
const VerilatedLockGuard lock(s_mutex);
|
||||
s_ns.s_profThreadsStart = flag;
|
||||
}
|
||||
void Verilated::profThreadsWindow(vluint64_t flag) VL_MT_SAFE {
|
||||
const VerilatedLockGuard lock(m_mutex);
|
||||
const VerilatedLockGuard lock(s_mutex);
|
||||
s_ns.s_profThreadsWindow = flag;
|
||||
}
|
||||
void Verilated::profThreadsFilenamep(const char* flagp) VL_MT_SAFE {
|
||||
const VerilatedLockGuard lock(m_mutex);
|
||||
const VerilatedLockGuard lock(s_mutex);
|
||||
if (s_ns.s_profThreadsFilenamep) free(const_cast<char*>(s_ns.s_profThreadsFilenamep));
|
||||
s_ns.s_profThreadsFilenamep = strdup(flagp);
|
||||
}
|
||||
@@ -2286,18 +2335,18 @@ void Verilated::profThreadsFilenamep(const char* flagp) VL_MT_SAFE {
|
||||
const char* Verilated::catName(const char* n1, const char* n2, const char* delimiter) VL_MT_SAFE {
|
||||
// Returns new'ed data
|
||||
// Used by symbol table creation to make module names
|
||||
static VL_THREAD_LOCAL char* strp = nullptr;
|
||||
static VL_THREAD_LOCAL size_t len = 0;
|
||||
static VL_THREAD_LOCAL char* t_strp = nullptr;
|
||||
static VL_THREAD_LOCAL size_t t_len = 0;
|
||||
size_t newlen = strlen(n1) + strlen(n2) + strlen(delimiter) + 1;
|
||||
if (!strp || newlen > len) {
|
||||
if (strp) delete[] strp;
|
||||
strp = new char[newlen];
|
||||
len = newlen;
|
||||
if (!t_strp || newlen > t_len) {
|
||||
if (t_strp) delete[] t_strp;
|
||||
t_strp = new char[newlen];
|
||||
t_len = newlen;
|
||||
}
|
||||
strcpy(strp, n1);
|
||||
if (*n1) strcat(strp, delimiter);
|
||||
strcat(strp, n2);
|
||||
return strp;
|
||||
strcpy(t_strp, n1);
|
||||
if (*n1) strcat(t_strp, delimiter);
|
||||
strcat(t_strp, n2);
|
||||
return t_strp;
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
@@ -2306,8 +2355,8 @@ const char* Verilated::catName(const char* n1, const char* n2, const char* delim
|
||||
// Keeping these out of class Verilated to avoid having to include <list>
|
||||
// in verilated.h (for compilation speed)
|
||||
typedef std::list<std::pair<Verilated::VoidPCb, void*>> VoidPCbList;
|
||||
static VoidPCbList g_flushCbs;
|
||||
static VoidPCbList g_exitCbs;
|
||||
static VoidPCbList s_flushCbs;
|
||||
static VoidPCbList s_exitCbs;
|
||||
|
||||
static void addCb(Verilated::VoidPCb cb, void* datap, VoidPCbList& cbs) {
|
||||
std::pair<Verilated::VoidPCb, void*> pair(cb, datap);
|
||||
@@ -2318,21 +2367,21 @@ static void removeCb(Verilated::VoidPCb cb, void* datap, VoidPCbList& cbs) {
|
||||
std::pair<Verilated::VoidPCb, void*> pair(cb, datap);
|
||||
cbs.remove(pair);
|
||||
}
|
||||
static void runCallbacks(VoidPCbList& cbs) VL_MT_SAFE {
|
||||
static void runCallbacks(const VoidPCbList& cbs) VL_MT_SAFE {
|
||||
for (const auto& i : cbs) i.first(i.second);
|
||||
}
|
||||
|
||||
void Verilated::addFlushCb(VoidPCb cb, void* datap) VL_MT_SAFE {
|
||||
const VerilatedLockGuard lock(m_mutex);
|
||||
addCb(cb, datap, g_flushCbs);
|
||||
const VerilatedLockGuard lock(s_mutex);
|
||||
addCb(cb, datap, s_flushCbs);
|
||||
}
|
||||
void Verilated::removeFlushCb(VoidPCb cb, void* datap) VL_MT_SAFE {
|
||||
const VerilatedLockGuard lock(m_mutex);
|
||||
removeCb(cb, datap, g_flushCbs);
|
||||
const VerilatedLockGuard lock(s_mutex);
|
||||
removeCb(cb, datap, s_flushCbs);
|
||||
}
|
||||
void Verilated::runFlushCallbacks() VL_MT_SAFE {
|
||||
const VerilatedLockGuard lock(m_mutex);
|
||||
runCallbacks(g_flushCbs);
|
||||
const VerilatedLockGuard lock(s_mutex);
|
||||
runCallbacks(s_flushCbs);
|
||||
fflush(stderr);
|
||||
fflush(stdout);
|
||||
// When running internal code coverage (gcc --coverage, as opposed to
|
||||
@@ -2342,16 +2391,16 @@ void Verilated::runFlushCallbacks() VL_MT_SAFE {
|
||||
}
|
||||
|
||||
void Verilated::addExitCb(VoidPCb cb, void* datap) VL_MT_SAFE {
|
||||
const VerilatedLockGuard lock(m_mutex);
|
||||
addCb(cb, datap, g_exitCbs);
|
||||
const VerilatedLockGuard lock(s_mutex);
|
||||
addCb(cb, datap, s_exitCbs);
|
||||
}
|
||||
void Verilated::removeExitCb(VoidPCb cb, void* datap) VL_MT_SAFE {
|
||||
const VerilatedLockGuard lock(m_mutex);
|
||||
removeCb(cb, datap, g_exitCbs);
|
||||
const VerilatedLockGuard lock(s_mutex);
|
||||
removeCb(cb, datap, s_exitCbs);
|
||||
}
|
||||
void Verilated::runExitCallbacks() VL_MT_SAFE {
|
||||
const VerilatedLockGuard lock(m_mutex);
|
||||
runCallbacks(g_exitCbs);
|
||||
const VerilatedLockGuard lock(s_mutex);
|
||||
runCallbacks(s_exitCbs);
|
||||
}
|
||||
|
||||
const char* Verilated::productName() VL_PURE { return VERILATOR_PRODUCT; }
|
||||
@@ -2366,11 +2415,11 @@ void Verilated::commandArgs(int argc, const char** argv) VL_MT_SAFE {
|
||||
|
||||
const char* Verilated::commandArgsPlusMatch(const char* prefixp) VL_MT_SAFE {
|
||||
const std::string& match = VerilatedImp::argPlusMatch(prefixp);
|
||||
static VL_THREAD_LOCAL char outstr[VL_VALUE_STRING_MAX_WIDTH];
|
||||
static VL_THREAD_LOCAL char t_outstr[VL_VALUE_STRING_MAX_WIDTH];
|
||||
if (match.empty()) return "";
|
||||
outstr[0] = '\0';
|
||||
strncat(outstr, match.c_str(), VL_VALUE_STRING_MAX_WIDTH - 1);
|
||||
return outstr;
|
||||
t_outstr[0] = '\0';
|
||||
strncat(t_outstr, match.c_str(), VL_VALUE_STRING_MAX_WIDTH - 1);
|
||||
return t_outstr;
|
||||
}
|
||||
|
||||
void Verilated::nullPointerError(const char* filename, int linenum) VL_MT_SAFE {
|
||||
@@ -2444,22 +2493,10 @@ void Verilated::endOfEvalGuts(VerilatedEvalMsgQueue* evalMsgQp) VL_MT_SAFE {
|
||||
//
|
||||
// To avoid the trouble, all member variables are enclosed in VerilatedImpU union.
|
||||
// ctor nor dtor of members are not called automatically.
|
||||
// VerilatedImp::setup() and teardown() guarantees to initialize/destruct just once.
|
||||
// VerilatedInitializer::setup() and teardown() guarantees to initialize/destruct just once.
|
||||
|
||||
void VerilatedImp::setup() {
|
||||
static bool done = false;
|
||||
if (!done) {
|
||||
new (&VerilatedImp::s_s) VerilatedImpData();
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
void VerilatedImp::teardown() {
|
||||
static bool done = false;
|
||||
if (!done) {
|
||||
VerilatedImp::s_s.~VerilatedImpU();
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
void VerilatedImp::setup() { new (&VerilatedImp::s_s) VerilatedImpData(); }
|
||||
void VerilatedImp::teardown() { VerilatedImp::s_s.~VerilatedImpU(); }
|
||||
|
||||
//===========================================================================
|
||||
// VerilatedImp:: Methods
|
||||
@@ -2606,7 +2643,7 @@ vluint32_t VerilatedVarProps::entSize() const {
|
||||
|
||||
size_t VerilatedVarProps::totalSize() const {
|
||||
size_t size = entSize();
|
||||
for (int udim = 0; udim <= udims(); ++udim) size *= m_unpacked[udim].elements();
|
||||
for (int udim = 0; udim < udims(); ++udim) size *= m_unpacked[udim].elements();
|
||||
return size;
|
||||
}
|
||||
|
||||
@@ -2625,8 +2662,6 @@ void* VerilatedVarProps::datapAdjustIndex(void* datap, int dim, int indx) const
|
||||
//======================================================================
|
||||
// VerilatedScope:: Methods
|
||||
|
||||
VerilatedScope::VerilatedScope() {}
|
||||
|
||||
VerilatedScope::~VerilatedScope() {
|
||||
// Memory cleanup - not called during normal operation
|
||||
VerilatedImp::scopeErase(this);
|
||||
@@ -2705,7 +2740,7 @@ void VerilatedScope::varInsert(int finalize, const char* namep, void* datap, boo
|
||||
}
|
||||
va_end(ap);
|
||||
|
||||
m_varsp->insert(std::make_pair(namep, var));
|
||||
m_varsp->emplace(namep, var);
|
||||
}
|
||||
|
||||
// cppcheck-suppress unusedFunction // Used by applications
|
||||
@@ -2752,6 +2787,10 @@ void VerilatedHierarchy::add(VerilatedScope* fromp, VerilatedScope* top) {
|
||||
VerilatedImp::hierarchyAdd(fromp, top);
|
||||
}
|
||||
|
||||
void VerilatedHierarchy::remove(VerilatedScope* fromp, VerilatedScope* top) {
|
||||
VerilatedImp::hierarchyRemove(fromp, top);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
// VerilatedOneThreaded:: Methods
|
||||
|
||||
|
||||
+41
-38
@@ -1,7 +1,7 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2020 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2021 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -129,12 +129,12 @@ extern vluint32_t VL_THREAD_ID() VL_MT_SAFE;
|
||||
#define VL_LOCK_SPINS 50000 /// Number of times to spin for a mutex before relaxing
|
||||
|
||||
/// Mutex, wrapped to allow -fthread_safety checks
|
||||
class VL_CAPABILITY("mutex") VerilatedMutex {
|
||||
class VL_CAPABILITY("mutex") VerilatedMutex final {
|
||||
private:
|
||||
std::mutex m_mutex; // Mutex
|
||||
public:
|
||||
VerilatedMutex() {}
|
||||
~VerilatedMutex() {}
|
||||
VerilatedMutex() = default;
|
||||
~VerilatedMutex() = default;
|
||||
const VerilatedMutex& operator!() const { return *this; } // For -fthread_safety
|
||||
/// Acquire/lock mutex
|
||||
void lock() VL_ACQUIRE() {
|
||||
@@ -155,7 +155,7 @@ public:
|
||||
};
|
||||
|
||||
/// Lock guard for mutex (ala std::unique_lock), wrapped to allow -fthread_safety checks
|
||||
class VL_SCOPED_CAPABILITY VerilatedLockGuard {
|
||||
class VL_SCOPED_CAPABILITY VerilatedLockGuard final {
|
||||
VL_UNCOPYABLE(VerilatedLockGuard);
|
||||
|
||||
private:
|
||||
@@ -174,19 +174,19 @@ public:
|
||||
#else // !VL_THREADED
|
||||
|
||||
/// Empty non-threaded mutex to avoid #ifdefs in consuming code
|
||||
class VerilatedMutex {
|
||||
class VerilatedMutex final {
|
||||
public:
|
||||
void lock() {}
|
||||
void unlock() {}
|
||||
};
|
||||
|
||||
/// Empty non-threaded lock guard to avoid #ifdefs in consuming code
|
||||
class VerilatedLockGuard {
|
||||
class VerilatedLockGuard final {
|
||||
VL_UNCOPYABLE(VerilatedLockGuard);
|
||||
|
||||
public:
|
||||
explicit VerilatedLockGuard(VerilatedMutex&) {}
|
||||
~VerilatedLockGuard() {}
|
||||
~VerilatedLockGuard() = default;
|
||||
void lock() {}
|
||||
void unlock() {}
|
||||
};
|
||||
@@ -194,7 +194,7 @@ public:
|
||||
#endif // VL_THREADED
|
||||
|
||||
/// Remember the calling thread at construction time, and make sure later calls use same thread
|
||||
class VerilatedAssertOneThread {
|
||||
class VerilatedAssertOneThread final {
|
||||
// MEMBERS
|
||||
#if defined(VL_THREADED) && defined(VL_DEBUG)
|
||||
vluint32_t m_threadid; /// Thread that is legal
|
||||
@@ -230,7 +230,7 @@ public:
|
||||
|
||||
class VerilatedScope;
|
||||
|
||||
class VerilatedModule {
|
||||
class VerilatedModule VL_NOT_FINAL {
|
||||
VL_UNCOPYABLE(VerilatedModule);
|
||||
|
||||
private:
|
||||
@@ -269,7 +269,8 @@ public:
|
||||
#define VL_CELL(instname, type) ///< Declare a cell, ala SP_CELL
|
||||
|
||||
/// Declare a module, ala SC_MODULE
|
||||
#define VL_MODULE(modname) class modname : public VerilatedModule
|
||||
#define VL_MODULE(modname) class modname VL_NOT_FINAL : public VerilatedModule
|
||||
// Not class final in VL_MODULE, as users might be abstracting our models (--hierarchical)
|
||||
|
||||
/// Constructor, ala SC_CTOR
|
||||
#define VL_CTOR(modname) modname(const char* __VCname = "")
|
||||
@@ -298,7 +299,7 @@ public:
|
||||
//===========================================================================
|
||||
/// Verilator symbol table base class
|
||||
|
||||
class VerilatedSyms {
|
||||
class VerilatedSyms VL_NOT_FINAL {
|
||||
public: // But for internal use only
|
||||
#ifdef VL_THREADED
|
||||
VerilatedEvalMsgQueue* __Vm_evalMsgQp;
|
||||
@@ -311,7 +312,7 @@ public: // But for internal use only
|
||||
/// Verilator global class information class
|
||||
/// This class is initialized by main thread only. Reading post-init is thread safe.
|
||||
|
||||
class VerilatedScope {
|
||||
class VerilatedScope final {
|
||||
public:
|
||||
typedef enum : vluint8_t {
|
||||
SCOPE_MODULE,
|
||||
@@ -330,7 +331,7 @@ private:
|
||||
Type m_type = SCOPE_OTHER; ///< Type of the scope
|
||||
|
||||
public: // But internals only - called from VerilatedModule's
|
||||
VerilatedScope();
|
||||
VerilatedScope() = default;
|
||||
~VerilatedScope();
|
||||
void configure(VerilatedSyms* symsp, const char* prefixp, const char* suffixp,
|
||||
const char* identifier, vlsint8_t timeunit, const Type& type) VL_MT_UNSAFE;
|
||||
@@ -359,18 +360,19 @@ public: // But internals only - called from VerilatedModule's
|
||||
Type type() const { return m_type; }
|
||||
};
|
||||
|
||||
class VerilatedHierarchy {
|
||||
class VerilatedHierarchy final {
|
||||
public:
|
||||
static void add(VerilatedScope* fromp, VerilatedScope* top);
|
||||
static void remove(VerilatedScope* fromp, VerilatedScope* top);
|
||||
};
|
||||
|
||||
//===========================================================================
|
||||
/// Verilator global static information class
|
||||
|
||||
class Verilated {
|
||||
class Verilated final {
|
||||
// MEMBERS
|
||||
// Slow path variables
|
||||
static VerilatedMutex m_mutex; ///< Mutex for s_s/s_ns members, when VL_THREADED
|
||||
static VerilatedMutex s_mutex; ///< Mutex for s_s/s_ns members, when VL_THREADED
|
||||
|
||||
static struct Serialized { // All these members serialized/deserialized
|
||||
// Fast path
|
||||
@@ -386,8 +388,9 @@ class Verilated {
|
||||
int s_errorLimit; ///< Stop on error number
|
||||
int s_randReset; ///< Random reset: 0=all 0s, 1=all 1s, 2=random
|
||||
int s_randSeed; ///< Random seed: 0=random
|
||||
int s_randSeedEpoch; ///< Number incrementing on each reseed, 0=illegal
|
||||
Serialized();
|
||||
~Serialized() {}
|
||||
~Serialized() = default;
|
||||
} s_s;
|
||||
|
||||
static struct NonSerialized { // Non-serialized information
|
||||
@@ -397,8 +400,8 @@ class Verilated {
|
||||
vluint32_t s_profThreadsWindow = 2; ///< +prof+threads window size
|
||||
// Slow path
|
||||
const char* s_profThreadsFilenamep; ///< +prof+threads filename
|
||||
NonSerialized();
|
||||
~NonSerialized();
|
||||
void setup();
|
||||
void teardown();
|
||||
} s_ns;
|
||||
|
||||
// no need to be save-restored (serialized) the
|
||||
@@ -407,8 +410,8 @@ class Verilated {
|
||||
VerilatedMutex m_argMutex; ///< Mutex for s_args members, when VL_THREADED
|
||||
int argc = 0;
|
||||
const char** argv = nullptr;
|
||||
CommandArgValues() {}
|
||||
~CommandArgValues() {}
|
||||
CommandArgValues() = default;
|
||||
~CommandArgValues() = default;
|
||||
} s_args;
|
||||
|
||||
// Not covered by mutex, as per-thread
|
||||
@@ -422,11 +425,13 @@ class Verilated {
|
||||
const char* t_dpiFilename = nullptr; ///< DPI context filename
|
||||
int t_dpiLineno = 0; ///< DPI context line number
|
||||
|
||||
ThreadLocal();
|
||||
~ThreadLocal();
|
||||
ThreadLocal() = default;
|
||||
~ThreadLocal() = default;
|
||||
} t_s;
|
||||
|
||||
private:
|
||||
friend struct VerilatedInitializer;
|
||||
|
||||
// CONSTRUCTORS
|
||||
VL_UNCOPYABLE(Verilated);
|
||||
|
||||
@@ -442,6 +447,9 @@ public:
|
||||
static int randReset() VL_MT_SAFE { return s_s.s_randReset; } ///< Return randReset value
|
||||
static void randSeed(int val) VL_MT_SAFE;
|
||||
static int randSeed() VL_MT_SAFE { return s_s.s_randSeed; } ///< Return randSeed value
|
||||
static vluint32_t randSeedEpoch() VL_MT_SAFE { return s_s.s_randSeedEpoch; }
|
||||
/// Random seed extended to 64 bits, and defaulted if user seed==0
|
||||
static vluint64_t randSeedDefault64() VL_MT_SAFE;
|
||||
|
||||
/// Enable debug of internal verilated code
|
||||
static void debug(int level) VL_MT_SAFE;
|
||||
@@ -452,7 +460,7 @@ public:
|
||||
static inline int debug() VL_MT_SAFE { return s_s.s_debug; }
|
||||
#else
|
||||
/// Return constant 0 debug level, so C++'s optimizer rips up
|
||||
static inline int debug() VL_PURE { return 0; }
|
||||
static constexpr int debug() VL_PURE { return 0; }
|
||||
#endif
|
||||
/// Enable calculation of unused signals
|
||||
static void calcUnusedSigs(bool flag) VL_MT_SAFE;
|
||||
@@ -567,8 +575,8 @@ public:
|
||||
static int dpiLineno() VL_MT_SAFE { return t_s.t_dpiLineno; }
|
||||
static int exportFuncNum(const char* namep) VL_MT_SAFE;
|
||||
|
||||
static size_t serialized1Size() VL_PURE { return sizeof(s_s); }
|
||||
static void* serialized1Ptr() VL_MT_UNSAFE { return &s_s; } // Unsafe, for Serialize only
|
||||
static constexpr size_t serialized1Size() VL_PURE { return sizeof(s_s); }
|
||||
static constexpr void* serialized1Ptr() VL_MT_UNSAFE { return &s_s; } // For Serialize only
|
||||
static size_t serialized2Size() VL_PURE;
|
||||
static void* serialized2Ptr() VL_MT_UNSAFE;
|
||||
#ifdef VL_THREADED
|
||||
@@ -648,13 +656,14 @@ extern vluint64_t vl_rand64() VL_MT_SAFE;
|
||||
inline IData VL_RANDOM_I(int obits) VL_MT_SAFE { return vl_rand64() & VL_MASK_I(obits); }
|
||||
inline QData VL_RANDOM_Q(int obits) VL_MT_SAFE { return vl_rand64() & VL_MASK_Q(obits); }
|
||||
extern WDataOutP VL_RANDOM_W(int obits, WDataOutP outwp); ///< Randomize a signal
|
||||
extern IData VL_RANDOM_SEEDED_II(int obits, IData seed) VL_MT_SAFE;
|
||||
inline IData VL_URANDOM_RANGE_I(IData hi, IData lo) {
|
||||
vluint64_t rnd = vl_rand64();
|
||||
if (VL_LIKELY(hi > lo)) {
|
||||
// Modulus isn't very fast but it's common that hi-low is power-of-two
|
||||
return (rnd % (hi - lo)) + lo;
|
||||
return (rnd % (hi - lo + 1)) + lo;
|
||||
} else {
|
||||
return (rnd % (lo - hi)) + hi;
|
||||
return (rnd % (lo - hi + 1)) + hi;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -753,9 +762,9 @@ static inline void* VL_CVT_Q_VP(QData lhs) VL_PURE {
|
||||
u.q = lhs;
|
||||
return u.fp;
|
||||
}
|
||||
/// Return QData from void*
|
||||
static inline QData VL_CVT_VP_Q(void* fp) VL_PURE {
|
||||
union { void* fp; QData q; } u;
|
||||
/// Return QData from const void*
|
||||
static inline QData VL_CVT_VP_Q(const void* fp) VL_PURE {
|
||||
union { const void* fp; QData q; } u;
|
||||
u.q = 0;
|
||||
u.fp = fp;
|
||||
return u.q;
|
||||
@@ -1364,12 +1373,6 @@ static inline WDataOutP VL_XOR_W(int words, WDataOutP owp, WDataInP lwp, WDataIn
|
||||
for (int i = 0; (i < words); ++i) owp[i] = (lwp[i] ^ rwp[i]);
|
||||
return owp;
|
||||
}
|
||||
// EMIT_RULE: VL_XNOR: oclean=dirty; obits=lbits; lbits==rbits;
|
||||
static inline WDataOutP VL_XNOR_W(int words, WDataOutP owp, WDataInP lwp,
|
||||
WDataInP rwp) VL_MT_SAFE {
|
||||
for (int i = 0; (i < words); ++i) owp[i] = (lwp[i] ^ ~rwp[i]);
|
||||
return owp;
|
||||
}
|
||||
// EMIT_RULE: VL_NOT: oclean=dirty; obits=lbits;
|
||||
static inline WDataOutP VL_NOT_W(int words, WDataOutP owp, WDataInP lwp) VL_MT_SAFE {
|
||||
for (int i = 0; i < words; ++i) owp[i] = ~(lwp[i]);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
######################################################################
|
||||
# DESCRIPTION: Makefile commands for all verilated target files
|
||||
#
|
||||
# Copyright 2003-2020 by Wilson Snyder. This program is free software; you
|
||||
# Copyright 2003-2021 by Wilson Snyder. This program is free software; you
|
||||
# can redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2020 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2021 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2020 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2021 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+19
-18
@@ -3,7 +3,7 @@
|
||||
//
|
||||
// THIS MODULE IS PUBLICLY LICENSED
|
||||
//
|
||||
// Copyright 2001-2020 by Wilson Snyder. This program is free software; you
|
||||
// Copyright 2001-2021 by Wilson Snyder. This program is free software; you
|
||||
// can redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -29,7 +29,7 @@
|
||||
// VerilatedCovImpBase
|
||||
/// Implementation base class for constants
|
||||
|
||||
struct VerilatedCovImpBase {
|
||||
struct VerilatedCovImpBase VL_NOT_FINAL {
|
||||
// TYPES
|
||||
enum { MAX_KEYS = 33 }; /// Maximum user arguments + filename+lineno
|
||||
enum { KEY_UNDEF = 0 }; /// Magic key # for unspecified values
|
||||
@@ -39,7 +39,7 @@ struct VerilatedCovImpBase {
|
||||
// VerilatedCovImpItem
|
||||
/// Implementation class for a VerilatedCov item
|
||||
|
||||
class VerilatedCovImpItem : VerilatedCovImpBase {
|
||||
class VerilatedCovImpItem VL_NOT_FINAL : VerilatedCovImpBase {
|
||||
public: // But only local to this file
|
||||
// MEMBERS
|
||||
int m_keys[MAX_KEYS]; ///< Key
|
||||
@@ -52,7 +52,7 @@ public: // But only local to this file
|
||||
m_vals[i] = 0;
|
||||
}
|
||||
}
|
||||
virtual ~VerilatedCovImpItem() {}
|
||||
virtual ~VerilatedCovImpItem() = default;
|
||||
virtual vluint64_t count() const = 0;
|
||||
virtual void zero() const = 0;
|
||||
};
|
||||
@@ -63,7 +63,7 @@ public: // But only local to this file
|
||||
/// This isn't in the header file for auto-magic conversion because it
|
||||
/// inlines to too much code and makes compilation too slow.
|
||||
|
||||
template <class T> class VerilatedCoverItemSpec : public VerilatedCovImpItem {
|
||||
template <class T> class VerilatedCoverItemSpec final : public VerilatedCovImpItem {
|
||||
private:
|
||||
// MEMBERS
|
||||
T* m_countp; ///< Count value
|
||||
@@ -78,7 +78,7 @@ public:
|
||||
: m_countp{countp} {
|
||||
*m_countp = 0;
|
||||
}
|
||||
virtual ~VerilatedCoverItemSpec() override {}
|
||||
virtual ~VerilatedCoverItemSpec() override = default;
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
@@ -87,10 +87,10 @@ public:
|
||||
/// All value and keys are indexed into a unique number. Thus we can greatly reduce
|
||||
/// the storage requirements for otherwise identical keys.
|
||||
|
||||
class VerilatedCovImp : VerilatedCovImpBase {
|
||||
class VerilatedCovImp final : VerilatedCovImpBase {
|
||||
private:
|
||||
// TYPES
|
||||
typedef std::map<std::string, int> ValueIndexMap;
|
||||
typedef std::map<const std::string, int> ValueIndexMap;
|
||||
typedef std::map<int, std::string> IndexValueMap;
|
||||
typedef std::deque<VerilatedCovImpItem*> ItemList;
|
||||
|
||||
@@ -99,13 +99,14 @@ private:
|
||||
ValueIndexMap m_valueIndexes VL_GUARDED_BY(m_mutex); ///< Unique arbitrary value for values
|
||||
IndexValueMap m_indexValues VL_GUARDED_BY(m_mutex); ///< Unique arbitrary value for keys
|
||||
ItemList m_items VL_GUARDED_BY(m_mutex); ///< List of all items
|
||||
int m_nextIndex VL_GUARDED_BY(m_mutex) = (KEY_UNDEF + 1); ///< Next insert value
|
||||
|
||||
VerilatedCovImpItem* m_insertp VL_GUARDED_BY(m_mutex) = nullptr; ///< Item about to insert
|
||||
const char* m_insertFilenamep VL_GUARDED_BY(m_mutex) = nullptr; ///< Filename about to insert
|
||||
int m_insertLineno VL_GUARDED_BY(m_mutex) = 0; ///< Line number about to insert
|
||||
|
||||
// CONSTRUCTORS
|
||||
VerilatedCovImp() {}
|
||||
VerilatedCovImp() = default;
|
||||
VL_UNCOPYABLE(VerilatedCovImp);
|
||||
|
||||
public:
|
||||
@@ -118,14 +119,13 @@ public:
|
||||
private:
|
||||
// PRIVATE METHODS
|
||||
int valueIndex(const std::string& value) VL_REQUIRES(m_mutex) {
|
||||
static int nextIndex = KEY_UNDEF + 1;
|
||||
const auto iter = m_valueIndexes.find(value);
|
||||
if (iter != m_valueIndexes.end()) return iter->second;
|
||||
nextIndex++;
|
||||
assert(nextIndex > 0); // Didn't rollover
|
||||
m_valueIndexes.insert(std::make_pair(value, nextIndex));
|
||||
m_indexValues.insert(std::make_pair(nextIndex, value));
|
||||
return nextIndex;
|
||||
m_nextIndex++;
|
||||
assert(m_nextIndex > 0); // Didn't rollover
|
||||
m_valueIndexes.emplace(value, m_nextIndex);
|
||||
m_indexValues.emplace(m_nextIndex, value);
|
||||
return m_nextIndex;
|
||||
}
|
||||
static std::string dequote(const std::string& text) VL_PURE {
|
||||
// Quote any special characters
|
||||
@@ -235,6 +235,7 @@ private:
|
||||
m_items.clear();
|
||||
m_indexValues.clear();
|
||||
m_valueIndexes.clear();
|
||||
m_nextIndex = KEY_UNDEF + 1;
|
||||
}
|
||||
|
||||
public:
|
||||
@@ -350,7 +351,7 @@ public:
|
||||
os << "# SystemC::Coverage-3\n";
|
||||
|
||||
// Build list of events; totalize if collapsing hierarchy
|
||||
typedef std::map<std::string, std::pair<std::string, vluint64_t>> EventMap;
|
||||
typedef std::map<const std::string, std::pair<std::string, vluint64_t>> EventMap;
|
||||
EventMap eventCounts;
|
||||
for (const auto& itemp : m_items) {
|
||||
std::string name;
|
||||
@@ -389,7 +390,7 @@ public:
|
||||
cit->second.second += itemp->count();
|
||||
cit->second.first = combineHier(oldhier, hier);
|
||||
} else {
|
||||
eventCounts.insert(std::make_pair(name, make_pair(hier, itemp->count())));
|
||||
eventCounts.emplace(name, make_pair(hier, itemp->count()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -399,7 +400,7 @@ public:
|
||||
os << i.first;
|
||||
if (!i.second.first.empty()) os << keyValueFormatter(VL_CIK_HIER, i.second.first);
|
||||
os << "' " << i.second.second;
|
||||
os << std::endl;
|
||||
os << '\n';
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
//
|
||||
// THIS MODULE IS PUBLICLY LICENSED
|
||||
//
|
||||
// Copyright 2001-2020 by Wilson Snyder. This program is free software; you
|
||||
// Copyright 2001-2021 by Wilson Snyder. This program is free software; you
|
||||
// can redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -88,7 +88,7 @@ template <class T> std::string vlCovCvtToStr(const T& t) VL_PURE {
|
||||
/// Global class with methods affecting all coverage data.
|
||||
/// All public methods in this class are thread safe.
|
||||
|
||||
class VerilatedCov {
|
||||
class VerilatedCov final {
|
||||
VL_UNCOPYABLE(VerilatedCov);
|
||||
|
||||
public:
|
||||
|
||||
+12
-75
@@ -3,7 +3,7 @@
|
||||
//
|
||||
// THIS MODULE IS PUBLICLY LICENSED
|
||||
//
|
||||
// Copyright 2001-2020 by Wilson Snyder. This program is free software; you
|
||||
// Copyright 2001-2021 by Wilson Snyder. This program is free software; you
|
||||
// can redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -29,69 +29,27 @@
|
||||
#define VLCOVGEN_ITEM(string_parsed_by_vlcovgen)
|
||||
|
||||
// clang-format off
|
||||
VLCOVGEN_ITEM("name=>'col0_name', short=>'C0', group=>1, default=>undef, descr=>'The column title for the header line of this column'")
|
||||
VLCOVGEN_ITEM("name=>'col1_name', short=>'C1', group=>1, default=>undef, ")
|
||||
VLCOVGEN_ITEM("name=>'col2_name', short=>'C2', group=>1, default=>undef, ")
|
||||
VLCOVGEN_ITEM("name=>'col3_name', short=>'C3', group=>1, default=>undef, ")
|
||||
VLCOVGEN_ITEM("name=>'column', short=>'n', group=>1, default=>0, descr=>'Column number for the item. Used to disambiguate multiple coverage points on the same line number'")
|
||||
VLCOVGEN_ITEM("name=>'filename', short=>'f', group=>1, default=>undef, descr=>'Filename of the item'")
|
||||
VLCOVGEN_ITEM("name=>'groupdesc', short=>'d', group=>1, default=>'', descr=>'Description of the covergroup this item belongs to'")
|
||||
VLCOVGEN_ITEM("name=>'groupname', short=>'g', group=>1, default=>'', descr=>'Group name of the covergroup this item belongs to'")
|
||||
VLCOVGEN_ITEM("name=>'groupcmt', short=>'O', group=>1, default=>'', ")
|
||||
VLCOVGEN_ITEM("name=>'linescov', short=>'S', group=>1, default=>'', descr=>'List of comma-separated lines covered'")
|
||||
VLCOVGEN_ITEM("name=>'per_instance',short=>'P', group=>1, default=>0, descr=>'True if every hierarchy is independently counted; otherwise all hierarchies will be combined into a single count'")
|
||||
VLCOVGEN_ITEM("name=>'row0_name', short=>'R0', group=>1, default=>undef, descr=>'The row title for the header line of this row'")
|
||||
VLCOVGEN_ITEM("name=>'row1_name', short=>'R1', group=>1, default=>undef, ")
|
||||
VLCOVGEN_ITEM("name=>'row2_name', short=>'R2', group=>1, default=>undef, ")
|
||||
VLCOVGEN_ITEM("name=>'row3_name', short=>'R3', group=>1, default=>undef, ")
|
||||
VLCOVGEN_ITEM("name=>'table', short=>'T', group=>1, default=>undef, descr=>'The name of the table for automatically generated tables'")
|
||||
VLCOVGEN_ITEM("name=>'thresh', short=>'s', group=>1, default=>undef, ")
|
||||
VLCOVGEN_ITEM("name=>'type', short=>'t', group=>1, default=>'', descr=>'Type of coverage (block, line, fsm, etc)'")
|
||||
VLCOVGEN_ITEM("'name':'column', 'short':'n', 'group':1, 'default':0, 'descr':'Column number for the item. Used to disambiguate multiple coverage points on the same line number'")
|
||||
VLCOVGEN_ITEM("'name':'filename', 'short':'f', 'group':1, 'default':None, 'descr':'Filename of the item'")
|
||||
VLCOVGEN_ITEM("'name':'linescov', 'short':'S', 'group':1, 'default':'', 'descr':'List of comma-separated lines covered'")
|
||||
VLCOVGEN_ITEM("'name':'per_instance','short':'P', 'group':1, 'default':0, 'descr':'True if every hierarchy is independently counted; otherwise all hierarchies will be combined into a single count'")
|
||||
VLCOVGEN_ITEM("'name':'thresh', 'short':'s', 'group':1, 'default':None, 'descr':'Number of hits to consider covered (aka at_least)'")
|
||||
VLCOVGEN_ITEM("'name':'type', 'short':'t', 'group':1, 'default':'', 'descr':'Type of coverage (block, line, fsm, etc)'")
|
||||
// Bin attributes
|
||||
VLCOVGEN_ITEM("name=>'col0', short=>'c0', group=>0, default=>undef, descr=>'The (enumeration) value name for this column in a table cross' ")
|
||||
VLCOVGEN_ITEM("name=>'col1', short=>'c1', group=>0, default=>undef, ")
|
||||
VLCOVGEN_ITEM("name=>'col2', short=>'c2', group=>0, default=>undef, ")
|
||||
VLCOVGEN_ITEM("name=>'col3', short=>'c3', group=>0, default=>undef, ")
|
||||
VLCOVGEN_ITEM("name=>'comment', short=>'o', group=>0, default=>'', descr=>'Textual description for the item'")
|
||||
VLCOVGEN_ITEM("name=>'hier', short=>'h', group=>0, default=>'', descr=>'Hierarchy path name for the item'")
|
||||
VLCOVGEN_ITEM("name=>'limit', short=>'L', group=>0, default=>undef, ")
|
||||
VLCOVGEN_ITEM("name=>'lineno', short=>'l', group=>0, default=>0, descr=>'Line number for the item'")
|
||||
VLCOVGEN_ITEM("name=>'row0', short=>'r0', group=>0, default=>undef, descr=>'The (enumeration) value name for this row in a table cross'")
|
||||
VLCOVGEN_ITEM("name=>'row1', short=>'r1', group=>0, default=>undef, ")
|
||||
VLCOVGEN_ITEM("name=>'row2', short=>'r2', group=>0, default=>undef, ")
|
||||
VLCOVGEN_ITEM("name=>'row3', short=>'r3', group=>0, default=>undef, ")
|
||||
VLCOVGEN_ITEM("name=>'weight', short=>'w', group=>0, default=>undef, descr=>'For totaling items, weight of this item'")
|
||||
VLCOVGEN_ITEM("'name':'comment', 'short':'o', 'group':0, 'default':'', 'descr':'Textual description for the item'")
|
||||
VLCOVGEN_ITEM("'name':'hier', 'short':'h', 'group':0, 'default':'', 'descr':'Hierarchy path name for the item'")
|
||||
VLCOVGEN_ITEM("'name':'lineno', 'short':'l', 'group':0, 'default':0, 'descr':'Line number for the item'")
|
||||
VLCOVGEN_ITEM("'name':'weight', 'short':'w', 'group':0, 'default':None, 'descr':'For totaling items, weight of this item'")
|
||||
// clang-format on
|
||||
|
||||
// VLCOVGEN_CIK_AUTO_EDIT_BEGIN
|
||||
#define VL_CIK_COL0 "c0"
|
||||
#define VL_CIK_COL0_NAME "C0"
|
||||
#define VL_CIK_COL1 "c1"
|
||||
#define VL_CIK_COL1_NAME "C1"
|
||||
#define VL_CIK_COL2 "c2"
|
||||
#define VL_CIK_COL2_NAME "C2"
|
||||
#define VL_CIK_COL3 "c3"
|
||||
#define VL_CIK_COL3_NAME "C3"
|
||||
#define VL_CIK_COLUMN "n"
|
||||
#define VL_CIK_COMMENT "o"
|
||||
#define VL_CIK_FILENAME "f"
|
||||
#define VL_CIK_GROUPCMT "O"
|
||||
#define VL_CIK_GROUPDESC "d"
|
||||
#define VL_CIK_GROUPNAME "g"
|
||||
#define VL_CIK_HIER "h"
|
||||
#define VL_CIK_LIMIT "L"
|
||||
#define VL_CIK_LINENO "l"
|
||||
#define VL_CIK_LINESCOV "S"
|
||||
#define VL_CIK_PER_INSTANCE "P"
|
||||
#define VL_CIK_ROW0 "r0"
|
||||
#define VL_CIK_ROW0_NAME "R0"
|
||||
#define VL_CIK_ROW1 "r1"
|
||||
#define VL_CIK_ROW1_NAME "R1"
|
||||
#define VL_CIK_ROW2 "r2"
|
||||
#define VL_CIK_ROW2_NAME "R2"
|
||||
#define VL_CIK_ROW3 "r3"
|
||||
#define VL_CIK_ROW3_NAME "R3"
|
||||
#define VL_CIK_TABLE "T"
|
||||
#define VL_CIK_THRESH "s"
|
||||
#define VL_CIK_TYPE "t"
|
||||
#define VL_CIK_WEIGHT "w"
|
||||
@@ -102,38 +60,17 @@ VLCOVGEN_ITEM("name=>'weight', short=>'w', group=>0, default=>undef, descr
|
||||
/// Verilator coverage global class.
|
||||
/// This class is thread safe.
|
||||
|
||||
class VerilatedCovKey {
|
||||
class VerilatedCovKey final {
|
||||
public:
|
||||
static std::string shortKey(const std::string& key) VL_PURE {
|
||||
// VLCOVGEN_SHORT_AUTO_EDIT_BEGIN
|
||||
if (key == "col0") return VL_CIK_COL0;
|
||||
if (key == "col0_name") return VL_CIK_COL0_NAME;
|
||||
if (key == "col1") return VL_CIK_COL1;
|
||||
if (key == "col1_name") return VL_CIK_COL1_NAME;
|
||||
if (key == "col2") return VL_CIK_COL2;
|
||||
if (key == "col2_name") return VL_CIK_COL2_NAME;
|
||||
if (key == "col3") return VL_CIK_COL3;
|
||||
if (key == "col3_name") return VL_CIK_COL3_NAME;
|
||||
if (key == "column") return VL_CIK_COLUMN;
|
||||
if (key == "comment") return VL_CIK_COMMENT;
|
||||
if (key == "filename") return VL_CIK_FILENAME;
|
||||
if (key == "groupcmt") return VL_CIK_GROUPCMT;
|
||||
if (key == "groupdesc") return VL_CIK_GROUPDESC;
|
||||
if (key == "groupname") return VL_CIK_GROUPNAME;
|
||||
if (key == "hier") return VL_CIK_HIER;
|
||||
if (key == "limit") return VL_CIK_LIMIT;
|
||||
if (key == "lineno") return VL_CIK_LINENO;
|
||||
if (key == "linescov") return VL_CIK_LINESCOV;
|
||||
if (key == "per_instance") return VL_CIK_PER_INSTANCE;
|
||||
if (key == "row0") return VL_CIK_ROW0;
|
||||
if (key == "row0_name") return VL_CIK_ROW0_NAME;
|
||||
if (key == "row1") return VL_CIK_ROW1;
|
||||
if (key == "row1_name") return VL_CIK_ROW1_NAME;
|
||||
if (key == "row2") return VL_CIK_ROW2;
|
||||
if (key == "row2_name") return VL_CIK_ROW2_NAME;
|
||||
if (key == "row3") return VL_CIK_ROW3;
|
||||
if (key == "row3_name") return VL_CIK_ROW3_NAME;
|
||||
if (key == "table") return VL_CIK_TABLE;
|
||||
if (key == "thresh") return VL_CIK_THRESH;
|
||||
if (key == "type") return VL_CIK_TYPE;
|
||||
if (key == "weight") return VL_CIK_WEIGHT;
|
||||
|
||||
+24
-97
@@ -1,7 +1,7 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2009-2020 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2009-2021 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -37,11 +37,6 @@
|
||||
//======================================================================
|
||||
// Internal macros
|
||||
|
||||
// Not supported yet
|
||||
#define _VL_SVDPI_UNIMP() \
|
||||
VL_FATAL_MT(__FILE__, __LINE__, "", \
|
||||
(std::string("%%Error: Unsupported DPI function: ") + VL_FUNC).c_str())
|
||||
|
||||
#define _VL_SVDPI_WARN(...) VL_PRINTF_MT(__VA_ARGS__)
|
||||
|
||||
// Function requires a "context" in the import declaration
|
||||
@@ -258,16 +253,6 @@ static void* _vl_sv_adjusted_datap(const VerilatedDpiOpenVar* varp, int nargs, i
|
||||
return datap;
|
||||
}
|
||||
|
||||
static int _vl_sv_adjusted_bit(const VerilatedDpiOpenVar* varp, int indx) {
|
||||
if (VL_UNLIKELY(indx < varp->low(0) || indx > varp->high(0))) {
|
||||
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function packed index out of bounds; %d "
|
||||
"outside [%d:%d].\n",
|
||||
indx, varp->left(0), varp->right(0));
|
||||
return 0;
|
||||
}
|
||||
return indx - varp->low(0);
|
||||
}
|
||||
|
||||
/// Return pointer to simulator open array element, or nullptr if outside range
|
||||
static void* _vl_svGetArrElemPtr(const svOpenArrayHandle h, int nargs, int indx1, int indx2,
|
||||
int indx3) VL_MT_SAFE {
|
||||
@@ -283,7 +268,7 @@ static void _vl_svGetBitArrElemVecVal(svBitVecVal* d, const svOpenArrayHandle s,
|
||||
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(s);
|
||||
void* datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3);
|
||||
if (VL_UNLIKELY(!datap)) return;
|
||||
switch (varp->vltype()) {
|
||||
switch (varp->vltype()) { // LCOV_EXCL_BR_LINE
|
||||
case VLVT_UINT8: d[0] = *(reinterpret_cast<CData*>(datap)); return;
|
||||
case VLVT_UINT16: d[0] = *(reinterpret_cast<SData*>(datap)); return;
|
||||
case VLVT_UINT32: d[0] = *(reinterpret_cast<IData*>(datap)); return;
|
||||
@@ -299,10 +284,10 @@ static void _vl_svGetBitArrElemVecVal(svBitVecVal* d, const svOpenArrayHandle s,
|
||||
for (int i = 0; i < VL_WORDS_I(varp->packed().elements()); ++i) d[i] = wdatap[i];
|
||||
return;
|
||||
}
|
||||
default:
|
||||
default: // LCOV_EXCL_START // Errored earlier
|
||||
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n",
|
||||
varp->vltype());
|
||||
return;
|
||||
return; // LCOV_EXCL_STOP
|
||||
}
|
||||
}
|
||||
/// Copy to user logic array from simulator open array
|
||||
@@ -311,7 +296,7 @@ static void _vl_svGetLogicArrElemVecVal(svLogicVecVal* d, const svOpenArrayHandl
|
||||
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(s);
|
||||
void* datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3);
|
||||
if (VL_UNLIKELY(!datap)) return;
|
||||
switch (varp->vltype()) {
|
||||
switch (varp->vltype()) { // LCOV_EXCL_BR_LINE
|
||||
case VLVT_UINT8:
|
||||
d[0].aval = *(reinterpret_cast<CData*>(datap));
|
||||
d[0].bval = 0;
|
||||
@@ -330,7 +315,7 @@ static void _vl_svGetLogicArrElemVecVal(svLogicVecVal* d, const svOpenArrayHandl
|
||||
d[0].aval = lwp[0];
|
||||
d[0].bval = 0;
|
||||
d[1].aval = lwp[1];
|
||||
d[0].bval = 0;
|
||||
d[1].bval = 0;
|
||||
break;
|
||||
}
|
||||
case VLVT_WDATA: {
|
||||
@@ -341,10 +326,10 @@ static void _vl_svGetLogicArrElemVecVal(svLogicVecVal* d, const svOpenArrayHandl
|
||||
}
|
||||
return;
|
||||
}
|
||||
default:
|
||||
default: // LCOV_EXCL_START // Errored earlier
|
||||
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n",
|
||||
varp->vltype());
|
||||
return;
|
||||
return; // LCOV_EXCL_STOP
|
||||
}
|
||||
}
|
||||
|
||||
@@ -354,7 +339,7 @@ static void _vl_svPutBitArrElemVecVal(const svOpenArrayHandle d, const svBitVecV
|
||||
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(d);
|
||||
void* datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3);
|
||||
if (VL_UNLIKELY(!datap)) return;
|
||||
switch (varp->vltype()) {
|
||||
switch (varp->vltype()) { // LCOV_EXCL_BR_LINE
|
||||
case VLVT_UINT8: *(reinterpret_cast<CData*>(datap)) = s[0]; return;
|
||||
case VLVT_UINT16: *(reinterpret_cast<SData*>(datap)) = s[0]; return;
|
||||
case VLVT_UINT32: *(reinterpret_cast<IData*>(datap)) = s[0]; return;
|
||||
@@ -364,10 +349,10 @@ static void _vl_svPutBitArrElemVecVal(const svOpenArrayHandle d, const svBitVecV
|
||||
for (int i = 0; i < VL_WORDS_I(varp->packed().elements()); ++i) wdatap[i] = s[i];
|
||||
return;
|
||||
}
|
||||
default:
|
||||
default: // LCOV_EXCL_START // Errored earlier
|
||||
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n",
|
||||
varp->vltype());
|
||||
return;
|
||||
return; // LCOV_EXCL_STOP
|
||||
}
|
||||
}
|
||||
/// Copy to simulator open array from from user logic array
|
||||
@@ -376,7 +361,7 @@ static void _vl_svPutLogicArrElemVecVal(const svOpenArrayHandle d, const svLogic
|
||||
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(d);
|
||||
void* datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3);
|
||||
if (VL_UNLIKELY(!datap)) return;
|
||||
switch (varp->vltype()) {
|
||||
switch (varp->vltype()) { // LCOV_EXCL_BR_LINE
|
||||
case VLVT_UINT8: *(reinterpret_cast<CData*>(datap)) = s[0].aval; return;
|
||||
case VLVT_UINT16: *(reinterpret_cast<SData*>(datap)) = s[0].aval; return;
|
||||
case VLVT_UINT32: *(reinterpret_cast<IData*>(datap)) = s[0].aval; return;
|
||||
@@ -388,10 +373,10 @@ static void _vl_svPutLogicArrElemVecVal(const svOpenArrayHandle d, const svLogic
|
||||
for (int i = 0; i < VL_WORDS_I(varp->packed().elements()); ++i) wdatap[i] = s[i].aval;
|
||||
return;
|
||||
}
|
||||
default:
|
||||
default: // LCOV_EXCL_START // Errored earlier
|
||||
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n",
|
||||
varp->vltype());
|
||||
return;
|
||||
return; // LCOV_EXCL_STOP
|
||||
}
|
||||
}
|
||||
|
||||
@@ -400,31 +385,14 @@ static svBit _vl_svGetBitArrElem(const svOpenArrayHandle s, int nargs, int indx1
|
||||
int indx3, int indx4) VL_MT_SAFE {
|
||||
// One extra index supported, as need bit number
|
||||
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(s);
|
||||
void* datap;
|
||||
int lsb;
|
||||
if (varp->packed().elements()) {
|
||||
datap = _vl_sv_adjusted_datap(varp, nargs - 1, indx1, indx2, indx3);
|
||||
lsb = _vl_sv_adjusted_bit(
|
||||
varp, ((nargs == 1) ? indx1 : (nargs == 2) ? indx2 : (nargs == 3) ? indx3 : indx4));
|
||||
} else {
|
||||
datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3);
|
||||
lsb = 0;
|
||||
}
|
||||
void* datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3);
|
||||
if (VL_UNLIKELY(!datap)) return 0;
|
||||
switch (varp->vltype()) {
|
||||
case VLVT_UINT8: return (*(reinterpret_cast<CData*>(datap)) >> lsb) & 1;
|
||||
case VLVT_UINT16: return (*(reinterpret_cast<SData*>(datap)) >> lsb) & 1;
|
||||
case VLVT_UINT32: return (*(reinterpret_cast<IData*>(datap)) >> lsb) & 1;
|
||||
case VLVT_UINT64:
|
||||
return (*(reinterpret_cast<QData*>(datap)) >> static_cast<QData>(lsb)) & 1ULL;
|
||||
case VLVT_WDATA: {
|
||||
WDataOutP wdatap = (reinterpret_cast<WDataOutP>(datap));
|
||||
return VL_BITRSHIFT_W(wdatap, lsb) & 1;
|
||||
}
|
||||
default:
|
||||
switch (varp->vltype()) { // LCOV_EXCL_BR_LINE
|
||||
case VLVT_UINT8: return (*(reinterpret_cast<CData*>(datap))) & 1;
|
||||
default: // LCOV_EXCL_START // Errored earlier
|
||||
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n",
|
||||
varp->vltype());
|
||||
return 0;
|
||||
return 0; // LCOV_EXCL_STOP
|
||||
}
|
||||
}
|
||||
/// Update simulator open array from bit
|
||||
@@ -433,27 +401,14 @@ static void _vl_svPutBitArrElem(const svOpenArrayHandle d, svBit value, int narg
|
||||
// One extra index supported, as need bit number
|
||||
value &= 1; // Make sure clean
|
||||
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(d);
|
||||
void* datap;
|
||||
int lsb;
|
||||
if (varp->packed().elements()) {
|
||||
datap = _vl_sv_adjusted_datap(varp, nargs - 1, indx1, indx2, indx3);
|
||||
lsb = _vl_sv_adjusted_bit(
|
||||
varp, ((nargs == 1) ? indx1 : (nargs == 2) ? indx2 : (nargs == 3) ? indx3 : indx4));
|
||||
} else {
|
||||
datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3);
|
||||
lsb = 0;
|
||||
}
|
||||
void* datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3);
|
||||
if (VL_UNLIKELY(!datap)) return;
|
||||
switch (varp->vltype()) {
|
||||
case VLVT_UINT8: VL_ASSIGNBIT_II(-1, lsb, *(reinterpret_cast<CData*>(datap)), value); return;
|
||||
case VLVT_UINT16: VL_ASSIGNBIT_II(-1, lsb, *(reinterpret_cast<SData*>(datap)), value); return;
|
||||
case VLVT_UINT32: VL_ASSIGNBIT_II(-1, lsb, *(reinterpret_cast<IData*>(datap)), value); return;
|
||||
case VLVT_UINT64: VL_ASSIGNBIT_QI(-1, lsb, *(reinterpret_cast<QData*>(datap)), value); return;
|
||||
case VLVT_WDATA: VL_ASSIGNBIT_WI(-1, lsb, (reinterpret_cast<WDataOutP>(datap)), value); return;
|
||||
default:
|
||||
switch (varp->vltype()) { // LCOV_EXCL_BR_LINE
|
||||
case VLVT_UINT8: *(reinterpret_cast<CData*>(datap)) = value; return;
|
||||
default: // LCOV_EXCL_START // Errored earlier
|
||||
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n",
|
||||
varp->vltype());
|
||||
return;
|
||||
return; // LCOV_EXCL_STOP
|
||||
}
|
||||
}
|
||||
|
||||
@@ -643,13 +598,6 @@ svBit svGetBitArrElem(const svOpenArrayHandle s, int indx1, ...) {
|
||||
out = _vl_svGetBitArrElem(s, 3, indx1, indx2, indx3, 0);
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
int indx2 = va_arg(ap, int);
|
||||
int indx3 = va_arg(ap, int);
|
||||
int indx4 = va_arg(ap, int);
|
||||
out = _vl_svGetBitArrElem(s, 4, indx1, indx2, indx3, indx4);
|
||||
break;
|
||||
}
|
||||
default: out = _vl_svGetBitArrElem(s, -1, 0, 0, 0, 0); break; // Will error
|
||||
}
|
||||
va_end(ap);
|
||||
@@ -683,13 +631,6 @@ svLogic svGetLogicArrElem(const svOpenArrayHandle s, int indx1, ...) {
|
||||
out = _vl_svGetBitArrElem(s, 3, indx1, indx2, indx3, 0);
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
int indx2 = va_arg(ap, int);
|
||||
int indx3 = va_arg(ap, int);
|
||||
int indx4 = va_arg(ap, int);
|
||||
out = _vl_svGetBitArrElem(s, 4, indx1, indx2, indx3, indx4);
|
||||
break;
|
||||
}
|
||||
default: out = _vl_svGetBitArrElem(s, -1, 0, 0, 0, 0); break; // Will error
|
||||
}
|
||||
va_end(ap);
|
||||
@@ -725,13 +666,6 @@ void svPutBitArrElem(const svOpenArrayHandle d, svBit value, int indx1, ...) {
|
||||
_vl_svPutBitArrElem(d, value, 3, indx1, indx2, indx3, 0);
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
int indx2 = va_arg(ap, int);
|
||||
int indx3 = va_arg(ap, int);
|
||||
int indx4 = va_arg(ap, int);
|
||||
_vl_svPutBitArrElem(d, value, 4, indx1, indx2, indx3, indx4);
|
||||
break;
|
||||
}
|
||||
default: _vl_svPutBitArrElem(d, value, -1, 0, 0, 0, 0); break; // Will error
|
||||
}
|
||||
va_end(ap);
|
||||
@@ -763,13 +697,6 @@ void svPutLogicArrElem(const svOpenArrayHandle d, svLogic value, int indx1, ...)
|
||||
_vl_svPutBitArrElem(d, value, 3, indx1, indx2, indx3, 0);
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
int indx2 = va_arg(ap, int);
|
||||
int indx3 = va_arg(ap, int);
|
||||
int indx4 = va_arg(ap, int);
|
||||
_vl_svPutBitArrElem(d, value, 4, indx1, indx2, indx3, indx4);
|
||||
break;
|
||||
}
|
||||
default: _vl_svPutBitArrElem(d, value, -1, 0, 0, 0, 0); break; // Will error
|
||||
}
|
||||
va_end(ap);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2020 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2021 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
//
|
||||
// THIS MODULE IS PUBLICLY LICENSED
|
||||
//
|
||||
// Copyright 2001-2020 by Wilson Snyder. This program is free software; you
|
||||
// Copyright 2001-2021 by Wilson Snyder. This program is free software; you
|
||||
// can redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
//
|
||||
// THIS MODULE IS PUBLICLY LICENSED
|
||||
//
|
||||
// Copyright 2001-2020 by Wilson Snyder. This program is free software; you
|
||||
// Copyright 2001-2021 by Wilson Snyder. This program is free software; you
|
||||
// can redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -35,7 +35,7 @@
|
||||
/// Base class to create a Verilator FST dump
|
||||
/// This is an internally used class - see VerilatedFstC for what to call from applications
|
||||
|
||||
class VerilatedFst : public VerilatedTrace<VerilatedFst> {
|
||||
class VerilatedFst final : public VerilatedTrace<VerilatedFst> {
|
||||
private:
|
||||
// Give the superclass access to private bits (to avoid virtual functions)
|
||||
friend class VerilatedTrace<VerilatedFst>;
|
||||
@@ -128,7 +128,7 @@ template <> void VerilatedTrace<VerilatedFst>::set_time_resolution(const std::st
|
||||
/// Also derived for use in SystemC simulations.
|
||||
/// Thread safety: Unless otherwise indicated, every function is VL_MT_UNSAFE_ONE
|
||||
|
||||
class VerilatedFstC {
|
||||
class VerilatedFstC final {
|
||||
VerilatedFst m_sptrace; ///< Trace file being created
|
||||
|
||||
// CONSTRUCTORS
|
||||
|
||||
+601
-133
@@ -1,7 +1,7 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2010-2020 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2010-2021 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -26,10 +26,13 @@
|
||||
|
||||
#include "verilated.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <deque>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <unordered_set>
|
||||
|
||||
//===================================================================
|
||||
// String formatters (required by below containers)
|
||||
@@ -41,10 +44,21 @@ extern std::string VL_TO_STRING(QData lhs);
|
||||
inline std::string VL_TO_STRING(const std::string& obj) { return "\"" + obj + "\""; }
|
||||
extern std::string VL_TO_STRING_W(int words, WDataInP obj);
|
||||
|
||||
//===================================================================
|
||||
// Shuffle RNG
|
||||
|
||||
class VlURNG final {
|
||||
public:
|
||||
typedef size_t result_type;
|
||||
static constexpr size_t min() { return 0; }
|
||||
static constexpr size_t max() { return 1ULL << 31; }
|
||||
size_t operator()() { return VL_MASK_I(31) & VL_RANDOM_I(32); }
|
||||
};
|
||||
|
||||
//===================================================================
|
||||
// Readmem/Writemem operation classes
|
||||
|
||||
class VlReadMem {
|
||||
class VlReadMem final {
|
||||
bool m_hex; // Hex format
|
||||
int m_bits; // Bit width of values
|
||||
const std::string& m_filename; // Filename
|
||||
@@ -61,7 +75,7 @@ public:
|
||||
void setData(void* valuep, const std::string& rhs);
|
||||
};
|
||||
|
||||
class VlWriteMem {
|
||||
class VlWriteMem final {
|
||||
bool m_hex; // Hex format
|
||||
int m_bits; // Bit width of values
|
||||
FILE* m_fp; // File handle for filename
|
||||
@@ -74,22 +88,33 @@ public:
|
||||
};
|
||||
|
||||
//===================================================================
|
||||
// Verilog array container
|
||||
// Verilog wide-number-in-array container
|
||||
// Similar to std::array<WData, N>, but lighter weight, only methods needed
|
||||
// by Verilator, to help compile time.
|
||||
//
|
||||
// This is only used when we need an upper-level container and so can't
|
||||
// simply use a C style array (which is just a pointer).
|
||||
|
||||
template <std::size_t T_Words> class VlWide {
|
||||
WData m_storage[T_Words];
|
||||
template <std::size_t T_Words> class VlWide final {
|
||||
EData m_storage[T_Words];
|
||||
|
||||
public:
|
||||
// cppcheck-suppress uninitVar
|
||||
VlWide() {}
|
||||
~VlWide() {}
|
||||
const WData& at(size_t index) const { return m_storage[index]; }
|
||||
WData& at(size_t index) { return m_storage[index]; }
|
||||
VlWide() = default;
|
||||
~VlWide() = default;
|
||||
VlWide(const VlWide&) = default;
|
||||
VlWide(VlWide&&) = default;
|
||||
|
||||
// OPERATOR METHODS
|
||||
VlWide& operator=(const VlWide&) = default;
|
||||
VlWide& operator=(VlWide&&) = default;
|
||||
const EData& operator[](size_t index) const { return m_storage[index]; };
|
||||
EData& operator[](size_t index) { return m_storage[index]; };
|
||||
operator WDataOutP() { return &m_storage[0]; }
|
||||
|
||||
// METHODS
|
||||
const EData& at(size_t index) const { return m_storage[index]; }
|
||||
EData& at(size_t index) { return m_storage[index]; }
|
||||
WData* data() { return &m_storage[0]; }
|
||||
const WData* data() const { return &m_storage[0]; }
|
||||
bool operator<(const VlWide<T_Words>& rhs) const {
|
||||
@@ -107,12 +132,369 @@ template <std::size_t T_Words> std::string VL_TO_STRING(const VlWide<T_Words>& o
|
||||
return VL_TO_STRING_W(T_Words, obj.data());
|
||||
}
|
||||
|
||||
//===================================================================
|
||||
// Verilog queue and dynamic array container
|
||||
// There are no multithreaded locks on this; the base variable must
|
||||
// be protected by other means
|
||||
//
|
||||
// Bound here is the maximum size() allowed, e.g. 1 + SystemVerilog bound
|
||||
// For dynamic arrays it is always zero
|
||||
template <class T_Value, size_t T_MaxSize = 0> class VlQueue final {
|
||||
private:
|
||||
// TYPES
|
||||
typedef std::deque<T_Value> Deque;
|
||||
|
||||
public:
|
||||
typedef typename Deque::const_iterator const_iterator;
|
||||
|
||||
private:
|
||||
// MEMBERS
|
||||
Deque m_deque; // State of the assoc array
|
||||
T_Value m_defaultValue; // Default value
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
// m_defaultValue isn't defaulted. Caller's constructor must do it.
|
||||
VlQueue() = default;
|
||||
~VlQueue() = default;
|
||||
VlQueue(const VlQueue&) = default;
|
||||
VlQueue(VlQueue&&) = default;
|
||||
VlQueue& operator=(const VlQueue&) = default;
|
||||
VlQueue& operator=(VlQueue&&) = default;
|
||||
|
||||
// Standard copy constructor works. Verilog: assoca = assocb
|
||||
// Also must allow conversion from a different T_MaxSize queue
|
||||
template <size_t U_MaxSize = 0> VlQueue operator=(const VlQueue<T_Value, U_MaxSize>& rhs) {
|
||||
m_deque = rhs.privateDeque();
|
||||
if (VL_UNLIKELY(T_MaxSize && T_MaxSize < m_deque.size())) m_deque.resize(T_MaxSize - 1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
static VlQueue cons(const T_Value& lhs) {
|
||||
VlQueue out;
|
||||
out.push_back(lhs);
|
||||
return out;
|
||||
}
|
||||
static VlQueue cons(const T_Value& lhs, const T_Value& rhs) {
|
||||
VlQueue out;
|
||||
out.push_back(rhs);
|
||||
out.push_back(lhs);
|
||||
return out;
|
||||
}
|
||||
static VlQueue cons(const VlQueue& lhs, const T_Value& rhs) {
|
||||
VlQueue out = lhs;
|
||||
out.push_front(rhs);
|
||||
return out;
|
||||
}
|
||||
static VlQueue cons(const T_Value& lhs, const VlQueue& rhs) {
|
||||
VlQueue out = rhs;
|
||||
out.push_back(lhs);
|
||||
return out;
|
||||
}
|
||||
static VlQueue cons(const VlQueue& lhs, const VlQueue& rhs) {
|
||||
VlQueue out = rhs;
|
||||
for (const auto& i : lhs.m_deque) out.push_back(i);
|
||||
return out;
|
||||
}
|
||||
|
||||
// METHODS
|
||||
T_Value& atDefault() { return m_defaultValue; }
|
||||
const T_Value& atDefault() const { return m_defaultValue; }
|
||||
const Deque& privateDeque() const { return m_deque; }
|
||||
|
||||
// Size. Verilog: function int size(), or int num()
|
||||
int size() const { return m_deque.size(); }
|
||||
// Clear array. Verilog: function void delete([input index])
|
||||
void clear() { m_deque.clear(); }
|
||||
void erase(vlsint32_t index) {
|
||||
if (VL_LIKELY(index >= 0 && index < m_deque.size()))
|
||||
m_deque.erase(m_deque.begin() + index);
|
||||
}
|
||||
|
||||
// Dynamic array new[] becomes a renew()
|
||||
void renew(size_t size) {
|
||||
clear();
|
||||
m_deque.resize(size, atDefault());
|
||||
}
|
||||
// Dynamic array new[]() becomes a renew_copy()
|
||||
void renew_copy(size_t size, const VlQueue<T_Value, T_MaxSize>& rhs) {
|
||||
if (size == 0) {
|
||||
clear();
|
||||
} else {
|
||||
*this = rhs;
|
||||
m_deque.resize(size, atDefault());
|
||||
}
|
||||
}
|
||||
|
||||
// function void q.push_front(value)
|
||||
void push_front(const T_Value& value) {
|
||||
m_deque.push_front(value);
|
||||
if (VL_UNLIKELY(T_MaxSize != 0 && m_deque.size() > T_MaxSize)) m_deque.pop_back();
|
||||
}
|
||||
// function void q.push_back(value)
|
||||
void push_back(const T_Value& value) {
|
||||
if (VL_LIKELY(T_MaxSize == 0 || m_deque.size() < T_MaxSize)) m_deque.push_back(value);
|
||||
}
|
||||
// function value_t q.pop_front();
|
||||
T_Value pop_front() {
|
||||
if (m_deque.empty()) return m_defaultValue;
|
||||
T_Value v = m_deque.front();
|
||||
m_deque.pop_front();
|
||||
return v;
|
||||
}
|
||||
// function value_t q.pop_back();
|
||||
T_Value pop_back() {
|
||||
if (m_deque.empty()) return m_defaultValue;
|
||||
T_Value v = m_deque.back();
|
||||
m_deque.pop_back();
|
||||
return v;
|
||||
}
|
||||
|
||||
// Setting. Verilog: assoc[index] = v
|
||||
// Can't just overload operator[] or provide a "at" reference to set,
|
||||
// because we need to be able to insert only when the value is set
|
||||
T_Value& at(vlsint32_t index) {
|
||||
static T_Value s_throwAway;
|
||||
// Needs to work for dynamic arrays, so does not use T_MaxSize
|
||||
if (VL_UNLIKELY(index < 0 || index >= m_deque.size())) {
|
||||
s_throwAway = atDefault();
|
||||
return s_throwAway;
|
||||
} else {
|
||||
return m_deque[index];
|
||||
}
|
||||
}
|
||||
// Accessing. Verilog: v = assoc[index]
|
||||
const T_Value& at(vlsint32_t index) const {
|
||||
static T_Value s_throwAway;
|
||||
// Needs to work for dynamic arrays, so does not use T_MaxSize
|
||||
if (VL_UNLIKELY(index < 0 || index >= m_deque.size())) {
|
||||
return atDefault();
|
||||
} else {
|
||||
return m_deque[index];
|
||||
}
|
||||
}
|
||||
// function void q.insert(index, value);
|
||||
void insert(vlsint32_t index, const T_Value& value) {
|
||||
if (VL_UNLIKELY(index < 0 || index >= m_deque.size())) return;
|
||||
m_deque.insert(m_deque.begin() + index, value);
|
||||
}
|
||||
|
||||
// Return slice q[lsb:msb]
|
||||
VlQueue slice(vlsint32_t lsb, vlsint32_t msb) const {
|
||||
VlQueue out;
|
||||
if (VL_UNLIKELY(lsb < 0)) lsb = 0;
|
||||
if (VL_UNLIKELY(lsb >= m_deque.size())) lsb = m_deque.size() - 1;
|
||||
if (VL_UNLIKELY(msb >= m_deque.size())) msb = m_deque.size() - 1;
|
||||
for (vlsint32_t i = lsb; i <= msb; ++i) out.push_back(m_deque[i]);
|
||||
return out;
|
||||
}
|
||||
|
||||
// For save/restore
|
||||
const_iterator begin() const { return m_deque.begin(); }
|
||||
const_iterator end() const { return m_deque.end(); }
|
||||
|
||||
// Methods
|
||||
void sort() { std::sort(m_deque.begin(), m_deque.end()); }
|
||||
template <typename Func> void sort(Func with_func) {
|
||||
// with_func returns arbitrary type to use for the sort comparison
|
||||
std::sort(m_deque.begin(), m_deque.end(), [=](const T_Value& a, const T_Value& b) {
|
||||
// index number is meaninless with sort, as it changes
|
||||
return with_func(0, a) < with_func(0, b);
|
||||
});
|
||||
}
|
||||
void rsort() { std::sort(m_deque.rbegin(), m_deque.rend()); }
|
||||
template <typename Func> void rsort(Func with_func) {
|
||||
// with_func returns arbitrary type to use for the sort comparison
|
||||
std::sort(m_deque.rbegin(), m_deque.rend(), [=](const T_Value& a, const T_Value& b) {
|
||||
// index number is meaninless with sort, as it changes
|
||||
return with_func(0, a) < with_func(0, b);
|
||||
});
|
||||
}
|
||||
void reverse() { std::reverse(m_deque.begin(), m_deque.end()); }
|
||||
void shuffle() { std::shuffle(m_deque.begin(), m_deque.end(), VlURNG()); }
|
||||
VlQueue unique() const {
|
||||
VlQueue out;
|
||||
std::unordered_set<T_Value> saw;
|
||||
for (const auto& i : m_deque) {
|
||||
auto it = saw.find(i);
|
||||
if (it == saw.end()) {
|
||||
saw.insert(it, i);
|
||||
out.push_back(i);
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
VlQueue<IData> unique_index() const {
|
||||
VlQueue<IData> out;
|
||||
IData index = 0;
|
||||
std::unordered_set<T_Value> saw;
|
||||
for (const auto& i : m_deque) {
|
||||
auto it = saw.find(i);
|
||||
if (it == saw.end()) {
|
||||
saw.insert(it, i);
|
||||
out.push_back(index);
|
||||
}
|
||||
++index;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
template <typename Func> VlQueue find(Func with_func) const {
|
||||
VlQueue out;
|
||||
IData index = 0;
|
||||
for (const auto& i : m_deque) {
|
||||
if (with_func(index, i)) out.push_back(i);
|
||||
++index;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
template <typename Func> VlQueue<IData> find_index(Func with_func) const {
|
||||
VlQueue<IData> out;
|
||||
IData index = 0;
|
||||
for (const auto& i : m_deque) {
|
||||
if (with_func(index, i)) out.push_back(index);
|
||||
++index;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
template <typename Func> VlQueue find_first(Func with_func) const {
|
||||
// Can't use std::find_if as need index number
|
||||
IData index = 0;
|
||||
for (const auto& i : m_deque) {
|
||||
if (with_func(index, i)) return VlQueue::cons(i);
|
||||
++index;
|
||||
}
|
||||
return VlQueue{};
|
||||
}
|
||||
template <typename Func> VlQueue<IData> find_first_index(Func with_func) const {
|
||||
IData index = 0;
|
||||
for (const auto& i : m_deque) {
|
||||
if (with_func(index, i)) return VlQueue<IData>::cons(index);
|
||||
++index;
|
||||
}
|
||||
return VlQueue<IData>{};
|
||||
}
|
||||
template <typename Func> VlQueue find_last(Func with_func) const {
|
||||
IData index = m_deque.size() - 1;
|
||||
for (auto it = m_deque.rbegin(); it != m_deque.rend(); ++it) {
|
||||
if (with_func(index, *it)) return VlQueue::cons(*it);
|
||||
--index;
|
||||
}
|
||||
return VlQueue{};
|
||||
}
|
||||
template <typename Func> VlQueue<IData> find_last_index(Func with_func) const {
|
||||
IData index = m_deque.size() - 1;
|
||||
for (auto it = m_deque.rbegin(); it != m_deque.rend(); ++it) {
|
||||
if (with_func(index, *it)) return VlQueue<IData>::cons(index);
|
||||
--index;
|
||||
}
|
||||
return VlQueue<IData>{};
|
||||
}
|
||||
|
||||
// Reduction operators
|
||||
VlQueue min() const {
|
||||
if (m_deque.empty()) return VlQueue();
|
||||
const auto it = std::min_element(m_deque.begin(), m_deque.end());
|
||||
return VlQueue::cons(*it);
|
||||
}
|
||||
VlQueue max() const {
|
||||
if (m_deque.empty()) return VlQueue();
|
||||
const auto it = std::max_element(m_deque.begin(), m_deque.end());
|
||||
return VlQueue::cons(*it);
|
||||
}
|
||||
|
||||
T_Value r_sum() const {
|
||||
T_Value out(0); // Type must have assignment operator
|
||||
for (const auto& i : m_deque) out += i;
|
||||
return out;
|
||||
}
|
||||
template <typename Func> T_Value r_sum(Func with_func) const {
|
||||
T_Value out(0); // Type must have assignment operator
|
||||
IData index = 0;
|
||||
for (const auto& i : m_deque) out += with_func(index++, i);
|
||||
return out;
|
||||
}
|
||||
T_Value r_product() const {
|
||||
if (m_deque.empty()) return T_Value(0);
|
||||
auto it = m_deque.begin();
|
||||
T_Value out{*it};
|
||||
++it;
|
||||
for (; it != m_deque.end(); ++it) out *= *it;
|
||||
return out;
|
||||
}
|
||||
template <typename Func> T_Value r_product(Func with_func) const {
|
||||
if (m_deque.empty()) return T_Value(0);
|
||||
auto it = m_deque.begin();
|
||||
IData index = 0;
|
||||
T_Value out{with_func(index, *it)};
|
||||
++it;
|
||||
++index;
|
||||
for (; it != m_deque.end(); ++it) out *= with_func(index++, *it);
|
||||
return out;
|
||||
}
|
||||
T_Value r_and() const {
|
||||
if (m_deque.empty()) return T_Value(0);
|
||||
auto it = m_deque.begin();
|
||||
T_Value out{*it};
|
||||
++it;
|
||||
for (; it != m_deque.end(); ++it) out &= *it;
|
||||
return out;
|
||||
}
|
||||
template <typename Func> T_Value r_and(Func with_func) const {
|
||||
if (m_deque.empty()) return T_Value(0);
|
||||
auto it = m_deque.begin();
|
||||
IData index = 0;
|
||||
T_Value out{with_func(index, *it)};
|
||||
++it;
|
||||
++index;
|
||||
for (; it != m_deque.end(); ++it) out &= with_func(index, *it);
|
||||
return out;
|
||||
}
|
||||
T_Value r_or() const {
|
||||
T_Value out(0); // Type must have assignment operator
|
||||
for (const auto& i : m_deque) out |= i;
|
||||
return out;
|
||||
}
|
||||
template <typename Func> T_Value r_or(Func with_func) const {
|
||||
T_Value out(0); // Type must have assignment operator
|
||||
IData index = 0;
|
||||
for (const auto& i : m_deque) out |= with_func(index++, i);
|
||||
return out;
|
||||
}
|
||||
T_Value r_xor() const {
|
||||
T_Value out(0); // Type must have assignment operator
|
||||
for (const auto& i : m_deque) out ^= i;
|
||||
return out;
|
||||
}
|
||||
template <typename Func> T_Value r_xor(Func with_func) const {
|
||||
T_Value out(0); // Type must have assignment operator
|
||||
IData index = 0;
|
||||
for (const auto& i : m_deque) out ^= with_func(index++, i);
|
||||
return out;
|
||||
}
|
||||
|
||||
// Dumping. Verilog: str = $sformatf("%p", assoc)
|
||||
std::string to_string() const {
|
||||
if (m_deque.empty()) return "'{}"; // No trailing space
|
||||
std::string out = "'{";
|
||||
std::string comma;
|
||||
for (const auto& i : m_deque) {
|
||||
out += comma + VL_TO_STRING(i);
|
||||
comma = ", ";
|
||||
}
|
||||
return out + "} ";
|
||||
}
|
||||
};
|
||||
|
||||
template <class T_Value> std::string VL_TO_STRING(const VlQueue<T_Value>& obj) {
|
||||
return obj.to_string();
|
||||
}
|
||||
|
||||
//===================================================================
|
||||
// Verilog associative array container
|
||||
// There are no multithreaded locks on this; the base variable must
|
||||
// be protected by other means
|
||||
//
|
||||
template <class T_Key, class T_Value> class VlAssocArray {
|
||||
template <class T_Key, class T_Value> class VlAssocArray final {
|
||||
private:
|
||||
// TYPES
|
||||
typedef std::map<T_Key, T_Value> Map;
|
||||
@@ -127,14 +509,17 @@ private:
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
VlAssocArray() {
|
||||
// m_defaultValue isn't defaulted. Caller's constructor must do it.
|
||||
}
|
||||
~VlAssocArray() {}
|
||||
// Standard copy constructor works. Verilog: assoca = assocb
|
||||
// m_defaultValue isn't defaulted. Caller's constructor must do it.
|
||||
VlAssocArray() = default;
|
||||
~VlAssocArray() = default;
|
||||
VlAssocArray(const VlAssocArray&) = default;
|
||||
VlAssocArray(VlAssocArray&&) = default;
|
||||
VlAssocArray& operator=(const VlAssocArray&) = default;
|
||||
VlAssocArray& operator=(VlAssocArray&&) = default;
|
||||
|
||||
// METHODS
|
||||
T_Value& atDefault() { return m_defaultValue; }
|
||||
const T_Value& atDefault() const { return m_defaultValue; }
|
||||
|
||||
// Size of array. Verilog: function int size(), or int num()
|
||||
int size() const { return m_map.size(); }
|
||||
@@ -181,8 +566,7 @@ public:
|
||||
T_Value& at(const T_Key& index) {
|
||||
const auto it = m_map.find(index);
|
||||
if (it == m_map.end()) {
|
||||
std::pair<typename Map::iterator, bool> pit
|
||||
= m_map.insert(std::make_pair(index, m_defaultValue));
|
||||
std::pair<typename Map::iterator, bool> pit = m_map.emplace(index, m_defaultValue);
|
||||
return pit.first->second;
|
||||
}
|
||||
return it->second;
|
||||
@@ -196,12 +580,176 @@ public:
|
||||
return it->second;
|
||||
}
|
||||
}
|
||||
// Setting as a chained operation
|
||||
VlAssocArray& set(const T_Key& index, const T_Value& value) {
|
||||
at(index) = value;
|
||||
return *this;
|
||||
}
|
||||
VlAssocArray& setDefault(const T_Value& value) {
|
||||
atDefault() = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// For save/restore
|
||||
const_iterator begin() const { return m_map.begin(); }
|
||||
const_iterator end() const { return m_map.end(); }
|
||||
|
||||
// Methods
|
||||
VlQueue<T_Value> unique() const {
|
||||
VlQueue<T_Value> out;
|
||||
std::set<T_Value> saw;
|
||||
for (const auto& i : m_map) {
|
||||
auto it = saw.find(i.second);
|
||||
if (it == saw.end()) {
|
||||
saw.insert(it, i.second);
|
||||
out.push_back(i.second);
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
VlQueue<T_Key> unique_index() const {
|
||||
VlQueue<T_Key> out;
|
||||
std::set<T_Key> saw;
|
||||
for (const auto& i : m_map) {
|
||||
auto it = saw.find(i.second);
|
||||
if (it == saw.end()) {
|
||||
saw.insert(it, i.second);
|
||||
out.push_back(i.first);
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
template <typename Func> VlQueue<T_Value> find(Func with_func) const {
|
||||
VlQueue<T_Value> out;
|
||||
for (const auto& i : m_map)
|
||||
if (with_func(i.first, i.second)) out.push_back(i.second);
|
||||
return out;
|
||||
}
|
||||
template <typename Func> VlQueue<T_Key> find_index(Func with_func) const {
|
||||
VlQueue<T_Key> out;
|
||||
for (const auto& i : m_map)
|
||||
if (with_func(i.first, i.second)) out.push_back(i.first);
|
||||
return out;
|
||||
}
|
||||
template <typename Func> VlQueue<T_Value> find_first(Func with_func) const {
|
||||
const auto it
|
||||
= std::find_if(m_map.begin(), m_map.end(), [=](const std::pair<T_Key, T_Value>& i) {
|
||||
return with_func(i.first, i.second);
|
||||
});
|
||||
if (it == m_map.end()) return VlQueue<T_Value>{};
|
||||
return VlQueue<T_Value>::cons(it->second);
|
||||
}
|
||||
template <typename Func> VlQueue<T_Key> find_first_index(Func with_func) const {
|
||||
const auto it
|
||||
= std::find_if(m_map.begin(), m_map.end(), [=](const std::pair<T_Key, T_Value>& i) {
|
||||
return with_func(i.first, i.second);
|
||||
});
|
||||
if (it == m_map.end()) return VlQueue<T_Value>{};
|
||||
return VlQueue<T_Key>::cons(it->first);
|
||||
}
|
||||
template <typename Func> VlQueue<T_Value> find_last(Func with_func) const {
|
||||
const auto it
|
||||
= std::find_if(m_map.rbegin(), m_map.rend(), [=](const std::pair<T_Key, T_Value>& i) {
|
||||
return with_func(i.first, i.second);
|
||||
});
|
||||
if (it == m_map.rend()) return VlQueue<T_Value>{};
|
||||
return VlQueue<T_Value>::cons(it->second);
|
||||
}
|
||||
template <typename Func> VlQueue<T_Key> find_last_index(Func with_func) const {
|
||||
const auto it
|
||||
= std::find_if(m_map.rbegin(), m_map.rend(), [=](const std::pair<T_Key, T_Value>& i) {
|
||||
return with_func(i.first, i.second);
|
||||
});
|
||||
if (it == m_map.rend()) return VlQueue<T_Value>{};
|
||||
return VlQueue<T_Key>::cons(it->first);
|
||||
}
|
||||
|
||||
// Reduction operators
|
||||
VlQueue<T_Value> min() const {
|
||||
if (m_map.empty()) return VlQueue<T_Value>();
|
||||
const auto it = std::min_element(
|
||||
m_map.begin(), m_map.end(),
|
||||
[](const std::pair<T_Key, T_Value>& a, const std::pair<T_Key, T_Value>& b) {
|
||||
return a.second < b.second;
|
||||
});
|
||||
return VlQueue<T_Value>::cons(it->second);
|
||||
}
|
||||
VlQueue<T_Value> max() const {
|
||||
if (m_map.empty()) return VlQueue<T_Value>();
|
||||
const auto it = std::max_element(
|
||||
m_map.begin(), m_map.end(),
|
||||
[](const std::pair<T_Key, T_Value>& a, const std::pair<T_Key, T_Value>& b) {
|
||||
return a.second < b.second;
|
||||
});
|
||||
return VlQueue<T_Value>::cons(it->second);
|
||||
}
|
||||
|
||||
T_Value r_sum() const {
|
||||
T_Value out(0); // Type must have assignment operator
|
||||
for (const auto& i : m_map) out += i.second;
|
||||
return out;
|
||||
}
|
||||
template <typename Func> T_Value r_sum(Func with_func) const {
|
||||
T_Value out(0); // Type must have assignment operator
|
||||
for (const auto& i : m_map) out += with_func(i.first, i.second);
|
||||
return out;
|
||||
}
|
||||
T_Value r_product() const {
|
||||
if (m_map.empty()) return T_Value(0);
|
||||
auto it = m_map.begin();
|
||||
T_Value out{it->second};
|
||||
++it;
|
||||
for (; it != m_map.end(); ++it) out *= it->second;
|
||||
return out;
|
||||
}
|
||||
template <typename Func> T_Value r_product(Func with_func) const {
|
||||
if (m_map.empty()) return T_Value(0);
|
||||
auto it = m_map.begin();
|
||||
T_Value out{with_func(it->first, it->second)};
|
||||
++it;
|
||||
for (; it != m_map.end(); ++it) out *= with_func(it->first, it->second);
|
||||
return out;
|
||||
}
|
||||
T_Value r_and() const {
|
||||
if (m_map.empty()) return T_Value(0);
|
||||
auto it = m_map.begin();
|
||||
T_Value out{it->second};
|
||||
++it;
|
||||
for (; it != m_map.end(); ++it) out &= it->second;
|
||||
return out;
|
||||
}
|
||||
template <typename Func> T_Value r_and(Func with_func) const {
|
||||
if (m_map.empty()) return T_Value(0);
|
||||
auto it = m_map.begin();
|
||||
T_Value out{with_func(it->first, it->second)};
|
||||
++it;
|
||||
for (; it != m_map.end(); ++it) out &= with_func(it->first, it->second);
|
||||
return out;
|
||||
}
|
||||
T_Value r_or() const {
|
||||
T_Value out(0); // Type must have assignment operator
|
||||
for (const auto& i : m_map) out |= i.second;
|
||||
return out;
|
||||
}
|
||||
template <typename Func> T_Value r_or(Func with_func) const {
|
||||
T_Value out(0); // Type must have assignment operator
|
||||
for (const auto& i : m_map) out |= with_func(i.first, i.second);
|
||||
return out;
|
||||
}
|
||||
T_Value r_xor() const {
|
||||
T_Value out(0); // Type must have assignment operator
|
||||
for (const auto& i : m_map) out ^= i.second;
|
||||
return out;
|
||||
}
|
||||
template <typename Func> T_Value r_xor(Func with_func) const {
|
||||
T_Value out(0); // Type must have assignment operator
|
||||
for (const auto& i : m_map) out ^= with_func(i.first, i.second);
|
||||
return out;
|
||||
}
|
||||
|
||||
// Dumping. Verilog: str = $sformatf("%p", assoc)
|
||||
std::string to_string() const {
|
||||
if (m_map.empty()) return "'{}"; // No trailing space
|
||||
std::string out = "'{";
|
||||
std::string comma;
|
||||
for (const auto& i : m_map) {
|
||||
@@ -246,132 +794,40 @@ void VL_WRITEMEM_N(bool hex, int bits, const std::string& filename,
|
||||
}
|
||||
|
||||
//===================================================================
|
||||
// Verilog queue and dynamic array container
|
||||
// There are no multithreaded locks on this; the base variable must
|
||||
// be protected by other means
|
||||
//
|
||||
// Bound here is the maximum size() allowed, e.g. 1 + SystemVerilog bound
|
||||
// For dynamic arrays it is always zero
|
||||
template <class T_Value, size_t T_MaxSize = 0> class VlQueue {
|
||||
// Verilog packed array container
|
||||
// For when a standard C++[] array is not sufficient, e.g. an
|
||||
// array under a queue, or methods operating on the array
|
||||
|
||||
template <class T_Value, std::size_t T_Depth> class VlUnpacked final {
|
||||
private:
|
||||
// TYPES
|
||||
typedef std::deque<T_Value> Deque;
|
||||
typedef std::array<T_Value, T_Depth> Array;
|
||||
|
||||
public:
|
||||
typedef typename Deque::const_iterator const_iterator;
|
||||
typedef typename Array::const_iterator const_iterator;
|
||||
|
||||
private:
|
||||
// MEMBERS
|
||||
Deque m_deque; // State of the assoc array
|
||||
T_Value m_defaultValue; // Default value
|
||||
Array m_array; // State of the assoc array
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
VlQueue() {
|
||||
// m_defaultValue isn't defaulted. Caller's constructor must do it.
|
||||
}
|
||||
~VlQueue() {}
|
||||
// Standard copy constructor works. Verilog: assoca = assocb
|
||||
VlUnpacked() = default;
|
||||
~VlUnpacked() = default;
|
||||
VlUnpacked(const VlUnpacked&) = default;
|
||||
VlUnpacked(VlUnpacked&&) = default;
|
||||
VlUnpacked& operator=(const VlUnpacked&) = default;
|
||||
VlUnpacked& operator=(VlUnpacked&&) = default;
|
||||
|
||||
// METHODS
|
||||
T_Value& atDefault() { return m_defaultValue; }
|
||||
// Raw access
|
||||
WData* data() { return &m_array[0]; }
|
||||
const WData* data() const { return &m_array[0]; }
|
||||
|
||||
// Size. Verilog: function int size(), or int num()
|
||||
int size() const { return m_deque.size(); }
|
||||
// Clear array. Verilog: function void delete([input index])
|
||||
void clear() { m_deque.clear(); }
|
||||
void erase(size_t index) {
|
||||
if (VL_LIKELY(index < m_deque.size())) m_deque.erase(index);
|
||||
}
|
||||
|
||||
// Dynamic array new[] becomes a renew()
|
||||
void renew(size_t size) {
|
||||
clear();
|
||||
m_deque.resize(size, atDefault());
|
||||
}
|
||||
// Dynamic array new[]() becomes a renew_copy()
|
||||
void renew_copy(size_t size, const VlQueue<T_Value, T_MaxSize>& rhs) {
|
||||
if (size == 0) {
|
||||
clear();
|
||||
} else {
|
||||
*this = rhs;
|
||||
m_deque.resize(size, atDefault());
|
||||
}
|
||||
}
|
||||
|
||||
// function void q.push_front(value)
|
||||
void push_front(const T_Value& value) {
|
||||
m_deque.push_front(value);
|
||||
if (VL_UNLIKELY(T_MaxSize != 0 && m_deque.size() > T_MaxSize)) m_deque.pop_back();
|
||||
}
|
||||
// function void q.push_back(value)
|
||||
void push_back(const T_Value& value) {
|
||||
if (VL_LIKELY(T_MaxSize == 0 || m_deque.size() < T_MaxSize)) m_deque.push_back(value);
|
||||
}
|
||||
// function value_t q.pop_front();
|
||||
T_Value pop_front() {
|
||||
if (m_deque.empty()) return m_defaultValue;
|
||||
T_Value v = m_deque.front();
|
||||
m_deque.pop_front();
|
||||
return v;
|
||||
}
|
||||
// function value_t q.pop_back();
|
||||
T_Value pop_back() {
|
||||
if (m_deque.empty()) return m_defaultValue;
|
||||
T_Value v = m_deque.back();
|
||||
m_deque.pop_back();
|
||||
return v;
|
||||
}
|
||||
|
||||
// Setting. Verilog: assoc[index] = v
|
||||
// Can't just overload operator[] or provide a "at" reference to set,
|
||||
// because we need to be able to insert only when the value is set
|
||||
T_Value& at(size_t index) {
|
||||
static T_Value s_throwAway;
|
||||
// Needs to work for dynamic arrays, so does not use T_MaxSize
|
||||
if (VL_UNLIKELY(index >= m_deque.size())) {
|
||||
s_throwAway = atDefault();
|
||||
return s_throwAway;
|
||||
} else {
|
||||
return m_deque[index];
|
||||
}
|
||||
}
|
||||
// Accessing. Verilog: v = assoc[index]
|
||||
const T_Value& at(size_t index) const {
|
||||
static T_Value s_throwAway;
|
||||
// Needs to work for dynamic arrays, so does not use T_MaxSize
|
||||
if (VL_UNLIKELY(index >= m_deque.size())) {
|
||||
return atDefault();
|
||||
} else {
|
||||
return m_deque[index];
|
||||
}
|
||||
}
|
||||
// function void q.insert(index, value);
|
||||
void insert(size_t index, const T_Value& value) {
|
||||
if (VL_UNLIKELY(index >= m_deque.size())) return;
|
||||
m_deque[index] = value;
|
||||
}
|
||||
|
||||
// For save/restore
|
||||
const_iterator begin() const { return m_deque.begin(); }
|
||||
const_iterator end() const { return m_deque.end(); }
|
||||
|
||||
// Dumping. Verilog: str = $sformatf("%p", assoc)
|
||||
std::string to_string() const {
|
||||
std::string out = "'{";
|
||||
std::string comma;
|
||||
for (const auto& i : m_deque) {
|
||||
out += comma + VL_TO_STRING(i);
|
||||
comma = ", ";
|
||||
}
|
||||
return out + "} ";
|
||||
}
|
||||
T_Value& operator[](size_t index) { return m_array[index]; };
|
||||
const T_Value& operator[](size_t index) const { return m_array[index]; };
|
||||
};
|
||||
|
||||
template <class T_Value> std::string VL_TO_STRING(const VlQueue<T_Value>& obj) {
|
||||
return obj.to_string();
|
||||
}
|
||||
|
||||
//===================================================================
|
||||
// Verilog class reference container
|
||||
// There are no multithreaded locks on this; the base variable must
|
||||
@@ -386,6 +842,17 @@ inline T VL_NULL_CHECK(T t, const char* filename, int linenum) {
|
||||
return t;
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
static inline bool VL_CAST_DYNAMIC(VlClassRef<T> in, VlClassRef<U>& outr) {
|
||||
VlClassRef<U> casted = std::dynamic_pointer_cast<U>(in);
|
||||
if (VL_LIKELY(casted)) {
|
||||
outr = casted;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//======================================================================
|
||||
// Conversion functions
|
||||
|
||||
@@ -396,6 +863,7 @@ inline std::string VL_CVT_PACK_STR_NQ(QData lhs) VL_PURE {
|
||||
return VL_CVT_PACK_STR_NW(VL_WQ_WORDS_E, lw);
|
||||
}
|
||||
inline std::string VL_CVT_PACK_STR_NN(const std::string& lhs) VL_PURE { return lhs; }
|
||||
inline std::string& VL_CVT_PACK_STR_NN(std::string& lhs) VL_PURE { return lhs; }
|
||||
inline std::string VL_CVT_PACK_STR_NI(IData lhs) VL_PURE {
|
||||
WData lw[VL_WQ_WORDS_E];
|
||||
VL_SET_WI(lw, lhs);
|
||||
@@ -477,17 +945,17 @@ extern std::string VL_SUBSTR_N(const std::string& lhs, IData rhs, IData ths) VL_
|
||||
inline IData VL_CMP_NN(const std::string& lhs, const std::string& rhs, bool ignoreCase) VL_PURE {
|
||||
// SystemVerilog does not allow a string variable to contain '\0'.
|
||||
// So C functions such as strcmp() can correctly compare strings.
|
||||
int result;
|
||||
if (ignoreCase) {
|
||||
result = VL_STRCASECMP(lhs.c_str(), rhs.c_str());
|
||||
return VL_STRCASECMP(lhs.c_str(), rhs.c_str());
|
||||
} else {
|
||||
result = std::strcmp(lhs.c_str(), rhs.c_str());
|
||||
return std::strcmp(lhs.c_str(), rhs.c_str());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
extern IData VL_ATOI_N(const std::string& str, int base) VL_PURE;
|
||||
|
||||
extern IData VL_FGETS_NI(std::string& dest, IData fpi);
|
||||
|
||||
//======================================================================
|
||||
// Dumping
|
||||
|
||||
|
||||
+33
-21
@@ -1,7 +1,7 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2009-2020 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2009-2021 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -46,7 +46,7 @@ class VerilatedScope;
|
||||
|
||||
#ifdef VL_THREADED
|
||||
/// Message, enqueued on an mtask, and consumed on the main eval thread
|
||||
class VerilatedMsg {
|
||||
class VerilatedMsg final {
|
||||
public:
|
||||
// TYPES
|
||||
struct Cmp {
|
||||
@@ -61,10 +61,14 @@ private:
|
||||
std::function<void()> m_cb; ///< Lambda to execute when message received
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
VerilatedMsg(const std::function<void()>& cb)
|
||||
explicit VerilatedMsg(const std::function<void()>& cb)
|
||||
: m_mtaskId{Verilated::mtaskId()}
|
||||
, m_cb{cb} {}
|
||||
~VerilatedMsg() {}
|
||||
~VerilatedMsg() = default;
|
||||
VerilatedMsg(const VerilatedMsg&) = default;
|
||||
VerilatedMsg(VerilatedMsg&&) = default;
|
||||
VerilatedMsg& operator=(const VerilatedMsg&) = default;
|
||||
VerilatedMsg& operator=(VerilatedMsg&&) = default;
|
||||
// METHODS
|
||||
vluint32_t mtaskId() const { return m_mtaskId; }
|
||||
/// Execute the lambda function
|
||||
@@ -74,7 +78,7 @@ public:
|
||||
/// Each thread has a queue it pushes to
|
||||
/// This assumes no thread starts pushing the next tick until the previous has drained.
|
||||
/// If more aggressiveness is needed, a double-buffered scheme might work well.
|
||||
class VerilatedEvalMsgQueue {
|
||||
class VerilatedEvalMsgQueue final {
|
||||
typedef std::multiset<VerilatedMsg, VerilatedMsg::Cmp> VerilatedThreadQueue;
|
||||
|
||||
std::atomic<vluint64_t> m_depth; ///< Current depth of queue (see comments below)
|
||||
@@ -87,7 +91,7 @@ public:
|
||||
: m_depth{0} {
|
||||
assert(atomic_is_lock_free(&m_depth));
|
||||
}
|
||||
~VerilatedEvalMsgQueue() {}
|
||||
~VerilatedEvalMsgQueue() = default;
|
||||
|
||||
private:
|
||||
VL_UNCOPYABLE(VerilatedEvalMsgQueue);
|
||||
@@ -126,7 +130,7 @@ public:
|
||||
};
|
||||
|
||||
/// Each thread has a local queue to build up messages until the end of the eval() call
|
||||
class VerilatedThreadMsgQueue {
|
||||
class VerilatedThreadMsgQueue final {
|
||||
std::queue<VerilatedMsg> m_queue;
|
||||
|
||||
public:
|
||||
@@ -170,7 +174,7 @@ public:
|
||||
#endif // VL_THREADED
|
||||
|
||||
// FILE* list constructed from a file-descriptor
|
||||
class VerilatedFpList {
|
||||
class VerilatedFpList final {
|
||||
FILE* m_fp[31];
|
||||
std::size_t m_sz = 0;
|
||||
|
||||
@@ -189,7 +193,7 @@ public:
|
||||
//======================================================================
|
||||
// VerilatedImp
|
||||
|
||||
class VerilatedImpData {
|
||||
class VerilatedImpData final {
|
||||
// Whole class is internal use only - Global information shared between verilated*.cpp files.
|
||||
protected:
|
||||
friend class Verilated;
|
||||
@@ -207,8 +211,8 @@ protected:
|
||||
int m_timeFormatPrecision = 0; // $timeformat number of decimal places
|
||||
int m_timeFormatWidth = 20; // $timeformat character width
|
||||
enum { UNITS_NONE = 99 }; // Default based on precision
|
||||
Serialized() {}
|
||||
~Serialized() {}
|
||||
Serialized() = default;
|
||||
~Serialized() = default;
|
||||
} m_ser;
|
||||
|
||||
VerilatedMutex m_sergMutex; ///< Protect m_ser
|
||||
@@ -260,7 +264,7 @@ protected:
|
||||
}
|
||||
};
|
||||
|
||||
class VerilatedImp {
|
||||
class VerilatedImp final {
|
||||
// Whole class is internal use only - Global information shared between verilated*.cpp files.
|
||||
protected:
|
||||
friend class Verilated;
|
||||
@@ -268,15 +272,15 @@ protected:
|
||||
// MEMBERS
|
||||
union VerilatedImpU { ///< Enclose in an union to call ctor/dtor manually
|
||||
VerilatedImpData v;
|
||||
VerilatedImpU() {}
|
||||
~VerilatedImpU() {}
|
||||
VerilatedImpU() {} // Can't be = default;
|
||||
~VerilatedImpU() {} // Can't be = default;
|
||||
};
|
||||
static VerilatedImpU s_s; ///< Static Singleton; One and only static this
|
||||
|
||||
public: // But only for verilated*.cpp
|
||||
// CONSTRUCTORS
|
||||
VerilatedImp() {}
|
||||
~VerilatedImp() {}
|
||||
VerilatedImp() = default;
|
||||
~VerilatedImp() = default;
|
||||
static void setup();
|
||||
static void teardown();
|
||||
|
||||
@@ -327,7 +331,7 @@ public:
|
||||
if (it != s_s.v.m_userMap.end()) {
|
||||
it->second = userData;
|
||||
} else {
|
||||
s_s.v.m_userMap.insert(it, std::make_pair(std::make_pair(scopep, userKey), userData));
|
||||
s_s.v.m_userMap.emplace(std::make_pair(scopep, userKey), userData);
|
||||
}
|
||||
}
|
||||
static inline void* userFind(const void* scopep, void* userKey) VL_MT_SAFE {
|
||||
@@ -370,9 +374,7 @@ public: // But only for verilated*.cpp
|
||||
// Slow ok - called once/scope at construction
|
||||
const VerilatedLockGuard lock(s_s.v.m_nameMutex);
|
||||
const auto it = s_s.v.m_nameMap.find(scopep->name());
|
||||
if (it == s_s.v.m_nameMap.end()) {
|
||||
s_s.v.m_nameMap.insert(it, std::make_pair(scopep->name(), scopep));
|
||||
}
|
||||
if (it == s_s.v.m_nameMap.end()) s_s.v.m_nameMap.emplace(scopep->name(), scopep);
|
||||
}
|
||||
static inline const VerilatedScope* scopeFind(const char* namep) VL_MT_SAFE {
|
||||
const VerilatedLockGuard lock(s_s.v.m_nameMutex);
|
||||
@@ -409,6 +411,16 @@ public: // But only for verilated*.cpp
|
||||
const VerilatedLockGuard lock(s_s.v.m_hierMapMutex);
|
||||
s_s.v.m_hierMap[fromp].push_back(top);
|
||||
}
|
||||
static void hierarchyRemove(const VerilatedScope* fromp,
|
||||
const VerilatedScope* top) VL_MT_SAFE {
|
||||
// Slow ok - called at destruction for VPI accessible elements
|
||||
const VerilatedLockGuard lock(s_s.v.m_hierMapMutex);
|
||||
VerilatedHierarchyMap& map = s_s.v.m_hierMap;
|
||||
if (map.find(fromp) == map.end()) return;
|
||||
VerilatedScopeVector& scopes = map[fromp];
|
||||
const auto it = find(scopes.begin(), scopes.end(), top);
|
||||
if (it != scopes.end()) scopes.erase(it);
|
||||
}
|
||||
static const VerilatedHierarchyMap* hierarchyMap() VL_MT_SAFE_POSTINIT {
|
||||
// Thread save only assuming this is called only after model construction completed
|
||||
return &s_s.v.m_hierMap;
|
||||
@@ -428,7 +440,7 @@ public: // But only for verilated*.cpp
|
||||
const VerilatedLockGuard lock(s_s.v.m_exportMutex);
|
||||
const auto it = s_s.v.m_exportMap.find(namep);
|
||||
if (it == s_s.v.m_exportMap.end()) {
|
||||
s_s.v.m_exportMap.insert(it, std::make_pair(namep, s_s.v.m_exportNext++));
|
||||
s_s.v.m_exportMap.emplace(namep, s_s.v.m_exportNext++);
|
||||
return s_s.v.m_exportNext++;
|
||||
} else {
|
||||
return it->second;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2020 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2021 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -24,8 +24,8 @@
|
||||
|
||||
// clang-format off
|
||||
|
||||
// Use VL_DISABLE_INTRINSICS to disable all intrinsics based optimization
|
||||
#if !defined(VL_DISABLE_INTRINSICS) && !defined(VL_PORTABLE_ONLY)
|
||||
// Use VL_PORTABLE_ONLY to disable all intrinsics based optimization
|
||||
#ifndef VL_PORTABLE_ONLY
|
||||
# if defined(__SSE2__) && !defined(VL_DISABLE_SSE2)
|
||||
# define VL_HAVE_SSE2 1
|
||||
# include <emmintrin.h>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
//
|
||||
// THIS MODULE IS PUBLICLY LICENSED
|
||||
//
|
||||
// Copyright 2001-2020 by Wilson Snyder. This program is free software; you
|
||||
// Copyright 2001-2021 by Wilson Snyder. This program is free software; you
|
||||
// can redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+11
-11
@@ -3,7 +3,7 @@
|
||||
//
|
||||
// THIS MODULE IS PUBLICLY LICENSED
|
||||
//
|
||||
// Copyright 2000-2020 by Wilson Snyder. This program is free software; you
|
||||
// Copyright 2000-2021 by Wilson Snyder. This program is free software; you
|
||||
// can redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -28,7 +28,7 @@
|
||||
// VerilatedSerialize - convert structures to a stream representation
|
||||
// This class is not thread safe, it must be called by a single thread
|
||||
|
||||
class VerilatedSerialize {
|
||||
class VerilatedSerialize VL_NOT_FINAL {
|
||||
protected:
|
||||
// MEMBERS
|
||||
// For speed, keep m_cp as the first member of this structure
|
||||
@@ -38,8 +38,8 @@ protected:
|
||||
std::string m_filename; ///< Filename, for error messages
|
||||
VerilatedAssertOneThread m_assertOne; ///< Assert only called from single thread
|
||||
|
||||
inline static size_t bufferSize() { return 256 * 1024; } // See below for slack calculation
|
||||
inline static size_t bufferInsertSize() { return 16 * 1024; }
|
||||
static constexpr size_t bufferSize() { return 256 * 1024; } // See below for slack calculation
|
||||
static constexpr size_t bufferInsertSize() { return 16 * 1024; }
|
||||
|
||||
void header() VL_MT_UNSAFE_ONE;
|
||||
void trailer() VL_MT_UNSAFE_ONE;
|
||||
@@ -87,7 +87,7 @@ private:
|
||||
// VerilatedDeserial - load structures from a stream representation
|
||||
// This class is not thread safe, it must be called by a single thread
|
||||
|
||||
class VerilatedDeserialize {
|
||||
class VerilatedDeserialize VL_NOT_FINAL {
|
||||
protected:
|
||||
// MEMBERS
|
||||
// For speed, keep m_cp as the first member of this structure
|
||||
@@ -98,8 +98,8 @@ protected:
|
||||
std::string m_filename; ///< Filename, for error messages
|
||||
VerilatedAssertOneThread m_assertOne; ///< Assert only called from single thread
|
||||
|
||||
inline static size_t bufferSize() { return 256 * 1024; } // See below for slack calculation
|
||||
inline static size_t bufferInsertSize() { return 16 * 1024; }
|
||||
static constexpr size_t bufferSize() { return 256 * 1024; } // See below for slack calculation
|
||||
static constexpr size_t bufferInsertSize() { return 16 * 1024; }
|
||||
|
||||
virtual void fill() = 0;
|
||||
void header() VL_MT_UNSAFE_ONE;
|
||||
@@ -154,13 +154,13 @@ private:
|
||||
// VerilatedSave - serialize to a file
|
||||
// This class is not thread safe, it must be called by a single thread
|
||||
|
||||
class VerilatedSave : public VerilatedSerialize {
|
||||
class VerilatedSave final : public VerilatedSerialize {
|
||||
private:
|
||||
int m_fd = -1; ///< File descriptor we're writing to
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
VerilatedSave() {}
|
||||
VerilatedSave() = default;
|
||||
virtual ~VerilatedSave() override { close(); }
|
||||
// METHODS
|
||||
/// Open the file; call isOpen() to see if errors
|
||||
@@ -174,13 +174,13 @@ public:
|
||||
// VerilatedRestore - deserialize from a file
|
||||
// This class is not thread safe, it must be called by a single thread
|
||||
|
||||
class VerilatedRestore : public VerilatedDeserialize {
|
||||
class VerilatedRestore final : public VerilatedDeserialize {
|
||||
private:
|
||||
int m_fd = -1; ///< File descriptor we're writing to
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
VerilatedRestore() {}
|
||||
VerilatedRestore() = default;
|
||||
virtual ~VerilatedRestore() override { close(); }
|
||||
|
||||
// METHODS
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2009-2020 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2009-2021 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -34,7 +34,7 @@
|
||||
// This class is thread safe (though most of SystemC is not).
|
||||
|
||||
#define VL_SC_BV_DATAP(bv) (VlScBvExposer::sp_datap(bv))
|
||||
class VlScBvExposer : public sc_bv_base {
|
||||
class VlScBvExposer final : public sc_bv_base {
|
||||
public:
|
||||
static const vluint32_t* sp_datap(const sc_bv_base& base) VL_MT_SAFE {
|
||||
return static_cast<const VlScBvExposer*>(&base)->sp_datatp();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2020 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2021 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -36,26 +36,24 @@
|
||||
/// Thread safety: Assume is constructed only with model, then any number of readers
|
||||
|
||||
// See also V3Ast::VNumRange
|
||||
class VerilatedRange {
|
||||
int m_left;
|
||||
int m_right;
|
||||
class VerilatedRange final {
|
||||
int m_left = 0;
|
||||
int m_right = 0;
|
||||
|
||||
protected:
|
||||
friend class VerilatedVarProps;
|
||||
friend class VerilatedScope;
|
||||
VerilatedRange()
|
||||
: m_left{0}
|
||||
, m_right{0} {}
|
||||
VerilatedRange(int left, int right)
|
||||
: m_left{left}
|
||||
, m_right{right} {}
|
||||
VerilatedRange() = default;
|
||||
void init(int left, int right) {
|
||||
m_left = left;
|
||||
m_right = right;
|
||||
}
|
||||
|
||||
public:
|
||||
~VerilatedRange() {}
|
||||
VerilatedRange(int left, int right)
|
||||
: m_left{left}
|
||||
, m_right{right} {}
|
||||
~VerilatedRange() = default;
|
||||
int left() const { return m_left; }
|
||||
int right() const { return m_right; }
|
||||
int low() const { return (m_left < m_right) ? m_left : m_right; }
|
||||
@@ -70,22 +68,22 @@ public:
|
||||
/// Verilator variable
|
||||
/// Thread safety: Assume is constructed only with model, then any number of readers
|
||||
|
||||
class VerilatedVarProps {
|
||||
class VerilatedVarProps VL_NOT_FINAL {
|
||||
// TYPES
|
||||
enum { MAGIC = 0xddc4f829 };
|
||||
// MEMBERS
|
||||
const vluint32_t m_magic; // Magic number
|
||||
const VerilatedVarType m_vltype; // Data type
|
||||
const VerilatedVarFlags m_vlflags; // Direction
|
||||
const int m_pdims; // Packed dimensions
|
||||
const int m_udims; // Unpacked dimensions
|
||||
const int m_pdims; // Packed dimensions, 0 = none
|
||||
const int m_udims; // Unpacked dimensions, 0 = none
|
||||
VerilatedRange m_packed; // Packed array range
|
||||
std::vector<VerilatedRange> m_unpacked; // Unpacked array ranges
|
||||
void initUnpacked(const int* ulims) {
|
||||
for (int i = 0; i < m_udims; ++i) {
|
||||
const int left = ulims ? ulims[2 * i + 0] : 0;
|
||||
const int right = ulims ? ulims[2 * i + 1] : 0;
|
||||
m_unpacked.push_back(VerilatedRange(left, right));
|
||||
const int uleft = ulims ? ulims[2 * i + 0] : 0;
|
||||
const int uright = ulims ? ulims[2 * i + 1] : 0;
|
||||
m_unpacked.emplace_back(uleft, uright);
|
||||
}
|
||||
}
|
||||
// CONSTRUCTORS
|
||||
@@ -138,7 +136,7 @@ public:
|
||||
}
|
||||
|
||||
public:
|
||||
~VerilatedVarProps() {}
|
||||
~VerilatedVarProps() = default;
|
||||
// METHODS
|
||||
bool magicOk() const { return m_magic == MAGIC; }
|
||||
VerilatedVarType vltype() const { return m_vltype; }
|
||||
@@ -189,7 +187,7 @@ public:
|
||||
//===========================================================================
|
||||
/// Verilator DPI open array variable
|
||||
|
||||
class VerilatedDpiOpenVar {
|
||||
class VerilatedDpiOpenVar final {
|
||||
// MEMBERS
|
||||
const VerilatedVarProps* m_propsp; // Variable properties
|
||||
void* m_datap; // Location of data (local to thread always, so safe)
|
||||
@@ -201,7 +199,7 @@ public:
|
||||
VerilatedDpiOpenVar(const VerilatedVarProps* propsp, const void* datap)
|
||||
: m_propsp{propsp}
|
||||
, m_datap{const_cast<void*>(datap)} {}
|
||||
~VerilatedDpiOpenVar() {}
|
||||
~VerilatedDpiOpenVar() = default;
|
||||
// METHODS
|
||||
void* datap() const { return m_datap; }
|
||||
// METHODS - from VerilatedVarProps
|
||||
@@ -227,7 +225,7 @@ public:
|
||||
/// Verilator variable
|
||||
/// Thread safety: Assume is constructed only with model, then any number of readers
|
||||
|
||||
class VerilatedVar : public VerilatedVarProps {
|
||||
class VerilatedVar final : public VerilatedVarProps {
|
||||
// MEMBERS
|
||||
void* m_datap; // Location of data
|
||||
const char* m_namep; // Name - slowpath
|
||||
@@ -243,7 +241,7 @@ protected:
|
||||
, m_isParam{isParam} {}
|
||||
|
||||
public:
|
||||
~VerilatedVar() {}
|
||||
~VerilatedVar() = default;
|
||||
// ACCESSORS
|
||||
void* datap() const { return m_datap; }
|
||||
const VerilatedRange& range() const { return packed(); } // Deprecated
|
||||
|
||||
+12
-10
@@ -1,7 +1,7 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2020 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2021 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "verilated_sym_props.h"
|
||||
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
//======================================================================
|
||||
@@ -42,26 +43,27 @@ struct VerilatedCStrCmp {
|
||||
};
|
||||
|
||||
/// Map of sorted scope names to find associated scope class
|
||||
class VerilatedScopeNameMap
|
||||
class VerilatedScopeNameMap final
|
||||
: public std::map<const char*, const VerilatedScope*, VerilatedCStrCmp> {
|
||||
public:
|
||||
VerilatedScopeNameMap() {}
|
||||
~VerilatedScopeNameMap() {}
|
||||
VerilatedScopeNameMap() = default;
|
||||
~VerilatedScopeNameMap() = default;
|
||||
};
|
||||
|
||||
/// Map of sorted variable names to find associated variable class
|
||||
class VerilatedVarNameMap : public std::map<const char*, VerilatedVar, VerilatedCStrCmp> {
|
||||
class VerilatedVarNameMap final : public std::map<const char*, VerilatedVar, VerilatedCStrCmp> {
|
||||
public:
|
||||
VerilatedVarNameMap() {}
|
||||
~VerilatedVarNameMap() {}
|
||||
VerilatedVarNameMap() = default;
|
||||
~VerilatedVarNameMap() = default;
|
||||
};
|
||||
|
||||
typedef std::vector<const VerilatedScope*> VerilatedScopeVector;
|
||||
|
||||
class VerilatedHierarchyMap : public std::map<const VerilatedScope*, VerilatedScopeVector> {
|
||||
class VerilatedHierarchyMap final
|
||||
: public std::unordered_map<const VerilatedScope*, VerilatedScopeVector> {
|
||||
public:
|
||||
VerilatedHierarchyMap() {}
|
||||
~VerilatedHierarchyMap() {}
|
||||
VerilatedHierarchyMap() = default;
|
||||
~VerilatedHierarchyMap() = default;
|
||||
};
|
||||
|
||||
#endif // Guard
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//=============================================================================
|
||||
//
|
||||
// Copyright 2012-2020 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2012-2021 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -98,10 +98,8 @@ VlThreadPool::VlThreadPool(int nThreads, bool profiling)
|
||||
}
|
||||
|
||||
VlThreadPool::~VlThreadPool() {
|
||||
for (int i = 0; i < m_workers.size(); ++i) {
|
||||
// Each ~WorkerThread will wait for its thread to exit.
|
||||
delete m_workers[i];
|
||||
}
|
||||
// Each ~WorkerThread will wait for its thread to exit.
|
||||
for (auto& i : m_workers) delete i;
|
||||
if (VL_UNLIKELY(m_profiling)) tearDownProfilingClientThread();
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
//
|
||||
// THIS MODULE IS PUBLICLY LICENSED
|
||||
//
|
||||
// Copyright 2012-2020 by Wilson Snyder. This program is free software; you
|
||||
// Copyright 2012-2021 by Wilson Snyder. This program is free software; you
|
||||
// can redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -52,7 +52,7 @@ typedef void* VlThrSymTab;
|
||||
typedef void (*VlExecFnp)(bool, VlThrSymTab);
|
||||
|
||||
/// Track dependencies for a single MTask.
|
||||
class VlMTaskVertex {
|
||||
class VlMTaskVertex final {
|
||||
// MEMBERS
|
||||
static std::atomic<vluint64_t> s_yields; // Statistics
|
||||
|
||||
@@ -82,7 +82,7 @@ public:
|
||||
// that must notify this MTaskVertex before it will become ready
|
||||
// to run.
|
||||
explicit VlMTaskVertex(vluint32_t upstreamDepCount);
|
||||
~VlMTaskVertex() {}
|
||||
~VlMTaskVertex() = default;
|
||||
|
||||
static vluint64_t yields() { return s_yields; }
|
||||
static void yieldThread() {
|
||||
@@ -124,7 +124,7 @@ public:
|
||||
};
|
||||
|
||||
// Profiling support
|
||||
class VlProfileRec {
|
||||
class VlProfileRec final {
|
||||
protected:
|
||||
friend class VlThreadPool;
|
||||
enum VlProfileE { TYPE_MTASK_RUN, TYPE_BARRIER };
|
||||
@@ -136,7 +136,7 @@ protected:
|
||||
unsigned m_cpu; // Execution CPU number (at start anyways)
|
||||
public:
|
||||
class Barrier {};
|
||||
VlProfileRec() {}
|
||||
VlProfileRec() = default;
|
||||
explicit VlProfileRec(Barrier) { m_cpu = getcpu(); }
|
||||
void startRecord(vluint64_t time, uint32_t mtask, uint32_t predict) {
|
||||
m_type = VlProfileRec::TYPE_MTASK_RUN;
|
||||
@@ -168,7 +168,7 @@ public:
|
||||
|
||||
class VlThreadPool;
|
||||
|
||||
class VlWorkerThread {
|
||||
class VlWorkerThread final {
|
||||
private:
|
||||
// TYPES
|
||||
struct ExecRec {
|
||||
@@ -247,7 +247,7 @@ public:
|
||||
static void startWorker(VlWorkerThread* workerp);
|
||||
};
|
||||
|
||||
class VlThreadPool {
|
||||
class VlThreadPool final {
|
||||
// TYPES
|
||||
typedef std::vector<VlProfileRec> ProfileTrace;
|
||||
typedef std::set<ProfileTrace*> ProfileSet;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
//
|
||||
// THIS MODULE IS PUBLICLY LICENSED
|
||||
//
|
||||
// Copyright 2001-2020 by Wilson Snyder. This program is free software; you
|
||||
// Copyright 2001-2021 by Wilson Snyder. This program is free software; you
|
||||
// can redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -40,7 +40,7 @@
|
||||
// Threaded tracing
|
||||
|
||||
// A simple synchronized first in first out queue
|
||||
template <class T> class VerilatedThreadQueue { // LCOV_EXCL_LINE // lcov bug
|
||||
template <class T> class VerilatedThreadQueue final { // LCOV_EXCL_LINE // lcov bug
|
||||
private:
|
||||
VerilatedMutex m_mutex; // Protects m_queue
|
||||
std::condition_variable_any m_cv;
|
||||
@@ -83,7 +83,7 @@ public:
|
||||
|
||||
// Commands used by thread tracing. Anonymous enum in class, as we want
|
||||
// it scoped, but we also want the automatic conversion to integer types.
|
||||
class VerilatedTraceCommand {
|
||||
class VerilatedTraceCommand final {
|
||||
public:
|
||||
// These must all fit in 4 bit at the moment, as the tracing routines
|
||||
// pack parameters in the top bits.
|
||||
@@ -110,7 +110,7 @@ public:
|
||||
// VerilatedTrace uses F-bounded polymorphism to access duck-typed
|
||||
// implementations in the format specific derived class, which must be passed
|
||||
// as the type parameter T_Derived
|
||||
template <class T_Derived> class VerilatedTrace {
|
||||
template <class T_Derived> class VerilatedTrace VL_NOT_FINAL {
|
||||
public:
|
||||
//=========================================================================
|
||||
// Generic tracing internals
|
||||
@@ -216,7 +216,6 @@ protected:
|
||||
double timeRes() const { return m_timeRes; }
|
||||
double timeUnit() const { return m_timeUnit; }
|
||||
std::string timeResStr() const;
|
||||
std::string timeUnitStr() const;
|
||||
|
||||
void traceInit() VL_MT_UNSAFE;
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
//
|
||||
// THIS MODULE IS PUBLICLY LICENSED
|
||||
//
|
||||
// Copyright 2001-2020 by Wilson Snyder. This program is free software; you
|
||||
// Copyright 2001-2021 by Wilson Snyder. This program is free software; you
|
||||
// can redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
// clang-format off
|
||||
|
||||
#ifndef VL_CPPCHECK
|
||||
#ifndef VL_DERIVED_T
|
||||
# error "This file should be included in trace format implementations"
|
||||
#endif
|
||||
@@ -46,7 +47,7 @@ static double timescaleToDouble(const char* unitp) {
|
||||
unitp = endp;
|
||||
for (; *unitp && isspace(*unitp); unitp++) {}
|
||||
switch (*unitp) {
|
||||
case 's': value *= 1e1; break;
|
||||
case 's': value *= 1e0; break;
|
||||
case 'm': value *= 1e-3; break;
|
||||
case 'u': value *= 1e-6; break;
|
||||
case 'n': value *= 1e-9; break;
|
||||
@@ -69,7 +70,7 @@ static std::string doubleToTimescale(double value) {
|
||||
else if (value >= 1e-18) { suffixp = "as"; value *= 1e18; }
|
||||
// clang-format on
|
||||
char valuestr[100];
|
||||
sprintf(valuestr, "%3.0f%s", value, suffixp);
|
||||
sprintf(valuestr, "%0.0f%s", value, suffixp);
|
||||
return valuestr; // Gets converted to string, so no ref to stack
|
||||
}
|
||||
|
||||
@@ -373,10 +374,6 @@ template <> std::string VerilatedTrace<VL_DERIVED_T>::timeResStr() const {
|
||||
return doubleToTimescale(m_timeRes);
|
||||
}
|
||||
|
||||
template <> std::string VerilatedTrace<VL_DERIVED_T>::timeUnitStr() const {
|
||||
return doubleToTimescale(m_timeUnit);
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
// External interface to client code
|
||||
|
||||
@@ -558,7 +555,7 @@ template <> void VerilatedTrace<VL_DERIVED_T>::fullDouble(vluint32_t* oldp, doub
|
||||
// All of these take a destination pointer where the string will be emitted,
|
||||
// and a value to convert. There are a couple of variants for efficiency.
|
||||
|
||||
inline static void cvtCDataToStr(char* dstp, CData value) {
|
||||
static inline void cvtCDataToStr(char* dstp, CData value) {
|
||||
#ifdef VL_HAVE_SSE2
|
||||
// Similar to cvtSDataToStr but only the bottom 8 byte lanes are used
|
||||
const __m128i a = _mm_cvtsi32_si128(value);
|
||||
@@ -580,7 +577,7 @@ inline static void cvtCDataToStr(char* dstp, CData value) {
|
||||
#endif
|
||||
}
|
||||
|
||||
inline static void cvtSDataToStr(char* dstp, SData value) {
|
||||
static inline void cvtSDataToStr(char* dstp, SData value) {
|
||||
#ifdef VL_HAVE_SSE2
|
||||
// We want each bit in the 16-bit input value to end up in a byte lane
|
||||
// within the 128-bit XMM register. Note that x86 is little-endian and we
|
||||
@@ -616,7 +613,7 @@ inline static void cvtSDataToStr(char* dstp, SData value) {
|
||||
#endif
|
||||
}
|
||||
|
||||
inline static void cvtIDataToStr(char* dstp, IData value) {
|
||||
static inline void cvtIDataToStr(char* dstp, IData value) {
|
||||
#ifdef VL_HAVE_AVX2
|
||||
// Similar to cvtSDataToStr but the bottom 16-bits are processed in the
|
||||
// top half of the YMM registerss
|
||||
@@ -635,9 +632,46 @@ inline static void cvtIDataToStr(char* dstp, IData value) {
|
||||
#endif
|
||||
}
|
||||
|
||||
inline static void cvtQDataToStr(char* dstp, QData value) {
|
||||
static inline void cvtQDataToStr(char* dstp, QData value) {
|
||||
cvtIDataToStr(dstp, value >> 32);
|
||||
cvtIDataToStr(dstp + 32, value);
|
||||
}
|
||||
|
||||
#define cvtEDataToStr cvtIDataToStr
|
||||
|
||||
//=============================================================================
|
||||
|
||||
#ifdef VERILATED_VCD_TEST
|
||||
|
||||
void verilated_trace_imp_selftest() {
|
||||
#define SELF_CHECK(got, exp) \
|
||||
do { \
|
||||
if ((got) != (exp)) VL_FATAL_MT(__FILE__, __LINE__, "", "%Error: selftest\n"); \
|
||||
} while (0)
|
||||
|
||||
#define SELF_CHECK_TS(scale) \
|
||||
SELF_CHECK(doubleToTimescale(timescaleToDouble(scale)), std::string{scale});
|
||||
SELF_CHECK_TS("1s");
|
||||
SELF_CHECK_TS("100ms");
|
||||
SELF_CHECK_TS("10ms");
|
||||
SELF_CHECK_TS("1ms");
|
||||
SELF_CHECK_TS("100us");
|
||||
SELF_CHECK_TS("10us");
|
||||
SELF_CHECK_TS("1us");
|
||||
SELF_CHECK_TS("100ns");
|
||||
SELF_CHECK_TS("10ns");
|
||||
SELF_CHECK_TS("1ns");
|
||||
SELF_CHECK_TS("100ps");
|
||||
SELF_CHECK_TS("10ps");
|
||||
SELF_CHECK_TS("1ps");
|
||||
SELF_CHECK_TS("100fs");
|
||||
SELF_CHECK_TS("10fs");
|
||||
SELF_CHECK_TS("1fs");
|
||||
SELF_CHECK_TS("100as");
|
||||
SELF_CHECK_TS("10as");
|
||||
SELF_CHECK_TS("1as");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif // VL_CPPCHECK
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
//
|
||||
// THIS MODULE IS PUBLICLY LICENSED
|
||||
//
|
||||
// Copyright 2001-2020 by Wilson Snyder. This program is free software; you
|
||||
// Copyright 2001-2021 by Wilson Snyder. This program is free software; you
|
||||
// can redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -198,7 +198,7 @@ void VerilatedVcd::makeNameMap() {
|
||||
std::string newname = std::string("top");
|
||||
if (hiername[0] != '\t') newname += ' ';
|
||||
newname += hiername;
|
||||
newmapp->insert(std::make_pair(newname, decl));
|
||||
newmapp->emplace(newname, decl);
|
||||
}
|
||||
deleteNameMap();
|
||||
m_namemapp = newmapp;
|
||||
@@ -511,7 +511,7 @@ void VerilatedVcd::declare(vluint32_t code, const char* name, const char* wirep,
|
||||
decl += buf;
|
||||
}
|
||||
decl += " $end\n";
|
||||
m_namemapp->insert(std::make_pair(hiername, decl));
|
||||
m_namemapp->emplace(hiername, decl);
|
||||
}
|
||||
|
||||
void VerilatedVcd::declBit(vluint32_t code, const char* name, bool array, int arraynum) {
|
||||
@@ -777,6 +777,8 @@ void VerilatedVcd::fullDouble(vluint32_t code, const double newval) {
|
||||
#ifdef VERILATED_VCD_TEST
|
||||
#include <iostream>
|
||||
|
||||
extern void verilated_trace_imp_selftest();
|
||||
|
||||
vluint32_t v1, v2, s1, s2[3];
|
||||
vluint32_t tri96[3];
|
||||
vluint32_t tri96__tri[3];
|
||||
@@ -843,6 +845,8 @@ void vcdChange(void*, VerilatedVcd* vcdp) {
|
||||
|
||||
// clang-format off
|
||||
void vcdTestMain(const char* filenamep) {
|
||||
verilated_trace_imp_selftest();
|
||||
|
||||
v1 = v2 = s1 = 0;
|
||||
s2[0] = s2[1] = s2[2] = 0;
|
||||
tri96[2] = tri96[1] = tri96[0] = 0;
|
||||
@@ -889,6 +893,7 @@ void vcdTestMain(const char* filenamep) {
|
||||
}
|
||||
# endif
|
||||
vcdp->close();
|
||||
VL_DO_CLEAR(delete vcdp, vcdp = nullptr);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
//
|
||||
// THIS MODULE IS PUBLICLY LICENSED
|
||||
//
|
||||
// Copyright 2001-2020 by Wilson Snyder. This program is free software; you
|
||||
// Copyright 2001-2021 by Wilson Snyder. This program is free software; you
|
||||
// can redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -34,13 +34,13 @@ class VerilatedVcd;
|
||||
// VerilatedFile
|
||||
/// File handling routines, which can be overrode for e.g. socket I/O
|
||||
|
||||
class VerilatedVcdFile {
|
||||
class VerilatedVcdFile VL_NOT_FINAL {
|
||||
private:
|
||||
int m_fd = 0; ///< File descriptor we're writing to
|
||||
public:
|
||||
// METHODS
|
||||
VerilatedVcdFile() {}
|
||||
virtual ~VerilatedVcdFile() {}
|
||||
VerilatedVcdFile() = default;
|
||||
virtual ~VerilatedVcdFile() = default;
|
||||
virtual bool open(const std::string& name) VL_MT_UNSAFE;
|
||||
virtual void close() VL_MT_UNSAFE;
|
||||
virtual ssize_t write(const char* bufp, ssize_t len) VL_MT_UNSAFE;
|
||||
@@ -51,7 +51,7 @@ public:
|
||||
/// Base class to create a Verilator VCD dump
|
||||
/// This is an internally used class - see VerilatedVcdC for what to call from applications
|
||||
|
||||
class VerilatedVcd : public VerilatedTrace<VerilatedVcd> {
|
||||
class VerilatedVcd VL_NOT_FINAL : public VerilatedTrace<VerilatedVcd> {
|
||||
private:
|
||||
// Give the superclass access to private bits (to avoid virtual functions)
|
||||
friend class VerilatedTrace<VerilatedVcd>;
|
||||
@@ -76,7 +76,7 @@ private:
|
||||
std::vector<char> m_suffixes; ///< VCD line end string codes + metadata
|
||||
const char* m_suffixesp; ///< Pointer to first element of above
|
||||
|
||||
typedef std::map<std::string, std::string> NameMap;
|
||||
typedef std::map<const std::string, const std::string> NameMap;
|
||||
NameMap* m_namemapp = nullptr; ///< List of names for the header
|
||||
|
||||
void bufferResize(vluint64_t minsize);
|
||||
@@ -329,7 +329,7 @@ template <> void VerilatedTrace<VerilatedVcd>::set_time_resolution(const std::st
|
||||
/// Also derived for use in SystemC simulations.
|
||||
/// Thread safety: Unless otherwise indicated, every function is VL_MT_UNSAFE_ONE
|
||||
|
||||
class VerilatedVcdC {
|
||||
class VerilatedVcdC VL_NOT_FINAL {
|
||||
VerilatedVcd m_sptrace; ///< Trace file being created
|
||||
|
||||
// CONSTRUCTORS
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
//
|
||||
// THIS MODULE IS PUBLICLY LICENSED
|
||||
//
|
||||
// Copyright 2001-2020 by Wilson Snyder. This program is free software; you
|
||||
// Copyright 2001-2021 by Wilson Snyder. This program is free software; you
|
||||
// can redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//=============================================================================
|
||||
//
|
||||
// Copyright 2001-2020 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2001-2021 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -31,7 +31,7 @@
|
||||
/// This class is passed to the SystemC simulation kernel, just like a
|
||||
/// documented SystemC trace format.
|
||||
|
||||
class VerilatedVcdSc : sc_trace_file, public VerilatedVcdC {
|
||||
class VerilatedVcdSc final : sc_trace_file, public VerilatedVcdC {
|
||||
// CONSTRUCTORS
|
||||
VL_UNCOPYABLE(VerilatedVcdSc);
|
||||
|
||||
|
||||
+374
-245
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2009-2020 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2009-2021 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -33,14 +33,14 @@
|
||||
|
||||
//======================================================================
|
||||
|
||||
class VerilatedVpi {
|
||||
class VerilatedVpi final {
|
||||
public:
|
||||
/// Call timed callbacks
|
||||
/// Users should call this from their main loops
|
||||
static void callTimedCbs() VL_MT_UNSAFE_ONE;
|
||||
/// Call value based callbacks
|
||||
/// Users should call this from their main loops
|
||||
static void callValueCbs() VL_MT_UNSAFE_ONE;
|
||||
static bool callValueCbs() VL_MT_UNSAFE_ONE;
|
||||
/// Call callbacks of arbitrary types
|
||||
/// Users can call this from their application code
|
||||
static bool callCbs(vluint32_t reason) VL_MT_UNSAFE_ONE;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2020 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2021 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -118,7 +118,7 @@
|
||||
# define VL_PREFETCH_RW(p) ///< Prefetch data with read/write intent
|
||||
#endif
|
||||
|
||||
#ifdef VL_THREADED
|
||||
#if defined(VL_THREADED) && !defined(VL_CPPCHECK)
|
||||
# if defined(_MSC_VER) && _MSC_VER >= 1900
|
||||
# define VL_THREAD_LOCAL thread_local
|
||||
# elif defined(__GNUC__)
|
||||
@@ -374,7 +374,10 @@ typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
|
||||
//=========================================================================
|
||||
// Class definition helpers
|
||||
|
||||
// Used to declare a class as uncopyable; put after a private:
|
||||
/// Used to indicate a base class, e.g. cannot label "class final"
|
||||
#define VL_NOT_FINAL
|
||||
|
||||
/// Used to declare a class as uncopyable; put after a private:
|
||||
#define VL_UNCOPYABLE(Type) \
|
||||
Type(const Type& other) = delete; \
|
||||
Type& operator=(const Type&) = delete
|
||||
@@ -447,7 +450,7 @@ typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
|
||||
# define NOMINMAX
|
||||
# include "Windows.h"
|
||||
# define VL_CPU_RELAX() YieldProcessor()
|
||||
# elif defined(__i386__) || defined(__x86_64__)
|
||||
# elif defined(__i386__) || defined(__x86_64__) || defined(VL_CPPCHECK)
|
||||
/// For more efficient busy waiting on SMT CPUs, let the processor know
|
||||
/// we're just waiting so it can let another thread run
|
||||
# define VL_CPU_RELAX() asm volatile("rep; nop" ::: "memory")
|
||||
|
||||
@@ -102,7 +102,7 @@ typedef uint32_t svBitVecVal;
|
||||
* Because the contents of the unused bits is undetermined,
|
||||
* the following macros can be handy.
|
||||
*/
|
||||
#define SV_MASK(N) (~(-1 << (N)))
|
||||
#define SV_MASK(N) (~(0xffffffffU << (N)))
|
||||
|
||||
#define SV_GET_UNSIGNED_BITS(VALUE, N) \
|
||||
((N) == 32 ? (VALUE) : ((VALUE) & SV_MASK(N)))
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
#!/usr/bin/env perl
|
||||
######################################################################
|
||||
#
|
||||
# Copyright 2007-2020 by Wilson Snyder. This program is free software; you
|
||||
# can redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
#
|
||||
######################################################################
|
||||
|
||||
# DESCRIPTION: Diff bison files
|
||||
|
||||
use warnings;
|
||||
use Getopt::Long;
|
||||
use IO::File;
|
||||
use strict;
|
||||
|
||||
our $Debug;
|
||||
our $Opt_Unsup;
|
||||
|
||||
if (! GetOptions (
|
||||
#"help" => \&usage,
|
||||
"debug" => sub { $Debug = 1; },
|
||||
"unsup!" => \$Opt_Unsup, # Ignore unsupported
|
||||
)) {
|
||||
die "usage();"
|
||||
}
|
||||
|
||||
diff($ARGV[0],$ARGV[1]);
|
||||
|
||||
sub diff {
|
||||
my $a=shift;
|
||||
my $b=shift;
|
||||
|
||||
my $ta = "/tmp/bisondiff.$$.a";
|
||||
my $tb = "/tmp/bisondiff.$$.b";
|
||||
|
||||
prep($a,$ta);
|
||||
prep($b,$tb);
|
||||
|
||||
system("diff -u -w $ta $tb");
|
||||
}
|
||||
|
||||
sub prep {
|
||||
my $filename = shift;
|
||||
my $wfilename = shift;
|
||||
|
||||
my $fh = IO::File->new("<$filename") or die "%Error: $! $filename";
|
||||
my $fho = IO::File->new(">$wfilename") or die "%Error: $! writing $wfilename";
|
||||
|
||||
my %declared;
|
||||
my %used;
|
||||
|
||||
my $body = 0;
|
||||
my $rule = "";
|
||||
my $skip = 1;
|
||||
while (defined(my $line = $fh->getline)) {
|
||||
if ($skip == 1) {
|
||||
next if $line !~ /%token/;
|
||||
$skip = 2;
|
||||
}
|
||||
|
||||
if ($Opt_Unsup) {
|
||||
$line =~ s!//UNSUP!|!g;
|
||||
$line =~ s!(\s+)\|(\s+)!$1$2!g; # As "UNSUP" often replaces "|"
|
||||
}
|
||||
|
||||
# %type<foo>
|
||||
$line =~ s/^(%\S+)<(\S+)>/$1/;
|
||||
# rule<foo>
|
||||
$line =~ s/^([a-zA-Z0-9_]+)<\S+>:/$1:/;
|
||||
# Productions
|
||||
$line =~ s/[ \t]{[^}]*?}/\t{}/g;
|
||||
|
||||
$fho->print($line);
|
||||
}
|
||||
}
|
||||
|
||||
# Local Variables:
|
||||
# compile-command: "./bisondiff --unsup $VP/Parser/VParseBison.y ../src/verilog.y"
|
||||
# End:
|
||||
+346
-457
@@ -1,509 +1,398 @@
|
||||
#!/usr/bin/env perl
|
||||
# See copyright, etc in below POD section.
|
||||
#!/usr/bin/env python3
|
||||
######################################################################
|
||||
|
||||
use warnings;
|
||||
use Cwd;
|
||||
use File::Copy qw(cp);
|
||||
use File::Path qw(mkpath);
|
||||
use File::Spec;
|
||||
use FindBin qw($RealBin);
|
||||
use Getopt::Long;
|
||||
use Parallel::Forker;
|
||||
use Unix::Processors;
|
||||
use IO::File;
|
||||
use Pod::Usage;
|
||||
use strict;
|
||||
use vars qw($Debug);
|
||||
import argparse
|
||||
import glob
|
||||
import multiprocessing
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
|
||||
our $Opt_Stop = 1;
|
||||
our $Opt_Fastcov = 1;
|
||||
our $Exclude_Branch_Regexp;
|
||||
our $Exclude_Line_Regexp;
|
||||
our $Remove_Gcda_Regexp;
|
||||
RealPath = os.path.dirname(os.path.realpath(__file__))
|
||||
Exclude_Branch_Regexps = []
|
||||
Exclude_Line_Regexps = []
|
||||
Remove_Gcda_Regexps = []
|
||||
Remove_Sources = []
|
||||
Source_Globs = []
|
||||
|
||||
our @Remove_Sources;
|
||||
our @Source_Globs;
|
||||
if 'VERILATOR_ROOT' not in os.environ:
|
||||
os.environ['VERILATOR_ROOT'] = os.getcwd()
|
||||
|
||||
our $Fork = new Parallel::Forker(use_sig_child => 1, poll_interval => 10*1000);
|
||||
$Fork->max_proc(Unix::Processors->new->max_online * 1.5);
|
||||
$SIG{CHLD} = sub { Parallel::Forker::sig_child($Fork); };
|
||||
$SIG{TERM} = sub { $Fork->kill_tree_all('TERM') if $Fork && $Fork->in_parent; die "Quitting...\n"; };
|
||||
######################################################################
|
||||
|
||||
#======================================================================
|
||||
# main
|
||||
|
||||
our $Opt_Hashset;
|
||||
our $opt_stages = '';
|
||||
our $Opt_Scenarios;
|
||||
our %Opt_Stages;
|
||||
our @Opt_Tests;
|
||||
def test():
|
||||
if not os.path.exists("nodist/code_coverage.dat"):
|
||||
sys.exit("%Error: Run code_coverage from the top of the verilator kit")
|
||||
exec(open("./nodist/code_coverage.dat").read())
|
||||
|
||||
autoflush STDOUT 1;
|
||||
autoflush STDERR 1;
|
||||
Getopt::Long::config("no_auto_abbrev");
|
||||
if (! GetOptions(
|
||||
"debug" => sub { $Debug = 1; },
|
||||
"hashset=s" => \$Opt_Hashset, # driver.pl hashset
|
||||
"<>" => sub { die "%Error: Unknown parameter: $_[0]\n"; },
|
||||
"fastcov!" => \$Opt_Fastcov, # use fastcov, not documented, for debug
|
||||
"scenarios=s" => \$Opt_Scenarios, # driver.pl scenarios
|
||||
"stage=s" => \$opt_stages, # starting stage number
|
||||
"stages=s" => \$opt_stages, # starting stage number
|
||||
"stop!" => \$Opt_Stop, # stop/do not stop on error in tests
|
||||
"test=s@" => \@Opt_Tests, # test name
|
||||
)) {
|
||||
die "%Error: Bad usage, try 'code_coverage --help'\n";
|
||||
}
|
||||
|
||||
{
|
||||
my $start = 0;
|
||||
my $end = 99;
|
||||
if ($opt_stages && $opt_stages =~ /^(\d+)$/) {
|
||||
$start = $end = $1;
|
||||
} elsif ($opt_stages && $opt_stages =~ /^(\d+)-(\d+$)$/) {
|
||||
$start = $1; $end = $2;
|
||||
} elsif ($opt_stages && $opt_stages =~ /^-(\d+$)$/) {
|
||||
$end = $1;
|
||||
} elsif ($opt_stages && $opt_stages =~ /^(\d+)-$/) {
|
||||
$start = $1;
|
||||
} elsif ($opt_stages) {
|
||||
die "%Error: --stages not understood: $opt_stages,";
|
||||
}
|
||||
for (my $n = $start; $n <= $end; ++$n) { $Opt_Stages{$n} = 1; }
|
||||
}
|
||||
|
||||
test();
|
||||
exit(0);
|
||||
|
||||
#######################################################################
|
||||
|
||||
sub test {
|
||||
-r "nodist/code_coverage.dat" or die "%Error: Run from the top of the verilator kit,";
|
||||
require "./nodist/code_coverage.dat";
|
||||
|
||||
if ($Opt_Stages{1}) {
|
||||
travis_fold_start("configure");
|
||||
print "Stage 1: configure (coverage on)\n";
|
||||
run("make distclean || true");
|
||||
run("autoconf");
|
||||
if Args.stage_enabled[1]:
|
||||
ci_fold_start("configure")
|
||||
print("Stage 1: configure (coverage on)")
|
||||
run("make distclean || true")
|
||||
run("autoconf")
|
||||
# Exceptions can pollute the branch coverage data
|
||||
run("./configure --enable-longtests CXX='g++ --coverage -fno-exceptions -DVL_GCOV'");
|
||||
travis_fold_end();
|
||||
}
|
||||
run("./configure --enable-longtests CXX='g++ --coverage -fno-exceptions -DVL_GCOV'"
|
||||
)
|
||||
ci_fold_end()
|
||||
|
||||
if ($Opt_Stages{2}) {
|
||||
travis_fold_start("build");
|
||||
print "Stage 2: build\n";
|
||||
my $nproc = Unix::Processors->new->max_online;
|
||||
run("make -k -j $nproc VERILATOR_NO_OPT_BUILD=1");
|
||||
if Args.stage_enabled[2]:
|
||||
ci_fold_start("build")
|
||||
print("Stage 2: build")
|
||||
nproc = multiprocessing.cpu_count()
|
||||
run("make -k -j " + str(nproc) + " VERILATOR_NO_OPT_BUILD=1")
|
||||
# The optimized versions will not collect good coverage, overwrite them
|
||||
run("cp bin/verilator_bin_dbg bin/verilator_bin");
|
||||
run("cp bin/verilator_coverage_bin_dbg bin/verilator_coverage_bin");
|
||||
travis_fold_end();
|
||||
}
|
||||
run("cp bin/verilator_bin_dbg bin/verilator_bin")
|
||||
run("cp bin/verilator_coverage_bin_dbg bin/verilator_coverage_bin")
|
||||
ci_fold_end()
|
||||
|
||||
if ($Opt_Stages{3}) {
|
||||
travis_fold_start("test");
|
||||
print "Stage 3: make tests (with coverage on)\n";
|
||||
if ($#Opt_Tests < 0) {
|
||||
run("make examples VERILATOR_NO_OPT_BUILD=1")
|
||||
if !$Opt_Scenarios || $Opt_Scenarios =~ /dist/i;
|
||||
run("make test_regress VERILATOR_NO_OPT_BUILD=1"
|
||||
. ($Opt_Scenarios ? " SCENARIOS='".$Opt_Scenarios."'" : "")
|
||||
. ($Opt_Hashset ? " DRIVER_HASHSET='--hashset=".$Opt_Hashset."'" : "")
|
||||
. ($Opt_Stop ? '' : ' || true'));
|
||||
} else {
|
||||
foreach my $test (@Opt_Tests) {
|
||||
if (! -f $test && -f "test_regress/t/${test}") {
|
||||
$test = "test_regress/t/${test}";
|
||||
}
|
||||
run($test);
|
||||
}
|
||||
}
|
||||
travis_fold_end();
|
||||
}
|
||||
if Args.stage_enabled[3]:
|
||||
ci_fold_start("test")
|
||||
print("Stage 3: make tests (with coverage on)")
|
||||
if not Args.tests:
|
||||
if not Args.scenarios or re.match('dist', Args.scenarios):
|
||||
run("make examples VERILATOR_NO_OPT_BUILD=1")
|
||||
run("make test_regress VERILATOR_NO_OPT_BUILD=1" +
|
||||
(" SCENARIOS='" + Args.scenarios +
|
||||
"'" if Args.scenarios else "") +
|
||||
(" DRIVER_HASHSET='--hashset=" + Args.hashset +
|
||||
"'" if Args.hashset else "") +
|
||||
('' if Args.stop else ' || true'))
|
||||
else:
|
||||
for test in Args.tests:
|
||||
if not os.path.exists(test) and os.path.exists(
|
||||
"test_regress/t/" + test):
|
||||
test = "test_regress/t/" + test
|
||||
run(test)
|
||||
ci_fold_end()
|
||||
|
||||
my $cc_dir = "nodist/obj_dir/coverage";
|
||||
if ($Opt_Stages{4}) {
|
||||
travis_fold_start("gcno");
|
||||
print "Stage 4: Create gcno files under $cc_dir\n";
|
||||
mkpath($cc_dir);
|
||||
mkpath("$cc_dir/info");
|
||||
my $dats = `find . -print | grep .gcda`;
|
||||
my %dats;
|
||||
foreach my $dat (split '\n', $dats) {
|
||||
$dats{$dat} = 1;
|
||||
}
|
||||
foreach my $dat (sort keys %dats) {
|
||||
(my $gcno = $dat) =~ s!\.gcda$!.gcno!;
|
||||
if ($dat =~ /$Remove_Gcda_Regexp/) {
|
||||
# Remove .gcda/.gcno for files we don't care about before we slowly
|
||||
# read them
|
||||
unlink $dat;
|
||||
unlink $gcno;
|
||||
delete $dats{$dat};
|
||||
next;
|
||||
}
|
||||
}
|
||||
$dats = `find . -print | grep .gcno`;
|
||||
my %gcnos;
|
||||
foreach my $gcno (split '\n', $dats) {
|
||||
(my $gbase = $gcno) =~ s!.*/!!;
|
||||
$gcnos{$gbase} = File::Spec->rel2abs($gcno);
|
||||
}
|
||||
cc_dir = "nodist/obj_dir/coverage"
|
||||
if Args.stage_enabled[4]:
|
||||
ci_fold_start("gcno")
|
||||
print("Stage 4: Create gcno files under " + cc_dir)
|
||||
os.makedirs(cc_dir, exist_ok=True)
|
||||
os.makedirs(cc_dir + "/info", exist_ok=True)
|
||||
|
||||
sp = subprocess.Popen("find . -print | grep .gcda",
|
||||
shell=True,
|
||||
stdout=subprocess.PIPE)
|
||||
datout = sp.stdout.read()
|
||||
dats = {}
|
||||
for dat in datout.splitlines():
|
||||
dat = dat.decode('utf-8')
|
||||
dats[dat] = 1
|
||||
for dat in sorted(dats.keys()):
|
||||
gcno = re.sub(r'\.gcda$', '.gcno', dat)
|
||||
for regexp in Remove_Gcda_Regexps:
|
||||
if re.search(regexp, dat):
|
||||
# Remove .gcda/.gcno for files we don't care about before we slowly
|
||||
# read them
|
||||
os.unlink(dat)
|
||||
os.unlink(gcno)
|
||||
del dats[dat]
|
||||
break
|
||||
|
||||
sp = subprocess.Popen("find . -print | grep .gcno",
|
||||
shell=True,
|
||||
stdout=subprocess.PIPE)
|
||||
datout = sp.stdout.read()
|
||||
gcnos = {}
|
||||
for gcno in datout.splitlines():
|
||||
gcno = gcno.decode('utf-8')
|
||||
gbase = re.sub(r'.*/', '', gcno, count=1)
|
||||
gcnos[gbase] = os.path.abspath(gcno)
|
||||
# We need a matching .gcno for every .gcda, try to find a matching file elsewhere
|
||||
foreach my $dat (sort keys %dats) {
|
||||
(my $gcno = $dat) =~ s!\.gcda$!.gcno!;
|
||||
(my $gbase = $gcno) =~ s!.*/!!;
|
||||
if (!-r $gcno) {
|
||||
if ($gcnos{$gbase}) {
|
||||
symlink($gcnos{$gbase}, $gcno)
|
||||
or die "%Error: can't ln -s $gcnos{$gbase} $gcno,";
|
||||
} else {
|
||||
warn "MISSING .gcno for a .gcda: $gcno\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
travis_fold_end();
|
||||
}
|
||||
for dat in sorted(dats):
|
||||
gcno = re.sub(r'\.gcda$', '.gcno', dat)
|
||||
gbase = re.sub(r'.*/', '', gcno, count=1)
|
||||
if not os.path.exists(gcno):
|
||||
if gbase in gcnos:
|
||||
os.symlink(gcnos[gbase], gcno)
|
||||
else:
|
||||
print("MISSING .gcno for a .gcda: " + gcno,
|
||||
file=sys.stderr)
|
||||
ci_fold_end()
|
||||
|
||||
if ($Opt_Stages{5} && $Opt_Fastcov) {
|
||||
travis_fold_start("fastcov");
|
||||
if Args.stage_enabled[5]:
|
||||
ci_fold_start("fastcov")
|
||||
# Must run in root directory to find all files
|
||||
mkpath($cc_dir);
|
||||
#run("${RealBin}/fastcov.py -b -c src/obj_dbg -X".
|
||||
# " --exclude /usr --exclude test_regress"
|
||||
# ." -o ${cc_dir}/app_total.json");
|
||||
run("${RealBin}/fastcov.py -b -c src/obj_dbg -X --lcov".
|
||||
" --exclude /usr --exclude test_regress"
|
||||
." -o ${cc_dir}/app_total.info");
|
||||
travis_fold_end();
|
||||
}
|
||||
os.makedirs(cc_dir, exist_ok=True)
|
||||
run(RealPath + "/fastcov.py -b -c src/obj_dbg -X --lcov" +
|
||||
" --exclude /usr --exclude test_regress" + " -o " + cc_dir +
|
||||
"/app_total.info")
|
||||
ci_fold_end()
|
||||
|
||||
if ($Opt_Stages{5} && !$Opt_Fastcov) {
|
||||
travis_fold_start("infos");
|
||||
print "Stage 5: make infos\n";
|
||||
my $dats = `find . -print | grep .gcda`;
|
||||
my %dirs;
|
||||
foreach my $dat (split '\n', $dats) {
|
||||
(my $dir = $dat) =~ s!/[^/]+$!!;
|
||||
$dirs{$dir} = 1;
|
||||
}
|
||||
|
||||
foreach my $dir (sort keys %dirs) {
|
||||
(my $outname = $dir) =~ s![^a-zA-Z0-9]+!_!g;
|
||||
$Fork->schedule(run_on_start => sub {
|
||||
# .info may be empty, so ignore errors (unfortunately)
|
||||
run("cd $cc_dir/info ; lcov -c -d ../../../../$dir --exclude /usr -o app_test_${outname}.info || true");
|
||||
})->run;
|
||||
}
|
||||
$Fork->wait_all;
|
||||
travis_fold_end();
|
||||
}
|
||||
|
||||
if ($Opt_Stages{6}) {
|
||||
travis_fold_start("clone");
|
||||
if Args.stage_enabled[6]:
|
||||
ci_fold_start("clone")
|
||||
# No control file to override single lines, so replicate the sources
|
||||
# Also lets us see the insertion markers in the HTML source res
|
||||
print "Stage 6: Clone sources under $cc_dir\n";
|
||||
clone_sources($cc_dir);
|
||||
travis_fold_end();
|
||||
}
|
||||
print("Stage 6: Clone sources under " + cc_dir)
|
||||
clone_sources(cc_dir)
|
||||
ci_fold_end()
|
||||
|
||||
if ($Opt_Stages{8} && !$Opt_Fastcov) {
|
||||
travis_fold_start("copy");
|
||||
print "Stage 8: Copy .gcno files\n";
|
||||
my $dats = `find . -print | grep .gcno`;
|
||||
foreach my $dat (sort (split '\n', $dats)) {
|
||||
next if $dat =~ /$cc_dir/;
|
||||
my $outdat = $cc_dir."/".$dat;
|
||||
#print "cp $dat, $outdat);\n";
|
||||
cp($dat, $outdat);
|
||||
}
|
||||
travis_fold_end();
|
||||
}
|
||||
if Args.stage_enabled[11]:
|
||||
ci_fold_start("dirs")
|
||||
print("Stage 11: Cleanup paths")
|
||||
cleanup_abs_paths_info(cc_dir, cc_dir + "/app_total.info",
|
||||
cc_dir + "/app_total.info")
|
||||
ci_fold_end()
|
||||
|
||||
if ($Opt_Stages{10} && !$Opt_Fastcov) {
|
||||
travis_fold_start("combine");
|
||||
print "Stage 10: Combine data files\n";
|
||||
{
|
||||
run("cd $cc_dir ; lcov -c -i -d src/obj_dbg -o app_base.info");
|
||||
run("cd $cc_dir ; lcov -a app_base.info -o app_total.info");
|
||||
my $infos = `cd $cc_dir ; find info -print | grep .info`;
|
||||
my $comb = "";
|
||||
my @infos = (sort (split /\n/, $infos));
|
||||
foreach my $info (@infos) {
|
||||
$comb .= " -a $info";
|
||||
# Need to batch them to avoid overrunning shell command length limit
|
||||
if (length($comb) > 10000 || $info eq $infos[$#infos]) {
|
||||
# .info may be empty, so ignore errors (unfortunately)
|
||||
run("cd $cc_dir ; lcov -a app_total.info $comb -o app_total.info || true");
|
||||
$comb = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
travis_fold_end();
|
||||
}
|
||||
|
||||
if ($Opt_Stages{11}) {
|
||||
travis_fold_start("dirs");
|
||||
print "Stage 11: Cleanup paths\n";
|
||||
if ($Opt_Fastcov) {
|
||||
cleanup_abs_paths_info($cc_dir, "$cc_dir/app_total.info", "$cc_dir/app_total.info");
|
||||
#cleanup_abs_paths_json($cc_dir, "$cc_dir/app_total.json", "$cc_dir/app_total.json");
|
||||
} else {
|
||||
cleanup_abs_paths_info($cc_dir, "$cc_dir/app_total.info", "$cc_dir/app_total.info");
|
||||
}
|
||||
travis_fold_end();
|
||||
}
|
||||
|
||||
if ($Opt_Stages{12}) {
|
||||
travis_fold_start("filter");
|
||||
print "Stage 12: Filter processed source files\n";
|
||||
my $inc = '';
|
||||
foreach my $glob (@Source_Globs) {
|
||||
foreach my $infile (glob $glob) {
|
||||
$inc .= " '$infile'";
|
||||
}
|
||||
}
|
||||
my $exc = '';
|
||||
foreach my $glob (@Remove_Sources) {
|
||||
if Args.stage_enabled[12]:
|
||||
ci_fold_start("filter")
|
||||
print("Stage 12: Filter processed source files")
|
||||
inc = ''
|
||||
for globf in Source_Globs:
|
||||
for infile in glob.glob(globf):
|
||||
inc += " '" + infile + "'"
|
||||
exc = ''
|
||||
for globf in Remove_Sources:
|
||||
# Fastcov does exact match not globbing at present
|
||||
# Lcov requires whole path match so needs the glob
|
||||
$glob =~ s!^\*!! if $Opt_Fastcov;
|
||||
$glob =~ s!\*$!! if $Opt_Fastcov;
|
||||
$exc .= " '$glob'";
|
||||
}
|
||||
if ($Opt_Fastcov) {
|
||||
$inc = "--include ".$inc if $inc ne '';
|
||||
$exc = "--exclude ".$exc if $exc ne '';
|
||||
run("cd $cc_dir ; ${RealBin}/fastcov.py -C app_total.info ${inc} ${exc} -x --lcov -o app_total_f.info");
|
||||
} else {
|
||||
run("cd $cc_dir ; lcov --remove app_total.info $exc -o app_total_f.info");
|
||||
}
|
||||
travis_fold_end();
|
||||
}
|
||||
globf = re.sub(r'^\*', '', globf)
|
||||
globf = re.sub(r'\*$', '', globf)
|
||||
exc += " '" + globf + "'"
|
||||
if inc != '':
|
||||
inc = "--include " + inc
|
||||
if exc != '':
|
||||
exc = "--exclude " + exc
|
||||
run("cd " + cc_dir + " ; " + RealPath +
|
||||
"/fastcov.py -C app_total.info " + inc + " " + exc +
|
||||
" -x --lcov -o app_total_f.info")
|
||||
ci_fold_end()
|
||||
|
||||
if ($Opt_Stages{17}) {
|
||||
travis_fold_start("report");
|
||||
print "Stage 17: Create HTML\n";
|
||||
run("cd $cc_dir ; genhtml app_total_f.info --demangle-cpp"
|
||||
." --rc lcov_branch_coverage=1 --rc genhtml_hi_limit=100 --output-directory html");
|
||||
travis_fold_end();
|
||||
}
|
||||
if Args.stage_enabled[17]:
|
||||
ci_fold_start("report")
|
||||
print("Stage 17: Create HTML")
|
||||
run("cd " + cc_dir + " ; genhtml app_total_f.info --demangle-cpp" +
|
||||
" --rc lcov_branch_coverage=1 --rc genhtml_hi_limit=100 --output-directory html"
|
||||
)
|
||||
ci_fold_end()
|
||||
|
||||
if ($Opt_Stages{18}) {
|
||||
travis_fold_start("upload");
|
||||
print "Stage 18: Upload\n";
|
||||
my $cmd = "bash <(curl -s https://codecov.io/bash) -f $cc_dir/app_total.info";
|
||||
print "print: Not running: export CODECOV_TOKEN=<hidden>\n";
|
||||
print "print: Not running: $cmd\n";
|
||||
travis_fold_end();
|
||||
}
|
||||
if Args.stage_enabled[18]:
|
||||
ci_fold_start("upload")
|
||||
print("Stage 18: Upload")
|
||||
cmd = "bash <(curl -s https://codecov.io/bash) -f " + cc_dir + "/app_total.info"
|
||||
print("print: Not running: export CODECOV_TOKEN=<hidden>")
|
||||
print("print: Not running: " + cmd)
|
||||
ci_fold_end()
|
||||
|
||||
if ($Opt_Stages{19}) {
|
||||
print "*-* All Finished *-*\n";
|
||||
print "\n";
|
||||
print "* See report in ${cc_dir}/html/index.html\n";
|
||||
print "* Remember to make distclean && ./configure before working on non-coverage\n";
|
||||
}
|
||||
}
|
||||
if Args.stage_enabled[19]:
|
||||
print("*-* All Finished *-*")
|
||||
print("")
|
||||
print("* See report in " + cc_dir + "/html/index.html")
|
||||
print(
|
||||
"* Remember to make distclean && ./configure before working on non-coverage"
|
||||
)
|
||||
|
||||
sub clone_sources {
|
||||
my $cc_dir = shift;
|
||||
my $excluded_lines = 0;
|
||||
my $excluded_br_lines = 0;
|
||||
foreach my $glob (@Source_Globs) {
|
||||
foreach my $infile (glob $glob) {
|
||||
$infile !~ m!^/!
|
||||
or die "%Error: source globs should be relative not absolute filenames,";
|
||||
my $outfile = $cc_dir."/".$infile;
|
||||
(my $outpath = $outfile) =~ s!/[^/]*$!!;
|
||||
mkpath($outpath);
|
||||
my $fh = IO::File->new("<$infile") or die "%Error: $! $infile,";
|
||||
my $ofh = IO::File->new(">$outfile") or die "%Error: $! $outfile,";
|
||||
my $lineno = 0;
|
||||
while (defined(my $line = $fh->getline)) {
|
||||
$lineno++;
|
||||
chomp $line;
|
||||
if ($line =~ /LCOV_EXCL_LINE/) {
|
||||
$line .= " LCOV_EXCL_BR_LINE";
|
||||
}
|
||||
elsif ($line =~ /LCOV_EXCL_START/) {
|
||||
$line .= " LCOV_EXCL_BR_START";
|
||||
}
|
||||
elsif ($line =~ /LCOV_EXCL_STOP/) {
|
||||
$line .= " LCOV_EXCL_BR_STOP";
|
||||
}
|
||||
elsif ($line =~ /$Exclude_Line_Regexp/) {
|
||||
$line .= " //code_coverage: // LCOV_EXCL_LINE LCOV_EXCL_BR_LINE";
|
||||
$excluded_lines++;
|
||||
$excluded_br_lines++;
|
||||
#print "$infile:$lineno: $line";
|
||||
}
|
||||
elsif ($line =~ /$Exclude_Branch_Regexp/) {
|
||||
$line .= " //code_coverage: // LCOV_EXCL_BR_LINE";
|
||||
$excluded_br_lines++;
|
||||
#print "$infile:$lineno: $line";
|
||||
}
|
||||
$ofh->print("$line\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
print "Number of source lines automatically LCOV_EXCL_LINE'ed: $excluded_lines\n";
|
||||
print "Number of source lines automatically LCOV_EXCL_BR_LINE'ed: $excluded_br_lines\n";
|
||||
}
|
||||
|
||||
sub cleanup_abs_paths_info {
|
||||
my $cc_dir = shift;
|
||||
my $infile = shift;
|
||||
my $outfile = shift;
|
||||
my $fh = IO::File->new("<$infile") or die "%Error: $! $infile,";
|
||||
my @lines;
|
||||
while (defined(my $line = $fh->getline)) {
|
||||
if ($line =~ m!^SF:!) {
|
||||
$line =~ s!$ENV{VERILATOR_ROOT}/!!;
|
||||
$line =~ s!$cc_dir/!!;
|
||||
$line =~ s!obj_dbg/verilog.y$!verilog.y!;
|
||||
#print "Remaining SF: ",$line;
|
||||
}
|
||||
push @lines, $line;
|
||||
}
|
||||
my $ofh = IO::File->new(">$outfile") or die "%Error: $! $outfile,";
|
||||
$ofh->print(@lines);
|
||||
}
|
||||
def clone_sources(cc_dir):
|
||||
excluded_lines = 0
|
||||
excluded_br_lines = 0
|
||||
for globf in Source_Globs:
|
||||
for infile in glob.glob(globf):
|
||||
if re.match(r'^/', infile):
|
||||
sys.exit(
|
||||
"%Error: source globs should be relative not absolute filenames, "
|
||||
+ infile)
|
||||
outfile = cc_dir + "/" + infile
|
||||
outpath = re.sub(r'/[^/]*$', '', outfile, count=1)
|
||||
os.makedirs(outpath, exist_ok=True)
|
||||
with open(infile) as fh:
|
||||
with open(outfile, "w") as ofh:
|
||||
lineno = 0
|
||||
for line in fh:
|
||||
lineno += 1
|
||||
line = line.rstrip()
|
||||
done = False
|
||||
if re.search(r'LCOV_EXCL_LINE', line):
|
||||
line += " LCOV_EXCL_BR_LINE"
|
||||
done = True
|
||||
elif re.search(r'LCOV_EXCL_START', line):
|
||||
line += " LCOV_EXCL_BR_START"
|
||||
done = True
|
||||
elif re.search(r'LCOV_EXCL_STOP', line):
|
||||
line += " LCOV_EXCL_BR_STOP"
|
||||
done = True
|
||||
|
||||
sub cleanup_abs_paths_json {
|
||||
my $cc_dir = shift;
|
||||
my $infile = shift;
|
||||
my $outfile = shift;
|
||||
# Handcrafted cleanup, alternative would be to deserialize/serialize JSON
|
||||
# But JSON::Parse not installed by default
|
||||
# JSON::PP more likely to be installed, but slower
|
||||
my $fh = IO::File->new("<$infile") or die "%Error: $! $infile,";
|
||||
my @lines;
|
||||
while (defined(my $line = $fh->getline)) {
|
||||
$line =~ s!"$ENV{VERILATOR_ROOT}/!"!g;
|
||||
$line =~ s!"$cc_dir/!"!g;
|
||||
$line =~ s!obj_dbg/verilog.y$!verilog.y!g;
|
||||
push @lines, $line;
|
||||
}
|
||||
my $ofh = IO::File->new(">$outfile") or die "%Error: $! $outfile,";
|
||||
$ofh->print(@lines);
|
||||
}
|
||||
for regexp in Exclude_Line_Regexps:
|
||||
if done:
|
||||
break
|
||||
if re.search(regexp, line):
|
||||
#print("%s:%d: %s" % (infile, lineno, line)
|
||||
line += " //code_coverage: // LCOV_EXCL_LINE LCOV_EXCL_BR_LINE"
|
||||
excluded_lines += 1
|
||||
excluded_br_lines += 1
|
||||
done = True
|
||||
|
||||
#######################################################################
|
||||
for regexp in Exclude_Branch_Regexps:
|
||||
if done:
|
||||
break
|
||||
if re.search(regexp, line):
|
||||
#print("%s:%d: %s" % (infile, lineno, line)
|
||||
line += " //code_coverage: // LCOV_EXCL_BR_LINE"
|
||||
excluded_br_lines += 1
|
||||
done = True
|
||||
|
||||
ofh.write(line + "\n")
|
||||
print("Number of source lines automatically LCOV_EXCL_LINE'ed: %d" %
|
||||
excluded_lines)
|
||||
print("Number of source lines automatically LCOV_EXCL_BR_LINE'ed: %d" %
|
||||
excluded_br_lines)
|
||||
|
||||
|
||||
def cleanup_abs_paths_info(cc_dir, infile, outfile):
|
||||
lines = []
|
||||
with open(infile) as fh:
|
||||
for line in fh:
|
||||
if re.search(r'^SF:', line):
|
||||
line = re.sub(os.environ['VERILATOR_ROOT'] + '/',
|
||||
'',
|
||||
line,
|
||||
count=1)
|
||||
line = re.sub(cc_dir + '/', '', line, count=1)
|
||||
line = re.sub(r'obj_dbg/verilog.y$', 'verilog.y', line)
|
||||
#print("Remaining SF: "+line)
|
||||
lines.append(line)
|
||||
|
||||
with open(outfile, "w") as ofh:
|
||||
for line in lines:
|
||||
ofh.write(line)
|
||||
|
||||
|
||||
def cleanup_abs_paths_json(cc_dir, infile, outfile):
|
||||
# Handcrafted cleanup, alternative would be to deserialize/serialize JSON,
|
||||
# but this is much faster
|
||||
lines = []
|
||||
with open(infile) as fh:
|
||||
for line in fh:
|
||||
line = re.sub('"' + os.environ['VERILATOR_ROOT'] + '/', '"', line)
|
||||
line = re.sub('"' + cc_dir + '/', '"', line)
|
||||
line = re.sub(r'obj_dbg/verilog.y$', 'verilog.y', line)
|
||||
lines.append(line)
|
||||
|
||||
with open(outfile, "w") as ofh:
|
||||
for line in lines:
|
||||
ofh.write(line)
|
||||
|
||||
|
||||
######################################################################
|
||||
# .dat file callbacks
|
||||
|
||||
sub exclude_branch_regexp {
|
||||
$Exclude_Branch_Regexp = shift;
|
||||
}
|
||||
sub exclude_line_regexp {
|
||||
$Exclude_Line_Regexp = shift;
|
||||
}
|
||||
sub remove_gcda_regexp {
|
||||
$Remove_Gcda_Regexp = shift;
|
||||
}
|
||||
sub remove_source {
|
||||
my @srcs = @_;
|
||||
push @Remove_Sources, @srcs;
|
||||
}
|
||||
sub source_globs {
|
||||
my @dirs = @_;
|
||||
push @Source_Globs, @dirs;
|
||||
}
|
||||
|
||||
def exclude_branch_regexp(*regexps):
|
||||
Exclude_Branch_Regexps.extend(regexps)
|
||||
|
||||
|
||||
def exclude_line_regexp(*regexps):
|
||||
Exclude_Line_Regexps.extend(regexps)
|
||||
|
||||
|
||||
def remove_gcda_regexp(*regexps):
|
||||
Remove_Gcda_Regexps.extend(regexps)
|
||||
|
||||
|
||||
def remove_source(*sources):
|
||||
Remove_Sources.extend(sources)
|
||||
|
||||
|
||||
def source_globs(*dirs):
|
||||
Source_Globs.extend(dirs)
|
||||
|
||||
|
||||
#######################################################################
|
||||
|
||||
sub run {
|
||||
# Run a system command, check errors
|
||||
my $command = shift;
|
||||
print "\t$command\n";
|
||||
system "$command";
|
||||
my $status = $?;
|
||||
($status == 0) or die "%Error: Command Failed $command, $status, stopped";
|
||||
}
|
||||
|
||||
our $_Travis_Action;
|
||||
sub travis_fold_start {
|
||||
$_Travis_Action = shift;
|
||||
print "travis_fold:start:$_Travis_Action\n";
|
||||
}
|
||||
sub travis_fold_end {
|
||||
print "travis_fold:end:$_Travis_Action\n";
|
||||
}
|
||||
def run(command):
|
||||
# run a system command, check errors
|
||||
print("\t%s" % command)
|
||||
os.system(command)
|
||||
status = subprocess.call(command, shell=True)
|
||||
if status < 0:
|
||||
raise Exception("%Error: Command failed " + command + ", stopped")
|
||||
|
||||
|
||||
def ci_fold_start(action):
|
||||
print("::group::" + action)
|
||||
|
||||
|
||||
def ci_fold_end():
|
||||
print("::endgroup::\n")
|
||||
|
||||
|
||||
#######################################################################
|
||||
__END__
|
||||
#######################################################################
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
code_coverage - Build and collect Verilator coverage
|
||||
|
||||
=head1 SYNOPSIS
|
||||
parser = argparse.ArgumentParser(
|
||||
allow_abbrev=False,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
description=
|
||||
"""code_coverage builds Verilator with C++ coverage support and runs
|
||||
tests with coverage enabled. This will rebuild the current object
|
||||
files. Run as:
|
||||
|
||||
cd $VERILATOR_ROOT
|
||||
nodist/code_coverage
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
code_coverage builds Verilator with C++ coverage support and runs tests
|
||||
with coverage enabled.
|
||||
|
||||
This will rebuild the current object files.
|
||||
|
||||
=head1 ARGUMENTS
|
||||
|
||||
=over 4
|
||||
|
||||
=item --hashset I<hashset>
|
||||
|
||||
Pass test hashset onto driver.pl test harness.
|
||||
|
||||
=item --help
|
||||
|
||||
Displays this message and program version and exits.
|
||||
|
||||
=item --scenarios I<scenarios>
|
||||
|
||||
Pass test scenarios onto driver.pl test harness.
|
||||
|
||||
=item --stages I<stage>
|
||||
|
||||
Runs a specific stage or range of stages (see the script).
|
||||
|
||||
=item --no-stop
|
||||
|
||||
Do not stop collecting data if tests fail.
|
||||
|
||||
=item --test I<test_regress_test_name>
|
||||
|
||||
Instead of normal regressions, run the specified test. May be specified
|
||||
multiple times for multiple tests.
|
||||
|
||||
=back
|
||||
|
||||
=head1 DISTRIBUTION
|
||||
|
||||
Copyright 2019-2020 by Wilson Snyder. This program is free software; you
|
||||
nodist/code_coverage""",
|
||||
epilog=
|
||||
"""Copyright 2019-2021 by Wilson Snyder. This program is free software; you
|
||||
can redistribute it and/or modify it under the terms of either the GNU
|
||||
Lesser General Public License Version 3 or the Perl Artistic License
|
||||
Version 2.0.
|
||||
|
||||
SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0""")
|
||||
|
||||
=head1 AUTHORS
|
||||
parser.add_argument('--debug', action='store_true', help='enable debug')
|
||||
parser.add_argument('--hashset',
|
||||
action='store',
|
||||
help='pass test hashset onto driver.pl test harness')
|
||||
parser.add_argument('--scenarios',
|
||||
action='store',
|
||||
help='pass test scenarios onto driver.pl test harness')
|
||||
parser.add_argument(
|
||||
'--stages',
|
||||
action='store',
|
||||
help='runs a specific stage or range of stages (see the script)')
|
||||
parser.add_argument(
|
||||
'--test',
|
||||
action='append',
|
||||
dest='tests',
|
||||
default=[],
|
||||
help=
|
||||
'Instead of normal regressions, run the specified test(s), may be used multiple times'
|
||||
)
|
||||
parser.add_argument('--no-stop',
|
||||
dest='stop',
|
||||
action='store_false',
|
||||
help='do not stop collecting data if tests fail')
|
||||
|
||||
Wilson Snyder <[email protected]>
|
||||
parser.set_defaults(stop=True)
|
||||
Args = parser.parse_args()
|
||||
|
||||
=head1 SEE ALSO
|
||||
if True:
|
||||
start = 0
|
||||
end = 99
|
||||
Args.stage_enabled = {}
|
||||
if Args.stages:
|
||||
match_one = re.match(r'^(\d+)$', Args.stages)
|
||||
match_range = re.match(r'^(\d+)-(\d+)$', Args.stages)
|
||||
match_to = re.match(r'^-(\d+)$', Args.stages)
|
||||
match_from = re.match(r'^(\d+)-$', Args.stages)
|
||||
if match_one:
|
||||
start = end = int(match_one.group(1))
|
||||
elif match_range:
|
||||
start = int(match_range.group(1))
|
||||
end = int(match_range.group(2))
|
||||
elif match_to:
|
||||
end = int(match_to.group(1))
|
||||
elif match_from:
|
||||
start = int(match_from.group(1))
|
||||
else:
|
||||
os.exit("%Error: --stages not understood: " + Args.stages)
|
||||
for n in range(1, 100):
|
||||
Args.stage_enabled[n] = False
|
||||
for n in range(start, end + 1):
|
||||
Args.stage_enabled[n] = True
|
||||
|
||||
C<lcov>
|
||||
|
||||
=cut
|
||||
test()
|
||||
|
||||
######################################################################
|
||||
### Local Variables:
|
||||
|
||||
+43
-43
@@ -1,62 +1,62 @@
|
||||
# -*- Perl -*-
|
||||
# -*- Python -*-
|
||||
# DESCRIPTION: Verilator: Internal C++ code lcov control file
|
||||
#
|
||||
# Copyright 2019-2020 by Wilson Snyder. This program is free software; you
|
||||
# Copyright 2019-2021 by Wilson Snyder. This program is free software; you
|
||||
# can redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
source_globs("src/*.cpp",
|
||||
"src/*.h",
|
||||
"src/*.l",
|
||||
"src/*.y",
|
||||
"src/obj_dbg/*.h",
|
||||
"src/obj_dbg/*.cpp",
|
||||
"include/*.c",
|
||||
"include/*.cpp",
|
||||
"include/*.h",
|
||||
"include/*/*.h",
|
||||
"include/*/*.cpp",
|
||||
"include/*/*.c",
|
||||
);
|
||||
source_globs("src/*.cpp")
|
||||
source_globs("src/*.h")
|
||||
source_globs("src/*.l")
|
||||
source_globs("src/*.y")
|
||||
source_globs("src/obj_dbg/*.h")
|
||||
source_globs("src/obj_dbg/*.cpp")
|
||||
source_globs("include/*.c")
|
||||
source_globs("include/*.cpp")
|
||||
source_globs("include/*.h")
|
||||
source_globs("include/*/*.h")
|
||||
source_globs("include/*/*.cpp")
|
||||
source_globs("include/*/*.c")
|
||||
|
||||
# Note *'s are removed when using fastcov
|
||||
remove_source("/usr/*");
|
||||
remove_source("*/include/sysc/*");
|
||||
remove_source("*/V3ClkGater.cpp");
|
||||
remove_source("*/V3ClkGater.h");
|
||||
remove_source("*/V3GraphDfa.cpp");
|
||||
remove_source("*/V3GraphDfa.h");
|
||||
remove_source("*/V3Lexer_pregen.yy.cpp");
|
||||
remove_source("*/V3PreLex_pregen.yy.cpp");
|
||||
remove_source("*/verilog.c");
|
||||
remove_source("*include/gtkwave/*");
|
||||
remove_source("/usr/*")
|
||||
remove_source("*/include/sysc/*")
|
||||
remove_source("*/V3ClkGater.cpp")
|
||||
remove_source("*/V3ClkGater.h")
|
||||
remove_source("*/V3GraphDfa.cpp")
|
||||
remove_source("*/V3GraphDfa.h")
|
||||
remove_source("*/V3Lexer_pregen.yy.cpp")
|
||||
remove_source("*/V3PreLex_pregen.yy.cpp")
|
||||
remove_source("*/verilog.c")
|
||||
remove_source("*include/gtkwave/*")
|
||||
# Something wrong in generation, unfortunately as would like this
|
||||
#genhtml: ERROR: cannot read /svaha/wsnyder/SandBox/homecvs/v4/verilator/src/obj_dbg/verilog.y
|
||||
#remove_source("*/src/obj_dbg/verilog.y");
|
||||
remove_source("*test_regress/*");
|
||||
remove_source("*examples/*");
|
||||
#remove_source("*/src/obj_dbg/verilog.y")
|
||||
remove_source("*test_regress/*")
|
||||
remove_source("*examples/*")
|
||||
|
||||
# Remove collected coverage on each little test main file
|
||||
# Would just be removed with remove_source in later step
|
||||
remove_gcda_regexp(qr!test_regress/.*/(Vt_|Vtop_).*\.gcda!);
|
||||
remove_gcda_regexp(r'test_regress/.*/(Vt_|Vtop_).*\.gcda')
|
||||
|
||||
# Exclude line entirely, also excludes from function and branch coverage
|
||||
exclude_line_regexp(qr/(\bv3fatalSrc\b
|
||||
|\bfatalSrc\b
|
||||
|\bVL_UNCOVERABLE\b
|
||||
|\bVL_UNREACHABLE\b
|
||||
|\bVL_FATAL
|
||||
|\bUASSERT
|
||||
|\bNUM_ASSERT
|
||||
|\bERROR_RSVD_WORD
|
||||
|\bV3ERROR_NA
|
||||
|\bUINFO\b)/x);
|
||||
exclude_line_regexp(r'\bv3fatalSrc\b')
|
||||
exclude_line_regexp(r'\bfatalSrc\b')
|
||||
exclude_line_regexp(r'\bVL_UNCOVERABLE\b')
|
||||
exclude_line_regexp(r'\bVL_UNREACHABLE\b')
|
||||
exclude_line_regexp(r'\bVL_FATAL')
|
||||
exclude_line_regexp(r'\bUASSERT')
|
||||
exclude_line_regexp(r'\bNUM_ASSERT')
|
||||
exclude_line_regexp(r'\bERROR_RSVD_WORD')
|
||||
exclude_line_regexp(r'\bV3ERROR_NA')
|
||||
exclude_line_regexp(r'\bUINFO\b')
|
||||
|
||||
# Exclude for branch coverage only
|
||||
exclude_branch_regexp(qr/(\bdebug\(\)
|
||||
|\bassert\(
|
||||
|\bSELF_CHECK)/x);
|
||||
exclude_branch_regexp(r'\bdebug\(\)')
|
||||
exclude_branch_regexp(r'\bassert\(')
|
||||
exclude_branch_regexp(r'\bBROKEN_RTK\(')
|
||||
exclude_branch_regexp(r'\bSELF_CHECK')
|
||||
|
||||
1;
|
||||
True
|
||||
|
||||
+92
-147
@@ -1,164 +1,109 @@
|
||||
#!/usr/bin/env perl
|
||||
# See copyright, etc in below POD section.
|
||||
#!/usr/bin/env python3
|
||||
######################################################################
|
||||
|
||||
use warnings;
|
||||
use Getopt::Long;
|
||||
use IO::File;
|
||||
use Pod::Usage;
|
||||
use Data::Dumper; $Data::Dumper::Indent=1;
|
||||
use strict;
|
||||
use vars qw($Debug);
|
||||
import argparse
|
||||
import re
|
||||
|
||||
#======================================================================
|
||||
######################################################################
|
||||
|
||||
our @Header;
|
||||
our %Vertexes;
|
||||
our @Edges;
|
||||
our %Edges;
|
||||
Header = []
|
||||
Vertexes = []
|
||||
Edges = []
|
||||
|
||||
#======================================================================
|
||||
#######################################################################
|
||||
|
||||
|
||||
def dotread(filename):
|
||||
with open(filename) as fh:
|
||||
header = True
|
||||
vnum = 0
|
||||
|
||||
vertex_re = re.compile(r'^\t([a-zA-Z0-9_]+)\t(.*)$')
|
||||
edge_re = re.compile(
|
||||
r'^\t([a-zA-Z0-9_]+)\s+->\s+([a-zA-Z0-9_]+)\s*(.*)$')
|
||||
|
||||
for line in fh:
|
||||
vertex_match = re.search(vertex_re, line)
|
||||
edge_match = re.search(edge_re, line)
|
||||
if vertex_match:
|
||||
if vertex_match.group(1) != 'nTITLE':
|
||||
header = False
|
||||
Vertexes.append({
|
||||
'num': vnum,
|
||||
'line': line,
|
||||
'name': vertex_match.group(1)
|
||||
})
|
||||
vnum += 1
|
||||
elif edge_match:
|
||||
fromv = edge_match.group(1)
|
||||
tov = edge_match.group(2)
|
||||
w = re.match(r'weight=(\d+)', line)
|
||||
weight = w.group(1) if w else 1
|
||||
w = re.match(r'style=(\S+)', line)
|
||||
cutable = w.group(1) if w else None
|
||||
edge = {
|
||||
'num': vnum,
|
||||
'line': line,
|
||||
'weight': weight,
|
||||
'cutable': cutable,
|
||||
'from': fromv,
|
||||
'to': tov
|
||||
}
|
||||
vnum += 1
|
||||
Edges.append(edge)
|
||||
elif header:
|
||||
Header.append(line)
|
||||
print("IGNORE: " + line)
|
||||
|
||||
|
||||
#######################################################################
|
||||
|
||||
|
||||
def cwrite(filename):
|
||||
with open(filename, "w") as fh:
|
||||
fh.write("void V3GraphTestImport::dotImport() {\n")
|
||||
fh.write(" auto* gp = &m_graph;\n")
|
||||
for ver in sorted(Vertexes, key=lambda ver: ver['num']):
|
||||
fh.write(
|
||||
" auto* %s = new V3GraphTestVertex(gp, \"%s\"); if (%s) {}\n"
|
||||
% (ver['name'], ver['name'], ver['name']))
|
||||
fh.write("\n")
|
||||
for edge in Edges:
|
||||
fh.write(" new V3GraphEdge(gp, %s, %s, %s, %s);\n" %
|
||||
(edge['from'], edge['to'], edge['weight'],
|
||||
"true" if edge['cutable'] else "false"))
|
||||
fh.write("}\n")
|
||||
|
||||
|
||||
######################################################################
|
||||
# main
|
||||
|
||||
$Debug = 0;
|
||||
my $opt_filename;
|
||||
autoflush STDOUT 1;
|
||||
autoflush STDERR 1;
|
||||
if (! GetOptions(
|
||||
"help" => \&usage,
|
||||
"debug" => \&debug,
|
||||
"<>" => \¶meter,
|
||||
)) {
|
||||
usage();
|
||||
}
|
||||
|
||||
dotread($opt_filename);
|
||||
cwrite("graph_export.cpp");
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
sub usage {
|
||||
pod2usage(-verbose=>2, -exitval=>0, -output=>\*STDOUT);
|
||||
exit(1); # Unreachable
|
||||
}
|
||||
|
||||
sub debug {
|
||||
$Debug = 1;
|
||||
}
|
||||
|
||||
sub parameter {
|
||||
my $param = shift;
|
||||
if (!$opt_filename) {
|
||||
$opt_filename = $param;
|
||||
} else {
|
||||
die "%Error: Unknown parameter: $param\n";
|
||||
}
|
||||
}
|
||||
|
||||
#######################################################################
|
||||
|
||||
sub dotread {
|
||||
my $filename = shift;
|
||||
|
||||
my $fh = IO::File->new($filename) or die "%Error: $! $filename,";
|
||||
my $header = 1;
|
||||
my $vnum = 0;
|
||||
while (defined (my $line = $fh->getline)) {
|
||||
if ($line =~ /^\t([a-zA-Z0-9_]+)\t(.*)$/) {
|
||||
next if $1 eq 'nTITLE';
|
||||
$header = 0;
|
||||
$Vertexes{$1} = {num => $vnum++,
|
||||
line => $line,
|
||||
name => $1,};
|
||||
}
|
||||
elsif ($line =~ /^\t([a-zA-Z0-9_]+)\s+->\s+([a-zA-Z0-9_]+)\s+(.*)$/) {
|
||||
my $from=$1; my $to=$2;
|
||||
my $weight = 1; $weight = $1 if $line =~ /weight=(\d+)/;
|
||||
my $cutable = undef; $cutable = $1 if $line =~ /style=(\S+)/;
|
||||
my $edge = {num => $vnum++,
|
||||
line => $line,
|
||||
weight => $weight,
|
||||
cutable => $cutable,
|
||||
from => $from,
|
||||
to => $to,};
|
||||
push @Edges, $edge;
|
||||
$Edges{$from}{$to} = $edge;
|
||||
}
|
||||
elsif ($header) {
|
||||
push @Header, $line;
|
||||
print "IGNORE: $line";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#######################################################################
|
||||
|
||||
sub cwrite {
|
||||
my $filename = shift;
|
||||
|
||||
my $fh = IO::File->new(">$filename") or die "%Error: $! $filename,";
|
||||
$fh->print("void V3GraphTestImport::dotImport() {\n");
|
||||
$fh->print(" DfaGraph* gp = &m_graph;\n");
|
||||
foreach my $ver (sort {$a->{num} <=> $b->{num}} (values %Vertexes)) {
|
||||
$fh->printf(" V3GraphTestVertex* %s = new V3GraphTestVertex(gp, \"%s\"); if (%s) {}\n",
|
||||
$ver->{name}, $ver->{name}, $ver->{name});
|
||||
}
|
||||
$fh->print("\n");
|
||||
foreach my $edge (@Edges) {
|
||||
$fh->printf(" new V3GraphEdge(gp, %s, %s, %s, %s);\n",
|
||||
$edge->{from}, $edge->{to},
|
||||
$edge->{weight}, $edge->{cutable}?"true":"false");
|
||||
}
|
||||
$fh->print("}\n");
|
||||
}
|
||||
|
||||
#######################################################################
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
dot_importer - Take graph .dot file and convert into .cpp file
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
dot_importer a.dot
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Dot_importer takes a graphvis .dot file and converts into .cpp file. This
|
||||
.cpp file is then manually included in V3GraphTest.cpp to verify various
|
||||
sub-algorithms.
|
||||
|
||||
=head1 ARGUMENTS
|
||||
|
||||
=over 4
|
||||
|
||||
=item --help
|
||||
|
||||
Displays this message and program version and exits.
|
||||
|
||||
=back
|
||||
|
||||
=head1 DISTRIBUTION
|
||||
|
||||
Copyright 2005-2020 by Wilson Snyder. This program is free software; you
|
||||
parser = argparse.ArgumentParser(
|
||||
allow_abbrev=False,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
description=
|
||||
"""dot_importer takes a graphvis .dot file and converts into .cpp file.
|
||||
This x.cpp file is then manually included in V3GraphTest.cpp to verify
|
||||
various xsub-algorithms.""",
|
||||
epilog=
|
||||
"""Copyright 2005-2021 by Wilson Snyder. This program is free software; you
|
||||
can redistribute it and/or modify it under the terms of either the GNU
|
||||
Lesser General Public License Version 3 or the Perl Artistic License
|
||||
Version 2.0.
|
||||
|
||||
SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0""")
|
||||
|
||||
=head1 AUTHORS
|
||||
parser.add_argument('--debug',
|
||||
action='store_const',
|
||||
const=9,
|
||||
help='enable debug')
|
||||
parser.add_argument('filename', help='input .dot filename to process')
|
||||
|
||||
Wilson Snyder <[email protected]>
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
=cut
|
||||
Args = parser.parse_args()
|
||||
dotread(Args.filename)
|
||||
cwrite("graph_export.cpp")
|
||||
|
||||
######################################################################
|
||||
### Local Variables:
|
||||
### compile-command: "./dot_importer | tee ~/d/a.dot"
|
||||
### compile-command: "./dot_importer ../test_regress/obj_vlt/t_EXAMPLE/*orderg_o*.dot && cat graph_export.cpp"
|
||||
### End:
|
||||
|
||||
@@ -1,205 +0,0 @@
|
||||
#!/usr/bin/env perl
|
||||
# See copyright, etc in below POD section.
|
||||
######################################################################
|
||||
|
||||
use warnings;
|
||||
use Getopt::Long;
|
||||
use IO::File;
|
||||
use Pod::Usage;
|
||||
use Data::Dumper; $Data::Dumper::Indent=1;
|
||||
use strict;
|
||||
use vars qw($Debug);
|
||||
|
||||
#======================================================================
|
||||
|
||||
our @Header;
|
||||
our %Vertexes;
|
||||
our %Edges;
|
||||
our %User;
|
||||
our %User2;
|
||||
|
||||
#======================================================================
|
||||
# main
|
||||
|
||||
$Debug = 0;
|
||||
my $opt_filename;
|
||||
my $opt_circle;
|
||||
autoflush STDOUT 1;
|
||||
autoflush STDERR 1;
|
||||
if (! GetOptions(
|
||||
"help" => \&usage,
|
||||
"debug" => \&debug,
|
||||
"<>" => \¶meter,
|
||||
"circle=s" => \$opt_circle,
|
||||
)) {
|
||||
usage();
|
||||
}
|
||||
|
||||
dotread($opt_filename);
|
||||
circle($opt_circle) if $opt_circle;
|
||||
simplify();
|
||||
dotwrite();
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
sub usage {
|
||||
pod2usage(-verbose=>2, -exitval=>0, -output=>\*STDOUT);
|
||||
exit(1); # Unreachable
|
||||
}
|
||||
|
||||
sub debug {
|
||||
$Debug = 1;
|
||||
}
|
||||
|
||||
sub parameter {
|
||||
my $param = shift;
|
||||
if (!$opt_filename) {
|
||||
$opt_filename = $param;
|
||||
} else {
|
||||
die "%Error: Unknown parameter: $param\n";
|
||||
}
|
||||
}
|
||||
|
||||
#######################################################################
|
||||
|
||||
sub dotread {
|
||||
my $filename = shift;
|
||||
|
||||
my $fh = IO::File->new($filename) or die "%Error: $! $filename,";
|
||||
my $header = 1;
|
||||
while (defined (my $line = $fh->getline)) {
|
||||
if ($line =~ /^\t([a-zA-Z0-9_]+)\t(.*)$/) {
|
||||
$header = 0;
|
||||
$Vertexes{$1} = $2;
|
||||
}
|
||||
elsif ($line =~ /^\t([a-zA-Z0-9_]+)\s+->\s+([a-zA-Z0-9_]+)\s+(.*)$/) {
|
||||
$Edges{$1}{$2} = $3;
|
||||
}
|
||||
elsif ($header) {
|
||||
push @Header, $line;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
######################################################################
|
||||
|
||||
sub simplify {
|
||||
foreach my $ver (sort (keys %Vertexes)) {
|
||||
$Vertexes{$ver} = _simplify($Vertexes{$ver});
|
||||
}
|
||||
foreach my $v1 (sort (keys %Edges)) {
|
||||
foreach my $v2 (sort (keys %{$Edges{$v1}})) {
|
||||
$Edges{$v1}{$v2} = _simplify($Edges{$v1}{$v2});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub _simplify {
|
||||
my $text = shift;
|
||||
$text =~ s/__DOT__/./g;
|
||||
return $text;
|
||||
}
|
||||
|
||||
|
||||
sub dotwrite {
|
||||
foreach my $line (@Header) {
|
||||
print "$line";
|
||||
}
|
||||
foreach my $ver (sort (keys %Vertexes)) {
|
||||
print "\t$ver\t$Vertexes{$ver}\n";
|
||||
}
|
||||
foreach my $v1 (sort (keys %Edges)) {
|
||||
foreach my $v2 (sort (keys %{$Edges{$v1}})) {
|
||||
print "\t$v1 -> $v2\t$Edges{$v1}{$v2}\n";
|
||||
}
|
||||
}
|
||||
print "}\n";
|
||||
}
|
||||
|
||||
######################################################################
|
||||
|
||||
sub circle {
|
||||
my $node = shift;
|
||||
%User = ();
|
||||
%User2 = ();
|
||||
_circle_recurse($node, 1);
|
||||
|
||||
foreach my $ver (keys %Vertexes) {
|
||||
if (!$User{$ver}) {
|
||||
delete $Vertexes{$ver};
|
||||
delete $Edges{$ver};
|
||||
}
|
||||
}
|
||||
foreach my $v1 (sort (keys %Edges)) {
|
||||
foreach my $v2 (sort (keys %{$Edges{$v1}})) {
|
||||
if (!$Vertexes{$v2}) { delete $Edges{$v1}{$v2}; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub _circle_recurse {
|
||||
my $node = $_[0];
|
||||
my $level = $_[1];
|
||||
$Vertexes{$node} or warn "%Warning: Can't find ref node $node\n";
|
||||
|
||||
$User{$node} = 1 if (($User2{$node}||0)==1);
|
||||
return $User{$node} if $User2{$node};
|
||||
|
||||
$User2{$node} = 1;
|
||||
my $r = 0;
|
||||
foreach my $v2 (keys %{$Edges{$node}}) {
|
||||
$r |= _circle_recurse($v2,$level++)||0;
|
||||
}
|
||||
$User{$node} = 1 if $r;
|
||||
$User2{$node} = 2;
|
||||
return $r;
|
||||
}
|
||||
|
||||
#######################################################################
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
dot_pruner -
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
dot_pruner *.log
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
dd
|
||||
|
||||
=head1 ARGUMENTS
|
||||
|
||||
=over 4
|
||||
|
||||
=item --help
|
||||
|
||||
Displays this message and program version and exits.
|
||||
|
||||
=back
|
||||
|
||||
=head1 DISTRIBUTION
|
||||
|
||||
Copyright 2005-2020 by Wilson Snyder. This program is free software; you
|
||||
can redistribute it and/or modify it under the terms of either the GNU
|
||||
Lesser General Public License Version 3 or the Perl Artistic License
|
||||
Version 2.0.
|
||||
|
||||
SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
Wilson Snyder <[email protected]>
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
=cut
|
||||
|
||||
######################################################################
|
||||
### Local Variables:
|
||||
### compile-command: "./dot_pruner | tee ~/d/a.dot"
|
||||
### End:
|
||||
@@ -1,61 +0,0 @@
|
||||
#!/usr/bin/env perl
|
||||
######################################################################
|
||||
#
|
||||
# Copyright 2007-2020 by Wilson Snyder. This program is free software; you
|
||||
# can redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
#
|
||||
######################################################################
|
||||
|
||||
# DESCRIPTION: Diff flex files
|
||||
|
||||
use warnings;
|
||||
use IO::File;
|
||||
use strict;
|
||||
|
||||
my $Debug;
|
||||
|
||||
diff($ARGV[0],$ARGV[1]);
|
||||
|
||||
sub diff {
|
||||
my $a=shift;
|
||||
my $b=shift;
|
||||
|
||||
my $ta = "/tmp/flexdiff.$$.a";
|
||||
my $tb = "/tmp/flexdiff.$$.b";
|
||||
|
||||
prep($a,$ta);
|
||||
prep($b,$tb);
|
||||
|
||||
system("diff -u -w $ta $tb");
|
||||
}
|
||||
|
||||
sub prep {
|
||||
my $filename = shift;
|
||||
my $wfilename = shift;
|
||||
|
||||
my $fh = IO::File->new("<$filename") or die "%Error: $! $filename";
|
||||
my $fho = IO::File->new(">$wfilename") or die "%Error: $! writing $wfilename";
|
||||
|
||||
my %declared;
|
||||
my %used;
|
||||
my @lines;
|
||||
|
||||
while (defined(my $line = $fh->getline)) {
|
||||
# Productions
|
||||
#$line =~ s/[ \t]{[^}]*?}/\t{}/g;
|
||||
$line =~ s/StashPrefix;//g;
|
||||
$line =~ s/VALTEXT;//g;
|
||||
$line =~ s/CALLBACK\([^)]*\);//g;
|
||||
push @lines, $line;
|
||||
}
|
||||
|
||||
#@lines = sort @lines;
|
||||
$fho->print(@lines);
|
||||
}
|
||||
|
||||
# Local Variables:
|
||||
# compile-command: "./flexdiff $VP/Parser/VParseLex.l ../src/verilog.l"
|
||||
# End:
|
||||
@@ -16,6 +16,7 @@ from glob import glob
|
||||
from subprocess import getstatusoutput
|
||||
from argparse import ArgumentParser
|
||||
|
||||
|
||||
def interesting(s):
|
||||
if 'assert' in s: return 1
|
||||
if 'Assert' in s: return 1
|
||||
@@ -33,17 +34,19 @@ def interesting(s):
|
||||
|
||||
def main():
|
||||
p = ArgumentParser()
|
||||
p.add_argument('--dir',default='out1/queue')
|
||||
p.add_argument('--dir', default='out1/queue')
|
||||
args = p.parse_args()
|
||||
|
||||
for infile in glob(args.dir+'/*'):
|
||||
for infile in glob(args.dir + '/*'):
|
||||
# Input filenames are known not to contain spaces or other unusual
|
||||
# characters, therefore this works.
|
||||
status,output = getstatusoutput('../../bin/verilator_bin --cc '+infile)
|
||||
status, output = getstatusoutput('../../bin/verilator_bin --cc ' +
|
||||
infile)
|
||||
if interesting(output):
|
||||
print(infile)
|
||||
print(status)
|
||||
print(output)
|
||||
|
||||
if __name__=='__main__':
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
@@ -15,7 +15,8 @@
|
||||
from subprocess import getstatusoutput
|
||||
from os import system
|
||||
|
||||
def take_while(f,a):
|
||||
|
||||
def take_while(f, a):
|
||||
# any(a) => (a->bool)->[a]->[a]
|
||||
# Does the same think as Haskell's takewhile.
|
||||
out = []
|
||||
@@ -26,44 +27,50 @@ def take_while(f,a):
|
||||
return out
|
||||
return out
|
||||
|
||||
def skip_while(f,a):
|
||||
|
||||
def skip_while(f, a):
|
||||
# any(a) => (a->bool)->[a]->[a]
|
||||
# Basically, the opposite thing from skipwhile
|
||||
while len(a) and f(a[0]):
|
||||
a = a[1:]
|
||||
return a
|
||||
|
||||
|
||||
def print_lines(a):
|
||||
# printable(a) => [a]->void
|
||||
for elem in a:
|
||||
print(elem)
|
||||
|
||||
def write_file(filename,contents):
|
||||
|
||||
def write_file(filename, contents):
|
||||
# str->str->void
|
||||
f = open(filename,'w')
|
||||
f = open(filename, 'w')
|
||||
f.write(contents)
|
||||
|
||||
|
||||
def parse_line(s):
|
||||
# str->maybe str
|
||||
if len(s)==0: return
|
||||
part = skip_while(lambda x: x!='"',s)
|
||||
if len(part)==0 or part[0]!='"': return None
|
||||
literal_part = take_while(lambda x: x!='"',part[1:])
|
||||
return ''.join(filter(lambda x: x!='\\',literal_part))
|
||||
if len(s) == 0: return
|
||||
part = skip_while(lambda x: x != '"', s)
|
||||
if len(part) == 0 or part[0] != '"': return None
|
||||
literal_part = take_while(lambda x: x != '"', part[1:])
|
||||
return ''.join(filter(lambda x: x != '\\', literal_part))
|
||||
|
||||
|
||||
def main():
|
||||
status,output = getstatusoutput('flex -T ../../src/verilog.l')
|
||||
assert status==0
|
||||
status, output = getstatusoutput('flex -T ../../src/verilog.l')
|
||||
assert status == 0
|
||||
|
||||
lines = output.splitlines()
|
||||
lines = take_while(lambda x: 'beginning dump of nfa' not in x,lines)
|
||||
tokens = set(filter(lambda x: x,map(parse_line,lines)))
|
||||
lines = take_while(lambda x: 'beginning dump of nfa' not in x, lines)
|
||||
tokens = set(filter(lambda x: x, map(parse_line, lines)))
|
||||
|
||||
dirname = 'dictionary'
|
||||
r = system('mkdir -p '+dirname)
|
||||
assert(r==0)
|
||||
for i,token in enumerate(tokens):
|
||||
write_file(dirname+'/'+str(i),token)
|
||||
r = system('mkdir -p ' + dirname)
|
||||
assert (r == 0)
|
||||
for i, token in enumerate(tokens):
|
||||
write_file(dirname + '/' + str(i), token)
|
||||
|
||||
if __name__=='__main__':
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
+111
-182
@@ -1,211 +1,140 @@
|
||||
#!/usr/bin/env perl
|
||||
# See copyright, etc in below POD section.
|
||||
#!/usr/bin/env python3
|
||||
######################################################################
|
||||
|
||||
use warnings;
|
||||
use Getopt::Long;
|
||||
use Cwd;
|
||||
use IO::File;
|
||||
use Pod::Usage;
|
||||
use strict;
|
||||
use vars qw($Debug);
|
||||
import argparse
|
||||
import multiprocessing
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
|
||||
#======================================================================
|
||||
# main
|
||||
######################################################################
|
||||
|
||||
our $Opt_Stage = 0;
|
||||
our $Opt_Jobs = calc_jobs();
|
||||
|
||||
autoflush STDOUT 1;
|
||||
autoflush STDERR 1;
|
||||
Getopt::Long::config("no_auto_abbrev");
|
||||
if (! GetOptions(
|
||||
"debug" => sub { $Debug = 1; },
|
||||
"<>" => sub { die "%Error: Unknown parameter: $_[0]\n"; },
|
||||
"stage=i" => \$Opt_Stage,
|
||||
"j=i" => \$Opt_Jobs,
|
||||
)) {
|
||||
die "%Error: Bad usage, try 'install_test --help'\n";
|
||||
}
|
||||
def test():
|
||||
if not os.path.exists("nodist/install_test"):
|
||||
sys.exit("%Error: Run from the top of the verilator kit")
|
||||
|
||||
test();
|
||||
exit(0);
|
||||
|
||||
#######################################################################
|
||||
|
||||
sub test {
|
||||
-r "nodist/install_test" or die "%Error: Run from the top of the verilator kit,";
|
||||
|
||||
cleanenv();
|
||||
run("make distclean") if -r "Makefile";
|
||||
cleanenv()
|
||||
if os.path.exists("Makefile"):
|
||||
run("make distclean")
|
||||
|
||||
# Try building from a scratch area
|
||||
my $srcdir = getcwd();
|
||||
my $blddir = $srcdir."/test_regress/obj_dir/install_test_bld";
|
||||
my $prefix = $srcdir."/test_regress/obj_dir/install_test_prefix";
|
||||
my $testdirp= $srcdir."/test_regress/obj_dir/install_test_testp";
|
||||
my $testdirn= $srcdir."/test_regress/obj_dir/install_test_testn";
|
||||
srcdir = os.getcwd()
|
||||
blddir = srcdir + "/test_regress/obj_dir/install_test_bld"
|
||||
prefix = srcdir + "/test_regress/obj_dir/install_test_prefix"
|
||||
testdirp = srcdir + "/test_regress/obj_dir/install_test_testp"
|
||||
testdirn = srcdir + "/test_regress/obj_dir/install_test_testn"
|
||||
|
||||
if ($Opt_Stage <= 0) {
|
||||
run("/bin/rm -rf $blddir");
|
||||
run("/bin/mkdir -p $blddir");
|
||||
run("cd $blddir && $srcdir/configure --prefix $prefix");
|
||||
run("cd $blddir && make -j $Opt_Jobs");
|
||||
}
|
||||
if Args.stage <= 0:
|
||||
print("== stage 0")
|
||||
run("/bin/rm -rf " + blddir)
|
||||
run("/bin/mkdir -p " + blddir)
|
||||
run("cd " + blddir + " && " + srcdir + "/configure --prefix " + prefix)
|
||||
run("cd " + blddir + " && make -j " + str(calc_jobs()))
|
||||
|
||||
# Install it under the prefix
|
||||
if ($Opt_Stage <= 1) {
|
||||
run("/bin/rm -rf $prefix");
|
||||
run("/bin/mkdir -p $prefix");
|
||||
run("cd $blddir && make install");
|
||||
run("test -e $prefix/share/man/man1/verilator.1");
|
||||
run("test -e $prefix/share/verilator/examples/make_tracing_c/Makefile");
|
||||
run("test -e $prefix/share/verilator/include/verilated.h");
|
||||
run("test -e $prefix/bin/verilator");
|
||||
run("test -e $prefix/bin/verilator_bin");
|
||||
run("test -e $prefix/bin/verilator_bin_dbg");
|
||||
run("test -e $prefix/bin/verilator_gantt");
|
||||
run("test -e $prefix/bin/verilator_profcfunc");
|
||||
}
|
||||
if Args.stage <= 1:
|
||||
print("== stage 1")
|
||||
run("/bin/rm -rf " + prefix)
|
||||
run("/bin/mkdir -p " + prefix)
|
||||
run("cd " + blddir + " && make install")
|
||||
run("test -e " + prefix + "/share/man/man1/verilator.1")
|
||||
run("test -e " + prefix +
|
||||
"/share/verilator/examples/make_tracing_c/Makefile")
|
||||
run("test -e " + prefix + "/share/verilator/include/verilated.h")
|
||||
run("test -e " + prefix + "/bin/verilator")
|
||||
run("test -e " + prefix + "/bin/verilator_bin")
|
||||
run("test -e " + prefix + "/bin/verilator_bin_dbg")
|
||||
run("test -e " + prefix + "/bin/verilator_gantt")
|
||||
run("test -e " + prefix + "/bin/verilator_profcfunc")
|
||||
|
||||
# Run a test using just the path
|
||||
if ($Opt_Stage <= 2) {
|
||||
my $dir = $testdirp;
|
||||
run("/bin/rm -rf $dir");
|
||||
run("/bin/mkdir -p $dir");
|
||||
my $bin1 = $prefix."/bin";
|
||||
my $bin2 = $prefix."/share/bin";
|
||||
write_verilog($dir);
|
||||
run("cd $dir && PATH=$bin1:$bin2:\$PATH verilator --cc foo.v --exe foo.cpp");
|
||||
run("cd $dir/obj_dir && PATH=$bin1:$bin2:\$PATH make -f Vfoo.mk");
|
||||
run("cd $dir && PATH=$bin1:$bin2:\$PATH obj_dir/Vfoo");
|
||||
}
|
||||
# run a test using just the path
|
||||
if Args.stage <= 2:
|
||||
print("== stage 2")
|
||||
dir = testdirp
|
||||
run("/bin/rm -rf " + dir)
|
||||
run("/bin/mkdir -p " + dir)
|
||||
path = prefix + "/bin" + ":" + prefix + "/share/bin"
|
||||
write_verilog(dir)
|
||||
run("cd " + dir + " && PATH=" + path +
|
||||
":$PATH verilator --cc top.v --exe sim_main.cpp")
|
||||
run("cd " + dir + "/obj_dir && PATH=" + path +
|
||||
":$PATH make -f Vtop.mk")
|
||||
run("cd " + dir + " && PATH=" + path + ":$PATH obj_dir/Vtop")
|
||||
|
||||
# Run a test using exact path to binary
|
||||
if ($Opt_Stage <= 3) {
|
||||
my $dir = $testdirn;
|
||||
run("/bin/rm -rf $dir");
|
||||
run("/bin/mkdir -p $dir");
|
||||
write_verilog($dir);
|
||||
my $bin1 = $prefix."/bin";
|
||||
my $bin2 = $prefix."/share/bin";
|
||||
run("cd $dir && $bin1/verilator --cc foo.v --exe foo.cpp");
|
||||
run("cd $dir/obj_dir && make -f Vfoo.mk");
|
||||
run("cd $dir/obj_dir && ./Vfoo");
|
||||
}
|
||||
# run a test using exact path to binary
|
||||
if Args.stage <= 3:
|
||||
print("== stage 3")
|
||||
dir = testdirn
|
||||
run("/bin/rm -rf " + dir)
|
||||
run("/bin/mkdir -p " + dir)
|
||||
write_verilog(dir)
|
||||
bin1 = prefix + "/bin"
|
||||
run("cd " + dir + " && " + bin1 +
|
||||
"/verilator --cc top.v --exe sim_main.cpp")
|
||||
run("cd " + dir + "/obj_dir && make -f Vtop.mk")
|
||||
run("cd " + dir + "/obj_dir && ./Vtop")
|
||||
|
||||
if ($Opt_Stage <= 9) {
|
||||
print "*-* All Finished *-*\n";
|
||||
}
|
||||
}
|
||||
if Args.stage <= 9:
|
||||
print("*-* All Finished *-*")
|
||||
|
||||
sub write_verilog {
|
||||
my $dir = shift;
|
||||
IO::File->new(">$dir/foo.v")->print('module t; initial begin $display("HELLO WORLD"); $finish; end endmodule'."\n");
|
||||
my $fh = IO::File->new(">$dir/foo.cpp");
|
||||
$fh->print('#include "Vfoo.h"' ,"\n");
|
||||
$fh->print('unsigned int main_time = 0;' ,"\n");
|
||||
$fh->print('double sc_time_stamp() {' ,"\n");
|
||||
$fh->print(' return main_time;' ,"\n");
|
||||
$fh->print('}' ,"\n");
|
||||
$fh->print('int main() {' ,"\n");
|
||||
$fh->print(' Vfoo *top = new Vfoo;' ,"\n");
|
||||
$fh->print(' while (!Verilated::gotFinish()) {',"\n");
|
||||
$fh->print(' top->eval();' ,"\n");
|
||||
$fh->print(' main_time++;' ,"\n");
|
||||
$fh->print(' }' ,"\n");
|
||||
$fh->print(' top->final();' ,"\n");
|
||||
$fh->print('}' ,"\n");
|
||||
}
|
||||
|
||||
sub cleanenv {
|
||||
foreach my $var (keys %ENV) {
|
||||
if ($var eq "VERILATOR_ROOT"
|
||||
|| $var eq "VERILATOR_INCLUDE"
|
||||
|| $var eq "VERILATOR_NO_OPT_BUILD") {
|
||||
print "unset $var # Was '$ENV{$var}'\n";
|
||||
delete $ENV{$var}
|
||||
}
|
||||
}
|
||||
}
|
||||
def write_verilog(dir):
|
||||
shutil.copy2("examples/make_hello_c/top.v", dir + "/top.v")
|
||||
shutil.copy2("examples/make_hello_c/sim_main.cpp", dir + "/sim_main.cpp")
|
||||
|
||||
|
||||
def cleanenv():
|
||||
for var in os.environ:
|
||||
if (var == "VERILATOR_ROOT" or var == "VERILATOR_INCLUDE"
|
||||
or var == "VERILATOR_NO_OPT_BUILD"):
|
||||
print("unset %s # Was '%s'" % (var, os.environ[var]))
|
||||
del os.environ[var]
|
||||
|
||||
|
||||
def calc_jobs():
|
||||
return multiprocessing.cpu_count() + 1
|
||||
|
||||
|
||||
def run(command):
|
||||
# run a system command, check errors
|
||||
print("\t%s" % command)
|
||||
os.system(command)
|
||||
status = subprocess.call(command, shell=True)
|
||||
if status < 0:
|
||||
raise Exception("%Error: Command failed " + command + ", stopped")
|
||||
|
||||
|
||||
#######################################################################
|
||||
|
||||
sub calc_jobs {
|
||||
my $ok = eval "
|
||||
use Unix::Processors;
|
||||
return Unix::Processors->new->max_online;
|
||||
";
|
||||
$ok && !$@ or return 1;
|
||||
print "driver.pl: Found $ok cores, using -j ",$ok+1,"\n" if $Debug;
|
||||
return $ok + 1;
|
||||
}
|
||||
|
||||
sub run {
|
||||
# Run a system command, check errors
|
||||
my $command = shift;
|
||||
print "\t$command\n";
|
||||
system "$command";
|
||||
my $status = $?;
|
||||
($status == 0) or die "%Error: Command Failed $command, $status, stopped";
|
||||
}
|
||||
|
||||
#######################################################################
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
install_test - Build and install Verilator several ways
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
install_test
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
install_test performs several make-and-install iterations to verify the
|
||||
kit. It isn't part of the normal "make test" due to the number of builds
|
||||
required.
|
||||
|
||||
=head1 ARGUMENTS
|
||||
|
||||
=over 4
|
||||
|
||||
=item --help
|
||||
|
||||
Displays this message and program version and exits.
|
||||
|
||||
=item -j I<jobs>
|
||||
|
||||
Specify make -j flag. Defaults to number of cores + 1 if Perl's
|
||||
Unix::Processors is installed, else 1.
|
||||
|
||||
=item -stage I<stage>
|
||||
|
||||
Runs a specific test stage (see the script).
|
||||
|
||||
=back
|
||||
|
||||
=head1 DISTRIBUTION
|
||||
|
||||
Copyright 2009-2020 by Wilson Snyder. This program is free software; you
|
||||
parser = argparse.ArgumentParser(
|
||||
allow_abbrev=False,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
description=
|
||||
"""install_test performs several make-and-install iterations to verify the
|
||||
Verilator kit. It isn't part of the normal "make test" due to the number
|
||||
of builds required.""",
|
||||
epilog=
|
||||
"""Copyright 2009-2021 by Wilson Snyder. This program is free software; you
|
||||
can redistribute it and/or modify it under the terms of either the GNU
|
||||
Lesser General Public License Version 3 or the Perl Artistic License
|
||||
Version 2.0.
|
||||
|
||||
SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0""")
|
||||
parser.add_argument('--debug',
|
||||
action='store_const',
|
||||
const=9,
|
||||
help='enable debug')
|
||||
parser.add_argument('--stage',
|
||||
type=int,
|
||||
default=0,
|
||||
help='run a specific test stage (see the script)')
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
Wilson Snyder <[email protected]>
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
=cut
|
||||
Args = parser.parse_args()
|
||||
test()
|
||||
|
||||
######################################################################
|
||||
### Local Variables:
|
||||
### compile-command: "cd .. ; nodist/install_test "
|
||||
### compile-command: "cd .. ; nodist/install_test"
|
||||
### End:
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
#!/usr/bin/env perl
|
||||
# See copyright, etc in below POD section.
|
||||
######################################################################
|
||||
|
||||
use warnings;
|
||||
use strict;
|
||||
|
||||
#======================================================================
|
||||
# main
|
||||
|
||||
eval `modulecmd perl add axiom-athdl`;
|
||||
exec('atsim',@ARGV);
|
||||
|
||||
#######################################################################
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
invoke_atsim - Invoke tool under "modules" command
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
invoke_atsim {ncv arguments}
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
=head1 DISTRIBUTION
|
||||
|
||||
Copyright 2005-2020 by Wilson Snyder. This program is free software; you
|
||||
can redistribute it and/or modify it under the terms of either the GNU
|
||||
Lesser General Public License Version 3 or the Perl Artistic License
|
||||
Version 2.0.
|
||||
|
||||
SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
Wilson Snyder <[email protected]>
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
=cut
|
||||
|
||||
######################################################################
|
||||
### Local Variables:
|
||||
### compile-command: "./invoke_atsim -help"
|
||||
### End:
|
||||
@@ -1,49 +0,0 @@
|
||||
#!/usr/bin/env perl
|
||||
# See copyright, etc in below POD section.
|
||||
######################################################################
|
||||
|
||||
use warnings;
|
||||
use strict;
|
||||
|
||||
#======================================================================
|
||||
# main
|
||||
|
||||
eval `modulecmd perl add cds-ius`;
|
||||
exec('iccr',@ARGV);
|
||||
|
||||
#######################################################################
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
invoke_iccr - Invoke tool under "modules" command
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
invoke_iccr {ncv arguments}
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
=head1 DISTRIBUTION
|
||||
|
||||
Copyright 2007-2020 by Wilson Snyder. This program is free software; you
|
||||
can redistribute it and/or modify it under the terms of either the GNU
|
||||
Lesser General Public License Version 3 or the Perl Artistic License
|
||||
Version 2.0.
|
||||
|
||||
SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
Wilson Snyder <[email protected]>
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
=cut
|
||||
|
||||
######################################################################
|
||||
### Local Variables:
|
||||
### compile-command: "./invoke_iccr -help"
|
||||
### End:
|
||||
@@ -1,49 +0,0 @@
|
||||
#!/usr/bin/env perl
|
||||
# See copyright, etc in below POD section.
|
||||
######################################################################
|
||||
|
||||
use warnings;
|
||||
use strict;
|
||||
|
||||
#======================================================================
|
||||
# main
|
||||
|
||||
eval `modulecmd perl add cds-ius/latest`;
|
||||
exec('ncverilog',@ARGV);
|
||||
|
||||
#######################################################################
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
invoke_ncverilog - Invoke tool under "modules" command
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
invoke_ncverilog {ncv arguments}
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
=head1 DISTRIBUTION
|
||||
|
||||
Copyright 2005-2020 by Wilson Snyder. This program is free software; you
|
||||
can redistribute it and/or modify it under the terms of either the GNU
|
||||
Lesser General Public License Version 3 or the Perl Artistic License
|
||||
Version 2.0.
|
||||
|
||||
SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
Wilson Snyder <[email protected]>
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
=cut
|
||||
|
||||
######################################################################
|
||||
### Local Variables:
|
||||
### compile-command: "./invoke_ncverilog -help"
|
||||
### End:
|
||||
@@ -1,49 +0,0 @@
|
||||
#!/usr/bin/env perl
|
||||
# See copyright, etc in below POD section.
|
||||
######################################################################
|
||||
|
||||
use warnings;
|
||||
use strict;
|
||||
|
||||
#======================================================================
|
||||
# main
|
||||
|
||||
eval `modulecmd perl add synopsys-sim/latest`;
|
||||
exec('vcs',@ARGV);
|
||||
|
||||
#######################################################################
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
invoke_vcs - Invoke tool under "modules" command
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
invoke_vcs {ncv arguments}
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
=head1 DISTRIBUTION
|
||||
|
||||
Copyright 2005-2020 by Wilson Snyder. This program is free software; you
|
||||
can redistribute it and/or modify it under the terms of either the GNU
|
||||
Lesser General Public License Version 3 or the Perl Artistic License
|
||||
Version 2.0.
|
||||
|
||||
SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
Wilson Snyder <[email protected]>
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
=cut
|
||||
|
||||
######################################################################
|
||||
### Local Variables:
|
||||
### compile-command: "./invoke_vcs -help"
|
||||
### End:
|
||||
@@ -1,352 +0,0 @@
|
||||
#!/usr/bin/env perl
|
||||
# See copyright, etc in below POD section.
|
||||
######################################################################
|
||||
|
||||
use warnings;
|
||||
use Getopt::Long;
|
||||
use IO::File;
|
||||
use Pod::Usage;
|
||||
use Data::Dumper; $Data::Dumper::Indent=1;
|
||||
use strict;
|
||||
use vars qw($Debug);
|
||||
|
||||
#======================================================================
|
||||
|
||||
our $Tree;
|
||||
our %OpMap;
|
||||
gentree();
|
||||
|
||||
#======================================================================
|
||||
# main
|
||||
|
||||
$Debug = 0;
|
||||
my $opt_filename;
|
||||
autoflush STDOUT 1;
|
||||
autoflush STDERR 1;
|
||||
if (! GetOptions(
|
||||
"help" => \&usage,
|
||||
"debug" => \&debug,
|
||||
"<>" => \¶meter,
|
||||
)) {
|
||||
usage();
|
||||
}
|
||||
|
||||
vread($opt_filename);
|
||||
#print Dumper($Tree);
|
||||
vwrite();
|
||||
|
||||
print '(query-replace-regexp "(\\([0-9a-z_]+\\))" "\\1" nil nil nil)',"\n";
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
sub usage {
|
||||
pod2usage(-verbose=>2, -exitval=>0, -output=>\*STDOUT);
|
||||
exit(1); # Unreachable
|
||||
}
|
||||
|
||||
sub debug {
|
||||
$Debug = 1;
|
||||
}
|
||||
|
||||
sub parameter {
|
||||
my $param = shift;
|
||||
if (!$opt_filename) {
|
||||
$opt_filename = $param;
|
||||
} else {
|
||||
die "%Error: Unknown parameter: $param\n";
|
||||
}
|
||||
}
|
||||
|
||||
#######################################################################
|
||||
|
||||
sub vread {
|
||||
my $filename = shift;
|
||||
my $fh = IO::File->new($filename) or die "%Error: $! $filename,";
|
||||
my $lasthier="";
|
||||
$Tree = {
|
||||
op => 'NETLIST',
|
||||
t => [[],[],[],[],[],],
|
||||
};
|
||||
my @stack;
|
||||
$stack[1] = $Tree;
|
||||
while (defined (my $line = $fh->getline)) {
|
||||
if ($line =~ /^\s+(\S+):\s+(\S+)\s+0x\S+\s+{(\d+)}\s+w(\d+)\s+(.*)$/) {
|
||||
my $hier = $1;
|
||||
my $op = $2;
|
||||
my $lineno = $3;
|
||||
my $width = $4;
|
||||
my $etc = $5;
|
||||
|
||||
$etc =~ s/__DOT__/./g;
|
||||
$etc =~ s/__PVT__//g;
|
||||
|
||||
my $self = {
|
||||
op => $op,
|
||||
#width => $width,
|
||||
#lineno => $lineno,
|
||||
#line => $line,
|
||||
etc => $etc,
|
||||
args => [split(/[ \t]+/,$etc)],
|
||||
t => [[],[],[],[],[],],
|
||||
};
|
||||
|
||||
my @hiers = (1,split(/:/,$hier));
|
||||
my $depth = $#hiers+1;
|
||||
my $newchild = $hiers[$#hiers];
|
||||
|
||||
#print "DD $depth $newchild $op\n";
|
||||
|
||||
push @{$stack[$depth-1]->{t}[$newchild]}, $self;
|
||||
$stack[$depth] = $self;
|
||||
|
||||
$lasthier = $hier;
|
||||
#print " $lasthier\n";
|
||||
#print Dumper($Tree);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
######################################################################
|
||||
|
||||
our $Indent = 0;
|
||||
use vars qw($Code_Self);
|
||||
use vars qw($Avoid_Hex);
|
||||
|
||||
sub vwrite {
|
||||
$Indent = 0;
|
||||
print vwrite_rec($Tree);
|
||||
}
|
||||
|
||||
sub vwrite_rec {
|
||||
my $self = shift;
|
||||
#print "/*$self->{op}*/";
|
||||
my $code = $OpMap{$self->{op}} or die "%Error: No map for $self->{op},";
|
||||
local $Code_Self = $self;
|
||||
#print Dumper($self->{t}[3]),"\n";
|
||||
&$code;
|
||||
}
|
||||
|
||||
######################################################################
|
||||
# Tree functions
|
||||
|
||||
sub p { print join("",@_); }
|
||||
|
||||
sub exists1 { return defined $Code_Self->{t}[1][0]; }
|
||||
sub exists2 { return defined $Code_Self->{t}[2][0]; }
|
||||
sub exists3 { return defined $Code_Self->{t}[3][0]; }
|
||||
sub exists4 { return defined $Code_Self->{t}[4][0]; }
|
||||
sub exists5 { return defined $Code_Self->{t}[5][0]; }
|
||||
|
||||
sub t1 { foreach my $r (@{$Code_Self->{t}[1]}) { vwrite_rec($r); } }
|
||||
sub t2 { foreach my $r (@{$Code_Self->{t}[2]}) { vwrite_rec($r); } }
|
||||
sub t3 { foreach my $r (@{$Code_Self->{t}[3]}) { vwrite_rec($r); } }
|
||||
sub t4 { foreach my $r (@{$Code_Self->{t}[4]}) { vwrite_rec($r); } }
|
||||
sub t5 { foreach my $r (@{$Code_Self->{t}[5]}) { vwrite_rec($r); } }
|
||||
sub p1 { p "("; t1; p ")";}
|
||||
sub p2 { p "("; t2; p ")";}
|
||||
sub p3 { p "("; t3; p ")";}
|
||||
sub p4 { p "("; t4; p ")";}
|
||||
sub p5 { p "("; t5; p ")";}
|
||||
sub a1 { p $Code_Self->{args}[0]; }
|
||||
sub a2 { p $Code_Self->{args}[1]; }
|
||||
sub a3 { p $Code_Self->{args}[2]; }
|
||||
sub a4 { p $Code_Self->{args}[3]; }
|
||||
sub a5 { p $Code_Self->{args}[4]; }
|
||||
sub a6 { p $Code_Self->{args}[5]; }
|
||||
sub a7 { p $Code_Self->{args}[6]; }
|
||||
|
||||
sub indentInc { $Indent+=2; }
|
||||
sub indentDec { $Indent-=2; }
|
||||
sub nl { p "\n"," "x$Indent; }
|
||||
|
||||
######################################################################
|
||||
|
||||
# nl is a newline
|
||||
# p# indicates to add parens
|
||||
# t# indicates tree reference
|
||||
# a# indicates info from dump where n1 is the width.
|
||||
|
||||
sub gentree {
|
||||
%OpMap = (
|
||||
'NULLNODE' => sub { "" },
|
||||
'NETLIST' => sub { nl;t1;t2;t3;t4;t5; },
|
||||
'ACTIVE' => sub { p "always_act @(";t1;p ") begin";indentInc;nl;t2;t3;t4;t5;indentDec;p "end";nl; },
|
||||
'ADD' => sub { p1;p " + ";p2; },
|
||||
'ALWAYS' => sub { p "always @(";t1;p ") begin";indentInc;nl;t2;t3;t4;t5;indentDec;p "end";nl; },
|
||||
'ALWAYSPOST' => sub { p "ALWAYSPOST what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
|
||||
'AND' => sub { p1;p " & ";p2; },
|
||||
'ARRAYSEL' => sub { t1;p "[";t2;p "]"; },
|
||||
'ASSIGN' => sub { t2;p " = ";t1;p ";";nl; },
|
||||
'ASSIGNDLY' => sub { t2;p " <= ";t1;p ";";nl; },
|
||||
'ASSIGNPOST' => sub { p "ASSIGNPOST what{";t1;p " = ";t2;p ";";nl; },
|
||||
'ASSIGNPRE' => sub { p "ASSIGNPRE what{";t1;p " = ";t2;p ";";nl; },
|
||||
'ASSIGNW' => sub { p "assign ";t2;p " = ";t1;p ";";nl; },
|
||||
'ATTROF' => sub { p "ATTROF what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
|
||||
'BEGIN' => sub { p "begin";indentInc;nl;t1;t2;t3;t4;t5;indentDec;p "end";nl; },
|
||||
'BITSEL' => sub { t1;local $Avoid_Hex=1; p "[";t2;p "]"; },
|
||||
'CASE' => sub { p "CASE what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
|
||||
'CASEITEM' => sub { p "CASEITEM what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
|
||||
'CAST' => sub { p "CAST what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
|
||||
'CCALL' => sub { p "CCALL what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
|
||||
'CELL' => sub { a1;p " ";a7;p " (/*CELL*/);"; nl; },
|
||||
'CFUNC' => sub { p "CFUNC what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
|
||||
'CHANGEDET' => sub { p "CHANGEDET what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
|
||||
'CINCLUDE' => sub { p "CINCLUDE what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
|
||||
'COMMENT' => sub { p "//COMMENT what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl;nl; },
|
||||
'CONCAT' => sub { p "{";p1;p ",";p2;p "}"; },
|
||||
'CONDITIONAL' => sub { p1;p " ? ";p2;p " : ";p3; },
|
||||
'CONST' => sub { p_const(); },
|
||||
'COVER' => sub { p "COVER what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
|
||||
'CRETURN' => sub { p "CRETURN what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
|
||||
'CSTMT' => sub { p "CSTMT what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
|
||||
'DEFPARAM' => sub { p "defparam ";p1;p " = ";p2;p ";";nl; },
|
||||
'DISPLAY' => sub { p '$write("';p1;p "\",";p2;p3;p4;p5;p ");";nl; },
|
||||
'DIV' => sub { p1;p " / ";p2; },
|
||||
'EQ' => sub { p1;p " == ";p2; },
|
||||
'EQCASE' => sub { p1;p " === ";p2; },
|
||||
'EXTEND' => sub { t1; },
|
||||
'EXTRACT' => sub { t1;local $Avoid_Hex=1; p "[";t2;p ":";t3;p "]"; },
|
||||
'FINISH' => sub { p '$finish;';nl },
|
||||
'FOR' => sub { p "for (";p1;p ",";p2;p ",";p3;p ") begin";indentInc;nl;p4;p5;indentDec;p "end";nl; },
|
||||
'FUNC' => sub { p "FUNC what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
|
||||
'FUNCREF' => sub { p "FUNCREF what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
|
||||
'GT' => sub { p1;p " > ";p2; },
|
||||
'GTE' => sub { p1;p " >= ";p2; },
|
||||
'IF' => sub { p "if (";p1;p ") begin";indentInc;nl;t2;indentDec;if (exists3) {p "end else begin";indentInc;nl;t3;indentDec;} p "end"; nl; },
|
||||
'INITARRAY' => sub { p "INITARRAY what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
|
||||
'INITIAL' => sub { p "initial begin";indentInc;nl;t1;t2;t3;t4;t5;indentDec;p "end";nl; },
|
||||
'LOGAND' => sub { p1;p " && ";p2; },
|
||||
'LOGNOT' => sub { p1;p " || ";p2; },
|
||||
'LOGOR' => sub { p "!";p1; },
|
||||
'LT' => sub { p1;p " < ";p2; },
|
||||
'LTE' => sub { p1;p " <= ";p2; },
|
||||
'MODDIV' => sub { p1;p " % ";p2; },
|
||||
'MODULE' => sub { p "module ";a1;p " (/*AUTOARG*/);";indentInc;nl;t1;t2;t3;t4;t5;indentDec;nl;p "endmodule";nl; },
|
||||
'MUL' => sub { p1;p " * ";p2; },
|
||||
'NEQ' => sub { p1;p " != ";p2; },
|
||||
'NEQCASE' => sub { p1;p " !== ";p2; },
|
||||
'NOT' => sub { p " ~";p1; },
|
||||
'OR' => sub { p1;p " | ";p2; },
|
||||
'PIN' => sub { p ";p ";p1;p " (";p2;p "),";nl; },
|
||||
'PORT' => sub { p ""; },
|
||||
'PRAGMA' => sub { p "PRAGMA what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
|
||||
'RAND' => sub { p '$rand'; },
|
||||
'RANGE' => sub { t1; local $Avoid_Hex=1; p "[";t2;p ":";t3;p "]"; },
|
||||
'REDAND' => sub { p "&(";p1;p ")"; },
|
||||
'REDOR' => sub { p "|(";p1;p ")"; },
|
||||
'REDXNOR' => sub { p "~|(";p1;p ")"; },
|
||||
'REDXOR' => sub { p "~^(";p1;p ")"; },
|
||||
'REPLICATE' => sub { p "{";p1;p "{";p2;p "}}"; },
|
||||
'SCCTOR' => sub { p "SCCTOR what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
|
||||
'SCHDR' => sub { p "SCHDR what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
|
||||
'SCIMP' => sub { p "SCIMP what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
|
||||
'SCINT' => sub { p "SCINT what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
|
||||
'SCOPE' => sub { t1;t2;t3;t4;t5; },
|
||||
'SENITEM' => sub { a1;p " ";t1; },
|
||||
'SENTREE' => sub { t1;t2;t3;t4;t5; },
|
||||
'SHIFTL' => sub { p1;p " << ";p2; },
|
||||
'SHIFTR' => sub { p1;p " >> ";p2; },
|
||||
'STOP' => sub { p '$stop;';nl; },
|
||||
'SUB' => sub { p1;p " - ";p2; },
|
||||
'TASK' => sub { p "TASK what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
|
||||
'TASKREF' => sub { p "TASKREF what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
|
||||
'TEXT' => sub { p "TEXT what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
|
||||
'TIME' => sub { p '$time'; },
|
||||
'TOPSCOPE' => sub { t1;t2;t3;t4;t5; },
|
||||
'TRACE' => sub { p "TRACE what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
|
||||
'UCFUNC' => sub { p '$c(';p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p ")"; },
|
||||
'UCSTMT' => sub { p '$c(';p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p ");";nl; },
|
||||
'NEGATE' => sub { p " -";p1; },
|
||||
'VAR' => sub { p_var(); },
|
||||
'VARPIN' => sub { p "VARPIN what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
|
||||
'VARREF' => sub { a1; },
|
||||
'VARSCOPE' => sub { },
|
||||
'WHILE' => sub { t1; p "while (";t2;p ") begin";indentInc;nl;t3;t4;indentDec;p "end";nl; },
|
||||
'WORDSEL' => sub { p1;p "[";p2;p ":";p3;p "]"; },
|
||||
'XNOR' => sub { p1;p " ~^ ";p2; },
|
||||
'XOR' => sub { p1;p " ^";p2; },
|
||||
);
|
||||
}
|
||||
|
||||
sub p_var {
|
||||
my $self = $Code_Self;
|
||||
if ($self->{etc} =~ /\[I\]/) {
|
||||
print "input";
|
||||
} elsif ($self->{etc} =~ /\[O\]/) {
|
||||
print "output";
|
||||
} else {
|
||||
print "reg";
|
||||
}
|
||||
p "\t";
|
||||
{
|
||||
local $Avoid_Hex=1;
|
||||
t1;
|
||||
}
|
||||
p "\t";
|
||||
a1;
|
||||
if (exists2()) {
|
||||
p " = ";
|
||||
t2;
|
||||
}
|
||||
p ";";
|
||||
nl;
|
||||
}
|
||||
|
||||
sub p_const {
|
||||
my $v = $Code_Self->{args}[0];
|
||||
if ($v =~ /\?32\?h(.*)$/
|
||||
|| ($Avoid_Hex && $v =~ /^[0-9?]*h(.*)$/)) {
|
||||
print hex $1;
|
||||
} else {
|
||||
print $v;
|
||||
}
|
||||
}
|
||||
|
||||
#######################################################################
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
vtree_importer -
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
vtree_importer *.log
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
dd
|
||||
|
||||
=head1 ARGUMENTS
|
||||
|
||||
=over 4
|
||||
|
||||
=item --help
|
||||
|
||||
Displays this message and program version and exits.
|
||||
|
||||
=back
|
||||
|
||||
=head1 DISTRIBUTION
|
||||
|
||||
Copyright 2005-2020 by Wilson Snyder. This program is free software; you
|
||||
can redistribute it and/or modify it under the terms of either the GNU
|
||||
Lesser General Public License Version 3 or the Perl Artistic License
|
||||
Version 2.0.
|
||||
|
||||
SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
Wilson Snyder <[email protected]>
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
=cut
|
||||
|
||||
######################################################################
|
||||
### Local Variables:
|
||||
### compile-command: "./vtree_importer "
|
||||
### End:
|
||||
+4
-4
@@ -1,27 +1,27 @@
|
||||
# DESCRIPTION: Verilator: GDB startup file with useful defines
|
||||
#
|
||||
# Copyright 2012-2020 by Wilson Snyder. This program is free software; you
|
||||
# Copyright 2012-2021 by Wilson Snyder. This program is free software; you
|
||||
# can redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
define pn
|
||||
call $arg0->dumpGdb()
|
||||
call AstNode::dumpGdb($arg0)
|
||||
end
|
||||
document pn
|
||||
Verilator: Print single AstNode NODEP
|
||||
end
|
||||
|
||||
define pnt
|
||||
call $arg0->dumpTreeGdb()
|
||||
call AstNode::dumpTreeGdb($arg0)
|
||||
end
|
||||
document pnt
|
||||
Verilator: Print AstNode NODEP's tree
|
||||
end
|
||||
|
||||
define dtf
|
||||
call AstNode::dumpTreeFileGdb(0)
|
||||
call AstNode::dumpTreeFileGdb($arg0, 0)
|
||||
end
|
||||
document dtf
|
||||
Verilator: Dump AstNode tree to file
|
||||
|
||||
+9
-7
@@ -7,7 +7,7 @@
|
||||
#
|
||||
#*****************************************************************************
|
||||
#
|
||||
# Copyright 2003-2020 by Wilson Snyder. This program is free software; you
|
||||
# Copyright 2003-2021 by Wilson Snyder. This program is free software; you
|
||||
# can redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
@@ -18,7 +18,7 @@
|
||||
#### Start of system configuration section. ####
|
||||
|
||||
srcdir = @srcdir@
|
||||
PERL = @PERL@
|
||||
PYTHON3 = @PYTHON3@
|
||||
EXEEXT = @EXEEXT@
|
||||
# VPATH only does sources; fix install_test's not creating ../bin
|
||||
vpath %.h @srcdir@
|
||||
@@ -52,8 +52,8 @@ obj_dbg:
|
||||
opt: ../bin/verilator_bin
|
||||
ifeq ($(VERILATOR_NO_OPT_BUILD),1) # Faster laptop development... One build
|
||||
../bin/verilator_bin: ../bin/verilator_bin_dbg
|
||||
-rm -rf $@ $@.exe
|
||||
-cp -p $<$(EXEEXT) $@$(EXEEXT)
|
||||
-cp -p $<$(EXEEXT) $@$(EXEEXT).tmp
|
||||
-mv -f $@$(EXEEXT).tmp $@$(EXEEXT)
|
||||
else
|
||||
../bin/verilator_bin: obj_opt ../bin prefiles
|
||||
$(MAKE) -C obj_opt -j 1 TGT=../$@ -f ../Makefile_obj serial
|
||||
@@ -78,17 +78,19 @@ endif
|
||||
prefiles::
|
||||
prefiles:: config_rev.h
|
||||
# This output goes into srcdir if locally configured, as we need to distribute it as part of the kit.
|
||||
config_rev.h: ${srcdir}/config_rev.pl $(GIT_CHANGE_DEP)
|
||||
$(PERL) ${srcdir}/config_rev.pl ${srcdir} >$@
|
||||
config_rev.h: ${srcdir}/config_rev $(GIT_CHANGE_DEP)
|
||||
$(PYTHON3) ${srcdir}/config_rev ${srcdir} >$@
|
||||
|
||||
# Human convenience
|
||||
format:
|
||||
$(MAKE) -C .. $@
|
||||
clang-format:
|
||||
$(MAKE) -C .. $@
|
||||
|
||||
maintainer-copy::
|
||||
clean mostlyclean distclean maintainer-clean::
|
||||
-rm -rf obj_* *.log *.dmp *.vpd core
|
||||
-rm -f *.o *.d perlxsi.c *_gen_*
|
||||
-rm -f *.o *.d *_gen_*
|
||||
-rm -f *__gen* obj_*
|
||||
-rm -f .objcache*
|
||||
|
||||
|
||||
+5
-4
@@ -7,7 +7,7 @@
|
||||
#
|
||||
#*****************************************************************************
|
||||
#
|
||||
# Copyright 2003-2020 by Wilson Snyder. This program is free software; you
|
||||
# Copyright 2003-2021 by Wilson Snyder. This program is free software; you
|
||||
# can redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
@@ -41,6 +41,7 @@ LINK = @CXX@
|
||||
LEX = @LEX@
|
||||
LFLAGS = -d
|
||||
PERL = @PERL@
|
||||
PYTHON3 = @PYTHON3@
|
||||
YACC = @YACC@
|
||||
OBJCACHE ?= @OBJCACHE@
|
||||
|
||||
@@ -94,7 +95,6 @@ LIBS = $(CFG_LIBS) -lm
|
||||
|
||||
CPPFLAGS += -MMD
|
||||
CPPFLAGS += -I. -I$(bldsrc) -I$(srcdir) -I$(incdir) -I../../include
|
||||
CPPFLAGS += -DYYDEBUG # Required to get nice error messages
|
||||
#CPPFLAGS += -DVL_LEAK_CHECKS # If running valgrind or other hunting tool
|
||||
CPPFLAGS += $(COPT)
|
||||
CPPFLAGS += -MP # Only works on recent GCC versions
|
||||
@@ -139,7 +139,7 @@ make_info:
|
||||
@echo " Compile flags: " $(CXX) ${CFLAGS} ${CXXFLAGS} ${CPPFLAGS}
|
||||
|
||||
clean mostlyclean distclean maintainer-clean::
|
||||
-rm -f *.o *.d perlxsi.c *_gen_*
|
||||
-rm -f *.o *.d *_gen_*
|
||||
-rm -f *__gen*
|
||||
-rm -f obj_* .objcache*
|
||||
|
||||
@@ -229,6 +229,7 @@ RAW_OBJS = \
|
||||
V3PreShell.o \
|
||||
V3Premit.o \
|
||||
V3ProtectLib.o \
|
||||
V3Randomize.o \
|
||||
V3Reloop.o \
|
||||
V3Scope.o \
|
||||
V3Scoreboard.o \
|
||||
@@ -332,7 +333,7 @@ V3Lexer_pregen.yy.cpp: verilog.l V3ParseBison.h $(HEADERS)
|
||||
${LEX} ${LFLAGS} -o$@ $<
|
||||
|
||||
V3Lexer.yy.cpp: V3Lexer_pregen.yy.cpp $(FLEXFIX)
|
||||
$(PERL) $(FLEXFIX) V3Lexer <$< >$@
|
||||
$(PYTHON3) $(FLEXFIX) V3Lexer <$< >$@
|
||||
|
||||
V3PreLex_pregen.yy.cpp: V3PreLex.l $(HEADERS)
|
||||
${LEX} --version
|
||||
|
||||
+222
-13
@@ -6,7 +6,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2020 by Wilson Snyder. This program is free software; you
|
||||
// Copyright 2003-2021 by Wilson Snyder. This program is free software; you
|
||||
// can redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -35,20 +35,177 @@
|
||||
#include "V3EmitCBase.h"
|
||||
#include "V3Const.h"
|
||||
#include "V3SenTree.h" // for SenTreeSet
|
||||
#include "V3Graph.h"
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
//***** See below for main transformation engine
|
||||
|
||||
//######################################################################
|
||||
|
||||
// Extend V3GraphVertex class for use in latch detection graph
|
||||
|
||||
class LatchDetectGraphVertex final : public V3GraphVertex {
|
||||
public:
|
||||
enum VertexType : uint8_t { VT_BLOCK, VT_BRANCH, VT_OUTPUT };
|
||||
|
||||
private:
|
||||
string m_name; // Only used for .dot file generation
|
||||
VertexType m_type; // Vertex type (BLOCK/BRANCH/OUTPUT)
|
||||
|
||||
string typestr() const { // "
|
||||
switch (m_type) {
|
||||
case VT_BLOCK: return "(||)"; // basic block node
|
||||
case VT_BRANCH: return "(&&)"; // if/else branch mode
|
||||
case VT_OUTPUT: return "(out)"; // var assignment
|
||||
default: return "??"; // unknown
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
LatchDetectGraphVertex(V3Graph* graphp, const string& name, VertexType type = VT_BLOCK)
|
||||
: V3GraphVertex(graphp)
|
||||
, m_name(name)
|
||||
, m_type(type) {}
|
||||
virtual string name() const { return m_name + " " + typestr(); }
|
||||
virtual string dotColor() const { return user() ? "green" : "black"; }
|
||||
virtual int type() const { return m_type; }
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
// Extend V3Graph class for use as a latch detection graph
|
||||
|
||||
class LatchDetectGraph final : public V3Graph {
|
||||
protected:
|
||||
typedef std::vector<AstVarRef*> VarRefVec;
|
||||
|
||||
LatchDetectGraphVertex* m_curVertexp; // Current latch detection graph vertex
|
||||
VarRefVec m_outputs; // Vector of lvalues encountered on this pass
|
||||
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
||||
static LatchDetectGraphVertex* castVertexp(void* vertexp) {
|
||||
return reinterpret_cast<LatchDetectGraphVertex*>(vertexp);
|
||||
}
|
||||
|
||||
// Recursively traverse the graph to determine whether every control 'BLOCK' has an assignment
|
||||
// to the output we are currently analysing (the output whose 'user() is set), if so return
|
||||
// true. Where a BLOCK contains a BRANCH, both the if and else sides of the branch must return
|
||||
// true for the BRANCH to evalute to true. A BLOCK however needs only a single one of its
|
||||
// siblings to evaluate true in order to evaluate true itself. On output vertex only evaluates
|
||||
// true if it is the vertex we are analyzing on this check
|
||||
|
||||
bool latchCheckInternal(LatchDetectGraphVertex* vertexp) {
|
||||
bool result = false;
|
||||
switch (vertexp->type()) {
|
||||
case LatchDetectGraphVertex::VT_OUTPUT: // Base case
|
||||
result = vertexp->user();
|
||||
break;
|
||||
case LatchDetectGraphVertex::VT_BLOCK: // (OR of potentially many siblings)
|
||||
for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep = edgep->outNextp()) {
|
||||
if (latchCheckInternal(castVertexp(edgep->top()))) {
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case LatchDetectGraphVertex::VT_BRANCH: // (AND of both sibling)
|
||||
// A BRANCH vertex always has exactly 2 siblings
|
||||
LatchDetectGraphVertex* ifp = castVertexp(vertexp->outBeginp()->top());
|
||||
LatchDetectGraphVertex* elsp = castVertexp(vertexp->outBeginp()->outNextp()->top());
|
||||
result = latchCheckInternal(ifp) && latchCheckInternal(elsp);
|
||||
break;
|
||||
}
|
||||
vertexp->user(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public:
|
||||
LatchDetectGraph() { clear(); }
|
||||
~LatchDetectGraph() { clear(); }
|
||||
// ACCESSORS
|
||||
LatchDetectGraphVertex* currentp() { return m_curVertexp; }
|
||||
void currentp(LatchDetectGraphVertex* vertex) { m_curVertexp = vertex; }
|
||||
// METHODS
|
||||
void begin() {
|
||||
// Start a new if/else tracking graph
|
||||
// See NODE STATE comment in ActiveLatchCheckVisitor
|
||||
AstNode::user1ClearTree();
|
||||
m_curVertexp = new LatchDetectGraphVertex(this, "ROOT");
|
||||
}
|
||||
// Clear out userp field of referenced outputs on destruction
|
||||
// (occurs at the end of each combinational always block)
|
||||
void clear() {
|
||||
m_outputs.clear();
|
||||
// Calling base class clear will unlink & delete all edges & vertices
|
||||
V3Graph::clear();
|
||||
m_curVertexp = nullptr;
|
||||
}
|
||||
// Add a new control path and connect it to its parent
|
||||
LatchDetectGraphVertex* addPathVertex(LatchDetectGraphVertex* parent, const string& name,
|
||||
bool branch = false) {
|
||||
m_curVertexp = new LatchDetectGraphVertex(this, name,
|
||||
branch ? LatchDetectGraphVertex::VT_BRANCH
|
||||
: LatchDetectGraphVertex::VT_BLOCK);
|
||||
new V3GraphEdge(this, parent, m_curVertexp, 1);
|
||||
return m_curVertexp;
|
||||
}
|
||||
// Add a new output variable vertex and store a pointer to it in the user1 field of the
|
||||
// variables AstNode
|
||||
LatchDetectGraphVertex* addOutputVertex(AstVarRef* nodep) {
|
||||
LatchDetectGraphVertex* outVertexp
|
||||
= new LatchDetectGraphVertex(this, nodep->name(), LatchDetectGraphVertex::VT_OUTPUT);
|
||||
nodep->varp()->user1p(outVertexp);
|
||||
m_outputs.push_back(nodep);
|
||||
return outVertexp;
|
||||
}
|
||||
// Connect an output assignment to its parent control block
|
||||
void addAssignment(AstVarRef* nodep) {
|
||||
LatchDetectGraphVertex* outVertexp;
|
||||
if (!nodep->varp()->user1p()) { // Not seen this output before
|
||||
outVertexp = addOutputVertex(nodep);
|
||||
} else
|
||||
outVertexp = castVertexp(nodep->varp()->user1p());
|
||||
|
||||
new V3GraphEdge(this, m_curVertexp, outVertexp, 1);
|
||||
}
|
||||
// Run latchCheckInternal on each variable assigned by the always block to see if all control
|
||||
// paths make an assignment. Detected latches are flagged in the variables AstVar
|
||||
void latchCheck(AstNode* nodep, bool latch_expected) {
|
||||
bool latch_detected = false;
|
||||
for (const auto& vrp : m_outputs) {
|
||||
LatchDetectGraphVertex* vertp = castVertexp(vrp->varp()->user1p());
|
||||
vertp->user(true); // Identify the output vertex we are checking paths _to_
|
||||
if (!latchCheckInternal(castVertexp(verticesBeginp()))) { latch_detected = true; }
|
||||
if (latch_detected && !latch_expected) {
|
||||
nodep->v3warn(
|
||||
LATCH,
|
||||
"Latch inferred for signal "
|
||||
<< vrp->prettyNameQ()
|
||||
<< " (not all control paths of combinational always assign a value)\n"
|
||||
<< nodep->warnMore()
|
||||
<< "... Suggest use of always_latch for intentional latches");
|
||||
if (debug() >= 9) { dumpDotFilePrefixed("latch_" + vrp->name()); }
|
||||
}
|
||||
vertp->user(false); // Clear again (see above)
|
||||
vrp->varp()->isLatched(latch_detected);
|
||||
}
|
||||
// Should _all_ variables assigned in always_latch be latches? Probably, but this only
|
||||
// warns if none of them are
|
||||
if (latch_expected && !latch_detected)
|
||||
nodep->v3warn(NOLATCH, "No latches detected in always_latch block");
|
||||
}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
// Collect existing active names
|
||||
|
||||
class ActiveBaseVisitor : public AstNVisitor {
|
||||
class ActiveBaseVisitor VL_NOT_FINAL : public AstNVisitor {
|
||||
protected:
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
};
|
||||
|
||||
class ActiveNamer : public ActiveBaseVisitor {
|
||||
class ActiveNamer final : public ActiveBaseVisitor {
|
||||
private:
|
||||
// STATE
|
||||
AstScope* m_scopep = nullptr; // Current scope to add statement to
|
||||
@@ -130,15 +287,57 @@ public:
|
||||
}
|
||||
|
||||
// CONSTRUCTORS
|
||||
ActiveNamer() {}
|
||||
virtual ~ActiveNamer() override {}
|
||||
ActiveNamer() = default;
|
||||
virtual ~ActiveNamer() override = default;
|
||||
void main(AstScope* nodep) { iterate(nodep); }
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
// Latch checking visitor
|
||||
|
||||
class ActiveLatchCheckVisitor final : public ActiveBaseVisitor {
|
||||
private:
|
||||
// NODE STATE
|
||||
// Input:
|
||||
// AstVar::user1p // V2LatchGraphVertex* The vertex handling this node
|
||||
AstUser1InUse m_inuser1;
|
||||
// STATE
|
||||
LatchDetectGraph m_graph; // Graph used to detect latches in combo always
|
||||
// VISITORS
|
||||
virtual void visit(AstVarRef* nodep) {
|
||||
AstVar* varp = nodep->varp();
|
||||
if (nodep->access().isWriteOrRW() && varp->isSignal() && !varp->isUsedLoopIdx()) {
|
||||
m_graph.addAssignment(nodep);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstNodeIf* nodep) {
|
||||
LatchDetectGraphVertex* parentp = m_graph.currentp();
|
||||
LatchDetectGraphVertex* branchp = m_graph.addPathVertex(parentp, "BRANCH", true);
|
||||
m_graph.addPathVertex(branchp, "IF");
|
||||
iterateAndNextNull(nodep->ifsp());
|
||||
m_graph.addPathVertex(branchp, "ELSE");
|
||||
iterateAndNextNull(nodep->elsesp());
|
||||
m_graph.currentp(parentp);
|
||||
}
|
||||
// Empty visitors, speed things up
|
||||
virtual void visit(AstNodeMath* nodep) {}
|
||||
//--------------------
|
||||
virtual void visit(AstNode* nodep) { iterateChildren(nodep); }
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
ActiveLatchCheckVisitor(AstNode* nodep, VAlwaysKwd kwd) {
|
||||
m_graph.begin();
|
||||
iterate(nodep);
|
||||
m_graph.latchCheck(nodep, kwd == VAlwaysKwd::ALWAYS_LATCH);
|
||||
}
|
||||
virtual ~ActiveLatchCheckVisitor() {}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
// Active AssignDly replacement functions
|
||||
|
||||
class ActiveDlyVisitor : public ActiveBaseVisitor {
|
||||
class ActiveDlyVisitor final : public ActiveBaseVisitor {
|
||||
public:
|
||||
enum CheckType : uint8_t { CT_SEQ, CT_COMBO, CT_INITIAL, CT_LATCH };
|
||||
|
||||
@@ -157,11 +356,14 @@ private:
|
||||
<< "... Suggest blocking assignments (=)");
|
||||
} else if (m_check == CT_LATCH) {
|
||||
// Suppress. Shouldn't matter that the interior of the latch races
|
||||
} else {
|
||||
} else if (!(VN_IS(nodep->lhsp(), VarRef)
|
||||
&& VN_CAST(nodep->lhsp(), VarRef)->varp()->isLatched())) {
|
||||
nodep->v3warn(COMBDLY, "Delayed assignments (<=) in non-clocked"
|
||||
" (non flop or latch) block\n"
|
||||
<< nodep->warnMore()
|
||||
<< "... Suggest blocking assignments (=)");
|
||||
// Conversely, we could also suggest latches use delayed assignments, as
|
||||
// recommended by Cliff Cummings?
|
||||
}
|
||||
AstNode* newp = new AstAssign(nodep->fileline(), nodep->lhsp()->unlinkFrBack(),
|
||||
nodep->rhsp()->unlinkFrBack());
|
||||
@@ -171,10 +373,9 @@ private:
|
||||
}
|
||||
virtual void visit(AstAssign* nodep) override {
|
||||
if (m_check == CT_SEQ) {
|
||||
AstNode* las = m_assignp;
|
||||
VL_RESTORER(m_assignp);
|
||||
m_assignp = nodep;
|
||||
iterateAndNextNull(nodep->lhsp());
|
||||
m_assignp = las;
|
||||
}
|
||||
}
|
||||
virtual void visit(AstVarRef* nodep) override {
|
||||
@@ -205,13 +406,13 @@ public:
|
||||
, m_alwaysp{nodep} {
|
||||
iterate(nodep);
|
||||
}
|
||||
virtual ~ActiveDlyVisitor() override {}
|
||||
virtual ~ActiveDlyVisitor() override = default;
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
// Active class functions
|
||||
|
||||
class ActiveVisitor : public ActiveBaseVisitor {
|
||||
class ActiveVisitor final : public ActiveBaseVisitor {
|
||||
private:
|
||||
// NODE STATE
|
||||
// Each call to V3Const::constify
|
||||
@@ -284,7 +485,6 @@ private:
|
||||
m_namer.scopep()->addActivep(m_scopeFinalp);
|
||||
}
|
||||
nodep->unlinkFrBack();
|
||||
m_scopeFinalp->addStmtsp(new AstComment(nodep->fileline(), nodep->typeName(), true));
|
||||
m_scopeFinalp->addStmtsp(nodep->bodysp()->unlinkFrBackWithNext());
|
||||
VL_DO_DANGLING(nodep->deleteTree(), nodep);
|
||||
}
|
||||
@@ -343,6 +543,7 @@ private:
|
||||
|
||||
// Warn and/or convert any delayed assignments
|
||||
if (combo && !sequent) {
|
||||
ActiveLatchCheckVisitor latchvisitor(nodep, kwd);
|
||||
if (kwd == VAlwaysKwd::ALWAYS_LATCH) {
|
||||
ActiveDlyVisitor dlyvisitor(nodep, ActiveDlyVisitor::CT_LATCH);
|
||||
} else {
|
||||
@@ -364,6 +565,14 @@ private:
|
||||
}
|
||||
visitAlways(nodep, nodep->sensesp(), nodep->keyword());
|
||||
}
|
||||
virtual void visit(AstAlwaysPostponed* nodep) override {
|
||||
UINFO(4, " ALW " << nodep << endl);
|
||||
if (!nodep->bodysp()) {
|
||||
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
|
||||
return;
|
||||
}
|
||||
visitAlways(nodep, nullptr, VAlwaysKwd::ALWAYS);
|
||||
}
|
||||
virtual void visit(AstAlwaysPublic* nodep) override {
|
||||
// Move always to appropriate ACTIVE based on its sense list
|
||||
UINFO(4, " ALWPub " << nodep << endl);
|
||||
@@ -406,7 +615,7 @@ private:
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit ActiveVisitor(AstNetlist* nodep) { iterate(nodep); }
|
||||
virtual ~ActiveVisitor() override {}
|
||||
virtual ~ActiveVisitor() override = default;
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
||||
+2
-2
@@ -6,7 +6,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2020 by Wilson Snyder. This program is free software; you
|
||||
// Copyright 2003-2021 by Wilson Snyder. This program is free software; you
|
||||
// can redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
//============================================================================
|
||||
|
||||
class V3Active {
|
||||
class V3Active final {
|
||||
public:
|
||||
static void activeAll(AstNetlist* nodep);
|
||||
};
|
||||
|
||||
+3
-3
@@ -6,7 +6,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2020 by Wilson Snyder. This program is free software; you
|
||||
// Copyright 2003-2021 by Wilson Snyder. This program is free software; you
|
||||
// can redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -35,7 +35,7 @@
|
||||
//######################################################################
|
||||
// Active class functions
|
||||
|
||||
class ActiveTopVisitor : public AstNVisitor {
|
||||
class ActiveTopVisitor final : public AstNVisitor {
|
||||
private:
|
||||
// NODE STATE
|
||||
// Entire netlist
|
||||
@@ -128,7 +128,7 @@ private:
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit ActiveTopVisitor(AstNetlist* nodep) { iterate(nodep); }
|
||||
virtual ~ActiveTopVisitor() override {}
|
||||
virtual ~ActiveTopVisitor() override = default;
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
||||
+2
-2
@@ -6,7 +6,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2020 by Wilson Snyder. This program is free software; you
|
||||
// Copyright 2003-2021 by Wilson Snyder. This program is free software; you
|
||||
// can redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
//============================================================================
|
||||
|
||||
class V3ActiveTop {
|
||||
class V3ActiveTop final {
|
||||
public:
|
||||
static void activeTopAll(AstNetlist* nodep);
|
||||
};
|
||||
|
||||
+96
-20
@@ -6,7 +6,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2005-2020 by Wilson Snyder. This program is free software; you
|
||||
// Copyright 2005-2021 by Wilson Snyder. This program is free software; you
|
||||
// can redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -26,7 +26,7 @@
|
||||
//######################################################################
|
||||
// Assert class functions
|
||||
|
||||
class AssertVisitor : public AstNVisitor {
|
||||
class AssertVisitor final : public AstNVisitor {
|
||||
private:
|
||||
// NODE STATE/TYPES
|
||||
// Cleared on netlist
|
||||
@@ -36,7 +36,11 @@ private:
|
||||
// STATE
|
||||
AstNodeModule* m_modp = nullptr; // Last module
|
||||
AstBegin* m_beginp = nullptr; // Last begin
|
||||
unsigned m_monitorNum = 0; // Global $monitor numbering (not per module)
|
||||
AstVar* m_monitorNumVarp = nullptr; // $monitor number variable
|
||||
AstVar* m_monitorOffVarp = nullptr; // $monitoroff variable
|
||||
unsigned m_modPastNum = 0; // Module past numbering
|
||||
unsigned m_modStrobeNum = 0; // Module $strobe numbering
|
||||
VDouble0 m_statCover; // Statistic tracking
|
||||
VDouble0 m_statAsNotImm; // Statistic tracking
|
||||
VDouble0 m_statAsImm; // Statistic tracking
|
||||
@@ -62,19 +66,39 @@ private:
|
||||
nodep->fmtp()->scopeNamep(new AstScopeName(nodep->fileline()));
|
||||
}
|
||||
}
|
||||
|
||||
AstNode* newIfAssertOn(AstNode* nodep) {
|
||||
AstVarRef* newMonitorNumVarRefp(AstNode* nodep, VAccess access) {
|
||||
if (!m_monitorNumVarp) {
|
||||
m_monitorNumVarp = new AstVar{nodep->fileline(), AstVarType::MODULETEMP,
|
||||
"__VmonitorNum", nodep->findUInt64DType()};
|
||||
v3Global.rootp()->dollarUnitPkgAddp()->addStmtp(m_monitorNumVarp);
|
||||
}
|
||||
const auto varrefp = new AstVarRef(nodep->fileline(), m_monitorNumVarp, access);
|
||||
varrefp->classOrPackagep(v3Global.rootp()->dollarUnitPkgAddp());
|
||||
return varrefp;
|
||||
}
|
||||
AstVarRef* newMonitorOffVarRefp(AstNode* nodep, VAccess access) {
|
||||
if (!m_monitorOffVarp) {
|
||||
m_monitorOffVarp = new AstVar{nodep->fileline(), AstVarType::MODULETEMP,
|
||||
"__VmonitorOff", nodep->findBitDType()};
|
||||
v3Global.rootp()->dollarUnitPkgAddp()->addStmtp(m_monitorOffVarp);
|
||||
}
|
||||
const auto varrefp = new AstVarRef(nodep->fileline(), m_monitorOffVarp, access);
|
||||
varrefp->classOrPackagep(v3Global.rootp()->dollarUnitPkgAddp());
|
||||
return varrefp;
|
||||
}
|
||||
AstNode* newIfAssertOn(AstNode* nodep, bool force) {
|
||||
// Add a internal if to check assertions are on.
|
||||
// Don't make this a AND term, as it's unlikely to need to test this.
|
||||
FileLine* fl = nodep->fileline();
|
||||
AstNode* newp
|
||||
= new AstIf(fl,
|
||||
// If assertions are off, have constant propagation rip them out later
|
||||
// This allows syntax errors and such to be detected normally.
|
||||
(v3Global.opt.assertOn()
|
||||
? static_cast<AstNode*>(new AstCMath(fl, "Verilated::assertOn()", 1))
|
||||
: static_cast<AstNode*>(new AstConst(fl, AstConst::LogicFalse()))),
|
||||
nodep, nullptr);
|
||||
AstNode* newp = new AstIf(
|
||||
fl,
|
||||
(force ? new AstConst(fl, AstConst::BitTrue())
|
||||
: // If assertions are off, have constant propagation rip them out later
|
||||
// This allows syntax errors and such to be detected normally.
|
||||
(v3Global.opt.assertOn()
|
||||
? static_cast<AstNode*>(new AstCMath(fl, "Verilated::assertOn()", 1))
|
||||
: static_cast<AstNode*>(new AstConst(fl, AstConst::BitFalse())))),
|
||||
nodep, nullptr);
|
||||
newp->user1(true); // Don't assert/cover this if
|
||||
return newp;
|
||||
}
|
||||
@@ -91,7 +115,7 @@ private:
|
||||
|
||||
AstNode* newFireAssert(AstNode* nodep, const string& message) {
|
||||
AstNode* bodysp = newFireAssertUnchecked(nodep, message);
|
||||
bodysp = newIfAssertOn(bodysp);
|
||||
bodysp = newIfAssertOn(bodysp, false);
|
||||
return bodysp;
|
||||
}
|
||||
|
||||
@@ -131,20 +155,21 @@ private:
|
||||
if (bodysp && passsp) bodysp = bodysp->addNext(passsp);
|
||||
ifp = new AstIf(nodep->fileline(), propp, bodysp, nullptr);
|
||||
bodysp = ifp;
|
||||
} else if (VN_IS(nodep, Assert)) {
|
||||
} else if (VN_IS(nodep, Assert) || VN_IS(nodep, AssertIntrinsic)) {
|
||||
if (nodep->immediate()) {
|
||||
++m_statAsImm;
|
||||
} else {
|
||||
++m_statAsNotImm;
|
||||
}
|
||||
if (passsp) passsp = newIfAssertOn(passsp);
|
||||
if (failsp) failsp = newIfAssertOn(failsp);
|
||||
bool force = VN_IS(nodep, AssertIntrinsic);
|
||||
if (passsp) passsp = newIfAssertOn(passsp, force);
|
||||
if (failsp) failsp = newIfAssertOn(failsp, force);
|
||||
if (!failsp) failsp = newFireAssertUnchecked(nodep, "'assert' failed.");
|
||||
ifp = new AstIf(nodep->fileline(), propp, passsp, failsp);
|
||||
// It's more LIKELY that we'll take the nullptr if clause
|
||||
// than the sim-killing else clause:
|
||||
ifp->branchPred(VBranchPred::BP_LIKELY);
|
||||
bodysp = newIfAssertOn(ifp);
|
||||
bodysp = newIfAssertOn(ifp, force);
|
||||
} else {
|
||||
nodep->v3fatalSrc("Unknown node type");
|
||||
}
|
||||
@@ -207,7 +232,7 @@ private:
|
||||
bool allow_none = nodep->unique0Pragma();
|
||||
|
||||
// Empty case means no property
|
||||
if (!propp) propp = new AstConst(nodep->fileline(), AstConst::LogicFalse());
|
||||
if (!propp) propp = new AstConst(nodep->fileline(), AstConst::BitFalse());
|
||||
|
||||
// Note: if this ends with an 'else', then we don't need to validate that one of the
|
||||
// predicates evaluates to true.
|
||||
@@ -276,7 +301,7 @@ private:
|
||||
}
|
||||
}
|
||||
// Empty case means no property
|
||||
if (!propp) propp = new AstConst(nodep->fileline(), AstConst::LogicFalse());
|
||||
if (!propp) propp = new AstConst(nodep->fileline(), AstConst::BitFalse());
|
||||
|
||||
bool allow_none = has_default || nodep->unique0Pragma();
|
||||
AstNode* ohot
|
||||
@@ -342,13 +367,62 @@ private:
|
||||
} else if (nodep->displayType() == AstDisplayType::DT_ERROR
|
||||
|| nodep->displayType() == AstDisplayType::DT_FATAL) {
|
||||
replaceDisplay(nodep, "%%Error");
|
||||
} else if (nodep->displayType() == AstDisplayType::DT_MONITOR) {
|
||||
nodep->displayType(AstDisplayType::DT_DISPLAY);
|
||||
const auto fl = nodep->fileline();
|
||||
const auto monNum = ++m_monitorNum;
|
||||
// Where $monitor was we do "__VmonitorNum = N;"
|
||||
const auto newsetp = new AstAssign{fl, newMonitorNumVarRefp(nodep, VAccess::WRITE),
|
||||
new AstConst{fl, monNum}};
|
||||
nodep->replaceWith(newsetp);
|
||||
// Add "always_comb if (__VmonitorOn && __VmonitorNum==N) $display(...);"
|
||||
AstNode* stmtsp = nodep;
|
||||
AstIf* ifp = new AstIf{
|
||||
fl,
|
||||
new AstLogAnd{fl, new AstLogNot{fl, newMonitorOffVarRefp(nodep, VAccess::READ)},
|
||||
new AstEq{fl, new AstConst{fl, monNum},
|
||||
newMonitorNumVarRefp(nodep, VAccess::READ)}},
|
||||
stmtsp, nullptr};
|
||||
ifp->branchPred(VBranchPred::BP_UNLIKELY);
|
||||
AstNode* newp = new AstAlwaysPostponed{fl, ifp};
|
||||
m_modp->addStmtp(newp);
|
||||
} else if (nodep->displayType() == AstDisplayType::DT_STROBE) {
|
||||
nodep->displayType(AstDisplayType::DT_DISPLAY);
|
||||
// Need one-shot
|
||||
const auto fl = nodep->fileline();
|
||||
const auto varp
|
||||
= new AstVar{fl, AstVarType::MODULETEMP, "__Vstrobe" + cvtToStr(m_modStrobeNum++),
|
||||
nodep->findBitDType()};
|
||||
m_modp->addStmtp(varp);
|
||||
// Where $strobe was we do "__Vstrobe = '1;"
|
||||
const auto newsetp = new AstAssign{fl, new AstVarRef{fl, varp, VAccess::WRITE},
|
||||
new AstConst{fl, AstConst::BitTrue{}}};
|
||||
nodep->replaceWith(newsetp);
|
||||
// Add "always_comb if (__Vstrobe) begin $display(...); __Vstrobe = '0; end"
|
||||
AstNode* stmtsp = nodep;
|
||||
AstIf* ifp = new AstIf{fl, new AstVarRef{fl, varp, VAccess::READ}, stmtsp, nullptr};
|
||||
ifp->branchPred(VBranchPred::BP_UNLIKELY);
|
||||
AstNode* newp = new AstAlwaysPostponed{fl, ifp};
|
||||
stmtsp->addNext(new AstAssign{fl, new AstVarRef{fl, varp, VAccess::WRITE},
|
||||
new AstConst{fl, AstConst::BitFalse{}}});
|
||||
m_modp->addStmtp(newp);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void visit(AstMonitorOff* nodep) override {
|
||||
const auto newp
|
||||
= new AstAssign(nodep->fileline(), newMonitorOffVarRefp(nodep, VAccess::WRITE),
|
||||
new AstConst(nodep->fileline(), AstConst::BitTrue{}, nodep->off()));
|
||||
nodep->replaceWith(newp);
|
||||
VL_DO_DANGLING(pushDeletep(nodep), nodep);
|
||||
}
|
||||
virtual void visit(AstAssert* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
newPslAssertion(nodep, nodep->failsp());
|
||||
}
|
||||
virtual void visit(AstAssertIntrinsic* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
newPslAssertion(nodep, nodep->failsp());
|
||||
}
|
||||
virtual void visit(AstCover* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
newPslAssertion(nodep, nullptr);
|
||||
@@ -362,9 +436,11 @@ private:
|
||||
virtual void visit(AstNodeModule* nodep) override {
|
||||
VL_RESTORER(m_modp);
|
||||
VL_RESTORER(m_modPastNum);
|
||||
VL_RESTORER(m_modStrobeNum);
|
||||
{
|
||||
m_modp = nodep;
|
||||
m_modPastNum = 0;
|
||||
m_modStrobeNum = 0;
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -6,7 +6,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2005-2020 by Wilson Snyder. This program is free software; you
|
||||
// Copyright 2005-2021 by Wilson Snyder. This program is free software; you
|
||||
// can redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
//============================================================================
|
||||
|
||||
class V3Assert {
|
||||
class V3Assert final {
|
||||
public:
|
||||
static void assertAll(AstNetlist* nodep);
|
||||
};
|
||||
|
||||
+7
-7
@@ -6,7 +6,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2005-2020 by Wilson Snyder. This program is free software; you
|
||||
// Copyright 2005-2021 by Wilson Snyder. This program is free software; you
|
||||
// can redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -26,7 +26,7 @@
|
||||
//######################################################################
|
||||
// Assert class functions
|
||||
|
||||
class AssertPreVisitor : public AstNVisitor {
|
||||
class AssertPreVisitor final : public AstNVisitor {
|
||||
// Removes clocks and other pre-optimizations
|
||||
// Eventually inlines calls to sequences, properties, etc.
|
||||
// We're not parsing the tree, or anything more complicated.
|
||||
@@ -103,7 +103,7 @@ private:
|
||||
AstNode* past = new AstPast(fl, exprp, nullptr);
|
||||
past->dtypeFrom(exprp);
|
||||
exprp = new AstAnd(fl, past, new AstNot(fl, exprp->cloneTree(false)));
|
||||
exprp->dtypeSetLogicBool();
|
||||
exprp->dtypeSetBit();
|
||||
nodep->replaceWith(exprp);
|
||||
nodep->sentreep(newSenTree(nodep));
|
||||
VL_DO_DANGLING(pushDeletep(nodep), nodep);
|
||||
@@ -122,7 +122,7 @@ private:
|
||||
AstNode* past = new AstPast(fl, exprp, nullptr);
|
||||
past->dtypeFrom(exprp);
|
||||
exprp = new AstAnd(fl, new AstNot(fl, past), exprp->cloneTree(false));
|
||||
exprp->dtypeSetLogicBool();
|
||||
exprp->dtypeSetBit();
|
||||
nodep->replaceWith(exprp);
|
||||
nodep->sentreep(newSenTree(nodep));
|
||||
VL_DO_DANGLING(pushDeletep(nodep), nodep);
|
||||
@@ -135,7 +135,7 @@ private:
|
||||
AstNode* past = new AstPast(fl, exprp, nullptr);
|
||||
past->dtypeFrom(exprp);
|
||||
exprp = new AstEq(fl, past, exprp->cloneTree(false));
|
||||
exprp->dtypeSetLogicBool();
|
||||
exprp->dtypeSetBit();
|
||||
nodep->replaceWith(exprp);
|
||||
nodep->sentreep(newSenTree(nodep));
|
||||
VL_DO_DANGLING(pushDeletep(nodep), nodep);
|
||||
@@ -153,7 +153,7 @@ private:
|
||||
AstNode* past = new AstPast(fl, lhsp, nullptr);
|
||||
past->dtypeFrom(lhsp);
|
||||
AstNode* exprp = new AstOr(fl, new AstNot(fl, past), rhsp);
|
||||
exprp->dtypeSetLogicBool();
|
||||
exprp->dtypeSetBit();
|
||||
nodep->replaceWith(exprp);
|
||||
nodep->sentreep(newSenTree(nodep));
|
||||
VL_DO_DANGLING(pushDeletep(nodep), nodep);
|
||||
@@ -197,7 +197,7 @@ public:
|
||||
// Process
|
||||
iterate(nodep);
|
||||
}
|
||||
virtual ~AssertPreVisitor() override {}
|
||||
virtual ~AssertPreVisitor() override = default;
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user