mirror of
https://github.com/verilator/verilator.git
synced 2026-10-05 09:33:41 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7c79f0d431 | ||
|
|
41b9b30b9b | ||
|
|
1fa82ffb7b | ||
|
|
4f93ac6477 | ||
|
|
f7533010c6 | ||
|
|
47b650d821 | ||
|
|
0c2c097377 | ||
|
|
d721f70690 | ||
|
|
ea8aaa21e8 | ||
|
|
660d1059b0 | ||
|
|
e7dc2de14b | ||
|
|
32100a3c91 | ||
|
|
67f7432dd7 | ||
|
|
59dc2853e3 | ||
|
|
ada58465b2 | ||
|
|
173f57c636 | ||
|
|
1f3e8640f7 | ||
|
|
6039e9dcc3 | ||
|
|
d64f979f99 | ||
|
|
0c53d19113 | ||
|
|
c64a07fd09 | ||
|
|
694919b9d1 | ||
|
|
606b35853b | ||
|
|
26b7452178 | ||
|
|
b51f887567 | ||
|
|
c4b8675d77 | ||
|
|
a7cd7a1ed9 | ||
|
|
a48c779367 | ||
|
|
cf1eccc24f | ||
|
|
d45caca011 | ||
|
|
0722f47539 | ||
|
|
a372e010bd | ||
|
|
530817191e | ||
|
|
1282548a1c | ||
|
|
c7610ed044 | ||
|
|
ffc1c51526 | ||
|
|
b130a8cfeb | ||
|
|
551bd284dd | ||
|
|
9edccfdffa | ||
|
|
1a056f6db9 | ||
|
|
e018eb7bac | ||
|
|
0a91ddf38a | ||
|
|
67bb2c640e | ||
|
|
561eaa311d | ||
|
|
3f7a248ed4 | ||
|
|
ecaa07a72a | ||
|
|
99bdc27be3 | ||
|
|
c3c46967dc | ||
|
|
7f1a9239ab | ||
|
|
c8102c8ffe | ||
|
|
5aa12e9b51 | ||
|
|
829437b20b | ||
|
|
3c4131d45d | ||
|
|
ae8d8ee1ac | ||
|
|
89ec3d16dc | ||
|
|
7602c983c5 | ||
|
|
560efb2c9e | ||
|
|
c2328ef46a | ||
|
|
f6035447ae | ||
|
|
38438b3373 | ||
|
|
71dedccbbe | ||
|
|
cddbe4642f | ||
|
|
bdfdc737a0 | ||
|
|
3d045c3aee | ||
|
|
9583f152ee | ||
|
|
5b2755d28d | ||
|
|
9378259779 | ||
|
|
3d762282b9 | ||
|
|
30783e6a79 | ||
|
|
aa86c777f4 | ||
|
|
a2792785fe | ||
|
|
267315e7d4 | ||
|
|
99d39cb6ff | ||
|
|
915ceb2d04 | ||
|
|
49c90ecbce | ||
|
|
8395004d25 | ||
|
|
5de1c619c8 | ||
|
|
a6d678d41d | ||
|
|
2b91d764b5 | ||
|
|
62337bb6ac | ||
|
|
9abab2c366 | ||
|
|
b22e368b25 | ||
|
|
a9cd2998e5 | ||
|
|
f1ea30f257 | ||
|
|
0b74e9b354 | ||
|
|
8189416d0c | ||
|
|
5f0e1fae7f | ||
|
|
880a9be3b1 | ||
|
|
7bfc1a00a7 | ||
|
|
baff64a43d | ||
|
|
b7f2bb0e80 | ||
|
|
08e0a397d3 | ||
|
|
5f333be947 | ||
|
|
f5f4e15ce2 | ||
|
|
fbd568dc47 | ||
|
|
c79ea88576 | ||
|
|
9be4e7b576 | ||
|
|
33105f017c | ||
|
|
e02f97854c | ||
|
|
960d0de361 | ||
|
|
31ce1fdfd3 | ||
|
|
9821381059 | ||
|
|
3f7bf3d2dc | ||
|
|
f9e69984ff | ||
|
|
b1b5b5dfe2 | ||
|
|
c7440b250f | ||
|
|
bab8462789 | ||
|
|
4eaa6fdd06 | ||
|
|
38b2845e2a | ||
|
|
14d24213a8 | ||
|
|
c61258c0d0 | ||
|
|
47226236f4 | ||
|
|
e744c21f56 | ||
|
|
89a0632ecc | ||
|
|
dcc05db7f1 | ||
|
|
90fb2e5487 | ||
|
|
b5ce7d5982 | ||
|
|
f211616a4c | ||
|
|
a9cb9bac21 | ||
|
|
ae005434e4 | ||
|
|
ef87d057fc | ||
|
|
181b9a5795 | ||
|
|
9baf9c55c2 | ||
|
|
e29132377e | ||
|
|
999751c422 | ||
|
|
22656d6fdd | ||
|
|
ef0c5fd772 | ||
|
|
90c61c79d6 | ||
|
|
4ba3bff87f | ||
|
|
c3dd6f5344 | ||
|
|
321880f5a6 | ||
|
|
3737d209f6 | ||
|
|
29c4b0a141 | ||
|
|
956f64c6ba | ||
|
|
c2d18d8ae4 | ||
|
|
5b9806ae6d | ||
|
|
665fa140a8 | ||
|
|
32f843a214 | ||
|
|
72a3c756ad | ||
|
|
47069dfe52 | ||
|
|
43a84d7ad8 | ||
|
|
b6ca2a42f2 | ||
|
|
e52a4ac74f | ||
|
|
decfa6bd7a | ||
|
|
8931bd37e2 | ||
|
|
4b79d23d00 | ||
|
|
77fe7c426e | ||
|
|
331c2244fc | ||
|
|
5a3eab634a | ||
|
|
77e68acf54 | ||
|
|
7a355d448a | ||
|
|
3b7ad1820d | ||
|
|
d3b63b2653 | ||
|
|
046896e60a | ||
|
|
fb9119ff49 | ||
|
|
818aaa8b89 | ||
|
|
26bdfc3474 | ||
|
|
0e91d8a10e | ||
|
|
434c3c3ef3 | ||
|
|
21e05c43dd | ||
|
|
0e154b35ef | ||
|
|
e6554e061c | ||
|
|
0f004c8e7b | ||
|
|
f5b1a5cd58 | ||
|
|
48a098b041 | ||
|
|
f8c0169e82 | ||
|
|
539c9d4c63 | ||
|
|
b4d8220cbb | ||
|
|
5eded789aa | ||
|
|
e931c6230a | ||
|
|
64a6e1ac8b | ||
|
|
50094ca296 | ||
|
|
15b32dc140 | ||
|
|
441ecfedc9 | ||
|
|
78147ee8d7 | ||
|
|
8c58612a3b | ||
|
|
56f9d244de | ||
|
|
2ba9eb4228 | ||
|
|
9a8c878f2d | ||
|
|
41a563bdc8 | ||
|
|
4e5f30858b | ||
|
|
b989ac6db5 | ||
|
|
4d1f4bbf49 | ||
|
|
e9ad665d32 | ||
|
|
78052f87bd | ||
|
|
ebf5c11e03 | ||
|
|
7e355e211c | ||
|
|
f36461e696 | ||
|
|
88d7ca01b0 | ||
|
|
2e2b82c052 | ||
|
|
f1bb0544be | ||
|
|
3b1371124e | ||
|
|
e6857df5c6 | ||
|
|
73374a0303 | ||
|
|
e334740dd6 | ||
|
|
84ee833ea7 | ||
|
|
b7ad1e6d61 | ||
|
|
340efe3a3a | ||
|
|
2342549caf | ||
|
|
028737cde8 | ||
|
|
bf972963f4 | ||
|
|
9bda91b3bf | ||
|
|
e4c5eb5e69 | ||
|
|
2e8cc22c54 | ||
|
|
655910d486 | ||
|
|
2a0ec88379 | ||
|
|
80859a609a | ||
|
|
d679d50eca | ||
|
|
65de118e51 | ||
|
|
4cd56b1fb9 | ||
|
|
f3945e7c02 | ||
|
|
5ef982b4b5 | ||
|
|
f96d336b97 | ||
|
|
a68a4fc888 | ||
|
|
0c3ffa1841 | ||
|
|
24a0d2a0c9 | ||
|
|
ca42be982c | ||
|
|
ffc31e2efa | ||
|
|
8952aa59ff | ||
|
|
2966f03042 | ||
|
|
d15e9e2b7a | ||
|
|
fd45be3def | ||
|
|
0658a7654f | ||
|
|
7526151670 | ||
|
|
560b59f97f | ||
|
|
b2ca89c185 | ||
|
|
1de2de4bde | ||
|
|
4135867e53 | ||
|
|
ff425369ac | ||
|
|
30ccccdb67 | ||
|
|
5e3016f34a | ||
|
|
f775feb7f0 | ||
|
|
0a94ea5386 | ||
|
|
aa8423ba46 | ||
|
|
d753f36ebc | ||
|
|
55976dbc25 | ||
|
|
77c005835d | ||
|
|
6b0601fd54 | ||
|
|
c1652979d5 | ||
|
|
740fee660e | ||
|
|
984ee624ed | ||
|
|
00ef0519f5 | ||
|
|
59d170c6f8 | ||
|
|
9a722ccf62 | ||
|
|
748fa4cb80 | ||
|
|
694cf371f9 | ||
|
|
8696e38e6f | ||
|
|
706162ecc6 | ||
|
|
c3f17ce2c4 | ||
|
|
41f29d2ce3 | ||
|
|
7b119a594f | ||
|
|
b7d20b102b | ||
|
|
ac05a779ae | ||
|
|
935032366f | ||
|
|
1160dddc6d | ||
|
|
293a5f402b | ||
|
|
ca09f73446 | ||
|
|
e814855357 | ||
|
|
692306ef44 | ||
|
|
ffdc0afe5f | ||
|
|
98037cad56 | ||
|
|
61e3536163 | ||
|
|
a1a186a86c | ||
|
|
04e0c7e4f1 | ||
|
|
833686446c | ||
|
|
c6dae40cf6 | ||
|
|
cd737065f2 | ||
|
|
010084201a | ||
|
|
60f7eff701 | ||
|
|
d1862e25eb | ||
|
|
b0018fd680 | ||
|
|
2742a8c813 | ||
|
|
05e12ab60e | ||
|
|
9bda2cb4ad | ||
|
|
393b9e435d | ||
|
|
e87a726989 | ||
|
|
62387a0e32 | ||
|
|
31079ca8b5 | ||
|
|
4184ad1921 | ||
|
|
e7ebe0e280 | ||
|
|
c14bbb9421 | ||
|
|
b1b92b7dd4 | ||
|
|
a14394dbb5 | ||
|
|
96b7831243 | ||
|
|
1e440765c0 | ||
|
|
2ccf49031b | ||
|
|
0abc856be9 | ||
|
|
d2a8fa7440 | ||
|
|
106d635d0f | ||
|
|
cff9f8143e | ||
|
|
cfa401e01d | ||
|
|
d6195e354f | ||
|
|
c0892dd11c | ||
|
|
899de9a282 | ||
|
|
4b593f8eb3 | ||
|
|
28b6e79cf7 | ||
|
|
fe5822ba54 | ||
|
|
c496649c49 | ||
|
|
37e3c6da70 | ||
|
|
4cb5c1e1db | ||
|
|
b7a7504ba5 | ||
|
|
3a5cbd5b67 | ||
|
|
27883b52d6 | ||
|
|
b95ee84343 | ||
|
|
185e5d8f42 | ||
|
|
987ce927eb | ||
|
|
b08c694cd6 | ||
|
|
e69a8e838d | ||
|
|
61612582e6 | ||
|
|
8b00939f0c | ||
|
|
da5644211f | ||
|
|
c1d7bfa617 | ||
|
|
c26ce25cea | ||
|
|
758264dc77 | ||
|
|
304697d133 | ||
|
|
fdbf465eda | ||
|
|
90102d9867 | ||
|
|
a1bb471aca | ||
|
|
4ef37d9411 | ||
|
|
f3b10df454 | ||
|
|
f5a226a183 | ||
|
|
5515eed0b6 | ||
|
|
381c87a1eb | ||
|
|
20e896ec21 | ||
|
|
70603bb752 | ||
|
|
7cb6dc664e | ||
|
|
dae9fa5053 | ||
|
|
aa1a0b0f13 | ||
|
|
371bf01957 | ||
|
|
ef7759a522 | ||
|
|
0ef9087f89 | ||
|
|
00059987a1 |
@@ -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/blob/master/docs/CONTRIBUTING.rst)
|
||||
about: Use this to report that 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.rst)
|
||||
title: ''
|
||||
labels: new
|
||||
assignees: ''
|
||||
@@ -13,4 +13,6 @@ Can you attach an example that shows the issue? (Must be openly licensed, ideal
|
||||
|
||||
What 'verilator --version' are you using? Did you try it with the git master version?
|
||||
|
||||
Would you be willing to try to fix Verilator yourself with assistance?
|
||||
What OS and distribution are you using?
|
||||
|
||||
May we assist you in trying to fix this in Verilator yourself?
|
||||
|
||||
@@ -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/blob/master/docs/CONTRIBUTING.rst)
|
||||
about: Use this to request something should be supported, or a new feature added. (Note our contributor agreement at https://github.com/verilator/verilator/blob/master/docs/CONTRIBUTING.rst)
|
||||
title: ''
|
||||
labels: new
|
||||
assignees: ''
|
||||
@@ -13,4 +13,4 @@ What would you like added/supported?
|
||||
|
||||
Can you attach an example that runs on other simulators? (Must be openly licensed, ideally in test_regress format.)
|
||||
|
||||
May we assist you in trying to fix this yourself?
|
||||
May we assist you in trying to fix this in Verilator yourself?
|
||||
|
||||
@@ -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/blob/master/docs/CONTRIBUTING.rst)
|
||||
about: Use this to ask a question, not related to a specific bug nor feature request. (Note our contributor agreement at https://github.com/verilator/verilator/blob/master/docs/CONTRIBUTING.rst)
|
||||
title: ''
|
||||
labels: new
|
||||
assignees: ''
|
||||
|
||||
@@ -29,7 +29,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-20.04, ubuntu-18.04]
|
||||
os: [ubuntu-22.04, ubuntu-20.04, ubuntu-18.04]
|
||||
compiler:
|
||||
- { cc: clang, cxx: clang++ }
|
||||
- { cc: gcc, cxx: g++ }
|
||||
@@ -37,9 +37,16 @@ jobs:
|
||||
exclude:
|
||||
# Build pull requests only with ubuntu-20.04 and without m32
|
||||
- os: ${{ github.event_name == 'pull_request' && 'ubuntu-18.04' || 'do-not-exclude' }}
|
||||
- os: ${{ github.event_name == 'pull_request' && 'ubuntu-22.04' || 'do-not-exclude' }}
|
||||
- m32: ${{ github.event_name == 'pull_request' && 1 || 'do-not-exclude' }}
|
||||
# Build -m32 only on ubuntu-20.04
|
||||
- {os: ubuntu-18.04, m32: 1}
|
||||
- {os: ubuntu-22.04, m32: 1}
|
||||
include:
|
||||
# Build GCC 10 on ubuntu-20.04
|
||||
- os: ubuntu-20.04
|
||||
compiler: { cc: gcc-10, cxx: g++-10 }
|
||||
m32: 0
|
||||
runs-on: ${{ matrix.os }}
|
||||
name: Build | ${{ matrix.os }} | ${{ matrix.compiler.cc }} ${{ matrix.m32 && '| -m32' || '' }}
|
||||
env:
|
||||
@@ -90,7 +97,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-20.04, ubuntu-18.04]
|
||||
os: [ubuntu-22.04, ubuntu-20.04, ubuntu-18.04]
|
||||
compiler:
|
||||
- { cc: clang, cxx: clang++ }
|
||||
- { cc: gcc, cxx: g++ }
|
||||
@@ -99,9 +106,18 @@ jobs:
|
||||
exclude:
|
||||
# Build pull requests only with ubuntu-20.04 and without m32
|
||||
- os: ${{ github.event_name == 'pull_request' && 'ubuntu-18.04' || 'do-not-exclude' }}
|
||||
- os: ${{ github.event_name == 'pull_request' && 'ubuntu-22.04' || 'do-not-exclude' }}
|
||||
- m32: ${{ github.event_name == 'pull_request' && 1 || 'do-not-exclude' }}
|
||||
# Build -m32 only on ubuntu-20.04
|
||||
- {os: ubuntu-18.04, m32: 1}
|
||||
- {os: ubuntu-22.04, m32: 1}
|
||||
include:
|
||||
# Test with GCC 10 on ubuntu-20.04 without m32
|
||||
- {os: ubuntu-20.04, compiler: { cc: gcc-10, cxx: g++-10 }, m32: 0, suite: dist-vlt-0}
|
||||
- {os: ubuntu-20.04, compiler: { cc: gcc-10, cxx: g++-10 }, m32: 0, suite: dist-vlt-1}
|
||||
- {os: ubuntu-20.04, compiler: { cc: gcc-10, cxx: g++-10 }, m32: 0, suite: dist-vlt-2}
|
||||
- {os: ubuntu-20.04, compiler: { cc: gcc-10, cxx: g++-10 }, m32: 0, suite: vltmt-0}
|
||||
- {os: ubuntu-20.04, compiler: { cc: gcc-10, cxx: g++-10 }, m32: 0, suite: vltmt-1}
|
||||
runs-on: ${{ matrix.os }}
|
||||
name: Test | ${{ matrix.os }} | ${{ matrix.compiler.cc }} | ${{ matrix.suite }} ${{ matrix.m32 && '| -m32' || '' }}
|
||||
env:
|
||||
@@ -110,7 +126,7 @@ jobs:
|
||||
CI_M32: ${{ matrix.m32 }}
|
||||
CC: ${{ matrix.compiler.cc }}
|
||||
CXX: ${{ matrix.compiler.cxx }}
|
||||
CACHE_BASE_KEY: test-${{ matrix.os }}-${{ matrix.compiler.cc }}-m32=${{ matrix.m32 }}-${ matrix.suite }}
|
||||
CACHE_BASE_KEY: test-${{ matrix.os }}-${{ matrix.compiler.cc }}-m32=${{ matrix.m32 }}-${{ matrix.suite }}
|
||||
CCACHE_MAXSIZE: 64M # Per build matrix entry (2160M in total)
|
||||
VERILATOR_ARCHIVE: verilator-${{ github.sha }}-${{ matrix.os }}-${{ matrix.compiler.cc }}${{ matrix.m32 && '-m32' || '' }}.tar.gz
|
||||
steps:
|
||||
|
||||
@@ -39,3 +39,4 @@ verilator-config-version.cmake
|
||||
**/__pycache__/*
|
||||
**/_build/*
|
||||
**/obj_dir/*
|
||||
/.vscode/
|
||||
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
set noparent
|
||||
linelength=100
|
||||
filter=-build/c++11
|
||||
filter=-build/header_guard
|
||||
filter=-build/include_order
|
||||
filter=-build/include_subdir
|
||||
filter=-readability/inheritance
|
||||
filter=-readability/nolint
|
||||
filter=-readability/todo
|
||||
filter=-runtime/references
|
||||
filter=-whitespace/blank_line
|
||||
filter=-whitespace/empty_if_body
|
||||
filter=-whitespace/indent
|
||||
filter=-whitespace/newline
|
||||
filter=-whitespace/braces
|
||||
filter=-whitespace/parens
|
||||
filter=-whitespace/todo
|
||||
@@ -8,10 +8,165 @@ The changes in each Verilator version are described below. The
|
||||
contributors that suggested a given feature are shown in []. Thanks!
|
||||
|
||||
|
||||
Verilator 4.224 2022-06-19
|
||||
==========================
|
||||
|
||||
**Major:**
|
||||
|
||||
* VCD tracing is now parallelized with --threads (#3449). [Geza Lore, Shunyao CAD]
|
||||
|
||||
**Minor:**
|
||||
|
||||
* Add -f<optimization> options to replace -O<letter> options (#3436).
|
||||
* Changed --no-merge-const-pool to -fno-merge-const-pool (#3436).
|
||||
* Changed --no-decoration to remove output whitespace (#3460). [Kamil Rakoczy]
|
||||
* Support compile time trace signal selection with tracing_on/off (#3323). [Shunyao CAD]
|
||||
* Support non-ANSI interface port declarations (#3439). [Geza Lore, Shunyao CAD]
|
||||
* Support concat assignment to packed array (#3446).
|
||||
* Improve conditional merging optimization (#3125). [Geza Lore, Shunyao CAD]
|
||||
* Define VM_TRACE_VCD when tracing in VCD format. [Geza Lore, Shunyao CAD]
|
||||
* Add assert when VerilatedContext is mis-deleted (#3121). [Rupert Swarbrick]
|
||||
* Internal prep work towards timing control. [Krzysztof Bieganski]
|
||||
* Fix hang with large case statement optimization (#3405). [Mike Urbach]
|
||||
* Fix UNOPTFLAT warning from initial static var (#3406). [Kamil Rakoczy]
|
||||
* Fix compile error when enable VL_LEAK_CHECKS (#3411). [HungMingWu]
|
||||
* Fix cmake rules to support higher-level targets (#3377) (#3386). [Martin Stadler]
|
||||
* Fix BLKANDNBLK on $readmem/$writemem (#3379). [Alex Solomatnikov]
|
||||
* Fix 'with' operator with type casting (#3387). [xiak95]
|
||||
* Fix incorrect conditional merging (#3409). [Raynard Qiao]
|
||||
* Fix passing VL_TRACE_FST_WRITER_THREAD in CMake build. [Geza Lore, Shunyao CAD]
|
||||
* Fix compile error under strict C++11 mode (#3463). [Kevin Kiningham]
|
||||
* Fix public unpacked input ports (#3465). [Todd Strader]
|
||||
|
||||
|
||||
Verilator 4.222 2022-05-02
|
||||
==========================
|
||||
|
||||
**Minor:**
|
||||
|
||||
* Split --prof-threads into --prof-exec and --prof-pgo (#3365). [Geza Lore, Shunyao CAD]
|
||||
* Deprecate 'vluint64_t' and similar types (#3255).
|
||||
* Raise error on assignment to const in initial blocks. [Geza Lore, Shunyao CAD]
|
||||
* Issue INITIALDLY/COMBDLY/BLKSEQ warnings consistent with Verilator execution. [Geza Lore, Shunyao CAD]
|
||||
* Support LoongArch ISA multithreading (#3353) (#3354). [Xi Zhang]
|
||||
* Fix MSVC localtime_s (#3124).
|
||||
* Fix Bison 3.8.2 error (#3366). [elike-ypq]
|
||||
* Fix rare bug in -Oz (V3Localize) (#3286). [Geza Lore, Shunyao CAD]
|
||||
* Fix tracing interfaces inside interfaces (#3309). [Kevin Millis]
|
||||
* Fix filenames with dots overwriting debug .vpp files (#3373).
|
||||
* Fix including VK_USER_OBJS in make library (#3370) (#3382). [Julien Margetts]
|
||||
* Fix hang in generate symbol references (#3391) (#3398). [Yoda Lee]
|
||||
* Fix missing #include <memory> (#3392). [Aliaksei Chapyzhenka]
|
||||
* Fix crash in recursive module inlining (#3393). [david-sawatzke]
|
||||
* Fix --protect-ids mangling names of library methods. [Geza Lore, Shunyao CAD]
|
||||
* Fix foreach segmentation fault (#3400). [Kamil Rakoczy]
|
||||
|
||||
|
||||
Verilator 4.220 2022-03-12
|
||||
==========================
|
||||
|
||||
**Minor:**
|
||||
|
||||
* Removed the deprecated lint_off flag -msg; use -rule instead.
|
||||
* Removed the deprecated "fl" attribute in XML output; use "loc" attribute instead.
|
||||
* Suppress WIDTH warning on negate using carry bit (#3295). [Peter Monsson]
|
||||
* Add trace dumpvars() call for selective runtime tracing (#3322). [Shunyao CAD]
|
||||
* Add VERILATOR_VERSION_INTEGER for determining API (#3343). [Larry Doolittle]
|
||||
* Improve various V3Combine algorithm details (#3328). [Yutetsu TAKATSUKASA]
|
||||
* Improve various V3Order algorithm details. [Geza Lore]
|
||||
* Fix MacOS arm64 build (#3285) (#3291). [Guokai Chen]
|
||||
* Fix signed number operation (#3294) (#3308). [Raynard Qiao]
|
||||
* Fix FST traces to include vector range (#3296) (#3297). [Jamie Iles]
|
||||
* Fix skipping public enum values with four-state values (#3303).
|
||||
* Fix $readmem file not found to be warning not error (#3310). [Alexander Grobman]
|
||||
* Fix class stringification on wide arrays (#3312). [Iru Cai]
|
||||
* Fix $fscanf etc to return -1 on EOF (#3313). [Jose Tejada]
|
||||
* Fix public function arguments that are arrayed (#3316). [pawel256]
|
||||
* Fix unnamedblk error on foreach (#3321). [Aliaksei Chapyzhenka]
|
||||
* Fix crash in recursive module inlining (#3324). [Larry Doolittle]
|
||||
* Fix VL_RESTORER behavior on passing a lvalue reference (#3326). [HungMingWu]
|
||||
* Fix compile error with --trace-fst --sc (#3332). [leavinel]
|
||||
* Fix cast to array types (#3333). [Todd Strader]
|
||||
* Fix Vdeeptemp error with --threads and --compiler clang (#3338). [Per Karlsson]
|
||||
|
||||
|
||||
Verilator 4.218 2022-01-17
|
||||
==========================
|
||||
|
||||
**Major:**
|
||||
|
||||
* Primary inputs and outputs (VL_INW/VL_OUTW) now use VlWide type.
|
||||
In general this should be backward compatible, but may lead to some
|
||||
wrapper code needing changes.
|
||||
* Option --cdc is deprecated and is planned for removal,
|
||||
file a bug if this is still being used.
|
||||
|
||||
**Minor:**
|
||||
|
||||
* Support class static members (#2233).
|
||||
* Support force/release (#2431) (#2593). [Shunyao CAD]
|
||||
* Add 'forceable' attribute to allow forcing from C++. (#3272). [Geza Lore, Shunyao CAD]
|
||||
* Support lower dimension looping in foreach loops (#3172). [Ehab Ibrahim]
|
||||
* Support up to 64 bit enums for .next/.prev/.name (#3244). [Alexander Grobman]
|
||||
* Reduce .rodata footprint of trace initialization (#3250). [Geza Lore, Shunyao CAD]
|
||||
* Support FST tracing in hierarchical Verilation (#3251). [Yutetsu TAKATSUKASA]
|
||||
* Use C++11 standard types for MacOS portability (#3254) (#3257). [Adrien Le Masle]
|
||||
* Fix make support for BSD ar (#2999) (#3256). [Julie Schwartz]
|
||||
* Fix bad ending address on $readmem (#3205). [Julie Schwartz]
|
||||
* Fix MSWIN compile error (#2681). [Unai Martinez-Corral]
|
||||
* Fix break under foreach loop (#3230).
|
||||
* Fix VL_STREAML_FAST_QQI with 64 bit left-hand-side (#3232) (#3235). [Adrien Le Masle]
|
||||
* Fix $sformat of inputs/outputs (#3236). [Adrien Le Masle]
|
||||
* Fix associative array first method as statement (#3228). [Adrien Le Masle]
|
||||
* Fix associative array foreach loop (#3229).
|
||||
* Fix $fclose not accepting expressions (#3237). [Julie Schwartz]
|
||||
* Fix $random not updating seed (#3238). [Julie Schwartz]
|
||||
* Fix top level param overwrite when package has same param (#3241) (#3247). [Adrien Le Masle]
|
||||
* Fix spurious UNUSED by ignoring inout pin connections (#3242). [Julie Schwartz]
|
||||
* Fix splitting of _eval and other top level functions. [Geza Lore, Shunyao CAD]
|
||||
* Fix internal error by inout port (#3258). [Yutetsu TAKATSUKASA]
|
||||
* Fix GCC 11 compile error (#3273). [HungMingWu]
|
||||
|
||||
|
||||
Verilator 4.216 2021-12-05
|
||||
==========================
|
||||
|
||||
**Major:**
|
||||
|
||||
* Add --lib-create, similar to --protect-lib but without protections.
|
||||
* Support tracing through --hierarchical/--lib-create libraries (#3200).
|
||||
|
||||
**Minor:**
|
||||
|
||||
* Internal code cleanups and improvements. [Geza Lore]
|
||||
* Improve --thread Verilation-time performance.
|
||||
* Support task name in $display %m (#3211). [Julie Schwartz]
|
||||
* Make 'bit', 'logic' and 'time' types unsigned by default. [Geza Lore]
|
||||
* Optimize $random concatenates/selects (#3114).
|
||||
* Fix array method names with parenthesis (#3181) (#3183). [Teng Huang]
|
||||
* Fix split_var assign merging (#3177) (#3179). [Yutetsu TAKATSUKASA]
|
||||
* Fix wrong bit op tree optimization (#3185). [Yutetsu TAKATSUKASA]
|
||||
* Fix some SliceSels not being constants (#3186) (#3218). [Michaël Lefebvre]
|
||||
* Fix nested generate if genblk naming (#3189). [yanx21]
|
||||
* Fix hang on recursive definition error (#3199). [Jonathan Kimmitt]
|
||||
* Fix display of signed without format (#3204). [Julie Schwartz]
|
||||
* Fix display of empty string constant (#3207) (#3215). [Julie Schwartz]
|
||||
* Fix incorrect width after and-or optimization (#3208). [Julie Schwartz]
|
||||
* Fix $fopen etc on integer arrays (#3214). [adrienlemasle]
|
||||
* Fix $size on dynamic strings (#3216).
|
||||
* Fix %0 format on $value$plusargs (#3217).
|
||||
* Fix timescale portability on Arm64 (#3222).
|
||||
|
||||
|
||||
Verilator 4.214 2021-10-17
|
||||
==========================
|
||||
|
||||
* Add profile-guided optmization of mtasks (#3150).
|
||||
**Major:**
|
||||
|
||||
* Add profile-guided optimization of mtasks (#3150).
|
||||
|
||||
**Minor:**
|
||||
|
||||
* Verilator_gantt has removed the ASCII graphics, use the VCD output instead.
|
||||
* Verilator_gantt now shows the predicted mtask times, eval times, and additional statistics.
|
||||
* Verilator_gantt data files now include processor information, to allow later processing.
|
||||
@@ -74,7 +229,7 @@ Verilator 4.210 2021-07-07
|
||||
|
||||
* Add --prof-c to pass profiling to compiler (#3059). [Alexander Grobman]
|
||||
* Optimize a lot more model variables into function locals (#3027). [Geza Lore]
|
||||
* Support middle-of-design nested topmodules (#3026). [Dan Petrisko]
|
||||
* Support middle-of-design nested top modules (#3026). [Dan Petrisko]
|
||||
* Remove deprecated --no-relative-cfuncs option (#3024). [Geza Lore]
|
||||
* Remove deprecated --inhibit-sim option (#3035). [Geza Lore]
|
||||
* Merge const static data globally into a new constant pool (#3013). [Geza Lore]
|
||||
@@ -113,10 +268,10 @@ Verilator 4.204 2021-06-12
|
||||
* Fix to emit 'else if' without nesting (#2944). [Geza Lore]
|
||||
* Fix part select issues in LATCH warning (#2948) (#2938). [Julien Margetts]
|
||||
* Fix to not emit empty files with low split limits (#2961). [Geza Lore]
|
||||
* Fix merging of assignments in C++ code (#2970). [Ruper Swarbrick]
|
||||
* Fix merging of assignments in C++ code (#2970). [Rupert Swarbrick]
|
||||
* Fix unused variable warnings (#2991). [Pieter Kapsenberg]
|
||||
* Fix --protect-ids when using SV classes (#2994). [Geza Lore]
|
||||
* Fix constant function calls with uninit value (#2995). [yanx21]
|
||||
* Fix constant function calls with uninitialized value (#2995). [yanx21]
|
||||
* Fix Makefiles to support Windows EXEEXT usage (#3008). [Miodrag Milanovic]
|
||||
|
||||
|
||||
@@ -154,7 +309,7 @@ Verilator 4.202 2021-04-24
|
||||
* Fix Cygwin example compile issues (#2856). [Mark Shaw]
|
||||
* Fix select of with index variable (#2880). [Alexander Grobman]
|
||||
* Fix cmake version number to be numeric (#2881). [Yuri Victorovich]
|
||||
* Fix MinGW not supportting 'localtime_r' (#2882). [HyungKi Jeong]
|
||||
* Fix MinGW not supporting 'localtime_r' (#2882). [HyungKi Jeong]
|
||||
* Fix cast from packed, typedef'ed interface signal (#2884). [Todd Strader]
|
||||
* Fix VPI package reported as vpiModule (#2885). [Todd Strader]
|
||||
* Fix dumping waveforms to multiple FST files (#2889). [David Metz]
|
||||
@@ -301,7 +456,7 @@ Verilator 4.102 2020-10-15
|
||||
* Support # as a comment in -f files (#2497). [phantom-killua]
|
||||
* Support 'this' (#2585). [Rafal Kapuscik]
|
||||
* Support defines for FST tracing (#2592). [Markus Krause]
|
||||
* Support non-overapping implication inside properties (#1292). [Peter Monsson]
|
||||
* Support non-overlapping implication inside properties (#1292). [Peter Monsson]
|
||||
* Fix timescale with --hierarchical (#2554). [Yutetsu TAKATSUKASA]
|
||||
* Fix cmake build with --hierarchical (#2560). [Yutetsu TAKATSUKASA]
|
||||
* Fix -G dropping public indication (#2561). [Andrew Goessling]
|
||||
@@ -327,7 +482,7 @@ Verilator 4.100 2020-09-07
|
||||
* Support (with limitations) class extern, class extends, virtual class.
|
||||
* Support $urandom, $urandom_range without stability.
|
||||
* Support assume property. [Peter Monsson]
|
||||
* Support non-overapping implication inside properties (#1292). [Peter Monsson]
|
||||
* Support non-overlapping implication inside properties (#1292). [Peter Monsson]
|
||||
* Fix false DECLFILENAME on black-boxed modules (#2430). [Philipp Wagner]
|
||||
* Fix naming of "id : begin" blocks.
|
||||
* Fix class constructor error on assignments to const.
|
||||
@@ -3727,7 +3882,7 @@ Verilator 0.0 1994-07-08
|
||||
Copyright
|
||||
=========
|
||||
|
||||
Copyright 2001-2021 by Wilson Snyder. This program is free software; you
|
||||
Copyright 2001-2022 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
@@ -7,7 +7,7 @@
|
||||
#
|
||||
#*****************************************************************************
|
||||
#
|
||||
# Copyright 2003-2021 by Wilson Snyder. This program is free software; you
|
||||
# Copyright 2003-2022 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.
|
||||
|
||||
+13
-12
@@ -21,7 +21,7 @@ Welcome to Verilator
|
||||
.. list-table::
|
||||
|
||||
* - **Welcome to Verilator, the fastest Verilog/SystemVerilog simulator.**
|
||||
* Accepts synthesizable Verilog or SystemVerilog
|
||||
* Accepts Verilog or SystemVerilog
|
||||
* Performs lint code-quality checks
|
||||
* Compiles into multithreaded C++, or SystemC
|
||||
* Creates XML to front-end your own tools
|
||||
@@ -57,23 +57,24 @@ files, the "Verilated" code.
|
||||
|
||||
The user writes a little C++/SystemC wrapper file, which instantiates the
|
||||
"Verilated" model of the user's top level module. These C++/SystemC files
|
||||
are then compiled by a C++ compiler (gcc/clang/MSVC++). The resulting
|
||||
executable performs the design simulation. Verilator also supports linking
|
||||
its generated libraries, optionally encrypted, into other simulators.
|
||||
are then compiled by a C++ compiler (gcc/clang/MSVC++). Executing the
|
||||
resulting executable performs the design simulation. Verilator also
|
||||
supports linking Verilated generated libraries, optionally encrypted, into
|
||||
other simulators.
|
||||
|
||||
Verilator may not be the best choice if you are expecting a full featured
|
||||
replacement for NC-Verilog, VCS or another commercial Verilog simulator, or
|
||||
if you are looking for a behavioral Verilog simulator e.g. for a quick
|
||||
class project (we recommend `Icarus Verilog`_ for this.) However, if you
|
||||
are looking for a path to migrate SystemVerilog to C++ or SystemC, or your
|
||||
team is comfortable writing just a touch of C++ code, Verilator is the tool
|
||||
for you.
|
||||
replacement for Incisive, ModelSim/Questa, VCS or another commercial
|
||||
Verilog simulator, or if you are looking for a behavioral Verilog simulator
|
||||
e.g. for a quick class project (we recommend `Icarus Verilog`_ for this.)
|
||||
However, if you are looking for a path to migrate SystemVerilog to C++ or
|
||||
SystemC, or your team is comfortable writing just a touch of C++ code,
|
||||
Verilator is the tool for you.
|
||||
|
||||
|
||||
Performance
|
||||
===========
|
||||
|
||||
Verilator does not simply convert Verilog HDL to C++ or SystemC. Rather,
|
||||
Verilator does not directly translate Verilog HDL to C++ or SystemC. Rather,
|
||||
Verilator compiles your code into a much faster optimized and optionally
|
||||
thread-partitioned model, which is in turn wrapped inside a C++/SystemC
|
||||
module. The results are a compiled Verilog model that executes even on a
|
||||
@@ -137,7 +138,7 @@ Related Projects
|
||||
Open License
|
||||
============
|
||||
|
||||
Verilator is Copyright 2003-2021 by Wilson Snyder. (Report bugs to
|
||||
Verilator is Copyright 2003-2022 by Wilson Snyder. (Report bugs to
|
||||
`Verilator Issues <https://verilator.org/issues>`_.)
|
||||
|
||||
Verilator is free software; you can redistribute it and/or modify it under
|
||||
|
||||
+12
-10
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env perl
|
||||
######################################################################
|
||||
#
|
||||
# Copyright 2003-2021 by Wilson Snyder. This program is free software; you
|
||||
# Copyright 2003-2022 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.
|
||||
@@ -319,6 +319,7 @@ detailed descriptions of these arguments.
|
||||
-f <file> Parse arguments from a file
|
||||
-FI <file> Force include of a file
|
||||
--flatten Force inlining of all modules, tasks and functions
|
||||
-fno-<optimization> Disable internal optimization stage
|
||||
-G<name>=<value> Overwrite top-level parameter
|
||||
--gdb Run Verilator under GDB interactively
|
||||
--gdbbt Run Verilator under GDB for backtrace
|
||||
@@ -336,6 +337,7 @@ detailed descriptions of these arguments.
|
||||
-LDFLAGS <flags> Linker pre-object arguments for makefile
|
||||
--l2-name <value> Verilog scope name of the top module
|
||||
--language <lang> Default language standard to parse
|
||||
--lib-create <name> Create a DPI library
|
||||
+libext+<ext>+[ext]... Extensions for finding modules
|
||||
--lint-only Lint, but do not make output
|
||||
-MAKEFLAGS <flags> Arguments to pass to make during --build
|
||||
@@ -343,11 +345,10 @@ detailed descriptions of these arguments.
|
||||
--MMD Create .d dependency files
|
||||
--MP Create phony dependency targets
|
||||
--Mdir <directory> Name of output object directory
|
||||
--no-merge-const-pool Disable merging of different types in const pool
|
||||
--mod-prefix <topname> Name to prepend to lower classes
|
||||
--no-clk <signal-name> Prevent marking specified signal as clock
|
||||
--no-decoration Disable comments and symbol decorations
|
||||
--no-pins64 Don't use vluint64_t's for 33-64 bit sigs
|
||||
--no-pins64 Don't use uint64_t's for 33-64 bit sigs
|
||||
--no-skip-identical Disable skipping identical output
|
||||
+notimingchecks Ignored
|
||||
-O0 Disable optimizations
|
||||
@@ -369,7 +370,8 @@ detailed descriptions of these arguments.
|
||||
--prefix <topname> Name of top level class
|
||||
--prof-c Compile C++ code with profiling
|
||||
--prof-cfuncs Name functions for profiling
|
||||
--prof-threads Enable generating gantt chart data for threads
|
||||
--prof-exec Enable generating execution profile for gantt chart
|
||||
--prof-pgo Enable generating profiling data for PGO
|
||||
--protect-key <key> Key for symbol protection
|
||||
--protect-ids Hash identifier names for obscurity
|
||||
--protect-lib <name> Create a DPI protected library
|
||||
@@ -403,7 +405,7 @@ detailed descriptions of these arguments.
|
||||
--trace-max-width <width> Maximum array depth for tracing
|
||||
--trace-params Enable tracing of parameters
|
||||
--trace-structs Enable tracing structure names
|
||||
--trace-threads <threads> Enable waveform creation on separate threads
|
||||
--trace-threads <threads> Enable FST waveform creation on separate threads
|
||||
--trace-underscore Enable tracing of _signals
|
||||
-U<var> Undefine preprocessor define
|
||||
--unroll-count <loops> Tune maximum loop iterations
|
||||
@@ -444,10 +446,10 @@ description of these arguments.
|
||||
+verilator+error+limit+<value> Set error limit
|
||||
+verilator+help Display help
|
||||
+verilator+noassert Disable assert checking
|
||||
+verilator+prof+threads+file+<filename> Set profile filename
|
||||
+verilator+prof+threads+start+<value> Set profile starting point
|
||||
+verilator+prof+threads+window+<value> Set profile duration
|
||||
+verilator+prof+vlt+file+<filename> Set profile guided filename
|
||||
+verilator+prof+exec+file+<filename> Set execution profile filename
|
||||
+verilator+prof+exec+start+<value> Set execution profile starting point
|
||||
+verilator+prof+exec+window+<value> Set execution profile duration
|
||||
+verilator+prof+vlt+file+<filename> Set PGO profile filename
|
||||
+verilator+rand+reset+<value> Set random reset technique
|
||||
+verilator+seed+<value> Set random seed
|
||||
+verilator+V Verbose version and config
|
||||
@@ -458,7 +460,7 @@ description of these arguments.
|
||||
|
||||
The latest version is available from L<https://verilator.org>.
|
||||
|
||||
Copyright 2003-2021 by Wilson Snyder. This program is free software; you can
|
||||
Copyright 2003-2022 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.
|
||||
|
||||
@@ -14,7 +14,7 @@ parser = argparse.ArgumentParser(
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
description="""Report ccache behavior of a Verilated model build.""",
|
||||
epilog=
|
||||
"""Copyright 2002-2021 by Wilson Snyder. This program is free software; you
|
||||
"""Copyright 2002-2022 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
|
||||
######################################################################
|
||||
#
|
||||
# Copyright 2003-2021 by Wilson Snyder. This program is free software; you
|
||||
# Copyright 2003-2022 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.
|
||||
@@ -187,7 +187,7 @@ L<https://verilator.org/guide/latest/exe_verilator_coverage.html>.
|
||||
|
||||
The latest version is available from L<https://verilator.org>.
|
||||
|
||||
Copyright 2003-2021 by Wilson Snyder. This program is free software; you
|
||||
Copyright 2003-2022 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.
|
||||
|
||||
@@ -38,10 +38,10 @@ def diff_dir(a, b):
|
||||
|
||||
anyfile = False
|
||||
for base in sorted(files.keys()):
|
||||
if (not 'a' in files[base]) or (not 'b' in files[base]):
|
||||
continue
|
||||
a = files[base]['a']
|
||||
b = files[base]['b']
|
||||
if not a or not b:
|
||||
continue
|
||||
print("=" * 70)
|
||||
print("= %s <-> %s" % (a, b))
|
||||
diff_file(a, b)
|
||||
@@ -113,7 +113,7 @@ directories, ignoring irrelevant pointer differences.
|
||||
For documentation see
|
||||
https://verilator.org/guide/latest/exe_verilator_difftree.html
|
||||
|
||||
Copyright 2005-2021 by Wilson Snyder. This program is free software; you
|
||||
Copyright 2005-2022 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.
|
||||
|
||||
+165
-145
@@ -9,7 +9,7 @@ import re
|
||||
import statistics
|
||||
# from pprint import pprint
|
||||
|
||||
Threads = collections.defaultdict(lambda: {})
|
||||
Threads = collections.defaultdict(lambda: collections.defaultdict(lambda: {}))
|
||||
Mtasks = collections.defaultdict(lambda: {})
|
||||
Evals = collections.defaultdict(lambda: {})
|
||||
EvalLoops = collections.defaultdict(lambda: {})
|
||||
@@ -30,12 +30,12 @@ def process(filename):
|
||||
|
||||
def read_data(filename):
|
||||
with open(filename) as fh:
|
||||
re_prof = re.compile(
|
||||
r'^VLPROF mtask\s(\d+)\sstart\s(\d+)\selapsed\s(\d+)\spredict_start\s(\d+)\spredict_cost\s(\d+)\scpu\s(\d+)\son thread (\d+)'
|
||||
)
|
||||
re_eval = re.compile(r'^VLPROF eval\sstart\s(\d+)\selapsed\s(\d+)')
|
||||
re_loop = re.compile(
|
||||
r'^VLPROF eval_loop\sstart\s(\d+)\selapsed\s(\d+)')
|
||||
re_thread = re.compile(r'^VLPROFTHREAD (\d+)$')
|
||||
re_record = re.compile(r'^VLPROFEXEC (\S+) (\d+)(.*)$')
|
||||
re_payload_mtaskBegin = re.compile(
|
||||
r'id (\d+) predictStart (\d+) cpu (\d+)')
|
||||
re_payload_mtaskEnd = re.compile(r'id (\d+) predictCost (\d+)')
|
||||
|
||||
re_arg1 = re.compile(r'VLPROF arg\s+(\S+)\+([0-9.]*)\s*')
|
||||
re_arg2 = re.compile(r'VLPROF arg\s+(\S+)\s+([0-9.]*)\s*$')
|
||||
re_stat = re.compile(r'VLPROF stat\s+(\S+)\s+([0-9.]+)')
|
||||
@@ -43,47 +43,60 @@ def read_data(filename):
|
||||
re_proc_cpu = re.compile(r'VLPROFPROC processor\s*:\s*(\d+)\s*$')
|
||||
re_proc_dat = re.compile(r'VLPROFPROC ([a-z_ ]+)\s*:\s*(.*)$')
|
||||
cpu = None
|
||||
thread = None
|
||||
|
||||
lastEvalBeginTick = None
|
||||
lastEvalLoopBeginTick = None
|
||||
|
||||
for line in fh:
|
||||
if re_prof.match(line):
|
||||
match = re_prof.match(line)
|
||||
mtask = int(match.group(1))
|
||||
start = int(match.group(2))
|
||||
elapsed_time = int(match.group(3))
|
||||
end = start + elapsed_time
|
||||
predict_start = int(match.group(4))
|
||||
predict_cost = int(match.group(5))
|
||||
cpu = int(match.group(6))
|
||||
thread = int(match.group(7))
|
||||
if start not in Threads[thread]:
|
||||
Threads[thread][start] = {}
|
||||
Threads[thread][start]['mtask'] = mtask
|
||||
Threads[thread][start]['end'] = end
|
||||
Threads[thread][start]['cpu'] = cpu
|
||||
Threads[thread][start]['predict_start'] = predict_start
|
||||
Threads[thread][start]['predict_cost'] = predict_cost
|
||||
|
||||
if 'elapsed' not in Mtasks[mtask]:
|
||||
Mtasks[mtask] = {'end': 0, 'elapsed': 0}
|
||||
Mtasks[mtask]['thread'] = thread
|
||||
Mtasks[mtask]['elapsed'] += elapsed_time
|
||||
Mtasks[mtask]['predict_start'] = predict_start
|
||||
Mtasks[mtask]['predict_cost'] = predict_cost
|
||||
Mtasks[mtask]['end'] = max(Mtasks[mtask]['end'], end)
|
||||
elif re_eval.match(line):
|
||||
match = re_eval.match(line)
|
||||
start = int(match.group(1))
|
||||
elapsed_time = int(match.group(2))
|
||||
Evals[start]['start'] = start
|
||||
Evals[start]['end'] = start + elapsed_time
|
||||
elif re_loop.match(line):
|
||||
match = re_loop.match(line)
|
||||
start = int(match.group(1))
|
||||
elapsed_time = int(match.group(2))
|
||||
EvalLoops[start]['start'] = start
|
||||
EvalLoops[start]['end'] = start + elapsed_time
|
||||
elif re.match(r'^VLPROFTHREAD', line):
|
||||
None # pylint: disable=pointless-statement
|
||||
recordMatch = re_record.match(line)
|
||||
if recordMatch:
|
||||
kind, tick, payload = recordMatch.groups()
|
||||
tick = int(tick)
|
||||
payload = payload.strip()
|
||||
if kind == "EVAL_BEGIN":
|
||||
Evals[tick]['start'] = tick
|
||||
lastEvalBeginTick = tick
|
||||
elif kind == "EVAL_END":
|
||||
Evals[lastEvalBeginTick]['end'] = tick
|
||||
lastEvalBeginTick = None
|
||||
elif kind == "EVAL_LOOP_BEGIN":
|
||||
EvalLoops[tick]['start'] = tick
|
||||
lastEvalLoopBeginTick = tick
|
||||
elif kind == "EVAL_LOOP_END":
|
||||
EvalLoops[lastEvalLoopBeginTick]['end'] = tick
|
||||
lastEvalLoopBeginTick = None
|
||||
elif kind == "MTASK_BEGIN":
|
||||
mtask, predict_start, ecpu = re_payload_mtaskBegin.match(
|
||||
payload).groups()
|
||||
mtask = int(mtask)
|
||||
predict_start = int(predict_start)
|
||||
ecpu = int(ecpu)
|
||||
Threads[thread][tick]['mtask'] = mtask
|
||||
Threads[thread][tick]['predict_start'] = predict_start
|
||||
Threads[thread][tick]['cpu'] = ecpu
|
||||
if 'elapsed' not in Mtasks[mtask]:
|
||||
Mtasks[mtask] = {'end': 0, 'elapsed': 0}
|
||||
Mtasks[mtask]['begin'] = tick
|
||||
Mtasks[mtask]['thread'] = thread
|
||||
Mtasks[mtask]['predict_start'] = predict_start
|
||||
elif kind == "MTASK_END":
|
||||
mtask, predict_cost = re_payload_mtaskEnd.match(
|
||||
payload).groups()
|
||||
mtask = int(mtask)
|
||||
predict_cost = int(predict_cost)
|
||||
begin = Mtasks[mtask]['begin']
|
||||
Threads[thread][begin]['end'] = tick
|
||||
Threads[thread][begin]['predict_cost'] = predict_cost
|
||||
Mtasks[mtask]['elapsed'] += tick - begin
|
||||
Mtasks[mtask]['predict_cost'] = predict_cost
|
||||
Mtasks[mtask]['end'] = max(Mtasks[mtask]['end'], tick)
|
||||
elif Args.debug:
|
||||
print("-Unknown execution trace record: %s" % line)
|
||||
elif re_thread.match(line):
|
||||
thread = int(re_thread.match(line).group(1))
|
||||
elif re.match(r'^VLPROF(THREAD|VERSION)', line):
|
||||
pass
|
||||
elif re_arg1.match(line):
|
||||
match = re_arg1.match(line)
|
||||
Global['args'][match.group(1)] = match.group(2)
|
||||
@@ -105,7 +118,7 @@ def read_data(filename):
|
||||
value = re.sub(r'\s+$', '', value)
|
||||
Global['cpuinfo'][cpu][term] = value
|
||||
elif re.match(r'^#', line):
|
||||
None # pylint: disable=pointless-statement
|
||||
pass
|
||||
elif Args.debug:
|
||||
print("-Unk: %s" % line)
|
||||
# TODO -- this is parsing text printed by a client.
|
||||
@@ -131,11 +144,12 @@ def report():
|
||||
plus = "+" if re.match(r'^\+', arg) else " "
|
||||
print(" %s%s%s" % (arg, plus, Global['args'][arg]))
|
||||
|
||||
nthreads = len(Threads)
|
||||
nthreads = int(Global['stats']['threads'])
|
||||
Global['cpus'] = {}
|
||||
for thread in Threads:
|
||||
# Make potentially multiple characters per column
|
||||
for start in Threads[thread]:
|
||||
if not Threads[thread][start]: continue
|
||||
cpu = Threads[thread][start]['cpu']
|
||||
elapsed = Threads[thread][start]['end'] - start
|
||||
if cpu not in Global['cpus']:
|
||||
@@ -169,74 +183,79 @@ def report():
|
||||
print("\nAnalysis:")
|
||||
print(" Total threads = %d" % nthreads)
|
||||
print(" Total mtasks = %d" % len(Mtasks))
|
||||
ncpus = len(Global['cpus'])
|
||||
ncpus = max(len(Global['cpus']), 1)
|
||||
print(" Total cpus used = %d" % ncpus)
|
||||
print(" Total yields = %d" % int(Global['stats']['yields']))
|
||||
print(" Total yields = %d" %
|
||||
int(Global['stats'].get('yields', 0)))
|
||||
print(" Total evals = %d" % len(Evals))
|
||||
print(" Total eval loops = %d" % len(EvalLoops))
|
||||
print(" Total eval time = %d rdtsc ticks" %
|
||||
Global['measured_last_end'])
|
||||
print(" Longest mtask time = %d rdtsc ticks" % long_mtask_time)
|
||||
print(" All-thread mtask time = %d rdtsc ticks" %
|
||||
measured_mt_mtask_time)
|
||||
long_efficiency = long_mtask_time / (Global.get('measured_last_end', 1)
|
||||
or 1)
|
||||
print(" Longest-thread efficiency = %0.1f%%" % (long_efficiency * 100.0))
|
||||
mt_efficiency = measured_mt_mtask_time / (
|
||||
Global.get('measured_last_end', 1) * nthreads or 1)
|
||||
print(" All-thread efficiency = %0.1f%%" % (mt_efficiency * 100.0))
|
||||
print(" All-thread speedup = %0.1f" % (mt_efficiency * nthreads))
|
||||
if Global['rdtsc_cycle_time'] > 0:
|
||||
ut = measured_mt_mtask_time / Global['rdtsc_cycle_time']
|
||||
print("tot_mtask_cpu=" + measured_mt_mtask_time + " cyc=" +
|
||||
Global['rdtsc_cycle_time'] + " ut=" + ut)
|
||||
if Mtasks:
|
||||
print(" Total eval time = %d rdtsc ticks" %
|
||||
Global['measured_last_end'])
|
||||
print(" Longest mtask time = %d rdtsc ticks" % long_mtask_time)
|
||||
print(" All-thread mtask time = %d rdtsc ticks" %
|
||||
measured_mt_mtask_time)
|
||||
long_efficiency = long_mtask_time / (Global.get(
|
||||
'measured_last_end', 1) or 1)
|
||||
print(" Longest-thread efficiency = %0.1f%%" %
|
||||
(long_efficiency * 100.0))
|
||||
mt_efficiency = measured_mt_mtask_time / (
|
||||
Global.get('measured_last_end', 1) * nthreads or 1)
|
||||
print(" All-thread efficiency = %0.1f%%" %
|
||||
(mt_efficiency * 100.0))
|
||||
print(" All-thread speedup = %0.1f" %
|
||||
(mt_efficiency * nthreads))
|
||||
if Global['rdtsc_cycle_time'] > 0:
|
||||
ut = measured_mt_mtask_time / Global['rdtsc_cycle_time']
|
||||
print("tot_mtask_cpu=" + measured_mt_mtask_time + " cyc=" +
|
||||
Global['rdtsc_cycle_time'] + " ut=" + ut)
|
||||
|
||||
predict_mt_efficiency = predict_mt_mtask_time / (
|
||||
Global.get('predict_last_end', 1) * nthreads or 1)
|
||||
print("\nPrediction (what Verilator used for scheduling):")
|
||||
print(" All-thread efficiency = %0.1f%%" %
|
||||
(predict_mt_efficiency * 100.0))
|
||||
print(" All-thread speedup = %0.1f" %
|
||||
(predict_mt_efficiency * nthreads))
|
||||
predict_mt_efficiency = predict_mt_mtask_time / (
|
||||
Global.get('predict_last_end', 1) * nthreads or 1)
|
||||
print("\nPrediction (what Verilator used for scheduling):")
|
||||
print(" All-thread efficiency = %0.1f%%" %
|
||||
(predict_mt_efficiency * 100.0))
|
||||
print(" All-thread speedup = %0.1f" %
|
||||
(predict_mt_efficiency * nthreads))
|
||||
|
||||
p2e_ratios = []
|
||||
min_p2e = 1000000
|
||||
min_mtask = None
|
||||
max_p2e = -1000000
|
||||
max_mtask = None
|
||||
p2e_ratios = []
|
||||
min_p2e = 1000000
|
||||
min_mtask = None
|
||||
max_p2e = -1000000
|
||||
max_mtask = None
|
||||
|
||||
for mtask in sorted(Mtasks.keys()):
|
||||
if Mtasks[mtask]['elapsed'] > 0:
|
||||
if Mtasks[mtask]['predict_cost'] == 0:
|
||||
Mtasks[mtask]['predict_cost'] = 1 # don't log(0) below
|
||||
p2e_ratio = math.log(Mtasks[mtask]['predict_cost'] /
|
||||
Mtasks[mtask]['elapsed'])
|
||||
p2e_ratios.append(p2e_ratio)
|
||||
for mtask in sorted(Mtasks.keys()):
|
||||
if Mtasks[mtask]['elapsed'] > 0:
|
||||
if Mtasks[mtask]['predict_cost'] == 0:
|
||||
Mtasks[mtask]['predict_cost'] = 1 # don't log(0) below
|
||||
p2e_ratio = math.log(Mtasks[mtask]['predict_cost'] /
|
||||
Mtasks[mtask]['elapsed'])
|
||||
p2e_ratios.append(p2e_ratio)
|
||||
|
||||
if p2e_ratio > max_p2e:
|
||||
max_p2e = p2e_ratio
|
||||
max_mtask = mtask
|
||||
if p2e_ratio < min_p2e:
|
||||
min_p2e = p2e_ratio
|
||||
min_mtask = mtask
|
||||
if p2e_ratio > max_p2e:
|
||||
max_p2e = p2e_ratio
|
||||
max_mtask = mtask
|
||||
if p2e_ratio < min_p2e:
|
||||
min_p2e = p2e_ratio
|
||||
min_mtask = mtask
|
||||
|
||||
print("\nStatistics:")
|
||||
print(" min log(p2e) = %0.3f" % min_p2e, end="")
|
||||
print(" from mtask %d (predict %d," %
|
||||
(min_mtask, Mtasks[min_mtask]['predict_cost']),
|
||||
end="")
|
||||
print(" elapsed %d)" % Mtasks[min_mtask]['elapsed'])
|
||||
print(" max log(p2e) = %0.3f" % max_p2e, end="")
|
||||
print(" from mtask %d (predict %d," %
|
||||
(max_mtask, Mtasks[max_mtask]['predict_cost']),
|
||||
end="")
|
||||
print(" elapsed %d)" % Mtasks[max_mtask]['elapsed'])
|
||||
print("\nMTask statistics:")
|
||||
print(" min log(p2e) = %0.3f" % min_p2e, end="")
|
||||
print(" from mtask %d (predict %d," %
|
||||
(min_mtask, Mtasks[min_mtask]['predict_cost']),
|
||||
end="")
|
||||
print(" elapsed %d)" % Mtasks[min_mtask]['elapsed'])
|
||||
print(" max log(p2e) = %0.3f" % max_p2e, end="")
|
||||
print(" from mtask %d (predict %d," %
|
||||
(max_mtask, Mtasks[max_mtask]['predict_cost']),
|
||||
end="")
|
||||
print(" elapsed %d)" % Mtasks[max_mtask]['elapsed'])
|
||||
|
||||
stddev = statistics.pstdev(p2e_ratios)
|
||||
mean = statistics.mean(p2e_ratios)
|
||||
print(" mean = %0.3f" % mean)
|
||||
print(" stddev = %0.3f" % stddev)
|
||||
print(" e ^ stddev = %0.3f" % math.exp(stddev))
|
||||
stddev = statistics.pstdev(p2e_ratios)
|
||||
mean = statistics.mean(p2e_ratios)
|
||||
print(" mean = %0.3f" % mean)
|
||||
print(" stddev = %0.3f" % stddev)
|
||||
print(" e ^ stddev = %0.3f" % math.exp(stddev))
|
||||
|
||||
report_cpus()
|
||||
|
||||
@@ -375,44 +394,45 @@ def write_vcd(filename):
|
||||
vcd['values'][eval_start][elcode] = n
|
||||
vcd['values'][eval_end][elcode] = None
|
||||
|
||||
# Predicted graph
|
||||
for eval_start in EvalLoops:
|
||||
eval_end = EvalLoops[eval_start]['end']
|
||||
# Compute scale so predicted graph is of same width as eval
|
||||
measured_scaling = (eval_end -
|
||||
eval_start) / Global['predict_last_end']
|
||||
# Predict mtasks that fill the time the eval occupied
|
||||
for mtask in Mtasks:
|
||||
thread = Mtasks[mtask]['thread']
|
||||
pred_scaled_start = eval_start + int(
|
||||
Mtasks[mtask]['predict_start'] * measured_scaling)
|
||||
pred_scaled_end = eval_start + int(
|
||||
(Mtasks[mtask]['predict_start'] +
|
||||
Mtasks[mtask]['predict_cost']) * measured_scaling)
|
||||
if pred_scaled_start == pred_scaled_end:
|
||||
continue
|
||||
if Mtasks:
|
||||
# Predicted graph
|
||||
for eval_start in EvalLoops:
|
||||
eval_end = EvalLoops[eval_start]['end']
|
||||
# Compute scale so predicted graph is of same width as eval
|
||||
measured_scaling = (eval_end -
|
||||
eval_start) / Global['predict_last_end']
|
||||
# Predict mtasks that fill the time the eval occupied
|
||||
for mtask in Mtasks:
|
||||
thread = Mtasks[mtask]['thread']
|
||||
pred_scaled_start = eval_start + int(
|
||||
Mtasks[mtask]['predict_start'] * measured_scaling)
|
||||
pred_scaled_end = eval_start + int(
|
||||
(Mtasks[mtask]['predict_start'] +
|
||||
Mtasks[mtask]['predict_cost']) * measured_scaling)
|
||||
if pred_scaled_start == pred_scaled_end:
|
||||
continue
|
||||
|
||||
sig = "predicted_thread%d_mtask" % thread
|
||||
if sig not in vcd['sigs']['predicted_threads']:
|
||||
vcd['sigs']['predicted_threads'][sig] = code
|
||||
code += 1
|
||||
mcode = vcd['sigs']['predicted_threads'][sig]
|
||||
sig = "predicted_thread%d_mtask" % thread
|
||||
if sig not in vcd['sigs']['predicted_threads']:
|
||||
vcd['sigs']['predicted_threads'][sig] = code
|
||||
code += 1
|
||||
mcode = vcd['sigs']['predicted_threads'][sig]
|
||||
|
||||
vcd['values'][pred_scaled_start][mcode] = mtask
|
||||
vcd['values'][pred_scaled_end][mcode] = None
|
||||
vcd['values'][pred_scaled_start][mcode] = mtask
|
||||
vcd['values'][pred_scaled_end][mcode] = None
|
||||
|
||||
parallelism['predicted'][pred_scaled_start] += 1
|
||||
parallelism['predicted'][pred_scaled_end] -= 1
|
||||
parallelism['predicted'][pred_scaled_start] += 1
|
||||
parallelism['predicted'][pred_scaled_end] -= 1
|
||||
|
||||
# Parallelism graph
|
||||
for measpred in ('measured', 'predicted'):
|
||||
vcd['sigs']['Stats']["%s_parallelism" % measpred] = code
|
||||
pcode = code
|
||||
code += 1
|
||||
value = 0
|
||||
for time in sorted(parallelism[measpred].keys()):
|
||||
value += parallelism[measpred][time]
|
||||
vcd['values'][time][pcode] = value
|
||||
# Parallelism graph
|
||||
for measpred in ('measured', 'predicted'):
|
||||
vcd['sigs']['Stats']["%s_parallelism" % measpred] = code
|
||||
pcode = code
|
||||
code += 1
|
||||
value = 0
|
||||
for time in sorted(parallelism[measpred].keys()):
|
||||
value += parallelism[measpred][time]
|
||||
vcd['values'][time][pcode] = value
|
||||
|
||||
# Create output file
|
||||
fh.write("$version Generated by verilator_gantt $end\n")
|
||||
@@ -463,7 +483,7 @@ parser = argparse.ArgumentParser(
|
||||
For documentation see
|
||||
https://verilator.org/guide/latest/exe_verilator_gantt.html
|
||||
|
||||
Copyright 2018-2021 by Wilson Snyder. This program is free software; you
|
||||
Copyright 2018-2022 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.
|
||||
@@ -476,10 +496,10 @@ parser.add_argument('--no-vcd',
|
||||
action='store_true')
|
||||
parser.add_argument('--vcd',
|
||||
help='filename for vcd outpue',
|
||||
default='profile_threads.vcd')
|
||||
default='profile_exec.vcd')
|
||||
parser.add_argument('filename',
|
||||
help='input profile_threads.dat filename to process',
|
||||
default='profile_threads.dat')
|
||||
help='input profile_exec.dat filename to process',
|
||||
default='profile_exec.dat')
|
||||
|
||||
Args = parser.parse_args()
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env perl
|
||||
# DESCRIPTION: Print include statements for each ARGV
|
||||
#
|
||||
# Copyright 2003-2021 by Wilson Snyder. This program is free software; you
|
||||
# Copyright 2003-2022 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.
|
||||
|
||||
@@ -182,7 +182,7 @@ in each Verilog block.
|
||||
For documentation see
|
||||
https://verilator.org/guide/latest/exe_verilator_profcfunc.html
|
||||
|
||||
Copyright 2002-2021 by Wilson Snyder. This program is free software; you
|
||||
Copyright 2002-2022 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.
|
||||
|
||||
+7
-3
@@ -54,8 +54,12 @@ if [ "$CI_BUILD_STAGE_NAME" = "build" ]; then
|
||||
|
||||
if [ "$CI_OS_NAME" = "linux" ]; then
|
||||
sudo apt-get update
|
||||
sudo apt-get install libfl-dev libgoogle-perftools-dev ccache
|
||||
if [ "$CI_RUNS_ON" = "ubuntu-20.04" ]; then
|
||||
sudo apt-get install libfl-dev ccache
|
||||
if [ "$CI_RUNS_ON" != "ubuntu-22.04" ]; then
|
||||
# Some conflict of libunwind verison on 22.04, can live without it for now
|
||||
sudo apt-get install libgoogle-perftools-dev
|
||||
fi
|
||||
if [ "$CI_RUNS_ON" = "ubuntu-20.04" ] || [ "$CI_RUNS_ON" = "ubuntu-22.04" ]; then
|
||||
sudo apt-get install libsystemc libsystemc-dev
|
||||
fi
|
||||
if [ "$COVERAGE" = 1 ]; then
|
||||
@@ -85,7 +89,7 @@ elif [ "$CI_BUILD_STAGE_NAME" = "test" ]; then
|
||||
sudo apt-get update
|
||||
# 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
|
||||
if [ "$CI_RUNS_ON" = "ubuntu-20.04" ] || [ "$CI_RUNS_ON" = "ubuntu-22.04" ]; then
|
||||
sudo apt-get install libsystemc-dev
|
||||
fi
|
||||
if [ "$CI_M32" = 1 ]; then
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
# DESCRIPTION: codecov.io config
|
||||
#
|
||||
# Copyright 2020-2021 by Wilson Snyder. This program is free software; you
|
||||
# Copyright 2020-2022 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.
|
||||
|
||||
+17
-11
@@ -1,20 +1,20 @@
|
||||
# DESCRIPTION: Process this file with autoconf to produce a configure script.
|
||||
#
|
||||
# Copyright 2003-2021 by Wilson Snyder. Verilator is free software; you
|
||||
# Copyright 2003-2022 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.214 2021-10-17],
|
||||
AC_INIT([Verilator],[4.224 2022-06-19],
|
||||
[https://verilator.org],
|
||||
[verilator],[https://verilator.org])
|
||||
# When releasing, also update header of Changes file
|
||||
# and commit using "devel release" or "Version bump" message
|
||||
# Then 'make maintainer-dist'
|
||||
|
||||
AC_CONFIG_HEADER(src/config_build.h)
|
||||
AC_CONFIG_HEADERS(src/config_build.h)
|
||||
AC_CONFIG_FILES(Makefile src/Makefile src/Makefile_obj include/verilated.mk include/verilated_config.h verilator.pc verilator-config.cmake verilator-config-version.cmake)
|
||||
|
||||
# Version
|
||||
@@ -22,6 +22,8 @@ AC_MSG_RESULT([configuring for $PACKAGE_STRING])
|
||||
PACKAGE_VERSION_NUMBER=`AS_ECHO("$PACKAGE_VERSION") | sed 's/ .*//g'`
|
||||
AC_SUBST(PACKAGE_VERSION_NUMBER)
|
||||
AC_DEFINE_UNQUOTED([PACKAGE_VERSION_NUMBER_STRING],["$PACKAGE_VERSION_NUMBER"],[Package version as a number])
|
||||
VERILATOR_VERSION_INTEGER=`AS_ECHO("$PACKAGE_VERSION") | [sed 's/\([0-9]\)\.\([0-9][0-9][0-9]\) .*/\1\2000/g']`
|
||||
AC_SUBST(VERILATOR_VERSION_INTEGER)
|
||||
|
||||
# Ignore automake flags passed by Ubuntu builds
|
||||
AC_ARG_ENABLE([dependency-tracking],
|
||||
@@ -143,10 +145,10 @@ AC_SUBST(CFG_WITH_LONGTESTS)
|
||||
AC_MSG_RESULT($CFG_WITH_LONGTESTS)
|
||||
|
||||
# Compiler flags (ensure they are not empty to avoid configure defaults)
|
||||
CFLAGS+=" "
|
||||
CPPFLAGS+=" "
|
||||
CXXFLAGS+=" "
|
||||
LDFLAGS+=" "
|
||||
CFLAGS="$CFLAGS "
|
||||
CPPFLAGS="$CPPFLAGS "
|
||||
CXXFLAGS="$CXXFLAGS "
|
||||
LDFLAGS="$LDFLAGS "
|
||||
|
||||
# Checks for programs.
|
||||
AC_PROG_CC
|
||||
@@ -346,14 +348,18 @@ AC_SUBST(CFG_CXXFLAGS_PROFILE)
|
||||
|
||||
# Flag to select newest language standard supported
|
||||
# Macros work such that first option that passes is the one we take
|
||||
# Currently enabled c++14 due to packaged SystemC dependency
|
||||
# c++14 is the newest that Verilator is regressed to support
|
||||
# Currently enable c++17/c++14 due to packaged SystemC dependency
|
||||
# c++17 is the newest that Verilator is regularly tested to support
|
||||
# c++11 is the oldest that Verilator supports
|
||||
# gnu is requried for Cygwin to compile verilated.h successfully
|
||||
#_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_NEWEST,-std=gnu++20)
|
||||
#_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_NEWEST,-std=c++20)
|
||||
#_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_NEWEST,-std=gnu++17)
|
||||
#_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_NEWEST,-std=c++17)
|
||||
case "$(which lsb_release 2>&1 > /dev/null && lsb_release -d)" in
|
||||
*Ubuntu*22.04*)
|
||||
_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_NEWEST,-std=gnu++17)
|
||||
_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_NEWEST,-std=c++17)
|
||||
;;
|
||||
esac
|
||||
_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_NEWEST,-std=gnu++14)
|
||||
_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_NEWEST,-std=c++14)
|
||||
_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_NEWEST,-std=gnu++11)
|
||||
|
||||
@@ -2,3 +2,4 @@
|
||||
*.html
|
||||
*.pdf
|
||||
_build
|
||||
guide/spelling.txt
|
||||
|
||||
@@ -3,12 +3,15 @@ under the Developer Certificate of Origin (https://developercertificate.org/).
|
||||
|
||||
Please see the Verilator manual for 200+ additional contributors. Thanks to all.
|
||||
|
||||
Adrien Le Masle
|
||||
Ahmed El-Mahmoudy
|
||||
Alex Chadwick
|
||||
Àlex Torregrosa
|
||||
Aliaksei Chapyzhenka
|
||||
Ameya Vikram Singh
|
||||
Andreas Kuster
|
||||
Chris Randall
|
||||
Chuxuan Wang
|
||||
Conor McCullough
|
||||
Dan Petrisko
|
||||
Daniel Bates
|
||||
@@ -16,6 +19,7 @@ David Horton
|
||||
David Metz
|
||||
David Stanford
|
||||
David Turner
|
||||
Drew Ranck
|
||||
Drew Taussig
|
||||
Driss Hafdi
|
||||
Edgar E. Iglesias
|
||||
@@ -27,9 +31,12 @@ Geza Lore
|
||||
Gianfranco Costamagna
|
||||
Glen Gibb
|
||||
Graham Rushton
|
||||
Guokai Chen
|
||||
Harald Heckmann
|
||||
Howard Su
|
||||
Huang Rui
|
||||
Huanghuang Zhou
|
||||
HungMingWu
|
||||
HyungKi Jeong
|
||||
Iru Cai
|
||||
Ivan Vnučec
|
||||
@@ -38,6 +45,7 @@ James Hanlon
|
||||
James Hutchinson
|
||||
James Pallister
|
||||
Jamey Hicks
|
||||
Jamie Iles
|
||||
Jan Van Winkel
|
||||
Jean Berniolles
|
||||
Jeremy Bennett
|
||||
@@ -45,13 +53,16 @@ John Coiner
|
||||
John Demme
|
||||
Jonathan Drolet
|
||||
Josh Redford
|
||||
Julie Schwartz
|
||||
Julien Margetts
|
||||
Kaleb Barrett
|
||||
Kamil Rakoczy
|
||||
Kanad Kanhere
|
||||
Keith Colbert
|
||||
Kevin Kiningham
|
||||
Krzysztof Bieganski
|
||||
Kuba Ober
|
||||
Larry Doolittle
|
||||
Ludwig Rogiers
|
||||
Lukasz Dalek
|
||||
Maarten De Braekeleer
|
||||
@@ -61,8 +72,10 @@ Markus Krause
|
||||
Marlon James
|
||||
Marshal Qiao
|
||||
Martin Schmidt
|
||||
Martin Stadler
|
||||
Matthew Ballance
|
||||
Michael Killough
|
||||
Michaël Lefebvre
|
||||
Mike Popoloski
|
||||
Miodrag Milanović
|
||||
Morten Borup Petersen
|
||||
@@ -79,6 +92,7 @@ Pieter Kapsenberg
|
||||
Piotr Binkowski
|
||||
Qingyao Sun
|
||||
Rafal Kapuscik
|
||||
Raynard Qiao
|
||||
Richard Myers
|
||||
Rupert Swarbrick
|
||||
Samuel Riedel
|
||||
@@ -88,6 +102,7 @@ Sergi Granell
|
||||
Stefan Wallentowitz
|
||||
Stephen Henry
|
||||
Steven Hugg
|
||||
Teng Huang
|
||||
Tim Snyder
|
||||
Tobias Rosenkranz
|
||||
Tobias Wölfel
|
||||
@@ -100,6 +115,8 @@ Vassilis Papaefstathiou
|
||||
Veripool API Bot
|
||||
Victor Besyakov
|
||||
Wilson Snyder
|
||||
Xi Zhang
|
||||
Yoda Lee
|
||||
Yossi Nivin
|
||||
Yuri Victorovich
|
||||
Yutetsu TAKATSUKASA
|
||||
|
||||
+3
-1
@@ -5,7 +5,7 @@
|
||||
#
|
||||
# Code available from: https://verilator.org
|
||||
#
|
||||
# Copyright 2003-2021 by Wilson Snyder. This program is free software; you
|
||||
# Copyright 2003-2022 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,6 +35,7 @@ default:
|
||||
# Intermediate rules
|
||||
|
||||
vl-extract: ../bin/verilator ../Changes
|
||||
ln -sf ../spelling.txt guide/spelling.txt
|
||||
mkdir -p _build/gen
|
||||
$(PYTHON3) bin/vl_sphinx_extract ../bin/verilator
|
||||
sed 's/`/\&96;/g' < ../Changes > _build/gen/Changes
|
||||
@@ -77,6 +78,7 @@ clean mostlyclean distclean maintainer-clean::
|
||||
rm -f *.pg *.pgs *.toc *.tp *.tps *.vr *.vrs *.idx
|
||||
rm -f *.ev *.evs *.ov *.ovs *.cv *.cvs *.ma *.mas
|
||||
rm -f *.tex
|
||||
rm -f guide/spelling.txt
|
||||
|
||||
distclean maintainer-clean::
|
||||
rm -f *.info* *.1 *.html *.pdf $(INFOS)
|
||||
|
||||
@@ -40,7 +40,7 @@ parser = argparse.ArgumentParser(
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
description="""Read a file and extract documentation data.""",
|
||||
epilog=
|
||||
""" Copyright 2021-2021 by Wilson Snyder. This package is free software;
|
||||
""" Copyright 2021-2022 by Wilson Snyder. This package 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.
|
||||
|
||||
@@ -55,7 +55,7 @@ parser = argparse.ArgumentParser(
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
description="""Post-process Sphinx HTML.""",
|
||||
epilog=
|
||||
""" Copyright 2021-2021 by Wilson Snyder. This package is free software;
|
||||
""" Copyright 2021-2022 by Wilson Snyder. This package 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,4 +1,4 @@
|
||||
.. Copyright 2003-2021 by Wilson Snyder.
|
||||
.. Copyright 2003-2022 by Wilson Snyder.
|
||||
.. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
****************
|
||||
|
||||
+1
-1
@@ -36,7 +36,7 @@ def setup(app):
|
||||
# -- Project information
|
||||
|
||||
project = 'Verilator'
|
||||
copyright = '2021 by Wilson Snyder, under LGPL-3.0 or Artistic-2.0'
|
||||
copyright = '2022 by Wilson Snyder, under LGPL-3.0 or Artistic-2.0'
|
||||
author = 'Wilson Snyder'
|
||||
|
||||
# The master toctree document.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.. Copyright 2003-2021 by Wilson Snyder.
|
||||
.. Copyright 2003-2022 by Wilson Snyder.
|
||||
.. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
.. _Connecting:
|
||||
@@ -96,7 +96,7 @@ model. Here is a simple example:
|
||||
|
||||
Vtop *top; // Instantiation of model
|
||||
|
||||
vluint64_t main_time = 0; // Current simulation time
|
||||
uint64_t main_time = 0; // Current simulation time
|
||||
// This is a 64-bit integer to reduce wrap over issues and
|
||||
// allow modulus. This is in units of the timeprecision
|
||||
// used in Verilog (or from --timescale-override)
|
||||
@@ -110,6 +110,9 @@ model. Here is a simple example:
|
||||
Verilated::commandArgs(argc, argv); // Remember args
|
||||
|
||||
top = new Vtop; // Create model
|
||||
// Do not instead make Vtop as a file-scope static
|
||||
// variable, as the "C++ static initialization order fiasco"
|
||||
// may cause a crash
|
||||
|
||||
top->reset_l = 0; // Set some inputs
|
||||
|
||||
@@ -150,7 +153,7 @@ netlist as an instantiation.
|
||||
The SC_MODULE gets the same pinout as the Verilog module, with the
|
||||
following type conversions: Pins of a single bit become bool. Pins 2-32
|
||||
bits wide become uint32_t's. Pins 33-64 bits wide become sc_bv's or
|
||||
vluint64_t's depending on the :vlopt:`--no-pins64` option. Wider pins
|
||||
uint64_t's depending on the :vlopt:`--no-pins64` option. Wider pins
|
||||
become sc_bv's. (Uints simulate the fastest so are used where possible.)
|
||||
|
||||
Model internals, including lower level sub-modules are not pure SystemC
|
||||
@@ -200,7 +203,7 @@ DPI System Task/Functions
|
||||
-------------------------
|
||||
|
||||
Verilator extends the DPI format to allow using the same scheme to
|
||||
efficiently add system functions. Simply use a dollar-sign prefixed system
|
||||
efficiently add system functions. Use a dollar-sign prefixed system
|
||||
function name for the import, but note it must be escaped.
|
||||
|
||||
.. code-block:: sv
|
||||
@@ -257,7 +260,9 @@ with respect to that top level module, then the scope could be set with
|
||||
|
||||
#include "svdpi.h"
|
||||
...
|
||||
svSetScope(svGetScopeFromName("TOP.dut"));
|
||||
const svScope scope = svGetScopeFromName("TOP.dut");
|
||||
assert(scope); // Check for nullptr if scope not found
|
||||
svSetScope(scope);
|
||||
|
||||
(Remember that Verilator adds a "TOP" to the top of the module hierarchy.)
|
||||
|
||||
@@ -422,12 +427,12 @@ accesses the above signal "readme" would be:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
cat >sim_main.cpp <<'<<EOF'
|
||||
cat >sim_main.cpp <<'EOF'
|
||||
#include "Vour.h"
|
||||
#include "verilated.h"
|
||||
#include "verilated_vpi.h" // Required to get definitions
|
||||
|
||||
vluint64_t main_time = 0; // See comments in first example
|
||||
uint64_t main_time = 0; // See comments in first example
|
||||
double sc_time_stamp() { return main_time; }
|
||||
|
||||
void read_and_check() {
|
||||
@@ -506,7 +511,7 @@ structure. If a ``VerilatedContext`` is not created prior to creating a
|
||||
model, a default global one is created automatically.
|
||||
|
||||
The ``Verilated::`` methods, including the ``Verilated::commandArgs`` call
|
||||
shown above, simply call VerilatedContext methods using the default global
|
||||
shown above, call VerilatedContext methods using the default global
|
||||
VerilatedContext. (Technically they operate on the last one used by a
|
||||
given thread.) If you are using multiple simulation contexts you should
|
||||
not use the Verilated:: methods, and instead always use VerilatedContext
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.. Copyright 2003-2021 by Wilson Snyder.
|
||||
.. Copyright 2003-2022 by Wilson Snyder.
|
||||
.. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
*******************************
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.. Copyright 2003-2021 by Wilson Snyder.
|
||||
.. Copyright 2003-2022 by Wilson Snyder.
|
||||
.. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
************************
|
||||
@@ -23,14 +23,14 @@ Contributors
|
||||
Many people have provided ideas and other assistance with Verilator.
|
||||
|
||||
Verilator is receiving major development support from the `CHIPS Alliance
|
||||
<https://chipsalliance.org>`_.
|
||||
<https://chipsalliance.org>`_ and `Shunyao CAD <https://shunyaocad.com>`_.
|
||||
|
||||
Previous major corporate sponsors of Verilator, by providing significant
|
||||
contributions of time or funds included include: Atmel Corporation, Cavium
|
||||
Inc., Compaq Corporation, Digital Equipment Corporation, Embecosm Ltd.,
|
||||
Hicamp Systems, Intel Corporation, Mindspeed Technologies Inc., MicroTune
|
||||
Inc., picoChip Designs Ltd., Sun Microsystems Inc., Nauticus Networks Inc.,
|
||||
and SiCortex Inc.
|
||||
SiCortex Inc, and Shunyao CAD.
|
||||
|
||||
The people who have contributed major functionality are: Byron Bradley,
|
||||
Jeremy Bennett, Lane Brooks, John Coiner, Duane Galbi, Geza Lore, Todd
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.. Copyright 2003-2021 by Wilson Snyder.
|
||||
.. Copyright 2003-2022 by Wilson Snyder.
|
||||
.. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
*********
|
||||
@@ -8,7 +8,7 @@ Copyright
|
||||
The latest version of Verilator is available from `https://verilator.org
|
||||
<https://verilator.org>`_.
|
||||
|
||||
Copyright 2003-2021 by Wilson Snyder. This program is free software; you
|
||||
Copyright 2003-2022 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,4 +1,4 @@
|
||||
.. Copyright 2003-2021 by Wilson Snyder.
|
||||
.. Copyright 2003-2022 by Wilson Snyder.
|
||||
.. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
Deprecations
|
||||
@@ -9,17 +9,29 @@ The following deprecated items are scheduled for future removal:
|
||||
C++11 compiler support
|
||||
Verilator currently requires C++11 or newer compilers. Verilator will
|
||||
require C++14 or newer compilers for both compiling Verilator and
|
||||
compiling Verilated models no sooner than January 2022.
|
||||
compiling Verilated models no sooner than January 2023.
|
||||
|
||||
Verilated_heavy.h
|
||||
The legacy "verilated_heavy.h" include was replaced with just including
|
||||
"verilated.h". Verilated_heavy.h is planned for removal no sooner than
|
||||
July 2022.
|
||||
|
||||
Configuration File -msg
|
||||
The :vlopt:`lint_off` "-msg" option has been replaced with the "-rule"
|
||||
option. "-msg" is planned for removal no sooner than January 2021.
|
||||
Option `--cdc`
|
||||
The experimental `--cdc` option is believed to be generally unused and is
|
||||
planned for removal no sooner than January 2023.
|
||||
|
||||
XML locations
|
||||
The XML "fl" attribute has been replaced with the "loc" attribute. "fl"
|
||||
is planned for removal no sooner than January 2021.
|
||||
Option `-O<letter>`
|
||||
The debug `-O<letter>` options have been replaced with
|
||||
`-fno-<optimization>` debug options to match GCC. The old options are
|
||||
planned for removal no sooner than June 2023.
|
||||
|
||||
Option `--prof-threads`
|
||||
The `--prof-threads` option has been superseded by the `--prof-exec` and
|
||||
`--prof-pgo` options and is planned for removal no sooner than April 2023.
|
||||
|
||||
Verilated model options `+verilator+prof+threads+*`
|
||||
The `+verilator+prof+threads+start`, `+verilator+prof+threads+window` and
|
||||
`+verilator+prof+threads+file` options have been superseded by the
|
||||
`+verilator+prof+exec+start`, `+verilator+prof+exec+window` and
|
||||
`+verilator+prof+exec+file` options respectively and are planned for removal
|
||||
no sooner than April 2023.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.. Copyright 2003-2021 by Wilson Snyder.
|
||||
.. Copyright 2003-2022 by Wilson Snyder.
|
||||
.. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
Environment
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.. Copyright 2003-2021 by Wilson Snyder.
|
||||
.. Copyright 2003-2022 by Wilson Snyder.
|
||||
.. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
.. _Example C++ Execution:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.. Copyright 2003-2021 by Wilson Snyder.
|
||||
.. Copyright 2003-2022 by Wilson Snyder.
|
||||
.. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
First you need Verilator installed, see :ref:`Installation`. In brief, if
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.. Copyright 2003-2021 by Wilson Snyder.
|
||||
.. Copyright 2003-2022 by Wilson Snyder.
|
||||
.. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
.. _Examples in the Distribution:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.. Copyright 2003-2021 by Wilson Snyder.
|
||||
.. Copyright 2003-2022 by Wilson Snyder.
|
||||
.. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
.. _Example SystemC Execution:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.. Copyright 2003-2021 by Wilson Snyder.
|
||||
.. Copyright 2003-2022 by Wilson Snyder.
|
||||
.. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
.. _Examples:
|
||||
|
||||
+22
-10
@@ -1,4 +1,4 @@
|
||||
.. Copyright 2003-2021 by Wilson Snyder.
|
||||
.. Copyright 2003-2022 by Wilson Snyder.
|
||||
.. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
.. _Simulation Runtime Arguments:
|
||||
@@ -38,33 +38,45 @@ Summary:
|
||||
|
||||
Display help and exit.
|
||||
|
||||
.. option:: +verilator+prof+threads+file+<filename>
|
||||
.. option:: +verilator+prof+exec+file+<filename>
|
||||
|
||||
When a model was Verilated using :vlopt:`--prof-threads`, sets the
|
||||
When a model was Verilated using :vlopt:`--prof-exec`, sets the
|
||||
simulation runtime filename to dump to. Defaults to
|
||||
:file:`profile_threads.dat`.
|
||||
:file:`profile_exec.dat`.
|
||||
|
||||
.. option:: +verilator+prof+threads+start+<value>
|
||||
.. option:: +verilator+prof+exec+start+<value>
|
||||
|
||||
When a model was Verilated using :vlopt:`--prof-threads`, the simulation
|
||||
When a model was Verilated using :vlopt:`--prof-exec`, the simulation
|
||||
runtime will wait until $time is at this value (expressed in units of
|
||||
the time precision), then start the profiling warmup, then
|
||||
capturing. Generally this should be set to some time that is well within
|
||||
the normal operation of the simulation, i.e. outside of reset. If 0, the
|
||||
dump is disabled. Defaults to 1.
|
||||
|
||||
.. option:: +verilator+prof+threads+window+<value>
|
||||
.. option:: +verilator+prof+exec+window+<value>
|
||||
|
||||
When a model was Verilated using :vlopt:`--prof-threads`, after $time
|
||||
reaches :vlopt:`+verilator+prof+threads+start+\<value\>`, Verilator will
|
||||
When a model was Verilated using :vlopt:`--prof-exec`, after $time
|
||||
reaches :vlopt:`+verilator+prof+exec+start+\<value\>`, Verilator will
|
||||
warm up the profiling for this number of eval() calls, then will capture
|
||||
the profiling of this number of eval() calls. Defaults to 2, which
|
||||
makes sense for a single-clock-domain module where it's typical to want
|
||||
to capture one posedge eval() and one negedge eval().
|
||||
|
||||
.. option:: +verilator+prof+threads+file+<filename>
|
||||
|
||||
Deprecated. Alias for :vlopt:`+verilator+prof+exec+file+\<filename\>`
|
||||
|
||||
.. option:: +verilator+prof+threads+start+<value>
|
||||
|
||||
Deprecated. Alias for :vlopt:`+verilator+prof+exec+start+\<value\>`
|
||||
|
||||
.. option:: +verilator+prof+threads+window+<value>
|
||||
|
||||
Deprecated. Alias for :vlopt:`+verilator+prof+exec+window+\<filename\>`
|
||||
|
||||
.. option:: +verilator+prof+vlt+file+<filename>
|
||||
|
||||
When a model was Verilated using :vlopt:`--prof-threads`, sets the
|
||||
When a model was Verilated using :vlopt:`--prof-pgo`, sets the
|
||||
profile-guided optimization data runtime filename to dump to. Defaults
|
||||
to :file:`profile.vlt`.
|
||||
|
||||
|
||||
+170
-84
@@ -1,4 +1,4 @@
|
||||
.. Copyright 2003-2021 by Wilson Snyder.
|
||||
.. Copyright 2003-2022 by Wilson Snyder.
|
||||
.. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
verilator Arguments
|
||||
@@ -99,10 +99,10 @@ Summary:
|
||||
.. option:: --bbox-sys
|
||||
|
||||
Black box any unknown $system task or function calls. System tasks will
|
||||
simply become no-operations, and system functions will be replaced with
|
||||
unsized zero. Arguments to such functions will be parsed, but not
|
||||
otherwise checked. This prevents errors when linting in the presence of
|
||||
company specific PLI calls.
|
||||
become no-operations, and system functions will be replaced with unsized
|
||||
zero. Arguments to such functions will be parsed, but not otherwise
|
||||
checked. This prevents errors when linting in the presence of company
|
||||
specific PLI calls.
|
||||
|
||||
Using this argument will likely cause incorrect simulation.
|
||||
|
||||
@@ -158,41 +158,26 @@ Summary:
|
||||
|
||||
.. option:: --clk <signal-name>
|
||||
|
||||
Sometimes it is quite difficult for Verilator to distinguish clock
|
||||
signals from other data signals. Occasionally the clock signals can end
|
||||
up in the checking list of signals which determines if further
|
||||
evaluation is needed. This will heavily degrade the performance of a
|
||||
Verilated model.
|
||||
|
||||
With :vlopt:`--clk`, the specified signal-name is taken as a root clock
|
||||
into the model, then Verilator will mark the signal as clocker and
|
||||
propagate the clocker attribute automatically to other signals derived
|
||||
from that. In this way, Verilator will try to avoid taking the clocker
|
||||
signal into checking list.
|
||||
into the model; Verilator will mark the signal as clocker and
|
||||
propagate the clocker attribute automatically to other signals downstream in
|
||||
that clock tree.
|
||||
|
||||
Note signal-name is specified by the RTL hierarchy path. For example,
|
||||
v.foo.bar. If the signal is the input to top-module, the directly the
|
||||
signal name. If you find it difficult to find the exact name, try to use
|
||||
a :option:`/*verilator&32;clocker*/` metacomment in RTL file to mark the
|
||||
The provided signal-name is specified using a RTL hierarchy path. For
|
||||
example, v.foo.bar. If the signal is the input to top-module, then
|
||||
directly provide the signal name. Alternatively, use a
|
||||
:option:`/*verilator&32;clocker*/` metacomment in RTL file to mark the
|
||||
signal directly.
|
||||
|
||||
If clock signals are assigned to vectors and then later used
|
||||
individually, Verilator will attempt to decompose the vector and connect
|
||||
the single-bit clock signals directly. This should be transparent to
|
||||
the user.
|
||||
If clock signals are assigned to vectors and then later used as
|
||||
individual bits, Verilator will attempt to decompose the vector and
|
||||
connect the single-bit clock signals.
|
||||
|
||||
.. option:: --make <build-tool>
|
||||
|
||||
Generates a script for the specified build tool.
|
||||
|
||||
Supported values are ``gmake`` for GNU Make and ``cmake`` for CMake.
|
||||
Both can be specified together. If no build tool is specified, gmake is
|
||||
assumed. The executable of gmake can be configured via environment
|
||||
variable "MAKE".
|
||||
|
||||
When using :vlopt:`--build` Verilator takes over the responsibility of
|
||||
building the model library/executable. For this reason :option:`--make`
|
||||
cannot be specified when using :vlopt:`--build`.
|
||||
The clocker attribute is useful in cases where Verilator does not
|
||||
properly distinguish clock signals from other data signals. Using
|
||||
clocker will cause the signal indicated to be considered a clock, and
|
||||
remove it from the combinatorial logic reevaluation checking code. This
|
||||
may greatly improve performance.
|
||||
|
||||
.. option:: --compiler <compiler-name>
|
||||
|
||||
@@ -446,6 +431,54 @@ Summary:
|
||||
flattening large designs may require significant CPU time, memory and
|
||||
storage.
|
||||
|
||||
.. option:: -fno-acyc-simp
|
||||
|
||||
.. option:: -fno-assemble
|
||||
|
||||
.. option:: -fno-case
|
||||
|
||||
.. option:: -fno-combine
|
||||
|
||||
.. option:: -fno-const
|
||||
|
||||
.. option:: -fno-const-bit-op-tree
|
||||
|
||||
.. option:: -fno-dedup
|
||||
|
||||
.. option:: -fno-expand
|
||||
|
||||
.. option:: -fno-gate
|
||||
|
||||
.. option:: -fno-inline
|
||||
|
||||
.. option:: -fno-life
|
||||
|
||||
.. option:: -fno-life-post
|
||||
|
||||
.. option:: -fno-localize
|
||||
|
||||
.. option:: -fno-merge-cond
|
||||
|
||||
.. option:: -fno-merge-cond-motion
|
||||
|
||||
.. option:: -fno-merge-const-pool
|
||||
|
||||
.. option:: -fno-reloop
|
||||
|
||||
.. option:: -fno-reorder
|
||||
|
||||
.. option:: -fno-split
|
||||
|
||||
.. option:: -fno-subst
|
||||
|
||||
.. option:: -fno-subst-const
|
||||
|
||||
.. option:: -fno-table
|
||||
|
||||
Rarely needed. Disables one of the internal optimization steps. These
|
||||
are typically used only when recommended by a maintainer to help debug
|
||||
or work around an issue.
|
||||
|
||||
.. option:: -G<name>=<value>
|
||||
|
||||
Overwrites the given parameter of the toplevel module. The value is
|
||||
@@ -590,6 +623,23 @@ Summary:
|
||||
"+libext+" is fairly standard across Verilog tools. Defaults to
|
||||
".v+.sv".
|
||||
|
||||
.. option:: --lib-create <name>
|
||||
|
||||
Produces C++, Verilog wrappers and a Makefile which can in turn produce
|
||||
a DPI library which can be used by Verilator or other simulators along
|
||||
with the corresponding Verilog wrapper. The Makefile will build both a
|
||||
static and dynamic version of the library named :file:`lib<name>.a` and
|
||||
:file:`lib<name>.so` respectively. This is done because some simulators
|
||||
require a dynamic library, but the static library is arguably easier to
|
||||
use if possible. :vlopt:`--protect-lib` implies :vlopt:`--protect-ids`.
|
||||
|
||||
When using :vlopt:`--lib-create` it is advised to also use
|
||||
:vlopt:`--timescale-override /1fs <--timescale-override>` to ensure the
|
||||
model has a time resolution that is always compatible with the time
|
||||
precision of the upper instantiating module.
|
||||
|
||||
See also :vlopt:`--protect-lib`.
|
||||
|
||||
.. option:: --lint-only
|
||||
|
||||
Check the files for lint violations only, do not create any other
|
||||
@@ -601,6 +651,19 @@ Summary:
|
||||
If the design is not to be completely Verilated see also the
|
||||
:vlopt:`--bbox-sys` and :vlopt:`--bbox-unsup` options.
|
||||
|
||||
.. option:: --make <build-tool>
|
||||
|
||||
Generates a script for the specified build tool.
|
||||
|
||||
Supported values are ``gmake`` for GNU Make and ``cmake`` for CMake.
|
||||
Both can be specified together. If no build tool is specified, gmake is
|
||||
assumed. The executable of gmake can be configured via environment
|
||||
variable "MAKE".
|
||||
|
||||
When using :vlopt:`--build` Verilator takes over the responsibility of
|
||||
building the model library/executable. For this reason :option:`--make`
|
||||
cannot be specified when using :vlopt:`--build`.
|
||||
|
||||
.. option:: -MAKEFLAGS <string>
|
||||
|
||||
When using :vlopt:`--build`, add the specified argument to the invoked
|
||||
@@ -633,13 +696,6 @@ Summary:
|
||||
The directory is created if it does not exist and the parent directories
|
||||
exist; otherwise manually create the Mdir before calling Verilator.
|
||||
|
||||
.. option:: --no-merge-const-pool
|
||||
|
||||
Rarely needed. In order to minimize cache footprint, values of different
|
||||
data type, that are yet emitted identically in C++ are merged in the
|
||||
constant pool. This option disables this and causes every constant pool
|
||||
entry with a distinct data type to be emitted separately.
|
||||
|
||||
.. option:: --mod-prefix <topname>
|
||||
|
||||
Specifies the name to prepend to all lower level classes. Defaults to
|
||||
@@ -688,9 +744,9 @@ Summary:
|
||||
|
||||
Rarely needed. Enables or disables a specific optimizations, with the
|
||||
optimization selected based on the letter passed. A lowercase letter
|
||||
disables an optimization, an upper case letter enables it. This is
|
||||
intended for debugging use only; see the source code for
|
||||
version-dependent mappings of optimizations to -O letters.
|
||||
disables an optimization, an upper case letter enables it. This option
|
||||
is deprecated and the various `-f<optimization>` arguments should be
|
||||
used instead.
|
||||
|
||||
.. option:: -o <executable>
|
||||
|
||||
@@ -753,7 +809,7 @@ Summary:
|
||||
.. option:: --pins-bv <width>
|
||||
|
||||
Specifies SystemC inputs/outputs of greater than or equal to <width>
|
||||
bits wide should use sc_bv's instead of uint32/vluint64_t's. The
|
||||
bits wide should use sc_bv's instead of uint32/uint64_t's. The
|
||||
default is "--pins-bv 65", and the value must be less than or equal
|
||||
to 65. Versions before Verilator 3.671 defaulted to "--pins-bv 33".
|
||||
The more sc_bv is used, the worse for performance. Use the
|
||||
@@ -830,10 +886,19 @@ Summary:
|
||||
|
||||
Using :vlopt:`--prof-cfuncs` also enables :vlopt:`--prof-c`.
|
||||
|
||||
.. option:: --prof-exec
|
||||
|
||||
Enable collection of execution trace, that can be converted into a gantt
|
||||
chart with verilator_gantt See :ref:`Execution Profiling`.
|
||||
|
||||
.. option:: --prof-pgo
|
||||
|
||||
Enable collection of profiling data for profile guided Verilation. Currently
|
||||
this is only useful with :vlopt:`--threads`. See :ref:`Thread PGO`.
|
||||
|
||||
.. option:: --prof-threads
|
||||
|
||||
Enable gantt chart data collection for threaded builds. See :ref:`Thread
|
||||
Profiling` and :ref:`Thread PGO`.
|
||||
Deprecated. Same as --prof-exec and --prof-pgo together.
|
||||
|
||||
.. option:: --protect-key <key>
|
||||
|
||||
@@ -869,29 +934,20 @@ Summary:
|
||||
|
||||
Using DPI imports/exports is allowed and generally relatively safe in
|
||||
terms of information disclosed, which is limited to the DPI function
|
||||
prototyptes. Use of the VPI is not recommended as many design details
|
||||
prototypes. Use of the VPI is not recommended as many design details
|
||||
may be exposed, and an INSECURE warning will be issued.
|
||||
|
||||
.. option:: --protect-lib <name>
|
||||
|
||||
Produces C++, Verilog wrappers and a Makefile which can in turn produce
|
||||
a DPI library which can be used by Verilator or other simulators along
|
||||
with the corresponding Verilog wrapper. The Makefile will build both a
|
||||
static and dynamic version of the library named :file:`lib<name>.a` and
|
||||
:file:`lib<name>.so` respectively. This is done because some simulators
|
||||
require a dynamic library, but the static library is arguably easier to
|
||||
use if possible. :vlopt:`--protect-lib` implies :vlopt:`--protect-ids`.
|
||||
Produces a DPI library similar to :vlopt:`--lib-create`, but hides
|
||||
internal design details. :vlopt:`--protect-lib` implies
|
||||
:vlopt:`--protect-ids`, and :vlopt:`--lib-create`.
|
||||
|
||||
This allows for the secure delivery of sensitive IP without the need for
|
||||
encrypted RTL (i.e. IEEE P1735). See :file:`examples/make_protect_lib`
|
||||
in the distribution for a demonstration of how to build and use the DPI
|
||||
library.
|
||||
|
||||
When using :vlopt:`--protect-lib` it is advised to also use
|
||||
:vlopt:`--timescale-override /1fs <--timescale-override>` to ensure the
|
||||
model has a time resolution that is always compatible with the time
|
||||
precision of the upper instantiating module.
|
||||
|
||||
.. option:: --private
|
||||
|
||||
Opposite of :vlopt:`--public`. Is the default; this option exists for
|
||||
@@ -1026,7 +1082,8 @@ Summary:
|
||||
is not thread safe. With "--threads 1", the generated model is single
|
||||
threaded but may run in a multithreaded environment. With "--threads N",
|
||||
where N >= 2, the model is generated to run multithreaded on up to N
|
||||
threads. See :ref:`Multithreading`.
|
||||
threads. See :ref:`Multithreading`. This option also applies to
|
||||
:vlopt:`--trace` (but not :vlopt:`--trace-fst`).
|
||||
|
||||
.. option:: --threads-dpi all
|
||||
|
||||
@@ -1104,7 +1161,8 @@ Summary:
|
||||
Having tracing compiled in may result in some small performance losses,
|
||||
even when tracing is not turned on during model execution.
|
||||
|
||||
See also :vlopt:`--trace-threads` option.
|
||||
When using :vlopt:`--threads`, VCD tracing is parallelized, using the
|
||||
same number of threads as passed to :vlopt:`--threads`.
|
||||
|
||||
.. option:: --trace-coverage
|
||||
|
||||
@@ -1158,18 +1216,18 @@ Summary:
|
||||
.. option:: --trace-threads *threads*
|
||||
|
||||
Enable waveform tracing using separate threads. This is typically faster
|
||||
in simulation runtime but uses more total compute. This option is
|
||||
independent of, and works with, both :vlopt:`--trace` and
|
||||
:vlopt:`--trace-fst`. Different trace formats can take advantage of
|
||||
more trace threads to varying degrees. Currently VCD tracing can utilize
|
||||
at most "--trace-threads 1", and FST tracing can utilize at most
|
||||
"--trace-threads 2". This overrides :vlopt:`--no-threads` .
|
||||
in simulation runtime but uses more total compute. This option only
|
||||
applies to :vlopt:`--trace-fst`. FST tracing can utilize at most
|
||||
"--trace-threads 2". This overrides :vlopt:`--no-threads`.
|
||||
|
||||
This option is accepted, but has absolutely no effect with
|
||||
:vlopt:`--trace`, which respects :vlopt:`--threads` instead.
|
||||
|
||||
.. option:: --trace-underscore
|
||||
|
||||
Enable tracing of signals that start with an underscore. Normally, these
|
||||
signals are not output during tracing. See also
|
||||
:vlopt:`--coverage-underscore` option.
|
||||
Enable tracing of signals or modules that start with an
|
||||
underscore. Normally, these signals are not output during tracing. See
|
||||
also :vlopt:`--coverage-underscore` option.
|
||||
|
||||
.. option:: -U<var>
|
||||
|
||||
@@ -1358,9 +1416,10 @@ Summary:
|
||||
.. note::
|
||||
|
||||
This option applies only to values which are explicitly written as X
|
||||
in the Verilog source code. Initial values of clocks are set to 0
|
||||
unless `--x-initial-edge` is specified. Initial values of all other
|
||||
state holding variables are controlled with `--x-initial`.
|
||||
in modules (not classes) in the Verilog source code. Initial values
|
||||
of clocks are set to 0 unless `--x-initial-edge` is
|
||||
specified. Initial values of all other state holding variables are
|
||||
controlled with `--x-initial`.
|
||||
|
||||
.. option:: --x-initial 0
|
||||
|
||||
@@ -1506,9 +1565,9 @@ The grammar of configuration commands is as follows:
|
||||
|
||||
.. option:: no_clocker -module "<modulename>" [-function "<funcname>"] -var "<signame>"
|
||||
|
||||
Indicate the signal is used as clock or not. This information is used by
|
||||
Verilator to mark the signal as clocker and propagate the clocker
|
||||
attribute automatically to derived signals. See :vlopt:`--clk`.
|
||||
Indicates that the signal is used as clock or not. This information is
|
||||
used by Verilator to mark the signal and any derived signals as
|
||||
clocker. See :vlopt:`--clk`.
|
||||
|
||||
Same as :option:`/*verilator&32;clocker*/` metacomment.
|
||||
|
||||
@@ -1522,6 +1581,14 @@ The grammar of configuration commands is as follows:
|
||||
|
||||
Same as :option:`/*verilator&32;coverage_block_off*/` metacomment.
|
||||
|
||||
.. option:: forceable -module "<modulename>" -var "<signame>"
|
||||
|
||||
Generate public `<signame>__VforceEn` and `<signame>__VforceVal` signals
|
||||
that can be used to force/release a signal from C++ code. The force control
|
||||
signals are created as :option:`public_flat` signals.
|
||||
|
||||
Same as :option:`/*verilator&32;forceable*/` metacomment.
|
||||
|
||||
.. option:: full_case -file "<filename>" -lines <lineno>
|
||||
|
||||
.. option:: parallel_case -file "<filename>" -lines <lineno>
|
||||
@@ -1623,7 +1690,7 @@ The grammar of configuration commands is as follows:
|
||||
.. option:: sc_bv -module "<modulename>" [-function "<funcname>"] -var "<signame>"
|
||||
|
||||
Sets the port to be of :code:`sc_bv<{width}>` type, instead of bool,
|
||||
vluint32_t or vluint64_t. Same as :option:`/*verilator&32;sc_bv*/`
|
||||
uint32_t or uint64_t. Same as :option:`/*verilator&32;sc_bv*/`
|
||||
metacomment.
|
||||
|
||||
.. option:: sformat [-module "<modulename>"] [-task "<taskname>"] -var "<signame>"
|
||||
@@ -1652,9 +1719,28 @@ The grammar of configuration commands is as follows:
|
||||
|
||||
.. option:: tracing_off [-file "<filename>" [-lines <line> [ - <line> ]]]
|
||||
|
||||
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).
|
||||
.. option:: tracing_on [-scope "<scopename>" [-levels <levels> ]]
|
||||
|
||||
For tracing_off, instances below any module in the files/ranges
|
||||
specified will also not be traced.
|
||||
.. option:: tracing_off [-scope "<scopename>" [-levels <levels> ]]
|
||||
|
||||
Enable/disable waveform tracing for all future signals declared in
|
||||
all files.
|
||||
|
||||
With -file, enable/disable waveform tracing in the specified
|
||||
filename (or wildcard with '\*' or '?'), and -line range of line
|
||||
numbers (or all lines if omitted).
|
||||
|
||||
For tracing_off with -file, instances below any module in the
|
||||
files/ranges specified will also not be traced. To overcome this
|
||||
feature, use tracing_on on the upper module declaration and on any
|
||||
cells, or use the -scope flavor of the command.
|
||||
|
||||
With -scope enable/disable waveform tracing for the specified scope (or
|
||||
wildcard with '\*' or '?'), and optional --levels number of levels
|
||||
below. These controls only take place after other file/line/module
|
||||
based controls have indicated the signal should be traced.
|
||||
|
||||
With -levels (used with -scope), the number of levels below that
|
||||
scope which the rule is to match, where 0 means all levels below, 1
|
||||
the exact level as the provided scope, and 2 meaning an additional
|
||||
level of children below the provided scope, etc.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.. Copyright 2003-2021 by Wilson Snyder.
|
||||
.. Copyright 2003-2022 by Wilson Snyder.
|
||||
.. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
verilator_coverage
|
||||
@@ -67,7 +67,7 @@ which have low coverage are written to the output directory.
|
||||
|
||||
Specifies if the coverage point does not include the count number of
|
||||
coverage hits, then the coverage point will be considered above the
|
||||
threashold, and the coverage report will put a "%" to indicate the coverage
|
||||
threshold, and the coverage report will put a "%" to indicate the coverage
|
||||
is not sufficient. Defaults to 10.
|
||||
|
||||
.. option:: --help
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.. Copyright 2003-2021 by Wilson Snyder.
|
||||
.. Copyright 2003-2022 by Wilson Snyder.
|
||||
.. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
verilator_gantt
|
||||
@@ -13,7 +13,7 @@ For an overview of use of verilator_gantt, see :ref:`Profiling`.
|
||||
Gantt Chart VCD
|
||||
---------------
|
||||
|
||||
Verilated_gnatt creates a value change dump (VCD) format dump file which
|
||||
Verilated_gantt creates a value change dump (VCD) format dump file which
|
||||
may be viewed in a waveform viewer (e.g. C<GTKWave>):
|
||||
|
||||
.. figure:: figures/fig_gantt_min.png
|
||||
@@ -72,7 +72,7 @@ verilator_gantt Arguments
|
||||
|
||||
.. option:: <filename>
|
||||
|
||||
The filename to read data from, defaults to "profile_threads.dat".
|
||||
The filename to read data from, defaults to "profile_exec.dat".
|
||||
|
||||
.. option:: --help
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.. Copyright 2003-2021 by Wilson Snyder.
|
||||
.. Copyright 2003-2022 by Wilson Snyder.
|
||||
.. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
verilator_profcfunc
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.. Copyright 2003-2021 by Wilson Snyder.
|
||||
.. Copyright 2003-2022 by Wilson Snyder.
|
||||
.. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
*********************************
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.. Copyright 2003-2021 by Wilson Snyder.
|
||||
.. Copyright 2003-2022 by Wilson Snyder.
|
||||
.. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
*******************
|
||||
@@ -48,6 +48,14 @@ or "`ifdef`"'s may break other tools.
|
||||
Verilog functions where the variable is flattened out, and also enable
|
||||
other optimizations.
|
||||
|
||||
Verilator does not use any text inside the quotes for
|
||||
ordering/scheduling. If you need the $c to be called at a specific
|
||||
time, e.g. when a variable changes, then the $c must be under an
|
||||
appropriate sensitivity statement, e.g. :code:`always @(posedge clk)
|
||||
$c("func()")` to call it on every edge, or e.g. :code:`always @*
|
||||
c("func(",a,")")` to call it when :code:`a` changes (the latter working
|
||||
because :code:`a` is outside the quotes).
|
||||
|
||||
If you will be reading or writing any Verilog variables inside the C++
|
||||
functions, the Verilog signals must be declared with
|
||||
:option:`/*verilator&32;public*/` metacomments.
|
||||
@@ -176,10 +184,9 @@ or "`ifdef`"'s may break other tools.
|
||||
|
||||
.. option:: /*verilator&32;no_clocker*/
|
||||
|
||||
Used after a signal declaration to indicate the signal is used as clock
|
||||
or not. This information is used by Verilator to mark the signal as
|
||||
clocker and propagate the clocker attribute automatically to derived
|
||||
signals. See :vlopt:`--clk`.
|
||||
Specifies that the signal is used as clock or not. This information is
|
||||
used by Verilator to mark the signal and any derived signals as
|
||||
clocker. See :vlopt:`--clk`.
|
||||
|
||||
Same as :option:`clocker` and :option:`no_clocker` in configuration
|
||||
files.
|
||||
@@ -202,6 +209,20 @@ or "`ifdef`"'s may break other tools.
|
||||
(if appropriate :vlopt:`--coverage` flags are passed) after being
|
||||
disabled earlier with :option:`/*verilator&32;coverage_off*/`.
|
||||
|
||||
.. option:: /*verilator&32;forceable*/
|
||||
|
||||
Specifies that the signal (net or variable) should be made forceable from
|
||||
C++ code by generating public `<signame>__VforceEn` and
|
||||
`<signame>__VforceVal` signals The force control signals are created as
|
||||
:option:`public_flat` signals.
|
||||
|
||||
To force a marked signal from C++, set the corresponding `__VforceVal`
|
||||
variable to the desired value, and the `__VforceEn` signal to the bit-mask
|
||||
indicating which bits of the signal to force. To force all bits of the
|
||||
target signal, set `__VforceEn` to all ones. To release the signal (or part
|
||||
thereof), set appropriate bits of the `__VforceEn` signal to zero.
|
||||
|
||||
Same as :option:`forceable` in configuration files.
|
||||
|
||||
.. _verilator_hier_block:
|
||||
|
||||
@@ -424,7 +445,7 @@ or "`ifdef`"'s may break other tools.
|
||||
.. option:: /*verilator&32;sc_bv*/
|
||||
|
||||
Used after a port declaration. It sets the port to be of
|
||||
:code:`sc_bv<{width}>` type, instead of bool, vluint32_t or vluint64_t.
|
||||
:code:`sc_bv<{width}>` type, instead of bool, uint32_t or uint64_t.
|
||||
This may be useful if the port width is parameterized and the
|
||||
instantiating C++ code wants to always have a sc_bv so it can accept any
|
||||
width. In general you should avoid using this attribute when not
|
||||
@@ -482,6 +503,13 @@ or "`ifdef`"'s may break other tools.
|
||||
Verilator) text that should be passed through to the XML output as a tag,
|
||||
for use by downstream applications.
|
||||
|
||||
.. option:: /*verilator&32;trace_init_task*/
|
||||
|
||||
Attached to a DPI import to indicate that function should be called when
|
||||
initializing tracing. This attribute is indented only to be used
|
||||
internally in code that Verilator generates when :vlopt:`--lib-create`
|
||||
or :vlopt:`--hierarchical` is used along with :vlopt:`--trace`.
|
||||
|
||||
.. option:: /*verilator&32;tracing_off*/
|
||||
|
||||
Disable waveform tracing for all future signals that are declared in
|
||||
|
||||
+41
-23
@@ -1,4 +1,4 @@
|
||||
.. Copyright 2003-2021 by Wilson Snyder.
|
||||
.. Copyright 2003-2022 by Wilson Snyder.
|
||||
.. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
******************************
|
||||
@@ -35,15 +35,17 @@ simulators.
|
||||
Does Verilator run under Windows?
|
||||
"""""""""""""""""""""""""""""""""
|
||||
|
||||
Yes, using Cygwin. Verilated output also compiles under Microsoft Visual
|
||||
C++, but this is not tested every release.
|
||||
Yes, ideally run Ubuntu under Windows Subsystem for Linux (WSL2).
|
||||
Alternatively use Cygwin, though this tends to be slower and is not
|
||||
regularly tested. Verilated output also compiles under Microsoft Visual
|
||||
C++, but this is also not regularly tested.
|
||||
|
||||
|
||||
Can you provide binaries?
|
||||
"""""""""""""""""""""""""
|
||||
|
||||
You can install Verilator via the system package manager (apt, yum, etc.)
|
||||
on many Linux distributions, including Debian, Ubuntu, SuSE, RedHat, and
|
||||
on many Linux distributions, including Debian, Ubuntu, SuSE, Red Hat, and
|
||||
others. These packages are provided by the Linux distributions and
|
||||
generally will lag the version of the mainline Verilator repository. If no
|
||||
binary package is available for your distribution, how about you set one
|
||||
@@ -70,23 +72,38 @@ a good thing for getting working silicon.
|
||||
Will Verilator output remain under my own license/copyright?
|
||||
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
|
||||
Yes, it's just like using GCC on your programs; this is why Verilator uses
|
||||
the "GNU **Lesser** Public License Version 3" instead of the more typical
|
||||
"GNU Public License". See the licenses for details, but in brief, if you
|
||||
change Verilator itself or the header files Verilator includes, you must
|
||||
make the source code available under the GNU Lesser Public License.
|
||||
However, Verilator output (the Verilated code) only "include"s the licensed
|
||||
files, and so you are **not** required to open-source release any output
|
||||
from Verilator.
|
||||
Your SystemVerilog, VPI/DPI, or main() C++ code remains under your own license.
|
||||
|
||||
It's just like how using GCC on your programs does not change the copyright
|
||||
of your program; this is why Verilator uses the "GNU **Lesser** Public
|
||||
License Version 3" instead of the more typical "GNU Public License". See
|
||||
the licenses for details.
|
||||
|
||||
Some examples:
|
||||
|
||||
* Any SystemVerilog or other input fed into Verilator remain your own.
|
||||
|
||||
* Any of your VPI/DPI C++ routines that Verilator calls remain your own.
|
||||
|
||||
* Any of your main() C++ code that calls into Verilator remain your own.
|
||||
|
||||
* If you change Verilator itself, for example changing or adding a file
|
||||
under the src/ directory in the repository, you must make the source code
|
||||
available under the GNU Lesser Public License.
|
||||
|
||||
* If you change a header Verilator provides, for example under include/ in
|
||||
the repository, you must make the source code available under the GNU
|
||||
Lesser Public License.
|
||||
|
||||
You also have the option of using the Perl Artistic License, which again
|
||||
does not require you to release your Verilog or generated code, and also
|
||||
allows you to modify Verilator for internal use without distributing the
|
||||
modified version. But please contribute back to the community!
|
||||
does not require you to release your Verilog, C++, or generated code. This
|
||||
license also allows you to modify Verilator for internal use without
|
||||
distributing the modified version. But please contribute back to the
|
||||
community!
|
||||
|
||||
One limit is that you cannot under either license release a closed-source
|
||||
Verilog simulation product incorporating Verilator. That is you can have a
|
||||
commercial product, but must make the source code available.
|
||||
Under both license you can offer a commercial product that is based on
|
||||
Verilator either directly or embedded within. However under both licenses,
|
||||
any changes you make to Verilator for such a product must be open sourced.
|
||||
|
||||
As is standard with Open Source, contributions back to Verilator will be
|
||||
placed under the Verilator copyright and LGPL/Artistic license. Small test
|
||||
@@ -132,7 +149,8 @@ B. Or, for finer-grained control, or C++ files with multiple Verilated
|
||||
...
|
||||
Verilated::traceEverOn(true);
|
||||
VerilatedVcdC* tfp = new VerilatedVcdC;
|
||||
topp->trace(tfp, 99); // Trace 99 levels of hierarchy
|
||||
topp->trace(tfp, 99); // Trace 99 levels of hierarchy (or see below)
|
||||
// tfp->dumpvars(1, "t"); // trace 1 level under "t"
|
||||
tfp->open("obj_dir/t_trace_ena_cc/simx.vcd");
|
||||
...
|
||||
while (contextp->time() < sim_time && !contextp->gotFinish()) {
|
||||
@@ -351,8 +369,8 @@ also use the "import DPI" SystemVerilog feature to call C code (see the
|
||||
chapter above). There is also limited VPI access to public signals.
|
||||
|
||||
If you want something more complex, since Verilator emits standard C++
|
||||
code, you can simply write your own C++ routines that can access and modify
|
||||
signal values without needing any PLI interface code, and call it with
|
||||
code, you can write your own C++ routines that can access and modify signal
|
||||
values without needing any PLI interface code, and call it with
|
||||
$c("{any_c++_statement}").
|
||||
|
||||
See the :ref:`Connecting` section.
|
||||
@@ -442,7 +460,7 @@ the signal, as you would any other member variable.
|
||||
Signals are the smallest of 8-bit unsigned chars (equivalent to uint8_t),
|
||||
16-bit unsigned shorts (uint16_t), 32-bit unsigned longs (uint32_t), or
|
||||
64-bit unsigned long longs (uint64_t) that fits the width of the signal.
|
||||
Generally, you can use just uint32_t's for 1 to 32 bits, or vluint64_t for
|
||||
Generally, you can use just uint32_t's for 1 to 32 bits, or uint64_t for
|
||||
1 to 64 bits, and the compiler will properly up-convert smaller entities.
|
||||
Note even signed ports are declared as unsigned; you must sign extend
|
||||
yourself to the appropriate signal width.
|
||||
@@ -479,7 +497,7 @@ by your code or you'll get strange results.
|
||||
Should a module be in Verilog or SystemC?
|
||||
"""""""""""""""""""""""""""""""""""""""""
|
||||
|
||||
Sometimes there is a block that just interconnects instances, and have a
|
||||
Sometimes there is a block that only 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
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.. Copyright 2003-2021 by Wilson Snyder.
|
||||
.. Copyright 2003-2022 by Wilson Snyder.
|
||||
.. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
*****
|
||||
@@ -120,7 +120,7 @@ In certain debug and other modes, it also creates:
|
||||
- Debugging graph files (from --debug)
|
||||
* - *{prefix}{misc}*\ .tree
|
||||
- Debugging files (from --debug)
|
||||
* - {mod_prefix}_{each_verilog_module}*{__n}*\ .vpp
|
||||
* - {mod_prefix}_{each_verilog_base_filename}*\ .vpp
|
||||
- Pre-processed verilog (from --debug)
|
||||
|
||||
After running Make, the C++ compiler may produce the following:
|
||||
@@ -155,13 +155,13 @@ The Verilated executable may produce the following:
|
||||
* - gmon.out
|
||||
- GCC/clang code profiler output, often fed into :command:`verilator_profcfunc`
|
||||
* - profile.vlt
|
||||
- -profile data file for :ref:`Thread PGO`
|
||||
* - profile_threads.dat
|
||||
- -profile-threads data file for :command:`verilator_gnatt`
|
||||
- --prof-pgo data file for :ref:`Thread PGO`
|
||||
* - profile_exec.dat
|
||||
- --prof-exec data file for :command:`verilator_gantt`
|
||||
|
||||
Verilator_gantt may produce the following:
|
||||
|
||||
.. list-table::
|
||||
|
||||
* - profile_threads.vcd
|
||||
* - profile_exec.vcd
|
||||
- Gantt report waveform output
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.. Copyright 2003-2021 by Wilson Snyder.
|
||||
.. Copyright 2003-2022 by Wilson Snyder.
|
||||
.. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
######################
|
||||
|
||||
+19
-11
@@ -1,4 +1,4 @@
|
||||
.. Copyright 2003-2021 by Wilson Snyder.
|
||||
.. Copyright 2003-2022 by Wilson Snyder.
|
||||
.. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
.. _Installation:
|
||||
@@ -77,17 +77,17 @@ OS Requirements
|
||||
---------------
|
||||
|
||||
Verilator is developed and has primary testing on Ubuntu, with additional
|
||||
testing on FreeBSD and Apple OS-X. Versions have also built on Redhat
|
||||
Linux, HPUX and Solaris. It should run with minor porting on any
|
||||
GNU/Linux-ish platform. Verilator also works on Windows under Cygwin, and
|
||||
Windows under MinGW (gcc -mno-cygwin). Verilated output (not Verilator
|
||||
itself) compiles under all the options above, plus using MSVC++.
|
||||
testing on FreeBSD and Apple OS-X. Versions have also built on Red Hat
|
||||
Linux, and other flavors of GNU/Linux-ish platforms. Verilator also works
|
||||
on Windows Subsystem for Linux (WSL2), Windows under Cygwin, and Windows
|
||||
under MinGW (gcc -mno-cygwin). Verilated output (not Verilator itself)
|
||||
compiles under all the options above, plus using MSVC++.
|
||||
|
||||
|
||||
Install Prerequisites
|
||||
---------------------
|
||||
|
||||
To build or run Verilator you need these standard packages:
|
||||
To build or run Verilator, you need these standard packages:
|
||||
|
||||
::
|
||||
|
||||
@@ -98,13 +98,20 @@ To build or run Verilator you need these standard packages:
|
||||
sudo apt-get install libfl-dev # Ubuntu only (ignore if gives error)
|
||||
sudo apt-get install zlibc zlib1g zlib1g-dev # Ubuntu only (ignore if gives error)
|
||||
|
||||
To build or run the following are optional but should be installed for good
|
||||
performance:
|
||||
To build or run Verilator, the following are optional but should be installed
|
||||
for good performance:
|
||||
|
||||
::
|
||||
|
||||
sudo apt-get install ccache # If present at build, needed for run
|
||||
sudo apt-get install libgoogle-perftools-dev numactl perl-doc
|
||||
sudo apt-get install libgoogle-perftools-dev numactl
|
||||
|
||||
The following is optional but is recommended for nicely rendered command line
|
||||
help when running Verilator:
|
||||
|
||||
::
|
||||
|
||||
sudo apt-get install perl-doc
|
||||
|
||||
To build Verilator you will need to install these packages; these do not
|
||||
need to be present to run Verilator:
|
||||
@@ -118,7 +125,8 @@ Those developing Verilator itself may also want these (see internals.rst):
|
||||
::
|
||||
|
||||
sudo apt-get install gdb graphviz cmake clang clang-format-11 gprof lcov
|
||||
sudo pip3 install sphinx sphinx_rtd_theme breathe
|
||||
sudo apt-get install yapf3
|
||||
sudo pip3 install sphinx sphinx_rtd_theme sphinxcontrib-spelling breathe
|
||||
cpan install Pod::Perldoc
|
||||
cpan install Parallel::Forker
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.. Copyright 2003-2021 by Wilson Snyder.
|
||||
.. Copyright 2003-2022 by Wilson Snyder.
|
||||
.. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
***************
|
||||
@@ -92,7 +92,7 @@ appropriate code to detect failing cases at simulation runtime and print an
|
||||
|
||||
Verilator likewise also asserts any "unique" or "priority" SystemVerilog
|
||||
keywords on case statement, as well as "unique" on if statements. However,
|
||||
"priority if" is currently simply ignored.
|
||||
"priority if" is currently ignored.
|
||||
|
||||
|
||||
.. _Language Limitations:
|
||||
@@ -136,7 +136,7 @@ ___05F (5F is the hex code of an underscore.)
|
||||
Bind
|
||||
----
|
||||
|
||||
sVerilator only supports bind to a target module name, not to an
|
||||
Verilator only supports bind to a target module name, not to an
|
||||
instance path.
|
||||
|
||||
|
||||
@@ -174,9 +174,9 @@ Structures and Unions
|
||||
---------------------
|
||||
|
||||
Presently Verilator only supports packed structs and packed unions. Rand
|
||||
and randc tags on members are simply ignored. All structures and unions
|
||||
are represented as a single vector, which means that generating one member
|
||||
of a structure from blocking, and another from non-blocking assignments is
|
||||
and randc tags on members are ignored. All structures and unions are
|
||||
represented as a single vector, which means that generating one member of a
|
||||
structure from blocking, and another from non-blocking assignments is
|
||||
unsupported.
|
||||
|
||||
|
||||
@@ -336,6 +336,24 @@ Verilator does not support SEREs yet. All assertion and coverage
|
||||
statements must be simple expressions that complete in one cycle.
|
||||
|
||||
|
||||
Force statement
|
||||
---------------
|
||||
|
||||
Verilator supports the procedural `force` (and corresponding `release`)
|
||||
statement. The behavior of the `force` statement however does not entirely
|
||||
comply with the IEEE 1800 SystemVerilog standard. According to the standard,
|
||||
when a procedural statement of the form `force a = b;` is executed, the
|
||||
simulation should behave as if from that point forwards, a continuous
|
||||
assignment `assign a = b;` have been added to override the drivers of `a`.
|
||||
More specifically: the value of `a` should be updated, whenever the value of
|
||||
`b` changes, all the way until a `release a;` statement is executed.
|
||||
Verilator instead evaluates the current value of `b` at the time the `force`
|
||||
statement is executed, and forces `a` to that value, without updating it
|
||||
until a new `force` or `release` statement is encountered that applies to
|
||||
`a`. This non-standard behavior is nevertheless consistent with some other
|
||||
simulators.
|
||||
|
||||
|
||||
Encrypted Verilog
|
||||
-----------------
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.. Copyright 2003-2021 by Wilson Snyder.
|
||||
.. Copyright 2003-2022 by Wilson Snyder.
|
||||
.. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
********
|
||||
|
||||
+21
-21
@@ -1,4 +1,4 @@
|
||||
.. Copyright 2003-2021 by Wilson Snyder.
|
||||
.. Copyright 2003-2022 by Wilson Snyder.
|
||||
.. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
.. _Simulating:
|
||||
@@ -279,26 +279,25 @@ To use profiling:
|
||||
is being spent.
|
||||
|
||||
|
||||
.. _Thread Profiling:
|
||||
.. _Execution Profiling:
|
||||
|
||||
Thread Profiling
|
||||
================
|
||||
Execution Profiling
|
||||
===================
|
||||
|
||||
When using multithreaded mode (:vlopt:`--threads`), it is useful to see
|
||||
statistics and visualize how well the multiple CPUs are being utilized.
|
||||
For performance optimization, it is useful to see statistics and visualize how
|
||||
execution time is distributed in a verilated model.
|
||||
|
||||
With the :vlopt:`--prof-threads` option, Verilator will:
|
||||
With the :vlopt:`--prof-exec` option, Verilator will:
|
||||
|
||||
* Add code to the Verilated model to record the start and end time of each
|
||||
macro-task across a number of calls to eval. (What is a macro-task? See
|
||||
the Verilator internals document (:file:`docs/internals.rst` in the
|
||||
distribution.)
|
||||
* Add code to the Verilated model to record execution flow.
|
||||
|
||||
* Add code to save profiling data in non-human-friendly form to the file
|
||||
specified with :vlopt:`+verilator+prof+threads+file+\<filename\>`.
|
||||
specified with :vlopt:`+verilator+prof+exec+file+\<filename\>`.
|
||||
|
||||
* Add code to save profiling data for thread profile-guided
|
||||
optimization. See :ref:`Thread PGO`.
|
||||
* In multi-threaded models, add code to record the start and end time of each
|
||||
macro-task across a number of calls to eval. (What is a macro-task? See the
|
||||
Verilator internals document (:file:`docs/internals.rst` in the
|
||||
distribution.)
|
||||
|
||||
The :command:`verilator_gantt` program may then be run to transform the
|
||||
saved profiling file into a nicer visual format and produce some related
|
||||
@@ -406,8 +405,8 @@ others as they prove beneficial.
|
||||
Thread Profile-Guided Optimization
|
||||
----------------------------------
|
||||
|
||||
Verilator supports thread profile-guided optimization (Thread PGO) to
|
||||
improve multithreaded performance.
|
||||
Verilator supports profile-guided optimization (Verilation) of multi-threaded
|
||||
models (Thread PGO) to improve performance.
|
||||
|
||||
When using multithreading, Verilator computes how long macro tasks take and
|
||||
tries to balance those across threads. (What is a macro-task? See the
|
||||
@@ -417,13 +416,14 @@ balanced, leading to decreased performance. Thread PGO allows collecting
|
||||
profiling data to replace the estimates and better optimize these
|
||||
decisions.
|
||||
|
||||
To use Thread PGO, Verilate the model with the :vlopt:`--prof-threads`
|
||||
option.
|
||||
To use Thread PGO, Verilate the model with the :vlopt:`--prof-pgo` option. This
|
||||
will code to the verilated model to save profiling data for profile-guided
|
||||
optimization.
|
||||
|
||||
Run the model executable. When the executable exits, it will create a
|
||||
profile.vlt file.
|
||||
|
||||
Rerun Verilator, optionally omitting the :vlopt:`--prof-threads` option,
|
||||
Rerun Verilator, optionally omitting the :vlopt:`--prof-pgo` option,
|
||||
and adding the profile.vlt generated earlier to the command line.
|
||||
|
||||
Note there is no Verilator equivalent to GCC's --fprofile-use. Verilator's
|
||||
@@ -433,8 +433,8 @@ directly without any prefix.
|
||||
If results from multiple simulations are to be used in generating the
|
||||
optimization, multiple simulation's profile.vlt may be concatenated
|
||||
externally, or each of the files may be fed as separate command line
|
||||
options into Verilator. Verilator will simply sum the profile results, so
|
||||
a longer running test will have proportionally more weight for optimization
|
||||
options into Verilator. Verilator will sum the profile results, so a
|
||||
longer running test will have proportionally more weight for optimization
|
||||
than a shorter running test.
|
||||
|
||||
If you provide any profile feedback data to Verilator, and it cannot use
|
||||
|
||||
+20
-17
@@ -1,4 +1,4 @@
|
||||
.. Copyright 2003-2021 by Wilson Snyder.
|
||||
.. Copyright 2003-2022 by Wilson Snyder.
|
||||
.. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
**********
|
||||
@@ -68,12 +68,11 @@ multi-core SoC.
|
||||
|
||||
Verilator is run in hierarchical mode on the whole SoC. Verilator will
|
||||
make two models, one for the CPU hierarchy block, and one for the SoC. The
|
||||
Verialted code for the SoC will automatically call the CPU Verilated model.
|
||||
Verilated code for the SoC will automatically call the CPU Verilated model.
|
||||
|
||||
The current hierarchical Verilation is based on protect-lib. Each hierarchy
|
||||
block is Verilated to a protect-lib. User modules of the hierarchy blocks
|
||||
will see a tiny wrapper generated by protect-lib instead of the actual
|
||||
design.
|
||||
The current hierarchical Verilation is based on :vlopt:`--lib-create`. Each
|
||||
hierarchy block is Verilated into a library. User modules of the hierarchy
|
||||
blocks will see a tiny wrapper generated by :vlopt:`--lib-create`.
|
||||
|
||||
|
||||
Usage
|
||||
@@ -222,9 +221,13 @@ model, it may be beneficial to performance to adjust the
|
||||
influences the partitioning of the model by adjusting the assumed execution
|
||||
time of DPI imports.
|
||||
|
||||
The :vlopt:`--trace-threads` options can be used to produce trace dumps
|
||||
using multiple threads. If :vlopt:`--trace-threads` is set without
|
||||
:vlopt:`--threads`, then :vlopt:`--trace-threads` will imply
|
||||
When using :vlopt:`--trace` to perform VCD tracing, the VCD trace
|
||||
construction is parallelized using the same number of threads as specified
|
||||
with :vlopt:`--threads`, and is executed on the same thread pool as the model.
|
||||
|
||||
The :vlopt:`--trace-threads` options can be used with :vlopt:`--trace-fst`
|
||||
to offload FST tracing using multiple threads. If :vlopt:`--trace-threads` is
|
||||
given without :vlopt:`--threads`, then :vlopt:`--trace-threads` will imply
|
||||
:vlopt:`--threads 1 <--threads>`, i.e.: the support libraries will be
|
||||
thread safe.
|
||||
|
||||
@@ -232,12 +235,12 @@ With :vlopt:`--trace-threads 0 <--trace-threads>`, trace dumps are produced
|
||||
on the main thread. This again gives the highest single thread performance.
|
||||
|
||||
With :vlopt:`--trace-threads {N} <--trace-threads>`, where N is at least 1,
|
||||
N additional threads will be created and managed by the trace files (e.g.:
|
||||
VerilatedVcdC or VerilatedFstC), to generate the trace dump. The main
|
||||
thread will be released to proceed with execution as soon as possible,
|
||||
though some blocking of the main thread is still necessary while capturing
|
||||
the trace. Different trace formats can utilize a various number of
|
||||
threads. See the :vlopt:`--trace-threads` option.
|
||||
up to N additional threads will be created and managed by the trace files
|
||||
(e.g.: VerilatedFstC), to offload construction of the trace dump. The main
|
||||
thread will be released to proceed with execution as soon as possible, though
|
||||
some blocking of the main thread is still necessary while capturing the
|
||||
trace. FST tracing can utilize up to 2 offload threads, so there is no use
|
||||
of setting :vlopt:`--trace-threads` higher than 2 at the moment.
|
||||
|
||||
When running a multithreaded model, the default Linux task scheduler often
|
||||
works against the model, by assuming threads are short lived, and thus
|
||||
@@ -266,7 +269,7 @@ This will limit memory to socket 0, and threads to cores 0, 1, 2, 3,
|
||||
(presumably on socket 0) optimizing performance. Of course this must be
|
||||
adjusted if you want another simulator using e.g. socket 1, or if you
|
||||
Verilated with a different number of threads. To see what CPUs are
|
||||
actually used, use :vlopt:`--prof-threads`.
|
||||
actually used, use :vlopt:`--prof-exec`.
|
||||
|
||||
|
||||
Multithreaded Verilog and Library Support
|
||||
@@ -442,7 +445,7 @@ SystemC include directories and link to the SystemC libraries.
|
||||
|
||||
.. describe:: TRACE_THREADS
|
||||
|
||||
Optional. Generated multi-threaded trace dumping, same as
|
||||
Optional. Generated multi-threaded FST trace dumping, same as
|
||||
"--trace-threads".
|
||||
|
||||
.. describe:: TOP_MODULE
|
||||
|
||||
+14
-14
@@ -1,4 +1,4 @@
|
||||
.. Copyright 2003-2021 by Wilson Snyder.
|
||||
.. Copyright 2003-2022 by Wilson Snyder.
|
||||
.. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
*******************
|
||||
@@ -12,7 +12,7 @@ Disabling Warnings
|
||||
Warnings may be disabled in multiple ways:
|
||||
|
||||
#. Disable the warning in the source code. When the warning is printed it
|
||||
will include a warning code. Simply surround the offending line with a
|
||||
will include a warning code. Surround the offending line with a
|
||||
:code:`/*verilator&32;lint_off*/` and :code:`/*verilator&32;lint_on*/`
|
||||
metacomment pair:
|
||||
|
||||
@@ -162,7 +162,7 @@ List Of Warnings
|
||||
always @(posedge clk) foo[0] <= ...
|
||||
always_comb foo[1] = ...
|
||||
|
||||
Simply use a different register for the flop:
|
||||
Instead use a different register for the flop:
|
||||
|
||||
.. code-block:: sv
|
||||
|
||||
@@ -284,7 +284,7 @@ List Of Warnings
|
||||
|
||||
.. TODO better example
|
||||
|
||||
Warns that it is simply better style to use casez, and "?" in place of
|
||||
Warns that it is better style to use casez, and "?" in place of
|
||||
"x"'s. See
|
||||
`http://www.sunburst-design.com/papers/CummingsSNUG1999Boston_FullParallelCase_rev1_1.pdf
|
||||
<http://www.sunburst-design.com/papers/CummingsSNUG1999Boston_FullParallelCase_rev1_1.pdf>`_
|
||||
@@ -447,7 +447,7 @@ List Of Warnings
|
||||
p0();
|
||||
endmodule
|
||||
|
||||
Other tools with similar warnings: Veriable's forbid_defparam_rule.
|
||||
Other tools with similar warnings: Verible's forbid_defparam_rule.
|
||||
|
||||
|
||||
.. option:: DEPRECATED
|
||||
@@ -518,7 +518,7 @@ List Of Warnings
|
||||
Another way DIDNOTCONVERGE may occur is if # delays are used to generate
|
||||
clocks. Verilator ignores the delays and gives an :option:`ASSIGNDLY`
|
||||
or :option:`STMTDLY` warning. If these were suppressed, due to the
|
||||
absense of the delay, the code may now oscillate.
|
||||
absence of the delay, the code may now oscillate.
|
||||
|
||||
Finally, rare, more difficult cases can be debugged like a C++ program;
|
||||
either enter :command:`gdb` and use its tracing facilities, or edit the
|
||||
@@ -528,7 +528,7 @@ List Of Warnings
|
||||
.. option:: ENDCAPSULATED
|
||||
|
||||
Warns that a class member is declared is local or protected, but is
|
||||
being accessed from outside that class (if local) or a derrived class
|
||||
being accessed from outside that class (if local) or a derived class
|
||||
(if protected).
|
||||
|
||||
Ignoring this warning will only suppress the lint check, it will
|
||||
@@ -924,7 +924,7 @@ List Of Warnings
|
||||
simulate correctly.
|
||||
|
||||
Other tools with similar warnings: Icarus Verilog's portbind, "warning:
|
||||
Instantiating module ... with dangling impot port (...)". Slang's
|
||||
Instantiating module ... with dangling input port (...)". Slang's
|
||||
unconnected-port, "port '...' has no connection".
|
||||
|
||||
|
||||
@@ -1212,12 +1212,12 @@ List Of Warnings
|
||||
.. include:: ../../docs/gen/ex_STMTDLY_msg.rst
|
||||
|
||||
This is a warning because Verilator does not support delayed statements.
|
||||
It will simply ignore all such delays. In many cases ignoring a delay
|
||||
might be harmless, but if the delayed statement is, as in this example,
|
||||
used to cause some important action at a later time, it might be an
|
||||
important difference.
|
||||
It will ignore all such delays. In many cases ignoring a delay might be
|
||||
harmless, but if the delayed statement is, as in this example, used to
|
||||
cause some important action at a later time, it might be an important
|
||||
difference.
|
||||
|
||||
Some possible work arounds:
|
||||
Some possible workarounds:
|
||||
|
||||
* Move the delayed statement into the C++ wrapper file, where the
|
||||
stimulus and clock generation can be done in C++.
|
||||
@@ -1506,7 +1506,7 @@ List Of Warnings
|
||||
Error that a construct might be legal according to IEEE but is not
|
||||
currently supported by Verilator.
|
||||
|
||||
A typical workaround is to recode the construct into a simpler and more
|
||||
A typical workaround is to rewrite the construct into a simpler and more
|
||||
common alternative language construct.
|
||||
|
||||
Alternatively, check if the construct is supported by other tools, and
|
||||
|
||||
+18
-18
@@ -114,11 +114,11 @@ By convention, each function/method uses the variable ``nodep`` as a
|
||||
pointer to the ``AstNode`` currently being processed.
|
||||
|
||||
|
||||
``AstNVisitor``
|
||||
``VNVisitor``
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
The passes are implemented by AST visitor classes. These are implemented by
|
||||
subclasses of the abstract class, ``AstNVisitor``. Each pass creates an
|
||||
subclasses of the abstract class, ``VNVisitor``. Each pass creates an
|
||||
instance of the visitor class, which in turn implements a method to perform
|
||||
the pass.
|
||||
|
||||
@@ -268,13 +268,13 @@ Estimating Logic Costs
|
||||
|
||||
To compute the cost of any given path through the graph, Verilator
|
||||
estimates an execution cost for each task. Each macro-task has an execution
|
||||
cost which is simply the sum of its tasks' costs. We assume that
|
||||
communication overhead and synchronization overhead are zero, so the cost
|
||||
of any given path through the graph is simply the sum of macro-task
|
||||
execution costs. Sarkar does almost the same thing, except that he has
|
||||
nonzero estimates for synchronization costs.
|
||||
cost which is the sum of its tasks' costs. We assume that communication
|
||||
overhead and synchronization overhead are zero, so the cost of any given
|
||||
path through the graph is the sum of macro-task execution costs. Sarkar
|
||||
does almost the same thing, except that he has nonzero estimates for
|
||||
synchronization costs.
|
||||
|
||||
Verilator's cost estimates are assigned by ``InstrCountCostVisitor``. This
|
||||
Verilator's cost estimates are assigned by ``InstrCountVisitor``. This
|
||||
class is perhaps the most fragile piece of the multithread
|
||||
implementation. It's easy to have a bug where you count something cheap
|
||||
(eg. accessing one element of a huge array) as if it were expensive (eg.
|
||||
@@ -301,7 +301,7 @@ prerequisites on other threads have finished.
|
||||
|
||||
The synchronization cost is cheap if the prereqs are done. If they're not,
|
||||
fragmentation (idle CPU cores waiting) is possible. This is the major
|
||||
source of overhead in this approach. The ``--prof-threads`` switch and the
|
||||
source of overhead in this approach. The ``--prof-exec`` switch and the
|
||||
``verilator_gantt`` script can visualize the time lost to such
|
||||
fragmentation.
|
||||
|
||||
@@ -523,10 +523,10 @@ optimization passes. This allows separation of the pass algorithm from the
|
||||
AST on which it operates. Wikipedia provides an introduction to the concept
|
||||
at https://en.wikipedia.org/wiki/Visitor_pattern.
|
||||
|
||||
As noted above, all visitors are derived classes of ``AstNVisitor``. All
|
||||
As noted above, all visitors are derived classes of ``VNVisitor``. All
|
||||
derived classes of ``AstNode`` implement the ``accept`` method, which takes
|
||||
as argument a reference to an instance or a ``AstNVisitor`` derived class
|
||||
and applies the visit method of the ``AstNVisitor`` to the invoking AstNode
|
||||
as argument a reference to an instance or a ``VNVisitor`` derived class
|
||||
and applies the visit method of the ``VNVisitor`` to the invoking AstNode
|
||||
instance (i.e. ``this``).
|
||||
|
||||
One possible difficulty is that a call to ``accept`` may perform an edit
|
||||
@@ -604,8 +604,8 @@ There are three ways data is passed between visitor functions.
|
||||
Iterators
|
||||
---------
|
||||
|
||||
``AstNVisitor`` provides a set of iterators to facilitate walking over
|
||||
the tree. Each operates on the current ``AstNVisitor`` class (as this)
|
||||
``VNVisitor`` provides a set of iterators to facilitate walking over
|
||||
the tree. Each operates on the current ``VNVisitor`` class (as this)
|
||||
and takes an argument type ``AstNode*``.
|
||||
|
||||
``iterate``
|
||||
@@ -817,7 +817,7 @@ which you can install using cpan.
|
||||
|
||||
There are some traps to avoid when running regression tests
|
||||
|
||||
- When checking the MANIFEST, the test will barf on unexpected code in the
|
||||
- When checking the MANIFEST, the test will fail on unexpected code in the
|
||||
Verilator tree. So make sure to keep any such code outside the tree.
|
||||
|
||||
- Not all Linux systems install Perldoc by default. This is needed for the
|
||||
@@ -1183,10 +1183,10 @@ Verilator ideally would support all of IEEE, and has the goal to get close
|
||||
to full support. However the following IEEE sections and features are not
|
||||
anticipated to be ever implemented for the reasons indicated.
|
||||
|
||||
IEEE 1800-2017 3.3 recursive modules
|
||||
IEEE 1800-2017 3.3 modules within modules
|
||||
Little/no tool support, and arguably not a good practice.
|
||||
IEEE 1800-2017 6.12 "shortreal"
|
||||
Little/no tool support, and easily simply promoted to real.
|
||||
Little/no tool support, and easily promoted to real.
|
||||
IEEE 1800-2017 11.11 Min, typ, max
|
||||
No SDF support so will always use typical.
|
||||
IEEE 1800-2017 11.12 "let"
|
||||
@@ -1208,7 +1208,7 @@ IEEE 1800-2017 33 Config
|
||||
Distribution
|
||||
============
|
||||
|
||||
Copyright 2008-2021 by Wilson Snyder. Verilator is free software; you can
|
||||
Copyright 2008-2022 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.
|
||||
|
||||
|
||||
@@ -2,9 +2,11 @@ ABCp
|
||||
Accellera
|
||||
Affe
|
||||
Aleksander
|
||||
Alexandre
|
||||
Ami
|
||||
Amir
|
||||
Anastasiadis
|
||||
Anikin
|
||||
Antonin
|
||||
Antwerpen
|
||||
Arasanipalai
|
||||
@@ -70,6 +72,7 @@ Eda
|
||||
Eddleston
|
||||
Egbert
|
||||
Egil
|
||||
Ehab
|
||||
Eiler
|
||||
Eivind
|
||||
El
|
||||
@@ -82,6 +85,7 @@ Fabrizio
|
||||
Fekete
|
||||
Ferrandi
|
||||
Flachs
|
||||
Flavien
|
||||
Foletto
|
||||
Forker
|
||||
Francillon
|
||||
@@ -104,6 +108,7 @@ Goessling
|
||||
Gonnen
|
||||
Goorah
|
||||
Gossner
|
||||
Graybeal
|
||||
Grobman
|
||||
Gunter
|
||||
Guo
|
||||
@@ -121,6 +126,7 @@ Hornung
|
||||
Hossell
|
||||
Hsu
|
||||
Hyperthreading
|
||||
Ibrahim
|
||||
Iles
|
||||
Inlines
|
||||
Inout
|
||||
@@ -134,6 +140,7 @@ Jannis
|
||||
Jens
|
||||
Jeras
|
||||
Jiuyang
|
||||
Joannou
|
||||
Joly
|
||||
Jullien
|
||||
Junji
|
||||
@@ -147,6 +154,7 @@ Kamendje
|
||||
Kandadi
|
||||
Kaplan
|
||||
Karge
|
||||
Karlsson
|
||||
Katz
|
||||
Katzman
|
||||
Keren
|
||||
@@ -161,6 +169,7 @@ Kolecki
|
||||
Koonce
|
||||
Korteland
|
||||
Koszek
|
||||
Kouping
|
||||
Kravitz
|
||||
Krolnik
|
||||
Kruse
|
||||
@@ -194,6 +203,7 @@ Mednick
|
||||
Michiels
|
||||
Microsystems
|
||||
Milanovic
|
||||
Millis
|
||||
MinW
|
||||
Mindspeed
|
||||
Miodrag
|
||||
@@ -224,12 +234,14 @@ Petr
|
||||
Piechotka
|
||||
Piersall
|
||||
Plunkett
|
||||
Popolon
|
||||
Popov
|
||||
Prabhat
|
||||
Prabhu
|
||||
Prateek
|
||||
Pre
|
||||
Preprocess
|
||||
Pretet
|
||||
Priyadharshini
|
||||
Pullup
|
||||
Pulver
|
||||
@@ -262,12 +274,15 @@ Shi
|
||||
Shinkarovsky
|
||||
Shirakawa
|
||||
Shuba
|
||||
Shunyao
|
||||
Slatter
|
||||
SoC
|
||||
Sobhan
|
||||
Sokorac
|
||||
Solaris
|
||||
Solomatnikov
|
||||
Solt
|
||||
Southwell
|
||||
Srini
|
||||
Stamness
|
||||
Stephane
|
||||
@@ -286,6 +301,7 @@ SystemVerilog
|
||||
Takatsukasa
|
||||
Tambe
|
||||
Tariq
|
||||
Tejada
|
||||
Tengstrand
|
||||
Terpstra
|
||||
Thiede
|
||||
@@ -293,8 +309,10 @@ Thierry
|
||||
Thyer
|
||||
Tichelaar
|
||||
Tomov
|
||||
Tood
|
||||
Topa
|
||||
Tota
|
||||
Trefor
|
||||
Tresidder
|
||||
Tri
|
||||
Tristate
|
||||
@@ -304,11 +322,13 @@ Ubixum
|
||||
Uints
|
||||
Undefines
|
||||
Unsized
|
||||
Urbach
|
||||
Uselib
|
||||
Usha
|
||||
Usuario
|
||||
VERILATOR
|
||||
Vasu
|
||||
Vdeeptemp
|
||||
Vdly
|
||||
Vemumtab
|
||||
Vemuri
|
||||
@@ -351,7 +371,9 @@ Zhang
|
||||
abirkmanis
|
||||
accessor
|
||||
accessors
|
||||
adrienlemasle
|
||||
agrobman
|
||||
ahouska
|
||||
al
|
||||
ala
|
||||
andit
|
||||
@@ -372,8 +394,12 @@ backtrace
|
||||
backtraces
|
||||
basename
|
||||
bbox
|
||||
benchmarking
|
||||
biguint
|
||||
biops
|
||||
bitOpTree
|
||||
bitOpTree
|
||||
bitop
|
||||
bitstoreal
|
||||
blackbox
|
||||
bokke
|
||||
@@ -389,6 +415,7 @@ casez
|
||||
casted
|
||||
cb
|
||||
ccache
|
||||
ccall
|
||||
cdc
|
||||
ceil
|
||||
celldefine
|
||||
@@ -411,6 +438,8 @@ concat
|
||||
concats
|
||||
config
|
||||
const
|
||||
constexpr
|
||||
constpool
|
||||
coredump
|
||||
countbits
|
||||
countones
|
||||
@@ -426,6 +455,7 @@ da
|
||||
dat
|
||||
datadir
|
||||
datafiles
|
||||
david
|
||||
ddd
|
||||
deassign
|
||||
debugi
|
||||
@@ -434,6 +464,7 @@ defname
|
||||
defparam
|
||||
demangling
|
||||
der
|
||||
dereference
|
||||
desassign
|
||||
destructor
|
||||
detections
|
||||
@@ -462,6 +493,7 @@ dumpvars
|
||||
dut
|
||||
dx
|
||||
elab
|
||||
elike
|
||||
elsif
|
||||
endcase
|
||||
endcelldefine
|
||||
@@ -480,15 +512,18 @@ enums
|
||||
env
|
||||
envvar
|
||||
eof
|
||||
errae
|
||||
erroring
|
||||
et
|
||||
eval
|
||||
evals
|
||||
exe
|
||||
executables
|
||||
expr
|
||||
extern
|
||||
fanin
|
||||
fasttrace
|
||||
fauto
|
||||
fbranch
|
||||
fclose
|
||||
fdisplay
|
||||
@@ -503,6 +538,7 @@ filt
|
||||
flto
|
||||
flushCall
|
||||
fopen
|
||||
forceable
|
||||
foreach
|
||||
fprintf
|
||||
fprofile
|
||||
@@ -521,6 +557,7 @@ funcs
|
||||
fwrite
|
||||
gantt
|
||||
gcc
|
||||
gcda
|
||||
gdb
|
||||
genblk
|
||||
genvar
|
||||
@@ -552,6 +589,7 @@ incdir
|
||||
includer
|
||||
inferfaces
|
||||
inhibitSim
|
||||
initarray
|
||||
initializer
|
||||
initializers
|
||||
inits
|
||||
@@ -570,6 +608,7 @@ killua
|
||||
lang
|
||||
lcov
|
||||
ld
|
||||
leavinel
|
||||
len
|
||||
libext
|
||||
libgoogle
|
||||
@@ -584,6 +623,7 @@ ln
|
||||
loc
|
||||
localparam
|
||||
localparams
|
||||
localtime
|
||||
logicals
|
||||
longint
|
||||
lsb
|
||||
@@ -618,6 +658,7 @@ multithreaded
|
||||
multithreading
|
||||
mutexes
|
||||
mux
|
||||
myftptoyman
|
||||
mysignal
|
||||
namespace
|
||||
nand
|
||||
@@ -642,15 +683,19 @@ onehot
|
||||
ooo
|
||||
oprofile
|
||||
oversubscription
|
||||
parallelized
|
||||
param
|
||||
parameterized
|
||||
params
|
||||
parens
|
||||
pawel
|
||||
pc
|
||||
pdf
|
||||
perf
|
||||
perftools
|
||||
pgo
|
||||
picoChip
|
||||
pinIndex
|
||||
pinout
|
||||
plusargs
|
||||
pmos
|
||||
@@ -676,6 +721,7 @@ prev
|
||||
printf
|
||||
printtimescale
|
||||
profcfunc
|
||||
profiler
|
||||
prototyptes
|
||||
ps
|
||||
pthread
|
||||
@@ -703,12 +749,14 @@ regs
|
||||
reloop
|
||||
resetall
|
||||
respecified
|
||||
rodata
|
||||
rr
|
||||
rst
|
||||
runtime
|
||||
runtimes
|
||||
rw
|
||||
sVerilator
|
||||
sawatzke
|
||||
sc
|
||||
scalared
|
||||
sccanf
|
||||
@@ -724,6 +772,7 @@ specparam
|
||||
splitme
|
||||
spp
|
||||
sqrt
|
||||
src
|
||||
srcdir
|
||||
srcfile
|
||||
sscanf
|
||||
@@ -743,6 +792,7 @@ subcells
|
||||
subexpressions
|
||||
submodule
|
||||
submodules
|
||||
substring
|
||||
sv
|
||||
svBitVal
|
||||
svBitVecVal
|
||||
@@ -777,6 +827,7 @@ trunc
|
||||
txt
|
||||
typ
|
||||
typedef
|
||||
typedef'ed
|
||||
typedefed
|
||||
typedefs
|
||||
typename
|
||||
@@ -790,6 +841,7 @@ uniquified
|
||||
unistd
|
||||
unlink
|
||||
unlinked
|
||||
unnamedblk
|
||||
unopt
|
||||
unoptflat
|
||||
unoptimizable
|
||||
@@ -839,11 +891,14 @@ writeme
|
||||
writemem
|
||||
writememb
|
||||
writememh
|
||||
xiak
|
||||
xin
|
||||
xml
|
||||
xnor
|
||||
xout
|
||||
xuejiazidi
|
||||
yanx
|
||||
ypq
|
||||
yurivict
|
||||
zdave
|
||||
Øyvind
|
||||
|
||||
+1
-4
@@ -46,9 +46,6 @@ The XML document consists of 4 sections within the top level
|
||||
hierarchy. Each instance is represented with the ``<cell>`` element
|
||||
with the following attributes:
|
||||
|
||||
- ``fl`` (deprecated): The file id and line number where the module
|
||||
was instanced. Use ``loc`` instead.
|
||||
|
||||
- ``loc``: The file id, first line number, last line number, first
|
||||
column number and last column number of the identifier where the
|
||||
module was instanced, separated by commas.
|
||||
@@ -73,7 +70,7 @@ The XML document consists of 4 sections within the top level
|
||||
Distribution
|
||||
============
|
||||
|
||||
Copyright 2020-2021 by Wilson Snyder. Verilator is free software; you can
|
||||
Copyright 2020-2022 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.
|
||||
|
||||
|
||||
@@ -99,7 +99,7 @@ run:
|
||||
|
||||
@echo "-- DONE --------------------"
|
||||
@echo "Note: Once this example is understood, see examples/cmake_tracing_sc."
|
||||
@echo "Note: Also see the EXAMPLE section in the verilator manpage/document."
|
||||
@echo "Note: See also https://verilator.org/guide/latest/examples.html"
|
||||
|
||||
clean mostlyclean distclean maintainer-clean:
|
||||
@rm -rf build logs
|
||||
|
||||
@@ -33,5 +33,5 @@ add_executable(example ../make_tracing_c/sim_main.cpp)
|
||||
# Add the Verilated circuit to the target
|
||||
verilate(example COVERAGE TRACE
|
||||
INCLUDE_DIRS "../make_tracing_c"
|
||||
VERILATOR_ARGS -f ../make_tracing_c/input.vc -Os -x-assign 0
|
||||
VERILATOR_ARGS -f ../make_tracing_c/input.vc -x-assign fast
|
||||
SOURCES ../make_tracing_c/top.v)
|
||||
|
||||
@@ -45,7 +45,7 @@ set_property(
|
||||
# Add the Verilated circuit to the target
|
||||
verilate(example SYSTEMC COVERAGE TRACE
|
||||
INCLUDE_DIRS "../make_tracing_sc"
|
||||
VERILATOR_ARGS -f ../make_tracing_sc/input.vc -Os -x-assign 0
|
||||
VERILATOR_ARGS -f ../make_tracing_sc/input.vc -x-assign fast
|
||||
SOURCES ../make_tracing_sc/top.v)
|
||||
|
||||
verilator_link_systemc(example)
|
||||
|
||||
@@ -40,7 +40,7 @@ default:
|
||||
obj_dir/Vtop
|
||||
@echo "-- DONE --------------------"
|
||||
@echo "Note: Once this example is understood, see examples/make_tracing_c."
|
||||
@echo "Note: Also see the EXAMPLE section in the verilator manpage/document."
|
||||
@echo "Note: See also https://verilator.org/guide/latest/examples.html"
|
||||
|
||||
######################################################################
|
||||
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
// any use, without warranty, 2017 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
// See also the EXAMPLE section in the verilator manpage/document.
|
||||
// See also https://verilator.org/guide/latest/examples.html"
|
||||
|
||||
module top;
|
||||
initial begin
|
||||
$display("Hello World!");
|
||||
|
||||
@@ -49,7 +49,7 @@ run:
|
||||
obj_dir/Vtop
|
||||
@echo "-- DONE --------------------"
|
||||
@echo "Note: Once this example is understood, see examples/make_tracing_sc."
|
||||
@echo "Note: Also see the EXAMPLE section in the verilator manpage/document."
|
||||
@echo "Note: See also https://verilator.org/guide/latest/examples.html"
|
||||
|
||||
######################################################################
|
||||
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
// any use, without warranty, 2017 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
// See also the EXAMPLE section in the verilator manpage/document.
|
||||
// See also https://verilator.org/guide/latest/examples.html"
|
||||
|
||||
module top;
|
||||
initial begin
|
||||
$display("Hello World!");
|
||||
|
||||
@@ -33,7 +33,7 @@ VERILATOR_FLAGS =
|
||||
# Generate C++
|
||||
VERILATOR_FLAGS += -cc
|
||||
# Optimize
|
||||
VERILATOR_FLAGS += -Os -x-assign 0
|
||||
VERILATOR_FLAGS += -x-assign fast
|
||||
# Warn abount lint issues; may not want this on less solid designs
|
||||
VERILATOR_FLAGS += -Wall
|
||||
# This example does not use vl_time_stamp but rather
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
// any use, without warranty, 2019 by Todd Strader.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
// See also the EXAMPLE section in the verilator manpage/document.
|
||||
// See also https://verilator.org/guide/latest/examples.html"
|
||||
|
||||
module top (input clk);
|
||||
|
||||
integer cyc = 0;
|
||||
|
||||
@@ -36,7 +36,7 @@ VERILATOR_FLAGS += -cc --exe
|
||||
# Generate makefile dependencies (not shown as complicates the Makefile)
|
||||
#VERILATOR_FLAGS += -MMD
|
||||
# Optimize
|
||||
VERILATOR_FLAGS += -Os -x-assign 0
|
||||
VERILATOR_FLAGS += -x-assign fast
|
||||
# Warn abount lint issues; may not want this on less solid designs
|
||||
VERILATOR_FLAGS += -Wall
|
||||
# Make waveforms
|
||||
|
||||
@@ -34,6 +34,8 @@ int main(int argc, char** argv, char** env) {
|
||||
// Using unique_ptr is similar to
|
||||
// "VerilatedContext* contextp = new VerilatedContext" then deleting at end.
|
||||
const std::unique_ptr<VerilatedContext> contextp{new VerilatedContext};
|
||||
// Do not instead make Vtop as a file-scope static variable, as the
|
||||
// "C++ static initialization order fiasco" may cause a crash
|
||||
|
||||
// Set debug level, 0 is off, 9 is highest presently used
|
||||
// May be overridden by commandArgs argument parsing
|
||||
@@ -69,7 +71,7 @@ int main(int argc, char** argv, char** env) {
|
||||
// Historical note, before Verilator 4.200 Verilated::gotFinish()
|
||||
// was used above in place of contextp->gotFinish().
|
||||
// Most of the contextp-> calls can use Verilated:: calls instead;
|
||||
// the Verilated:: versions simply assume there's a single context
|
||||
// the Verilated:: versions just assume there's a single context
|
||||
// being used (per thread). It's faster and clearer to use the
|
||||
// newer contextp-> versions.
|
||||
|
||||
@@ -103,8 +105,8 @@ int main(int argc, char** argv, char** env) {
|
||||
top->eval();
|
||||
|
||||
// Read outputs
|
||||
VL_PRINTF("[%" VL_PRI64 "d] clk=%x rstl=%x iquad=%" VL_PRI64 "x"
|
||||
" -> oquad=%" VL_PRI64 "x owide=%x_%08x_%08x\n",
|
||||
VL_PRINTF("[%" PRId64 "] clk=%x rstl=%x iquad=%" PRIx64 " -> oquad=%" PRIx64
|
||||
" owide=%x_%08x_%08x\n",
|
||||
contextp->time(), top->clk, top->reset_l, top->in_quad, top->out_quad,
|
||||
top->out_wide[2], top->out_wide[1], top->out_wide[0]);
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ VERILATOR_FLAGS += -sc --exe
|
||||
# Generate makefile dependencies (not shown as complicates the Makefile)
|
||||
#VERILATOR_FLAGS += -MMD
|
||||
# Optimize
|
||||
VERILATOR_FLAGS += -Os -x-assign 0
|
||||
VERILATOR_FLAGS += -x-assign fast
|
||||
# Warn abount lint issues; may not want this on less solid designs
|
||||
VERILATOR_FLAGS += -Wall
|
||||
# Make waveforms
|
||||
|
||||
@@ -58,11 +58,11 @@ int sc_main(int argc, char* argv[]) {
|
||||
|
||||
// Define interconnect
|
||||
sc_signal<bool> reset_l;
|
||||
sc_signal<vluint32_t> in_small;
|
||||
sc_signal<vluint64_t> in_quad;
|
||||
sc_signal<uint32_t> in_small;
|
||||
sc_signal<uint64_t> in_quad;
|
||||
sc_signal<sc_bv<70>> in_wide;
|
||||
sc_signal<vluint32_t> out_small;
|
||||
sc_signal<vluint64_t> out_quad;
|
||||
sc_signal<uint32_t> out_small;
|
||||
sc_signal<uint64_t> out_quad;
|
||||
sc_signal<sc_bv<70>> out_wide;
|
||||
|
||||
// Construct the Verilated model, from inside Vtop.h
|
||||
|
||||
@@ -140,6 +140,10 @@ void **JenkinsIns(void *base_i, const unsigned char *mem, uint32_t length, uint3
|
||||
#include <sys/sysctl.h>
|
||||
#endif
|
||||
|
||||
#if defined(FST_MACOSX) || defined(__MINGW32__) || defined(__OpenBSD__) || defined(__FreeBSD__)
|
||||
#define FST_UNBUFFERED_IO
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
/* Boolean expression more often true than false */
|
||||
#define FST_LIKELY(x) __builtin_expect(!!(x), 1)
|
||||
@@ -4577,12 +4581,11 @@ if(sectype == FST_BL_ZWRAPPER)
|
||||
if(!fcomp) { tmpfile_close(&fcomp, &xc->f_nam); return(0); }
|
||||
}
|
||||
|
||||
#if defined(FST_MACOSX)
|
||||
#if defined(FST_UNBUFFERED_IO)
|
||||
setvbuf(fcomp, (char *)NULL, _IONBF, 0); /* keeps gzip from acting weird in tandem with fopen */
|
||||
#endif
|
||||
|
||||
#ifdef __MINGW32__
|
||||
setvbuf(fcomp, (char *)NULL, _IONBF, 0); /* keeps gzip from acting weird in tandem with fopen */
|
||||
xc->filename_unpacked = hf;
|
||||
#else
|
||||
if(hf)
|
||||
@@ -4880,7 +4883,7 @@ if((!nam)||(!(xc->f=fopen(nam, "rb"))))
|
||||
char *hf = (char *)calloc(1, flen + 6);
|
||||
int rc;
|
||||
|
||||
#if defined(__MINGW32__) || defined(FST_MACOSX)
|
||||
#if defined(FST_UNBUFFERED_IO)
|
||||
setvbuf(xc->f, (char *)NULL, _IONBF, 0); /* keeps gzip from acting weird in tandem with fopen */
|
||||
#endif
|
||||
|
||||
|
||||
+220
-158
@@ -3,7 +3,7 @@
|
||||
//
|
||||
// Code available from: https://verilator.org
|
||||
//
|
||||
// Copyright 2003-2021 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2022 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 @@
|
||||
//=========================================================================
|
||||
// Internal note:
|
||||
//
|
||||
// verilated.o may exist both in protect-lib (incrementally linked .a/.so)
|
||||
// verilated.o may exist both in --lib-create (incrementally linked .a/.so)
|
||||
// and the main module. Both refer the same instance of static
|
||||
// variables/VL_THREAD_LOCAL in verilated.o such as Verilated, or
|
||||
// VerilatedImpData. This is important to share that state, but the
|
||||
@@ -55,6 +55,7 @@
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <cerrno>
|
||||
#include <cstdlib>
|
||||
#include <sstream>
|
||||
#include <sys/stat.h> // mkdir
|
||||
#include <list>
|
||||
@@ -73,10 +74,10 @@ constexpr unsigned VL_VALUE_STRING_MAX_WIDTH = 8192;
|
||||
//===========================================================================
|
||||
// Static sanity checks
|
||||
|
||||
static_assert(sizeof(vluint8_t) == 1, "vluint8_t is missized");
|
||||
static_assert(sizeof(vluint16_t) == 2, "vluint8_t is missized");
|
||||
static_assert(sizeof(vluint32_t) == 4, "vluint8_t is missized");
|
||||
static_assert(sizeof(vluint64_t) == 8, "vluint8_t is missized");
|
||||
static_assert(sizeof(uint8_t) == 1, "uint8_t is missized");
|
||||
static_assert(sizeof(uint16_t) == 2, "uint8_t is missized");
|
||||
static_assert(sizeof(uint32_t) == 4, "uint8_t is missized");
|
||||
static_assert(sizeof(uint64_t) == 8, "uint8_t is missized");
|
||||
|
||||
//===========================================================================
|
||||
// Global variables
|
||||
@@ -168,6 +169,19 @@ void vl_stop_maybe(const char* filename, int linenum, const char* hier, bool may
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef VL_USER_WARN ///< Define this to override the vl_warn function
|
||||
void vl_warn(const char* filename, int linenum, const char* hier, const char* msg) VL_MT_UNSAFE {
|
||||
if (false && hier) {}
|
||||
if (filename && filename[0]) {
|
||||
// Not VL_PRINTF_MT, already on main thread
|
||||
VL_PRINTF("%%Warning: %s:%d: %s\n", filename, linenum, msg);
|
||||
} else {
|
||||
VL_PRINTF("%%Warning: %s\n", msg);
|
||||
}
|
||||
Verilated::runFlushCallbacks();
|
||||
}
|
||||
#endif
|
||||
|
||||
//===========================================================================
|
||||
// Wrapper to call certain functions via messages when multithreaded
|
||||
|
||||
@@ -201,6 +215,16 @@ void VL_FATAL_MT(const char* filename, int linenum, const char* hier, const char
|
||||
#endif
|
||||
}
|
||||
|
||||
void VL_WARN_MT(const char* filename, int linenum, const char* hier, const char* msg) VL_MT_SAFE {
|
||||
#ifdef VL_THREADED
|
||||
VerilatedThreadMsgQueue::post(VerilatedMsg{[=]() { //
|
||||
vl_warn(filename, linenum, hier, msg);
|
||||
}});
|
||||
#else
|
||||
vl_warn(filename, linenum, hier, msg);
|
||||
#endif
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
// Debug prints
|
||||
|
||||
@@ -208,7 +232,7 @@ void VL_FATAL_MT(const char* filename, int linenum, const char* hier, const char
|
||||
std::string _vl_string_vprintf(const char* formatp, va_list ap) VL_MT_SAFE {
|
||||
va_list aq;
|
||||
va_copy(aq, ap);
|
||||
size_t len = VL_VSNPRINTF(nullptr, 0, formatp, aq);
|
||||
const size_t len = VL_VSNPRINTF(nullptr, 0, formatp, aq);
|
||||
va_end(aq);
|
||||
if (VL_UNLIKELY(len < 1)) return "";
|
||||
|
||||
@@ -220,21 +244,21 @@ std::string _vl_string_vprintf(const char* formatp, va_list ap) VL_MT_SAFE {
|
||||
return out;
|
||||
}
|
||||
|
||||
vluint64_t _vl_dbg_sequence_number() VL_MT_SAFE {
|
||||
uint64_t _vl_dbg_sequence_number() VL_MT_SAFE {
|
||||
#ifdef VL_THREADED
|
||||
static std::atomic<vluint64_t> sequence;
|
||||
static std::atomic<uint64_t> sequence;
|
||||
#else
|
||||
static vluint64_t sequence = 0;
|
||||
static uint64_t sequence = 0;
|
||||
#endif
|
||||
return ++sequence;
|
||||
}
|
||||
|
||||
vluint32_t VL_THREAD_ID() VL_MT_SAFE {
|
||||
uint32_t VL_THREAD_ID() VL_MT_SAFE {
|
||||
#ifdef VL_THREADED
|
||||
// Alternative is to use std::this_thread::get_id, but that returns a
|
||||
// hard-to-read number and is very slow
|
||||
static std::atomic<vluint32_t> s_nextId(0);
|
||||
static VL_THREAD_LOCAL vluint32_t t_myId = ++s_nextId;
|
||||
static std::atomic<uint32_t> s_nextId(0);
|
||||
static VL_THREAD_LOCAL uint32_t t_myId = ++s_nextId;
|
||||
return t_myId;
|
||||
#else
|
||||
return 0;
|
||||
@@ -248,13 +272,13 @@ void VL_DBG_MSGF(const char* formatp, ...) VL_MT_SAFE {
|
||||
va_start(ap, formatp);
|
||||
const std::string out = _vl_string_vprintf(formatp, ap);
|
||||
va_end(ap);
|
||||
// printf("-imm-V{t%d,%" VL_PRI64 "d}%s", VL_THREAD_ID(), _vl_dbg_sequence_number(),
|
||||
// printf("-imm-V{t%d,%" PRId64 "}%s", VL_THREAD_ID(), _vl_dbg_sequence_number(),
|
||||
// out.c_str());
|
||||
|
||||
// Using VL_PRINTF not VL_PRINTF_MT so that we can call VL_DBG_MSGF
|
||||
// from within the guts of the thread execution machinery (and it goes
|
||||
// to the screen and not into the queues we're debugging)
|
||||
VL_PRINTF("-V{t%u,%" VL_PRI64 "u}%s", VL_THREAD_ID(), _vl_dbg_sequence_number(), out.c_str());
|
||||
VL_PRINTF("-V{t%u,%" PRIu64 "}%s", VL_THREAD_ID(), _vl_dbg_sequence_number(), out.c_str());
|
||||
}
|
||||
|
||||
#ifdef VL_THREADED
|
||||
@@ -272,7 +296,7 @@ void VL_PRINTF_MT(const char* formatp, ...) VL_MT_SAFE {
|
||||
//===========================================================================
|
||||
// Random -- Mostly called at init time, so not inline.
|
||||
|
||||
static vluint32_t vl_sys_rand32() VL_MT_UNSAFE {
|
||||
static uint32_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;
|
||||
@@ -285,9 +309,9 @@ static vluint32_t vl_sys_rand32() VL_MT_UNSAFE {
|
||||
#endif
|
||||
}
|
||||
|
||||
vluint64_t vl_rand64() VL_MT_SAFE {
|
||||
static VL_THREAD_LOCAL vluint64_t t_state[2];
|
||||
static VL_THREAD_LOCAL vluint32_t t_seedEpoch = 0;
|
||||
uint64_t vl_rand64() VL_MT_SAFE {
|
||||
static VL_THREAD_LOCAL uint64_t t_state[2];
|
||||
static VL_THREAD_LOCAL uint32_t t_seedEpoch = 0;
|
||||
// For speed, we use a thread-local epoch number to know when to reseed
|
||||
// A thread always belongs to a single context, so this works out ok
|
||||
if (VL_UNLIKELY(t_seedEpoch != VerilatedContextImp::randSeedEpoch())) {
|
||||
@@ -301,34 +325,35 @@ vluint64_t vl_rand64() VL_MT_SAFE {
|
||||
if (VL_COUNTONES_I(t_state[1]) < 10) t_state[1] = ~t_state[1];
|
||||
}
|
||||
// Xoroshiro128+ algorithm
|
||||
const vluint64_t result = t_state[0] + t_state[1];
|
||||
const uint64_t result = t_state[0] + t_state[1];
|
||||
t_state[1] ^= t_state[0];
|
||||
t_state[0] = (((t_state[0] << 55) | (t_state[0] >> 9)) ^ t_state[1] ^ (t_state[1] << 14));
|
||||
t_state[1] = (t_state[1] << 36) | (t_state[1] >> 28);
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifndef VL_NO_LEGACY
|
||||
// VL_RANDOM_W currently unused as $random always 32 bits, left for backwards compatibility
|
||||
// LCOV_EXCL_START
|
||||
WDataOutP VL_RANDOM_W(int obits, WDataOutP outwp) VL_MT_SAFE {
|
||||
for (int i = 0; i < VL_WORDS_I(obits) - 1; ++i) outwp[i] = vl_rand64();
|
||||
outwp[VL_WORDS_I(obits) - 1] = vl_rand64() & VL_MASK_E(obits);
|
||||
for (int i = 0; i < VL_WORDS_I(obits); ++i) outwp[i] = vl_rand64();
|
||||
// Last word is unclean
|
||||
return outwp;
|
||||
}
|
||||
// LCOV_EXCL_STOP
|
||||
#endif
|
||||
|
||||
IData VL_RANDOM_SEEDED_II(int obits, IData seed) VL_MT_SAFE {
|
||||
Verilated::threadContextp()->randSeed(static_cast<int>(seed));
|
||||
return VL_RANDOM_I(obits);
|
||||
IData VL_RANDOM_SEEDED_II(IData& seedr) VL_MT_SAFE {
|
||||
// $random - seed is a new seed to apply, then we return new seed
|
||||
Verilated::threadContextp()->randSeed(static_cast<int>(seedr));
|
||||
seedr = VL_RANDOM_I();
|
||||
return VL_RANDOM_I();
|
||||
}
|
||||
IData VL_URANDOM_SEEDED_II(IData seed) VL_MT_SAFE {
|
||||
// $urandom - seed is a new seed to apply
|
||||
Verilated::threadContextp()->randSeed(static_cast<int>(seed));
|
||||
return VL_RANDOM_I();
|
||||
}
|
||||
|
||||
IData VL_RAND_RESET_I(int obits) VL_MT_SAFE {
|
||||
if (Verilated::threadContextp()->randReset() == 0) return 0;
|
||||
IData data = ~0;
|
||||
if (Verilated::threadContextp()->randReset() != 1) { // if 2, randomize
|
||||
data = VL_RANDOM_I(obits);
|
||||
data = VL_RANDOM_I();
|
||||
}
|
||||
data &= VL_MASK_I(obits);
|
||||
return data;
|
||||
@@ -337,7 +362,7 @@ QData VL_RAND_RESET_Q(int obits) VL_MT_SAFE {
|
||||
if (Verilated::threadContextp()->randReset() == 0) return 0;
|
||||
QData data = ~0ULL;
|
||||
if (Verilated::threadContextp()->randReset() != 1) { // if 2, randomize
|
||||
data = VL_RANDOM_Q(obits);
|
||||
data = VL_RANDOM_Q();
|
||||
}
|
||||
data &= VL_MASK_Q(obits);
|
||||
return data;
|
||||
@@ -385,11 +410,11 @@ WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, const WDataInP lwp, const WData
|
||||
const int vw = VL_WORDS_I(vmsbp1); // aka "n" in the algorithm
|
||||
|
||||
if (vw == 1) { // Single divisor word breaks rest of algorithm
|
||||
vluint64_t k = 0;
|
||||
uint64_t k = 0;
|
||||
for (int j = uw - 1; j >= 0; --j) {
|
||||
vluint64_t unw64 = ((k << 32ULL) + static_cast<vluint64_t>(lwp[j]));
|
||||
owp[j] = unw64 / static_cast<vluint64_t>(rwp[0]);
|
||||
k = unw64 - static_cast<vluint64_t>(owp[j]) * static_cast<vluint64_t>(rwp[0]);
|
||||
const uint64_t unw64 = ((k << 32ULL) + static_cast<uint64_t>(lwp[j]));
|
||||
owp[j] = unw64 / static_cast<uint64_t>(rwp[0]);
|
||||
k = unw64 - static_cast<uint64_t>(owp[j]) * static_cast<uint64_t>(rwp[0]);
|
||||
}
|
||||
if (is_modulus) {
|
||||
owp[0] = k;
|
||||
@@ -399,8 +424,8 @@ WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, const WDataInP lwp, const WData
|
||||
}
|
||||
|
||||
// +1 word as we may shift during normalization
|
||||
vluint32_t un[VL_MULS_MAX_WORDS + 1]; // Fixed size, as MSVC++ doesn't allow [words] here
|
||||
vluint32_t vn[VL_MULS_MAX_WORDS + 1]; // v normalized
|
||||
uint32_t un[VL_MULS_MAX_WORDS + 1]; // Fixed size, as MSVC++ doesn't allow [words] here
|
||||
uint32_t vn[VL_MULS_MAX_WORDS + 1]; // v normalized
|
||||
|
||||
// Zero for ease of debugging and to save having to zero for shifts
|
||||
// Note +1 as loop will use extra word
|
||||
@@ -409,7 +434,7 @@ WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, const WDataInP lwp, const WData
|
||||
// Algorithm requires divisor MSB to be set
|
||||
// Copy and shift to normalize divisor so MSB of vn[vw-1] is set
|
||||
const int s = 31 - VL_BITBIT_I(vmsbp1 - 1); // shift amount (0...31)
|
||||
const vluint32_t shift_mask = s ? 0xffffffff : 0; // otherwise >> 32 won't mask the value
|
||||
const uint32_t shift_mask = s ? 0xffffffff : 0; // otherwise >> 32 won't mask the value
|
||||
for (int i = vw - 1; i > 0; --i) {
|
||||
vn[i] = (rwp[i] << s) | (shift_mask & (rwp[i - 1] >> (32 - s)));
|
||||
}
|
||||
@@ -429,10 +454,10 @@ WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, const WDataInP lwp, const WData
|
||||
// Main loop
|
||||
for (int j = uw - vw; j >= 0; --j) {
|
||||
// Estimate
|
||||
const vluint64_t unw64 = (static_cast<vluint64_t>(un[j + vw]) << 32ULL
|
||||
| static_cast<vluint64_t>(un[j + vw - 1]));
|
||||
vluint64_t qhat = unw64 / static_cast<vluint64_t>(vn[vw - 1]);
|
||||
vluint64_t rhat = unw64 - qhat * static_cast<vluint64_t>(vn[vw - 1]);
|
||||
const uint64_t unw64
|
||||
= (static_cast<uint64_t>(un[j + vw]) << 32ULL | static_cast<uint64_t>(un[j + vw - 1]));
|
||||
uint64_t qhat = unw64 / static_cast<uint64_t>(vn[vw - 1]);
|
||||
uint64_t rhat = unw64 - qhat * static_cast<uint64_t>(vn[vw - 1]);
|
||||
|
||||
again:
|
||||
if (qhat >= 0x100000000ULL || ((qhat * vn[vw - 2]) > ((rhat << 32ULL) + un[j + vw - 2]))) {
|
||||
@@ -441,10 +466,10 @@ WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, const WDataInP lwp, const WData
|
||||
if (rhat < 0x100000000ULL) goto again;
|
||||
}
|
||||
|
||||
vlsint64_t t = 0; // Must be signed
|
||||
vluint64_t k = 0;
|
||||
int64_t t = 0; // Must be signed
|
||||
uint64_t k = 0;
|
||||
for (int i = 0; i < vw; ++i) {
|
||||
vluint64_t p = qhat * vn[i]; // Multiply by estimate
|
||||
const uint64_t p = qhat * vn[i]; // Multiply by estimate
|
||||
t = un[i + j] - k - (p & 0xFFFFFFFFULL); // Subtract
|
||||
un[i + j] = t;
|
||||
k = (p >> 32ULL) - (t >> 32ULL);
|
||||
@@ -458,7 +483,7 @@ WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, const WDataInP lwp, const WData
|
||||
owp[j]--;
|
||||
k = 0;
|
||||
for (int i = 0; i < vw; ++i) {
|
||||
t = static_cast<vluint64_t>(un[i + j]) + static_cast<vluint64_t>(vn[i]) + k;
|
||||
t = static_cast<uint64_t>(un[i + j]) + static_cast<uint64_t>(vn[i]) + k;
|
||||
un[i + j] = t;
|
||||
k = t >> 32ULL;
|
||||
}
|
||||
@@ -589,7 +614,7 @@ double VL_ITOR_D_W(int lbits, const WDataInP lwp) VL_PURE {
|
||||
}
|
||||
double VL_ISTOR_D_W(int lbits, const WDataInP lwp) VL_PURE {
|
||||
if (!VL_SIGN_W(lbits, lwp)) return VL_ITOR_D_W(lbits, lwp);
|
||||
vluint32_t pos[VL_MULS_MAX_WORDS + 1]; // Fixed size, as MSVC++ doesn't allow [words] here
|
||||
uint32_t pos[VL_MULS_MAX_WORDS + 1]; // Fixed size, as MSVC++ doesn't allow [words] here
|
||||
VL_NEGATE_W(VL_WORDS_I(lbits), pos, lwp);
|
||||
_vl_clean_inplace_w(lbits, pos);
|
||||
return -VL_ITOR_D_W(lbits, pos);
|
||||
@@ -663,7 +688,7 @@ std::string _vl_vsformat_time(char* tmp, T ld, int timeunit, bool left, size_t w
|
||||
const WDataInP integer = VL_DIV_WWW(b, tmp0, shifted, fracDigitsPow10);
|
||||
const WDataInP frac = VL_MODDIV_WWW(b, tmp1, shifted, fracDigitsPow10);
|
||||
const WDataInP max64Bit
|
||||
= VL_EXTEND_WQ(b, 0, tmp2, std::numeric_limits<vluint64_t>::max()); // breaks shifted
|
||||
= VL_EXTEND_WQ(b, 0, tmp2, std::numeric_limits<uint64_t>::max()); // breaks shifted
|
||||
if (VL_GT_W(w, integer, max64Bit)) {
|
||||
WDataOutP v = VL_ASSIGN_W(b, tmp3, integer); // breaks fracDigitsPow10
|
||||
VlWide<w> zero, ten;
|
||||
@@ -683,23 +708,22 @@ std::string _vl_vsformat_time(char* tmp, T ld, int timeunit, bool left, size_t w
|
||||
if (!fracDigits) {
|
||||
digits = VL_SNPRINTF(tmp, VL_VALUE_STRING_MAX_WIDTH, "%s%s", ptr, suffix.c_str());
|
||||
} else {
|
||||
digits = VL_SNPRINTF(tmp, VL_VALUE_STRING_MAX_WIDTH, "%s.%0*" VL_PRI64 "u%s", ptr,
|
||||
digits = VL_SNPRINTF(tmp, VL_VALUE_STRING_MAX_WIDTH, "%s.%0*" PRIu64 "%s", ptr,
|
||||
fracDigits, VL_SET_QW(frac), suffix.c_str());
|
||||
}
|
||||
} else {
|
||||
const vluint64_t integer64 = VL_SET_QW(integer);
|
||||
const uint64_t integer64 = VL_SET_QW(integer);
|
||||
if (!fracDigits) {
|
||||
digits = VL_SNPRINTF(tmp, VL_VALUE_STRING_MAX_WIDTH, "%" VL_PRI64 "u%s", integer64,
|
||||
digits = VL_SNPRINTF(tmp, VL_VALUE_STRING_MAX_WIDTH, "%" PRIu64 "%s", integer64,
|
||||
suffix.c_str());
|
||||
} else {
|
||||
digits = VL_SNPRINTF(tmp, VL_VALUE_STRING_MAX_WIDTH,
|
||||
"%" VL_PRI64 "u.%0*" VL_PRI64 "u%s", integer64, fracDigits,
|
||||
VL_SET_QW(frac), suffix.c_str());
|
||||
digits = VL_SNPRINTF(tmp, VL_VALUE_STRING_MAX_WIDTH, "%" PRIu64 ".%0*" PRIu64 "%s",
|
||||
integer64, fracDigits, VL_SET_QW(frac), suffix.c_str());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
double shiftd = vl_time_multiplier(shift);
|
||||
double scaled = ld * shiftd;
|
||||
const double shiftd = vl_time_multiplier(shift);
|
||||
const double scaled = ld * shiftd;
|
||||
const double fracDiv = vl_time_multiplier(fracDigits);
|
||||
const double whole = scaled / fracDiv;
|
||||
if (!fracDigits) {
|
||||
@@ -749,7 +773,7 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
|
||||
}
|
||||
} else { // Format character
|
||||
inPct = false;
|
||||
char fmt = pos[0];
|
||||
const char fmt = pos[0];
|
||||
switch (fmt) {
|
||||
case '0': // FALLTHRU
|
||||
case '1': // FALLTHRU
|
||||
@@ -809,7 +833,7 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
|
||||
output += _vl_vsformat_time(t_tmp, d, timeunit, left, width);
|
||||
} else {
|
||||
const size_t len = pos - pctp + 1;
|
||||
std::string fmts{pctp, len};
|
||||
const std::string fmts{pctp, len};
|
||||
VL_SNPRINTF(t_tmp, VL_VALUE_STRING_MAX_WIDTH, fmts.c_str(), d);
|
||||
output += t_tmp;
|
||||
}
|
||||
@@ -855,9 +879,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 = VL_SNPRINTF(
|
||||
t_tmp, VL_VALUE_STRING_MAX_WIDTH, "%" VL_PRI64 "d",
|
||||
static_cast<vlsint64_t>(VL_EXTENDS_QQ(lbits, lbits, ld)));
|
||||
digits
|
||||
= VL_SNPRINTF(t_tmp, VL_VALUE_STRING_MAX_WIDTH, "%" PRId64,
|
||||
static_cast<int64_t>(VL_EXTENDS_QQ(lbits, lbits, ld)));
|
||||
append = t_tmp;
|
||||
} else {
|
||||
if (VL_SIGN_E(lbits, lwp[VL_WORDS_I(lbits) - 1])) {
|
||||
@@ -869,7 +893,7 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
|
||||
}
|
||||
digits = append.length();
|
||||
}
|
||||
int needmore = width - digits;
|
||||
const int needmore = width - digits;
|
||||
std::string padding;
|
||||
if (needmore > 0) {
|
||||
if (pctp && pctp[0] && pctp[1] == '0') { // %0
|
||||
@@ -885,14 +909,13 @@ 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
|
||||
= VL_SNPRINTF(t_tmp, VL_VALUE_STRING_MAX_WIDTH, "%" VL_PRI64 "u", ld);
|
||||
digits = VL_SNPRINTF(t_tmp, VL_VALUE_STRING_MAX_WIDTH, "%" PRIu64, ld);
|
||||
append = t_tmp;
|
||||
} else {
|
||||
append = VL_DECIMAL_NW(lbits, lwp);
|
||||
digits = append.length();
|
||||
}
|
||||
int needmore = width - digits;
|
||||
const int needmore = width - digits;
|
||||
std::string padding;
|
||||
if (needmore > 0) {
|
||||
if (pctp && pctp[0] && pctp[1] == '0') { // %0
|
||||
@@ -953,7 +976,7 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
|
||||
case 'x':
|
||||
for (; lsb >= 0; --lsb) {
|
||||
lsb = (lsb / 4) * 4; // Next digit
|
||||
IData charval = VL_BITRSHIFT_W(lwp, lsb) & 0xf;
|
||||
const IData charval = VL_BITRSHIFT_W(lwp, lsb) & 0xf;
|
||||
output += "0123456789abcdef"[charval];
|
||||
}
|
||||
break;
|
||||
@@ -1027,7 +1050,7 @@ static inline void _vl_vsss_read_str(FILE* fp, int& floc, const WDataInP fromp,
|
||||
}
|
||||
static inline char* _vl_vsss_read_bin(FILE* fp, int& floc, const WDataInP fromp,
|
||||
const std::string& fstr, char* beginp, std::size_t n,
|
||||
bool inhibit = false) {
|
||||
const bool inhibit = false) {
|
||||
// Variant of _vl_vsss_read_str using the same underlying I/O functions but optimized
|
||||
// specifically for block reads of N bytes (read operations are not demarcated by
|
||||
// whitespace). In the fp case, except descriptor to have been opened in binary mode.
|
||||
@@ -1041,9 +1064,7 @@ static inline char* _vl_vsss_read_bin(FILE* fp, int& floc, const WDataInP fromp,
|
||||
}
|
||||
static inline void _vl_vsss_setbit(WDataOutP owp, int obits, int lsb, int nbits,
|
||||
IData ld) VL_MT_SAFE {
|
||||
for (; nbits && lsb < obits; nbits--, lsb++, ld >>= 1) {
|
||||
VL_ASSIGNBIT_WI(0, lsb, owp, ld & 1);
|
||||
}
|
||||
for (; nbits && lsb < obits; nbits--, lsb++, ld >>= 1) { VL_ASSIGNBIT_WI(lsb, owp, ld & 1); }
|
||||
}
|
||||
static inline void _vl_vsss_based(WDataOutP owp, int obits, int baseLog2, const char* strp,
|
||||
size_t posstart, size_t posend) VL_MT_SAFE {
|
||||
@@ -1100,16 +1121,16 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
|
||||
_vl_vsss_skipspace(fp, floc, fromp, fstr);
|
||||
} else if (!inPct) { // Expected Format
|
||||
_vl_vsss_skipspace(fp, floc, fromp, fstr);
|
||||
int c = _vl_vsss_peek(fp, floc, fromp, fstr);
|
||||
const int c = _vl_vsss_peek(fp, floc, fromp, fstr);
|
||||
if (c != pos[0]) goto done;
|
||||
_vl_vsss_advance(fp, floc);
|
||||
} else { // Format character
|
||||
// Skip loading spaces
|
||||
inPct = false;
|
||||
char fmt = pos[0];
|
||||
const char fmt = pos[0];
|
||||
switch (fmt) {
|
||||
case '%': {
|
||||
int c = _vl_vsss_peek(fp, floc, fromp, fstr);
|
||||
const int c = _vl_vsss_peek(fp, floc, fromp, fstr);
|
||||
if (c != '%') goto done;
|
||||
_vl_vsss_advance(fp, floc);
|
||||
break;
|
||||
@@ -1139,7 +1160,7 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
|
||||
for (int i = 0; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
|
||||
switch (fmt) {
|
||||
case 'c': {
|
||||
int c = _vl_vsss_peek(fp, floc, fromp, fstr);
|
||||
const int c = _vl_vsss_peek(fp, floc, fromp, fstr);
|
||||
if (c == EOF) goto done;
|
||||
_vl_vsss_advance(fp, floc);
|
||||
owp[0] = c;
|
||||
@@ -1163,8 +1184,8 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
|
||||
_vl_vsss_skipspace(fp, floc, fromp, fstr);
|
||||
_vl_vsss_read_str(fp, floc, fromp, fstr, t_tmp, "0123456789+-xXzZ?_");
|
||||
if (!t_tmp[0]) goto done;
|
||||
vlsint64_t ld = 0;
|
||||
std::sscanf(t_tmp, "%30" VL_PRI64 "d", &ld);
|
||||
int64_t ld = 0;
|
||||
std::sscanf(t_tmp, "%30" PRId64, &ld);
|
||||
VL_SET_WQ(owp, ld);
|
||||
break;
|
||||
}
|
||||
@@ -1177,7 +1198,7 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
|
||||
// cppcheck-suppress unusedStructMember // It's used
|
||||
union {
|
||||
double r;
|
||||
vlsint64_t ld;
|
||||
int64_t ld;
|
||||
} u;
|
||||
u.r = std::strtod(t_tmp, nullptr);
|
||||
VL_SET_WQ(owp, u.ld);
|
||||
@@ -1189,7 +1210,7 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
|
||||
_vl_vsss_read_str(fp, floc, fromp, fstr, t_tmp, "0123456789+-xXzZ?_");
|
||||
if (!t_tmp[0]) goto done;
|
||||
QData ld = 0;
|
||||
std::sscanf(t_tmp, "%30" VL_PRI64 "u", &ld);
|
||||
std::sscanf(t_tmp, "%30" PRIu64, &ld);
|
||||
VL_SET_WQ(owp, ld);
|
||||
break;
|
||||
}
|
||||
@@ -1292,7 +1313,7 @@ void _vl_vint_to_string(int obits, char* destoutp, const WDataInP sourcep) VL_MT
|
||||
char* destp = destoutp;
|
||||
for (; lsb >= 0; --lsb) {
|
||||
lsb = (lsb / 8) * 8; // Next digit
|
||||
IData charval = VL_BITRSHIFT_W(sourcep, lsb) & 0xff;
|
||||
const IData charval = VL_BITRSHIFT_W(sourcep, lsb) & 0xff;
|
||||
if (!start || charval) {
|
||||
*destp++ = (charval == 0) ? ' ' : charval;
|
||||
start = false; // Drop leading 0s
|
||||
@@ -1477,7 +1498,7 @@ void VL_FWRITEF(IData fpi, const char* formatp, ...) VL_MT_SAFE {
|
||||
IData VL_FSCANF_IX(IData fpi, const char* formatp, ...) VL_MT_SAFE {
|
||||
// While threadsafe, each thread can only access different file handles
|
||||
FILE* const fp = VL_CVT_I_FP(fpi);
|
||||
if (VL_UNLIKELY(!fp)) return 0;
|
||||
if (VL_UNLIKELY(!fp)) return ~0U; // -1
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, formatp);
|
||||
@@ -1530,16 +1551,16 @@ IData VL_FREAD_I(int width, int array_lsb, int array_size, void* memp, IData fpi
|
||||
// Prep for reading
|
||||
IData read_count = 0;
|
||||
IData read_elements = 0;
|
||||
int start_shift = (width - 1) & ~7; // bit+7:bit gets first character
|
||||
const int start_shift = (width - 1) & ~7; // bit+7:bit gets first character
|
||||
int shift = start_shift;
|
||||
// Read the data
|
||||
// We process a character at a time, as then we don't need to deal
|
||||
// with changing buffer sizes dynamically, etc.
|
||||
while (true) {
|
||||
int c = std::fgetc(fp);
|
||||
const int c = std::fgetc(fp);
|
||||
if (VL_UNLIKELY(c == EOF)) break;
|
||||
// Shift value in
|
||||
IData entry = read_elements + start - array_lsb;
|
||||
const IData entry = read_elements + start - array_lsb;
|
||||
if (width <= 8) {
|
||||
CData* const datap = &(reinterpret_cast<CData*>(memp))[entry];
|
||||
if (shift == start_shift) *datap = 0;
|
||||
@@ -1600,6 +1621,7 @@ IData VL_VALUEPLUSARGS_INW(int rbits, const std::string& ld, WDataOutP rwp) VL_M
|
||||
inPct = true;
|
||||
} else if (!inPct) { // Normal text
|
||||
prefix += *posp;
|
||||
} else if (inPct && posp[0] == '0') { // %0
|
||||
} else { // Format character
|
||||
switch (std::tolower(*posp)) {
|
||||
case '%':
|
||||
@@ -1621,8 +1643,8 @@ IData VL_VALUEPLUSARGS_INW(int rbits, const std::string& ld, WDataOutP rwp) VL_M
|
||||
VL_ZERO_RESET_W(rbits, rwp);
|
||||
switch (std::tolower(fmt)) {
|
||||
case 'd': {
|
||||
vlsint64_t lld = 0;
|
||||
std::sscanf(dp, "%30" VL_PRI64 "d", &lld);
|
||||
int64_t lld = 0;
|
||||
std::sscanf(dp, "%30" PRId64, &lld);
|
||||
VL_SET_WQ(rwp, lld);
|
||||
break;
|
||||
}
|
||||
@@ -1656,7 +1678,7 @@ IData VL_VALUEPLUSARGS_INW(int rbits, const std::string& ld, WDataOutP rwp) VL_M
|
||||
VL_SET_WQ(rwp, VL_CVT_Q_D(temp));
|
||||
break;
|
||||
}
|
||||
default: // Other simulators simply return 0 in these cases and don't error out
|
||||
default: // Other simulators return 0 in these cases and don't error out
|
||||
return 0;
|
||||
}
|
||||
_vl_clean_inplace_w(rbits, rwp);
|
||||
@@ -1727,14 +1749,14 @@ std::string VL_TOUPPER_NN(const std::string& ld) VL_MT_SAFE {
|
||||
std::string VL_CVT_PACK_STR_NW(int lwords, const WDataInP lwp) VL_MT_SAFE {
|
||||
// See also _vl_vint_to_string
|
||||
char destout[VL_VALUE_STRING_MAX_CHARS + 1];
|
||||
int obits = lwords * VL_EDATASIZE;
|
||||
const int obits = lwords * VL_EDATASIZE;
|
||||
int lsb = obits - 1;
|
||||
bool start = true;
|
||||
char* destp = destout;
|
||||
size_t len = 0;
|
||||
for (; lsb >= 0; --lsb) {
|
||||
lsb = (lsb / 8) * 8; // Next digit
|
||||
IData charval = VL_BITRSHIFT_W(lwp, lsb) & 0xff;
|
||||
const IData charval = VL_BITRSHIFT_W(lwp, lsb) & 0xff;
|
||||
if (!start || charval) {
|
||||
*destp++ = (charval == 0) ? ' ' : charval;
|
||||
++len;
|
||||
@@ -1746,7 +1768,7 @@ std::string VL_CVT_PACK_STR_NW(int lwords, const WDataInP lwp) VL_MT_SAFE {
|
||||
|
||||
std::string VL_PUTC_N(const std::string& lhs, IData rhs, CData ths) VL_PURE {
|
||||
std::string lstring = lhs;
|
||||
const vlsint32_t rhs_s = rhs; // To signed value
|
||||
const int32_t rhs_s = rhs; // To signed value
|
||||
// 6.16.2:str.putc(i, c) does not change the value when i < 0 || i >= str.len() || c == 0
|
||||
if (0 <= rhs_s && rhs < lhs.length() && ths != 0) lstring[rhs] = ths;
|
||||
return lstring;
|
||||
@@ -1754,15 +1776,15 @@ std::string VL_PUTC_N(const std::string& lhs, IData rhs, CData ths) VL_PURE {
|
||||
|
||||
CData VL_GETC_N(const std::string& lhs, IData rhs) VL_PURE {
|
||||
CData v = 0;
|
||||
const vlsint32_t rhs_s = rhs; // To signed value
|
||||
const int32_t rhs_s = rhs; // To signed value
|
||||
// 6.16.3:str.getc(i) returns 0 if i < 0 || i >= str.len()
|
||||
if (0 <= rhs_s && rhs < lhs.length()) v = lhs[rhs];
|
||||
return v;
|
||||
}
|
||||
|
||||
std::string VL_SUBSTR_N(const std::string& lhs, IData rhs, IData ths) VL_PURE {
|
||||
const vlsint32_t rhs_s = rhs; // To signed value
|
||||
const vlsint32_t ths_s = ths; // To signed value
|
||||
const int32_t rhs_s = rhs; // To signed value
|
||||
const int32_t ths_s = ths; // To signed value
|
||||
// 6.16.8:str.substr(i, j) returns an empty string when i < 0 || j < i || j >= str.len()
|
||||
if (rhs_s < 0 || ths_s < rhs_s || ths >= lhs.length()) return "";
|
||||
// Second parameter of std::string::substr(i, n) is length, not position as in SystemVerilog
|
||||
@@ -1801,7 +1823,7 @@ static const char* memhFormat(int nBits) {
|
||||
return t_buf;
|
||||
}
|
||||
|
||||
static const char* formatBinary(int nBits, vluint32_t bits) {
|
||||
static const char* formatBinary(int nBits, uint32_t bits) {
|
||||
assert((nBits >= 1) && (nBits <= 32));
|
||||
|
||||
static VL_THREAD_LOCAL char t_buf[64];
|
||||
@@ -1823,7 +1845,7 @@ VlReadMem::VlReadMem(bool hex, int bits, const std::string& filename, QData star
|
||||
m_fp = std::fopen(filename.c_str(), "r");
|
||||
if (VL_UNLIKELY(!m_fp)) {
|
||||
// We don't report the Verilog source filename as it slow to have to pass it down
|
||||
VL_FATAL_MT(filename.c_str(), 0, "", "$readmem file not found");
|
||||
VL_WARN_MT(filename.c_str(), 0, "", "$readmem file not found");
|
||||
// cppcheck-suppress resourceLeak // m_fp is nullptr - bug in cppcheck
|
||||
return;
|
||||
}
|
||||
@@ -1882,6 +1904,7 @@ bool VlReadMem::get(QData& addrr, std::string& valuer) {
|
||||
ignore_to_eol = true;
|
||||
} else if (c == '@') {
|
||||
reading_addr = true;
|
||||
m_anyAddr = true;
|
||||
m_addr = 0;
|
||||
}
|
||||
// Check for hex or binary digits as file format requests
|
||||
@@ -1908,9 +1931,9 @@ bool VlReadMem::get(QData& addrr, std::string& valuer) {
|
||||
lastc = c;
|
||||
}
|
||||
|
||||
if (VL_UNLIKELY(m_end != ~0ULL && m_addr <= m_end)) {
|
||||
VL_FATAL_MT(m_filename.c_str(), m_linenum, "",
|
||||
"$readmem file ended before specified final address (IEEE 2017 21.4)");
|
||||
if (VL_UNLIKELY(m_end != ~0ULL && m_addr <= m_end && !m_anyAddr)) {
|
||||
VL_WARN_MT(m_filename.c_str(), m_linenum, "",
|
||||
"$readmem file ended before specified final address (IEEE 2017 21.4)");
|
||||
}
|
||||
|
||||
return false; // EOF
|
||||
@@ -1975,7 +1998,7 @@ VlWriteMem::~VlWriteMem() {
|
||||
void VlWriteMem::print(QData addr, bool addrstamp, const void* valuep) {
|
||||
if (VL_UNLIKELY(!m_fp)) return;
|
||||
if (addr != m_addr && addrstamp) { // Only assoc has time stamps
|
||||
fprintf(m_fp, "@%" VL_PRI64 "x\n", addr);
|
||||
fprintf(m_fp, "@%" PRIx64 "\n", addr);
|
||||
}
|
||||
m_addr = addr + 1;
|
||||
if (m_bits <= 8) {
|
||||
@@ -2004,9 +2027,9 @@ void VlWriteMem::print(QData addr, bool addrstamp, const void* valuep) {
|
||||
}
|
||||
} else if (m_bits <= 64) {
|
||||
const QData* const datap = reinterpret_cast<const QData*>(valuep);
|
||||
const vluint64_t value = VL_MASK_Q(m_bits) & *datap;
|
||||
const vluint32_t lo = value & 0xffffffff;
|
||||
const vluint32_t hi = value >> 32;
|
||||
const uint64_t value = VL_MASK_Q(m_bits) & *datap;
|
||||
const uint32_t lo = value & 0xffffffff;
|
||||
const uint32_t hi = value >> 32;
|
||||
if (m_hex) {
|
||||
fprintf(m_fp, memhFormat(m_bits - 32), hi);
|
||||
fprintf(m_fp, "%08x\n", lo);
|
||||
@@ -2068,7 +2091,7 @@ void VL_READMEM_N(bool hex, // Hex format, else binary
|
||||
VL_FATAL_MT(filename.c_str(), rmem.linenum(), "",
|
||||
"$readmem file address beyond bounds of array");
|
||||
} else {
|
||||
QData entry = addr - array_lsb;
|
||||
const QData entry = addr - array_lsb;
|
||||
if (bits <= 8) {
|
||||
CData* const datap = &(reinterpret_cast<CData*>(memp))[entry];
|
||||
rmem.setData(datap, value);
|
||||
@@ -2103,7 +2126,7 @@ void VL_WRITEMEM_N(bool hex, // Hex format, else binary
|
||||
QData start, // First array row address to write
|
||||
QData end // Last address to write, or ~0 when not specified
|
||||
) VL_MT_SAFE {
|
||||
QData addr_max = array_lsb + depth - 1;
|
||||
const QData addr_max = array_lsb + depth - 1;
|
||||
if (start < static_cast<QData>(array_lsb)) start = array_lsb;
|
||||
if (end > addr_max) end = addr_max;
|
||||
|
||||
@@ -2212,8 +2235,8 @@ double vl_time_multiplier(int scale) VL_PURE {
|
||||
return pow10[scale];
|
||||
}
|
||||
}
|
||||
vluint64_t vl_time_pow10(int n) {
|
||||
static const vluint64_t pow10[20] = {
|
||||
uint64_t vl_time_pow10(int n) {
|
||||
static const uint64_t pow10[20] = {
|
||||
1ULL,
|
||||
10ULL,
|
||||
100ULL,
|
||||
@@ -2257,7 +2280,7 @@ VerilatedContext::VerilatedContext()
|
||||
: m_impdatap{new VerilatedContextImpData} {
|
||||
Verilated::lastContextp(this);
|
||||
Verilated::threadContextp(this);
|
||||
m_ns.m_profThreadsFilename = "profile_threads.dat";
|
||||
m_ns.m_profExecFilename = "profile_exec.dat";
|
||||
m_ns.m_profVltFilename = "profile.vlt";
|
||||
m_fdps.resize(31);
|
||||
std::fill(m_fdps.begin(), m_fdps.end(), static_cast<FILE*>(nullptr));
|
||||
@@ -2266,7 +2289,17 @@ VerilatedContext::VerilatedContext()
|
||||
}
|
||||
|
||||
// Must declare here not in interface, as otherwise forward declarations not known
|
||||
VerilatedContext::~VerilatedContext() {}
|
||||
VerilatedContext::~VerilatedContext() {
|
||||
checkMagic(this);
|
||||
m_magic = 0x1; // Arbitrary but 0x1 is what Verilator src uses for a deleted pointer
|
||||
}
|
||||
|
||||
void VerilatedContext::checkMagic(const VerilatedContext* contextp) {
|
||||
if (VL_UNLIKELY(!contextp || contextp->m_magic != MAGIC)) {
|
||||
VL_FATAL_MT("", 0, "", // LCOV_EXCL_LINE
|
||||
"Attempt to create model using a bad/deleted VerilatedContext pointer");
|
||||
}
|
||||
}
|
||||
|
||||
VerilatedContext::Serialized::Serialized() {
|
||||
m_timeunit = VL_TIME_UNIT; // Initial value until overriden by _Vconfigure
|
||||
@@ -2325,21 +2358,21 @@ void VerilatedContext::gotFinish(bool flag) VL_MT_SAFE {
|
||||
const VerilatedLockGuard lock{m_mutex};
|
||||
m_s.m_gotFinish = flag;
|
||||
}
|
||||
void VerilatedContext::profThreadsStart(vluint64_t flag) VL_MT_SAFE {
|
||||
void VerilatedContext::profExecStart(uint64_t flag) VL_MT_SAFE {
|
||||
const VerilatedLockGuard lock{m_mutex};
|
||||
m_ns.m_profThreadsStart = flag;
|
||||
m_ns.m_profExecStart = flag;
|
||||
}
|
||||
void VerilatedContext::profThreadsWindow(vluint64_t flag) VL_MT_SAFE {
|
||||
void VerilatedContext::profExecWindow(uint64_t flag) VL_MT_SAFE {
|
||||
const VerilatedLockGuard lock{m_mutex};
|
||||
m_ns.m_profThreadsWindow = flag;
|
||||
m_ns.m_profExecWindow = flag;
|
||||
}
|
||||
void VerilatedContext::profThreadsFilename(const std::string& flag) VL_MT_SAFE {
|
||||
void VerilatedContext::profExecFilename(const std::string& flag) VL_MT_SAFE {
|
||||
const VerilatedLockGuard lock{m_mutex};
|
||||
m_ns.m_profThreadsFilename = flag;
|
||||
m_ns.m_profExecFilename = flag;
|
||||
}
|
||||
std::string VerilatedContext::profThreadsFilename() const VL_MT_SAFE {
|
||||
std::string VerilatedContext::profExecFilename() const VL_MT_SAFE {
|
||||
const VerilatedLockGuard lock{m_mutex};
|
||||
return m_ns.m_profThreadsFilename;
|
||||
return m_ns.m_profExecFilename;
|
||||
}
|
||||
void VerilatedContext::profVltFilename(const std::string& flag) VL_MT_SAFE {
|
||||
const VerilatedLockGuard lock{m_mutex};
|
||||
@@ -2484,13 +2517,16 @@ std::pair<int, char**> VerilatedContextImp::argc_argv() VL_MT_SAFE_EXCLUDES(m_ar
|
||||
|
||||
void VerilatedContextImp::commandArgVl(const std::string& arg) {
|
||||
if (0 == std::strncmp(arg.c_str(), "+verilator+", std::strlen("+verilator+"))) {
|
||||
std::string value;
|
||||
std::string str;
|
||||
uint64_t u64;
|
||||
if (arg == "+verilator+debug") {
|
||||
Verilated::debug(4);
|
||||
} else if (commandArgVlValue(arg, "+verilator+debugi+", value /*ref*/)) {
|
||||
Verilated::debug(std::atoi(value.c_str()));
|
||||
} else if (commandArgVlValue(arg, "+verilator+error+limit+", value /*ref*/)) {
|
||||
errorLimit(std::atoi(value.c_str()));
|
||||
} else if (commandArgVlUint64(arg, "+verilator+debugi+", u64, 0,
|
||||
std::numeric_limits<int>::max())) {
|
||||
Verilated::debug(static_cast<int>(u64));
|
||||
} else if (commandArgVlUint64(arg, "+verilator+error+limit+", u64, 0,
|
||||
std::numeric_limits<int>::max())) {
|
||||
errorLimit(static_cast<int>(u64));
|
||||
} else if (arg == "+verilator+help") {
|
||||
VerilatedImp::versionDump();
|
||||
VL_PRINTF_MT("For help, please see 'verilator --help'\n");
|
||||
@@ -2498,18 +2534,22 @@ void VerilatedContextImp::commandArgVl(const std::string& arg) {
|
||||
"Exiting due to command line argument (not an error)");
|
||||
} else if (arg == "+verilator+noassert") {
|
||||
assertOn(false);
|
||||
} else if (commandArgVlValue(arg, "+verilator+prof+threads+start+", value /*ref*/)) {
|
||||
profThreadsStart(std::atoll(value.c_str()));
|
||||
} else if (commandArgVlValue(arg, "+verilator+prof+threads+window+", value /*ref*/)) {
|
||||
profThreadsWindow(std::atol(value.c_str()));
|
||||
} else if (commandArgVlValue(arg, "+verilator+prof+threads+file+", value /*ref*/)) {
|
||||
profThreadsFilename(value);
|
||||
} else if (commandArgVlValue(arg, "+verilator+prof+vlt+file+", value /*ref*/)) {
|
||||
profVltFilename(value);
|
||||
} else if (commandArgVlValue(arg, "+verilator+rand+reset+", value /*ref*/)) {
|
||||
randReset(std::atoi(value.c_str()));
|
||||
} else if (commandArgVlValue(arg, "+verilator+seed+", value /*ref*/)) {
|
||||
randSeed(std::atoi(value.c_str()));
|
||||
} else if (commandArgVlUint64(arg, "+verilator+prof+exec+start+", u64)
|
||||
|| commandArgVlUint64(arg, "+verilator+prof+threads+start+", u64)) {
|
||||
profExecStart(u64);
|
||||
} else if (commandArgVlUint64(arg, "+verilator+prof+exec+window+", u64, 1)
|
||||
|| commandArgVlUint64(arg, "+verilator+prof+threads+window+", u64, 1)) {
|
||||
profExecWindow(u64);
|
||||
} else if (commandArgVlString(arg, "+verilator+prof+exec+file+", str)
|
||||
|| commandArgVlString(arg, "+verilator+prof+threads+file+", str)) {
|
||||
profExecFilename(str);
|
||||
} else if (commandArgVlString(arg, "+verilator+prof+vlt+file+", str)) {
|
||||
profVltFilename(str);
|
||||
} else if (commandArgVlUint64(arg, "+verilator+rand+reset+", u64, 0, 2)) {
|
||||
randReset(static_cast<int>(u64));
|
||||
} else if (commandArgVlUint64(arg, "+verilator+seed+", u64, 1,
|
||||
std::numeric_limits<int>::max())) {
|
||||
randSeed(static_cast<int>(u64));
|
||||
} else if (arg == "+verilator+V") {
|
||||
VerilatedImp::versionDump(); // Someday more info too
|
||||
VL_FATAL_MT("COMMAND_LINE", 0, "",
|
||||
@@ -2519,12 +2559,14 @@ void VerilatedContextImp::commandArgVl(const std::string& arg) {
|
||||
VL_FATAL_MT("COMMAND_LINE", 0, "",
|
||||
"Exiting due to command line argument (not an error)");
|
||||
} else {
|
||||
VL_PRINTF_MT("%%Warning: Unknown +verilator runtime argument: '%s'\n", arg.c_str());
|
||||
const std::string msg = "Unknown runtime argument: " + arg;
|
||||
VL_FATAL_MT("COMMAND_LINE", 0, "", msg.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
bool VerilatedContextImp::commandArgVlValue(const std::string& arg, const std::string& prefix,
|
||||
std::string& valuer) {
|
||||
|
||||
bool VerilatedContextImp::commandArgVlString(const std::string& arg, const std::string& prefix,
|
||||
std::string& valuer) {
|
||||
const size_t len = prefix.length();
|
||||
if (0 == std::strncmp(prefix.c_str(), arg.c_str(), len)) {
|
||||
valuer = arg.substr(len);
|
||||
@@ -2534,6 +2576,30 @@ bool VerilatedContextImp::commandArgVlValue(const std::string& arg, const std::s
|
||||
}
|
||||
}
|
||||
|
||||
bool VerilatedContextImp::commandArgVlUint64(const std::string& arg, const std::string& prefix,
|
||||
uint64_t& valuer, uint64_t min, uint64_t max) {
|
||||
std::string str;
|
||||
if (commandArgVlString(arg, prefix, str)) {
|
||||
const auto fail = [&](const std::string& extra = "") {
|
||||
std::stringstream ss;
|
||||
ss << "Argument '" << prefix << "' must be an unsigned integer";
|
||||
if (min != std::numeric_limits<uint64_t>::min()) ss << ", greater than " << min - 1;
|
||||
if (max != std::numeric_limits<uint64_t>::max()) ss << ", less than " << max + 1;
|
||||
if (!extra.empty()) ss << ". " << extra;
|
||||
const std::string& msg = ss.str();
|
||||
VL_FATAL_MT("COMMAND_LINE", 0, "", msg.c_str());
|
||||
};
|
||||
|
||||
if (std::any_of(str.begin(), str.end(), [](int c) { return !std::isdigit(c); })) fail();
|
||||
char* end;
|
||||
valuer = std::strtoull(str.c_str(), &end, 10);
|
||||
if (errno == ERANGE) fail("Value out of range of uint64_t");
|
||||
if (valuer < min || valuer > max) fail();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//======================================================================
|
||||
// VerilatedContext:: + VerilatedContextImp:: Methods - random
|
||||
|
||||
@@ -2542,20 +2608,19 @@ void VerilatedContext::randSeed(int val) VL_MT_SAFE {
|
||||
// and so the rand seed's mutex must also be static
|
||||
const VerilatedLockGuard lock{VerilatedContextImp::s().s_randMutex};
|
||||
m_s.m_randSeed = val;
|
||||
const vluint64_t newEpoch = VerilatedContextImp::s().s_randSeedEpoch + 1;
|
||||
const uint64_t newEpoch = VerilatedContextImp::s().s_randSeedEpoch + 1;
|
||||
// Obververs must see new epoch AFTER seed updated
|
||||
#ifdef VL_THREADED
|
||||
std::atomic_signal_fence(std::memory_order_release);
|
||||
#endif
|
||||
VerilatedContextImp::s().s_randSeedEpoch = newEpoch;
|
||||
}
|
||||
vluint64_t VerilatedContextImp::randSeedDefault64() const VL_MT_SAFE {
|
||||
uint64_t VerilatedContextImp::randSeedDefault64() const VL_MT_SAFE {
|
||||
if (randSeed() != 0) {
|
||||
return ((static_cast<vluint64_t>(randSeed()) << 32)
|
||||
^ (static_cast<vluint64_t>(randSeed())));
|
||||
return ((static_cast<uint64_t>(randSeed()) << 32) ^ (static_cast<uint64_t>(randSeed())));
|
||||
} else {
|
||||
return ((static_cast<vluint64_t>(vl_sys_rand32()) << 32)
|
||||
^ (static_cast<vluint64_t>(vl_sys_rand32())));
|
||||
return ((static_cast<uint64_t>(vl_sys_rand32()) << 32)
|
||||
^ (static_cast<uint64_t>(vl_sys_rand32())));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2602,6 +2667,7 @@ const VerilatedScopeNameMap* VerilatedContext::scopeNameMap() VL_MT_SAFE {
|
||||
|
||||
VerilatedSyms::VerilatedSyms(VerilatedContext* contextp)
|
||||
: _vm_contextp__(contextp ? contextp : Verilated::threadContextp()) {
|
||||
VerilatedContext::checkMagic(_vm_contextp__);
|
||||
Verilated::threadContextp(_vm_contextp__);
|
||||
#ifdef VL_THREADED
|
||||
__Vm_evalMsgQp = new VerilatedEvalMsgQueue;
|
||||
@@ -2609,6 +2675,7 @@ VerilatedSyms::VerilatedSyms(VerilatedContext* contextp)
|
||||
}
|
||||
|
||||
VerilatedSyms::~VerilatedSyms() {
|
||||
VerilatedContext::checkMagic(_vm_contextp__);
|
||||
#ifdef VL_THREADED
|
||||
delete __Vm_evalMsgQp;
|
||||
#endif
|
||||
@@ -2631,14 +2698,11 @@ void Verilated::debug(int level) VL_MT_SAFE {
|
||||
}
|
||||
}
|
||||
|
||||
const char* Verilated::catName(const char* n1, const char* n2, int scopet,
|
||||
const char* delimiter) VL_MT_SAFE {
|
||||
// Returns new'ed data
|
||||
const char* Verilated::catName(const char* n1, const char* n2, const char* delimiter) VL_MT_SAFE {
|
||||
// Used by symbol table creation to make module names
|
||||
static VL_THREAD_LOCAL char* t_strp = nullptr;
|
||||
static VL_THREAD_LOCAL size_t t_len = 0;
|
||||
const size_t newlen
|
||||
= std::strlen(n1) + std::strlen(n2) + std::strlen(delimiter) + (scopet > 0 ? 2 : 1);
|
||||
const size_t newlen = std::strlen(n1) + std::strlen(n2) + std::strlen(delimiter) + 1;
|
||||
if (VL_UNLIKELY(!t_strp || newlen > t_len)) {
|
||||
if (t_strp) delete[] t_strp;
|
||||
t_strp = new char[newlen];
|
||||
@@ -2646,8 +2710,6 @@ const char* Verilated::catName(const char* n1, const char* n2, int scopet,
|
||||
}
|
||||
char* dp = t_strp;
|
||||
for (const char* sp = n1; *sp;) *dp++ = *sp++;
|
||||
// Add scope type
|
||||
if (scopet) *dp++ = (char)(0x80 + scopet);
|
||||
for (const char* sp = delimiter; *sp;) *dp++ = *sp++;
|
||||
for (const char* sp = n2; *sp;) *dp++ = *sp++;
|
||||
*dp++ = '\0';
|
||||
@@ -2804,8 +2866,8 @@ VerilatedModule::~VerilatedModule() {
|
||||
// VerilatedVar:: Methods
|
||||
|
||||
// cppcheck-suppress unusedFunction // Used by applications
|
||||
vluint32_t VerilatedVarProps::entSize() const {
|
||||
vluint32_t size = 1;
|
||||
uint32_t VerilatedVarProps::entSize() const {
|
||||
uint32_t size = 1;
|
||||
switch (vltype()) {
|
||||
case VLVT_PTR: size = sizeof(void*); break;
|
||||
case VLVT_UINT8: size = sizeof(CData); break;
|
||||
@@ -2827,8 +2889,8 @@ size_t VerilatedVarProps::totalSize() const {
|
||||
void* VerilatedVarProps::datapAdjustIndex(void* datap, int dim, int indx) const {
|
||||
if (VL_UNLIKELY(dim <= 0 || dim > udims())) return nullptr;
|
||||
if (VL_UNLIKELY(indx < low(dim) || indx > high(dim))) return nullptr;
|
||||
int indxAdj = indx - low(dim);
|
||||
vluint8_t* bytep = reinterpret_cast<vluint8_t*>(datap);
|
||||
const int indxAdj = indx - low(dim);
|
||||
uint8_t* bytep = reinterpret_cast<uint8_t*>(datap);
|
||||
// If on index 1 of a 2 index array, then each index 1 is index2sz*entsz
|
||||
size_t slicesz = entSize();
|
||||
for (int d = dim + 1; d <= m_udims; ++d) slicesz *= elements(d);
|
||||
@@ -2849,7 +2911,7 @@ VerilatedScope::~VerilatedScope() {
|
||||
}
|
||||
|
||||
void VerilatedScope::configure(VerilatedSyms* symsp, const char* prefixp, const char* suffixp,
|
||||
const char* identifier, vlsint8_t timeunit,
|
||||
const char* identifier, int8_t timeunit,
|
||||
const Type& type) VL_MT_UNSAFE {
|
||||
// Slowpath - called once/scope at construction
|
||||
// We don't want the space and reference-count access overhead of strings.
|
||||
@@ -2872,7 +2934,7 @@ void VerilatedScope::configure(VerilatedSyms* symsp, const char* prefixp, const
|
||||
void VerilatedScope::exportInsert(int finalize, const char* namep, void* cb) VL_MT_UNSAFE {
|
||||
// Slowpath - called once/scope*export at construction
|
||||
// Insert a exported function into scope table
|
||||
int funcnum = VerilatedImp::exportInsert(namep);
|
||||
const int funcnum = VerilatedImp::exportInsert(namep);
|
||||
if (!finalize) {
|
||||
// Need two passes so we know array size to create
|
||||
// Alternative is to dynamically stretch the array, which is more code, and slower.
|
||||
@@ -2914,7 +2976,7 @@ void VerilatedScope::varInsert(int finalize, const char* namep, void* datap, boo
|
||||
} else {
|
||||
// We could have a linked list of ranges, but really this whole thing needs
|
||||
// to be generalized to support structs and unions, etc.
|
||||
std::string msg
|
||||
const std::string msg
|
||||
= std::string{"Unsupported multi-dimensional public varInsert: "} + namep;
|
||||
VL_FATAL_MT(__FILE__, __LINE__, "", msg.c_str());
|
||||
}
|
||||
@@ -2961,7 +3023,7 @@ void VerilatedScope::scopeDump() const {
|
||||
VerilatedImp::exportName(i));
|
||||
}
|
||||
}
|
||||
if (VerilatedVarNameMap* const varsp = this->varsp()) {
|
||||
if (const VerilatedVarNameMap* const varsp = this->varsp()) {
|
||||
for (const auto& i : *varsp) VL_PRINTF_MT(" VAR %p: %s\n", &(i.second), i.first);
|
||||
}
|
||||
}
|
||||
|
||||
+51
-41
@@ -3,7 +3,7 @@
|
||||
//
|
||||
// Code available from: https://verilator.org
|
||||
//
|
||||
// Copyright 2003-2021 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2022 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,6 +33,7 @@
|
||||
|
||||
// clang-format off
|
||||
#include "verilatedos.h"
|
||||
#include "verilated_config.h"
|
||||
#if VM_SC
|
||||
# include "verilated_sc.h" // Get SYSTEMC_VERSION and time declarations
|
||||
#endif
|
||||
@@ -86,6 +87,7 @@ class VerilatedCovContext;
|
||||
class VerilatedEvalMsgQueue;
|
||||
class VerilatedFst;
|
||||
class VerilatedFstC;
|
||||
class VerilatedFstSc;
|
||||
class VerilatedScope;
|
||||
class VerilatedScopeNameMap;
|
||||
class VerilatedVar;
|
||||
@@ -99,11 +101,11 @@ class VerilatedVcdSc;
|
||||
|
||||
// clang-format off
|
||||
// P // Packed data of bit type (C/S/I/Q/W)
|
||||
using CData = vluint8_t; ///< Data representing 'bit' of 1-8 packed bits
|
||||
using SData = vluint16_t; ///< Data representing 'bit' of 9-16 packed bits
|
||||
using IData = vluint32_t; ///< Data representing 'bit' of 17-32 packed bits
|
||||
using QData = vluint64_t; ///< Data representing 'bit' of 33-64 packed bits
|
||||
using EData = vluint32_t; ///< Data representing one element of WData array
|
||||
using CData = uint8_t; ///< Data representing 'bit' of 1-8 packed bits
|
||||
using SData = uint16_t; ///< Data representing 'bit' of 9-16 packed bits
|
||||
using IData = uint32_t; ///< Data representing 'bit' of 17-32 packed bits
|
||||
using QData = uint64_t; ///< Data representing 'bit' of 33-64 packed bits
|
||||
using EData = uint32_t; ///< Data representing one element of WData array
|
||||
using WData = EData; ///< Data representing >64 packed bits (used as pointer)
|
||||
// F = float; // No typedef needed; Verilator uses float
|
||||
// D = double; // No typedef needed; Verilator uses double
|
||||
@@ -113,7 +115,7 @@ using WData = EData; ///< Data representing >64 packed bits (used as poin
|
||||
using WDataInP = const WData*; ///< 'bit' of >64 packed bits as array input to a function
|
||||
using WDataOutP = WData*; ///< 'bit' of >64 packed bits as array output from a function
|
||||
|
||||
enum VerilatedVarType : vluint8_t {
|
||||
enum VerilatedVarType : uint8_t {
|
||||
VLVT_UNKNOWN = 0,
|
||||
VLVT_PTR, // Pointer to something
|
||||
VLVT_UINT8, // AKA CData
|
||||
@@ -141,11 +143,11 @@ enum VerilatedVarFlags {
|
||||
// Mutex and threading support
|
||||
|
||||
// Return current thread ID (or 0), not super fast, cache if needed
|
||||
extern vluint32_t VL_THREAD_ID() VL_MT_SAFE;
|
||||
extern uint32_t VL_THREAD_ID() VL_MT_SAFE;
|
||||
|
||||
#if VL_THREADED
|
||||
|
||||
#define VL_LOCK_SPINS 50000 /// Number of times to spin for a mutex before relaxing
|
||||
#define VL_LOCK_SPINS 50000 /// Number of times to spin for a mutex before yielding
|
||||
|
||||
/// Mutex, wrapped to allow -fthread_safety checks
|
||||
class VL_CAPABILITY("mutex") VerilatedMutex final {
|
||||
@@ -224,7 +226,7 @@ public:
|
||||
class VerilatedAssertOneThread final {
|
||||
// MEMBERS
|
||||
#if defined(VL_THREADED) && defined(VL_DEBUG)
|
||||
vluint32_t m_threadid; // Thread that is legal
|
||||
uint32_t m_threadid; // Thread that is legal
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
// The constructor establishes the thread id for all later calls.
|
||||
@@ -318,10 +320,10 @@ protected:
|
||||
bool m_fatalOnVpiError = true; // Fatal on vpi error/unsupported
|
||||
bool m_gotError = false; // A $finish statement executed
|
||||
bool m_gotFinish = false; // A $finish or $stop statement executed
|
||||
vluint64_t m_time = 0; // Current $time (unscaled), 0=at zero, or legacy
|
||||
uint64_t m_time = 0; // Current $time (unscaled), 0=at zero, or legacy
|
||||
// Slow path
|
||||
vlsint8_t m_timeunit; // Time unit as 0..15
|
||||
vlsint8_t m_timeprecision; // Time precision as 0..15
|
||||
int8_t m_timeunit; // Time unit as 0..15
|
||||
int8_t m_timeprecision; // Time precision as 0..15
|
||||
int m_errorCount = 0; // Number of errors
|
||||
int m_errorLimit = 1; // Stop on error number
|
||||
int m_randReset = 0; // Random reset: 0=all 0s, 1=all 1s, 2=random
|
||||
@@ -342,10 +344,10 @@ protected:
|
||||
struct NonSerialized { // Non-serialized information
|
||||
// These are reloaded from on command-line settings, so do not need to persist
|
||||
// Fast path
|
||||
vluint64_t m_profThreadsStart = 1; // +prof+threads starting time
|
||||
vluint32_t m_profThreadsWindow = 2; // +prof+threads window size
|
||||
uint64_t m_profExecStart = 1; // +prof+exec+start time
|
||||
uint32_t m_profExecWindow = 2; // +prof+exec+window size
|
||||
// Slow path
|
||||
std::string m_profThreadsFilename; // +prof+threads filename
|
||||
std::string m_profExecFilename; // +prof+exec+file filename
|
||||
std::string m_profVltFilename; // +prof+vlt filename
|
||||
} m_ns;
|
||||
|
||||
@@ -359,7 +361,7 @@ protected:
|
||||
} m_args VL_GUARDED_BY(m_argMutex);
|
||||
|
||||
// Implementation details
|
||||
std::unique_ptr<VerilatedContextImpData> m_impdatap;
|
||||
const std::unique_ptr<VerilatedContextImpData> m_impdatap;
|
||||
// Coverage access
|
||||
std::unique_ptr<VerilatedVirtualBase> m_coveragep; // Pointer for coveragep()
|
||||
|
||||
@@ -372,6 +374,10 @@ protected:
|
||||
// List of free descriptors in the MCT region [4, 32)
|
||||
std::vector<IData> m_fdFreeMct VL_GUARDED_BY(m_fdMutex);
|
||||
|
||||
// Magic to check for bad construction
|
||||
static constexpr uint64_t MAGIC = 0xC35F9A6E5298EE6EULL; // SHA256 "VerilatedContext"
|
||||
uint64_t m_magic = MAGIC;
|
||||
|
||||
private:
|
||||
// CONSTRUCTORS
|
||||
VL_UNCOPYABLE(VerilatedContext);
|
||||
@@ -466,16 +472,16 @@ public:
|
||||
/// timeInc, operating on the thread's context.
|
||||
///
|
||||
/// * Else, if VL_TIME_STAMP64 is defined, time comes from the legacy
|
||||
/// 'vluint64_t vl_time_stamp64()' which must a function be defined by
|
||||
/// 'uint64_t vl_time_stamp64()' which must a function be defined by
|
||||
/// the user's wrapper.
|
||||
///
|
||||
/// * Else, time comes from the legacy 'double sc_time_stamp()' which
|
||||
/// must be a function defined by the user's wrapper.
|
||||
vluint64_t time() const VL_MT_SAFE;
|
||||
uint64_t time() const VL_MT_SAFE;
|
||||
/// Set current simulation time. See time() for side effect details
|
||||
void time(vluint64_t value) VL_MT_SAFE { m_s.m_time = value; }
|
||||
void time(uint64_t value) VL_MT_SAFE { m_s.m_time = value; }
|
||||
/// Advance current simulation time. See time() for side effect details
|
||||
void timeInc(vluint64_t add) VL_MT_UNSAFE { m_s.m_time += add; }
|
||||
void timeInc(uint64_t add) VL_MT_UNSAFE { m_s.m_time += add; }
|
||||
/// Return time units as power-of-ten
|
||||
int timeunit() const VL_MT_SAFE { return -m_s.m_timeunit; }
|
||||
/// Set time units as power-of-ten
|
||||
@@ -516,13 +522,13 @@ public: // But for internal use only
|
||||
std::string dumpfile() const VL_MT_SAFE_EXCLUDES(m_timeDumpMutex);
|
||||
std::string dumpfileCheck() const VL_MT_SAFE_EXCLUDES(m_timeDumpMutex);
|
||||
|
||||
// Internal: --prof-threads related settings
|
||||
void profThreadsStart(vluint64_t flag) VL_MT_SAFE;
|
||||
vluint64_t profThreadsStart() const VL_MT_SAFE { return m_ns.m_profThreadsStart; }
|
||||
void profThreadsWindow(vluint64_t flag) VL_MT_SAFE;
|
||||
vluint32_t profThreadsWindow() const VL_MT_SAFE { return m_ns.m_profThreadsWindow; }
|
||||
void profThreadsFilename(const std::string& flag) VL_MT_SAFE;
|
||||
std::string profThreadsFilename() const VL_MT_SAFE;
|
||||
// Internal: --prof-exec related settings
|
||||
void profExecStart(uint64_t flag) VL_MT_SAFE;
|
||||
uint64_t profExecStart() const VL_MT_SAFE { return m_ns.m_profExecStart; }
|
||||
void profExecWindow(uint64_t flag) VL_MT_SAFE;
|
||||
uint32_t profExecWindow() const VL_MT_SAFE { return m_ns.m_profExecWindow; }
|
||||
void profExecFilename(const std::string& flag) VL_MT_SAFE;
|
||||
std::string profExecFilename() const VL_MT_SAFE;
|
||||
void profVltFilename(const std::string& flag) VL_MT_SAFE;
|
||||
std::string profVltFilename() const VL_MT_SAFE;
|
||||
|
||||
@@ -533,6 +539,10 @@ public: // But for internal use only
|
||||
// Internal: Serialization setup
|
||||
static constexpr size_t serialized1Size() VL_PURE { return sizeof(m_s); }
|
||||
void* serialized1Ptr() VL_MT_UNSAFE { return &m_s; }
|
||||
|
||||
// Internal: Check magic number
|
||||
static void checkMagic(const VerilatedContext* contextp);
|
||||
void selfTestClearMagic() { m_magic = 0x2; }
|
||||
};
|
||||
|
||||
//===========================================================================
|
||||
@@ -557,7 +567,7 @@ public: // But for internal use only
|
||||
|
||||
class VerilatedScope final {
|
||||
public:
|
||||
enum Type : vluint8_t {
|
||||
enum Type : uint8_t {
|
||||
SCOPE_MODULE,
|
||||
SCOPE_OTHER
|
||||
}; // Type of a scope, currently module is only interesting
|
||||
@@ -570,21 +580,21 @@ private:
|
||||
VerilatedVarNameMap* m_varsp = nullptr; // Variable map
|
||||
const char* m_namep = nullptr; // Scope name (Slowpath)
|
||||
const char* m_identifierp = nullptr; // Identifier of scope (with escapes removed)
|
||||
vlsint8_t m_timeunit = 0; // Timeunit in negative power-of-10
|
||||
int8_t m_timeunit = 0; // Timeunit in negative power-of-10
|
||||
Type m_type = SCOPE_OTHER; // Type of the scope
|
||||
|
||||
public: // But internals only - called from VerilatedModule's
|
||||
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;
|
||||
const char* identifier, int8_t timeunit, const Type& type) VL_MT_UNSAFE;
|
||||
void exportInsert(int finalize, const char* namep, void* cb) VL_MT_UNSAFE;
|
||||
void varInsert(int finalize, const char* namep, void* datap, bool isParam,
|
||||
VerilatedVarType vltype, int vlflags, int dims, ...) VL_MT_UNSAFE;
|
||||
// ACCESSORS
|
||||
const char* name() const { return m_namep; }
|
||||
const char* identifier() const { return m_identifierp; }
|
||||
vlsint8_t timeunit() const { return m_timeunit; }
|
||||
int8_t timeunit() const { return m_timeunit; }
|
||||
inline VerilatedSyms* symsp() const { return m_symsp; }
|
||||
VerilatedVar* varFind(const char* namep) const VL_MT_SAFE_POSTINIT;
|
||||
VerilatedVarNameMap* varsp() const VL_MT_SAFE_POSTINIT { return m_varsp; }
|
||||
@@ -634,9 +644,9 @@ class Verilated final {
|
||||
// Fast path
|
||||
VerilatedContext* t_contextp = nullptr; // Thread's context
|
||||
#ifdef VL_THREADED
|
||||
vluint32_t t_mtaskId = 0; // mtask# executing on this thread
|
||||
uint32_t t_mtaskId = 0; // mtask# executing on this thread
|
||||
// Messages maybe pending on thread, needs end-of-eval calls
|
||||
vluint32_t t_endOfEvalReqd = 0;
|
||||
uint32_t t_endOfEvalReqd = 0;
|
||||
#endif
|
||||
const VerilatedScope* t_dpiScopep = nullptr; // DPI context scope
|
||||
const char* t_dpiFilename = nullptr; // DPI context filename
|
||||
@@ -758,11 +768,11 @@ public:
|
||||
/// Return VerilatedContext::randSeed using current thread's VerilatedContext
|
||||
static int randSeed() VL_MT_SAFE { return Verilated::threadContextp()->randSeed(); }
|
||||
/// Call VerilatedContext::time using current thread's VerilatedContext
|
||||
static void time(vluint64_t val) VL_MT_SAFE { Verilated::threadContextp()->time(val); }
|
||||
static void time(uint64_t val) VL_MT_SAFE { Verilated::threadContextp()->time(val); }
|
||||
/// Return VerilatedContext::time using current thread's VerilatedContext
|
||||
static vluint64_t time() VL_MT_SAFE { return Verilated::threadContextp()->time(); }
|
||||
static uint64_t time() VL_MT_SAFE { return Verilated::threadContextp()->time(); }
|
||||
/// Call VerilatedContext::timeInc using current thread's VerilatedContext
|
||||
static void timeInc(vluint64_t add) VL_MT_UNSAFE { Verilated::threadContextp()->timeInc(add); }
|
||||
static void timeInc(uint64_t add) VL_MT_UNSAFE { Verilated::threadContextp()->timeInc(add); }
|
||||
// Deprecated
|
||||
static int timeunit() VL_MT_SAFE { return Verilated::threadContextp()->timeunit(); }
|
||||
static int timeprecision() VL_MT_SAFE { return Verilated::threadContextp()->timeprecision(); }
|
||||
@@ -823,8 +833,8 @@ public:
|
||||
public:
|
||||
// METHODS - INTERNAL USE ONLY (but public due to what uses it)
|
||||
// Internal: Create a new module name by concatenating two strings
|
||||
static const char* catName(const char* n1, const char* n2, int scopet = 0,
|
||||
const char* delimiter = "."); // Returns static data
|
||||
// Returns pointer to thread-local static data (overwritten on next call)
|
||||
static const char* catName(const char* n1, const char* n2, const char* delimiter = ".");
|
||||
|
||||
// Internal: Throw signal assertion
|
||||
static void nullPointerError(const char* filename, int linenum) VL_ATTR_NORETURN VL_MT_SAFE;
|
||||
@@ -848,8 +858,8 @@ public:
|
||||
#ifdef VL_THREADED
|
||||
// Internal: Set the mtaskId, called when an mtask starts
|
||||
// Per thread, so no need to be in VerilatedContext
|
||||
static void mtaskId(vluint32_t id) VL_MT_SAFE { t_s.t_mtaskId = id; }
|
||||
static vluint32_t mtaskId() VL_MT_SAFE { return t_s.t_mtaskId; }
|
||||
static void mtaskId(uint32_t id) VL_MT_SAFE { t_s.t_mtaskId = id; }
|
||||
static uint32_t mtaskId() VL_MT_SAFE { return t_s.t_mtaskId; }
|
||||
static void endOfEvalReqdInc() VL_MT_SAFE { ++t_s.t_endOfEvalReqd; }
|
||||
static void endOfEvalReqdDec() VL_MT_SAFE { --t_s.t_endOfEvalReqd; }
|
||||
|
||||
|
||||
+12
-3
@@ -2,7 +2,7 @@
|
||||
######################################################################
|
||||
# DESCRIPTION: Makefile commands for all verilated target files
|
||||
#
|
||||
# Copyright 2003-2021 by Wilson Snyder. This program is free software; you
|
||||
# Copyright 2003-2022 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.
|
||||
@@ -56,6 +56,7 @@ VK_CPPFLAGS_ALWAYS += \
|
||||
-DVM_SC=$(VM_SC) \
|
||||
-DVM_TRACE=$(VM_TRACE) \
|
||||
-DVM_TRACE_FST=$(VM_TRACE_FST) \
|
||||
-DVM_TRACE_VCD=$(VM_TRACE_VCD) \
|
||||
$(CFG_CXXFLAGS_NO_UNUSED) \
|
||||
|
||||
ifeq ($(CFG_WITH_CCWARN),yes) # Local... Else don't burden users
|
||||
@@ -193,6 +194,10 @@ VK_USER_OBJS = $(addsuffix .o, $(VM_USER_CLASSES))
|
||||
# but keeping the distinction for compatibility for now.
|
||||
VK_GLOBAL_OBJS = $(addsuffix .o, $(VM_GLOBAL_FAST) $(VM_GLOBAL_SLOW))
|
||||
|
||||
# Need to re-build if the generated makefile changes, as compiler options might
|
||||
# have changed.
|
||||
$(VK_GLOBAL_OBJS): $(VM_PREFIX).mk
|
||||
|
||||
ifneq ($(VM_PARALLEL_BUILDS),1)
|
||||
# Fast build for small designs: All .cpp files in one fell swoop. This
|
||||
# saves total compute, but can be slower if only a little changes. It is
|
||||
@@ -223,7 +228,9 @@ endif
|
||||
$(info Archive $(AR) -rcs $@ $^)
|
||||
$(foreach L, $(filter-out %.a,$^), $(shell echo $L >>[email protected]_deplist.tmp))
|
||||
@if test $(words $(filter %.a,$^)) -eq 0; then \
|
||||
$(AR) -rcs $@ @[email protected]_deplist.tmp; \
|
||||
$(RM) -f $@; \
|
||||
cat [email protected]_deplist.tmp | xargs $(AR) -rc $@; \
|
||||
$(AR) -s $@; \
|
||||
else \
|
||||
$(RM) -rf [email protected]; \
|
||||
for archive in $(filter %.a,$^); do \
|
||||
@@ -232,7 +239,9 @@ endif
|
||||
$(AR) -x ../../$${archive}; \
|
||||
cd ../..; \
|
||||
done; \
|
||||
$(AR) -rcs $@ @[email protected]_deplist.tmp [email protected]/*/*.o; \
|
||||
$(RM) -f $@; \
|
||||
cat [email protected]_deplist.tmp | xargs $(AR) -rc $@; \
|
||||
$(AR) -rcs $@ [email protected]/*/*.o; \
|
||||
fi \
|
||||
; $(RM) -rf [email protected]_deplist.tmp [email protected]
|
||||
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
//
|
||||
// Code available from: https://verilator.org
|
||||
//
|
||||
// Copyright 2003-2021 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2022 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 @@
|
||||
//
|
||||
// Code available from: https://verilator.org
|
||||
//
|
||||
// Copyright 2003-2021 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2022 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.
|
||||
@@ -20,6 +20,11 @@
|
||||
// Autoconf substitutes this with the strings from AC_INIT.
|
||||
#define VERILATOR_PRODUCT "@PACKAGE_NAME@"
|
||||
|
||||
/// Verilator version name, e.g. "1.000 2000-01-01"
|
||||
/// Verilator version name, e.g. "1.002 2000-01-01"
|
||||
// Autoconf substitutes this with the strings from AC_INIT.
|
||||
#define VERILATOR_VERSION "@PACKAGE_VERSION@"
|
||||
|
||||
/// Verilator version number as integer
|
||||
/// As major * 100000 + minor * 1000, e.g. 1002000 == 1.002
|
||||
// Autoconf substitutes this with the strings from AC_INIT.
|
||||
#define VERILATOR_VERSION_INTEGER @VERILATOR_VERSION_INTEGER@
|
||||
|
||||
+20
-22
@@ -3,7 +3,7 @@
|
||||
//
|
||||
// Code available from: https://verilator.org
|
||||
//
|
||||
// Copyright 2001-2021 by Wilson Snyder. This program is free software; you
|
||||
// Copyright 2001-2022 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,6 +29,7 @@
|
||||
#include <deque>
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
#include <utility>
|
||||
|
||||
//=============================================================================
|
||||
// VerilatedCovConst
|
||||
@@ -58,7 +59,7 @@ public: // But only local to this file
|
||||
}
|
||||
}
|
||||
virtual ~VerilatedCovImpItem() = default;
|
||||
virtual vluint64_t count() const = 0;
|
||||
virtual uint64_t count() const = 0;
|
||||
virtual void zero() const = 0;
|
||||
};
|
||||
|
||||
@@ -75,7 +76,7 @@ private:
|
||||
public:
|
||||
// METHODS
|
||||
// cppcheck-suppress truncLongCastReturn
|
||||
virtual vluint64_t count() const override { return *m_countp; }
|
||||
virtual uint64_t count() const override { return *m_countp; }
|
||||
virtual void zero() const override { *m_countp = 0; }
|
||||
// CONSTRUCTORS
|
||||
// cppcheck-suppress noExplicitConstructor
|
||||
@@ -102,7 +103,7 @@ private:
|
||||
using ItemList = std::deque<VerilatedCovImpItem*>;
|
||||
|
||||
// MEMBERS
|
||||
VerilatedMutex m_mutex; // Protects all members
|
||||
mutable VerilatedMutex m_mutex; // Protects all members
|
||||
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
|
||||
@@ -122,10 +123,6 @@ public:
|
||||
protected:
|
||||
friend class VerilatedCovContext;
|
||||
virtual ~VerilatedCovImp() override { clearGuts(); }
|
||||
static VerilatedCovImp& imp() VL_MT_SAFE {
|
||||
static VerilatedCovImp s_singleton;
|
||||
return s_singleton;
|
||||
}
|
||||
|
||||
private:
|
||||
// PRIVATE METHODS
|
||||
@@ -206,9 +203,9 @@ private:
|
||||
}
|
||||
|
||||
// Forward to . so we have a whole word
|
||||
std::string suffix = *bpost ? std::string{bpost + 1} : "";
|
||||
const std::string suffix = *bpost ? std::string{bpost + 1} : "";
|
||||
|
||||
std::string out = prefix + "*" + suffix;
|
||||
const std::string out = prefix + "*" + suffix;
|
||||
|
||||
// cout << "\nch pre="<<prefix<<" s="<<suffix<<"\nch a="<<old<<"\nch b="<<add
|
||||
// <<"\ncho="<<out<<endl;
|
||||
@@ -219,7 +216,7 @@ private:
|
||||
for (int i = 0; i < VerilatedCovConst::MAX_KEYS; ++i) {
|
||||
if (itemp->m_keys[i] != VerilatedCovConst::KEY_UNDEF) {
|
||||
// We don't compare keys, only values
|
||||
std::string val = m_indexValues[itemp->m_vals[i]];
|
||||
const std::string val = m_indexValues[itemp->m_vals[i]];
|
||||
if (std::string::npos != val.find(match)) { // Found
|
||||
return true;
|
||||
}
|
||||
@@ -231,7 +228,7 @@ private:
|
||||
// Little selftest
|
||||
#define SELF_CHECK(got, exp) \
|
||||
do { \
|
||||
if ((got) != (exp)) VL_FATAL_MT(__FILE__, __LINE__, "", "%Error: selftest\n"); \
|
||||
if ((got) != (exp)) VL_FATAL_MT(__FILE__, __LINE__, "", "%Error: selftest"); \
|
||||
} while (0)
|
||||
SELF_CHECK(combineHier("a.b.c", "a.b.c"), "a.b.c");
|
||||
SELF_CHECK(combineHier("a.b.c", "a.b"), "a.b*");
|
||||
@@ -302,7 +299,7 @@ public:
|
||||
// First two key/vals are filename
|
||||
ckeyps[0] = "filename";
|
||||
valps[0] = m_insertFilenamep;
|
||||
std::string linestr = vlCovCvtToStr(m_insertLineno);
|
||||
const std::string linestr = vlCovCvtToStr(m_insertLineno);
|
||||
ckeyps[1] = "lineno";
|
||||
valps[1] = linestr.c_str();
|
||||
// Default page if not specified
|
||||
@@ -342,7 +339,7 @@ public:
|
||||
m_insertp->m_vals[addKeynum] = valueIndex(val);
|
||||
++addKeynum;
|
||||
if (VL_UNCOVERABLE(!legalKey(key))) {
|
||||
std::string msg
|
||||
const std::string msg
|
||||
= ("%Error: Coverage keys of one character, or letter+digit are illegal: "
|
||||
+ key); // LCOV_EXCL_LINE
|
||||
VL_FATAL_MT("", 0, "", msg.c_str());
|
||||
@@ -358,7 +355,7 @@ public:
|
||||
Verilated::quiesce();
|
||||
const VerilatedLockGuard lock{m_mutex};
|
||||
#ifndef VM_COVERAGE
|
||||
VL_FATAL_MT("", 0, "", "%Error: Called VerilatedCov::write when VM_COVERAGE disabled\n");
|
||||
VL_FATAL_MT("", 0, "", "%Error: Called VerilatedCov::write when VM_COVERAGE disabled");
|
||||
#endif
|
||||
selftest();
|
||||
|
||||
@@ -371,7 +368,7 @@ public:
|
||||
os << "# SystemC::Coverage-3\n";
|
||||
|
||||
// Build list of events; totalize if collapsing hierarchy
|
||||
std::map<const std::string, std::pair<std::string, vluint64_t>> eventCounts;
|
||||
std::map<const std::string, std::pair<std::string, uint64_t>> eventCounts;
|
||||
for (const auto& itemp : m_items) {
|
||||
std::string name;
|
||||
std::string hier;
|
||||
@@ -380,8 +377,9 @@ public:
|
||||
|
||||
for (int i = 0; i < VerilatedCovConst::MAX_KEYS; ++i) {
|
||||
if (itemp->m_keys[i] != VerilatedCovConst::KEY_UNDEF) {
|
||||
std::string key = VerilatedCovKey::shortKey(m_indexValues[itemp->m_keys[i]]);
|
||||
std::string val = m_indexValues[itemp->m_vals[i]];
|
||||
const std::string key
|
||||
= VerilatedCovKey::shortKey(m_indexValues[itemp->m_keys[i]]);
|
||||
const std::string val = m_indexValues[itemp->m_vals[i]];
|
||||
if (key == VL_CIK_PER_INSTANCE) {
|
||||
if (val != "0") per_instance = true;
|
||||
}
|
||||
@@ -437,11 +435,11 @@ void VerilatedCovContext::clearNonMatch(const char* matchp) VL_MT_SAFE {
|
||||
}
|
||||
void VerilatedCovContext::zero() VL_MT_SAFE { impp()->zero(); }
|
||||
void VerilatedCovContext::write(const char* filenamep) VL_MT_SAFE { impp()->write(filenamep); }
|
||||
void VerilatedCovContext::_inserti(vluint32_t* itemp) VL_MT_SAFE {
|
||||
impp()->inserti(new VerilatedCoverItemSpec<vluint32_t>{itemp});
|
||||
void VerilatedCovContext::_inserti(uint32_t* itemp) VL_MT_SAFE {
|
||||
impp()->inserti(new VerilatedCoverItemSpec<uint32_t>{itemp});
|
||||
}
|
||||
void VerilatedCovContext::_inserti(vluint64_t* itemp) VL_MT_SAFE {
|
||||
impp()->inserti(new VerilatedCoverItemSpec<vluint64_t>{itemp});
|
||||
void VerilatedCovContext::_inserti(uint64_t* itemp) VL_MT_SAFE {
|
||||
impp()->inserti(new VerilatedCoverItemSpec<uint64_t>{itemp});
|
||||
}
|
||||
void VerilatedCovContext::_insertf(const char* filename, int lineno) VL_MT_SAFE {
|
||||
impp()->insertf(filename, lineno);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
//
|
||||
// Code available from: https://verilator.org
|
||||
//
|
||||
// Copyright 2001-2021 by Wilson Snyder. This program is free software; you
|
||||
// Copyright 2001-2022 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.
|
||||
@@ -72,7 +72,7 @@ class VerilatedCovImp;
|
||||
///
|
||||
/// Example:
|
||||
///
|
||||
/// vluint32_t m_cases[10]; // Storage for coverage data
|
||||
/// uint32_t m_cases[10]; // Storage for coverage data
|
||||
/// constructor() {
|
||||
/// // Initialize
|
||||
/// for (int i = 0; i < 10; ++i) m_cases[i] = 0;
|
||||
@@ -126,8 +126,8 @@ public: // But Internal use only
|
||||
// Call _insert1, followed by _insert2 and _insert3
|
||||
// Do not call directly; use VL_COVER_INSERT or higher level macros instead
|
||||
// _insert1: Remember item pointer with count. (Not const, as may add zeroing function)
|
||||
void _inserti(vluint32_t* itemp) VL_MT_SAFE;
|
||||
void _inserti(vluint64_t* itemp) VL_MT_SAFE;
|
||||
void _inserti(uint32_t* itemp) VL_MT_SAFE;
|
||||
void _inserti(uint64_t* itemp) VL_MT_SAFE;
|
||||
// _insert2: Set default filename and line number
|
||||
void _insertf(const char* filename, int lineno) VL_MT_SAFE;
|
||||
// _insert3: Set parameters
|
||||
@@ -157,8 +157,8 @@ protected:
|
||||
friend class VerilatedCovImp;
|
||||
// CONSTRUCTORS
|
||||
// Internal: Only made as part of VerilatedCovImp
|
||||
VerilatedCovContext() {}
|
||||
virtual ~VerilatedCovContext() {}
|
||||
VerilatedCovContext() = default;
|
||||
virtual ~VerilatedCovContext() = default;
|
||||
|
||||
// METHODS
|
||||
// Internal: access to implementation class
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
//
|
||||
// Code available from: https://verilator.org
|
||||
//
|
||||
// Copyright 2001-2021 by Wilson Snyder. This program is free software; you
|
||||
// Copyright 2001-2022 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 @@
|
||||
//
|
||||
// Code available from: https://verilator.org
|
||||
//
|
||||
// Copyright 2009-2021 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2009-2022 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.
|
||||
@@ -68,7 +68,7 @@ svLogic svGetBitselLogic(const svLogicVecVal* sp, int bit) {
|
||||
| (((sp[VL_BITWORD_I(bit)].bval >> VL_BITBIT_I(bit)) & 1) << 1));
|
||||
}
|
||||
|
||||
void svPutBitselBit(svBitVecVal* dp, int bit, svBit s) { VL_ASSIGNBIT_WI(32, bit, dp, s); }
|
||||
void svPutBitselBit(svBitVecVal* dp, int bit, svBit s) { VL_ASSIGNBIT_WI(bit, dp, s); }
|
||||
void svPutBitselLogic(svLogicVecVal* dp, int bit, svLogic s) {
|
||||
// Verilator doesn't support X/Z so only aval
|
||||
dp[VL_BITWORD_I(bit)].aval = ((dp[VL_BITWORD_I(bit)].aval & ~(VL_UL(1) << VL_BITBIT_I(bit)))
|
||||
@@ -417,7 +417,7 @@ static void _vl_svPutBitArrElem(const svOpenArrayHandle d, svBit value, int narg
|
||||
}
|
||||
|
||||
//======================================================================
|
||||
// DPI accessors that simply call above functions
|
||||
// DPI accessors that call above functions
|
||||
|
||||
void* svGetArrElemPtr(const svOpenArrayHandle h, int indx1, ...) {
|
||||
const VerilatedDpiOpenVar* const varp = _vl_openhandle_varp(h);
|
||||
@@ -428,13 +428,13 @@ void* svGetArrElemPtr(const svOpenArrayHandle h, int indx1, ...) {
|
||||
switch (varp->udims()) {
|
||||
case 1: datap = _vl_svGetArrElemPtr(h, 1, indx1, 0, 0); break;
|
||||
case 2: {
|
||||
int indx2 = va_arg(ap, int);
|
||||
const int indx2 = va_arg(ap, int);
|
||||
datap = _vl_svGetArrElemPtr(h, 2, indx1, indx2, 0);
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
int indx2 = va_arg(ap, int);
|
||||
int indx3 = va_arg(ap, int);
|
||||
const int indx2 = va_arg(ap, int);
|
||||
const int indx3 = va_arg(ap, int);
|
||||
datap = _vl_svGetArrElemPtr(h, 3, indx1, indx2, indx3);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
//
|
||||
// Code available from: https://verilator.org
|
||||
//
|
||||
// Copyright 2003-2021 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2022 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.
|
||||
|
||||
+69
-35
@@ -3,7 +3,7 @@
|
||||
//
|
||||
// Code available from: https://verilator.org
|
||||
//
|
||||
// Copyright 2001-2021 by Wilson Snyder. This program is free software; you
|
||||
// Copyright 2001-2022 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.
|
||||
@@ -83,9 +83,11 @@ static_assert(static_cast<int>(FST_ST_VCD_PROGRAM) == static_cast<int>(VLT_TRACE
|
||||
//=============================================================================
|
||||
// Specialization of the generics for this trace format
|
||||
|
||||
#define VL_DERIVED_T VerilatedFst
|
||||
#include "verilated_trace_imp.cpp"
|
||||
#undef VL_DERIVED_T
|
||||
#define VL_SUB_T VerilatedFst
|
||||
#define VL_BUF_T VerilatedFstBuffer
|
||||
#include "verilated_trace_imp.h"
|
||||
#undef VL_SUB_T
|
||||
#undef VL_BUF_T
|
||||
|
||||
//=============================================================================
|
||||
// VerilatedFst
|
||||
@@ -111,7 +113,7 @@ void VerilatedFst::open(const char* filename) VL_MT_SAFE_EXCLUDES(m_mutex) {
|
||||
|
||||
m_curScope.clear();
|
||||
|
||||
VerilatedTrace<VerilatedFst>::traceInit();
|
||||
Super::traceInit();
|
||||
|
||||
// Clear the scope stack
|
||||
auto it = m_curScope.begin();
|
||||
@@ -122,7 +124,7 @@ void VerilatedFst::open(const char* filename) VL_MT_SAFE_EXCLUDES(m_mutex) {
|
||||
|
||||
// convert m_code2symbol into an array for fast lookup
|
||||
if (!m_symbolp) {
|
||||
m_symbolp = new fstHandle[nextCode()];
|
||||
m_symbolp = new fstHandle[nextCode()]{0};
|
||||
for (const auto& i : m_code2symbol) m_symbolp[i.first] = i.second;
|
||||
}
|
||||
m_code2symbol.clear();
|
||||
@@ -133,23 +135,23 @@ void VerilatedFst::open(const char* filename) VL_MT_SAFE_EXCLUDES(m_mutex) {
|
||||
|
||||
void VerilatedFst::close() VL_MT_SAFE_EXCLUDES(m_mutex) {
|
||||
const VerilatedLockGuard lock{m_mutex};
|
||||
VerilatedTrace<VerilatedFst>::closeBase();
|
||||
Super::closeBase();
|
||||
fstWriterClose(m_fst);
|
||||
m_fst = nullptr;
|
||||
}
|
||||
|
||||
void VerilatedFst::flush() VL_MT_SAFE_EXCLUDES(m_mutex) {
|
||||
const VerilatedLockGuard lock{m_mutex};
|
||||
VerilatedTrace<VerilatedFst>::flushBase();
|
||||
Super::flushBase();
|
||||
fstWriterFlushContext(m_fst);
|
||||
}
|
||||
|
||||
void VerilatedFst::emitTimeChange(vluint64_t timeui) { fstWriterEmitTimeChange(m_fst, timeui); }
|
||||
void VerilatedFst::emitTimeChange(uint64_t timeui) { fstWriterEmitTimeChange(m_fst, timeui); }
|
||||
|
||||
//=============================================================================
|
||||
// Decl
|
||||
|
||||
void VerilatedFst::declDTypeEnum(int dtypenum, const char* name, vluint32_t elements,
|
||||
void VerilatedFst::declDTypeEnum(int dtypenum, const char* name, uint32_t elements,
|
||||
unsigned int minValbits, const char** itemNamesp,
|
||||
const char** itemValuesp) {
|
||||
const fstEnumHandle enumNum
|
||||
@@ -157,19 +159,21 @@ void VerilatedFst::declDTypeEnum(int dtypenum, const char* name, vluint32_t elem
|
||||
m_local2fstdtype[dtypenum] = enumNum;
|
||||
}
|
||||
|
||||
void VerilatedFst::declare(vluint32_t code, const char* name, int dtypenum, fstVarDir vardir,
|
||||
fstVarType vartype, bool array, int arraynum, int msb, int lsb) {
|
||||
void VerilatedFst::declare(uint32_t code, const char* name, int dtypenum, fstVarDir vardir,
|
||||
fstVarType vartype, bool array, int arraynum, bool bussed, int msb,
|
||||
int lsb) {
|
||||
const int bits = ((msb > lsb) ? (msb - lsb) : (lsb - msb)) + 1;
|
||||
|
||||
VerilatedTrace<VerilatedFst>::declCode(code, bits, false);
|
||||
const bool enabled = Super::declCode(code, name, bits, false);
|
||||
if (!enabled) return;
|
||||
|
||||
std::istringstream nameiss{name};
|
||||
std::string nameasstr = namePrefix() + name;
|
||||
std::istringstream nameiss{nameasstr};
|
||||
std::istream_iterator<std::string> beg(nameiss);
|
||||
std::istream_iterator<std::string> end;
|
||||
std::list<std::string> tokens(beg, end); // Split name
|
||||
std::string symbol_name{tokens.back()};
|
||||
tokens.pop_back(); // Remove symbol name from hierarchy
|
||||
tokens.insert(tokens.begin(), moduleName()); // Add current module to the hierarchy
|
||||
std::string tmpModName;
|
||||
|
||||
// Find point where current and new scope diverge
|
||||
@@ -195,9 +199,9 @@ void VerilatedFst::declare(vluint32_t code, const char* name, int dtypenum, fstV
|
||||
// If the scope ends with a non-ascii character, it will be 0x80 + fstScopeType
|
||||
fstWriterSetScope(m_fst, static_cast<fstScopeType>(new_it->back() & 0x7f),
|
||||
tmpModName.c_str(), nullptr);
|
||||
} else
|
||||
} else {
|
||||
fstWriterSetScope(m_fst, FST_ST_VCD_SCOPE, new_it->c_str(), nullptr);
|
||||
|
||||
}
|
||||
m_curScope.push_back(*new_it);
|
||||
new_it = tokens.erase(new_it);
|
||||
}
|
||||
@@ -205,6 +209,7 @@ void VerilatedFst::declare(vluint32_t code, const char* name, int dtypenum, fstV
|
||||
std::stringstream name_ss;
|
||||
name_ss << symbol_name;
|
||||
if (array) name_ss << "[" << arraynum << "]";
|
||||
if (bussed) name_ss << " [" << msb << ":" << lsb << "]";
|
||||
std::string name_str = name_ss.str();
|
||||
|
||||
if (dtypenum > 0) {
|
||||
@@ -221,66 +226,95 @@ void VerilatedFst::declare(vluint32_t code, const char* name, int dtypenum, fstV
|
||||
}
|
||||
}
|
||||
|
||||
void VerilatedFst::declBit(vluint32_t code, const char* name, int dtypenum, fstVarDir vardir,
|
||||
void VerilatedFst::declBit(uint32_t code, const char* name, int dtypenum, fstVarDir vardir,
|
||||
fstVarType vartype, bool array, int arraynum) {
|
||||
declare(code, name, dtypenum, vardir, vartype, array, arraynum, 0, 0);
|
||||
declare(code, name, dtypenum, vardir, vartype, array, arraynum, false, 0, 0);
|
||||
}
|
||||
void VerilatedFst::declBus(vluint32_t code, const char* name, int dtypenum, fstVarDir vardir,
|
||||
void VerilatedFst::declBus(uint32_t code, const char* name, int dtypenum, fstVarDir vardir,
|
||||
fstVarType vartype, bool array, int arraynum, int msb, int lsb) {
|
||||
declare(code, name, dtypenum, vardir, vartype, array, arraynum, msb, lsb);
|
||||
declare(code, name, dtypenum, vardir, vartype, array, arraynum, true, msb, lsb);
|
||||
}
|
||||
void VerilatedFst::declQuad(vluint32_t code, const char* name, int dtypenum, fstVarDir vardir,
|
||||
void VerilatedFst::declQuad(uint32_t code, const char* name, int dtypenum, fstVarDir vardir,
|
||||
fstVarType vartype, bool array, int arraynum, int msb, int lsb) {
|
||||
declare(code, name, dtypenum, vardir, vartype, array, arraynum, msb, lsb);
|
||||
declare(code, name, dtypenum, vardir, vartype, array, arraynum, true, msb, lsb);
|
||||
}
|
||||
void VerilatedFst::declArray(vluint32_t code, const char* name, int dtypenum, fstVarDir vardir,
|
||||
void VerilatedFst::declArray(uint32_t code, const char* name, int dtypenum, fstVarDir vardir,
|
||||
fstVarType vartype, bool array, int arraynum, int msb, int lsb) {
|
||||
declare(code, name, dtypenum, vardir, vartype, array, arraynum, msb, lsb);
|
||||
declare(code, name, dtypenum, vardir, vartype, array, arraynum, true, msb, lsb);
|
||||
}
|
||||
void VerilatedFst::declDouble(vluint32_t code, const char* name, int dtypenum, fstVarDir vardir,
|
||||
void VerilatedFst::declDouble(uint32_t code, const char* name, int dtypenum, fstVarDir vardir,
|
||||
fstVarType vartype, bool array, int arraynum) {
|
||||
declare(code, name, dtypenum, vardir, vartype, array, arraynum, 63, 0);
|
||||
declare(code, name, dtypenum, vardir, vartype, array, arraynum, false, 63, 0);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
// Get/commit trace buffer
|
||||
|
||||
VerilatedFstBuffer* VerilatedFst::getTraceBuffer() { return new VerilatedFstBuffer{*this}; }
|
||||
|
||||
void VerilatedFst::commitTraceBuffer(VerilatedFstBuffer* bufp) {
|
||||
#ifdef VL_TRACE_OFFLOAD
|
||||
if (bufp->m_offloadBufferWritep) {
|
||||
m_offloadBufferWritep = bufp->m_offloadBufferWritep;
|
||||
return; // Buffer will be deleted by the offload thread
|
||||
}
|
||||
#endif
|
||||
delete bufp;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
// VerilatedFstBuffer implementation
|
||||
|
||||
VerilatedFstBuffer::VerilatedFstBuffer(VerilatedFst& owner)
|
||||
: VerilatedTraceBuffer<VerilatedFst, VerilatedFstBuffer>{owner} {}
|
||||
|
||||
//=============================================================================
|
||||
// Trace rendering primitives
|
||||
|
||||
// Note: emit* are only ever called from one place (full* in
|
||||
// verilated_trace_imp.cpp, which is included in this file at the top),
|
||||
// verilated_trace_imp.h, which is included in this file at the top),
|
||||
// so always inline them.
|
||||
|
||||
VL_ATTR_ALWINLINE
|
||||
void VerilatedFst::emitBit(vluint32_t code, CData newval) {
|
||||
void VerilatedFstBuffer::emitBit(uint32_t code, CData newval) {
|
||||
VL_DEBUG_IFDEF(assert(m_symbolp[code]););
|
||||
fstWriterEmitValueChange(m_fst, m_symbolp[code], newval ? "1" : "0");
|
||||
}
|
||||
|
||||
VL_ATTR_ALWINLINE
|
||||
void VerilatedFst::emitCData(vluint32_t code, CData newval, int bits) {
|
||||
void VerilatedFstBuffer::emitCData(uint32_t code, CData newval, int bits) {
|
||||
char buf[VL_BYTESIZE];
|
||||
VL_DEBUG_IFDEF(assert(m_symbolp[code]););
|
||||
cvtCDataToStr(buf, newval << (VL_BYTESIZE - bits));
|
||||
fstWriterEmitValueChange(m_fst, m_symbolp[code], buf);
|
||||
}
|
||||
|
||||
VL_ATTR_ALWINLINE
|
||||
void VerilatedFst::emitSData(vluint32_t code, SData newval, int bits) {
|
||||
void VerilatedFstBuffer::emitSData(uint32_t code, SData newval, int bits) {
|
||||
char buf[VL_SHORTSIZE];
|
||||
VL_DEBUG_IFDEF(assert(m_symbolp[code]););
|
||||
cvtSDataToStr(buf, newval << (VL_SHORTSIZE - bits));
|
||||
fstWriterEmitValueChange(m_fst, m_symbolp[code], buf);
|
||||
}
|
||||
|
||||
VL_ATTR_ALWINLINE
|
||||
void VerilatedFst::emitIData(vluint32_t code, IData newval, int bits) {
|
||||
void VerilatedFstBuffer::emitIData(uint32_t code, IData newval, int bits) {
|
||||
char buf[VL_IDATASIZE];
|
||||
VL_DEBUG_IFDEF(assert(m_symbolp[code]););
|
||||
cvtIDataToStr(buf, newval << (VL_IDATASIZE - bits));
|
||||
fstWriterEmitValueChange(m_fst, m_symbolp[code], buf);
|
||||
}
|
||||
|
||||
VL_ATTR_ALWINLINE
|
||||
void VerilatedFst::emitQData(vluint32_t code, QData newval, int bits) {
|
||||
void VerilatedFstBuffer::emitQData(uint32_t code, QData newval, int bits) {
|
||||
char buf[VL_QUADSIZE];
|
||||
VL_DEBUG_IFDEF(assert(m_symbolp[code]););
|
||||
cvtQDataToStr(buf, newval << (VL_QUADSIZE - bits));
|
||||
fstWriterEmitValueChange(m_fst, m_symbolp[code], buf);
|
||||
}
|
||||
|
||||
VL_ATTR_ALWINLINE
|
||||
void VerilatedFst::emitWData(vluint32_t code, const WData* newvalp, int bits) {
|
||||
void VerilatedFstBuffer::emitWData(uint32_t code, const WData* newvalp, int bits) {
|
||||
int words = VL_WORDS_I(bits);
|
||||
char* wp = m_strbuf;
|
||||
// Convert the most significant word
|
||||
@@ -296,6 +330,6 @@ void VerilatedFst::emitWData(vluint32_t code, const WData* newvalp, int bits) {
|
||||
}
|
||||
|
||||
VL_ATTR_ALWINLINE
|
||||
void VerilatedFst::emitDouble(vluint32_t code, double newval) {
|
||||
void VerilatedFstBuffer::emitDouble(uint32_t code, double newval) {
|
||||
fstWriterEmitValueChange(m_fst, m_symbolp[code], &newval);
|
||||
}
|
||||
|
||||
+78
-41
@@ -3,7 +3,7 @@
|
||||
//
|
||||
// Code available from: https://verilator.org
|
||||
//
|
||||
// Copyright 2001-2021 by Wilson Snyder. This program is free software; you
|
||||
// Copyright 2001-2022 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,21 +31,25 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class VerilatedFstBuffer;
|
||||
|
||||
//=============================================================================
|
||||
// VerilatedFst
|
||||
// Base class to create a Verilator FST dump
|
||||
// This is an internally used class - see VerilatedFstC for what to call from applications
|
||||
|
||||
class VerilatedFst final : public VerilatedTrace<VerilatedFst> {
|
||||
class VerilatedFst final : public VerilatedTrace<VerilatedFst, VerilatedFstBuffer> {
|
||||
public:
|
||||
using Super = VerilatedTrace<VerilatedFst, VerilatedFstBuffer>;
|
||||
|
||||
private:
|
||||
// Give the superclass access to private bits (to avoid virtual functions)
|
||||
friend class VerilatedTrace<VerilatedFst>;
|
||||
friend Buffer; // Give the buffer access to the private bits
|
||||
|
||||
//=========================================================================
|
||||
// FST specific internals
|
||||
|
||||
void* m_fst;
|
||||
std::map<vluint32_t, fstHandle> m_code2symbol;
|
||||
std::map<uint32_t, fstHandle> m_code2symbol;
|
||||
std::map<int, fstEnumHandle> m_local2fstdtype;
|
||||
std::list<std::string> m_curScope;
|
||||
fstHandle* m_symbolp = nullptr; // same as m_code2symbol, but as an array
|
||||
@@ -53,38 +57,33 @@ private:
|
||||
|
||||
// CONSTRUCTORS
|
||||
VL_UNCOPYABLE(VerilatedFst);
|
||||
void declare(vluint32_t code, const char* name, int dtypenum, fstVarDir vardir,
|
||||
fstVarType vartype, bool array, int arraynum, int msb, int lsb);
|
||||
void declare(uint32_t code, const char* name, int dtypenum, fstVarDir vardir,
|
||||
fstVarType vartype, bool array, int arraynum, bool bussed, int msb, int lsb);
|
||||
|
||||
protected:
|
||||
//=========================================================================
|
||||
// Implementation of VerilatedTrace interface
|
||||
|
||||
// Implementations of protected virtual methods for VerilatedTrace
|
||||
virtual void emitTimeChange(vluint64_t timeui) override;
|
||||
// Called when the trace moves forward to a new time point
|
||||
virtual void emitTimeChange(uint64_t timeui) override;
|
||||
|
||||
// Hooks called from VerilatedTrace
|
||||
virtual bool preFullDump() override { return isOpen(); }
|
||||
virtual bool preChangeDump() override { return isOpen(); }
|
||||
|
||||
// Implementations of duck-typed methods for VerilatedTrace. These are
|
||||
// called from only one place (namely full*) so always inline them.
|
||||
inline void emitBit(vluint32_t code, CData newval);
|
||||
inline void emitCData(vluint32_t code, CData newval, int bits);
|
||||
inline void emitSData(vluint32_t code, SData newval, int bits);
|
||||
inline void emitIData(vluint32_t code, IData newval, int bits);
|
||||
inline void emitQData(vluint32_t code, QData newval, int bits);
|
||||
inline void emitWData(vluint32_t code, const WData* newvalp, int bits);
|
||||
inline void emitDouble(vluint32_t code, double newval);
|
||||
// Trace buffer management
|
||||
virtual VerilatedFstBuffer* getTraceBuffer() override;
|
||||
virtual void commitTraceBuffer(VerilatedFstBuffer*) override;
|
||||
|
||||
public:
|
||||
//=========================================================================
|
||||
// External interface to client code
|
||||
// (All must be threadsafe)
|
||||
|
||||
// CONSTRUCTOR
|
||||
explicit VerilatedFst(void* fst = nullptr);
|
||||
~VerilatedFst();
|
||||
|
||||
// METHODS - All must be thread safe
|
||||
// Open the file; call isOpen() to see if errors
|
||||
void open(const char* filename) VL_MT_SAFE_EXCLUDES(m_mutex);
|
||||
// Close the file
|
||||
@@ -97,32 +96,65 @@ public:
|
||||
//=========================================================================
|
||||
// Internal interface to Verilator generated code
|
||||
|
||||
// Inside dumping routines, declare a data type
|
||||
void declDTypeEnum(int dtypenum, const char* name, vluint32_t elements,
|
||||
unsigned int minValbits, const char** itemNamesp, const char** itemValuesp);
|
||||
|
||||
// Inside dumping routines, declare a signal
|
||||
void declBit(vluint32_t code, const char* name, int dtypenum, fstVarDir vardir,
|
||||
void declBit(uint32_t code, const char* name, int dtypenum, fstVarDir vardir,
|
||||
fstVarType vartype, bool array, int arraynum);
|
||||
void declBus(vluint32_t code, const char* name, int dtypenum, fstVarDir vardir,
|
||||
void declBus(uint32_t code, const char* name, int dtypenum, fstVarDir vardir,
|
||||
fstVarType vartype, bool array, int arraynum, int msb, int lsb);
|
||||
void declQuad(vluint32_t code, const char* name, int dtypenum, fstVarDir vardir,
|
||||
void declQuad(uint32_t code, const char* name, int dtypenum, fstVarDir vardir,
|
||||
fstVarType vartype, bool array, int arraynum, int msb, int lsb);
|
||||
void declArray(vluint32_t code, const char* name, int dtypenum, fstVarDir vardir,
|
||||
void declArray(uint32_t code, const char* name, int dtypenum, fstVarDir vardir,
|
||||
fstVarType vartype, bool array, int arraynum, int msb, int lsb);
|
||||
void declDouble(vluint32_t code, const char* name, int dtypenum, fstVarDir vardir,
|
||||
void declDouble(uint32_t code, const char* name, int dtypenum, fstVarDir vardir,
|
||||
fstVarType vartype, bool array, int arraynum);
|
||||
|
||||
void declDTypeEnum(int dtypenum, const char* name, uint32_t elements, unsigned int minValbits,
|
||||
const char** itemNamesp, const char** itemValuesp);
|
||||
};
|
||||
|
||||
#ifndef DOXYGEN
|
||||
// Declare specialization here as it's used in VerilatedFstC just below
|
||||
template <> void VerilatedTrace<VerilatedFst>::dump(vluint64_t timeui);
|
||||
template <> void VerilatedTrace<VerilatedFst>::set_time_unit(const char* unitp);
|
||||
template <> void VerilatedTrace<VerilatedFst>::set_time_unit(const std::string& unit);
|
||||
template <> void VerilatedTrace<VerilatedFst>::set_time_resolution(const char* unitp);
|
||||
template <> void VerilatedTrace<VerilatedFst>::set_time_resolution(const std::string& unit);
|
||||
template <> void VerilatedFst::Super::dump(uint64_t time);
|
||||
template <> void VerilatedFst::Super::set_time_unit(const char* unitp);
|
||||
template <> void VerilatedFst::Super::set_time_unit(const std::string& unit);
|
||||
template <> void VerilatedFst::Super::set_time_resolution(const char* unitp);
|
||||
template <> void VerilatedFst::Super::set_time_resolution(const std::string& unit);
|
||||
template <> void VerilatedFst::Super::dumpvars(int level, const std::string& hier);
|
||||
#endif
|
||||
|
||||
//=============================================================================
|
||||
// VerilatedFstBuffer
|
||||
|
||||
class VerilatedFstBuffer final : public VerilatedTraceBuffer<VerilatedFst, VerilatedFstBuffer> {
|
||||
// Give the trace file access to the private bits
|
||||
friend VerilatedFst;
|
||||
friend VerilatedFst::Super;
|
||||
|
||||
// The FST file handle
|
||||
void* const m_fst = m_owner.m_fst;
|
||||
// code to fstHande map, as an array
|
||||
const fstHandle* const m_symbolp = m_owner.m_symbolp;
|
||||
// String buffer long enough to hold maxBits() chars
|
||||
char* const m_strbuf = m_owner.m_strbuf;
|
||||
|
||||
public:
|
||||
// CONSTRUCTOR
|
||||
explicit VerilatedFstBuffer(VerilatedFst& owner);
|
||||
~VerilatedFstBuffer() = default;
|
||||
|
||||
//=========================================================================
|
||||
// Implementation of VerilatedTraceBuffer interface
|
||||
|
||||
// Implementations of duck-typed methods for VerilatedTraceBuffer. These are
|
||||
// called from only one place (the full* methods), so always inline them.
|
||||
VL_ATTR_ALWINLINE inline void emitBit(uint32_t code, CData newval);
|
||||
VL_ATTR_ALWINLINE inline void emitCData(uint32_t code, CData newval, int bits);
|
||||
VL_ATTR_ALWINLINE inline void emitSData(uint32_t code, SData newval, int bits);
|
||||
VL_ATTR_ALWINLINE inline void emitIData(uint32_t code, IData newval, int bits);
|
||||
VL_ATTR_ALWINLINE inline void emitQData(uint32_t code, QData newval, int bits);
|
||||
VL_ATTR_ALWINLINE inline void emitWData(uint32_t code, const WData* newvalp, int bits);
|
||||
VL_ATTR_ALWINLINE inline void emitDouble(uint32_t code, double newval);
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
// VerilatedFstC
|
||||
/// Create a FST dump file in C standalone (no SystemC) simulations.
|
||||
@@ -139,7 +171,7 @@ public:
|
||||
explicit VerilatedFstC(void* filep = nullptr)
|
||||
: m_sptrace{filep} {}
|
||||
/// Destruct, flush, and close the dump
|
||||
~VerilatedFstC() { close(); }
|
||||
virtual ~VerilatedFstC() { close(); }
|
||||
|
||||
// METHODS - User called
|
||||
|
||||
@@ -154,12 +186,12 @@ public:
|
||||
/// Write one cycle of dump data
|
||||
/// Call with the current context's time just after eval'ed,
|
||||
/// e.g. ->dump(contextp->time())
|
||||
void dump(vluint64_t timeui) { m_sptrace.dump(timeui); }
|
||||
void dump(uint64_t timeui) { m_sptrace.dump(timeui); }
|
||||
/// Write one cycle of dump data - backward compatible and to reduce
|
||||
/// conversion warnings. It's better to use a vluint64_t time instead.
|
||||
void dump(double timestamp) { dump(static_cast<vluint64_t>(timestamp)); }
|
||||
void dump(vluint32_t timestamp) { dump(static_cast<vluint64_t>(timestamp)); }
|
||||
void dump(int timestamp) { dump(static_cast<vluint64_t>(timestamp)); }
|
||||
/// conversion warnings. It's better to use a uint64_t time instead.
|
||||
void dump(double timestamp) { dump(static_cast<uint64_t>(timestamp)); }
|
||||
void dump(uint32_t timestamp) { dump(static_cast<uint64_t>(timestamp)); }
|
||||
void dump(int timestamp) { dump(static_cast<uint64_t>(timestamp)); }
|
||||
|
||||
// METHODS - Internal/backward compatible
|
||||
// \protectedsection
|
||||
@@ -178,9 +210,14 @@ public:
|
||||
void set_time_resolution(const std::string& unit) VL_MT_SAFE {
|
||||
m_sptrace.set_time_resolution(unit);
|
||||
}
|
||||
// Set variables to dump, using $dumpvars format
|
||||
// If level = 0, dump everything and hier is then ignored
|
||||
void dumpvars(int level, const std::string& hier) VL_MT_SAFE {
|
||||
m_sptrace.dumpvars(level, hier);
|
||||
}
|
||||
|
||||
// Internal class access
|
||||
inline VerilatedFst* spTrace() { return &m_sptrace; };
|
||||
inline VerilatedFst* spTrace() { return &m_sptrace; }
|
||||
};
|
||||
|
||||
#endif // guard
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
//
|
||||
// THIS MODULE IS PUBLICLY LICENSED
|
||||
//
|
||||
// Copyright 2001-2021 by Wilson Snyder. This program is free software; you
|
||||
// Copyright 2001-2022 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.
|
||||
@@ -27,6 +27,17 @@
|
||||
//======================================================================
|
||||
//======================================================================
|
||||
|
||||
void VerilatedFstSc::open(const char* filename) {
|
||||
if (!sc_core::sc_get_curr_simcontext()->elaboration_done()) {
|
||||
vl_fatal(__FILE__, __LINE__, "VerilatedFstSc",
|
||||
("%Error: VerilatedFstSc::open(\"" + std::string(filename)
|
||||
+ "\") is called before sc_core::sc_start(). "
|
||||
"Run sc_core::sc_start(sc_core::SC_ZERO_TIME) before opening a wave file.")
|
||||
.c_str());
|
||||
}
|
||||
VerilatedFstC::open(filename);
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// SystemC 2.1.v1
|
||||
// cppcheck-suppress unusedFunction
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//=============================================================================
|
||||
//
|
||||
// Copyright 2001-2021 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2001-2022 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,6 +26,8 @@
|
||||
#include "verilated_sc.h"
|
||||
#include "verilated_fst_c.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
//=============================================================================
|
||||
// VerilatedFstSc
|
||||
///
|
||||
@@ -57,6 +59,9 @@ public:
|
||||
if (!delta_cycle) { this->dump(sc_time_stamp().to_double()); }
|
||||
}
|
||||
|
||||
// Override VerilatedFstC. Must be called after starting simulation.
|
||||
virtual void open(const char* filename) /*override*/ VL_MT_SAFE;
|
||||
|
||||
private:
|
||||
/// Fake outs for linker
|
||||
|
||||
|
||||
+206
-221
File diff suppressed because it is too large
Load Diff
@@ -3,7 +3,7 @@
|
||||
//
|
||||
// Code available from: https://verilator.org
|
||||
//
|
||||
// Copyright 2010-2021 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2010-2022 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
-16
@@ -3,7 +3,7 @@
|
||||
//
|
||||
// Code available from: https://verilator.org
|
||||
//
|
||||
// Copyright 2009-2021 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2009-2022 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.
|
||||
@@ -32,10 +32,15 @@
|
||||
#include "verilated.h"
|
||||
#include "verilated_syms.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <deque>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
#include <limits>
|
||||
#include <map>
|
||||
#include <numeric>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#ifdef VL_THREADED
|
||||
# include <functional>
|
||||
# include <queue>
|
||||
@@ -60,7 +65,7 @@ public:
|
||||
|
||||
private:
|
||||
// MEMBERS
|
||||
vluint32_t m_mtaskId; // MTask that did enqueue
|
||||
uint32_t m_mtaskId; // MTask that did enqueue
|
||||
std::function<void()> m_cb; // Lambda to execute when message received
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
@@ -73,7 +78,7 @@ public:
|
||||
VerilatedMsg& operator=(const VerilatedMsg&) = default;
|
||||
VerilatedMsg& operator=(VerilatedMsg&&) = default;
|
||||
// METHODS
|
||||
vluint32_t mtaskId() const { return m_mtaskId; }
|
||||
uint32_t mtaskId() const { return m_mtaskId; }
|
||||
// Execute the lambda function
|
||||
void run() const { m_cb(); }
|
||||
};
|
||||
@@ -84,9 +89,9 @@ public:
|
||||
class VerilatedEvalMsgQueue final {
|
||||
using VerilatedThreadQueue = std::multiset<VerilatedMsg, VerilatedMsg::Cmp>;
|
||||
|
||||
std::atomic<vluint64_t> m_depth; // Current depth of queue (see comments below)
|
||||
std::atomic<uint64_t> m_depth; // Current depth of queue (see comments below)
|
||||
|
||||
VerilatedMutex m_mutex; // Mutex protecting queue
|
||||
mutable VerilatedMutex m_mutex; // Mutex protecting queue
|
||||
VerilatedThreadQueue m_queue VL_GUARDED_BY(m_mutex); // Message queue
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
@@ -240,8 +245,8 @@ public: // But only for verilated*.cpp
|
||||
// METHODS - extending into VerilatedContext, call via impp()->
|
||||
|
||||
// Random seed handling
|
||||
vluint64_t randSeedDefault64() const VL_MT_SAFE;
|
||||
static vluint32_t randSeedEpoch() VL_MT_SAFE { return s().s_randSeedEpoch; }
|
||||
uint64_t randSeedDefault64() const VL_MT_SAFE;
|
||||
static uint32_t randSeedEpoch() VL_MT_SAFE { return s().s_randSeedEpoch; }
|
||||
|
||||
// METHODS - timeformat
|
||||
int timeFormatUnits() const VL_MT_SAFE {
|
||||
@@ -277,7 +282,7 @@ public: // But only for verilated*.cpp
|
||||
IData fdNewMcd(const char* filenamep) VL_MT_SAFE_EXCLUDES(m_fdMutex) {
|
||||
const VerilatedLockGuard lock{m_fdMutex};
|
||||
if (m_fdFreeMct.empty()) return 0;
|
||||
IData idx = m_fdFreeMct.back();
|
||||
const IData idx = m_fdFreeMct.back();
|
||||
m_fdFreeMct.pop_back();
|
||||
m_fdps[idx] = std::fopen(filenamep, "w");
|
||||
if (VL_UNLIKELY(!m_fdps[idx])) return 0;
|
||||
@@ -299,7 +304,7 @@ public: // But only for verilated*.cpp
|
||||
m_fdFree[i] = id;
|
||||
}
|
||||
}
|
||||
IData idx = m_fdFree.back();
|
||||
const IData idx = m_fdFree.back();
|
||||
m_fdFree.pop_back();
|
||||
m_fdps[idx] = fp;
|
||||
return (idx | (1UL << 31)); // bit 31 indicates not MCD
|
||||
@@ -312,14 +317,14 @@ public: // But only for verilated*.cpp
|
||||
IData fdSeek(IData fdi, IData offset, IData origin) VL_MT_SAFE_EXCLUDES(m_fdMutex) {
|
||||
const VerilatedLockGuard lock{m_fdMutex};
|
||||
const VerilatedFpList fdlist = fdToFpList(fdi);
|
||||
if (VL_UNLIKELY(fdlist.size() != 1)) return 0;
|
||||
if (VL_UNLIKELY(fdlist.size() != 1)) return ~0U; // -1
|
||||
return static_cast<IData>(
|
||||
std::fseek(*fdlist.begin(), static_cast<long>(offset), static_cast<int>(origin)));
|
||||
}
|
||||
IData fdTell(IData fdi) VL_MT_SAFE_EXCLUDES(m_fdMutex) {
|
||||
const VerilatedLockGuard lock{m_fdMutex};
|
||||
const VerilatedFpList fdlist = fdToFpList(fdi);
|
||||
if (VL_UNLIKELY(fdlist.size() != 1)) return 0;
|
||||
if (VL_UNLIKELY(fdlist.size() != 1)) return ~0U; // -1
|
||||
return static_cast<IData>(std::ftell(*fdlist.begin()));
|
||||
}
|
||||
void fdWrite(IData fdi, const std::string& output) VL_MT_SAFE_EXCLUDES(m_fdMutex) {
|
||||
@@ -334,7 +339,7 @@ public: // But only for verilated*.cpp
|
||||
const VerilatedLockGuard lock{m_fdMutex};
|
||||
if (VL_BITISSET_I(fdi, 31)) {
|
||||
// Non-MCD case
|
||||
IData idx = VL_MASK_I(31) & fdi;
|
||||
const IData idx = VL_MASK_I(31) & fdi;
|
||||
if (VL_UNLIKELY(idx >= m_fdps.size())) return;
|
||||
if (VL_UNLIKELY(idx <= 2)) return; // stdout/stdin/stderr
|
||||
if (VL_UNLIKELY(!m_fdps[idx])) return; // Already free
|
||||
@@ -390,7 +395,11 @@ protected:
|
||||
// METHODS - protected
|
||||
void commandArgsAddGuts(int argc, const char** argv);
|
||||
void commandArgVl(const std::string& arg);
|
||||
bool commandArgVlValue(const std::string& arg, const std::string& prefix, std::string& valuer);
|
||||
bool commandArgVlString(const std::string& arg, const std::string& prefix,
|
||||
std::string& valuer);
|
||||
bool commandArgVlUint64(const std::string& arg, const std::string& prefix, uint64_t& valuer,
|
||||
uint64_t min = std::numeric_limits<uint64_t>::min(),
|
||||
uint64_t max = std::numeric_limits<uint64_t>::max());
|
||||
void commandArgDump() const VL_MT_SAFE_EXCLUDES(m_argMutex);
|
||||
};
|
||||
|
||||
@@ -480,7 +489,7 @@ public:
|
||||
public: // But only for verilated.cpp
|
||||
// Symbol table destruction cleans up the entries for each scope.
|
||||
static void userEraseScope(const VerilatedScope* scopep) VL_MT_SAFE {
|
||||
// Slow ok - called once/scope on destruction, so we simply iterate.
|
||||
// Slow ok - called once/scope on destruction, so we only iterate.
|
||||
const VerilatedLockGuard lock{s().m_userMapMutex};
|
||||
for (auto it = s().m_userMap.begin(); it != s().m_userMap.end();) {
|
||||
if (it->first.first == scopep) {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
//
|
||||
// Code available from: https://verilator.org
|
||||
//
|
||||
// Copyright 2003-2021 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2022 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.
|
||||
|
||||
@@ -0,0 +1,191 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//=============================================================================
|
||||
//
|
||||
// Code available from: https://verilator.org
|
||||
//
|
||||
// Copyright 2012-2022 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
//
|
||||
//=============================================================================
|
||||
///
|
||||
/// \file
|
||||
/// \brief Verilated run-time profiling implementation code
|
||||
///
|
||||
//=============================================================================
|
||||
|
||||
#include "verilatedos.h"
|
||||
#include "verilated_profiler.h"
|
||||
|
||||
#if VL_THREADED
|
||||
#include "verilated_threads.h"
|
||||
#endif
|
||||
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
|
||||
//=============================================================================
|
||||
// Globals
|
||||
|
||||
// Internal note: Globals may multi-construct, see verilated.cpp top.
|
||||
|
||||
VL_THREAD_LOCAL VlExecutionProfiler::ExecutionTrace VlExecutionProfiler::t_trace;
|
||||
|
||||
constexpr const char* const VlExecutionRecord::s_ascii[];
|
||||
|
||||
//=============================================================================
|
||||
// VlPgoProfiler implementation
|
||||
|
||||
uint16_t VlExecutionRecord::getcpu() {
|
||||
#if defined(__linux)
|
||||
return sched_getcpu(); // TODO: this is a system call. Not exactly cheap.
|
||||
#elif defined(__APPLE__) && !defined(__arm64__)
|
||||
uint32_t info[4];
|
||||
__cpuid_count(1, 0, info[0], info[1], info[2], info[3]);
|
||||
// info[1] is EBX, bits 24-31 are APIC ID
|
||||
if ((info[3] & (1 << 9)) == 0) {
|
||||
return -1; // no APIC on chip
|
||||
} else {
|
||||
return (unsigned)info[1] >> 24;
|
||||
}
|
||||
#elif defined(_WIN32)
|
||||
return GetCurrentProcessorNumber();
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
// VlExecutionProfiler implementation
|
||||
|
||||
template <size_t N> static size_t roundUptoMultipleOf(size_t value) {
|
||||
static_assert((N & (N - 1)) == 0, "'N' must be a power of 2");
|
||||
size_t mask = N - 1;
|
||||
return (value + mask) & ~mask;
|
||||
}
|
||||
|
||||
VlExecutionProfiler::VlExecutionProfiler() {
|
||||
// Setup profiling on main thread
|
||||
setupThread(0);
|
||||
}
|
||||
|
||||
void VlExecutionProfiler::configure(const VerilatedContext& context) {
|
||||
if (VL_UNLIKELY(m_enabled)) {
|
||||
--m_windowCount;
|
||||
if (VL_UNLIKELY(m_windowCount == context.profExecWindow())) {
|
||||
VL_DEBUG_IF(VL_DBG_MSGF("+ profile start collection\n"););
|
||||
clear(); // Clear the profile after the cache warm-up cycles.
|
||||
m_tickBegin = VL_CPU_TICK();
|
||||
} else if (VL_UNLIKELY(m_windowCount == 0)) {
|
||||
const uint64_t tickEnd = VL_CPU_TICK();
|
||||
VL_DEBUG_IF(VL_DBG_MSGF("+ profile end\n"););
|
||||
const std::string& fileName = context.profExecFilename();
|
||||
dump(fileName.c_str(), tickEnd);
|
||||
m_enabled = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const uint64_t startReq = context.profExecStart() + 1; // + 1, so we can start at time 0
|
||||
|
||||
if (VL_UNLIKELY(m_lastStartReq < startReq && VL_TIME_Q() >= context.profExecStart())) {
|
||||
VL_DEBUG_IF(VL_DBG_MSGF("+ profile start warmup\n"););
|
||||
VL_DEBUG_IF(assert(m_windowCount == 0););
|
||||
m_enabled = true;
|
||||
m_windowCount = context.profExecWindow() * 2;
|
||||
m_lastStartReq = startReq;
|
||||
}
|
||||
}
|
||||
|
||||
void VlExecutionProfiler::setupThread(uint32_t threadId) {
|
||||
// Reserve some space in the thread-local profiling buffer, in order to try to avoid malloc
|
||||
// while profiling.
|
||||
t_trace.reserve(RESERVED_TRACE_CAPACITY);
|
||||
// Register thread-local buffer in list of all buffers
|
||||
{
|
||||
const VerilatedLockGuard lock{m_mutex};
|
||||
bool exists = !m_traceps.emplace(threadId, &t_trace).second;
|
||||
assert(!exists);
|
||||
}
|
||||
}
|
||||
|
||||
void VlExecutionProfiler::clear() VL_MT_SAFE_EXCLUDES(m_mutex) {
|
||||
const VerilatedLockGuard lock{m_mutex};
|
||||
for (const auto& pair : m_traceps) {
|
||||
ExecutionTrace* const tracep = pair.second;
|
||||
const size_t reserve = roundUptoMultipleOf<RESERVED_TRACE_CAPACITY>(tracep->size());
|
||||
tracep->clear();
|
||||
tracep->reserve(reserve);
|
||||
}
|
||||
}
|
||||
|
||||
void VlExecutionProfiler::dump(const char* filenamep, uint64_t tickEnd)
|
||||
VL_MT_SAFE_EXCLUDES(m_mutex) {
|
||||
const VerilatedLockGuard lock{m_mutex};
|
||||
VL_DEBUG_IF(VL_DBG_MSGF("+prof+exec writing to '%s'\n", filenamep););
|
||||
|
||||
FILE* const fp = std::fopen(filenamep, "w");
|
||||
if (VL_UNLIKELY(!fp)) { VL_FATAL_MT(filenamep, 0, "", "+prof+exec+file file not writable"); }
|
||||
|
||||
// TODO Perhaps merge with verilated_coverage output format, so can
|
||||
// have a common merging and reporting tool, etc.
|
||||
fprintf(fp, "VLPROFVERSION 2.0 # Verilator execution profile version 2.0\n");
|
||||
fprintf(fp, "VLPROF arg +verilator+prof+exec+start+%" PRIu64 "\n",
|
||||
Verilated::threadContextp()->profExecStart());
|
||||
fprintf(fp, "VLPROF arg +verilator+prof+exec+window+%u\n",
|
||||
Verilated::threadContextp()->profExecWindow());
|
||||
const unsigned threads = static_cast<unsigned>(m_traceps.size());
|
||||
fprintf(fp, "VLPROF stat threads %u\n", threads);
|
||||
#ifdef VL_THREADED
|
||||
fprintf(fp, "VLPROF stat yields %" PRIu64 "\n", VlMTaskVertex::yields());
|
||||
#endif
|
||||
|
||||
// Copy /proc/cpuinfo into this output so verilator_gantt can be run on
|
||||
// a different machine
|
||||
{
|
||||
const std::unique_ptr<std::ifstream> ifp{new std::ifstream("/proc/cpuinfo")};
|
||||
if (!ifp->fail()) {
|
||||
std::string line;
|
||||
while (std::getline(*ifp, line)) { fprintf(fp, "VLPROFPROC %s\n", line.c_str()); }
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& pair : m_traceps) {
|
||||
const uint32_t threadId = pair.first;
|
||||
ExecutionTrace* const tracep = pair.second;
|
||||
fprintf(fp, "VLPROFTHREAD %" PRIu32 "\n", threadId);
|
||||
|
||||
for (const VlExecutionRecord& er : *tracep) {
|
||||
const char* const name = VlExecutionRecord::s_ascii[static_cast<uint8_t>(er.m_type)];
|
||||
const uint64_t time = er.m_tick - m_tickBegin;
|
||||
fprintf(fp, "VLPROFEXEC %s %" PRIu64, name, time);
|
||||
|
||||
switch (er.m_type) {
|
||||
case VlExecutionRecord::Type::EVAL_BEGIN:
|
||||
case VlExecutionRecord::Type::EVAL_END:
|
||||
case VlExecutionRecord::Type::EVAL_LOOP_BEGIN:
|
||||
case VlExecutionRecord::Type::EVAL_LOOP_END:
|
||||
// No payload
|
||||
fprintf(fp, "\n");
|
||||
break;
|
||||
case VlExecutionRecord::Type::MTASK_BEGIN: {
|
||||
const auto& payload = er.m_payload.mtaskBegin;
|
||||
fprintf(fp, " id %u predictStart %u cpu %u\n", payload.m_id,
|
||||
payload.m_predictStart, payload.m_cpu);
|
||||
break;
|
||||
}
|
||||
case VlExecutionRecord::Type::MTASK_END: {
|
||||
const auto& payload = er.m_payload.mtaskEnd;
|
||||
fprintf(fp, " id %u predictCost %u\n", payload.m_id, payload.m_predictCost);
|
||||
break;
|
||||
}
|
||||
default: abort(); // LCOV_EXCL_LINE
|
||||
}
|
||||
}
|
||||
}
|
||||
fprintf(fp, "VLPROF stat ticks %" PRIu64 "\n", tickEnd - m_tickBegin);
|
||||
|
||||
std::fclose(fp);
|
||||
}
|
||||
+188
-45
@@ -3,7 +3,7 @@
|
||||
//
|
||||
// Code available from: https://verilator.org
|
||||
//
|
||||
// Copyright 2012-2021 by Wilson Snyder. This program is free software; you
|
||||
// Copyright 2012-2022 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.
|
||||
@@ -12,7 +12,7 @@
|
||||
//=============================================================================
|
||||
///
|
||||
/// \file
|
||||
/// \brief Verilated general profiling header
|
||||
/// \brief Verilated run-time profiling header
|
||||
///
|
||||
/// This file is not part of the Verilated public-facing API.
|
||||
/// It is only for internal use by Verilated library routines.
|
||||
@@ -23,55 +23,204 @@
|
||||
#define VERILATOR_VERILATED_PROFILER_H_
|
||||
|
||||
#include "verilatedos.h"
|
||||
#include "verilated.h" // for VerilatedMutex and clang annotations
|
||||
|
||||
// Profile record, private class used only by this header
|
||||
class VerilatedProfilerRec final {
|
||||
std::string m_name; // Hashed name of mtask/etc
|
||||
size_t m_counterNumber = 0; // Which counter has data
|
||||
#ifndef VL_PROFILER
|
||||
#error "verilated_profiler.h/cpp expects VL_PROFILER (from --prof-{exec, pgo}"
|
||||
#endif
|
||||
|
||||
#include "verilated.h"
|
||||
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
class VlExecutionProfiler;
|
||||
|
||||
//=============================================================================
|
||||
// Macros to simplify generated code
|
||||
|
||||
#define VL_EXEC_TRACE_ADD_RECORD(vlSymsp) \
|
||||
if (VL_UNLIKELY((vlSymsp)->__Vm_executionProfiler.enabled())) \
|
||||
(vlSymsp)->__Vm_executionProfiler.addRecord()
|
||||
|
||||
//=============================================================================
|
||||
// Return high-precision counter for profiling, or 0x0 if not available
|
||||
VL_ATTR_ALWINLINE
|
||||
inline QData VL_CPU_TICK() {
|
||||
uint64_t val;
|
||||
VL_GET_CPU_TICK(val);
|
||||
return val;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
// Private class used by VlExecutionProfiler
|
||||
|
||||
#define _VL_FOREACH_APPLY(macro, arg) macro(arg, #arg)
|
||||
|
||||
// clang-format off
|
||||
#define FOREACH_VlExecutionRecord_TYPE(macro) \
|
||||
_VL_FOREACH_APPLY(macro, EVAL_BEGIN) \
|
||||
_VL_FOREACH_APPLY(macro, EVAL_END) \
|
||||
_VL_FOREACH_APPLY(macro, EVAL_LOOP_BEGIN) \
|
||||
_VL_FOREACH_APPLY(macro, EVAL_LOOP_END) \
|
||||
_VL_FOREACH_APPLY(macro, MTASK_BEGIN) \
|
||||
_VL_FOREACH_APPLY(macro, MTASK_END)
|
||||
// clang-format on
|
||||
|
||||
class VlExecutionRecord final {
|
||||
friend class VlExecutionProfiler;
|
||||
|
||||
// TYPES
|
||||
enum class Type : uint8_t {
|
||||
#define VL_FOREACH_MACRO(id, name) id,
|
||||
FOREACH_VlExecutionRecord_TYPE(VL_FOREACH_MACRO)
|
||||
#undef VL_FOREACH_MACRO
|
||||
};
|
||||
|
||||
static constexpr const char* const s_ascii[] = {
|
||||
#define VL_FOREACH_MACRO(id, name) name,
|
||||
FOREACH_VlExecutionRecord_TYPE(VL_FOREACH_MACRO)
|
||||
#undef VL_FOREACH_MACRO
|
||||
};
|
||||
|
||||
union Payload {
|
||||
struct {
|
||||
uint32_t m_id; // MTask id
|
||||
uint32_t m_predictStart; // Time scheduler predicted would start
|
||||
uint32_t m_cpu; // Executing CPU id
|
||||
} mtaskBegin;
|
||||
struct {
|
||||
uint32_t m_id; // MTask id
|
||||
uint32_t m_predictCost; // How long scheduler predicted would take
|
||||
} mtaskEnd;
|
||||
};
|
||||
|
||||
// STATE
|
||||
// Layout below allows efficient packing.
|
||||
const uint64_t m_tick = VL_CPU_TICK(); // Tick at construction
|
||||
Payload m_payload; // The record payload
|
||||
Type m_type; // The record type
|
||||
static_assert(alignof(uint64_t) >= alignof(Payload), "Padding not allowed");
|
||||
static_assert(alignof(Payload) >= alignof(Type), "Padding not allowed");
|
||||
|
||||
static uint16_t getcpu(); // Return currently executing CPU id
|
||||
|
||||
public:
|
||||
// CONSTRUCTOR
|
||||
VlExecutionRecord() = default;
|
||||
|
||||
// METHODS
|
||||
VerilatedProfilerRec(size_t counterNumber, const std::string& name)
|
||||
: m_name{name}
|
||||
, m_counterNumber{counterNumber} {}
|
||||
VerilatedProfilerRec() = default;
|
||||
size_t counterNumber() const { return m_counterNumber; }
|
||||
std::string name() const { return m_name; }
|
||||
void evalBegin() { m_type = Type::EVAL_BEGIN; }
|
||||
void evalEnd() { m_type = Type::EVAL_END; }
|
||||
void evalLoopBegin() { m_type = Type::EVAL_LOOP_BEGIN; }
|
||||
void evalLoopEnd() { m_type = Type::EVAL_LOOP_END; }
|
||||
void mtaskBegin(uint32_t id, uint32_t predictStart) {
|
||||
m_payload.mtaskBegin.m_id = id;
|
||||
m_payload.mtaskBegin.m_predictStart = predictStart;
|
||||
m_payload.mtaskBegin.m_cpu = getcpu();
|
||||
m_type = Type::MTASK_BEGIN;
|
||||
}
|
||||
void mtaskEnd(uint32_t id, uint32_t predictCost) {
|
||||
m_payload.mtaskEnd.m_id = id;
|
||||
m_payload.mtaskEnd.m_predictCost = predictCost;
|
||||
m_type = Type::MTASK_END;
|
||||
}
|
||||
};
|
||||
|
||||
// Create some number of bucketed profilers
|
||||
template <std::size_t T_Entries> class VerilatedProfiler final {
|
||||
// Counters are stored packed, all together, versus in VerilatedProfilerRec to
|
||||
// reduce cache effects
|
||||
std::array<vluint64_t, T_Entries> m_counters{}; // Time spent on this record
|
||||
std::deque<VerilatedProfilerRec> m_records; // Record information
|
||||
static_assert(std::is_trivially_destructible<VlExecutionRecord>::value,
|
||||
"VlExecutionRecord should be trivially destructible for fast buffer clearing");
|
||||
|
||||
//=============================================================================
|
||||
// VlExecutionProfiler is for collecting profiling data about model execution
|
||||
|
||||
class VlExecutionProfiler final {
|
||||
// CONSTANTS
|
||||
|
||||
// In order to try to avoid dynamic memory allocations during the actual profiling phase,
|
||||
// trace buffers are pre-allocated to be able to hold [a multiple] of this many records.
|
||||
static constexpr size_t RESERVED_TRACE_CAPACITY = 4096;
|
||||
|
||||
// TYPES
|
||||
|
||||
// Execution traces are recorded into thread local vectors. We can append records of profiling
|
||||
// events to this vector with very low overhead, and then dump them out later. This prevents
|
||||
// the overhead of printf/malloc/IO from corrupting the profiling data. It's super cheap to
|
||||
// append a VlProfileRec struct on the end of a pre-allocated vector; this is the only cost we
|
||||
// pay in real-time during a profiling cycle. Internal note: Globals may multi-construct, see
|
||||
// verilated.cpp top.
|
||||
using ExecutionTrace = std::vector<VlExecutionRecord>;
|
||||
|
||||
// STATE
|
||||
static VL_THREAD_LOCAL ExecutionTrace t_trace; // thread-local trace buffers
|
||||
mutable VerilatedMutex m_mutex;
|
||||
// Map from thread id to &t_trace of given thread
|
||||
std::map<uint32_t, ExecutionTrace*> m_traceps VL_GUARDED_BY(m_mutex);
|
||||
|
||||
bool m_enabled = false; // Is profiling currently enabled
|
||||
|
||||
uint64_t m_tickBegin = 0; // Sample time (rdtsc() on x86) at beginning of collection
|
||||
uint64_t m_lastStartReq = 0; // Last requested profiling start (in simulation time)
|
||||
uint32_t m_windowCount = 0; // Track our position in the cache warmup and profile window
|
||||
|
||||
public:
|
||||
// CONSTRUCTOR
|
||||
VlExecutionProfiler();
|
||||
|
||||
// METHODS
|
||||
|
||||
// Is profiling enabled
|
||||
inline bool enabled() const { return m_enabled; }
|
||||
// Append a trace record to the trace buffer of the current thread
|
||||
inline VlExecutionRecord& addRecord() {
|
||||
t_trace.emplace_back();
|
||||
return t_trace.back();
|
||||
}
|
||||
// Configure profiler (called in beginning of 'eval')
|
||||
void configure(const VerilatedContext&);
|
||||
// Setup profiling on a particular thread;
|
||||
void setupThread(uint32_t threadId);
|
||||
// Clear all profiling data
|
||||
void clear() VL_MT_SAFE_EXCLUDES(m_mutex);
|
||||
// Write profiling data into file
|
||||
void dump(const char* filenamep, uint64_t tickEnd) VL_MT_SAFE_EXCLUDES(m_mutex);
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
// VlPgoProfiler is for collecting profiling data for PGO
|
||||
|
||||
template <std::size_t T_Entries> class VlPgoProfiler final {
|
||||
// TYPES
|
||||
struct Record final {
|
||||
const std::string m_name; // Hashed name of mtask/etc
|
||||
const size_t m_counterNumber = 0; // Which counter has data
|
||||
};
|
||||
|
||||
// Counters are stored packed, all together to reduce cache effects
|
||||
std::array<uint64_t, T_Entries> m_counters; // Time spent on this record
|
||||
std::vector<Record> m_records; // Record information
|
||||
|
||||
public:
|
||||
// METHODS
|
||||
VerilatedProfiler() = default;
|
||||
~VerilatedProfiler() = default;
|
||||
VlPgoProfiler() = default;
|
||||
~VlPgoProfiler() = default;
|
||||
void write(const char* modelp, const std::string& filename) VL_MT_SAFE;
|
||||
void addCounter(size_t counter, const std::string& name) {
|
||||
VL_DEBUG_IF(assert(counter < T_Entries););
|
||||
m_records.emplace_back(VerilatedProfilerRec{counter, name});
|
||||
m_records.emplace_back(Record{name, counter});
|
||||
}
|
||||
void startCounter(size_t counter) {
|
||||
vluint64_t val;
|
||||
VL_RDTSC(val);
|
||||
// -= so when we add end time in stopCounter, we already subtracted
|
||||
// out, without needing to hold another temporary
|
||||
m_counters[counter] -= val;
|
||||
}
|
||||
void stopCounter(size_t counter) {
|
||||
vluint64_t val;
|
||||
VL_RDTSC(val);
|
||||
m_counters[counter] += val;
|
||||
// -= so when we add end time in stopCounter, the net effect is adding the difference,
|
||||
// without needing to hold onto a temporary
|
||||
m_counters[counter] -= VL_CPU_TICK();
|
||||
}
|
||||
void stopCounter(size_t counter) { m_counters[counter] += VL_CPU_TICK(); }
|
||||
};
|
||||
|
||||
template <std::size_t T_Entries>
|
||||
void VerilatedProfiler<T_Entries>::write(const char* modelp,
|
||||
const std::string& filename) VL_MT_SAFE {
|
||||
void VlPgoProfiler<T_Entries>::write(const char* modelp, const std::string& filename) VL_MT_SAFE {
|
||||
static VerilatedMutex s_mutex;
|
||||
const VerilatedLockGuard lock{s_mutex};
|
||||
|
||||
@@ -79,20 +228,15 @@ void VerilatedProfiler<T_Entries>::write(const char* modelp,
|
||||
// So when we have multiple models in an executable, possibly even
|
||||
// running on different threads, each will have a different symtab so
|
||||
// each will collect is own data correctly. However when each is
|
||||
// destroid we need to get all the data, not keep overwriting and only
|
||||
// destroyed we need to get all the data, not keep overwriting and only
|
||||
// get the last model's data.
|
||||
static bool s_firstCall = true;
|
||||
|
||||
VL_DEBUG_IF(VL_DBG_MSGF("+prof+vlt+file writing to '%s'\n", filename.c_str()););
|
||||
|
||||
FILE* fp = nullptr;
|
||||
if (!s_firstCall) fp = std::fopen(filename.c_str(), "a");
|
||||
if (VL_UNLIKELY(!fp))
|
||||
fp = std::fopen(filename.c_str(), "w"); // firstCall, or doesn't exist yet
|
||||
FILE* const fp = std::fopen(filename.c_str(), s_firstCall ? "w" : "a");
|
||||
if (VL_UNLIKELY(!fp)) {
|
||||
VL_FATAL_MT(filename.c_str(), 0, "", "+prof+vlt+file file not writable");
|
||||
// cppcheck-suppress resourceLeak // bug, doesn't realize fp is nullptr
|
||||
return; // LCOV_EXCL_LINE
|
||||
}
|
||||
s_firstCall = false;
|
||||
|
||||
@@ -101,10 +245,9 @@ void VerilatedProfiler<T_Entries>::write(const char* modelp,
|
||||
fprintf(fp, "// Verilated model profile-guided optimization data dump file\n");
|
||||
fprintf(fp, "`verilator_config\n");
|
||||
|
||||
for (const auto& it : m_records) {
|
||||
const std::string& name = it.name();
|
||||
fprintf(fp, "profile_data -model \"%s\" -mtask \"%s\" -cost 64'd%" VL_PRI64 "u\n", modelp,
|
||||
name.c_str(), m_counters[it.counterNumber()]);
|
||||
for (const Record& rec : m_records) {
|
||||
fprintf(fp, "profile_data -model \"%s\" -mtask \"%s\" -cost 64'd%" PRIu64 "\n", modelp,
|
||||
rec.m_name.c_str(), m_counters[rec.m_counterNumber]);
|
||||
}
|
||||
|
||||
std::fclose(fp);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
//
|
||||
// Code available from: https://verilator.org
|
||||
//
|
||||
// Copyright 2001-2021 by Wilson Snyder. This program is free software; you
|
||||
// Copyright 2001-2022 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.
|
||||
@@ -63,8 +63,8 @@ static const char* const VLTSAVE_TRAILER_STR = "vltsaved";
|
||||
bool VerilatedDeserialize::readDiffers(const void* __restrict datap,
|
||||
size_t size) VL_MT_UNSAFE_ONE {
|
||||
bufferCheck();
|
||||
const vluint8_t* __restrict dp = static_cast<const vluint8_t* __restrict>(datap);
|
||||
vluint8_t miss = 0;
|
||||
const uint8_t* __restrict dp = static_cast<const uint8_t* __restrict>(datap);
|
||||
uint8_t miss = 0;
|
||||
while (size--) miss |= (*dp++ ^ *m_cp++);
|
||||
return (miss != 0);
|
||||
}
|
||||
@@ -192,7 +192,7 @@ void VerilatedRestore::close() VL_MT_UNSAFE_ONE {
|
||||
void VerilatedSave::flush() VL_MT_UNSAFE_ONE {
|
||||
m_assertOne.check();
|
||||
if (VL_UNLIKELY(!isOpen())) return;
|
||||
vluint8_t* wp = m_bufp;
|
||||
const uint8_t* wp = m_bufp;
|
||||
while (true) {
|
||||
const ssize_t remaining = (m_cp - wp);
|
||||
if (remaining == 0) break;
|
||||
@@ -219,8 +219,8 @@ void VerilatedRestore::fill() VL_MT_UNSAFE_ONE {
|
||||
m_assertOne.check();
|
||||
if (VL_UNLIKELY(!isOpen())) return;
|
||||
// Move remaining characters down to start of buffer. (No memcpy, overlaps allowed)
|
||||
vluint8_t* rp = m_bufp;
|
||||
for (vluint8_t* sp = m_cp; sp < m_endp; *rp++ = *sp++) {} // Overlaps
|
||||
uint8_t* rp = m_bufp;
|
||||
for (uint8_t* sp = m_cp; sp < m_endp; *rp++ = *sp++) {} // Overlaps
|
||||
m_endp = m_bufp + (m_endp - m_cp);
|
||||
m_cp = m_bufp; // Reset buffer
|
||||
// Read into buffer starting at m_endp
|
||||
|
||||
+26
-26
@@ -3,7 +3,7 @@
|
||||
//
|
||||
// Code available from: https://verilator.org
|
||||
//
|
||||
// Copyright 2000-2021 by Wilson Snyder. This program is free software; you
|
||||
// Copyright 2000-2022 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,8 +40,8 @@ class VerilatedSerialize VL_NOT_FINAL {
|
||||
protected:
|
||||
// MEMBERS
|
||||
// For speed, keep m_cp as the first member of this structure
|
||||
vluint8_t* m_cp; // Current pointer into m_bufp buffer
|
||||
vluint8_t* m_bufp; // Output buffer
|
||||
uint8_t* m_cp; // Current pointer into m_bufp buffer
|
||||
uint8_t* m_bufp; // Output buffer
|
||||
bool m_isOpen = false; // True indicates open file/stream
|
||||
std::string m_filename; // Filename, for error messages
|
||||
VerilatedAssertOneThread m_assertOne; // Assert only called from single thread
|
||||
@@ -58,7 +58,7 @@ protected:
|
||||
public:
|
||||
/// Construct
|
||||
VerilatedSerialize() {
|
||||
m_bufp = new vluint8_t[bufferSize()];
|
||||
m_bufp = new uint8_t[bufferSize()];
|
||||
m_cp = m_bufp;
|
||||
}
|
||||
/// Flish, close, and destruct
|
||||
@@ -77,12 +77,12 @@ public:
|
||||
virtual void flush() VL_MT_UNSAFE_ONE {}
|
||||
/// Write data to stream
|
||||
VerilatedSerialize& write(const void* __restrict datap, size_t size) VL_MT_UNSAFE_ONE {
|
||||
const vluint8_t* __restrict dp = (const vluint8_t* __restrict)datap;
|
||||
const uint8_t* __restrict dp = (const uint8_t* __restrict)datap;
|
||||
while (size) {
|
||||
bufferCheck();
|
||||
size_t blk = size;
|
||||
if (blk > bufferInsertSize()) blk = bufferInsertSize();
|
||||
const vluint8_t* __restrict maxp = dp + blk;
|
||||
const uint8_t* __restrict maxp = dp + blk;
|
||||
for (; dp < maxp; *m_cp++ = *dp++) {}
|
||||
size -= blk;
|
||||
}
|
||||
@@ -111,9 +111,9 @@ class VerilatedDeserialize VL_NOT_FINAL {
|
||||
protected:
|
||||
// MEMBERS
|
||||
// For speed, keep m_cp as the first member of this structure
|
||||
vluint8_t* m_cp; // Current pointer into m_bufp buffer
|
||||
vluint8_t* m_bufp; // Output buffer
|
||||
vluint8_t* m_endp = nullptr; // Last valid byte in m_bufp buffer
|
||||
uint8_t* m_cp; // Current pointer into m_bufp buffer
|
||||
uint8_t* m_bufp; // Output buffer
|
||||
uint8_t* m_endp = nullptr; // Last valid byte in m_bufp buffer
|
||||
bool m_isOpen = false; // True indicates open file/stream
|
||||
std::string m_filename; // Filename, for error messages
|
||||
VerilatedAssertOneThread m_assertOne; // Assert only called from single thread
|
||||
@@ -131,7 +131,7 @@ protected:
|
||||
public:
|
||||
/// Construct
|
||||
VerilatedDeserialize() {
|
||||
m_bufp = new vluint8_t[bufferSize()];
|
||||
m_bufp = new uint8_t[bufferSize()];
|
||||
m_cp = m_bufp;
|
||||
}
|
||||
/// Destruct
|
||||
@@ -150,12 +150,12 @@ public:
|
||||
virtual void flush() VL_MT_UNSAFE_ONE {}
|
||||
/// Read data from stream
|
||||
VerilatedDeserialize& read(void* __restrict datap, size_t size) VL_MT_UNSAFE_ONE {
|
||||
vluint8_t* __restrict dp = static_cast<vluint8_t* __restrict>(datap);
|
||||
uint8_t* __restrict dp = static_cast<uint8_t* __restrict>(datap);
|
||||
while (size) {
|
||||
bufferCheck();
|
||||
size_t blk = size;
|
||||
if (blk > bufferInsertSize()) blk = bufferInsertSize();
|
||||
const vluint8_t* __restrict maxp = dp + blk;
|
||||
const uint8_t* __restrict maxp = dp + blk;
|
||||
for (; dp < maxp; *dp++ = *m_cp++) {}
|
||||
size -= blk;
|
||||
}
|
||||
@@ -165,7 +165,7 @@ public:
|
||||
// Internal use:
|
||||
// Read a datum and compare with expected value
|
||||
VerilatedDeserialize& readAssert(const void* __restrict datap, size_t size) VL_MT_UNSAFE_ONE;
|
||||
VerilatedDeserialize& readAssert(vluint64_t data) VL_MT_UNSAFE_ONE {
|
||||
VerilatedDeserialize& readAssert(uint64_t data) VL_MT_UNSAFE_ONE {
|
||||
return readAssert(&data, sizeof(data));
|
||||
}
|
||||
|
||||
@@ -236,28 +236,28 @@ public:
|
||||
|
||||
//=============================================================================
|
||||
|
||||
inline VerilatedSerialize& operator<<(VerilatedSerialize& os, const vluint64_t& rhs) {
|
||||
inline VerilatedSerialize& operator<<(VerilatedSerialize& os, const uint64_t& rhs) {
|
||||
return os.write(&rhs, sizeof(rhs));
|
||||
}
|
||||
inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, vluint64_t& rhs) {
|
||||
inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, uint64_t& rhs) {
|
||||
return os.read(&rhs, sizeof(rhs));
|
||||
}
|
||||
inline VerilatedSerialize& operator<<(VerilatedSerialize& os, const vluint32_t& rhs) {
|
||||
inline VerilatedSerialize& operator<<(VerilatedSerialize& os, const uint32_t& rhs) {
|
||||
return os.write(&rhs, sizeof(rhs));
|
||||
}
|
||||
inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, vluint32_t& rhs) {
|
||||
inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, uint32_t& rhs) {
|
||||
return os.read(&rhs, sizeof(rhs));
|
||||
}
|
||||
inline VerilatedSerialize& operator<<(VerilatedSerialize& os, const vluint16_t& rhs) {
|
||||
inline VerilatedSerialize& operator<<(VerilatedSerialize& os, const uint16_t& rhs) {
|
||||
return os.write(&rhs, sizeof(rhs));
|
||||
}
|
||||
inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, vluint16_t& rhs) {
|
||||
inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, uint16_t& rhs) {
|
||||
return os.read(&rhs, sizeof(rhs));
|
||||
}
|
||||
inline VerilatedSerialize& operator<<(VerilatedSerialize& os, const vluint8_t& rhs) {
|
||||
inline VerilatedSerialize& operator<<(VerilatedSerialize& os, const uint8_t& rhs) {
|
||||
return os.write(&rhs, sizeof(rhs));
|
||||
}
|
||||
inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, vluint8_t& rhs) {
|
||||
inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, uint8_t& rhs) {
|
||||
return os.read(&rhs, sizeof(rhs));
|
||||
}
|
||||
inline VerilatedSerialize& operator<<(VerilatedSerialize& os, const bool& rhs) {
|
||||
@@ -279,12 +279,12 @@ inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, float& rhs) {
|
||||
return os.read(&rhs, sizeof(rhs));
|
||||
}
|
||||
inline VerilatedSerialize& operator<<(VerilatedSerialize& os, const std::string& rhs) {
|
||||
vluint32_t len = rhs.length();
|
||||
const uint32_t len = rhs.length();
|
||||
os << len;
|
||||
return os.write(rhs.data(), len);
|
||||
}
|
||||
inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, std::string& rhs) {
|
||||
vluint32_t len = 0;
|
||||
uint32_t len = 0;
|
||||
os >> len;
|
||||
rhs.resize(len);
|
||||
return os.read((void*)rhs.data(), len);
|
||||
@@ -295,7 +295,7 @@ VerilatedDeserialize& operator>>(VerilatedDeserialize& os, VerilatedContext* rhs
|
||||
template <class T_Key, class T_Value>
|
||||
VerilatedSerialize& operator<<(VerilatedSerialize& os, VlAssocArray<T_Key, T_Value>& rhs) {
|
||||
os << rhs.atDefault();
|
||||
const vluint32_t len = rhs.size();
|
||||
const uint32_t len = rhs.size();
|
||||
os << len;
|
||||
for (const auto& i : rhs) {
|
||||
const T_Key index = i.first; // Copy to get around const_iterator
|
||||
@@ -307,10 +307,10 @@ VerilatedSerialize& operator<<(VerilatedSerialize& os, VlAssocArray<T_Key, T_Val
|
||||
template <class T_Key, class T_Value>
|
||||
VerilatedDeserialize& operator>>(VerilatedDeserialize& os, VlAssocArray<T_Key, T_Value>& rhs) {
|
||||
os >> rhs.atDefault();
|
||||
vluint32_t len = 0;
|
||||
uint32_t len = 0;
|
||||
os >> len;
|
||||
rhs.clear();
|
||||
for (vluint32_t i = 0; i < len; ++i) {
|
||||
for (uint32_t i = 0; i < len; ++i) {
|
||||
T_Key index;
|
||||
T_Value value;
|
||||
os >> index;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
//
|
||||
// Code available from: https://verilator.org
|
||||
//
|
||||
// Copyright 2009-2021 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2009-2022 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.
|
||||
@@ -39,10 +39,10 @@
|
||||
// This class is thread safe (though most of SystemC is not).
|
||||
class VlScBvExposer final : public sc_bv_base {
|
||||
public:
|
||||
static const vluint32_t* sp_datap(const sc_bv_base& base) VL_MT_SAFE {
|
||||
static const uint32_t* sp_datap(const sc_bv_base& base) VL_MT_SAFE {
|
||||
return static_cast<const VlScBvExposer*>(&base)->sp_datatp();
|
||||
}
|
||||
const vluint32_t* sp_datatp() const { return reinterpret_cast<vluint32_t*>(m_data); }
|
||||
const uint32_t* sp_datatp() const { return reinterpret_cast<uint32_t*>(m_data); }
|
||||
// Above reads this protected element in sc_bv_base:
|
||||
// sc_digit* m_data; // data array
|
||||
};
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
//
|
||||
// Code available from: https://verilator.org
|
||||
//
|
||||
// Copyright 2003-2021 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2022 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.
|
||||
@@ -69,9 +69,9 @@ public:
|
||||
|
||||
class VerilatedVarProps VL_NOT_FINAL {
|
||||
// TYPES
|
||||
static constexpr vluint32_t MAGIC = 0xddc4f829UL;
|
||||
static constexpr uint32_t MAGIC = 0xddc4f829UL;
|
||||
// MEMBERS
|
||||
const vluint32_t m_magic; // Magic number
|
||||
const uint32_t m_magic; // Magic number
|
||||
const VerilatedVarType m_vltype; // Data type
|
||||
const VerilatedVarFlags m_vlflags; // Direction
|
||||
const int m_pdims; // Packed dimensions, 0 = none
|
||||
@@ -142,7 +142,7 @@ public:
|
||||
VerilatedVarFlags vldir() const {
|
||||
return static_cast<VerilatedVarFlags>(static_cast<int>(m_vlflags) & VLVF_MASK_DIR);
|
||||
}
|
||||
vluint32_t entSize() const;
|
||||
uint32_t entSize() const;
|
||||
bool isPublicRW() const { return ((m_vlflags & VLVF_PUB_RW) != 0); }
|
||||
// DPI compatible C standard layout
|
||||
bool isDpiCLayout() const { return ((m_vlflags & VLVF_DPI_CLAY) != 0); }
|
||||
@@ -192,8 +192,8 @@ public:
|
||||
|
||||
class VerilatedDpiOpenVar final {
|
||||
// MEMBERS
|
||||
const VerilatedVarProps* m_propsp; // Variable properties
|
||||
void* m_datap; // Location of data (local to thread always, so safe)
|
||||
const VerilatedVarProps* const m_propsp; // Variable properties
|
||||
void* const m_datap; // Location of data (local to thread always, so safe)
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
VerilatedDpiOpenVar(const VerilatedVarProps* propsp, void* datap)
|
||||
@@ -230,10 +230,10 @@ public:
|
||||
|
||||
class VerilatedVar final : public VerilatedVarProps {
|
||||
// MEMBERS
|
||||
void* m_datap; // Location of data
|
||||
const char* m_namep; // Name - slowpath
|
||||
void* const m_datap; // Location of data
|
||||
const char* const m_namep; // Name - slowpath
|
||||
protected:
|
||||
bool m_isParam;
|
||||
const bool m_isParam;
|
||||
friend class VerilatedScope;
|
||||
// CONSTRUCTORS
|
||||
VerilatedVar(const char* namep, void* datap, VerilatedVarType vltype,
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
//
|
||||
// Code available from: https://verilator.org
|
||||
//
|
||||
// Copyright 2003-2021 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2022 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.
|
||||
|
||||
+27
-129
@@ -3,7 +3,7 @@
|
||||
//
|
||||
// Code available from: https://verilator.org
|
||||
//
|
||||
// Copyright 2012-2021 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2012-2022 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,22 +24,25 @@
|
||||
#include "verilatedos.h"
|
||||
#include "verilated_threads.h"
|
||||
|
||||
#ifdef VL_PROFILER
|
||||
#include "verilated_profiler.h"
|
||||
#endif
|
||||
|
||||
#include <cstdio>
|
||||
#include <fstream>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
//=============================================================================
|
||||
// Globals
|
||||
|
||||
// Internal note: Globals may multi-construct, see verilated.cpp top.
|
||||
|
||||
std::atomic<vluint64_t> VlMTaskVertex::s_yields;
|
||||
|
||||
VL_THREAD_LOCAL VlThreadPool::ProfileTrace* VlThreadPool::t_profilep = nullptr;
|
||||
std::atomic<uint64_t> VlMTaskVertex::s_yields;
|
||||
|
||||
//=============================================================================
|
||||
// VlMTaskVertex
|
||||
|
||||
VlMTaskVertex::VlMTaskVertex(vluint32_t upstreamDepCount)
|
||||
VlMTaskVertex::VlMTaskVertex(uint32_t upstreamDepCount)
|
||||
: m_upstreamDepsDone{0}
|
||||
, m_upstreamDepCount{upstreamDepCount} {
|
||||
assert(atomic_is_lock_free(&m_upstreamDepsDone));
|
||||
@@ -48,12 +51,11 @@ VlMTaskVertex::VlMTaskVertex(vluint32_t upstreamDepCount)
|
||||
//=============================================================================
|
||||
// VlWorkerThread
|
||||
|
||||
VlWorkerThread::VlWorkerThread(VlThreadPool* poolp, VerilatedContext* contextp, bool profiling)
|
||||
VlWorkerThread::VlWorkerThread(uint32_t threadId, VerilatedContext* contextp,
|
||||
VlExecutionProfiler* profilerp)
|
||||
: m_ready_size{0}
|
||||
, m_poolp{poolp}
|
||||
, m_profiling{profiling} // Must init this last -- after setting up fields that it might read:
|
||||
, m_exiting{false}
|
||||
, m_cthread{startWorker, this}
|
||||
, m_cthread{startWorker, this, threadId, profilerp}
|
||||
, m_contextp{contextp} {}
|
||||
|
||||
VlWorkerThread::~VlWorkerThread() {
|
||||
@@ -64,8 +66,6 @@ VlWorkerThread::~VlWorkerThread() {
|
||||
}
|
||||
|
||||
void VlWorkerThread::workerLoop() {
|
||||
if (VL_UNLIKELY(m_profiling)) m_poolp->setupProfilingClientThread();
|
||||
|
||||
ExecRec work;
|
||||
work.m_fnp = nullptr;
|
||||
|
||||
@@ -80,144 +80,42 @@ void VlWorkerThread::workerLoop() {
|
||||
work.m_fnp = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (VL_UNLIKELY(m_profiling)) m_poolp->tearDownProfilingClientThread();
|
||||
}
|
||||
|
||||
void VlWorkerThread::startWorker(VlWorkerThread* workerp) {
|
||||
void VlWorkerThread::startWorker(VlWorkerThread* workerp, uint32_t threadId,
|
||||
VlExecutionProfiler* profilerp) {
|
||||
Verilated::threadContextp(workerp->m_contextp);
|
||||
#ifdef VL_PROFILER
|
||||
// Note: setupThread is not defined without VL_PROFILER, hence the #ifdef. Still, we might
|
||||
// not be profiling execution (e.g.: PGO only), so profilerp might still be nullptr.
|
||||
if (profilerp) profilerp->setupThread(threadId);
|
||||
#endif
|
||||
workerp->workerLoop();
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
// VlThreadPool
|
||||
|
||||
VlThreadPool::VlThreadPool(VerilatedContext* contextp, int nThreads, bool profiling)
|
||||
: m_profiling{profiling} {
|
||||
VlThreadPool::VlThreadPool(VerilatedContext* contextp, int nThreads,
|
||||
VlExecutionProfiler* profiler) {
|
||||
// --threads N passes nThreads=N-1, as the "main" threads counts as 1
|
||||
++nThreads;
|
||||
const unsigned cpus = std::thread::hardware_concurrency();
|
||||
if (cpus < nThreads + 1) {
|
||||
if (cpus < nThreads) {
|
||||
static int warnedOnce = 0;
|
||||
if (!warnedOnce++) {
|
||||
VL_PRINTF_MT("%%Warning: System has %u CPUs but model Verilated with"
|
||||
" --threads %d; may run slow.\n",
|
||||
cpus, nThreads + 1);
|
||||
cpus, nThreads);
|
||||
}
|
||||
}
|
||||
// Create'em
|
||||
for (int i = 0; i < nThreads; ++i) {
|
||||
m_workers.push_back(new VlWorkerThread{this, contextp, profiling});
|
||||
// Create worker threads
|
||||
for (uint32_t threadId = 1; threadId < nThreads; ++threadId) {
|
||||
m_workers.push_back(new VlWorkerThread{threadId, contextp, profiler});
|
||||
}
|
||||
// Set up a profile buffer for the current thread too -- on the
|
||||
// assumption that it's the same thread that calls eval and may be
|
||||
// donated to run mtasks during the eval.
|
||||
if (VL_UNLIKELY(m_profiling)) setupProfilingClientThread();
|
||||
}
|
||||
|
||||
VlThreadPool::~VlThreadPool() {
|
||||
// Each ~WorkerThread will wait for its thread to exit.
|
||||
for (auto& i : m_workers) delete i;
|
||||
if (VL_UNLIKELY(m_profiling)) tearDownProfilingClientThread();
|
||||
}
|
||||
|
||||
void VlThreadPool::tearDownProfilingClientThread() {
|
||||
assert(t_profilep);
|
||||
delete t_profilep;
|
||||
t_profilep = nullptr;
|
||||
}
|
||||
|
||||
void VlThreadPool::setupProfilingClientThread() VL_MT_SAFE_EXCLUDES(m_mutex) {
|
||||
assert(!t_profilep);
|
||||
t_profilep = new ProfileTrace;
|
||||
// Reserve some space in the thread-local profiling buffer;
|
||||
// try not to malloc while collecting profiling.
|
||||
t_profilep->reserve(4096);
|
||||
{
|
||||
const VerilatedLockGuard lock{m_mutex};
|
||||
m_allProfiles.insert(t_profilep);
|
||||
}
|
||||
}
|
||||
|
||||
void VlThreadPool::profileAppendAll(const VlProfileRec& rec) VL_MT_SAFE_EXCLUDES(m_mutex) {
|
||||
const VerilatedLockGuard lock{m_mutex};
|
||||
for (const auto& profilep : m_allProfiles) {
|
||||
// Every thread's profile trace gets a copy of rec.
|
||||
profilep->emplace_back(rec);
|
||||
}
|
||||
}
|
||||
|
||||
void VlThreadPool::profileDump(const char* filenamep, vluint64_t tickStart, vluint64_t tickEnd)
|
||||
VL_MT_SAFE_EXCLUDES(m_mutex) {
|
||||
const VerilatedLockGuard lock{m_mutex};
|
||||
VL_DEBUG_IF(VL_DBG_MSGF("+prof+threads writing to '%s'\n", filenamep););
|
||||
|
||||
FILE* const fp = std::fopen(filenamep, "w");
|
||||
if (VL_UNLIKELY(!fp)) {
|
||||
VL_FATAL_MT(filenamep, 0, "", "+prof+threads+file file not writable");
|
||||
// cppcheck-suppress resourceLeak // bug, doesn't realize fp is nullptr
|
||||
return; // LCOV_EXCL_LINE
|
||||
}
|
||||
|
||||
// TODO Perhaps merge with verilated_coverage output format, so can
|
||||
// have a common merging and reporting tool, etc.
|
||||
fprintf(fp, "VLPROFTHREAD 1.1 # Verilator thread profile dump version 1.1\n");
|
||||
fprintf(fp, "VLPROF arg --threads %" VL_PRI64 "u\n", vluint64_t(m_workers.size() + 1));
|
||||
fprintf(fp, "VLPROF arg +verilator+prof+threads+start+%" VL_PRI64 "u\n",
|
||||
Verilated::threadContextp()->profThreadsStart());
|
||||
fprintf(fp, "VLPROF arg +verilator+prof+threads+window+%u\n",
|
||||
Verilated::threadContextp()->profThreadsWindow());
|
||||
fprintf(fp, "VLPROF stat yields %" VL_PRI64 "u\n", VlMTaskVertex::yields());
|
||||
|
||||
// Copy /proc/cpuinfo into this output so verilator_gantt can be run on
|
||||
// a different machine
|
||||
{
|
||||
const std::unique_ptr<std::ifstream> ifp{new std::ifstream("/proc/cpuinfo")};
|
||||
if (!ifp->fail()) {
|
||||
std::string line;
|
||||
while (std::getline(*ifp, line)) { fprintf(fp, "VLPROFPROC %s\n", line.c_str()); }
|
||||
}
|
||||
}
|
||||
|
||||
vluint32_t thread_id = 0;
|
||||
for (const auto& pi : m_allProfiles) {
|
||||
++thread_id;
|
||||
|
||||
bool printing = false; // False while in warmup phase
|
||||
for (const auto& ei : *pi) {
|
||||
switch (ei.m_type) {
|
||||
case VlProfileRec::TYPE_BARRIER: //
|
||||
printing = true;
|
||||
break;
|
||||
case VlProfileRec::TYPE_EVAL:
|
||||
if (!printing) break;
|
||||
fprintf(fp,
|
||||
"VLPROF eval start %" VL_PRI64 "u elapsed %" VL_PRI64 "u"
|
||||
" cpu %u on thread %u\n",
|
||||
ei.m_startTime - tickStart, (ei.m_endTime - ei.m_startTime), ei.m_cpu,
|
||||
thread_id);
|
||||
break;
|
||||
case VlProfileRec::TYPE_EVAL_LOOP:
|
||||
if (!printing) break;
|
||||
fprintf(fp,
|
||||
"VLPROF eval_loop start %" VL_PRI64 "u elapsed %" VL_PRI64 "u"
|
||||
" cpu %u on thread %u\n",
|
||||
ei.m_startTime - tickStart, (ei.m_endTime - ei.m_startTime), ei.m_cpu,
|
||||
thread_id);
|
||||
break;
|
||||
case VlProfileRec::TYPE_MTASK_RUN:
|
||||
if (!printing) break;
|
||||
fprintf(fp,
|
||||
"VLPROF mtask %d"
|
||||
" start %" VL_PRI64 "u elapsed %" VL_PRI64 "u"
|
||||
" predict_start %u predict_cost %u cpu %u on thread %u\n",
|
||||
ei.m_mtaskId, ei.m_startTime - tickStart, (ei.m_endTime - ei.m_startTime),
|
||||
ei.m_predictStart, ei.m_predictCost, ei.m_cpu, thread_id);
|
||||
break;
|
||||
default: assert(false); break; // LCOV_EXCL_LINE
|
||||
}
|
||||
}
|
||||
}
|
||||
fprintf(fp, "VLPROF stat ticks %" VL_PRI64 "u\n", tickEnd - tickStart);
|
||||
|
||||
std::fclose(fp);
|
||||
}
|
||||
|
||||
+20
-102
@@ -3,7 +3,7 @@
|
||||
//
|
||||
// Code available from: https://verilator.org
|
||||
//
|
||||
// Copyright 2012-2021 by Wilson Snyder. This program is free software; you
|
||||
// Copyright 2012-2022 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,15 +35,17 @@
|
||||
#error "verilated_threads.h/cpp expected VL_THREADED (from verilator --threads)"
|
||||
#endif
|
||||
|
||||
#include <atomic>
|
||||
#include <condition_variable>
|
||||
#include <set>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
// clang-format off
|
||||
#if defined(__linux)
|
||||
# include <sched.h> // For sched_getcpu()
|
||||
#endif
|
||||
#if defined(__APPLE__)
|
||||
#if defined(__APPLE__) && !defined(__arm64__)
|
||||
# include <cpuid.h> // For __cpuid_count()
|
||||
#endif
|
||||
// clang-format on
|
||||
@@ -58,7 +60,7 @@ using VlExecFnp = void (*)(VlSelfP, bool);
|
||||
// Track dependencies for a single MTask.
|
||||
class VlMTaskVertex final {
|
||||
// MEMBERS
|
||||
static std::atomic<vluint64_t> s_yields; // Statistics
|
||||
static std::atomic<uint64_t> s_yields; // Statistics
|
||||
|
||||
// On even cycles, _upstreamDepsDone increases as upstream
|
||||
// dependencies complete. When it reaches _upstreamDepCount,
|
||||
@@ -76,8 +78,8 @@ class VlMTaskVertex final {
|
||||
// during done-notification. Nobody's quantified that cost though.
|
||||
// If we were really serious about shrinking this class, we could
|
||||
// use 16-bit types here...)
|
||||
std::atomic<vluint32_t> m_upstreamDepsDone;
|
||||
const vluint32_t m_upstreamDepCount;
|
||||
std::atomic<uint32_t> m_upstreamDepsDone;
|
||||
const uint32_t m_upstreamDepCount;
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
@@ -85,10 +87,10 @@ public:
|
||||
// 'upstreamDepCount' is the number of upstream MTaskVertex's
|
||||
// that must notify this MTaskVertex before it will become ready
|
||||
// to run.
|
||||
explicit VlMTaskVertex(vluint32_t upstreamDepCount);
|
||||
explicit VlMTaskVertex(uint32_t upstreamDepCount);
|
||||
~VlMTaskVertex() = default;
|
||||
|
||||
static vluint64_t yields() { return s_yields; }
|
||||
static uint64_t yields() { return s_yields; }
|
||||
static void yieldThread() {
|
||||
++s_yields; // Statistics
|
||||
std::this_thread::yield();
|
||||
@@ -99,19 +101,19 @@ public:
|
||||
// false while it's still waiting on more dependencies.
|
||||
inline bool signalUpstreamDone(bool evenCycle) {
|
||||
if (evenCycle) {
|
||||
const vluint32_t upstreamDepsDone
|
||||
const uint32_t upstreamDepsDone
|
||||
= 1 + m_upstreamDepsDone.fetch_add(1, std::memory_order_release);
|
||||
assert(upstreamDepsDone <= m_upstreamDepCount);
|
||||
return (upstreamDepsDone == m_upstreamDepCount);
|
||||
} else {
|
||||
const vluint32_t upstreamDepsDone_prev
|
||||
const uint32_t upstreamDepsDone_prev
|
||||
= m_upstreamDepsDone.fetch_sub(1, std::memory_order_release);
|
||||
assert(upstreamDepsDone_prev > 0);
|
||||
return (upstreamDepsDone_prev == 1);
|
||||
}
|
||||
}
|
||||
inline bool areUpstreamDepsDone(bool evenCycle) const {
|
||||
const vluint32_t target = evenCycle ? m_upstreamDepCount : 0;
|
||||
const uint32_t target = evenCycle ? m_upstreamDepCount : 0;
|
||||
return m_upstreamDepsDone.load(std::memory_order_acquire) == target;
|
||||
}
|
||||
inline void waitUntilUpstreamDone(bool evenCycle) const {
|
||||
@@ -127,64 +129,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
// Profiling support
|
||||
class VlProfileRec final {
|
||||
protected:
|
||||
friend class VlThreadPool;
|
||||
enum VlProfileE { TYPE_MTASK_RUN, TYPE_EVAL, TYPE_EVAL_LOOP, TYPE_BARRIER };
|
||||
// Layout below allows efficient packing.
|
||||
// Leave endTime first, so no math needed to calculate address in endRecord
|
||||
vluint64_t m_endTime = 0; // Tick at end of execution
|
||||
vluint64_t m_startTime = 0; // Tick at start of execution
|
||||
vluint32_t m_mtaskId = 0; // Mtask we're logging
|
||||
vluint32_t m_predictStart = 0; // Time scheduler predicted would start
|
||||
vluint32_t m_predictCost = 0; // How long scheduler predicted would take
|
||||
VlProfileE m_type = TYPE_BARRIER; // Record type
|
||||
unsigned m_cpu; // Execution CPU number (at start anyways)
|
||||
public:
|
||||
class Barrier {};
|
||||
VlProfileRec() = default;
|
||||
explicit VlProfileRec(Barrier) { m_cpu = getcpu(); }
|
||||
void startEval(vluint64_t time) {
|
||||
m_type = VlProfileRec::TYPE_EVAL;
|
||||
m_startTime = time;
|
||||
m_cpu = getcpu();
|
||||
}
|
||||
void startEvalLoop(vluint64_t time) {
|
||||
m_type = VlProfileRec::TYPE_EVAL_LOOP;
|
||||
m_startTime = time;
|
||||
m_cpu = getcpu();
|
||||
}
|
||||
void startRecord(vluint64_t time, vluint32_t mtask, vluint32_t predictStart,
|
||||
vluint32_t predictCost) {
|
||||
m_type = VlProfileRec::TYPE_MTASK_RUN;
|
||||
m_mtaskId = mtask;
|
||||
m_predictStart = predictStart;
|
||||
m_predictCost = predictCost;
|
||||
m_startTime = time;
|
||||
m_cpu = getcpu();
|
||||
}
|
||||
void endRecord(vluint64_t time) { m_endTime = time; }
|
||||
static int getcpu() { // Return current executing CPU
|
||||
#if defined(__linux)
|
||||
return sched_getcpu();
|
||||
#elif defined(__APPLE__)
|
||||
vluint32_t info[4];
|
||||
__cpuid_count(1, 0, info[0], info[1], info[2], info[3]);
|
||||
// info[1] is EBX, bits 24-31 are APIC ID
|
||||
if ((info[3] & (1 << 9)) == 0) {
|
||||
return -1; // no APIC on chip
|
||||
} else {
|
||||
return (unsigned)info[1] >> 24;
|
||||
}
|
||||
#elif defined(_WIN32)
|
||||
return GetCurrentProcessorNumber();
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
class VlExecutionProfiler;
|
||||
class VlThreadPool;
|
||||
|
||||
class VlWorkerThread final {
|
||||
@@ -205,7 +150,7 @@ private:
|
||||
};
|
||||
|
||||
// MEMBERS
|
||||
VerilatedMutex m_mutex;
|
||||
mutable VerilatedMutex m_mutex;
|
||||
std::condition_variable_any m_cv;
|
||||
// Only notify the condition_variable if the worker is waiting
|
||||
bool m_waiting VL_GUARDED_BY(m_mutex) = false;
|
||||
@@ -217,18 +162,16 @@ private:
|
||||
// Store the size atomically, so we can spin wait
|
||||
std::atomic<size_t> m_ready_size;
|
||||
|
||||
VlThreadPool* m_poolp; // Our associated thread pool
|
||||
|
||||
bool m_profiling; // Is profiling enabled?
|
||||
std::atomic<bool> m_exiting; // Worker thread should exit
|
||||
std::thread m_cthread; // Underlying C++ thread record
|
||||
VerilatedContext* m_contextp; // Context for spawned thread
|
||||
VerilatedContext* const m_contextp; // Context for spawned thread
|
||||
|
||||
VL_UNCOPYABLE(VlWorkerThread);
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit VlWorkerThread(VlThreadPool* poolp, VerilatedContext* contextp, bool profiling);
|
||||
explicit VlWorkerThread(uint32_t threadId, VerilatedContext* contextp,
|
||||
VlExecutionProfiler* profilerp);
|
||||
~VlWorkerThread();
|
||||
|
||||
// METHODS
|
||||
@@ -265,34 +208,20 @@ public:
|
||||
if (notify) m_cv.notify_one();
|
||||
}
|
||||
void workerLoop();
|
||||
static void startWorker(VlWorkerThread* workerp);
|
||||
static void startWorker(VlWorkerThread* workerp, uint32_t threadId,
|
||||
VlExecutionProfiler* profilerp);
|
||||
};
|
||||
|
||||
class VlThreadPool final {
|
||||
// TYPES
|
||||
using ProfileTrace = std::vector<VlProfileRec>;
|
||||
|
||||
// MEMBERS
|
||||
std::vector<VlWorkerThread*> m_workers; // our workers
|
||||
bool m_profiling; // is profiling enabled?
|
||||
|
||||
// Support profiling -- we can append records of profiling events
|
||||
// to this vector with very low overhead, and then dump them out
|
||||
// later. This prevents the overhead of printf/malloc/IO from
|
||||
// corrupting the profiling data. It's super cheap to append
|
||||
// a VlProfileRec struct on the end of a pre-allocated vector;
|
||||
// this is the only cost we pay in real-time during a profiling cycle.
|
||||
// Internal note: Globals may multi-construct, see verilated.cpp top.
|
||||
static VL_THREAD_LOCAL ProfileTrace* t_profilep;
|
||||
std::set<ProfileTrace*> m_allProfiles VL_GUARDED_BY(m_mutex);
|
||||
VerilatedMutex m_mutex;
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
// Construct a thread pool with 'nThreads' dedicated threads. The thread
|
||||
// pool will create these threads and make them available to execute tasks
|
||||
// via this->workerp(index)->addTask(...)
|
||||
VlThreadPool(VerilatedContext* contextp, int nThreads, bool profiling);
|
||||
VlThreadPool(VerilatedContext* contextp, int nThreads, VlExecutionProfiler* profilerp);
|
||||
~VlThreadPool();
|
||||
|
||||
// METHODS
|
||||
@@ -302,17 +231,6 @@ public:
|
||||
assert(index < m_workers.size());
|
||||
return m_workers[index];
|
||||
}
|
||||
inline VlProfileRec* profileAppend() {
|
||||
t_profilep->emplace_back();
|
||||
return &(t_profilep->back());
|
||||
}
|
||||
void profileAppendAll(const VlProfileRec& rec) VL_MT_SAFE_EXCLUDES(m_mutex);
|
||||
void profileDump(const char* filenamep, vluint64_t tickStart, vluint64_t tickEnd)
|
||||
VL_MT_SAFE_EXCLUDES(m_mutex);
|
||||
// In profiling mode, each executing thread must call
|
||||
// this once to setup profiling state:
|
||||
void setupProfilingClientThread() VL_MT_SAFE_EXCLUDES(m_mutex);
|
||||
void tearDownProfilingClientThread();
|
||||
|
||||
private:
|
||||
VL_UNCOPYABLE(VlThreadPool);
|
||||
|
||||
+269
-144
@@ -3,7 +3,7 @@
|
||||
//
|
||||
// Code available from: https://verilator.org
|
||||
//
|
||||
// Copyright 2001-2021 by Wilson Snyder. This program is free software; you
|
||||
// Copyright 2001-2022 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,28 +24,49 @@
|
||||
|
||||
// clang-format off
|
||||
|
||||
// In FST mode, VL_TRACE_THREADED enables offloading, but only if we also have
|
||||
// the FST writer thread. This means with --trace-threads 1, we get the FST
|
||||
// writer thread only, and with --trace-threads 2 we get offloading as well
|
||||
#if defined(VL_TRACE_FST_WRITER_THREAD) && defined(VL_TRACE_THREADED)
|
||||
# define VL_TRACE_OFFLOAD
|
||||
#endif
|
||||
// VCD tracing can happen fully in parallel
|
||||
#if defined(VM_TRACE_VCD) && VM_TRACE_VCD && defined(VL_TRACE_THREADED)
|
||||
# define VL_TRACE_PARALLEL
|
||||
#endif
|
||||
|
||||
#if defined(VL_TRACE_PARALLEL) && defined(VL_TRACE_OFFLOAD)
|
||||
# error "Cannot have VL_TRACE_PARALLEL and VL_TRACE_OFFLOAD together"
|
||||
#endif
|
||||
|
||||
#include "verilated.h"
|
||||
#include "verilated_trace_defs.h"
|
||||
|
||||
#include <bitset>
|
||||
#include <condition_variable>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#ifdef VL_TRACE_THREADED
|
||||
# include <condition_variable>
|
||||
#ifdef VL_TRACE_OFFLOAD
|
||||
# include <deque>
|
||||
# include <thread>
|
||||
#endif
|
||||
|
||||
// clang-format on
|
||||
|
||||
#ifdef VL_TRACE_THREADED
|
||||
class VlThreadPool;
|
||||
template <class T_Trace, class T_Buffer> class VerilatedTraceBuffer;
|
||||
|
||||
#ifdef VL_TRACE_OFFLOAD
|
||||
//=============================================================================
|
||||
// Threaded tracing
|
||||
// Offloaded tracing
|
||||
|
||||
// A simple synchronized first in first out queue
|
||||
template <class T> class VerilatedThreadQueue final { // LCOV_EXCL_LINE // lcov bug
|
||||
private:
|
||||
VerilatedMutex m_mutex; // Protects m_queue
|
||||
mutable VerilatedMutex m_mutex; // Protects m_queue
|
||||
std::condition_variable_any m_cv;
|
||||
std::deque<T> m_queue VL_GUARDED_BY(m_mutex);
|
||||
|
||||
@@ -86,11 +107,11 @@ 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 final {
|
||||
class VerilatedTraceOffloadCommand final {
|
||||
public:
|
||||
// These must all fit in 4 bit at the moment, as the tracing routines
|
||||
// pack parameters in the top bits.
|
||||
enum : vluint8_t {
|
||||
enum : uint8_t {
|
||||
CHG_BIT_0 = 0x0,
|
||||
CHG_BIT_1 = 0x1,
|
||||
CHG_CDATA = 0x2,
|
||||
@@ -100,7 +121,8 @@ public:
|
||||
CHG_WDATA = 0x6,
|
||||
CHG_DOUBLE = 0x8,
|
||||
// TODO: full..
|
||||
TIME_CHANGE = 0xd,
|
||||
TIME_CHANGE = 0xc,
|
||||
TRACE_BUFFER = 0xd,
|
||||
END = 0xe, // End of buffer
|
||||
SHUTDOWN = 0xf // Shutdown worker thread, also marks end of buffer
|
||||
};
|
||||
@@ -110,16 +132,22 @@ public:
|
||||
//=============================================================================
|
||||
// VerilatedTrace
|
||||
|
||||
// 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 VL_NOT_FINAL {
|
||||
// T_Trace is the format specific subclass of VerilatedTrace.
|
||||
// T_Buffer is the format specific subclass of VerilatedTraceBuffer.
|
||||
template <class T_Trace, class T_Buffer> class VerilatedTrace VL_NOT_FINAL {
|
||||
// Give the buffer (both base and derived) access to the private bits
|
||||
friend VerilatedTraceBuffer<T_Trace, T_Buffer>;
|
||||
friend T_Buffer;
|
||||
|
||||
public:
|
||||
using Buffer = T_Buffer;
|
||||
|
||||
//=========================================================================
|
||||
// Generic tracing internals
|
||||
|
||||
using initCb_t = void (*)(void*, T_Derived*, vluint32_t); // Type of init callbacks
|
||||
using dumpCb_t = void (*)(void*, T_Derived*); // Type of all but init callbacks
|
||||
using initCb_t = void (*)(void*, T_Trace*, uint32_t); // Type of init callbacks
|
||||
using dumpCb_t = void (*)(void*, Buffer*); // Type of dump callbacks
|
||||
using cleanupCb_t = void (*)(void*, T_Trace*); // Type of cleanup callbacks
|
||||
|
||||
private:
|
||||
struct CallbackRecord {
|
||||
@@ -127,9 +155,10 @@ private:
|
||||
// (the one in Ubuntu 14.04 with GCC 4.8.4 in particular) use the
|
||||
// assignment operator on inserting into collections, so they don't work
|
||||
// with const fields...
|
||||
union {
|
||||
initCb_t m_initCb; // The callback function
|
||||
dumpCb_t m_dumpCb; // The callback function
|
||||
union { // The callback
|
||||
initCb_t m_initCb;
|
||||
dumpCb_t m_dumpCb;
|
||||
cleanupCb_t m_cleanupCb;
|
||||
};
|
||||
void* m_userp; // The user pointer to pass to the callback (the symbol table)
|
||||
CallbackRecord(initCb_t cb, void* userp)
|
||||
@@ -138,67 +167,103 @@ private:
|
||||
CallbackRecord(dumpCb_t cb, void* userp)
|
||||
: m_dumpCb{cb}
|
||||
, m_userp{userp} {}
|
||||
CallbackRecord(cleanupCb_t cb, void* userp)
|
||||
: m_cleanupCb{cb}
|
||||
, m_userp{userp} {}
|
||||
};
|
||||
|
||||
vluint32_t* m_sigs_oldvalp; // Old value store
|
||||
vluint64_t m_timeLastDump; // Last time we did a dump
|
||||
std::vector<CallbackRecord> m_initCbs; // Routines to initialize traciong
|
||||
std::vector<CallbackRecord> m_fullCbs; // Routines to perform full dump
|
||||
std::vector<CallbackRecord> m_chgCbs; // Routines to perform incremental dump
|
||||
#ifdef VL_TRACE_PARALLEL
|
||||
struct ParallelWorkerData {
|
||||
const dumpCb_t m_cb; // The callback
|
||||
void* const m_userp; // The use pointer to pass to the callback
|
||||
Buffer* const m_bufp; // The buffer pointer to pass to the callback
|
||||
std::atomic<bool> m_ready{false}; // The ready flag
|
||||
mutable VerilatedMutex m_mutex; // Mutex for suspension until ready
|
||||
std::condition_variable_any m_cv; // Condition variable for suspension
|
||||
bool m_waiting VL_GUARDED_BY(m_mutex) = false; // Whether a thread is suspended in wait()
|
||||
|
||||
void wait();
|
||||
|
||||
ParallelWorkerData(dumpCb_t cb, void* userp, Buffer* bufp)
|
||||
: m_cb{cb}
|
||||
, m_userp{userp}
|
||||
, m_bufp{bufp} {}
|
||||
};
|
||||
|
||||
// Passed a ParallelWorkerData*, second argument is ignored
|
||||
static void parallelWorkerTask(void*, bool);
|
||||
#endif
|
||||
|
||||
using ParallelCallbackMap = std::unordered_map<VlThreadPool*, std::vector<CallbackRecord>>;
|
||||
|
||||
protected:
|
||||
uint32_t* m_sigs_oldvalp = nullptr; // Previous value store
|
||||
EData* m_sigs_enabledp = nullptr; // Bit vector of enabled codes (nullptr = all on)
|
||||
private:
|
||||
uint64_t m_timeLastDump = 0; // Last time we did a dump
|
||||
std::vector<bool> m_sigs_enabledVec; // Staging for m_sigs_enabledp
|
||||
std::vector<CallbackRecord> m_initCbs; // Routines to initialize tracing
|
||||
ParallelCallbackMap m_fullCbs; // Routines to perform full dump
|
||||
ParallelCallbackMap m_chgCbs; // Routines to perform incremental dump
|
||||
std::vector<CallbackRecord> m_cleanupCbs; // Routines to call at the end of dump
|
||||
bool m_fullDump; // Whether a full dump is required on the next call to 'dump'
|
||||
vluint32_t m_nextCode; // Next code number to assign
|
||||
vluint32_t m_numSignals; // Number of distinct signals
|
||||
vluint32_t m_maxBits; // Number of bits in the widest signal
|
||||
std::string m_moduleName; // Name of module being trace initialized now
|
||||
char m_scopeEscape;
|
||||
double m_timeRes; // Time resolution (ns/ms etc)
|
||||
double m_timeUnit; // Time units (ns/ms etc)
|
||||
std::vector<VlThreadPool*> m_threadPoolps; // All thread pools, in insertion order
|
||||
bool m_fullDump = true; // Whether a full dump is required on the next call to 'dump'
|
||||
uint32_t m_nextCode = 0; // Next code number to assign
|
||||
uint32_t m_numSignals = 0; // Number of distinct signals
|
||||
uint32_t m_maxBits = 0; // Number of bits in the widest signal
|
||||
std::vector<std::string> m_namePrefixStack{""}; // Path prefixes to add to signal names
|
||||
std::vector<std::pair<int, std::string>> m_dumpvars; // dumpvar() entries
|
||||
char m_scopeEscape = '.';
|
||||
double m_timeRes = 1e-9; // Time resolution (ns/ms etc)
|
||||
double m_timeUnit = 1e-0; // Time units (ns/ms etc)
|
||||
|
||||
void addThreadPool(VlThreadPool* threadPoolp) VL_MT_SAFE_EXCLUDES(m_mutex);
|
||||
|
||||
void addCallbackRecord(std::vector<CallbackRecord>& cbVec, CallbackRecord& cbRec)
|
||||
VL_MT_SAFE_EXCLUDES(m_mutex);
|
||||
|
||||
// Equivalent to 'this' but is of the sub-type 'T_Derived*'. Use 'self()->'
|
||||
// Equivalent to 'this' but is of the sub-type 'T_Trace*'. Use 'self()->'
|
||||
// to access duck-typed functions to avoid a virtual function call.
|
||||
T_Derived* self() { return static_cast<T_Derived*>(this); }
|
||||
T_Trace* self() { return static_cast<T_Trace*>(this); }
|
||||
|
||||
void runParallelCallbacks(const ParallelCallbackMap& cbMap);
|
||||
|
||||
// Flush any remaining data for this file
|
||||
static void onFlush(void* selfp) VL_MT_UNSAFE_ONE;
|
||||
// Close the file on termination
|
||||
static void onExit(void* selfp) VL_MT_UNSAFE_ONE;
|
||||
|
||||
#ifdef VL_TRACE_THREADED
|
||||
// Number of total trace buffers that have been allocated
|
||||
vluint32_t m_numTraceBuffers;
|
||||
|
||||
// Size of trace buffers
|
||||
size_t m_traceBufferSize;
|
||||
|
||||
#ifdef VL_TRACE_OFFLOAD
|
||||
// Number of total offload buffers that have been allocated
|
||||
uint32_t m_numOffloadBuffers = 0;
|
||||
// Size of offload buffers
|
||||
size_t m_offloadBufferSize = 0;
|
||||
// Buffers handed to worker for processing
|
||||
VerilatedThreadQueue<vluint32_t*> m_buffersToWorker;
|
||||
VerilatedThreadQueue<uint32_t*> m_offloadBuffersToWorker;
|
||||
// Buffers returned from worker after processing
|
||||
VerilatedThreadQueue<vluint32_t*> m_buffersFromWorker;
|
||||
|
||||
// Get a new trace buffer that can be populated. May block if none available
|
||||
vluint32_t* getTraceBuffer();
|
||||
VerilatedThreadQueue<uint32_t*> m_offloadBuffersFromWorker;
|
||||
|
||||
protected:
|
||||
// Write pointer into current buffer
|
||||
vluint32_t* m_traceBufferWritep;
|
||||
uint32_t* m_offloadBufferWritep = nullptr;
|
||||
// End of offload buffer
|
||||
uint32_t* m_offloadBufferEndp = nullptr;
|
||||
|
||||
// End of trace buffer
|
||||
vluint32_t* m_traceBufferEndp;
|
||||
|
||||
// The worker thread itself
|
||||
private:
|
||||
// The offload worker thread itself
|
||||
std::unique_ptr<std::thread> m_workerThread;
|
||||
|
||||
// The function executed by the worker thread
|
||||
void workerThreadMain();
|
||||
// Get a new offload buffer that can be populated. May block if none available
|
||||
uint32_t* getOffloadBuffer();
|
||||
|
||||
// Wait until given buffer is placed in m_buffersFromWorker
|
||||
void waitForBuffer(const vluint32_t* bufferp);
|
||||
// The function executed by the offload worker thread
|
||||
void offloadWorkerThreadMain();
|
||||
|
||||
// Wait until given offload buffer is placed in m_offloadBuffersFromWorker
|
||||
void waitForOffloadBuffer(const uint32_t* bufferp);
|
||||
|
||||
// Shut down and join worker, if it's running, otherwise do nothing
|
||||
void shutdownWorker();
|
||||
void shutdownOffloadWorker();
|
||||
#endif
|
||||
|
||||
// CONSTRUCTORS
|
||||
@@ -208,14 +273,13 @@ protected:
|
||||
//=========================================================================
|
||||
// Internals available to format specific implementations
|
||||
|
||||
VerilatedMutex m_mutex; // Ensure dump() etc only called from single thread
|
||||
mutable VerilatedMutex m_mutex; // Ensure dump() etc only called from single thread
|
||||
|
||||
vluint32_t nextCode() const { return m_nextCode; }
|
||||
vluint32_t numSignals() const { return m_numSignals; }
|
||||
vluint32_t maxBits() const { return m_maxBits; }
|
||||
const std::string& moduleName() const { return m_moduleName; }
|
||||
uint32_t nextCode() const { return m_nextCode; }
|
||||
uint32_t numSignals() const { return m_numSignals; }
|
||||
uint32_t maxBits() const { return m_maxBits; }
|
||||
void fullDump(bool value) { m_fullDump = value; }
|
||||
vluint64_t timeLastDump() { return m_timeLastDump; }
|
||||
uint64_t timeLastDump() { return m_timeLastDump; }
|
||||
|
||||
double timeRes() const { return m_timeRes; }
|
||||
double timeUnit() const { return m_timeUnit; }
|
||||
@@ -223,12 +287,15 @@ protected:
|
||||
|
||||
void traceInit() VL_MT_UNSAFE;
|
||||
|
||||
void declCode(vluint32_t code, vluint32_t bits, bool tri);
|
||||
// Declare new signal and return true if enabled
|
||||
bool declCode(uint32_t code, const char* namep, uint32_t bits, bool tri);
|
||||
|
||||
// Is this an escape?
|
||||
bool isScopeEscape(char c) { return std::isspace(c) || c == m_scopeEscape; }
|
||||
// Character that splits scopes. Note whitespace are ALWAYS escapes.
|
||||
char scopeEscape() { return m_scopeEscape; }
|
||||
// Prefix to assume in signal declarations
|
||||
const std::string& namePrefix() const { return m_namePrefixStack.back(); }
|
||||
|
||||
void closeBase();
|
||||
void flushBase();
|
||||
@@ -237,13 +304,17 @@ protected:
|
||||
// Virtual functions to be provided by the format specific implementation
|
||||
|
||||
// Called when the trace moves forward to a new time point
|
||||
virtual void emitTimeChange(vluint64_t timeui) = 0;
|
||||
virtual void emitTimeChange(uint64_t timeui) = 0;
|
||||
|
||||
// These hooks are called before a full or change based dump is produced.
|
||||
// The return value indicates whether to proceed with the dump.
|
||||
virtual bool preFullDump() = 0;
|
||||
virtual bool preChangeDump() = 0;
|
||||
|
||||
// Trace buffer management
|
||||
virtual Buffer* getTraceBuffer() = 0;
|
||||
virtual void commitTraceBuffer(Buffer*) = 0;
|
||||
|
||||
public:
|
||||
//=========================================================================
|
||||
// External interface to client code
|
||||
@@ -257,21 +328,62 @@ public:
|
||||
// Set time resolution (s/ms, defaults to ns)
|
||||
void set_time_resolution(const char* unitp) VL_MT_SAFE;
|
||||
void set_time_resolution(const std::string& unit) VL_MT_SAFE;
|
||||
// Set variables to dump, using $dumpvars format
|
||||
// If level = 0, dump everything and hier is then ignored
|
||||
void dumpvars(int level, const std::string& hier) VL_MT_SAFE;
|
||||
|
||||
// Call
|
||||
void dump(vluint64_t timeui) VL_MT_SAFE_EXCLUDES(m_mutex);
|
||||
void dump(uint64_t timeui) VL_MT_SAFE_EXCLUDES(m_mutex);
|
||||
|
||||
//=========================================================================
|
||||
// Internal interface to Verilator generated code
|
||||
|
||||
//=========================================================================
|
||||
// Non-hot path internal interface to Verilator generated code
|
||||
|
||||
void addInitCb(initCb_t cb, void* userp) VL_MT_SAFE;
|
||||
void addFullCb(dumpCb_t cb, void* userp) VL_MT_SAFE;
|
||||
void addChgCb(dumpCb_t cb, void* userp) VL_MT_SAFE;
|
||||
void addCleanupCb(dumpCb_t cb, void* userp) VL_MT_SAFE;
|
||||
void addFullCb(dumpCb_t cb, void* userp, VlThreadPool* = nullptr) VL_MT_SAFE;
|
||||
void addChgCb(dumpCb_t cb, void* userp, VlThreadPool* = nullptr) VL_MT_SAFE;
|
||||
void addCleanupCb(cleanupCb_t cb, void* userp) VL_MT_SAFE;
|
||||
|
||||
void module(const std::string& name) VL_MT_UNSAFE;
|
||||
void scopeEscape(char flag) { m_scopeEscape = flag; }
|
||||
|
||||
void pushNamePrefix(const std::string&);
|
||||
void popNamePrefix(unsigned count = 1);
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
// VerilatedTraceBuffer
|
||||
|
||||
// T_Trace is the format specific subclass of VerilatedTrace.
|
||||
// T_Buffer is the format specific subclass of VerilatedTraceBuffer.
|
||||
// The format-specific hot-path methods use duck-typing via T_Buffer for performance.
|
||||
template <class T_Trace, class T_Buffer> class VerilatedTraceBuffer VL_NOT_FINAL {
|
||||
friend T_Trace; // Give the trace file access to the private bits
|
||||
|
||||
protected:
|
||||
T_Trace& m_owner; // The VerilatedTrace subclass that owns this buffer
|
||||
|
||||
// Previous value store
|
||||
uint32_t* const m_sigs_oldvalp = m_owner.m_sigs_oldvalp;
|
||||
// Bit vector of enabled codes (nullptr = all on)
|
||||
EData* const m_sigs_enabledp = m_owner.m_sigs_enabledp;
|
||||
|
||||
#ifdef VL_TRACE_OFFLOAD
|
||||
// Write pointer into current buffer
|
||||
uint32_t* m_offloadBufferWritep = m_owner.m_offloadBufferWritep;
|
||||
// End of offload buffer
|
||||
uint32_t* const m_offloadBufferEndp = m_owner.m_offloadBufferEndp;
|
||||
#endif
|
||||
|
||||
// Equivalent to 'this' but is of the sub-type 'T_Derived*'. Use 'self()->'
|
||||
// to access duck-typed functions to avoid a virtual function call.
|
||||
inline T_Buffer* self() { return static_cast<T_Buffer*>(this); }
|
||||
|
||||
explicit VerilatedTraceBuffer(T_Trace& owner);
|
||||
virtual ~VerilatedTraceBuffer() = default;
|
||||
|
||||
public:
|
||||
//=========================================================================
|
||||
// Hot path internal interface to Verilator generated code
|
||||
|
||||
@@ -281,108 +393,112 @@ public:
|
||||
// these here, but we cannot afford dynamic dispatch for calling these as
|
||||
// this is very hot code during tracing.
|
||||
|
||||
// duck-typed void emitBit(vluint32_t code, CData newval) = 0;
|
||||
// duck-typed void emitCData(vluint32_t code, CData newval, int bits) = 0;
|
||||
// duck-typed void emitSData(vluint32_t code, SData newval, int bits) = 0;
|
||||
// duck-typed void emitIData(vluint32_t code, IData newval, int bits) = 0;
|
||||
// duck-typed void emitQData(vluint32_t code, QData newval, int bits) = 0;
|
||||
// duck-typed void emitWData(vluint32_t code, const WData* newvalp, int bits) = 0;
|
||||
// duck-typed void emitDouble(vluint32_t code, double newval) = 0;
|
||||
// duck-typed void emitBit(uint32_t code, CData newval) = 0;
|
||||
// duck-typed void emitCData(uint32_t code, CData newval, int bits) = 0;
|
||||
// duck-typed void emitSData(uint32_t code, SData newval, int bits) = 0;
|
||||
// duck-typed void emitIData(uint32_t code, IData newval, int bits) = 0;
|
||||
// duck-typed void emitQData(uint32_t code, QData newval, int bits) = 0;
|
||||
// duck-typed void emitWData(uint32_t code, const WData* newvalp, int bits) = 0;
|
||||
// duck-typed void emitDouble(uint32_t code, double newval) = 0;
|
||||
|
||||
vluint32_t* oldp(vluint32_t code) { return m_sigs_oldvalp + code; }
|
||||
VL_ATTR_ALWINLINE inline uint32_t* oldp(uint32_t code) { return m_sigs_oldvalp + code; }
|
||||
|
||||
// Write to previous value buffer value and emit trace entry.
|
||||
void fullBit(vluint32_t* oldp, CData newval);
|
||||
void fullCData(vluint32_t* oldp, CData newval, int bits);
|
||||
void fullSData(vluint32_t* oldp, SData newval, int bits);
|
||||
void fullIData(vluint32_t* oldp, IData newval, int bits);
|
||||
void fullQData(vluint32_t* oldp, QData newval, int bits);
|
||||
void fullWData(vluint32_t* oldp, const WData* newvalp, int bits);
|
||||
void fullDouble(vluint32_t* oldp, double newval);
|
||||
void fullBit(uint32_t* oldp, CData newval);
|
||||
void fullCData(uint32_t* oldp, CData newval, int bits);
|
||||
void fullSData(uint32_t* oldp, SData newval, int bits);
|
||||
void fullIData(uint32_t* oldp, IData newval, int bits);
|
||||
void fullQData(uint32_t* oldp, QData newval, int bits);
|
||||
void fullWData(uint32_t* oldp, const WData* newvalp, int bits);
|
||||
void fullDouble(uint32_t* oldp, double newval);
|
||||
|
||||
#ifdef VL_TRACE_THREADED
|
||||
// Threaded tracing. Just dump everything in the trace buffer
|
||||
inline void chgBit(vluint32_t code, CData newval) {
|
||||
m_traceBufferWritep[0] = VerilatedTraceCommand::CHG_BIT_0 | newval;
|
||||
m_traceBufferWritep[1] = code;
|
||||
m_traceBufferWritep += 2;
|
||||
VL_DEBUG_IF(assert(m_traceBufferWritep <= m_traceBufferEndp););
|
||||
#ifdef VL_TRACE_OFFLOAD
|
||||
// Offloaded tracing. Just dump everything in the offload buffer
|
||||
inline void chgBit(uint32_t code, CData newval) {
|
||||
m_offloadBufferWritep[0] = VerilatedTraceOffloadCommand::CHG_BIT_0 | newval;
|
||||
m_offloadBufferWritep[1] = code;
|
||||
m_offloadBufferWritep += 2;
|
||||
VL_DEBUG_IF(assert(m_offloadBufferWritep <= m_offloadBufferEndp););
|
||||
}
|
||||
inline void chgCData(vluint32_t code, CData newval, int bits) {
|
||||
m_traceBufferWritep[0] = (bits << 4) | VerilatedTraceCommand::CHG_CDATA;
|
||||
m_traceBufferWritep[1] = code;
|
||||
m_traceBufferWritep[2] = newval;
|
||||
m_traceBufferWritep += 3;
|
||||
VL_DEBUG_IF(assert(m_traceBufferWritep <= m_traceBufferEndp););
|
||||
inline void chgCData(uint32_t code, CData newval, int bits) {
|
||||
m_offloadBufferWritep[0] = (bits << 4) | VerilatedTraceOffloadCommand::CHG_CDATA;
|
||||
m_offloadBufferWritep[1] = code;
|
||||
m_offloadBufferWritep[2] = newval;
|
||||
m_offloadBufferWritep += 3;
|
||||
VL_DEBUG_IF(assert(m_offloadBufferWritep <= m_offloadBufferEndp););
|
||||
}
|
||||
inline void chgSData(vluint32_t code, SData newval, int bits) {
|
||||
m_traceBufferWritep[0] = (bits << 4) | VerilatedTraceCommand::CHG_SDATA;
|
||||
m_traceBufferWritep[1] = code;
|
||||
m_traceBufferWritep[2] = newval;
|
||||
m_traceBufferWritep += 3;
|
||||
VL_DEBUG_IF(assert(m_traceBufferWritep <= m_traceBufferEndp););
|
||||
inline void chgSData(uint32_t code, SData newval, int bits) {
|
||||
m_offloadBufferWritep[0] = (bits << 4) | VerilatedTraceOffloadCommand::CHG_SDATA;
|
||||
m_offloadBufferWritep[1] = code;
|
||||
m_offloadBufferWritep[2] = newval;
|
||||
m_offloadBufferWritep += 3;
|
||||
VL_DEBUG_IF(assert(m_offloadBufferWritep <= m_offloadBufferEndp););
|
||||
}
|
||||
inline void chgIData(vluint32_t code, IData newval, int bits) {
|
||||
m_traceBufferWritep[0] = (bits << 4) | VerilatedTraceCommand::CHG_IDATA;
|
||||
m_traceBufferWritep[1] = code;
|
||||
m_traceBufferWritep[2] = newval;
|
||||
m_traceBufferWritep += 3;
|
||||
VL_DEBUG_IF(assert(m_traceBufferWritep <= m_traceBufferEndp););
|
||||
inline void chgIData(uint32_t code, IData newval, int bits) {
|
||||
m_offloadBufferWritep[0] = (bits << 4) | VerilatedTraceOffloadCommand::CHG_IDATA;
|
||||
m_offloadBufferWritep[1] = code;
|
||||
m_offloadBufferWritep[2] = newval;
|
||||
m_offloadBufferWritep += 3;
|
||||
VL_DEBUG_IF(assert(m_offloadBufferWritep <= m_offloadBufferEndp););
|
||||
}
|
||||
inline void chgQData(vluint32_t code, QData newval, int bits) {
|
||||
m_traceBufferWritep[0] = (bits << 4) | VerilatedTraceCommand::CHG_QDATA;
|
||||
m_traceBufferWritep[1] = code;
|
||||
*reinterpret_cast<QData*>(m_traceBufferWritep + 2) = newval;
|
||||
m_traceBufferWritep += 4;
|
||||
VL_DEBUG_IF(assert(m_traceBufferWritep <= m_traceBufferEndp););
|
||||
inline void chgQData(uint32_t code, QData newval, int bits) {
|
||||
m_offloadBufferWritep[0] = (bits << 4) | VerilatedTraceOffloadCommand::CHG_QDATA;
|
||||
m_offloadBufferWritep[1] = code;
|
||||
*reinterpret_cast<QData*>(m_offloadBufferWritep + 2) = newval;
|
||||
m_offloadBufferWritep += 4;
|
||||
VL_DEBUG_IF(assert(m_offloadBufferWritep <= m_offloadBufferEndp););
|
||||
}
|
||||
inline void chgWData(vluint32_t code, const WData* newvalp, int bits) {
|
||||
m_traceBufferWritep[0] = (bits << 4) | VerilatedTraceCommand::CHG_WDATA;
|
||||
m_traceBufferWritep[1] = code;
|
||||
m_traceBufferWritep += 2;
|
||||
for (int i = 0; i < (bits + 31) / 32; ++i) { *m_traceBufferWritep++ = newvalp[i]; }
|
||||
VL_DEBUG_IF(assert(m_traceBufferWritep <= m_traceBufferEndp););
|
||||
inline void chgWData(uint32_t code, const WData* newvalp, int bits) {
|
||||
m_offloadBufferWritep[0] = (bits << 4) | VerilatedTraceOffloadCommand::CHG_WDATA;
|
||||
m_offloadBufferWritep[1] = code;
|
||||
m_offloadBufferWritep += 2;
|
||||
for (int i = 0; i < (bits + 31) / 32; ++i) { *m_offloadBufferWritep++ = newvalp[i]; }
|
||||
VL_DEBUG_IF(assert(m_offloadBufferWritep <= m_offloadBufferEndp););
|
||||
}
|
||||
inline void chgDouble(vluint32_t code, double newval) {
|
||||
m_traceBufferWritep[0] = VerilatedTraceCommand::CHG_DOUBLE;
|
||||
m_traceBufferWritep[1] = code;
|
||||
inline void chgDouble(uint32_t code, double newval) {
|
||||
m_offloadBufferWritep[0] = VerilatedTraceOffloadCommand::CHG_DOUBLE;
|
||||
m_offloadBufferWritep[1] = code;
|
||||
// cppcheck-suppress invalidPointerCast
|
||||
*reinterpret_cast<double*>(m_traceBufferWritep + 2) = newval;
|
||||
m_traceBufferWritep += 4;
|
||||
VL_DEBUG_IF(assert(m_traceBufferWritep <= m_traceBufferEndp););
|
||||
*reinterpret_cast<double*>(m_offloadBufferWritep + 2) = newval;
|
||||
m_offloadBufferWritep += 4;
|
||||
VL_DEBUG_IF(assert(m_offloadBufferWritep <= m_offloadBufferEndp););
|
||||
}
|
||||
|
||||
#define CHG(name) chg##name##Impl
|
||||
#else
|
||||
#define CHG(name) chg##name
|
||||
#define chgBit chgBitImpl
|
||||
#define chgCData chgCDataImpl
|
||||
#define chgSData chgSDataImpl
|
||||
#define chgIData chgIDataImpl
|
||||
#define chgQData chgQDataImpl
|
||||
#define chgWData chgWDataImpl
|
||||
#define chgDouble chgDoubleImpl
|
||||
#endif
|
||||
|
||||
// In non-threaded mode, these are called directly by the trace callbacks,
|
||||
// and are called chg*. In threaded mode, they are called by the worker
|
||||
// In non-offload mode, these are called directly by the trace callbacks,
|
||||
// and are called chg*. In offload mode, they are called by the worker
|
||||
// thread and are called chg*Impl
|
||||
|
||||
// Check previous dumped value of signal. If changed, then emit trace entry
|
||||
inline void CHG(Bit)(vluint32_t* oldp, CData newval) {
|
||||
const vluint32_t diff = *oldp ^ newval;
|
||||
VL_ATTR_ALWINLINE inline void chgBit(uint32_t* oldp, CData newval) {
|
||||
const uint32_t diff = *oldp ^ newval;
|
||||
if (VL_UNLIKELY(diff)) fullBit(oldp, newval);
|
||||
}
|
||||
inline void CHG(CData)(vluint32_t* oldp, CData newval, int bits) {
|
||||
const vluint32_t diff = *oldp ^ newval;
|
||||
VL_ATTR_ALWINLINE inline void chgCData(uint32_t* oldp, CData newval, int bits) {
|
||||
const uint32_t diff = *oldp ^ newval;
|
||||
if (VL_UNLIKELY(diff)) fullCData(oldp, newval, bits);
|
||||
}
|
||||
inline void CHG(SData)(vluint32_t* oldp, SData newval, int bits) {
|
||||
const vluint32_t diff = *oldp ^ newval;
|
||||
VL_ATTR_ALWINLINE inline void chgSData(uint32_t* oldp, SData newval, int bits) {
|
||||
const uint32_t diff = *oldp ^ newval;
|
||||
if (VL_UNLIKELY(diff)) fullSData(oldp, newval, bits);
|
||||
}
|
||||
inline void CHG(IData)(vluint32_t* oldp, IData newval, int bits) {
|
||||
const vluint32_t diff = *oldp ^ newval;
|
||||
VL_ATTR_ALWINLINE inline void chgIData(uint32_t* oldp, IData newval, int bits) {
|
||||
const uint32_t diff = *oldp ^ newval;
|
||||
if (VL_UNLIKELY(diff)) fullIData(oldp, newval, bits);
|
||||
}
|
||||
inline void CHG(QData)(vluint32_t* oldp, QData newval, int bits) {
|
||||
const vluint64_t diff = *reinterpret_cast<QData*>(oldp) ^ newval;
|
||||
VL_ATTR_ALWINLINE inline void chgQData(uint32_t* oldp, QData newval, int bits) {
|
||||
const uint64_t diff = *reinterpret_cast<QData*>(oldp) ^ newval;
|
||||
if (VL_UNLIKELY(diff)) fullQData(oldp, newval, bits);
|
||||
}
|
||||
inline void CHG(WData)(vluint32_t* oldp, const WData* newvalp, int bits) {
|
||||
VL_ATTR_ALWINLINE inline void chgWData(uint32_t* oldp, const WData* newvalp, int bits) {
|
||||
for (int i = 0; i < (bits + 31) / 32; ++i) {
|
||||
if (VL_UNLIKELY(oldp[i] ^ newvalp[i])) {
|
||||
fullWData(oldp, newvalp, bits);
|
||||
@@ -390,11 +506,20 @@ public:
|
||||
}
|
||||
}
|
||||
}
|
||||
inline void CHG(Double)(vluint32_t* oldp, double newval) {
|
||||
VL_ATTR_ALWINLINE inline void chgDouble(uint32_t* oldp, double newval) {
|
||||
// cppcheck-suppress invalidPointerCast
|
||||
if (VL_UNLIKELY(*reinterpret_cast<double*>(oldp) != newval)) fullDouble(oldp, newval);
|
||||
}
|
||||
|
||||
#undef CHG
|
||||
#ifdef VL_TRACE_OFFLOAD
|
||||
#undef chgBit
|
||||
#undef chgCData
|
||||
#undef chgSData
|
||||
#undef chgIData
|
||||
#undef chgQData
|
||||
#undef chgWData
|
||||
#undef chgDouble
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // guard
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
//
|
||||
// Code available from: https://verilator.org
|
||||
//
|
||||
// Copyright 2001-2021 by Wilson Snyder. This program is free software; you
|
||||
// Copyright 2001-2022 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,688 +0,0 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//=============================================================================
|
||||
//
|
||||
// Code available from: https://verilator.org
|
||||
//
|
||||
// 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.
|
||||
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
//
|
||||
//=============================================================================
|
||||
///
|
||||
/// \file
|
||||
/// \brief Verilated common-format tracing implementation code
|
||||
///
|
||||
/// This file must be compiled and linked against all Verilated objects
|
||||
/// that use --trace.
|
||||
///
|
||||
/// Use "verilator --trace" to add this to the Makefile for the linker.
|
||||
///
|
||||
//=============================================================================
|
||||
|
||||
// clang-format off
|
||||
|
||||
#ifndef VL_CPPCHECK
|
||||
#ifndef VL_DERIVED_T
|
||||
# error "This file should be included in trace format implementations"
|
||||
#endif
|
||||
|
||||
#include "verilated_intrinsics.h"
|
||||
#include "verilated_trace.h"
|
||||
|
||||
#if 0
|
||||
# include <iostream>
|
||||
# define VL_TRACE_THREAD_DEBUG(msg) std::cout << "TRACE THREAD: " << msg << std::endl
|
||||
#else
|
||||
# define VL_TRACE_THREAD_DEBUG(msg)
|
||||
#endif
|
||||
|
||||
// clang-format on
|
||||
|
||||
//=============================================================================
|
||||
// Static utility functions
|
||||
|
||||
static double timescaleToDouble(const char* unitp) {
|
||||
char* endp = nullptr;
|
||||
double value = std::strtod(unitp, &endp);
|
||||
// On error so we allow just "ns" to return 1e-9.
|
||||
if (value == 0.0 && endp == unitp) value = 1;
|
||||
unitp = endp;
|
||||
for (; *unitp && std::isspace(*unitp); unitp++) {}
|
||||
switch (*unitp) {
|
||||
case 's': value *= 1e0; break;
|
||||
case 'm': value *= 1e-3; break;
|
||||
case 'u': value *= 1e-6; break;
|
||||
case 'n': value *= 1e-9; break;
|
||||
case 'p': value *= 1e-12; break;
|
||||
case 'f': value *= 1e-15; break;
|
||||
case 'a': value *= 1e-18; break;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
static std::string doubleToTimescale(double value) {
|
||||
const char* suffixp = "s";
|
||||
// clang-format off
|
||||
if (value >= 1e0) { suffixp = "s"; value *= 1e0; }
|
||||
else if (value >= 1e-3 ) { suffixp = "ms"; value *= 1e3; }
|
||||
else if (value >= 1e-6 ) { suffixp = "us"; value *= 1e6; }
|
||||
else if (value >= 1e-9 ) { suffixp = "ns"; value *= 1e9; }
|
||||
else if (value >= 1e-12) { suffixp = "ps"; value *= 1e12; }
|
||||
else if (value >= 1e-15) { suffixp = "fs"; value *= 1e15; }
|
||||
else if (value >= 1e-18) { suffixp = "as"; value *= 1e18; }
|
||||
// clang-format on
|
||||
char valuestr[100];
|
||||
VL_SNPRINTF(valuestr, 100, "%0.0f%s", value, suffixp);
|
||||
return valuestr; // Gets converted to string, so no ref to stack
|
||||
}
|
||||
|
||||
#ifdef VL_TRACE_THREADED
|
||||
//=========================================================================
|
||||
// Buffer management
|
||||
|
||||
template <> vluint32_t* VerilatedTrace<VL_DERIVED_T>::getTraceBuffer() {
|
||||
vluint32_t* bufferp;
|
||||
// Some jitter is expected, so some number of alternative trace buffers are
|
||||
// required, but don't allocate more than 8 buffers.
|
||||
if (m_numTraceBuffers < 8) {
|
||||
// Allocate a new buffer if none is available
|
||||
if (!m_buffersFromWorker.tryGet(bufferp)) {
|
||||
++m_numTraceBuffers;
|
||||
// Note: over allocate a bit so pointer comparison is well defined
|
||||
// if we overflow only by a small amount
|
||||
bufferp = new vluint32_t[m_traceBufferSize + 16];
|
||||
}
|
||||
} else {
|
||||
// Block until a buffer becomes available
|
||||
bufferp = m_buffersFromWorker.get();
|
||||
}
|
||||
return bufferp;
|
||||
}
|
||||
|
||||
template <> void VerilatedTrace<VL_DERIVED_T>::waitForBuffer(const vluint32_t* buffp) {
|
||||
// Slow path code only called on flush/shutdown, so use a simple algorithm.
|
||||
// Collect buffers from worker and stash them until we get the one we want.
|
||||
std::deque<vluint32_t*> stash;
|
||||
do { stash.push_back(m_buffersFromWorker.get()); } while (stash.back() != buffp);
|
||||
// Now put them back in the queue, in the original order.
|
||||
while (!stash.empty()) {
|
||||
m_buffersFromWorker.put_front(stash.back());
|
||||
stash.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
// Worker thread
|
||||
|
||||
template <> void VerilatedTrace<VL_DERIVED_T>::workerThreadMain() {
|
||||
bool shutdown = false;
|
||||
|
||||
do {
|
||||
vluint32_t* const bufferp = m_buffersToWorker.get();
|
||||
|
||||
VL_TRACE_THREAD_DEBUG("");
|
||||
VL_TRACE_THREAD_DEBUG("Got buffer: " << bufferp);
|
||||
|
||||
const vluint32_t* readp = bufferp;
|
||||
|
||||
while (true) {
|
||||
const vluint32_t cmd = readp[0];
|
||||
const vluint32_t top = cmd >> 4;
|
||||
// Always set this up, as it is almost always needed
|
||||
vluint32_t* const oldp = m_sigs_oldvalp + readp[1];
|
||||
// Note this increment needs to be undone on commands which do not
|
||||
// actually contain a code, but those are the rare cases.
|
||||
readp += 2;
|
||||
|
||||
switch (cmd & 0xF) {
|
||||
//===
|
||||
// CHG_* commands
|
||||
case VerilatedTraceCommand::CHG_BIT_0:
|
||||
VL_TRACE_THREAD_DEBUG("Command CHG_BIT_0 " << top);
|
||||
chgBitImpl(oldp, 0);
|
||||
continue;
|
||||
case VerilatedTraceCommand::CHG_BIT_1:
|
||||
VL_TRACE_THREAD_DEBUG("Command CHG_BIT_1 " << top);
|
||||
chgBitImpl(oldp, 1);
|
||||
continue;
|
||||
case VerilatedTraceCommand::CHG_CDATA:
|
||||
VL_TRACE_THREAD_DEBUG("Command CHG_CDATA " << top);
|
||||
// Bits stored in bottom byte of command
|
||||
chgCDataImpl(oldp, *readp, top);
|
||||
readp += 1;
|
||||
continue;
|
||||
case VerilatedTraceCommand::CHG_SDATA:
|
||||
VL_TRACE_THREAD_DEBUG("Command CHG_SDATA " << top);
|
||||
// Bits stored in bottom byte of command
|
||||
chgSDataImpl(oldp, *readp, top);
|
||||
readp += 1;
|
||||
continue;
|
||||
case VerilatedTraceCommand::CHG_IDATA:
|
||||
VL_TRACE_THREAD_DEBUG("Command CHG_IDATA " << top);
|
||||
// Bits stored in bottom byte of command
|
||||
chgIDataImpl(oldp, *readp, top);
|
||||
readp += 1;
|
||||
continue;
|
||||
case VerilatedTraceCommand::CHG_QDATA:
|
||||
VL_TRACE_THREAD_DEBUG("Command CHG_QDATA " << top);
|
||||
// Bits stored in bottom byte of command
|
||||
chgQDataImpl(oldp, *reinterpret_cast<const QData*>(readp), top);
|
||||
readp += 2;
|
||||
continue;
|
||||
case VerilatedTraceCommand::CHG_WDATA:
|
||||
VL_TRACE_THREAD_DEBUG("Command CHG_WDATA " << top);
|
||||
chgWDataImpl(oldp, readp, top);
|
||||
readp += VL_WORDS_I(top);
|
||||
continue;
|
||||
case VerilatedTraceCommand::CHG_DOUBLE:
|
||||
VL_TRACE_THREAD_DEBUG("Command CHG_DOUBLE " << top);
|
||||
chgDoubleImpl(oldp, *reinterpret_cast<const double*>(readp));
|
||||
readp += 2;
|
||||
continue;
|
||||
|
||||
//===
|
||||
// Rare commands
|
||||
case VerilatedTraceCommand::TIME_CHANGE:
|
||||
VL_TRACE_THREAD_DEBUG("Command TIME_CHANGE " << top);
|
||||
readp -= 1; // No code in this command, undo increment
|
||||
emitTimeChange(*reinterpret_cast<const vluint64_t*>(readp));
|
||||
readp += 2;
|
||||
continue;
|
||||
|
||||
//===
|
||||
// Commands ending this buffer
|
||||
case VerilatedTraceCommand::END: VL_TRACE_THREAD_DEBUG("Command END"); break;
|
||||
case VerilatedTraceCommand::SHUTDOWN:
|
||||
VL_TRACE_THREAD_DEBUG("Command SHUTDOWN");
|
||||
shutdown = true;
|
||||
break;
|
||||
|
||||
//===
|
||||
// Unknown command
|
||||
default: { // LCOV_EXCL_START
|
||||
VL_TRACE_THREAD_DEBUG("Command UNKNOWN");
|
||||
VL_PRINTF_MT("Trace command: 0x%08x\n", cmd);
|
||||
VL_FATAL_MT(__FILE__, __LINE__, "", "Unknown trace command");
|
||||
break;
|
||||
} // LCOV_EXCL_STOP
|
||||
}
|
||||
|
||||
// The above switch will execute 'continue' when necessary,
|
||||
// so if we ever reach here, we are done with the buffer.
|
||||
break;
|
||||
}
|
||||
|
||||
VL_TRACE_THREAD_DEBUG("Returning buffer");
|
||||
|
||||
// Return buffer
|
||||
m_buffersFromWorker.put(bufferp);
|
||||
} while (VL_LIKELY(!shutdown));
|
||||
}
|
||||
|
||||
template <> void VerilatedTrace<VL_DERIVED_T>::shutdownWorker() {
|
||||
// If the worker thread is not running, done..
|
||||
if (!m_workerThread) return;
|
||||
|
||||
// Hand an buffer with a shutdown command to the worker thread
|
||||
vluint32_t* const bufferp = getTraceBuffer();
|
||||
bufferp[0] = VerilatedTraceCommand::SHUTDOWN;
|
||||
m_buffersToWorker.put(bufferp);
|
||||
// Wait for it to return
|
||||
waitForBuffer(bufferp);
|
||||
// Join the thread and delete it
|
||||
m_workerThread->join();
|
||||
m_workerThread.reset(nullptr);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//=============================================================================
|
||||
// Life cycle
|
||||
|
||||
template <> void VerilatedTrace<VL_DERIVED_T>::closeBase() {
|
||||
#ifdef VL_TRACE_THREADED
|
||||
shutdownWorker();
|
||||
while (m_numTraceBuffers) {
|
||||
delete[] m_buffersFromWorker.get();
|
||||
--m_numTraceBuffers;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
template <> void VerilatedTrace<VL_DERIVED_T>::flushBase() {
|
||||
#ifdef VL_TRACE_THREADED
|
||||
// Hand an empty buffer to the worker thread
|
||||
vluint32_t* const bufferp = getTraceBuffer();
|
||||
*bufferp = VerilatedTraceCommand::END;
|
||||
m_buffersToWorker.put(bufferp);
|
||||
// Wait for it to be returned. As the processing is in-order,
|
||||
// this ensures all previous buffers have been processed.
|
||||
waitForBuffer(bufferp);
|
||||
#endif
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
// Callbacks to run on global events
|
||||
|
||||
template <> void VerilatedTrace<VL_DERIVED_T>::onFlush(void* selfp) {
|
||||
// This calls 'flush' on the derived classo (which must then get any mutex)
|
||||
reinterpret_cast<VL_DERIVED_T*>(selfp)->flush();
|
||||
}
|
||||
|
||||
template <> void VerilatedTrace<VL_DERIVED_T>::onExit(void* selfp) {
|
||||
// This calls 'close' on the derived class (which must then get any mutex)
|
||||
reinterpret_cast<VL_DERIVED_T*>(selfp)->close();
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
// VerilatedTrace
|
||||
|
||||
template <>
|
||||
VerilatedTrace<VL_DERIVED_T>::VerilatedTrace()
|
||||
: m_sigs_oldvalp{nullptr}
|
||||
, m_timeLastDump{0}
|
||||
, m_fullDump{true}
|
||||
, m_nextCode{0}
|
||||
, m_numSignals{0}
|
||||
, m_maxBits{0}
|
||||
, m_scopeEscape{'.'}
|
||||
, m_timeRes{1e-9}
|
||||
, m_timeUnit {
|
||||
1e-9
|
||||
}
|
||||
#ifdef VL_TRACE_THREADED
|
||||
, m_numTraceBuffers { 0 }
|
||||
#endif
|
||||
{
|
||||
set_time_unit(Verilated::threadContextp()->timeunitString());
|
||||
set_time_resolution(Verilated::threadContextp()->timeprecisionString());
|
||||
}
|
||||
|
||||
template <> VerilatedTrace<VL_DERIVED_T>::~VerilatedTrace() {
|
||||
if (m_sigs_oldvalp) VL_DO_CLEAR(delete[] m_sigs_oldvalp, m_sigs_oldvalp = nullptr);
|
||||
Verilated::removeFlushCb(VerilatedTrace<VL_DERIVED_T>::onFlush, this);
|
||||
Verilated::removeExitCb(VerilatedTrace<VL_DERIVED_T>::onExit, this);
|
||||
#ifdef VL_TRACE_THREADED
|
||||
closeBase();
|
||||
#endif
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
// Internals available to format specific implementations
|
||||
|
||||
template <> void VerilatedTrace<VL_DERIVED_T>::traceInit() VL_MT_UNSAFE {
|
||||
// Note: It is possible to re-open a trace file (VCD in particular),
|
||||
// so we must reset the next code here, but it must have the same number
|
||||
// of codes on re-open
|
||||
const vluint32_t expectedCodes = nextCode();
|
||||
m_nextCode = 1;
|
||||
m_numSignals = 0;
|
||||
m_maxBits = 0;
|
||||
|
||||
// Call all initialize callbacks, which will:
|
||||
// - Call decl* for each signal
|
||||
// - Store the base code
|
||||
for (vluint32_t i = 0; i < m_initCbs.size(); ++i) {
|
||||
const CallbackRecord& cbr = m_initCbs[i];
|
||||
cbr.m_initCb(cbr.m_userp, self(), nextCode());
|
||||
}
|
||||
|
||||
if (expectedCodes && nextCode() != expectedCodes) {
|
||||
VL_FATAL_MT(__FILE__, __LINE__, "",
|
||||
"Reopening trace file with different number of signals");
|
||||
}
|
||||
|
||||
// Now that we know the number of codes, allocate space for the buffer
|
||||
// holding previous signal values.
|
||||
if (!m_sigs_oldvalp) m_sigs_oldvalp = new vluint32_t[nextCode()];
|
||||
|
||||
// Set callback so flush/abort will flush this file
|
||||
Verilated::addFlushCb(VerilatedTrace<VL_DERIVED_T>::onFlush, this);
|
||||
Verilated::addExitCb(VerilatedTrace<VL_DERIVED_T>::onExit, this);
|
||||
|
||||
#ifdef VL_TRACE_THREADED
|
||||
// Compute trace buffer size. we need to be able to store a new value for
|
||||
// each signal, which is 'nextCode()' entries after the init callbacks
|
||||
// above have been run, plus up to 2 more words of metadata per signal,
|
||||
// plus fixed overhead of 1 for a termination flag and 3 for a time stamp
|
||||
// update.
|
||||
m_traceBufferSize = nextCode() + numSignals() * 2 + 4;
|
||||
|
||||
// Start the worker thread
|
||||
m_workerThread.reset(new std::thread{&VerilatedTrace<VL_DERIVED_T>::workerThreadMain, this});
|
||||
#endif
|
||||
}
|
||||
|
||||
template <>
|
||||
void VerilatedTrace<VL_DERIVED_T>::declCode(vluint32_t code, vluint32_t bits, bool tri) {
|
||||
if (VL_UNCOVERABLE(!code)) {
|
||||
VL_FATAL_MT(__FILE__, __LINE__, "", "Internal: internal trace problem, code 0 is illegal");
|
||||
}
|
||||
// Note: The tri-state flag is not used by Verilator, but is here for
|
||||
// compatibility with some foreign code.
|
||||
int codesNeeded = VL_WORDS_I(bits);
|
||||
if (tri) codesNeeded *= 2;
|
||||
m_nextCode = std::max(m_nextCode, code + codesNeeded);
|
||||
++m_numSignals;
|
||||
m_maxBits = std::max(m_maxBits, bits);
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
// Internals available to format specific implementations
|
||||
|
||||
template <> std::string VerilatedTrace<VL_DERIVED_T>::timeResStr() const {
|
||||
return doubleToTimescale(m_timeRes);
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
// External interface to client code
|
||||
|
||||
template <> void VerilatedTrace<VL_DERIVED_T>::set_time_unit(const char* unitp) VL_MT_SAFE {
|
||||
m_timeUnit = timescaleToDouble(unitp);
|
||||
}
|
||||
template <> void VerilatedTrace<VL_DERIVED_T>::set_time_unit(const std::string& unit) VL_MT_SAFE {
|
||||
set_time_unit(unit.c_str());
|
||||
}
|
||||
template <> void VerilatedTrace<VL_DERIVED_T>::set_time_resolution(const char* unitp) VL_MT_SAFE {
|
||||
m_timeRes = timescaleToDouble(unitp);
|
||||
}
|
||||
template <>
|
||||
void VerilatedTrace<VL_DERIVED_T>::set_time_resolution(const std::string& unit) VL_MT_SAFE {
|
||||
set_time_resolution(unit.c_str());
|
||||
}
|
||||
|
||||
template <>
|
||||
void VerilatedTrace<VL_DERIVED_T>::dump(vluint64_t timeui) VL_MT_SAFE_EXCLUDES(m_mutex) {
|
||||
// Not really VL_MT_SAFE but more VL_MT_UNSAFE_ONE.
|
||||
// This does get the mutex, but if multiple threads are trying to dump
|
||||
// chances are the data being dumped will have other problems
|
||||
const VerilatedLockGuard lock{m_mutex};
|
||||
if (VL_UNCOVERABLE(m_timeLastDump && timeui <= m_timeLastDump)) { // LCOV_EXCL_START
|
||||
VL_PRINTF_MT("%%Warning: previous dump at t=%" VL_PRI64 "u, requesting t=%" VL_PRI64
|
||||
"u, dump call ignored\n",
|
||||
m_timeLastDump, timeui);
|
||||
return;
|
||||
} // LCOV_EXCL_STOP
|
||||
m_timeLastDump = timeui;
|
||||
|
||||
Verilated::quiesce();
|
||||
|
||||
// Call hook for format specific behaviour
|
||||
if (VL_UNLIKELY(m_fullDump)) {
|
||||
if (!preFullDump()) return;
|
||||
} else {
|
||||
if (!preChangeDump()) return;
|
||||
}
|
||||
|
||||
#ifdef VL_TRACE_THREADED
|
||||
// Currently only incremental dumps run on the worker thread
|
||||
vluint32_t* bufferp = nullptr;
|
||||
if (VL_LIKELY(!m_fullDump)) {
|
||||
// Get the trace buffer we are about to fill
|
||||
bufferp = getTraceBuffer();
|
||||
m_traceBufferWritep = bufferp;
|
||||
m_traceBufferEndp = bufferp + m_traceBufferSize;
|
||||
|
||||
// Tell worker to update time point
|
||||
m_traceBufferWritep[0] = VerilatedTraceCommand::TIME_CHANGE;
|
||||
*reinterpret_cast<vluint64_t*>(m_traceBufferWritep + 1) = timeui;
|
||||
m_traceBufferWritep += 3;
|
||||
} else {
|
||||
// Update time point
|
||||
flushBase();
|
||||
emitTimeChange(timeui);
|
||||
}
|
||||
#else
|
||||
// Update time point
|
||||
emitTimeChange(timeui);
|
||||
#endif
|
||||
|
||||
// Run the callbacks
|
||||
if (VL_UNLIKELY(m_fullDump)) {
|
||||
m_fullDump = false; // No more need for next dump to be full
|
||||
for (vluint32_t i = 0; i < m_fullCbs.size(); ++i) {
|
||||
const CallbackRecord& cbr = m_fullCbs[i];
|
||||
cbr.m_dumpCb(cbr.m_userp, self());
|
||||
}
|
||||
} else {
|
||||
for (vluint32_t i = 0; i < m_chgCbs.size(); ++i) {
|
||||
const CallbackRecord& cbr = m_chgCbs[i];
|
||||
cbr.m_dumpCb(cbr.m_userp, self());
|
||||
}
|
||||
}
|
||||
|
||||
for (vluint32_t i = 0; i < m_cleanupCbs.size(); ++i) {
|
||||
const CallbackRecord& cbr = m_cleanupCbs[i];
|
||||
cbr.m_dumpCb(cbr.m_userp, self());
|
||||
}
|
||||
|
||||
#ifdef VL_TRACE_THREADED
|
||||
if (VL_LIKELY(bufferp)) {
|
||||
// Mark end of the trace buffer we just filled
|
||||
*m_traceBufferWritep++ = VerilatedTraceCommand::END;
|
||||
|
||||
// Assert no buffer overflow
|
||||
assert(m_traceBufferWritep - bufferp <= m_traceBufferSize);
|
||||
|
||||
// Pass it to the worker thread
|
||||
m_buffersToWorker.put(bufferp);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
// Non-hot path internal interface to Verilator generated code
|
||||
|
||||
template <>
|
||||
void VerilatedTrace<VL_DERIVED_T>::addCallbackRecord(std::vector<CallbackRecord>& cbVec,
|
||||
CallbackRecord& cbRec)
|
||||
VL_MT_SAFE_EXCLUDES(m_mutex) {
|
||||
const VerilatedLockGuard lock{m_mutex};
|
||||
if (VL_UNCOVERABLE(timeLastDump() != 0)) { // LCOV_EXCL_START
|
||||
const std::string msg = (std::string{"Internal: "} + __FILE__ + "::" + __FUNCTION__
|
||||
+ " called with already open file");
|
||||
VL_FATAL_MT(__FILE__, __LINE__, "", msg.c_str());
|
||||
} // LCOV_EXCL_STOP
|
||||
cbVec.push_back(cbRec);
|
||||
}
|
||||
|
||||
template <> void VerilatedTrace<VL_DERIVED_T>::addInitCb(initCb_t cb, void* userp) VL_MT_SAFE {
|
||||
CallbackRecord cbr{cb, userp};
|
||||
addCallbackRecord(m_initCbs, cbr);
|
||||
}
|
||||
template <> void VerilatedTrace<VL_DERIVED_T>::addFullCb(dumpCb_t cb, void* userp) VL_MT_SAFE {
|
||||
CallbackRecord cbr{cb, userp};
|
||||
addCallbackRecord(m_fullCbs, cbr);
|
||||
}
|
||||
template <> void VerilatedTrace<VL_DERIVED_T>::addChgCb(dumpCb_t cb, void* userp) VL_MT_SAFE {
|
||||
CallbackRecord cbr{cb, userp};
|
||||
addCallbackRecord(m_chgCbs, cbr);
|
||||
}
|
||||
template <> void VerilatedTrace<VL_DERIVED_T>::addCleanupCb(dumpCb_t cb, void* userp) VL_MT_SAFE {
|
||||
CallbackRecord cbr{cb, userp};
|
||||
addCallbackRecord(m_cleanupCbs, cbr);
|
||||
}
|
||||
template <> void VerilatedTrace<VL_DERIVED_T>::module(const std::string& name) VL_MT_UNSAFE {
|
||||
// Called via callbacks way above in call stack, which already hold m_mutex
|
||||
m_moduleName = name;
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
// Hot path internal interface to Verilator generated code
|
||||
|
||||
// These functions must write the new value back into the old value store,
|
||||
// and subsequently call the format specific emit* implementations. Note
|
||||
// that this file must be included in the format specific implementation, so
|
||||
// the emit* functions can be inlined for performance.
|
||||
|
||||
template <> void VerilatedTrace<VL_DERIVED_T>::fullBit(vluint32_t* oldp, CData newval) {
|
||||
*oldp = newval;
|
||||
self()->emitBit(oldp - m_sigs_oldvalp, newval);
|
||||
}
|
||||
|
||||
template <>
|
||||
void VerilatedTrace<VL_DERIVED_T>::fullCData(vluint32_t* oldp, CData newval, int bits) {
|
||||
*oldp = newval;
|
||||
self()->emitCData(oldp - m_sigs_oldvalp, newval, bits);
|
||||
}
|
||||
|
||||
template <>
|
||||
void VerilatedTrace<VL_DERIVED_T>::fullSData(vluint32_t* oldp, SData newval, int bits) {
|
||||
*oldp = newval;
|
||||
self()->emitSData(oldp - m_sigs_oldvalp, newval, bits);
|
||||
}
|
||||
|
||||
template <>
|
||||
void VerilatedTrace<VL_DERIVED_T>::fullIData(vluint32_t* oldp, IData newval, int bits) {
|
||||
*oldp = newval;
|
||||
self()->emitIData(oldp - m_sigs_oldvalp, newval, bits);
|
||||
}
|
||||
|
||||
template <>
|
||||
void VerilatedTrace<VL_DERIVED_T>::fullQData(vluint32_t* oldp, QData newval, int bits) {
|
||||
*reinterpret_cast<QData*>(oldp) = newval;
|
||||
self()->emitQData(oldp - m_sigs_oldvalp, newval, bits);
|
||||
}
|
||||
|
||||
template <>
|
||||
void VerilatedTrace<VL_DERIVED_T>::fullWData(vluint32_t* oldp, const WData* newvalp, int bits) {
|
||||
for (int i = 0; i < VL_WORDS_I(bits); ++i) oldp[i] = newvalp[i];
|
||||
self()->emitWData(oldp - m_sigs_oldvalp, newvalp, bits);
|
||||
}
|
||||
|
||||
template <> void VerilatedTrace<VL_DERIVED_T>::fullDouble(vluint32_t* oldp, double newval) {
|
||||
// cppcheck-suppress invalidPointerCast
|
||||
*reinterpret_cast<double*>(oldp) = newval;
|
||||
self()->emitDouble(oldp - m_sigs_oldvalp, newval);
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
// Primitives converting binary values to strings...
|
||||
|
||||
// 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.
|
||||
|
||||
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);
|
||||
const __m128i b = _mm_unpacklo_epi8(a, a);
|
||||
const __m128i c = _mm_shufflelo_epi16(b, 0);
|
||||
const __m128i m = _mm_set1_epi64x(0x0102040810204080);
|
||||
const __m128i d = _mm_cmpeq_epi8(_mm_and_si128(c, m), m);
|
||||
const __m128i result = _mm_sub_epi8(_mm_set1_epi8('0'), d);
|
||||
_mm_storel_epi64(reinterpret_cast<__m128i*>(dstp), result);
|
||||
#else
|
||||
dstp[0] = '0' | static_cast<char>((value >> 7) & 1);
|
||||
dstp[1] = '0' | static_cast<char>((value >> 6) & 1);
|
||||
dstp[2] = '0' | static_cast<char>((value >> 5) & 1);
|
||||
dstp[3] = '0' | static_cast<char>((value >> 4) & 1);
|
||||
dstp[4] = '0' | static_cast<char>((value >> 3) & 1);
|
||||
dstp[5] = '0' | static_cast<char>((value >> 2) & 1);
|
||||
dstp[6] = '0' | static_cast<char>((value >> 1) & 1);
|
||||
dstp[7] = '0' | static_cast<char>(value & 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
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
|
||||
// want the MSB of the input at the low address, so we will bit-reverse
|
||||
// at the same time.
|
||||
|
||||
// Put value in bottom of 128-bit register a[15:0] = value
|
||||
const __m128i a = _mm_cvtsi32_si128(value);
|
||||
// Interleave bytes with themselves
|
||||
// b[15: 0] = {2{a[ 7:0]}} == {2{value[ 7:0]}}
|
||||
// b[31:16] = {2{a[15:8]}} == {2{value[15:8]}}
|
||||
const __m128i b = _mm_unpacklo_epi8(a, a);
|
||||
// Shuffle bottom 64 bits, note swapping high bytes with low bytes
|
||||
// c[31: 0] = {2{b[31:16]}} == {4{value[15:8}}
|
||||
// c[63:32] = {2{b[15: 0]}} == {4{value[ 7:0}}
|
||||
const __m128i c = _mm_shufflelo_epi16(b, 0x05);
|
||||
// Shuffle whole register
|
||||
// d[ 63: 0] = {2{c[31: 0]}} == {8{value[15:8}}
|
||||
// d[126:54] = {2{c[63:32]}} == {8{value[ 7:0}}
|
||||
const __m128i d = _mm_shuffle_epi32(c, 0x50);
|
||||
// Test each bit within the bytes, this sets each byte lane to 0
|
||||
// if the bit for that lane is 0 and to 0xff if the bit is 1.
|
||||
const __m128i m = _mm_set1_epi64x(0x0102040810204080);
|
||||
const __m128i e = _mm_cmpeq_epi8(_mm_and_si128(d, m), m);
|
||||
// Convert to ASCII by subtracting the masks from ASCII '0':
|
||||
// '0' - 0 is '0', '0' - -1 is '1'
|
||||
const __m128i result = _mm_sub_epi8(_mm_set1_epi8('0'), e);
|
||||
// Store the 16 characters to the un-aligned buffer
|
||||
_mm_storeu_si128(reinterpret_cast<__m128i*>(dstp), result);
|
||||
#else
|
||||
cvtCDataToStr(dstp, value >> 8);
|
||||
cvtCDataToStr(dstp + 8, value);
|
||||
#endif
|
||||
}
|
||||
|
||||
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
|
||||
const __m256i a = _mm256_insert_epi32(_mm256_undefined_si256(), value, 0);
|
||||
const __m256i b = _mm256_permute4x64_epi64(a, 0);
|
||||
const __m256i s = _mm256_set_epi8(0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3);
|
||||
const __m256i c = _mm256_shuffle_epi8(b, s);
|
||||
const __m256i m = _mm256_set1_epi64x(0x0102040810204080);
|
||||
const __m256i d = _mm256_cmpeq_epi8(_mm256_and_si256(c, m), m);
|
||||
const __m256i result = _mm256_sub_epi8(_mm256_set1_epi8('0'), d);
|
||||
_mm256_storeu_si256(reinterpret_cast<__m256i*>(dstp), result);
|
||||
#else
|
||||
cvtSDataToStr(dstp, value >> 16);
|
||||
cvtSDataToStr(dstp + 16, value);
|
||||
#endif
|
||||
}
|
||||
|
||||
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("100s");
|
||||
SELF_CHECK_TS("10s");
|
||||
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
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user