mirror of
https://github.com/verilator/verilator.git
synced 2026-10-02 16:13:34 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
8f090176a6 | ||
|
|
43e8263d1f | ||
|
|
ac622f9db8 | ||
|
|
749a66b7a2 | ||
|
|
fc80ace6e4 | ||
|
|
b8f6b262e4 | ||
|
|
b64e89f7ed | ||
|
|
c3bec344a4 | ||
|
|
9731ec76e3 | ||
|
|
a9646cf45c | ||
|
|
5f597dd9fc | ||
|
|
7d57c3ca78 | ||
|
|
4739956cfe | ||
|
|
e202a6324a | ||
|
|
66d70c8b37 | ||
|
|
02aa639425 | ||
|
|
55da66164b | ||
|
|
2560fc867f | ||
|
|
f5c9deecb8 | ||
|
|
20af8a36a7 | ||
|
|
1c1c805b07 | ||
|
|
9029da5ab8 | ||
|
|
def7c8fe4d | ||
|
|
9184c4f501 | ||
|
|
44809f1843 | ||
|
|
87ced0cc3e | ||
|
|
741bb5328e | ||
|
|
33650336f5 | ||
|
|
bbce1dc256 | ||
|
|
8ab51dbf22 | ||
|
|
fd4595d6b4 | ||
|
|
204804ae52 | ||
|
|
c2819923c5 | ||
|
|
68f1432a68 | ||
|
|
0defb61a18 | ||
|
|
0fc805202c | ||
|
|
a7374e84a2 | ||
|
|
76681fd931 | ||
|
|
2418df7bb2 | ||
|
|
97d8d32049 | ||
|
|
08c8b0d7d6 | ||
|
|
81fd3e4732 | ||
|
|
d384a69877 | ||
|
|
a8b480559d | ||
|
|
f1b8b1d99b | ||
|
|
f67637144f | ||
|
|
4b274a8d4d | ||
|
|
c678e7ec3e | ||
|
|
2a79e46c46 | ||
|
|
d09b6a7d2c | ||
|
|
35eac0c457 | ||
|
|
cac0b0f316 | ||
|
|
8519dc1383 | ||
|
|
72f198d79e | ||
|
|
1cb8091125 | ||
|
|
18c543f2f2 | ||
|
|
496b9f9c63 | ||
|
|
1ee46ac5e1 | ||
|
|
f37c875be8 | ||
|
|
56dc66d842 | ||
|
|
7ae54ef973 | ||
|
|
4ed00c563c | ||
|
|
a49bfe871c | ||
|
|
6d97fea2f5 | ||
|
|
da833d55fe |
@@ -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: ''
|
||||
|
||||
@@ -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,6 +8,129 @@ The changes in each Verilator version are described below. The
|
||||
contributors that suggested a given feature are shown in []. Thanks!
|
||||
|
||||
|
||||
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
|
||||
==========================
|
||||
|
||||
**Major:**
|
||||
|
||||
* Add profile-guided optmization 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.
|
||||
* Support displaying x and z in $display task (#3107) (#3109). [Iru Cai]
|
||||
* Fix verilator_profcfunc profile accounting (#3115).
|
||||
* Fix display has no time units on class function (#3116). [Damien Pretet]
|
||||
* Fix removing if statement with side effect in condition (#3131). [Alexander Grobman]
|
||||
* Fix --waiver-output for multiline warnings (#2429) (#3141). [Keith Colbert]
|
||||
* Fix internal error on bad widths (#3140) (#3145). [Zhanglei Wang]
|
||||
* Fix crash on clang 12/13 (#3148). [Kouping Hsu]
|
||||
* Fix cygwin compile error due to missing -std=gnu++14 (#3149). [Sun Kim]
|
||||
* Fix $urandom_range when the range is 0 ... UINT_MAX (#3161). [Iru Cai]
|
||||
* Fix constructor-parameter argument comma-separation in C++ (#3162). [Matthew Ballance]
|
||||
* Fix missing install of vl_file_copy/vl_hier_graph (#3165). [Popolon]
|
||||
* Fix calling new with arguments in same class (#3166). [Matthew Ballance]
|
||||
* Fix false EOFNEWLINE warning when DOS carriage returns present (#3171).
|
||||
|
||||
|
||||
Verilator 4.212 2021-09-01
|
||||
==========================
|
||||
|
||||
@@ -3705,7 +3828,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.
|
||||
|
||||
+9
-21
@@ -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.
|
||||
@@ -118,23 +118,6 @@ INFOS = verilator.html verilator.pdf
|
||||
|
||||
INFOS_OLD = README README.html README.pdf
|
||||
|
||||
INST_PROJ_FILES = \
|
||||
bin/verilator \
|
||||
bin/verilator_ccache_report \
|
||||
bin/verilator_coverage \
|
||||
bin/verilator_gantt \
|
||||
bin/verilator_includer \
|
||||
bin/verilator_profcfunc \
|
||||
include/verilated.mk \
|
||||
include/*.[chv]* \
|
||||
include/gtkwave/*.[chv]* \
|
||||
include/vltstd/*.[chv]* \
|
||||
|
||||
INST_PROJ_BIN_FILES = \
|
||||
bin/verilator_bin$(EXEEXT) \
|
||||
bin/verilator_bin_dbg$(EXEEXT) \
|
||||
bin/verilator_coverage_bin_dbg$(EXEEXT) \
|
||||
|
||||
EXAMPLES_FIRST = \
|
||||
examples/make_hello_c \
|
||||
examples/make_hello_sc \
|
||||
@@ -142,7 +125,7 @@ EXAMPLES_FIRST = \
|
||||
EXAMPLES = $(EXAMPLES_FIRST) $(filter-out $(EXAMPLES_FIRST), $(sort $(wildcard examples/*)))
|
||||
|
||||
# See uninstall also - don't put wildcards in this variable, it might uninstall other stuff
|
||||
VL_INST_MAN_FILES = verilator.1 verilator_coverage.1 verilator_gantt.1 verilator_profcfunc.1
|
||||
VL_INST_MAN_FILES = verilator.1 verilator_coverage.1
|
||||
|
||||
default: all
|
||||
all: all_nomsg msg_test
|
||||
@@ -224,8 +207,10 @@ VL_INST_INC_SRCDIR_FILES = \
|
||||
include/vltstd/*.[chv]* \
|
||||
|
||||
VL_INST_DATA_SRCDIR_FILES = \
|
||||
examples/*/*.[chv]* examples/*/Makefile* \
|
||||
examples/*/CMakeLists.txt
|
||||
examples/*/*.[chv]* \
|
||||
examples/*/CMakeLists.txt \
|
||||
examples/*/Makefile* \
|
||||
examples/*/vl_* \
|
||||
|
||||
installbin:
|
||||
$(MKINSTALLDIRS) $(DESTDIR)$(bindir)
|
||||
@@ -369,6 +354,9 @@ clang-format:
|
||||
|
||||
PY_PROGRAMS = \
|
||||
bin/verilator_ccache_report \
|
||||
bin/verilator_difftree \
|
||||
bin/verilator_gantt \
|
||||
bin/verilator_profcfunc \
|
||||
examples/xml_py/vl_file_copy \
|
||||
examples/xml_py/vl_hier_graph \
|
||||
docs/guide/conf.py \
|
||||
|
||||
+1
-1
@@ -137,7 +137,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
|
||||
|
||||
+37
-36
@@ -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.
|
||||
@@ -34,11 +34,11 @@ my $opt_quiet_exit;
|
||||
|
||||
# No arguments can't do anything useful. Give help
|
||||
if ($#ARGV < 0) {
|
||||
pod2usage(-exitstatus=>2, -verbose=>0);
|
||||
pod2usage(-exitstatus => 2, -verbose => 0);
|
||||
}
|
||||
|
||||
# Insert debugging options up front
|
||||
push @ARGV, (split ' ',$ENV{VERILATOR_TEST_FLAGS}||"");
|
||||
push @ARGV, (split ' ', $ENV{VERILATOR_TEST_FLAGS} || "");
|
||||
|
||||
# We sneak a look at the flags so we can do some pre-environment checks
|
||||
# All flags will hit verilator...
|
||||
@@ -46,7 +46,7 @@ foreach my $sw (@ARGV) {
|
||||
push @Opt_Verilator_Sw, $sw;
|
||||
}
|
||||
|
||||
Getopt::Long::config("no_auto_abbrev","pass_through");
|
||||
Getopt::Long::config("no_auto_abbrev", "pass_through");
|
||||
if (! GetOptions(
|
||||
# Major operating modes
|
||||
"help" => \&usage,
|
||||
@@ -60,7 +60,7 @@ if (! GetOptions(
|
||||
# Additional parameters
|
||||
"<>" => sub {}, # Ignored
|
||||
)) {
|
||||
pod2usage(-exitstatus=>2, -verbose=>0);
|
||||
pod2usage(-exitstatus => 2, -verbose => 0);
|
||||
}
|
||||
|
||||
if ($opt_gdbbt && !gdb_works()) {
|
||||
@@ -73,12 +73,12 @@ if ($opt_gdbbt && !gdb_works()) {
|
||||
# Starting with that, escape all special chars for the shell;
|
||||
# The shell will undo the escapes and the verilator binary should
|
||||
# then see exactly the contents of @Opt_Verilator_Sw.
|
||||
my @quoted_sw = map {sh_escape($_)} @Opt_Verilator_Sw;
|
||||
my @quoted_sw = map { sh_escape($_) } @Opt_Verilator_Sw;
|
||||
if ($opt_gdb) {
|
||||
# Generic GDB interactive
|
||||
run (aslr_off()
|
||||
.($ENV{VERILATOR_GDB}||"gdb")
|
||||
." ".verilator_bin()
|
||||
. ($ENV{VERILATOR_GDB} || "gdb")
|
||||
. " " . verilator_bin()
|
||||
# Note, uncomment to set breakpoints before running:
|
||||
# ." -ex 'break main'"
|
||||
|
||||
@@ -87,42 +87,41 @@ if ($opt_gdb) {
|
||||
# escapes as you would expect in a double-quoted string.
|
||||
# That's not true for a single-quoted string, where \'
|
||||
# actually terminates the string -- not what we want!
|
||||
." -ex \"run ".join(' ', @quoted_sw)."\""
|
||||
." -ex 'set width 0'"
|
||||
." -ex 'bt'");
|
||||
. " -ex \"run " . join(' ', @quoted_sw) . "\""
|
||||
. " -ex 'set width 0'"
|
||||
. " -ex 'bt'");
|
||||
} elsif ($opt_rr) {
|
||||
# Record with rr
|
||||
run (aslr_off()
|
||||
."rr record ".verilator_bin()
|
||||
." ".join(' ', @quoted_sw));
|
||||
. "rr record " . verilator_bin()
|
||||
. " " . join(' ', @quoted_sw));
|
||||
} elsif ($opt_gdbbt && $Debug) {
|
||||
# Run under GDB to get gdbbt
|
||||
run (aslr_off()
|
||||
."gdb"
|
||||
." ".verilator_bin()
|
||||
." --batch --quiet --return-child-result"
|
||||
." -ex \"run ".join(' ', @quoted_sw)."\""
|
||||
." -ex 'set width 0'"
|
||||
." -ex 'bt' -ex 'quit'");
|
||||
. "gdb"
|
||||
. " " . verilator_bin()
|
||||
. " --batch --quiet --return-child-result"
|
||||
. " -ex \"run " . join(' ', @quoted_sw)."\""
|
||||
. " -ex 'set width 0'"
|
||||
. " -ex 'bt' -ex 'quit'");
|
||||
} elsif ($Debug) {
|
||||
# Debug
|
||||
run(aslr_off()
|
||||
.verilator_bin()." ".join(' ',@quoted_sw));
|
||||
run(aslr_off() . verilator_bin() . " " . join(' ', @quoted_sw));
|
||||
} else {
|
||||
# Normal, non gdb
|
||||
run(verilator_bin()." ".join(' ',@quoted_sw));
|
||||
run(verilator_bin() . " " . join(' ', @quoted_sw));
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
sub usage {
|
||||
pod2usage(-verbose=>2, -exitval=>0, -output=>\*STDOUT);
|
||||
pod2usage(-verbose => 2, -exitval => 0, -output => \*STDOUT);
|
||||
}
|
||||
|
||||
sub debug {
|
||||
shift;
|
||||
my $level = shift;
|
||||
$Debug = $level||3;
|
||||
$Debug = $level || 3;
|
||||
}
|
||||
|
||||
#######################################################################
|
||||
@@ -163,13 +162,13 @@ sub verilator_bin {
|
||||
sub gdb_works {
|
||||
$! = undef; # Cleanup -x
|
||||
system("gdb /bin/echo"
|
||||
." --batch-silent --quiet --return-child-result"
|
||||
." -ex 'run -n'" # `echo -n`
|
||||
." -ex 'set width 0'"
|
||||
." -ex 'bt'"
|
||||
." -ex 'quit'");
|
||||
. " --batch-silent --quiet --return-child-result"
|
||||
. " -ex 'run -n'" # `echo -n`
|
||||
. " -ex 'set width 0'"
|
||||
. " -ex 'bt'"
|
||||
. " -ex 'quit'");
|
||||
my $status = $?;
|
||||
return $status==0;
|
||||
return $status == 0;
|
||||
}
|
||||
|
||||
sub aslr_off {
|
||||
@@ -185,7 +184,7 @@ sub run {
|
||||
# Run command, check errors
|
||||
my $command = shift;
|
||||
$! = undef; # Cleanup -x
|
||||
print "\t$command\n" if $Debug>=3;
|
||||
print "\t$command\n" if $Debug >= 3;
|
||||
system($command);
|
||||
my $status = $?;
|
||||
if ($status) {
|
||||
@@ -193,7 +192,7 @@ sub run {
|
||||
warn "%Error: verilator: Misinstalled, or VERILATOR_ROOT might need to be in environment\n";
|
||||
}
|
||||
if ($Debug) { # For easy rerunning
|
||||
warn "%Error: export VERILATOR_ROOT=".($ENV{VERILATOR_ROOT}||"")."\n";
|
||||
warn "%Error: export VERILATOR_ROOT=" . ($ENV{VERILATOR_ROOT} || "") . "\n";
|
||||
warn "%Error: $command\n";
|
||||
}
|
||||
if ($status & 127) {
|
||||
@@ -201,13 +200,13 @@ sub run {
|
||||
|| ($status & 127) == 8 # SIGFPA
|
||||
|| ($status & 127) == 11) { # SIGSEGV
|
||||
warn "%Error: Verilator internal fault, sorry. "
|
||||
."Suggest trying --debug --gdbbt\n" if !$Debug;
|
||||
. "Suggest trying --debug --gdbbt\n" if !$Debug;
|
||||
} elsif (($status & 127) == 6) { # SIGABRT
|
||||
warn "%Error: Verilator aborted. "
|
||||
."Suggest trying --debug --gdbbt\n" if !$Debug;
|
||||
. "Suggest trying --debug --gdbbt\n" if !$Debug;
|
||||
} else {
|
||||
warn "%Error: Verilator threw signal $status. "
|
||||
."Suggest trying --debug --gdbbt\n" if !$Debug;
|
||||
. "Suggest trying --debug --gdbbt\n" if !$Debug;
|
||||
}
|
||||
}
|
||||
if (!$opt_quiet_exit && ($status != 256 || $Debug)) { # i.e. not normal exit(1)
|
||||
@@ -337,6 +336,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
|
||||
@@ -448,6 +448,7 @@ description of these arguments.
|
||||
+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+rand+reset+<value> Set random reset technique
|
||||
+verilator+seed+<value> Set random seed
|
||||
+verilator+V Verbose version and config
|
||||
@@ -458,7 +459,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.
|
||||
|
||||
+11
-11
@@ -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.
|
||||
@@ -30,7 +30,7 @@ $Debug = 0;
|
||||
|
||||
# No arguments can't do anything useful. Give help
|
||||
if ($#ARGV < 0) {
|
||||
pod2usage(-exitstatus=>2, -verbose=>0);
|
||||
pod2usage(-exitstatus => 2, -verbose => 0);
|
||||
}
|
||||
|
||||
# We sneak a look at the flags so we can do some pre-environment checks
|
||||
@@ -40,7 +40,7 @@ foreach my $sw (@ARGV) {
|
||||
push @Opt_Verilator_Sw, $sw;
|
||||
}
|
||||
|
||||
Getopt::Long::config("no_auto_abbrev","pass_through");
|
||||
Getopt::Long::config("no_auto_abbrev", "pass_through");
|
||||
if (! GetOptions (
|
||||
# Major operating modes
|
||||
"help" => \&usage,
|
||||
@@ -49,23 +49,23 @@ if (! GetOptions (
|
||||
# Additional parameters
|
||||
"<>" => sub {}, # Ignored
|
||||
)) {
|
||||
pod2usage(-exitstatus=>2, -verbose=>0);
|
||||
pod2usage(-exitstatus => 2, -verbose => 0);
|
||||
}
|
||||
|
||||
# Normal, non gdb
|
||||
run(verilator_coverage_bin()
|
||||
." ".join(' ',@Opt_Verilator_Sw));
|
||||
. " " . join(' ', @Opt_Verilator_Sw));
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
sub usage {
|
||||
pod2usage(-verbose=>2, -exitval=>0, -output=>\*STDOUT);
|
||||
pod2usage(-verbose => 2, -exitval => 0, -output => \*STDOUT);
|
||||
}
|
||||
|
||||
sub debug {
|
||||
shift;
|
||||
my $level = shift;
|
||||
$Debug = $level||3;
|
||||
$Debug = $level || 3;
|
||||
}
|
||||
|
||||
#######################################################################
|
||||
@@ -107,7 +107,7 @@ sub run {
|
||||
# Run command, check errors
|
||||
my $command = shift;
|
||||
$! = undef; # Cleanup -x
|
||||
print "\t$command\n" if $Debug>=3;
|
||||
print "\t$command\n" if $Debug >= 3;
|
||||
system($command);
|
||||
my $status = $?;
|
||||
if ($status) {
|
||||
@@ -115,11 +115,11 @@ sub run {
|
||||
warn "%Error: verilator_coverage: Misinstalled, or VERILATOR_ROOT might need to be in environment\n";
|
||||
}
|
||||
if ($Debug) { # For easy rerunning
|
||||
warn "%Error: export VERILATOR_ROOT=".($ENV{VERILATOR_ROOT}||"")."\n";
|
||||
warn "%Error: export VERILATOR_ROOT=" . ($ENV{VERILATOR_ROOT} || "") . "\n";
|
||||
warn "%Error: $command\n";
|
||||
}
|
||||
if ($status & 127) {
|
||||
if (($status & 127) == 8 || ($status & 127) == 11) { # SIGFPA or SIGSEGV
|
||||
if (($status & 127) == 8 || ($status & 127) == 11) { # SIGFPA or SIGSEGV
|
||||
warn "%Error: Verilator_coverage internal fault, sorry.\n" if !$Debug;
|
||||
} elsif (($status & 127) == 6) { # SIGABRT
|
||||
warn "%Error: Verilator_coverage aborted.\n" if !$Debug;
|
||||
@@ -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.
|
||||
|
||||
+107
-201
@@ -1,233 +1,139 @@
|
||||
#!/usr/bin/env perl
|
||||
# See copyright, etc in below POD section.
|
||||
#!/usr/bin/env python3
|
||||
# pylint: disable=C0103,C0114,C0116
|
||||
######################################################################
|
||||
|
||||
use warnings;
|
||||
use Getopt::Long;
|
||||
use IO::File;
|
||||
use Pod::Usage;
|
||||
use strict;
|
||||
use vars qw($Debug);
|
||||
import argparse
|
||||
import collections
|
||||
import glob
|
||||
import os.path
|
||||
import re
|
||||
import sys
|
||||
|
||||
#======================================================================
|
||||
# main
|
||||
|
||||
$Debug = 0;
|
||||
my $Opt_A;
|
||||
my $Opt_B;
|
||||
my $Opt_Lineno = 1;
|
||||
autoflush STDOUT 1;
|
||||
autoflush STDERR 1;
|
||||
Getopt::Long::config("no_auto_abbrev");
|
||||
if (! GetOptions(
|
||||
"help" => \&usage,
|
||||
"debug" => \&debug,
|
||||
"<>" => \¶meter,
|
||||
"lineno!" => \$Opt_Lineno,
|
||||
)) {
|
||||
die "%Error: Bad usage, try 'verilator_difftree --help'\n";
|
||||
}
|
||||
def diff(a, b):
|
||||
|
||||
defined $Opt_A or die "%Error: No old diff filename\n";
|
||||
defined $Opt_B or die "%Error: No new diff filename\n";
|
||||
if not os.path.exists(a):
|
||||
sys.exit("%Error: No old diff filename found: " + a)
|
||||
if not os.path.exists(b):
|
||||
sys.exit("%Error: No new diff filename found: " + b)
|
||||
|
||||
-e $Opt_A or die "%Error: No old diff filename found: $Opt_A\n";
|
||||
-e $Opt_B or die "%Error: No new diff filename found: $Opt_B\n";
|
||||
if os.path.isdir(a) and os.path.isdir(b):
|
||||
diff_dir(a, b)
|
||||
elif os.path.isfile(a) and os.path.isfile(b):
|
||||
diff_file(a, b)
|
||||
else:
|
||||
sys.exit("%Error: Mix of files and dirs")
|
||||
|
||||
if (-d $Opt_A && -d $Opt_B) {
|
||||
diff_dir($Opt_A, $Opt_B);
|
||||
} elsif (-f $Opt_A && -f $Opt_B) {
|
||||
diff_file($Opt_A, $Opt_B);
|
||||
} else {
|
||||
die "%Error: Mix of files and dirs\n";
|
||||
}
|
||||
|
||||
sub diff_dir {
|
||||
my $a = shift;
|
||||
my $b = shift;
|
||||
def diff_dir(a, b):
|
||||
# Diff all files under two directories
|
||||
my %files;
|
||||
files = collections.defaultdict(lambda: {})
|
||||
|
||||
foreach my $fn (glob("$a/*.tree")) {
|
||||
(my $base = $fn) =~ s!.*/!!;
|
||||
$files{$base}{a} = $fn;
|
||||
}
|
||||
foreach my $fn (glob("$b/*.tree")) {
|
||||
(my $base = $fn) =~ s!.*/!!;
|
||||
$files{$base}{b} = $fn;
|
||||
}
|
||||
my $any;
|
||||
foreach my $base (sort (keys %files)) {
|
||||
my $a = $files{$base}{a};
|
||||
my $b = $files{$base}{b};
|
||||
next if !$a || !$b;
|
||||
print "="x70,"\n";
|
||||
print "= $a <-> $b\n";
|
||||
diff_file($a,$b);
|
||||
$any = 1;
|
||||
}
|
||||
$any or warn("%Warning: No .tree files found that have similar base names:\n "
|
||||
.join("\n ", sort keys %files),"\n");
|
||||
}
|
||||
for fn in glob.glob(a + "/*.tree"):
|
||||
base = re.sub(r'.*/', '', fn)
|
||||
files[base]['a'] = fn
|
||||
for fn in glob.glob(b + "/*.tree"):
|
||||
base = re.sub(r'.*/', '', fn)
|
||||
files[base]['b'] = fn
|
||||
|
||||
sub diff_file {
|
||||
my $a = shift;
|
||||
my $b = shift;
|
||||
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']
|
||||
print("=" * 70)
|
||||
print("= %s <-> %s" % (a, b))
|
||||
diff_file(a, b)
|
||||
anyfile = True
|
||||
if not anyfile:
|
||||
sys.stderr.write(
|
||||
"%Warning: No .tree files found that have similar base names\n")
|
||||
|
||||
|
||||
def diff_file(a, b):
|
||||
# Compare the two tree files
|
||||
(my $short_a = $a) =~ s/[^a-zA-Z0-9.]+/_/g;
|
||||
(my $short_b = $b) =~ s/[^a-zA-Z0-9.]+/_/g;
|
||||
my $tmp_a = "/tmp/${$}_${short_a}.a";
|
||||
my $tmp_b = "/tmp/${$}_${short_b}.b";
|
||||
short_a = re.sub(r'[^a-zA-Z0-9.]+', '_', a)
|
||||
short_b = re.sub(r'[^a-zA-Z0-9.]+', '_', b)
|
||||
tmp_a = "/tmp/%s_%s.a" % (os.getpid(), short_a)
|
||||
tmp_b = "/tmp/%s_%s.b" % (os.getpid(), short_b)
|
||||
|
||||
my $vera = version_from($a);
|
||||
my $verb = version_from($b);
|
||||
my $verCvt = (($vera < 0x3900 && $verb >= 0x3900)
|
||||
|| ($vera >= 0x3900 && $verb < 0x3900));
|
||||
# Version conversion deprecated, but for future...
|
||||
# vera = version_from(a)
|
||||
# verb = version_from(b)
|
||||
# verCvt = ((vera < 0x3900 and verb >= 0x3900)
|
||||
# or (vera >= 0x3900 and verb < 0x3900))
|
||||
|
||||
filter($a, $tmp_a, $verCvt);
|
||||
filter($b, $tmp_b, $verCvt);
|
||||
system("diff -u $tmp_a $tmp_b");
|
||||
unlink $tmp_a;
|
||||
unlink $tmp_b;
|
||||
}
|
||||
filterf(a, tmp_a)
|
||||
filterf(b, tmp_b)
|
||||
os.system("diff -u " + tmp_a + " " + tmp_b)
|
||||
os.unlink(tmp_a)
|
||||
os.unlink(tmp_b)
|
||||
|
||||
sub version_from {
|
||||
my $fn = shift;
|
||||
|
||||
def version_from(filename):
|
||||
# Return dump format
|
||||
my $f1 = IO::File->new ($fn) or die "%Error: $! $fn,";
|
||||
while (defined (my $line=$f1->getline())) {
|
||||
last if $. > 10;
|
||||
return hex $1 if $line =~ /\(format (0x[0-9.]+)\)/;
|
||||
}
|
||||
return 1.0;
|
||||
}
|
||||
with open(filename) as fh:
|
||||
lineno = 0
|
||||
for line in fh:
|
||||
if lineno > 10:
|
||||
break
|
||||
match = re.search(r'format (0x[0-9.]+)', line)
|
||||
if match:
|
||||
return hex(match.group(1))
|
||||
return 1.0
|
||||
|
||||
sub filter {
|
||||
my $fn1 = shift;
|
||||
my $fn2 = shift;
|
||||
my $verCvt = shift;
|
||||
|
||||
def filterf(fn1, fn2):
|
||||
# Remove hex numbers before diffing
|
||||
my $f1 = IO::File->new ($fn1) or die "%Error: $! $fn1,";
|
||||
my $f2 = IO::File->new ($fn2,"w") or die "%Error: $! $fn2,";
|
||||
while (defined (my $line=$f1->getline())) {
|
||||
same_line:
|
||||
next if $line =~ / This=/;
|
||||
$line =~ s/0x[a-f0-9]+/0x/g;
|
||||
$line =~ s/<e[0-9]+\#?>/<e>/g;
|
||||
$line =~ s/{[a-z]*\d+}/{}/g if !$Opt_Lineno;
|
||||
if ($verCvt) {
|
||||
next if $line =~ /^ NETLIST/;
|
||||
if ($line =~ /: ([A-Z]+) /) {
|
||||
my $type = $1;
|
||||
next if $type =~ 'DTYPE';
|
||||
if ($type eq 'TYPETABLE' || $type eq 'RANGE') {
|
||||
$line =~ /^(\s+\S+:) /; my $prefix = $1;
|
||||
while (defined ($line=$f1->getline())) {
|
||||
next if $line =~ /^\s+[a-z]/; # Table body
|
||||
next if $line =~ /^${prefix}[0-9]:/;
|
||||
goto same_line;
|
||||
}
|
||||
next;
|
||||
}
|
||||
}
|
||||
}
|
||||
print $f2 $line;
|
||||
}
|
||||
$f1->close;
|
||||
$f2->close;
|
||||
}
|
||||
with open(fn1) as fh1:
|
||||
with open(fn2, "w") as fh2:
|
||||
for line in fh1:
|
||||
if re.search(r' This=', line):
|
||||
continue
|
||||
line = re.sub(r'0x[a-f0-9]+', '0x', line)
|
||||
line = re.sub(r'<e[0-9]+\#?>', '<e>', line)
|
||||
if not Args.no_lineno:
|
||||
line = re.sub(r'{[a-z]*\d+}', '{}', line)
|
||||
fh2.write(line)
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
sub usage {
|
||||
pod2usage(-verbose=>2, -exitval=>0, -output=>\*STDOUT);
|
||||
exit(1); # Unreachable
|
||||
}
|
||||
######################################################################
|
||||
######################################################################
|
||||
|
||||
sub debug {
|
||||
$Debug = 1;
|
||||
}
|
||||
|
||||
sub parameter {
|
||||
my $param = shift;
|
||||
if (!defined $Opt_A) {
|
||||
$Opt_A = $param;
|
||||
} elsif (!defined $Opt_B) {
|
||||
$Opt_B = $param;
|
||||
} else {
|
||||
die "%Error: Unknown parameter: $param\n";
|
||||
}
|
||||
}
|
||||
|
||||
#######################################################################
|
||||
|
||||
sub run {
|
||||
# Run a system command, check errors
|
||||
my $command = shift;
|
||||
print "\t$command\n";
|
||||
system "$command";
|
||||
my $status = $?;
|
||||
($status == 0) or die "%Error: Command Failed $command, $status, stopped";
|
||||
}
|
||||
|
||||
#######################################################################
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
verilator_difftree - Compare two Verilator debugging trees
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
verilator_difftree .../a/a.tree .../b/a.tree
|
||||
verilator_difftree .../a .../b
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Verilator_difftree is used for debugging Verilator tree output files. It
|
||||
performs a diff between two files, or all files common between two
|
||||
parser = argparse.ArgumentParser(
|
||||
allow_abbrev=False,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
description="""Compare two Verilator debugging trees""",
|
||||
epilog=
|
||||
"""Verilator_difftree is used for debugging Verilator tree output files.
|
||||
It performs a diff between two files, or all files common between two
|
||||
directories, ignoring irrelevant pointer differences.
|
||||
|
||||
=head1 ARGUMENTS
|
||||
For documentation see
|
||||
https://verilator.org/guide/latest/exe_verilator_difftree.html
|
||||
|
||||
=over 4
|
||||
|
||||
=item --help
|
||||
|
||||
Displays this message and program version and exits.
|
||||
|
||||
=item --nolineno
|
||||
|
||||
Do not show differences in line numbering.
|
||||
|
||||
=back
|
||||
|
||||
=head1 DISTRIBUTION
|
||||
|
||||
The latest version is available from L<https://verilator.org>.
|
||||
|
||||
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.
|
||||
|
||||
SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0""")
|
||||
|
||||
=head1 AUTHORS
|
||||
parser.add_argument('--debug',
|
||||
action='store_const',
|
||||
const=9,
|
||||
help='enable debug')
|
||||
parser.add_argument('--no-lineno',
|
||||
action='store_false',
|
||||
help='do not show differences in line numbering')
|
||||
parser.add_argument('filea', help='input file a to diff')
|
||||
parser.add_argument('fileb', help='input file b to diff')
|
||||
|
||||
Wilson Snyder <[email protected]>
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
C<verilator>
|
||||
|
||||
and L<https://verilator.org/verilator_doc.html> for detailed documentation.
|
||||
|
||||
=cut
|
||||
Args = parser.parse_args()
|
||||
diff(Args.filea, Args.fileb)
|
||||
|
||||
######################################################################
|
||||
### Local Variables:
|
||||
### compile-command: "$V4/bin/verilator_difftree {$V4D,$V4}/test_regress/obj_dir/t_EXAMPLE/V*_03_*.tree"
|
||||
### End:
|
||||
# Local Variables:
|
||||
# compile-command: "./verilator_difftree ../test_regress/t/t_difftree.{a,b}.tree"
|
||||
# End:
|
||||
|
||||
+429
-512
File diff suppressed because it is too large
Load Diff
@@ -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.
|
||||
@@ -10,11 +10,11 @@
|
||||
|
||||
require 5.005;
|
||||
use warnings;
|
||||
print "// DESCR"."IPTION: Generated by verilator_includer via makefile\n";
|
||||
print "// DESCR" . "IPTION: Generated by verilator_includer via makefile\n";
|
||||
foreach my $param (@ARGV) {
|
||||
if ($param =~ /^-D([^=]+)=(.*)/) {
|
||||
print "#define $1 $2\n"
|
||||
print "#define $1 $2\n";
|
||||
} else {
|
||||
print "#include \"$param\"\n"
|
||||
print "#include \"$param\"\n";
|
||||
}
|
||||
}
|
||||
|
||||
+173
-217
@@ -1,248 +1,204 @@
|
||||
#!/usr/bin/env perl
|
||||
# See copyright, etc in below POD section.
|
||||
#!/usr/bin/env python3
|
||||
# pylint: disable=C0103,C0114,C0116,R0914,R0912,R0915,eval-used
|
||||
######################################################################
|
||||
|
||||
require 5.006_001;
|
||||
use warnings;
|
||||
use Getopt::Long;
|
||||
use IO::File;
|
||||
use Pod::Usage;
|
||||
eval { use Data::Dumper; $Data::Dumper::Indent = 1; }; # Debug, ok if missing
|
||||
use strict;
|
||||
use vars qw($Debug);
|
||||
import argparse
|
||||
import collections
|
||||
import re
|
||||
# from pprint import pprint
|
||||
|
||||
#======================================================================
|
||||
######################################################################
|
||||
|
||||
|
||||
#======================================================================
|
||||
# main
|
||||
def profcfunc(filename):
|
||||
funcs = {}
|
||||
|
||||
$Debug = 0;
|
||||
my $Opt_File;
|
||||
autoflush STDOUT 1;
|
||||
autoflush STDERR 1;
|
||||
Getopt::Long::config("no_auto_abbrev");
|
||||
if (! GetOptions(
|
||||
"help" => \&usage,
|
||||
"debug" => \&debug,
|
||||
"<>" => \¶meter,
|
||||
)) {
|
||||
die "%Error: Bad usage, try 'verilator_profcfunc --help'\n";
|
||||
}
|
||||
with open(filename) as fh:
|
||||
|
||||
defined $Opt_File or die "%Error: No filename given\n";
|
||||
for line in fh:
|
||||
# %time cumesec selfsec calls {stuff} name
|
||||
match = re.match(
|
||||
r'^\s*([0-9.]+)\s+[0-9.]+\s+([0-9.]+)\s+([0-9.]+)\s+[^a-zA-Z_]*([a-zA-Z_].*)$',
|
||||
line)
|
||||
if match:
|
||||
pct = float(match.group(1))
|
||||
sec = float(match.group(2))
|
||||
calls = float(match.group(3))
|
||||
func = match.group(4)
|
||||
if func not in funcs:
|
||||
funcs[func] = {'pct': 0, 'sec': 0, 'calls': 0}
|
||||
funcs[func]['pct'] += pct
|
||||
funcs[func]['sec'] += sec
|
||||
funcs[func]['calls'] += calls
|
||||
continue
|
||||
|
||||
profcfunc($Opt_File);
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
sub usage {
|
||||
pod2usage(-verbose=>2, -exitval=>0, -output=>\*STDOUT);
|
||||
exit(1); # Unreachable
|
||||
}
|
||||
|
||||
sub debug {
|
||||
$Debug = 1;
|
||||
}
|
||||
|
||||
sub parameter {
|
||||
my $param = shift;
|
||||
if (!defined $Opt_File) {
|
||||
$Opt_File = $param;
|
||||
} else {
|
||||
die "%Error: Unknown parameter: $param\n";
|
||||
}
|
||||
}
|
||||
|
||||
#######################################################################
|
||||
|
||||
sub profcfunc {
|
||||
my $filename = shift;
|
||||
# Remove hex numbers before diffing
|
||||
my $fh = IO::File->new ($filename) or die "%Error: $! $filename,";
|
||||
|
||||
my %funcs;
|
||||
|
||||
while (defined (my $line=$fh->getline())) {
|
||||
# %time cumesec selfsec calls {stuff} name
|
||||
if ($line =~ /^\s*([0-9.]+)\s+[0-9.]+\s+([0-9.]+)\s+([0-9.]+)\s+[^a-zA-Z_]*([a-zA-Z_].*)$/) {
|
||||
my $pct=$1; my $sec=$2; my $calls=$3; my $func=$4;
|
||||
$funcs{$func}{pct} += $pct;
|
||||
$funcs{$func}{sec} += $sec;
|
||||
$funcs{$func}{calls} += $calls;
|
||||
}
|
||||
# Older gprofs have no call column for single-call functions
|
||||
# %time cumesec selfsec {stuff} name
|
||||
elsif ($line =~ /^\s*([0-9.]+)\s+[0-9.]+\s+([0-9.]+)\s+[^a-zA-Z_]*([a-zA-Z_].*)$/) {
|
||||
my $pct=$1; my $sec=$2; my $calls=1; my $func=$3;
|
||||
$funcs{$func}{pct} += $pct;
|
||||
$funcs{$func}{sec} += $sec;
|
||||
$funcs{$func}{calls} += $calls;
|
||||
}
|
||||
}
|
||||
$fh->close;
|
||||
# Older gprofs have no call column for single-call functions
|
||||
# %time cumesec selfsec {stuff} name
|
||||
match = re.match(
|
||||
r'^\s*([0-9.]+)\s+[0-9.]+\s+([0-9.]+)\s+[^a-zA-Z_]*([a-zA-Z_].*)$',
|
||||
line)
|
||||
if match:
|
||||
pct = float(match.group(1))
|
||||
sec = float(match.group(2))
|
||||
calls = 1
|
||||
func = match.group(3)
|
||||
if func not in funcs:
|
||||
funcs[func] = {'pct': 0, 'sec': 0, 'calls': 0}
|
||||
funcs[func]['pct'] += pct
|
||||
funcs[func]['sec'] += sec
|
||||
funcs[func]['calls'] += calls
|
||||
continue
|
||||
|
||||
# Find modules
|
||||
my %pointer_mods;
|
||||
my %verilated_mods;
|
||||
foreach my $func (keys %funcs) {
|
||||
if ($func =~ /(.*)::_eval\(([a-zA-Z_0-9]+__Syms).*\)$/) {
|
||||
$verilated_mods{$1} = qr/^$1/;
|
||||
$pointer_mods{$2} = $1;
|
||||
}
|
||||
}
|
||||
#print Dumper(\%pointer_mods, \%verilated_mods);
|
||||
verilated_mods = {}
|
||||
for func in funcs:
|
||||
match = re.search(r'(.*)::eval(_step)?\(', func)
|
||||
if match:
|
||||
prefix = match.group(1)
|
||||
if Args.debug:
|
||||
print("-got _eval %s prefix=%s" % (func, prefix))
|
||||
verilated_mods[prefix] = re.compile(r'^' + prefix)
|
||||
# pprint(verilated_mods)
|
||||
|
||||
# Resort by Verilog name
|
||||
my %vfuncs;
|
||||
my %groups;
|
||||
foreach my $func (keys %funcs) {
|
||||
my $pct = $funcs{$func}{pct};
|
||||
my $vfunc = $func;
|
||||
my $design;
|
||||
# Sort by Verilog name
|
||||
vfuncs = {}
|
||||
groups = {}
|
||||
groups['type'] = collections.defaultdict(lambda: 0)
|
||||
groups['design'] = collections.defaultdict(lambda: 0)
|
||||
groups['module'] = collections.defaultdict(lambda: 0)
|
||||
|
||||
if ($func =~ /\(([a-zA-Z_0-9]+__Syms)/) {
|
||||
$design = $pointer_mods{$1};
|
||||
}
|
||||
for func in funcs:
|
||||
pct = funcs[func]['pct']
|
||||
vfunc = func
|
||||
|
||||
foreach my $vde (keys %verilated_mods) {
|
||||
last if $design;
|
||||
if ($func =~ /$verilated_mods{$vde}/) {
|
||||
$design=$vde;
|
||||
last;
|
||||
}
|
||||
}
|
||||
funcarg = re.sub(r'^.*\(', '', func)
|
||||
|
||||
if ($vfunc =~ /__PROF__([a-zA-Z_0-9]+)__l?([0-9]+)\(/) {
|
||||
$vfunc = sprintf("VBlock %s:%d", $1, $2);
|
||||
$groups{type}{"Verilog Blocks under $design"} += $pct;
|
||||
$groups{design}{$design} += $pct;
|
||||
$groups{module}{$1} += $pct;
|
||||
} else {
|
||||
if ($design) {
|
||||
$vfunc = sprintf("VCommon %s", $func);
|
||||
$groups{type}{"Common code under $design"} += $pct;
|
||||
$groups{design}{$design} += $pct;
|
||||
$groups{module}{$design." common code"} += $pct;
|
||||
} elsif ($func =~ /^VL_[A-Z0-9_]+/
|
||||
|| $func =~ /^_?vl_[a-zA-Z0-9_]+/
|
||||
|| $func =~ /^verilated/i) {
|
||||
$vfunc = sprintf("VLib %s", $func);
|
||||
$groups{type}{'VLib'} += $pct;
|
||||
$groups{design}{'VLib'} += $pct;
|
||||
$groups{module}{'VLib'} += $pct;
|
||||
} elsif ($func =~ /^_mcount_private/) {
|
||||
$vfunc = sprintf("Prof %s", $func);
|
||||
$groups{type}{'Prof'} += $pct;
|
||||
$groups{design}{'Prof'} += $pct;
|
||||
$groups{module}{'Prof'} += $pct;
|
||||
} else {
|
||||
$vfunc = sprintf("C++ %s", $func);
|
||||
$groups{type}{'C++'} += $pct;
|
||||
$groups{design}{'C++'} += $pct;
|
||||
$groups{module}{'C++'} += $pct;
|
||||
}
|
||||
}
|
||||
$vfuncs{$vfunc} = $funcs{$func};
|
||||
}
|
||||
design = None
|
||||
for vde in verilated_mods:
|
||||
if verilated_mods[vde].match(func) or verilated_mods[vde].match(
|
||||
funcarg):
|
||||
design = vde
|
||||
break
|
||||
|
||||
vdesign = "-"
|
||||
|
||||
prof_match = re.search(r'__PROF__([a-zA-Z_0-9]+)__l?([0-9]+)\(', vfunc)
|
||||
if design and prof_match:
|
||||
linefunc = prof_match.group(1)
|
||||
lineno = int(prof_match.group(2))
|
||||
vfunc = "VBlock %s:%d" % (linefunc, lineno)
|
||||
vdesign = design
|
||||
groups['type']["Verilog Blocks under " + design] += pct
|
||||
groups['design'][design] += pct
|
||||
groups['module'][linefunc] += pct
|
||||
elif design:
|
||||
vfunc = "VCommon " + func
|
||||
vdesign = design
|
||||
groups['type']["Common code under " + design] += pct
|
||||
groups['design'][design] += pct
|
||||
groups['module'][design + " common code"] += pct
|
||||
elif re.match(r'(VL_[A-Z0-9_]+|_?vl_[a-zA-Z0-9_]+|Verilated)', vfunc):
|
||||
vfunc = "VLib " + func
|
||||
groups['type']['VLib'] += pct
|
||||
groups['design']['VLib'] += pct
|
||||
groups['module']['VLib'] += pct
|
||||
elif re.match(r'^_mcount_private', vfunc):
|
||||
vfunc = "Prof " + func
|
||||
groups['type']['Prof'] += pct
|
||||
groups['design']['Prof'] += pct
|
||||
groups['module']['Prof'] += pct
|
||||
else:
|
||||
vfunc = "C++ " + func
|
||||
groups['type']['C++'] += pct
|
||||
groups['design']['C++'] += pct
|
||||
groups['module']['C++'] += pct
|
||||
|
||||
if vfunc not in vfuncs:
|
||||
vfuncs[vfunc] = funcs[func]
|
||||
vfuncs[vfunc]['design'] = vdesign
|
||||
else:
|
||||
vfuncs[vfunc]['pct'] += funcs[func]['pct']
|
||||
vfuncs[vfunc]['calls'] += funcs[func]['calls']
|
||||
vfuncs[vfunc]['sec'] += funcs[func]['sec']
|
||||
|
||||
for ftype in ['type', 'design', 'module']:
|
||||
missing = 100
|
||||
for item in groups[ftype].keys():
|
||||
missing -= groups[ftype][item]
|
||||
groups[ftype]["\377Unaccounted for/rounding error"] = missing
|
||||
|
||||
print("Overall summary by %s:" % ftype)
|
||||
print(" %-6s %s" % ("% time", ftype))
|
||||
for what in sorted(groups[ftype].keys()):
|
||||
# \377 used to establish sort order
|
||||
pwhat = re.sub(r'^\377', '', what)
|
||||
print(" %6.2f %s" % (groups[ftype][what], pwhat))
|
||||
print()
|
||||
|
||||
design_width = 1
|
||||
for func in vfuncs:
|
||||
if design_width < len(vfuncs[func]['design']):
|
||||
design_width = len(vfuncs[func]['design'])
|
||||
|
||||
print("Verilog code profile:")
|
||||
print(" These are split into three categories:")
|
||||
print(" C++: Time in non-Verilated C++ code")
|
||||
print(" Prof: Time in profile overhead")
|
||||
print(" VBlock: Time attributable to a block in a" +
|
||||
" Verilog file and line")
|
||||
print(" VCommon: Time in a Verilated module," +
|
||||
" due to all parts of the design")
|
||||
print(" VLib: Time in Verilated common libraries," +
|
||||
" called by the Verilated code")
|
||||
print()
|
||||
|
||||
print(" % cumulative self ")
|
||||
print((" time seconds seconds calls %-" + str(design_width) +
|
||||
"s type filename and line number") % "design")
|
||||
|
||||
cume = 0
|
||||
for func in sorted(vfuncs.keys(),
|
||||
key=lambda f: vfuncs[f]['sec'],
|
||||
reverse=True):
|
||||
cume += vfuncs[func]['sec']
|
||||
print(("%6.2f %9.2f %8.2f %10d %-" + str(design_width) + "s %s") %
|
||||
(vfuncs[func]['pct'], cume, vfuncs[func]['sec'],
|
||||
vfuncs[func]['calls'], vfuncs[func]['design'], func))
|
||||
|
||||
|
||||
foreach my $type (qw(type design module)) {
|
||||
my $missing = 100;
|
||||
foreach (sort (keys %{$groups{$type}})) {
|
||||
$missing -= $groups{$type}{$_};
|
||||
}
|
||||
if ($missing) {
|
||||
$groups{$type}{"\377Unaccounted for/rounding error"} = $missing;
|
||||
}
|
||||
######################################################################
|
||||
######################################################################
|
||||
|
||||
print("Overall summary by $type:\n");
|
||||
printf(" %-6s %s\n","% time",$type);
|
||||
foreach my $what (sort (keys %{$groups{$type}})) {
|
||||
(my $pwhat = $what) =~ s/^\377//; # Just used to establish sort order
|
||||
printf(" %6.2f %s\n", $groups{$type}{$what}, $pwhat);
|
||||
}
|
||||
print("\n");
|
||||
}
|
||||
|
||||
print("Verilog code profile:\n");
|
||||
print(" These are split into three categories:\n");
|
||||
print(" C++: Time in non-Verilated C++ code\n");
|
||||
print(" Prof: Time in profile overhead\n");
|
||||
print(" VBlock: Time attributable to a block in a Verilog file and line\n");
|
||||
print(" VCommon: Time in a Verilated module, due to all parts of the design\n");
|
||||
print(" VLib: Time in Verilated common libraries, called by the Verilated code\n");
|
||||
print("\n");
|
||||
|
||||
print(" % cumulative self \n");
|
||||
print(" time seconds seconds calls type filename and line number\n");
|
||||
|
||||
my $cume = 0;
|
||||
foreach my $func (sort {$vfuncs{$b}{sec} <=> $vfuncs{$a}{sec}
|
||||
|| $a cmp $b}
|
||||
(keys %vfuncs)) {
|
||||
$cume += $vfuncs{$func}{sec};
|
||||
printf +("%6.2f %9.2f %8.2f %8d %s\n",
|
||||
$vfuncs{$func}{pct},
|
||||
$cume, $vfuncs{$func}{sec},
|
||||
$vfuncs{$func}{calls},
|
||||
$func);
|
||||
}
|
||||
}
|
||||
|
||||
#######################################################################
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
verilator_profcfunc - Read gprof report created with --prof-cfuncs
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
verilator --prof-cfuncs ....
|
||||
gcc ....
|
||||
{run executable}
|
||||
gprof
|
||||
verilator_profcfuncs gprof.out
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Verilator_profcfunc reads a profile report created by gprof. The names of
|
||||
parser = argparse.ArgumentParser(
|
||||
allow_abbrev=False,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
description="""Read gprof report created with --prof-cfuncs""",
|
||||
epilog=
|
||||
"""Verilator_profcfunc reads a profile report created by gprof. The names of
|
||||
the functions are then transformed, assuming the user used Verilator's
|
||||
--prof-cfuncs, and a report printed showing the percentage of time, etc,
|
||||
in each Verilog block.
|
||||
|
||||
For documentation see
|
||||
L<https://verilator.org/guide/latest/exe_verilator_profcfuncs.html>.
|
||||
https://verilator.org/guide/latest/exe_verilator_profcfunc.html
|
||||
|
||||
=head1 ARGUMENT SUMMARY
|
||||
|
||||
<filename> Input file (gprof.out)
|
||||
--help Display this help
|
||||
|
||||
=head1 DISTRIBUTION
|
||||
|
||||
The latest version is available from L<https://verilator.org>.
|
||||
|
||||
Copyright 2007-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.
|
||||
|
||||
SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0""")
|
||||
|
||||
=head1 SEE ALSO
|
||||
parser.add_argument('--debug',
|
||||
action='store_const',
|
||||
const=9,
|
||||
help='enable debug')
|
||||
parser.add_argument('filename', help='input gprof output to process')
|
||||
|
||||
C<verilator>
|
||||
|
||||
and L<https://verilator.org/guide/latest/exe_verilator_profcfuncs.html> for
|
||||
detailed documentation.
|
||||
|
||||
=cut
|
||||
Args = parser.parse_args()
|
||||
profcfunc(Args.filename)
|
||||
|
||||
######################################################################
|
||||
### Local Variables:
|
||||
### compile-command: "$V4/bin/verilator_profcfunc $V4/test_c/obj_dir/V*_03_*.tree $V4N/test_c/obj_dir/V*_03_*.tree"
|
||||
### End:
|
||||
# Local Variables:
|
||||
# compile-command: "./verilator_profcfunc ../test_regress/t/t_profcfunc.gprof"
|
||||
# End:
|
||||
|
||||
+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.
|
||||
|
||||
+15
-17
@@ -1,13 +1,13 @@
|
||||
# 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.212 2021-09-01],
|
||||
AC_INIT([Verilator],[4.220 2022-03-12],
|
||||
[https://verilator.org],
|
||||
[verilator],[https://verilator.org])
|
||||
# When releasing, also update header of Changes file
|
||||
@@ -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
|
||||
@@ -347,22 +349,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++17 is the newest that Verilator supports
|
||||
# c++03 is the oldest that Verilator supports
|
||||
# c++14 is the newest that Verilator is regressed 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)
|
||||
_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)
|
||||
_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_NEWEST,-std=c++11)
|
||||
_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_NEWEST,-std=c++03)
|
||||
AC_SUBST(CFG_CXXFLAGS_STD_NEWEST)
|
||||
# And likewise oldest standard (same list above, backwards)
|
||||
# This is used for internal testing
|
||||
_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_OLDEST,-std=c++03)
|
||||
_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_OLDEST,-std=c++11)
|
||||
_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_OLDEST,-std=c++14)
|
||||
#_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_OLDEST,-std=c++17)
|
||||
#_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_OLDEST,-std=c++20)
|
||||
AC_SUBST(CFG_CXXFLAGS_STD_OLDEST)
|
||||
|
||||
# Flags for compiling Verilator internals including parser, and Verilated files
|
||||
# These turn on extra warnings and are only used with 'configure --enable-ccwarn'
|
||||
|
||||
@@ -3,18 +3,22 @@ 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
|
||||
Ameya Vikram Singh
|
||||
Andreas Kuster
|
||||
Chris Randall
|
||||
Chuxuan Wang
|
||||
Conor McCullough
|
||||
Dan Petrisko
|
||||
Daniel Bates
|
||||
David Horton
|
||||
David Metz
|
||||
David Stanford
|
||||
David Turner
|
||||
Drew Ranck
|
||||
Drew Taussig
|
||||
Driss Hafdi
|
||||
Edgar E. Iglesias
|
||||
@@ -26,16 +30,20 @@ Geza Lore
|
||||
Gianfranco Costamagna
|
||||
Glen Gibb
|
||||
Graham Rushton
|
||||
Guokai Chen
|
||||
Harald Heckmann
|
||||
Howard Su
|
||||
Huang Rui
|
||||
HungMingWu
|
||||
HyungKi Jeong
|
||||
Iru Cai
|
||||
Ivan Vnučec
|
||||
Iztok Jeras
|
||||
James Hanlon
|
||||
James Hutchinson
|
||||
James Pallister
|
||||
Jamey Hicks
|
||||
Jamie Iles
|
||||
Jan Van Winkel
|
||||
Jean Berniolles
|
||||
Jeremy Bennett
|
||||
@@ -43,12 +51,15 @@ John Coiner
|
||||
John Demme
|
||||
Jonathan Drolet
|
||||
Josh Redford
|
||||
Julie Schwartz
|
||||
Julien Margetts
|
||||
Kaleb Barrett
|
||||
Kanad Kanhere
|
||||
Keith Colbert
|
||||
Kevin Kiningham
|
||||
Krzysztof Bieganski
|
||||
Kuba Ober
|
||||
Larry Doolittle
|
||||
Ludwig Rogiers
|
||||
Lukasz Dalek
|
||||
Maarten De Braekeleer
|
||||
@@ -60,6 +71,7 @@ Marshal Qiao
|
||||
Martin Schmidt
|
||||
Matthew Ballance
|
||||
Michael Killough
|
||||
Michaël Lefebvre
|
||||
Mike Popoloski
|
||||
Miodrag Milanović
|
||||
Morten Borup Petersen
|
||||
@@ -76,6 +88,7 @@ Pieter Kapsenberg
|
||||
Piotr Binkowski
|
||||
Qingyao Sun
|
||||
Rafal Kapuscik
|
||||
Raynard Qiao
|
||||
Richard Myers
|
||||
Rupert Swarbrick
|
||||
Samuel Riedel
|
||||
@@ -85,6 +98,7 @@ Sergi Granell
|
||||
Stefan Wallentowitz
|
||||
Stephen Henry
|
||||
Steven Hugg
|
||||
Teng Huang
|
||||
Tim Snyder
|
||||
Tobias Rosenkranz
|
||||
Tobias Wölfel
|
||||
@@ -101,3 +115,4 @@ Yossi Nivin
|
||||
Yuri Victorovich
|
||||
Yutetsu TAKATSUKASA
|
||||
Yves Mathieu
|
||||
Zhanglei Wang
|
||||
|
||||
+1
-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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
.. comment: generated by t_lint_didnotconverge_bad
|
||||
.. code-block:: sv
|
||||
:linenos:
|
||||
|
||||
always_comb b = ~a;
|
||||
always_comb a = b;
|
||||
@@ -0,0 +1,7 @@
|
||||
.. comment: generated by t_lint_didnotconverge_bad
|
||||
.. code-block::
|
||||
|
||||
-V{t#,#}+ Vt_lint_didnotconverge_bad___024root___change_request
|
||||
-V{t#,#}+ Vt_lint_didnotconverge_bad___024root___change_request_1
|
||||
-V{t#,#} CHANGE: t/t_lint_didnotconverge_bad.v:14: a
|
||||
%Error: t/t_lint_didnotconverge_bad.v:7: Verilated model didn't converge
|
||||
@@ -0,0 +1,4 @@
|
||||
.. comment: generated by t_lint_didnotconverge_nodbg_bad
|
||||
.. code-block::
|
||||
|
||||
%Error: t/t_lint_didnotconverge_bad.v:7: Verilated model didn't converge
|
||||
@@ -0,0 +1,5 @@
|
||||
.. comment: generated by t_lint_stmtdly_bad
|
||||
.. code-block:: sv
|
||||
:emphasize-lines: 1
|
||||
|
||||
#100 $finish; //<--- Warning
|
||||
@@ -0,0 +1,4 @@
|
||||
.. comment: generated by t_lint_stmtdly_bad
|
||||
.. code-block::
|
||||
|
||||
%Warning-STMTDLY: example.v:1:8 Unsupported: Ignoring delay on this delayed statement.
|
||||
@@ -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
|
||||
|
||||
****************
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
# pylint: disable=C0103,C0114,C0116,E0402,W0622
|
||||
# pylint: disable=C0103,C0114,C0116,C0301,E0402,W0622
|
||||
#
|
||||
# Configuration file for Verilator's Sphinx documentation builder.
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
@@ -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:
|
||||
@@ -422,7 +422,7 @@ 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
|
||||
|
||||
@@ -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
|
||||
|
||||
************************
|
||||
|
||||
@@ -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,13 @@ 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.
|
||||
|
||||
XML locations
|
||||
The XML "fl" attribute has been replaced with the "loc" attribute. "fl"
|
||||
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.
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
@@ -62,6 +62,12 @@ Summary:
|
||||
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+vlt+file+<filename>
|
||||
|
||||
When a model was Verilated using :vlopt:`--prof-threads`, sets the
|
||||
profile-guided optimization data runtime filename to dump to. Defaults
|
||||
to :file:`profile.vlt`.
|
||||
|
||||
.. option:: +verilator+rand+reset+<value>
|
||||
|
||||
When a model was Verilated using :vlopt:`--x-initial unique
|
||||
|
||||
@@ -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
|
||||
@@ -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>
|
||||
|
||||
@@ -590,6 +575,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 +603,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
|
||||
@@ -816,7 +831,7 @@ Summary:
|
||||
When compiling the C++ code, enable the compiler's profiling flag
|
||||
(e.g. :code:`g++ -pg`). See :ref:`Profiling`.
|
||||
|
||||
Using :vlopt:`--prof-cfuncs` also enables :vlopt:`prof-c`.
|
||||
Using :vlopt:`--prof-cfuncs` also enables :vlopt:`--prof-c`.
|
||||
|
||||
.. option:: --prof-cfuncs
|
||||
|
||||
@@ -828,12 +843,12 @@ Summary:
|
||||
came from. This allows gprof or oprofile reports to be correlated with
|
||||
the original Verilog source statements. See :ref:`Profiling`.
|
||||
|
||||
Using :vlopt:`--prof-cfuncs` also enables :vlopt:`prof-c`.
|
||||
Using :vlopt:`--prof-cfuncs` also enables :vlopt:`--prof-c`.
|
||||
|
||||
.. option:: --prof-threads
|
||||
|
||||
Enable gantt chart data collection for threaded builds. See :ref:`Thread
|
||||
Profiling`.
|
||||
Profiling` and :ref:`Thread PGO`.
|
||||
|
||||
.. option:: --protect-key <key>
|
||||
|
||||
@@ -869,29 +884,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
|
||||
@@ -1167,9 +1173,9 @@ Summary:
|
||||
|
||||
.. 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 +1364,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 +1513,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 +1529,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>
|
||||
@@ -1612,6 +1627,12 @@ The grammar of configuration commands is as follows:
|
||||
:option:`/*verilator&32;public_flat*/`, etc, metacomments. See
|
||||
e.g. :ref:`VPI Example`.
|
||||
|
||||
.. option:: profile_data -mtask "<mtask_hash>" -cost <cost_value>
|
||||
|
||||
Feeds profile-guided optimization data into the Verilator algorithms in
|
||||
order to improve model runtime performance. This option is not expected
|
||||
to be used by users directly. See :ref:`Thread PGO`.
|
||||
|
||||
.. option:: sc_bv -module "<modulename>" [-task "<taskname>"] -var "<signame>"
|
||||
|
||||
.. option:: sc_bv -module "<modulename>" [-function "<funcname>"] -var "<signame>"
|
||||
|
||||
@@ -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
|
||||
@@ -10,42 +10,60 @@ starts and ends, and showing when each thread is busy or idle.
|
||||
|
||||
For an overview of use of verilator_gantt, see :ref:`Profiling`.
|
||||
|
||||
Gantt Chart Contents
|
||||
--------------------
|
||||
Gantt Chart VCD
|
||||
---------------
|
||||
|
||||
The generated Gantt chart has time on the X-axis. Times shown are to the
|
||||
scale printed, i.e. a certain about of time for each character width. The
|
||||
Y-axis shows threads, each thread's execution is shown on one line. That
|
||||
line shows "[" at the position in time when it executes.
|
||||
Verilated_gantt creates a value change dump (VCD) format dump file which
|
||||
may be viewed in a waveform viewer (e.g. C<GTKWave>):
|
||||
|
||||
Following the "[" is the CPU number the task executed on, followed by zero
|
||||
or more "-" to make the width of the characters match the scaled execution
|
||||
time, followed by a "]". If the scale is too small, the CPU number and
|
||||
mtask number will not be printed. If the scale is very small, a "&"
|
||||
indicates multiple mtasks started at that time position.
|
||||
.. figure:: figures/fig_gantt_min.png
|
||||
|
||||
Example verilator_gantt output, as viewed with GTKWave.
|
||||
|
||||
The viewed waveform chart has time on the X-axis, with one unit for each
|
||||
time tick of the system's high-performance counter.
|
||||
|
||||
Also creates a value change dump (VCD) format dump file which may be viewed
|
||||
in a waveform viewer (e.g. C<GTKWave>). See below.
|
||||
|
||||
Gantt Chart VCD Signals
|
||||
-----------------------
|
||||
|
||||
In waveforms there are the following signals. Most signals the "decimal"
|
||||
format will remove the leading zeros and make the traces easier to read.
|
||||
In waveforms there are the following signals. In GTKWave, using a data
|
||||
format of "decimal" will remove the leading zeros and make the traces
|
||||
easier to read.
|
||||
|
||||
parallelism
|
||||
evals
|
||||
Increments each time when eval_step was measured to be active. This
|
||||
allow visualization of how much time eval_step was active.
|
||||
|
||||
eval_loop
|
||||
Increments each time when the evaluation loop within eval_step was
|
||||
measured to be active. For best performance there is only a single
|
||||
evaluation loop within each eval_step call, that is the eval_loop
|
||||
waveform looks identical to the evals waveform.
|
||||
|
||||
measured_parallelism
|
||||
The number of mtasks active at this time, for best performance this will
|
||||
match the thread count. You may want to use an "analog step" format to
|
||||
match the thread count. In GTKWave, use a data format of "analog step" to
|
||||
view this signal.
|
||||
|
||||
predicted_parallelism
|
||||
The number of mtasks Verilator predicted would be active at this time,
|
||||
for best performance this will match the thread count. In GTKWave, use a
|
||||
data format of "analog step" to view this signal.
|
||||
|
||||
cpu#_thread
|
||||
For the given CPU number, the thread number executing.
|
||||
For the given CPU number, the thread number measured to be executing.
|
||||
|
||||
mtask#_cpu
|
||||
For the given mtask id, the CPU it is executing on.
|
||||
For the given mtask id, the CPU it was measured to execute on.
|
||||
|
||||
thread#_mtask
|
||||
For the given thread number, the mtask id executing.
|
||||
For the given thread number, the mtask id it was executing.
|
||||
|
||||
predicted_thread#_mtask
|
||||
For the given thread number, the mtask id Verilator predicted would be
|
||||
executing.
|
||||
|
||||
|
||||
verilator_gantt Arguments
|
||||
-------------------------
|
||||
@@ -60,13 +78,6 @@ The filename to read data from, defaults to "profile_threads.dat".
|
||||
|
||||
Displays a help summary, the program version, and exits.
|
||||
|
||||
.. option:: --scale <n>
|
||||
|
||||
Sets the number of time units per character on the X-axis of the generated
|
||||
Gantt chart. (On x86, time units are rdtsc ticks.) Defaults to 0, which
|
||||
will automatically compute a reasonable scale where no two mtasks need to
|
||||
fit into same character width's worth of scaled time.
|
||||
|
||||
.. option:: --no-vcd
|
||||
|
||||
Disables creating a .vcd file.
|
||||
|
||||
@@ -1,20 +1,24 @@
|
||||
.. Copyright 2003-2021 by Wilson Snyder.
|
||||
.. Copyright 2003-2022 by Wilson Snyder.
|
||||
.. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
verilator_profcfuncs
|
||||
====================
|
||||
verilator_profcfunc
|
||||
===================
|
||||
|
||||
Verilator_profcfunc reads a profile report created by gprof. The names of
|
||||
the functions are then transformed, assuming the user used Verilator's
|
||||
--prof-cfuncs, and a report printed showing the percentage of time, etc, in
|
||||
each Verilog block.
|
||||
|
||||
For an overview of use of verilator_profcfuncs, see :ref:`Profiling`.
|
||||
Due to rounding errors in gprof reports, the input report's percentages may
|
||||
not total to 100%. In the verilator_profcfunc report this will get
|
||||
reported as a rounding error.
|
||||
|
||||
verilator_profcfuncs Arguments
|
||||
------------------------------
|
||||
For an overview of use of verilator_profcfunc, see :ref:`Profiling`.
|
||||
|
||||
.. program:: verilator_profcfuncs
|
||||
verilator_profcfunc Arguments
|
||||
-----------------------------
|
||||
|
||||
.. program:: verilator_profcfunc
|
||||
|
||||
.. option:: <filename>
|
||||
|
||||
@@ -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
|
||||
|
||||
*********************************
|
||||
@@ -15,5 +15,5 @@ options to each executable.
|
||||
exe_verilator.rst
|
||||
exe_verilator_coverage.rst
|
||||
exe_verilator_gantt.rst
|
||||
exe_verilator_profcfuncs.rst
|
||||
exe_verilator_profcfunc.rst
|
||||
exe_sim.rst
|
||||
|
||||
@@ -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 bitmask
|
||||
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:
|
||||
|
||||
@@ -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
|
||||
|
||||
+8
-5
@@ -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
|
||||
@@ -132,7 +134,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()) {
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 37 KiB |
+22
-2
@@ -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
|
||||
|
||||
*****
|
||||
@@ -74,7 +74,7 @@ For --cc/--sc, it creates:
|
||||
- DPI import and export declarations (from --dpi)
|
||||
* - *{prefix}*\ __Dpi.cpp
|
||||
- Global DPI export wrappers (from --dpi)
|
||||
* - *{prefix}*\ __Dpi_Export\ *{__n}\ .cpp
|
||||
* - *{prefix}*\ __Dpi_Export\ *{__n}*\ .cpp
|
||||
- DPI export wrappers scoped to this particular model (from --dpi)
|
||||
* - *{prefix}*\ __Inlines.h
|
||||
- Inline support functions
|
||||
@@ -145,3 +145,23 @@ After running Make, the C++ compiler may produce the following:
|
||||
- Intermediate dependencies
|
||||
* - *{prefix}{misc}*\ .o
|
||||
- Intermediate objects
|
||||
|
||||
The Verilated executable may produce the following:
|
||||
|
||||
.. list-table::
|
||||
|
||||
* - coverage.dat
|
||||
- Code coverage output, and default input filename for :command:`verilator_coverage`
|
||||
* - 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_gantt`
|
||||
|
||||
Verilator_gantt may produce the following:
|
||||
|
||||
.. list-table::
|
||||
|
||||
* - profile_threads.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
|
||||
|
||||
######################
|
||||
|
||||
+12
-12
@@ -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:
|
||||
@@ -51,15 +51,15 @@ In brief, to install from git:
|
||||
unsetenv VERILATOR_ROOT # For csh; ignore error if on bash
|
||||
unset VERILATOR_ROOT # For bash
|
||||
cd verilator
|
||||
git pull # Make sure git repository is up-to-date
|
||||
git tag # See what versions exist
|
||||
git pull # Make sure git repository is up-to-date
|
||||
git tag # See what versions exist
|
||||
#git checkout master # Use development branch (e.g. recent bug fixes)
|
||||
#git checkout stable # Use most recent stable release
|
||||
#git checkout v{version} # Switch to specified release version
|
||||
|
||||
autoconf # Create ./configure script
|
||||
./configure # Configure and create Makefile
|
||||
make -j # Build Verilator itself
|
||||
autoconf # Create ./configure script
|
||||
./configure # Configure and create Makefile
|
||||
make -j `nproc` # Build Verilator itself (if error, try just 'make')
|
||||
sudo make install
|
||||
|
||||
|
||||
@@ -77,11 +77,11 @@ 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
|
||||
@@ -287,7 +287,7 @@ Compile Verilator:
|
||||
|
||||
::
|
||||
|
||||
make -j
|
||||
make -j `nproc` # Or if error on `nproc`, the number of CPUs in system
|
||||
|
||||
|
||||
Test
|
||||
|
||||
@@ -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
|
||||
|
||||
***************
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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 onwards, 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
|
||||
|
||||
********
|
||||
|
||||
+127
-7
@@ -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:
|
||||
@@ -26,7 +26,8 @@ risk of reset bugs in trade for performance; see the above documentation
|
||||
for these options.
|
||||
|
||||
If using Verilated multithreaded, use ``numactl`` to ensure you are using
|
||||
non-conflicting hardware resources. See :ref:`Multithreading`.
|
||||
non-conflicting hardware resources. See :ref:`Multithreading`. Also
|
||||
consider using profile-guided optimization, see :ref:`Thread PGO`.
|
||||
|
||||
Minor Verilog code changes can also give big wins. You should not have any
|
||||
UNOPTFLAT warnings from Verilator. Fixing these warnings can result in
|
||||
@@ -93,9 +94,7 @@ cases, for example regressions, it is usually worth spending extra
|
||||
compilation time to reduce total CPU time.
|
||||
|
||||
If you will be running many simulations on a single model, you can
|
||||
investigate profile guided optimization. With GCC, using GCC's
|
||||
"-fprofile-arcs", then GCC's "-fbranch-probabilities" will yield another
|
||||
15% or so.
|
||||
investigate profile guided optimization. See :ref:`Compiler PGO`.
|
||||
|
||||
Modern compilers also support link-time optimization (LTO), which can help
|
||||
especially if you link in DPI code. To enable LTO on GCC, pass "-flto" in
|
||||
@@ -230,7 +229,7 @@ coverage point insertions into the model and collect the coverage data.
|
||||
|
||||
To get the coverage data from the model, in the user wrapper code,
|
||||
typically at the end once a test passes, call
|
||||
:code:`Verilated::coveragep()->write` with an argument of the filename for
|
||||
:code:`Verilated::threadContextp()->coveragep()->write` with an argument of the filename for
|
||||
the coverage data file to write coverage data to (typically
|
||||
"logs/coverage.dat").
|
||||
|
||||
@@ -298,6 +297,9 @@ With the :vlopt:`--prof-threads` option, Verilator will:
|
||||
* Add code to save profiling data in non-human-friendly form to the file
|
||||
specified with :vlopt:`+verilator+prof+threads+file+\<filename\>`.
|
||||
|
||||
* Add code to save profiling data for thread profile-guided
|
||||
optimization. See :ref:`Thread PGO`.
|
||||
|
||||
The :command:`verilator_gantt` program may then be run to transform the
|
||||
saved profiling file into a nicer visual format and produce some related
|
||||
statistics.
|
||||
@@ -306,7 +308,7 @@ statistics.
|
||||
|
||||
Example verilator_gantt output, as viewed with GTKWave.
|
||||
|
||||
The parallelism shows the number of CPUs being used at a given moment.
|
||||
The measured_parallelism shows the number of CPUs being used at a given moment.
|
||||
|
||||
The cpu_thread section shows which thread is executing on each of the physical CPUs.
|
||||
|
||||
@@ -314,6 +316,7 @@ statistics.
|
||||
|
||||
For more information see :command:`verilator_gantt`.
|
||||
|
||||
|
||||
.. _Profiling ccache efficiency:
|
||||
|
||||
Profiling ccache efficiency
|
||||
@@ -377,3 +380,120 @@ For example:
|
||||
os >> main_time;
|
||||
os >> *topp;
|
||||
}
|
||||
|
||||
|
||||
Profile-Guided Optimization
|
||||
===========================
|
||||
|
||||
Profile-guided optimization is the technique where profiling data is
|
||||
collected by running your simulation executable, then this information is
|
||||
used to guide the next Verilation or compilation.
|
||||
|
||||
There are two forms of profile-guided optimizations. Unfortunately for
|
||||
best results they must each be performed from the highest level code to the
|
||||
lowest, which means performing them separately and in this order:
|
||||
|
||||
* :ref:`Thread PGO`
|
||||
* :ref:`Compiler PGO`
|
||||
|
||||
Other forms of PGO may be supported in the future, such as clock and reset
|
||||
toggle rate PGO, branch prediction PGO, statement execution time PGO, or
|
||||
others as they prove beneficial.
|
||||
|
||||
|
||||
.. _Thread PGO:
|
||||
|
||||
Thread Profile-Guided Optimization
|
||||
----------------------------------
|
||||
|
||||
Verilator supports thread profile-guided optimization (Thread PGO) to
|
||||
improve multithreaded 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
|
||||
Verilator internals document (:file:`docs/internals.rst` in the
|
||||
distribution.) If the estimations are incorrect, the threads will not be
|
||||
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.
|
||||
|
||||
Run the model executable. When the executable exits, it will create a
|
||||
profile.vlt file.
|
||||
|
||||
Rerun Verilator, optionally omitting the :vlopt:`--prof-threads` 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
|
||||
profile data file (profile.vlt) can be placed on the verilator command line
|
||||
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
|
||||
than a shorter running test.
|
||||
|
||||
If you provide any profile feedback data to Verilator, and it cannot use
|
||||
it, it will issue the :option:`PROFOUTOFDATE` warning that threads were
|
||||
scheduled using estimated costs. This usually indicates that the profile
|
||||
data was generated from different Verilog source code than Verilator is
|
||||
currently running against. Therefore, repeat the data collection phase to
|
||||
create new profiling data, then rerun Verilator with the same input source
|
||||
files and that new profiling data.
|
||||
|
||||
|
||||
.. _Compiler PGO:
|
||||
|
||||
Compiler Profile-Guided Optimization
|
||||
------------------------------------
|
||||
|
||||
GCC and Clang support compiler profile-guided optimization (PGO). This
|
||||
optimizes any C/C++ program including Verilated code. Using compiler PGO
|
||||
typically yields improvements of 5-15% on both single-threaded and
|
||||
multi-threaded models.
|
||||
|
||||
To use compiler PGO with GCC or Clang, please see the appropriate compiler
|
||||
documentation. The process in GCC 10 was as follows:
|
||||
|
||||
1. Compile the Verilated model with the compiler's "-fprofile-generate"
|
||||
flag:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
verilator [whatever_flags] --make \
|
||||
-CFLAGS -fprofile-generate -LDFLAGS -fprofile-generate
|
||||
|
||||
or, if calling make yourself, add -fprofile-generate appropriately to your
|
||||
Makefile.
|
||||
|
||||
2. Run your simulation. This will create \*.gcda file(s) in the same
|
||||
directory as the source files.
|
||||
|
||||
3. Recompile the model with -fprofile-use. The compiler will read the
|
||||
\*.gcda file(s).
|
||||
|
||||
For GCC:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
verilator [whatever_flags] --build \
|
||||
-CFLAGS "-fprofile-use -fprofile-correction"
|
||||
|
||||
For Clang:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
llvm-profdata merge -output default.profdata *.profraw
|
||||
verilator [whatever_flags] --build \
|
||||
-CFLAGS "-fprofile-use -fprofile-correction"
|
||||
|
||||
or, if calling make yourself, add these CFLAGS switches appropriately to
|
||||
your Makefile.
|
||||
|
||||
Clang and GCC also support -fauto-profile which uses sample-based
|
||||
feedback-directed optimization. See the appropriate compiler
|
||||
documentation.
|
||||
|
||||
@@ -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
|
||||
|
||||
+89
-40
@@ -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
|
||||
|
||||
*******************
|
||||
@@ -130,9 +130,10 @@ List Of Warnings
|
||||
|
||||
.. option:: BADSTDPRAGMA
|
||||
|
||||
Error that a pragma is badly formed, when that pragma is defined by IEEE1800-2017.
|
||||
For example, an empty `pragma line, or an incorrect specified '`pragma protect'.
|
||||
Note that 3rd party pragmas not defined by IEEE1800-2017 are ignored.
|
||||
Error that a pragma is badly formed, when that pragma is defined by IEEE
|
||||
1800-2017. For example, an empty pragma line, or an incorrect specified
|
||||
'pragma protect'. Note that 3rd party pragmas not defined by IEEE
|
||||
1800-2017 are ignored.
|
||||
|
||||
|
||||
.. option:: BLKANDNBLK
|
||||
@@ -446,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
|
||||
@@ -481,39 +482,44 @@ List Of Warnings
|
||||
|
||||
Faulty example:
|
||||
|
||||
.. code-block:: sv
|
||||
.. include:: ../../docs/gen/ex_DIDNOTCONVERGE_faulty.rst
|
||||
|
||||
always_comb b = ~a;
|
||||
always_comb a = b
|
||||
Results in at runtime (not when Verilated):
|
||||
|
||||
This code will toggle forever, and thus to prevent an infinite loop, the
|
||||
executable will give the didn't converge error.
|
||||
.. include:: ../../docs/gen/ex_DIDNOTCONVERGE_nodbg_msg.rst
|
||||
|
||||
To debug this, first review any UNOPTFLAT warnings that were ignored.
|
||||
Though typically it is safe to ignore UNOPTFLAT (at a performance cost),
|
||||
at the time of issuing a UNOPTFLAT Verilator did not know if the logic
|
||||
would eventually converge and assumed it would.
|
||||
This is because the signals keep toggling even with out time
|
||||
passing. Thus to prevent an infinite loop, the Verilated executable
|
||||
gives the DIDNOTCONVERGE error.
|
||||
|
||||
To debug this, first review any UNOPT or UNOPTFLAT warnings that were
|
||||
ignored. Though typically it is safe to ignore UNOPTFLAT (at a
|
||||
performance cost), at the time of issuing a UNOPTFLAT Verilator did not
|
||||
know if the logic would eventually converge and assumed it would.
|
||||
|
||||
Next, run Verilator with :vlopt:`--prof-cfuncs -CFLAGS -DVL_DEBUG
|
||||
<--prof-cfuncs>`. Rerun the test. Now just before the convergence
|
||||
error you should see additional output similar to this:
|
||||
|
||||
.. code-block::
|
||||
.. include:: ../../docs/gen/ex_DIDNOTCONVERGE_msg.rst
|
||||
|
||||
CHANGE: filename.v:1: b
|
||||
CHANGE: filename.v:2: a
|
||||
|
||||
This means that signal b and signal a keep changing, inspect the code
|
||||
that modifies these signals. Note if many signals are getting printed
|
||||
then most likely all of them are oscillating. It may also be that
|
||||
e.g. "a" may be oscillating, then "a" feeds signal "c" which then is
|
||||
also reported as oscillating.
|
||||
The CHANGE line means that on the given filename and line number that
|
||||
drove a signal, the signal 'a' kept changing. Inspect the code that
|
||||
modifies these signals. Note if many signals are getting printed then
|
||||
most likely all of them are oscillating. It may also be that e.g. "a"
|
||||
may be oscillating, then "a" feeds signal "c" which then is also
|
||||
reported as oscillating.
|
||||
|
||||
One way DIDNOTCONVERGE may occur is flops are built out of gate
|
||||
primitives. error. Verilator does not support building flops or latches
|
||||
out of gate primitives, and any such code must change to use behavioral
|
||||
primitives. Verilator does not support building flops or latches out of
|
||||
gate primitives, and any such code must change to use behavioral
|
||||
constructs (e.g. always_ff and always_latch).
|
||||
|
||||
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
|
||||
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
|
||||
generated C++ code to add appropriate prints to see what is going on.
|
||||
@@ -522,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
|
||||
@@ -572,7 +578,7 @@ List Of Warnings
|
||||
must end in newline, as otherwise for example :command:`cat` with the
|
||||
file as an argument may produce undesirable results.
|
||||
|
||||
Repair by adding a newline to the end of the file.
|
||||
Repair by appending a newline to the end of the file.
|
||||
|
||||
Disabled by default as this is a code style warning; it will simulate
|
||||
correctly.
|
||||
@@ -792,8 +798,8 @@ List Of Warnings
|
||||
.. TODO better example
|
||||
|
||||
Warns that a module has multiple definitions. Generally this indicates
|
||||
a coding error, or a mistake in a library file and it's good practice to
|
||||
have one module per file (and only put each file once on the command
|
||||
a coding error, or a mistake in a library file, and it's good practice
|
||||
to have one module per file (and only put each file once on the command
|
||||
line) to avoid these issues. For some gate level netlists duplicates
|
||||
are sometimes unavoidable, and MODDUP should be disabled.
|
||||
|
||||
@@ -918,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".
|
||||
|
||||
|
||||
@@ -1005,9 +1011,25 @@ List Of Warnings
|
||||
a var/reg must be used as the target of procedural assignments.
|
||||
|
||||
|
||||
.. option:: PROFOUTOFDATE
|
||||
|
||||
Warns that threads were scheduled using estimated costs, despite the
|
||||
fact that data was provided from profile-guided optimization (see
|
||||
:ref:`Thread PGO`) as fed into Verilator using the
|
||||
:option:`profile_data` configuration file option. This usually
|
||||
indicates that the profile data was generated from different Verilog
|
||||
source code than Verilator is currently running against.
|
||||
|
||||
It is recommended to create new profiling data, then rerun Verilator
|
||||
with the same input source files and that new profiling data.
|
||||
|
||||
Ignoring this warning may only slow simulations, it will simulate
|
||||
correctly.
|
||||
|
||||
|
||||
.. option:: PROTECTED
|
||||
|
||||
Warning that a '`pragma protected' section was encountered. The code
|
||||
Warning that a 'pragma protected' section was encountered. The code
|
||||
inside the protected region will be partly checked for correctness, but is
|
||||
otherwise ignored.
|
||||
|
||||
@@ -1183,9 +1205,25 @@ List Of Warnings
|
||||
|
||||
Faulty example:
|
||||
|
||||
.. code-block:: sv
|
||||
.. include:: ../../docs/gen/ex_STMTDLY_faulty.rst
|
||||
|
||||
#100 $finish; //<--- Warning
|
||||
Results in:
|
||||
|
||||
.. 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.
|
||||
|
||||
Some possible workarounds:
|
||||
|
||||
* Move the delayed statement into the C++ wrapper file, where the
|
||||
stimulus and clock generation can be done in C++.
|
||||
|
||||
* Convert the statement into a FSM, or other statement that tests
|
||||
against $time.
|
||||
|
||||
|
||||
.. option:: SYMRSVDWORD
|
||||
@@ -1353,7 +1391,9 @@ List Of Warnings
|
||||
|
||||
Often UNOPTFLAT is caused by logic that isn't truly circular as viewed by
|
||||
synthesis which analyzes interconnection per-bit, but is circular to
|
||||
simulation which analyzes per-bus:
|
||||
simulation which analyzes per-bus.
|
||||
|
||||
Faulty example:
|
||||
|
||||
.. code-block:: sv
|
||||
|
||||
@@ -1466,9 +1506,16 @@ 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
|
||||
common alternative language construct.
|
||||
|
||||
Alternatively, check if the construct is supported by other tools, and
|
||||
if so please consider submitting a github pull request against the
|
||||
Verilator sources to implement the missing unsupported feature.
|
||||
|
||||
This error may be ignored with :vlopt:`--bbox-unsup`, however this will
|
||||
make the design simulate incorrectly; see the details under
|
||||
:vlopt:`--bbox-unsup`.
|
||||
make the design simulate incorrectly and is only intended for lint
|
||||
usage; see the details under :vlopt:`--bbox-unsup`.
|
||||
|
||||
|
||||
.. option:: UNUSED
|
||||
@@ -1598,7 +1645,7 @@ List Of Warnings
|
||||
* A part select has a different size then needed to index into the
|
||||
packed or unpacked array (etc).
|
||||
|
||||
Verilator for attempts to track the minimum width of unsized constants
|
||||
Verilator attempts to track the minimum width of unsized constants
|
||||
and will suppress the warning when the minimum width is appropriate to
|
||||
fit the required size.
|
||||
|
||||
@@ -1607,11 +1654,13 @@ List Of Warnings
|
||||
|
||||
The recommendation is to fix these issues by:
|
||||
|
||||
* Resizing the variable or constant. E.g. :code:`2'd2` instead of :code:`3'd2`.
|
||||
* Resizing the variable or constant to match the needed size for the
|
||||
expression. E.g. :code:`2'd2` instead of :code:`3'd2`.
|
||||
|
||||
* Using :code:`'0` or :code:`'1`.
|
||||
* Using :code:`'0` or :code:`'1` which automatically resize in an
|
||||
expression.
|
||||
|
||||
* Using part select to narrow a variable. E.g. :code:`too_wide[1:0]`.
|
||||
* Using part selects to narrow a variable. E.g. :code:`too_wide[1:0]`.
|
||||
|
||||
* Using concatenate to widen a variable. E.g. :code:`{1'b1, too_narrow}`.
|
||||
|
||||
|
||||
+12
-9
@@ -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.
|
||||
|
||||
@@ -405,6 +405,9 @@ routines in the sources to rely more heavily on randomness, and
|
||||
generally try harder not to keep input nodes together when we have the
|
||||
option to scramble things.
|
||||
|
||||
Profile-guided optimization make this a bit better, by adjusting mtask
|
||||
scheduling, but this does not yet guide the packing into mtasks.
|
||||
|
||||
|
||||
Performance Regression
|
||||
""""""""""""""""""""""
|
||||
@@ -520,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
|
||||
@@ -601,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``
|
||||
@@ -1180,7 +1183,7 @@ 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.
|
||||
@@ -1205,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.
|
||||
|
||||
|
||||
@@ -676,7 +676,6 @@ prev
|
||||
printf
|
||||
printtimescale
|
||||
profcfunc
|
||||
profcfuncs
|
||||
prototyptes
|
||||
ps
|
||||
pthread
|
||||
|
||||
+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
|
||||
|
||||
@@ -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!");
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -103,8 +103,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]);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
+99
-71
@@ -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
|
||||
@@ -168,6 +168,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 +214,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 +231,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 "";
|
||||
|
||||
@@ -248,13 +271,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
|
||||
@@ -308,27 +331,28 @@ vluint64_t vl_rand64() VL_MT_SAFE {
|
||||
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 +361,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;
|
||||
@@ -387,7 +411,7 @@ WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, const WDataInP lwp, const WData
|
||||
if (vw == 1) { // Single divisor word breaks rest of algorithm
|
||||
vluint64_t k = 0;
|
||||
for (int j = uw - 1; j >= 0; --j) {
|
||||
vluint64_t unw64 = ((k << 32ULL) + static_cast<vluint64_t>(lwp[j]));
|
||||
const 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]);
|
||||
}
|
||||
@@ -444,7 +468,7 @@ WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, const WDataInP lwp, const WData
|
||||
vlsint64_t t = 0; // Must be signed
|
||||
vluint64_t k = 0;
|
||||
for (int i = 0; i < vw; ++i) {
|
||||
vluint64_t p = qhat * vn[i]; // Multiply by estimate
|
||||
const vluint64_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);
|
||||
@@ -683,23 +707,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);
|
||||
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 +772,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 +832,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;
|
||||
}
|
||||
@@ -856,7 +879,7 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
|
||||
std::string append;
|
||||
if (lbits <= VL_QUADSIZE) {
|
||||
digits = VL_SNPRINTF(
|
||||
t_tmp, VL_VALUE_STRING_MAX_WIDTH, "%" VL_PRI64 "d",
|
||||
t_tmp, VL_VALUE_STRING_MAX_WIDTH, "%" PRId64,
|
||||
static_cast<vlsint64_t>(VL_EXTENDS_QQ(lbits, lbits, ld)));
|
||||
append = t_tmp;
|
||||
} else {
|
||||
@@ -869,7 +892,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 +908,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 +975,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 +1049,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 +1063,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 +1120,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 +1159,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;
|
||||
@@ -1164,7 +1184,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;
|
||||
vlsint64_t ld = 0;
|
||||
std::sscanf(t_tmp, "%30" VL_PRI64 "d", &ld);
|
||||
std::sscanf(t_tmp, "%30" PRId64, &ld);
|
||||
VL_SET_WQ(owp, ld);
|
||||
break;
|
||||
}
|
||||
@@ -1189,7 +1209,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 +1312,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 +1497,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 +1550,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 +1620,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 '%':
|
||||
@@ -1622,7 +1643,7 @@ IData VL_VALUEPLUSARGS_INW(int rbits, const std::string& ld, WDataOutP rwp) VL_M
|
||||
switch (std::tolower(fmt)) {
|
||||
case 'd': {
|
||||
vlsint64_t lld = 0;
|
||||
std::sscanf(dp, "%30" VL_PRI64 "d", &lld);
|
||||
std::sscanf(dp, "%30" PRId64, &lld);
|
||||
VL_SET_WQ(rwp, lld);
|
||||
break;
|
||||
}
|
||||
@@ -1727,14 +1748,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;
|
||||
@@ -1823,7 +1844,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 +1903,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 +1930,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 +1997,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) {
|
||||
@@ -2068,7 +2090,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 +2125,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;
|
||||
|
||||
@@ -2258,6 +2280,7 @@ VerilatedContext::VerilatedContext()
|
||||
Verilated::lastContextp(this);
|
||||
Verilated::threadContextp(this);
|
||||
m_ns.m_profThreadsFilename = "profile_threads.dat";
|
||||
m_ns.m_profVltFilename = "profile.vlt";
|
||||
m_fdps.resize(31);
|
||||
std::fill(m_fdps.begin(), m_fdps.end(), static_cast<FILE*>(nullptr));
|
||||
m_fdFreeMct.resize(30);
|
||||
@@ -2340,6 +2363,14 @@ std::string VerilatedContext::profThreadsFilename() const VL_MT_SAFE {
|
||||
const VerilatedLockGuard lock{m_mutex};
|
||||
return m_ns.m_profThreadsFilename;
|
||||
}
|
||||
void VerilatedContext::profVltFilename(const std::string& flag) VL_MT_SAFE {
|
||||
const VerilatedLockGuard lock{m_mutex};
|
||||
m_ns.m_profVltFilename = flag;
|
||||
}
|
||||
std::string VerilatedContext::profVltFilename() const VL_MT_SAFE {
|
||||
const VerilatedLockGuard lock{m_mutex};
|
||||
return m_ns.m_profVltFilename;
|
||||
}
|
||||
void VerilatedContext::randReset(int val) VL_MT_SAFE {
|
||||
const VerilatedLockGuard lock{m_mutex};
|
||||
m_s.m_randReset = val;
|
||||
@@ -2495,6 +2526,8 @@ void VerilatedContextImp::commandArgVl(const std::string& arg) {
|
||||
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*/)) {
|
||||
@@ -2620,14 +2653,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];
|
||||
@@ -2635,8 +2665,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';
|
||||
@@ -2816,7 +2844,7 @@ 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);
|
||||
const int indxAdj = indx - low(dim);
|
||||
vluint8_t* bytep = reinterpret_cast<vluint8_t*>(datap);
|
||||
// If on index 1 of a 2 index array, then each index 1 is index2sz*entsz
|
||||
size_t slicesz = entSize();
|
||||
@@ -2861,7 +2889,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.
|
||||
@@ -2903,7 +2931,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());
|
||||
}
|
||||
@@ -2950,7 +2978,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);
|
||||
}
|
||||
}
|
||||
|
||||
+9
-4
@@ -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;
|
||||
@@ -346,6 +348,7 @@ protected:
|
||||
vluint32_t m_profThreadsWindow = 2; // +prof+threads window size
|
||||
// Slow path
|
||||
std::string m_profThreadsFilename; // +prof+threads filename
|
||||
std::string m_profVltFilename; // +prof+vlt filename
|
||||
} m_ns;
|
||||
|
||||
mutable VerilatedMutex m_argMutex; // Protect m_argVec, m_argVecLoaded
|
||||
@@ -358,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()
|
||||
|
||||
@@ -522,6 +525,8 @@ public: // But for internal use only
|
||||
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;
|
||||
void profVltFilename(const std::string& flag) VL_MT_SAFE;
|
||||
std::string profVltFilename() const VL_MT_SAFE;
|
||||
|
||||
// Internal: Find scope
|
||||
const VerilatedScope* scopeFind(const char* namep) const VL_MT_SAFE;
|
||||
@@ -820,8 +825,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;
|
||||
|
||||
@@ -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.
|
||||
@@ -23,8 +23,6 @@ CFG_WITH_LONGTESTS = @CFG_WITH_LONGTESTS@
|
||||
CFG_CXXFLAGS_PROFILE = @CFG_CXXFLAGS_PROFILE@
|
||||
# Select newest language
|
||||
CFG_CXXFLAGS_STD_NEWEST = @CFG_CXXFLAGS_STD_NEWEST@
|
||||
# Select oldest language (for Verilator internal testing only)
|
||||
CFG_CXXFLAGS_STD_OLDEST = @CFG_CXXFLAGS_STD_OLDEST@
|
||||
# Compiler flags to use to turn off unused and generated code warnings, such as -Wno-div-by-zero
|
||||
CFG_CXXFLAGS_NO_UNUSED = @CFG_CXXFLAGS_NO_UNUSED@
|
||||
# Compiler flags that turn on extra warnings
|
||||
@@ -225,7 +223,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 \
|
||||
@@ -234,7 +234,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@
|
||||
|
||||
+13
-11
@@ -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
|
||||
@@ -206,9 +207,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 +220,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 +232,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 +303,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 +343,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,13 +359,13 @@ 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();
|
||||
|
||||
std::ofstream os{filename};
|
||||
if (os.fail()) {
|
||||
std::string msg = std::string{"%Error: Can't write '"} + filename + "'";
|
||||
const std::string msg = std::string{"%Error: Can't write '"} + filename + "'";
|
||||
VL_FATAL_MT("", 0, "", msg.c_str());
|
||||
return;
|
||||
}
|
||||
@@ -380,8 +381,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;
|
||||
}
|
||||
|
||||
@@ -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 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)))
|
||||
@@ -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.
|
||||
|
||||
+21
-13
@@ -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.
|
||||
@@ -122,7 +122,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();
|
||||
@@ -158,18 +158,20 @@ void VerilatedFst::declDTypeEnum(int dtypenum, const char* name, vluint32_t elem
|
||||
}
|
||||
|
||||
void VerilatedFst::declare(vluint32_t code, const char* name, int dtypenum, fstVarDir vardir,
|
||||
fstVarType vartype, bool array, int arraynum, int msb, int lsb) {
|
||||
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 = VerilatedTrace<VerilatedFst>::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 +197,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 +207,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) {
|
||||
@@ -223,23 +226,23 @@ 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,
|
||||
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,
|
||||
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,
|
||||
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,
|
||||
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,
|
||||
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);
|
||||
}
|
||||
|
||||
// Note: emit* are only ever called from one place (full* in
|
||||
@@ -248,12 +251,14 @@ void VerilatedFst::declDouble(vluint32_t code, const char* name, int dtypenum, f
|
||||
|
||||
VL_ATTR_ALWINLINE
|
||||
void VerilatedFst::emitBit(vluint32_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) {
|
||||
char buf[VL_BYTESIZE];
|
||||
VL_DEBUG_IFDEF(assert(m_symbolp[code]););
|
||||
cvtCDataToStr(buf, newval << (VL_BYTESIZE - bits));
|
||||
fstWriterEmitValueChange(m_fst, m_symbolp[code], buf);
|
||||
}
|
||||
@@ -261,6 +266,7 @@ void VerilatedFst::emitCData(vluint32_t code, CData newval, int bits) {
|
||||
VL_ATTR_ALWINLINE
|
||||
void VerilatedFst::emitSData(vluint32_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);
|
||||
}
|
||||
@@ -268,6 +274,7 @@ void VerilatedFst::emitSData(vluint32_t code, SData newval, int bits) {
|
||||
VL_ATTR_ALWINLINE
|
||||
void VerilatedFst::emitIData(vluint32_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);
|
||||
}
|
||||
@@ -275,6 +282,7 @@ void VerilatedFst::emitIData(vluint32_t code, IData newval, int bits) {
|
||||
VL_ATTR_ALWINLINE
|
||||
void VerilatedFst::emitQData(vluint32_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);
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
@@ -54,7 +54,7 @@ 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);
|
||||
fstVarType vartype, bool array, int arraynum, bool bussed, int msb, int lsb);
|
||||
|
||||
protected:
|
||||
//=========================================================================
|
||||
@@ -121,6 +121,7 @@ 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 VerilatedTrace<VerilatedFst>::dumpvars(int level, const std::string& hier);
|
||||
#endif
|
||||
|
||||
//=============================================================================
|
||||
@@ -139,7 +140,7 @@ public:
|
||||
explicit VerilatedFstC(void* filep = nullptr)
|
||||
: m_sptrace{filep} {}
|
||||
/// Destruct, flush, and close the dump
|
||||
~VerilatedFstC() { close(); }
|
||||
virtual ~VerilatedFstC() { close(); }
|
||||
|
||||
// METHODS - User called
|
||||
|
||||
@@ -178,9 +179,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
|
||||
|
||||
|
||||
+163
-164
@@ -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.
|
||||
@@ -28,6 +28,8 @@
|
||||
#error "verilated_funcs.h should only be included by verilated.h"
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
|
||||
//=========================================================================
|
||||
// Extern functions -- User may override -- See verilated.cpp
|
||||
|
||||
@@ -43,12 +45,17 @@ extern void vl_finish(const char* filename, int linenum, const char* hier);
|
||||
/// Verilator internal code must call VL_FINISH_MT instead, which eventually calls this.
|
||||
extern void vl_stop(const char* filename, int linenum, const char* hier);
|
||||
|
||||
/// Routine to call for a couple of fatal messages
|
||||
/// Routine to call for fatal messages
|
||||
/// User code may wish to replace this function, to do so, define VL_USER_FATAL.
|
||||
/// This code does not have to be thread safe.
|
||||
/// Verilator internal code must call VL_FINISH_MT instead, which eventually calls this.
|
||||
extern void vl_fatal(const char* filename, int linenum, const char* hier, const char* msg);
|
||||
|
||||
/// Routine to call for warning messages
|
||||
/// User code may wish to replace this function, to do so, define VL_USER_WARN.
|
||||
/// This code does not have to be thread safe.
|
||||
extern void vl_warn(const char* filename, int linenum, const char* hier, const char* msg);
|
||||
|
||||
//=========================================================================
|
||||
// Extern functions -- Slow path
|
||||
|
||||
@@ -57,9 +64,12 @@ extern void VL_FINISH_MT(const char* filename, int linenum, const char* hier) VL
|
||||
/// Multithread safe wrapper for calls to $stop
|
||||
extern void VL_STOP_MT(const char* filename, int linenum, const char* hier,
|
||||
bool maybe = true) VL_MT_SAFE;
|
||||
/// Multithread safe wrapper to call for a couple of fatal messages
|
||||
/// Multithread safe wrapper to call for fatal messages
|
||||
extern void VL_FATAL_MT(const char* filename, int linenum, const char* hier,
|
||||
const char* msg) VL_MT_SAFE;
|
||||
/// Multithread safe wrapper to call for warning messages
|
||||
extern void VL_WARN_MT(const char* filename, int linenum, const char* hier,
|
||||
const char* msg) VL_MT_SAFE;
|
||||
|
||||
// clang-format off
|
||||
/// Print a string, multithread safe. Eventually VL_PRINTF will get called.
|
||||
@@ -73,18 +83,21 @@ extern void VL_PRINTF_MT(const char* formatp, ...) VL_ATTR_PRINTF(1) VL_MT_SAFE;
|
||||
/// Print a debug message from internals with standard prefix, with printf style format
|
||||
extern void VL_DBG_MSGF(const char* formatp, ...) VL_ATTR_PRINTF(1) VL_MT_SAFE;
|
||||
|
||||
inline IData VL_RANDOM_I(int obits) VL_MT_SAFE { return vl_rand64() & VL_MASK_I(obits); }
|
||||
inline QData VL_RANDOM_Q(int obits) VL_MT_SAFE { return vl_rand64() & VL_MASK_Q(obits); }
|
||||
#ifndef VL_NO_LEGACY
|
||||
// EMIT_RULE: VL_RANDOM: oclean=dirty
|
||||
inline IData VL_RANDOM_I() VL_MT_SAFE { return vl_rand64(); }
|
||||
inline QData VL_RANDOM_Q() VL_MT_SAFE { return vl_rand64(); }
|
||||
extern WDataOutP VL_RANDOM_W(int obits, WDataOutP outwp);
|
||||
#endif
|
||||
extern IData VL_RANDOM_SEEDED_II(int obits, IData seed) VL_MT_SAFE;
|
||||
extern IData VL_RANDOM_SEEDED_II(IData& seedr) VL_MT_SAFE;
|
||||
extern IData VL_URANDOM_SEEDED_II(IData seed) VL_MT_SAFE;
|
||||
inline IData VL_URANDOM_RANGE_I(IData hi, IData lo) {
|
||||
vluint64_t rnd = vl_rand64();
|
||||
const vluint64_t rnd = vl_rand64();
|
||||
if (VL_LIKELY(hi > lo)) {
|
||||
// (hi - lo + 1) can be zero when hi is UINT_MAX and lo is zero
|
||||
if (VL_UNLIKELY(hi - lo + 1 == 0)) return rnd;
|
||||
// Modulus isn't very fast but it's common that hi-low is power-of-two
|
||||
return (rnd % (hi - lo + 1)) + lo;
|
||||
} else {
|
||||
if (VL_UNLIKELY(lo - hi + 1 == 0)) return rnd;
|
||||
return (rnd % (lo - hi + 1)) + hi;
|
||||
}
|
||||
}
|
||||
@@ -149,10 +162,6 @@ extern const char* vl_mc_scan_plusargs(const char* prefixp); // PLIish
|
||||
// Base macros
|
||||
|
||||
// Return true if data[bit] set; not 0/1 return, but 0/non-zero return.
|
||||
#define VL_BITISSET_I(data, bit) ((data) & (VL_UL(1) << VL_BITBIT_I(bit)))
|
||||
#define VL_BITISSET_Q(data, bit) ((data) & (1ULL << VL_BITBIT_Q(bit)))
|
||||
#define VL_BITISSET_E(data, bit) ((data) & (VL_EUL(1) << VL_BITBIT_E(bit)))
|
||||
#define VL_BITISSET_W(data, bit) ((data)[VL_BITWORD_E(bit)] & (VL_EUL(1) << VL_BITBIT_E(bit)))
|
||||
#define VL_BITISSETLIMIT_W(data, width, bit) (((bit) < (width)) && VL_BITISSET_W(data, bit))
|
||||
|
||||
// Shift appropriate word by bit. Does not account for wrapping between two words
|
||||
@@ -330,13 +339,19 @@ double vl_time_multiplier(int scale) VL_PURE;
|
||||
vluint64_t vl_time_pow10(int n) VL_PURE;
|
||||
|
||||
#ifdef VL_DEBUG
|
||||
/// Evaluate statement if Verilated::debug() enabled
|
||||
/// Evaluate statement if VL_DEBUG defined
|
||||
# define VL_DEBUG_IFDEF(stmt) \
|
||||
do { \
|
||||
stmt \
|
||||
} while (false)
|
||||
/// Evaluate statement if VL_DEBUG defined and Verilated::debug() enabled
|
||||
# define VL_DEBUG_IF(stmt) \
|
||||
do { \
|
||||
if (VL_UNLIKELY(Verilated::debug())) {stmt} \
|
||||
} while (false)
|
||||
#else
|
||||
// We intentionally do not compile the stmt to improve compile speed
|
||||
# define VL_DEBUG_IFDEF(stmt) do {} while (false)
|
||||
# define VL_DEBUG_IF(stmt) do {} while (false)
|
||||
#endif
|
||||
|
||||
@@ -360,13 +375,13 @@ vluint64_t vl_time_pow10(int n) VL_PURE;
|
||||
#define VL_CLEAN_QQ(obits, lbits, lhs) ((lhs)&VL_MASK_Q(obits))
|
||||
|
||||
// EMIT_RULE: VL_ASSIGNCLEAN: oclean=clean; obits==lbits;
|
||||
#define VL_ASSIGNCLEAN_W(obits, owp, lwp) VL_CLEAN_WW((obits), (obits), (owp), (lwp))
|
||||
#define VL_ASSIGNCLEAN_W(obits, owp, lwp) VL_CLEAN_WW((obits), (owp), (lwp))
|
||||
static inline WDataOutP _vl_clean_inplace_w(int obits, WDataOutP owp) VL_MT_SAFE {
|
||||
const int words = VL_WORDS_I(obits);
|
||||
owp[words - 1] &= VL_MASK_E(obits);
|
||||
return owp;
|
||||
}
|
||||
static inline WDataOutP VL_CLEAN_WW(int obits, int, WDataOutP owp, WDataInP const lwp) VL_MT_SAFE {
|
||||
static inline WDataOutP VL_CLEAN_WW(int obits, WDataOutP owp, WDataInP const lwp) VL_MT_SAFE {
|
||||
const int words = VL_WORDS_I(obits);
|
||||
for (int i = 0; (i < (words - 1)); ++i) owp[i] = lwp[i];
|
||||
owp[words - 1] = lwp[words - 1] & VL_MASK_E(obits);
|
||||
@@ -394,37 +409,37 @@ static inline WDataOutP VL_ASSIGN_W(int obits, WDataOutP owp, WDataInP const lwp
|
||||
}
|
||||
|
||||
// EMIT_RULE: VL_ASSIGNBIT: rclean=clean;
|
||||
static inline void VL_ASSIGNBIT_II(int, int bit, CData& lhsr, IData rhs) VL_PURE {
|
||||
static inline void VL_ASSIGNBIT_II(int bit, CData& lhsr, IData rhs) VL_PURE {
|
||||
lhsr = ((lhsr & ~(VL_UL(1) << VL_BITBIT_I(bit))) | (rhs << VL_BITBIT_I(bit)));
|
||||
}
|
||||
static inline void VL_ASSIGNBIT_II(int, int bit, SData& lhsr, IData rhs) VL_PURE {
|
||||
static inline void VL_ASSIGNBIT_II(int bit, SData& lhsr, IData rhs) VL_PURE {
|
||||
lhsr = ((lhsr & ~(VL_UL(1) << VL_BITBIT_I(bit))) | (rhs << VL_BITBIT_I(bit)));
|
||||
}
|
||||
static inline void VL_ASSIGNBIT_II(int, int bit, IData& lhsr, IData rhs) VL_PURE {
|
||||
static inline void VL_ASSIGNBIT_II(int bit, IData& lhsr, IData rhs) VL_PURE {
|
||||
lhsr = ((lhsr & ~(VL_UL(1) << VL_BITBIT_I(bit))) | (rhs << VL_BITBIT_I(bit)));
|
||||
}
|
||||
static inline void VL_ASSIGNBIT_QI(int, int bit, QData& lhsr, QData rhs) VL_PURE {
|
||||
static inline void VL_ASSIGNBIT_QI(int bit, QData& lhsr, QData rhs) VL_PURE {
|
||||
lhsr = ((lhsr & ~(1ULL << VL_BITBIT_Q(bit))) | (static_cast<QData>(rhs) << VL_BITBIT_Q(bit)));
|
||||
}
|
||||
static inline void VL_ASSIGNBIT_WI(int, int bit, WDataOutP owp, IData rhs) VL_MT_SAFE {
|
||||
EData orig = owp[VL_BITWORD_E(bit)];
|
||||
static inline void VL_ASSIGNBIT_WI(int bit, WDataOutP owp, IData rhs) VL_MT_SAFE {
|
||||
const EData orig = owp[VL_BITWORD_E(bit)];
|
||||
owp[VL_BITWORD_E(bit)] = ((orig & ~(VL_EUL(1) << VL_BITBIT_E(bit)))
|
||||
| (static_cast<EData>(rhs) << VL_BITBIT_E(bit)));
|
||||
}
|
||||
// Alternative form that is an instruction faster when rhs is constant one.
|
||||
static inline void VL_ASSIGNBIT_IO(int, int bit, CData& lhsr, IData) VL_PURE {
|
||||
static inline void VL_ASSIGNBIT_IO(int bit, CData& lhsr) VL_PURE {
|
||||
lhsr = (lhsr | (VL_UL(1) << VL_BITBIT_I(bit)));
|
||||
}
|
||||
static inline void VL_ASSIGNBIT_IO(int, int bit, SData& lhsr, IData) VL_PURE {
|
||||
static inline void VL_ASSIGNBIT_IO(int bit, SData& lhsr) VL_PURE {
|
||||
lhsr = (lhsr | (VL_UL(1) << VL_BITBIT_I(bit)));
|
||||
}
|
||||
static inline void VL_ASSIGNBIT_IO(int, int bit, IData& lhsr, IData) VL_PURE {
|
||||
static inline void VL_ASSIGNBIT_IO(int bit, IData& lhsr) VL_PURE {
|
||||
lhsr = (lhsr | (VL_UL(1) << VL_BITBIT_I(bit)));
|
||||
}
|
||||
static inline void VL_ASSIGNBIT_QO(int, int bit, QData& lhsr, IData) VL_PURE {
|
||||
static inline void VL_ASSIGNBIT_QO(int bit, QData& lhsr) VL_PURE {
|
||||
lhsr = (lhsr | (1ULL << VL_BITBIT_Q(bit)));
|
||||
}
|
||||
static inline void VL_ASSIGNBIT_WO(int, int bit, WDataOutP owp, IData) VL_MT_SAFE {
|
||||
static inline void VL_ASSIGNBIT_WO(int bit, WDataOutP owp) VL_MT_SAFE {
|
||||
const EData orig = owp[VL_BITWORD_E(bit)];
|
||||
owp[VL_BITWORD_E(bit)] = (orig | (VL_EUL(1) << VL_BITBIT_E(bit)));
|
||||
}
|
||||
@@ -585,9 +600,9 @@ static inline WDataOutP VL_EXTENDS_WW(int obits, int lbits, WDataOutP owp,
|
||||
// REDUCTION OPERATORS
|
||||
|
||||
// EMIT_RULE: VL_REDAND: oclean=clean; lclean==clean; obits=1;
|
||||
#define VL_REDAND_II(obits, lbits, lhs) ((lhs) == VL_MASK_I(lbits))
|
||||
#define VL_REDAND_IQ(obits, lbits, lhs) ((lhs) == VL_MASK_Q(lbits))
|
||||
static inline IData VL_REDAND_IW(int, int lbits, WDataInP const lwp) VL_MT_SAFE {
|
||||
#define VL_REDAND_II(lbits, lhs) ((lhs) == VL_MASK_I(lbits))
|
||||
#define VL_REDAND_IQ(lbits, lhs) ((lhs) == VL_MASK_Q(lbits))
|
||||
static inline IData VL_REDAND_IW(int lbits, WDataInP const lwp) VL_MT_SAFE {
|
||||
const int words = VL_WORDS_I(lbits);
|
||||
EData combine = lwp[0];
|
||||
for (int i = 1; i < words - 1; ++i) combine &= lwp[i];
|
||||
@@ -693,11 +708,11 @@ static inline IData VL_COUNTONES_W(int words, WDataInP const lwp) VL_MT_SAFE {
|
||||
// EMIT_RULE: VL_COUNTBITS_II: oclean = false; lhs clean
|
||||
static inline IData VL_COUNTBITS_I(int lbits, IData lhs, IData ctrl0, IData ctrl1,
|
||||
IData ctrl2) VL_PURE {
|
||||
int ctrlSum = (ctrl0 & 0x1) + (ctrl1 & 0x1) + (ctrl2 & 0x1);
|
||||
const int ctrlSum = (ctrl0 & 0x1) + (ctrl1 & 0x1) + (ctrl2 & 0x1);
|
||||
if (ctrlSum == 3) {
|
||||
return VL_COUNTONES_I(lhs);
|
||||
} else if (ctrlSum == 0) {
|
||||
IData mask = (lbits == 32) ? -1 : ((1 << lbits) - 1);
|
||||
const IData mask = (lbits == 32) ? -1 : ((1 << lbits) - 1);
|
||||
return VL_COUNTONES_I(~lhs & mask);
|
||||
} else {
|
||||
return (lbits == 32) ? 32 : lbits;
|
||||
@@ -768,7 +783,7 @@ static inline IData VL_CLOG2_Q(QData lhs) VL_PURE {
|
||||
return shifts;
|
||||
}
|
||||
static inline IData VL_CLOG2_W(int words, WDataInP const lwp) VL_MT_SAFE {
|
||||
EData adjust = (VL_COUNTONES_W(words, lwp) == 1) ? 0 : 1;
|
||||
const EData adjust = (VL_COUNTONES_W(words, lwp) == 1) ? 0 : 1;
|
||||
for (int i = words - 1; i >= 0; --i) {
|
||||
if (VL_UNLIKELY(lwp[i])) { // Shorter worst case if predict not taken
|
||||
for (int bit = VL_EDATASIZE - 1; bit >= 0; --bit) {
|
||||
@@ -859,52 +874,52 @@ static inline int _vl_cmp_w(int words, WDataInP const lwp, WDataInP const rwp) V
|
||||
return 0; // ==
|
||||
}
|
||||
|
||||
#define VL_LTS_IWW(obits, lbits, rbbits, lwp, rwp) (_vl_cmps_w(lbits, lwp, rwp) < 0)
|
||||
#define VL_LTES_IWW(obits, lbits, rbits, lwp, rwp) (_vl_cmps_w(lbits, lwp, rwp) <= 0)
|
||||
#define VL_GTS_IWW(obits, lbits, rbits, lwp, rwp) (_vl_cmps_w(lbits, lwp, rwp) > 0)
|
||||
#define VL_GTES_IWW(obits, lbits, rbits, lwp, rwp) (_vl_cmps_w(lbits, lwp, rwp) >= 0)
|
||||
#define VL_LTS_IWW(lbits, lwp, rwp) (_vl_cmps_w(lbits, lwp, rwp) < 0)
|
||||
#define VL_LTES_IWW(lbits, lwp, rwp) (_vl_cmps_w(lbits, lwp, rwp) <= 0)
|
||||
#define VL_GTS_IWW(lbits, lwp, rwp) (_vl_cmps_w(lbits, lwp, rwp) > 0)
|
||||
#define VL_GTES_IWW(lbits, lwp, rwp) (_vl_cmps_w(lbits, lwp, rwp) >= 0)
|
||||
|
||||
static inline IData VL_GTS_III(int, int lbits, int, IData lhs, IData rhs) VL_PURE {
|
||||
static inline IData VL_GTS_III(int lbits, IData lhs, IData rhs) VL_PURE {
|
||||
// For lbits==32, this becomes just a single instruction, otherwise ~5.
|
||||
// GCC 3.3.4 sign extension bugs on AMD64 architecture force us to use quad logic
|
||||
const vlsint64_t lhs_signed = VL_EXTENDS_QQ(64, lbits, lhs); // Q for gcc
|
||||
const vlsint64_t rhs_signed = VL_EXTENDS_QQ(64, lbits, rhs); // Q for gcc
|
||||
return lhs_signed > rhs_signed;
|
||||
}
|
||||
static inline IData VL_GTS_IQQ(int, int lbits, int, QData lhs, QData rhs) VL_PURE {
|
||||
static inline IData VL_GTS_IQQ(int lbits, QData lhs, QData rhs) VL_PURE {
|
||||
const vlsint64_t lhs_signed = VL_EXTENDS_QQ(64, lbits, lhs);
|
||||
const vlsint64_t rhs_signed = VL_EXTENDS_QQ(64, lbits, rhs);
|
||||
return lhs_signed > rhs_signed;
|
||||
}
|
||||
|
||||
static inline IData VL_GTES_III(int, int lbits, int, IData lhs, IData rhs) VL_PURE {
|
||||
static inline IData VL_GTES_III(int lbits, IData lhs, IData rhs) VL_PURE {
|
||||
const vlsint64_t lhs_signed = VL_EXTENDS_QQ(64, lbits, lhs); // Q for gcc
|
||||
const vlsint64_t rhs_signed = VL_EXTENDS_QQ(64, lbits, rhs); // Q for gcc
|
||||
return lhs_signed >= rhs_signed;
|
||||
}
|
||||
static inline IData VL_GTES_IQQ(int, int lbits, int, QData lhs, QData rhs) VL_PURE {
|
||||
static inline IData VL_GTES_IQQ(int lbits, QData lhs, QData rhs) VL_PURE {
|
||||
const vlsint64_t lhs_signed = VL_EXTENDS_QQ(64, lbits, lhs);
|
||||
const vlsint64_t rhs_signed = VL_EXTENDS_QQ(64, lbits, rhs);
|
||||
return lhs_signed >= rhs_signed;
|
||||
}
|
||||
|
||||
static inline IData VL_LTS_III(int, int lbits, int, IData lhs, IData rhs) VL_PURE {
|
||||
static inline IData VL_LTS_III(int lbits, IData lhs, IData rhs) VL_PURE {
|
||||
const vlsint64_t lhs_signed = VL_EXTENDS_QQ(64, lbits, lhs); // Q for gcc
|
||||
const vlsint64_t rhs_signed = VL_EXTENDS_QQ(64, lbits, rhs); // Q for gcc
|
||||
return lhs_signed < rhs_signed;
|
||||
}
|
||||
static inline IData VL_LTS_IQQ(int, int lbits, int, QData lhs, QData rhs) VL_PURE {
|
||||
static inline IData VL_LTS_IQQ(int lbits, QData lhs, QData rhs) VL_PURE {
|
||||
const vlsint64_t lhs_signed = VL_EXTENDS_QQ(64, lbits, lhs);
|
||||
const vlsint64_t rhs_signed = VL_EXTENDS_QQ(64, lbits, rhs);
|
||||
return lhs_signed < rhs_signed;
|
||||
}
|
||||
|
||||
static inline IData VL_LTES_III(int, int lbits, int, IData lhs, IData rhs) VL_PURE {
|
||||
static inline IData VL_LTES_III(int lbits, IData lhs, IData rhs) VL_PURE {
|
||||
const vlsint64_t lhs_signed = VL_EXTENDS_QQ(64, lbits, lhs); // Q for gcc
|
||||
const vlsint64_t rhs_signed = VL_EXTENDS_QQ(64, lbits, rhs); // Q for gcc
|
||||
return lhs_signed <= rhs_signed;
|
||||
}
|
||||
static inline IData VL_LTES_IQQ(int, int lbits, int, QData lhs, QData rhs) VL_PURE {
|
||||
static inline IData VL_LTES_IQQ(int lbits, QData lhs, QData rhs) VL_PURE {
|
||||
const vlsint64_t lhs_signed = VL_EXTENDS_QQ(64, lbits, lhs);
|
||||
const vlsint64_t rhs_signed = VL_EXTENDS_QQ(64, lbits, rhs);
|
||||
return lhs_signed <= rhs_signed;
|
||||
@@ -940,7 +955,7 @@ static inline WDataOutP VL_NEGATE_W(int words, WDataOutP owp, WDataInP const lwp
|
||||
static inline void VL_NEGATE_INPLACE_W(int words, WDataOutP owp_lwp) VL_MT_SAFE {
|
||||
EData carry = 1;
|
||||
for (int i = 0; i < words; ++i) {
|
||||
EData word = ~owp_lwp[i] + carry;
|
||||
const EData word = ~owp_lwp[i] + carry;
|
||||
carry = (word < ~owp_lwp[i]);
|
||||
owp_lwp[i] = word;
|
||||
}
|
||||
@@ -999,18 +1014,18 @@ static inline WDataOutP VL_MUL_W(int words, WDataOutP owp, WDataInP const lwp,
|
||||
return owp;
|
||||
}
|
||||
|
||||
static inline IData VL_MULS_III(int, int lbits, int, IData lhs, IData rhs) VL_PURE {
|
||||
static inline IData VL_MULS_III(int lbits, IData lhs, IData rhs) VL_PURE {
|
||||
const vlsint32_t lhs_signed = VL_EXTENDS_II(32, lbits, lhs);
|
||||
const vlsint32_t rhs_signed = VL_EXTENDS_II(32, lbits, rhs);
|
||||
return lhs_signed * rhs_signed;
|
||||
}
|
||||
static inline QData VL_MULS_QQQ(int, int lbits, int, QData lhs, QData rhs) VL_PURE {
|
||||
static inline QData VL_MULS_QQQ(int lbits, QData lhs, QData rhs) VL_PURE {
|
||||
const vlsint64_t lhs_signed = VL_EXTENDS_QQ(64, lbits, lhs);
|
||||
const vlsint64_t rhs_signed = VL_EXTENDS_QQ(64, lbits, rhs);
|
||||
return lhs_signed * rhs_signed;
|
||||
}
|
||||
|
||||
static inline WDataOutP VL_MULS_WWW(int, int lbits, int, WDataOutP owp, WDataInP const lwp,
|
||||
static inline WDataOutP VL_MULS_WWW(int lbits, WDataOutP owp, WDataInP const lwp,
|
||||
WDataInP const rwp) VL_MT_SAFE {
|
||||
const int words = VL_WORDS_I(lbits);
|
||||
// cppcheck-suppress variableScope
|
||||
@@ -1019,13 +1034,13 @@ static inline WDataOutP VL_MULS_WWW(int, int lbits, int, WDataOutP owp, WDataInP
|
||||
WData rwstore[VL_MULS_MAX_WORDS];
|
||||
WDataInP lwusp = lwp;
|
||||
WDataInP rwusp = rwp;
|
||||
EData lneg = VL_SIGN_E(lbits, lwp[words - 1]);
|
||||
const EData lneg = VL_SIGN_E(lbits, lwp[words - 1]);
|
||||
if (lneg) { // Negate lhs
|
||||
lwusp = lwstore;
|
||||
VL_NEGATE_W(words, lwstore, lwp);
|
||||
lwstore[words - 1] &= VL_MASK_E(lbits); // Clean it
|
||||
}
|
||||
EData rneg = VL_SIGN_E(lbits, rwp[words - 1]);
|
||||
const EData rneg = VL_SIGN_E(lbits, rwp[words - 1]);
|
||||
if (rneg) { // Negate rhs
|
||||
rwusp = rwstore;
|
||||
VL_NEGATE_W(words, rwstore, rwp);
|
||||
@@ -1218,31 +1233,27 @@ QData VL_POWSS_QQW(int obits, int, int rbits, QData lhs, WDataInP const rwp, boo
|
||||
|
||||
// INTERNAL: Stuff LHS bit 0++ into OUTPUT at specified offset
|
||||
// ld may be "dirty", output is clean
|
||||
static inline void _vl_insert_II(int, CData& lhsr, IData ld, int hbit, int lbit,
|
||||
int rbits) VL_PURE {
|
||||
static inline void _vl_insert_II(CData& lhsr, IData ld, int hbit, int lbit, int rbits) VL_PURE {
|
||||
const IData cleanmask = VL_MASK_I(rbits);
|
||||
const IData insmask = (VL_MASK_I(hbit - lbit + 1)) << lbit;
|
||||
lhsr = (lhsr & ~insmask) | ((ld << lbit) & (insmask & cleanmask));
|
||||
}
|
||||
static inline void _vl_insert_II(int, SData& lhsr, IData ld, int hbit, int lbit,
|
||||
int rbits) VL_PURE {
|
||||
static inline void _vl_insert_II(SData& lhsr, IData ld, int hbit, int lbit, int rbits) VL_PURE {
|
||||
const IData cleanmask = VL_MASK_I(rbits);
|
||||
const IData insmask = (VL_MASK_I(hbit - lbit + 1)) << lbit;
|
||||
lhsr = (lhsr & ~insmask) | ((ld << lbit) & (insmask & cleanmask));
|
||||
}
|
||||
static inline void _vl_insert_II(int, IData& lhsr, IData ld, int hbit, int lbit,
|
||||
int rbits) VL_PURE {
|
||||
static inline void _vl_insert_II(IData& lhsr, IData ld, int hbit, int lbit, int rbits) VL_PURE {
|
||||
const IData cleanmask = VL_MASK_I(rbits);
|
||||
const IData insmask = (VL_MASK_I(hbit - lbit + 1)) << lbit;
|
||||
lhsr = (lhsr & ~insmask) | ((ld << lbit) & (insmask & cleanmask));
|
||||
}
|
||||
static inline void _vl_insert_QQ(int, QData& lhsr, QData ld, int hbit, int lbit,
|
||||
int rbits) VL_PURE {
|
||||
static inline void _vl_insert_QQ(QData& lhsr, QData ld, int hbit, int lbit, int rbits) VL_PURE {
|
||||
const QData cleanmask = VL_MASK_Q(rbits);
|
||||
const QData insmask = (VL_MASK_Q(hbit - lbit + 1)) << lbit;
|
||||
lhsr = (lhsr & ~insmask) | ((ld << lbit) & (insmask & cleanmask));
|
||||
}
|
||||
static inline void _vl_insert_WI(int, WDataOutP owp, IData ld, int hbit, int lbit,
|
||||
static inline void _vl_insert_WI(WDataOutP owp, IData ld, int hbit, int lbit,
|
||||
int rbits = 0) VL_MT_SAFE {
|
||||
const int hoffset = VL_BITBIT_E(hbit);
|
||||
const int loffset = VL_BITBIT_E(lbit);
|
||||
@@ -1275,7 +1286,7 @@ static inline void _vl_insert_WI(int, WDataOutP owp, IData ld, int hbit, int lbi
|
||||
|
||||
// INTERNAL: Stuff large LHS bit 0++ into OUTPUT at specified offset
|
||||
// lwp may be "dirty"
|
||||
static inline void _vl_insert_WW(int, WDataOutP owp, WDataInP const lwp, int hbit, int lbit,
|
||||
static inline void _vl_insert_WW(WDataOutP owp, WDataInP const lwp, int hbit, int lbit,
|
||||
int rbits = 0) VL_MT_SAFE {
|
||||
const int hoffset = VL_BITBIT_E(hbit);
|
||||
const int loffset = VL_BITBIT_E(lbit);
|
||||
@@ -1331,19 +1342,19 @@ static inline void _vl_insert_WW(int, WDataOutP owp, WDataInP const lwp, int hbi
|
||||
}
|
||||
}
|
||||
|
||||
static inline void _vl_insert_WQ(int obits, WDataOutP owp, QData ld, int hbit, int lbit,
|
||||
static inline void _vl_insert_WQ(WDataOutP owp, QData ld, int hbit, int lbit,
|
||||
int rbits = 0) VL_MT_SAFE {
|
||||
VlWide<VL_WQ_WORDS_E> lwp;
|
||||
VL_SET_WQ(lwp, ld);
|
||||
_vl_insert_WW(obits, owp, lwp, hbit, lbit, rbits);
|
||||
_vl_insert_WW(owp, lwp, hbit, lbit, rbits);
|
||||
}
|
||||
|
||||
// EMIT_RULE: VL_REPLICATE: oclean=clean>width32, dirty<=width32; lclean=clean; rclean==clean;
|
||||
// RHS MUST BE CLEAN CONSTANT.
|
||||
#define VL_REPLICATE_IOI(obits, lbits, rbits, ld, rep) (-(ld)) // Iff lbits==1
|
||||
#define VL_REPLICATE_QOI(obits, lbits, rbits, ld, rep) (-(static_cast<QData>(ld))) // Iff lbits==1
|
||||
#define VL_REPLICATE_IOI(lbits, ld, rep) (-(ld)) // Iff lbits==1
|
||||
#define VL_REPLICATE_QOI(lbits, ld, rep) (-(static_cast<QData>(ld))) // Iff lbits==1
|
||||
|
||||
static inline IData VL_REPLICATE_III(int, int lbits, int, IData ld, IData rep) VL_PURE {
|
||||
static inline IData VL_REPLICATE_III(int lbits, IData ld, IData rep) VL_PURE {
|
||||
IData returndata = ld;
|
||||
for (unsigned i = 1; i < rep; ++i) {
|
||||
returndata = returndata << lbits;
|
||||
@@ -1351,7 +1362,7 @@ static inline IData VL_REPLICATE_III(int, int lbits, int, IData ld, IData rep) V
|
||||
}
|
||||
return returndata;
|
||||
}
|
||||
static inline QData VL_REPLICATE_QII(int, int lbits, int, IData ld, IData rep) VL_PURE {
|
||||
static inline QData VL_REPLICATE_QII(int lbits, IData ld, IData rep) VL_PURE {
|
||||
QData returndata = ld;
|
||||
for (unsigned i = 1; i < rep; ++i) {
|
||||
returndata = returndata << lbits;
|
||||
@@ -1359,27 +1370,27 @@ static inline QData VL_REPLICATE_QII(int, int lbits, int, IData ld, IData rep) V
|
||||
}
|
||||
return returndata;
|
||||
}
|
||||
static inline WDataOutP VL_REPLICATE_WII(int obits, int lbits, int, WDataOutP owp, IData ld,
|
||||
static inline WDataOutP VL_REPLICATE_WII(int lbits, WDataOutP owp, IData ld,
|
||||
IData rep) VL_MT_SAFE {
|
||||
owp[0] = ld;
|
||||
for (unsigned i = 1; i < rep; ++i) {
|
||||
_vl_insert_WI(obits, owp, ld, i * lbits + lbits - 1, i * lbits);
|
||||
_vl_insert_WI(owp, ld, i * lbits + lbits - 1, i * lbits);
|
||||
}
|
||||
return owp;
|
||||
}
|
||||
static inline WDataOutP VL_REPLICATE_WQI(int obits, int lbits, int, WDataOutP owp, QData ld,
|
||||
static inline WDataOutP VL_REPLICATE_WQI(int lbits, WDataOutP owp, QData ld,
|
||||
IData rep) VL_MT_SAFE {
|
||||
VL_SET_WQ(owp, ld);
|
||||
for (unsigned i = 1; i < rep; ++i) {
|
||||
_vl_insert_WQ(obits, owp, ld, i * lbits + lbits - 1, i * lbits);
|
||||
_vl_insert_WQ(owp, ld, i * lbits + lbits - 1, i * lbits);
|
||||
}
|
||||
return owp;
|
||||
}
|
||||
static inline WDataOutP VL_REPLICATE_WWI(int obits, int lbits, int, WDataOutP owp,
|
||||
WDataInP const lwp, IData rep) VL_MT_SAFE {
|
||||
static inline WDataOutP VL_REPLICATE_WWI(int lbits, WDataOutP owp, WDataInP const lwp,
|
||||
IData rep) VL_MT_SAFE {
|
||||
for (int i = 0; i < VL_WORDS_I(lbits); ++i) owp[i] = lwp[i];
|
||||
for (unsigned i = 1; i < rep; ++i) {
|
||||
_vl_insert_WW(obits, owp, lwp, i * lbits + lbits - 1, i * lbits);
|
||||
_vl_insert_WW(owp, lwp, i * lbits + lbits - 1, i * lbits);
|
||||
}
|
||||
return owp;
|
||||
}
|
||||
@@ -1388,7 +1399,7 @@ static inline WDataOutP VL_REPLICATE_WWI(int obits, int lbits, int, WDataOutP ow
|
||||
// Special "fast" versions for slice sizes that are a power of 2. These use
|
||||
// shifts and masks to execute faster than the slower for-loop approach where a
|
||||
// subset of bits is copied in during each iteration.
|
||||
static inline IData VL_STREAML_FAST_III(int, int lbits, int, IData ld, IData rd_log2) VL_PURE {
|
||||
static inline IData VL_STREAML_FAST_III(int lbits, IData ld, IData rd_log2) VL_PURE {
|
||||
// Pre-shift bits in most-significant slice:
|
||||
//
|
||||
// If lbits is not a multiple of the slice size (i.e., lbits % rd != 0),
|
||||
@@ -1426,13 +1437,13 @@ static inline IData VL_STREAML_FAST_III(int, int lbits, int, IData ld, IData rd_
|
||||
return ret >> (VL_IDATASIZE - lbits);
|
||||
}
|
||||
|
||||
static inline QData VL_STREAML_FAST_QQI(int, int lbits, int, QData ld, IData rd_log2) VL_PURE {
|
||||
static inline QData VL_STREAML_FAST_QQI(int lbits, QData ld, IData rd_log2) VL_PURE {
|
||||
// Pre-shift bits in most-significant slice (see comment in VL_STREAML_FAST_III)
|
||||
QData ret = ld;
|
||||
if (rd_log2) {
|
||||
const vluint32_t lbitsFloor = lbits & ~VL_MASK_I(rd_log2);
|
||||
const vluint32_t lbitsRem = lbits - lbitsFloor;
|
||||
const QData msbMask = VL_MASK_Q(lbitsRem) << lbitsFloor;
|
||||
const QData msbMask = lbitsFloor == 64 ? 0ULL : VL_MASK_Q(lbitsRem) << lbitsFloor;
|
||||
ret = (ret & ~msbMask) | ((ret & msbMask) << ((1ULL << rd_log2) - lbitsRem));
|
||||
}
|
||||
switch (rd_log2) {
|
||||
@@ -1458,7 +1469,7 @@ static inline QData VL_STREAML_FAST_QQI(int, int lbits, int, QData ld, IData rd_
|
||||
}
|
||||
|
||||
// Regular "slow" streaming operators
|
||||
static inline IData VL_STREAML_III(int, int lbits, int, IData ld, IData rd) VL_PURE {
|
||||
static inline IData VL_STREAML_III(int lbits, IData ld, IData rd) VL_PURE {
|
||||
IData ret = 0;
|
||||
// Slice size should never exceed the lhs width
|
||||
const IData mask = VL_MASK_I(rd);
|
||||
@@ -1470,7 +1481,7 @@ static inline IData VL_STREAML_III(int, int lbits, int, IData ld, IData rd) VL_P
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline QData VL_STREAML_QQI(int, int lbits, int, QData ld, IData rd) VL_PURE {
|
||||
static inline QData VL_STREAML_QQI(int lbits, QData ld, IData rd) VL_PURE {
|
||||
QData ret = 0;
|
||||
// Slice size should never exceed the lhs width
|
||||
const QData mask = VL_MASK_Q(rd);
|
||||
@@ -1482,7 +1493,7 @@ static inline QData VL_STREAML_QQI(int, int lbits, int, QData ld, IData rd) VL_P
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline WDataOutP VL_STREAML_WWI(int, int lbits, int, WDataOutP owp, WDataInP const lwp,
|
||||
static inline WDataOutP VL_STREAML_WWI(int lbits, WDataOutP owp, WDataInP const lwp,
|
||||
IData rd) VL_MT_SAFE {
|
||||
VL_ZERO_W(lbits, owp);
|
||||
// Slice size should never exceed the lhs width
|
||||
@@ -1493,7 +1504,8 @@ static inline WDataOutP VL_STREAML_WWI(int, int lbits, int, WDataOutP owp, WData
|
||||
for (int sbit = 0; sbit < ssize && sbit < lbits - istart; ++sbit) {
|
||||
// Extract a single bit from lwp and shift it to the correct
|
||||
// location for owp.
|
||||
EData bit = (VL_BITRSHIFT_W(lwp, (istart + sbit)) & 1) << VL_BITBIT_E(ostart + sbit);
|
||||
const EData bit = (VL_BITRSHIFT_W(lwp, (istart + sbit)) & 1)
|
||||
<< VL_BITBIT_E(ostart + sbit);
|
||||
owp[VL_BITWORD_E(ostart + sbit)] |= bit;
|
||||
}
|
||||
}
|
||||
@@ -1519,63 +1531,63 @@ static inline WDataOutP VL_CONCAT_WII(int obits, int lbits, int rbits, WDataOutP
|
||||
IData rd) VL_MT_SAFE {
|
||||
owp[0] = rd;
|
||||
for (int i = 1; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
|
||||
_vl_insert_WI(obits, owp, ld, rbits + lbits - 1, rbits);
|
||||
_vl_insert_WI(owp, ld, rbits + lbits - 1, rbits);
|
||||
return owp;
|
||||
}
|
||||
static inline WDataOutP VL_CONCAT_WWI(int obits, int lbits, int rbits, WDataOutP owp,
|
||||
WDataInP const lwp, IData rd) VL_MT_SAFE {
|
||||
owp[0] = rd;
|
||||
for (int i = 1; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
|
||||
_vl_insert_WW(obits, owp, lwp, rbits + lbits - 1, rbits);
|
||||
_vl_insert_WW(owp, lwp, rbits + lbits - 1, rbits);
|
||||
return owp;
|
||||
}
|
||||
static inline WDataOutP VL_CONCAT_WIW(int obits, int lbits, int rbits, WDataOutP owp, IData ld,
|
||||
WDataInP const rwp) VL_MT_SAFE {
|
||||
for (int i = 0; i < VL_WORDS_I(rbits); ++i) owp[i] = rwp[i];
|
||||
for (int i = VL_WORDS_I(rbits); i < VL_WORDS_I(obits); ++i) owp[i] = 0;
|
||||
_vl_insert_WI(obits, owp, ld, rbits + lbits - 1, rbits);
|
||||
_vl_insert_WI(owp, ld, rbits + lbits - 1, rbits);
|
||||
return owp;
|
||||
}
|
||||
static inline WDataOutP VL_CONCAT_WIQ(int obits, int lbits, int rbits, WDataOutP owp, IData ld,
|
||||
QData rd) VL_MT_SAFE {
|
||||
VL_SET_WQ(owp, rd);
|
||||
for (int i = VL_WQ_WORDS_E; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
|
||||
_vl_insert_WI(obits, owp, ld, rbits + lbits - 1, rbits);
|
||||
_vl_insert_WI(owp, ld, rbits + lbits - 1, rbits);
|
||||
return owp;
|
||||
}
|
||||
static inline WDataOutP VL_CONCAT_WQI(int obits, int lbits, int rbits, WDataOutP owp, QData ld,
|
||||
IData rd) VL_MT_SAFE {
|
||||
owp[0] = rd;
|
||||
for (int i = 1; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
|
||||
_vl_insert_WQ(obits, owp, ld, rbits + lbits - 1, rbits);
|
||||
_vl_insert_WQ(owp, ld, rbits + lbits - 1, rbits);
|
||||
return owp;
|
||||
}
|
||||
static inline WDataOutP VL_CONCAT_WQQ(int obits, int lbits, int rbits, WDataOutP owp, QData ld,
|
||||
QData rd) VL_MT_SAFE {
|
||||
VL_SET_WQ(owp, rd);
|
||||
for (int i = VL_WQ_WORDS_E; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
|
||||
_vl_insert_WQ(obits, owp, ld, rbits + lbits - 1, rbits);
|
||||
_vl_insert_WQ(owp, ld, rbits + lbits - 1, rbits);
|
||||
return owp;
|
||||
}
|
||||
static inline WDataOutP VL_CONCAT_WWQ(int obits, int lbits, int rbits, WDataOutP owp,
|
||||
WDataInP const lwp, QData rd) VL_MT_SAFE {
|
||||
VL_SET_WQ(owp, rd);
|
||||
for (int i = VL_WQ_WORDS_E; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
|
||||
_vl_insert_WW(obits, owp, lwp, rbits + lbits - 1, rbits);
|
||||
_vl_insert_WW(owp, lwp, rbits + lbits - 1, rbits);
|
||||
return owp;
|
||||
}
|
||||
static inline WDataOutP VL_CONCAT_WQW(int obits, int lbits, int rbits, WDataOutP owp, QData ld,
|
||||
WDataInP const rwp) VL_MT_SAFE {
|
||||
for (int i = 0; i < VL_WORDS_I(rbits); ++i) owp[i] = rwp[i];
|
||||
for (int i = VL_WORDS_I(rbits); i < VL_WORDS_I(obits); ++i) owp[i] = 0;
|
||||
_vl_insert_WQ(obits, owp, ld, rbits + lbits - 1, rbits);
|
||||
_vl_insert_WQ(owp, ld, rbits + lbits - 1, rbits);
|
||||
return owp;
|
||||
}
|
||||
static inline WDataOutP VL_CONCAT_WWW(int obits, int lbits, int rbits, WDataOutP owp,
|
||||
WDataInP const lwp, WDataInP const rwp) VL_MT_SAFE {
|
||||
for (int i = 0; i < VL_WORDS_I(rbits); ++i) owp[i] = rwp[i];
|
||||
for (int i = VL_WORDS_I(rbits); i < VL_WORDS_I(obits); ++i) owp[i] = 0;
|
||||
_vl_insert_WW(obits, owp, lwp, rbits + lbits - 1, rbits);
|
||||
_vl_insert_WW(owp, lwp, rbits + lbits - 1, rbits);
|
||||
return owp;
|
||||
}
|
||||
|
||||
@@ -1610,7 +1622,7 @@ static inline WDataOutP VL_SHIFTL_WWI(int obits, int, int, WDataOutP owp, WDataI
|
||||
for (int i = word_shift; i < VL_WORDS_I(obits); ++i) owp[i] = lwp[i - word_shift];
|
||||
} else {
|
||||
for (int i = 0; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
|
||||
_vl_insert_WW(obits, owp, lwp, obits - 1, rd);
|
||||
_vl_insert_WW(owp, lwp, obits - 1, rd);
|
||||
}
|
||||
return owp;
|
||||
}
|
||||
@@ -1763,7 +1775,8 @@ static inline WDataOutP VL_SHIFTRS_WWI(int obits, int lbits, int, WDataOutP owp,
|
||||
owp[lmsw] &= VL_MASK_E(lbits);
|
||||
} else {
|
||||
const int loffset = rd & VL_SIZEBITS_E;
|
||||
int nbitsonright = VL_EDATASIZE - loffset; // bits that end up in lword (know loffset!=0)
|
||||
const int nbitsonright
|
||||
= VL_EDATASIZE - loffset; // bits that end up in lword (know loffset!=0)
|
||||
// Middle words
|
||||
const int words = VL_WORDS_I(obits - rd);
|
||||
for (int i = 0; i < words; ++i) {
|
||||
@@ -1781,7 +1794,7 @@ static inline WDataOutP VL_SHIFTRS_WWW(int obits, int lbits, int rbits, WDataOut
|
||||
WDataInP const lwp, WDataInP const rwp) VL_MT_SAFE {
|
||||
EData overshift = 0; // Huge shift 1>>32 or more
|
||||
for (int i = 1; i < VL_WORDS_I(rbits); ++i) overshift |= rwp[i];
|
||||
if (VL_UNLIKELY(overshift || rwp[0] >= obits)) {
|
||||
if (VL_UNLIKELY(overshift || rwp[0] >= static_cast<IData>(obits))) {
|
||||
const int lmsw = VL_WORDS_I(obits) - 1;
|
||||
const EData sign = VL_SIGNONES_E(lbits, lwp[lmsw]);
|
||||
for (int j = 0; j <= lmsw; ++j) owp[j] = sign;
|
||||
@@ -1800,7 +1813,7 @@ static inline IData VL_SHIFTRS_IIW(int obits, int lbits, int rbits, IData lhs,
|
||||
WDataInP const rwp) VL_MT_SAFE {
|
||||
EData overshift = 0; // Huge shift 1>>32 or more
|
||||
for (int i = 1; i < VL_WORDS_I(rbits); ++i) overshift |= rwp[i];
|
||||
if (VL_UNLIKELY(overshift || rwp[0] >= obits)) {
|
||||
if (VL_UNLIKELY(overshift || rwp[0] >= static_cast<IData>(obits))) {
|
||||
const IData sign = -(lhs >> (lbits - 1)); // ffff_ffff if negative
|
||||
return VL_CLEAN_II(obits, obits, sign);
|
||||
}
|
||||
@@ -1810,7 +1823,7 @@ static inline QData VL_SHIFTRS_QQW(int obits, int lbits, int rbits, QData lhs,
|
||||
WDataInP const rwp) VL_MT_SAFE {
|
||||
EData overshift = 0; // Huge shift 1>>32 or more
|
||||
for (int i = 1; i < VL_WORDS_I(rbits); ++i) overshift |= rwp[i];
|
||||
if (VL_UNLIKELY(overshift || rwp[0] >= obits)) {
|
||||
if (VL_UNLIKELY(overshift || rwp[0] >= static_cast<IData>(obits))) {
|
||||
const QData sign = -(lhs >> (lbits - 1)); // ffff_ffff if negative
|
||||
return VL_CLEAN_QQ(obits, obits, sign);
|
||||
}
|
||||
@@ -1832,14 +1845,13 @@ static inline QData VL_SHIFTRS_QQQ(int obits, int lbits, int rbits, QData lhs, Q
|
||||
// Bit selection
|
||||
|
||||
// EMIT_RULE: VL_BITSEL: oclean=dirty; rclean==clean;
|
||||
#define VL_BITSEL_IIII(obits, lbits, rbits, zbits, lhs, rhs) ((lhs) >> (rhs))
|
||||
#define VL_BITSEL_QIII(obits, lbits, rbits, zbits, lhs, rhs) ((lhs) >> (rhs))
|
||||
#define VL_BITSEL_QQII(obits, lbits, rbits, zbits, lhs, rhs) ((lhs) >> (rhs))
|
||||
#define VL_BITSEL_IQII(obits, lbits, rbits, zbits, lhs, rhs) (static_cast<IData>((lhs) >> (rhs)))
|
||||
#define VL_BITSEL_IIII(lbits, lhs, rhs) ((lhs) >> (rhs))
|
||||
#define VL_BITSEL_QIII(lbits, lhs, rhs) ((lhs) >> (rhs))
|
||||
#define VL_BITSEL_QQII(lbits, lhs, rhs) ((lhs) >> (rhs))
|
||||
#define VL_BITSEL_IQII(lbits, lhs, rhs) (static_cast<IData>((lhs) >> (rhs)))
|
||||
|
||||
static inline IData VL_BITSEL_IWII(int, int lbits, int, int, WDataInP const lwp,
|
||||
IData rd) VL_MT_SAFE {
|
||||
int word = VL_BITWORD_E(rd);
|
||||
static inline IData VL_BITSEL_IWII(int lbits, WDataInP const lwp, IData rd) VL_MT_SAFE {
|
||||
const int word = VL_BITWORD_E(rd);
|
||||
if (VL_UNLIKELY(rd > static_cast<IData>(lbits))) {
|
||||
return ~0; // Spec says you can go outside the range of a array. Don't coredump if so.
|
||||
// We return all 1's as that's more likely to find bugs (?) than 0's.
|
||||
@@ -1850,27 +1862,24 @@ static inline IData VL_BITSEL_IWII(int, int lbits, int, int, WDataInP const lwp,
|
||||
|
||||
// EMIT_RULE: VL_RANGE: oclean=lclean; out=dirty
|
||||
// <msb> & <lsb> MUST BE CLEAN (currently constant)
|
||||
#define VL_SEL_IIII(obits, lbits, rbits, tbits, lhs, lsb, width) ((lhs) >> (lsb))
|
||||
#define VL_SEL_QQII(obits, lbits, rbits, tbits, lhs, lsb, width) ((lhs) >> (lsb))
|
||||
#define VL_SEL_IQII(obits, lbits, rbits, tbits, lhs, lsb, width) \
|
||||
(static_cast<IData>((lhs) >> (lsb)))
|
||||
#define VL_SEL_IIII(lbits, lhs, lsb, width) ((lhs) >> (lsb))
|
||||
#define VL_SEL_QQII(lbits, lhs, lsb, width) ((lhs) >> (lsb))
|
||||
#define VL_SEL_IQII(lbits, lhs, lsb, width) (static_cast<IData>((lhs) >> (lsb)))
|
||||
|
||||
static inline IData VL_SEL_IWII(int, int lbits, int, int, WDataInP const lwp, IData lsb,
|
||||
IData width) VL_MT_SAFE {
|
||||
int msb = lsb + width - 1;
|
||||
static inline IData VL_SEL_IWII(int lbits, WDataInP const lwp, IData lsb, IData width) VL_MT_SAFE {
|
||||
const int msb = lsb + width - 1;
|
||||
if (VL_UNLIKELY(msb >= lbits)) {
|
||||
return ~0; // Spec says you can go outside the range of a array. Don't coredump if so.
|
||||
} else if (VL_BITWORD_E(msb) == VL_BITWORD_E(static_cast<int>(lsb))) {
|
||||
return VL_BITRSHIFT_W(lwp, lsb);
|
||||
} else {
|
||||
// 32 bit extraction may span two words
|
||||
int nbitsfromlow = VL_EDATASIZE - VL_BITBIT_E(lsb); // bits that come from low word
|
||||
const int nbitsfromlow = VL_EDATASIZE - VL_BITBIT_E(lsb); // bits that come from low word
|
||||
return ((lwp[VL_BITWORD_E(msb)] << nbitsfromlow) | VL_BITRSHIFT_W(lwp, lsb));
|
||||
}
|
||||
}
|
||||
|
||||
static inline QData VL_SEL_QWII(int, int lbits, int, int, WDataInP const lwp, IData lsb,
|
||||
IData width) VL_MT_SAFE {
|
||||
static inline QData VL_SEL_QWII(int lbits, WDataInP const lwp, IData lsb, IData width) VL_MT_SAFE {
|
||||
const int msb = lsb + width - 1;
|
||||
if (VL_UNLIKELY(msb > lbits)) {
|
||||
return ~0; // Spec says you can go outside the range of a array. Don't coredump if so.
|
||||
@@ -1883,7 +1892,7 @@ static inline QData VL_SEL_QWII(int, int lbits, int, int, WDataInP const lwp, ID
|
||||
return (hi << nbitsfromlow) | lo;
|
||||
} else {
|
||||
// 64 bit extraction may span three words
|
||||
int nbitsfromlow = VL_EDATASIZE - VL_BITBIT_E(lsb);
|
||||
const int nbitsfromlow = VL_EDATASIZE - VL_BITBIT_E(lsb);
|
||||
const QData hi = (lwp[VL_BITWORD_E(msb)]);
|
||||
const QData mid = (lwp[VL_BITWORD_E(lsb) + 1]);
|
||||
const QData lo = VL_BITRSHIFT_W(lwp, lsb);
|
||||
@@ -1891,8 +1900,8 @@ static inline QData VL_SEL_QWII(int, int lbits, int, int, WDataInP const lwp, ID
|
||||
}
|
||||
}
|
||||
|
||||
static inline WDataOutP VL_SEL_WWII(int obits, int lbits, int, int, WDataOutP owp,
|
||||
WDataInP const lwp, IData lsb, IData width) VL_MT_SAFE {
|
||||
static inline WDataOutP VL_SEL_WWII(int obits, int lbits, WDataOutP owp, WDataInP const lwp,
|
||||
IData lsb, IData width) VL_MT_SAFE {
|
||||
const int msb = lsb + width - 1;
|
||||
const int word_shift = VL_BITWORD_E(lsb);
|
||||
if (VL_UNLIKELY(msb > lbits)) { // Outside bounds,
|
||||
@@ -1924,7 +1933,7 @@ static inline WDataOutP VL_SEL_WWII(int obits, int lbits, int, int, WDataOutP ow
|
||||
|
||||
// Return QData from double (numeric)
|
||||
// EMIT_RULE: VL_RTOIROUND_Q_D: oclean=dirty; lclean==clean/real
|
||||
static inline QData VL_RTOIROUND_Q_D(int, double lhs) VL_PURE {
|
||||
static inline QData VL_RTOIROUND_Q_D(double lhs) VL_PURE {
|
||||
// IEEE format: [63]=sign [62:52]=exp+1023 [51:0]=mantissa
|
||||
// This does not need to support subnormals as they are sub-integral
|
||||
lhs = VL_ROUND(lhs);
|
||||
@@ -1941,8 +1950,8 @@ static inline QData VL_RTOIROUND_Q_D(int, double lhs) VL_PURE {
|
||||
if (lhs < 0) out = -out;
|
||||
return out;
|
||||
}
|
||||
static inline IData VL_RTOIROUND_I_D(int bits, double lhs) VL_PURE {
|
||||
return static_cast<IData>(VL_RTOIROUND_Q_D(bits, lhs));
|
||||
static inline IData VL_RTOIROUND_I_D(double lhs) VL_PURE {
|
||||
return static_cast<IData>(VL_RTOIROUND_Q_D(lhs));
|
||||
}
|
||||
static inline WDataOutP VL_RTOIROUND_W_D(int obits, WDataOutP owp, double lhs) VL_PURE {
|
||||
// IEEE format: [63]=sign [62:52]=exp+1023 [51:0]=mantissa
|
||||
@@ -1956,7 +1965,7 @@ static inline WDataOutP VL_RTOIROUND_W_D(int obits, WDataOutP owp, double lhs) V
|
||||
if (lsb < 0) {
|
||||
VL_SET_WQ(owp, mantissa >> -lsb);
|
||||
} else if (lsb < obits) {
|
||||
_vl_insert_WQ(obits, owp, mantissa, lsb + 52, lsb);
|
||||
_vl_insert_WQ(owp, mantissa, lsb + 52, lsb);
|
||||
}
|
||||
if (lhs < 0) VL_NEGATE_INPLACE_W(VL_WORDS_I(obits), owp);
|
||||
return owp;
|
||||
@@ -1966,50 +1975,41 @@ static inline WDataOutP VL_RTOIROUND_W_D(int obits, WDataOutP owp, double lhs) V
|
||||
// Range assignments
|
||||
|
||||
// EMIT_RULE: VL_ASSIGNRANGE: rclean=dirty;
|
||||
static inline void VL_ASSIGNSEL_IIII(int rbits, int obits, int lsb, CData& lhsr,
|
||||
IData rhs) VL_PURE {
|
||||
_vl_insert_II(obits, lhsr, rhs, lsb + obits - 1, lsb, rbits);
|
||||
static inline void VL_ASSIGNSEL_II(int rbits, int obits, int lsb, CData& lhsr, IData rhs) VL_PURE {
|
||||
_vl_insert_II(lhsr, rhs, lsb + obits - 1, lsb, rbits);
|
||||
}
|
||||
static inline void VL_ASSIGNSEL_IIII(int rbits, int obits, int lsb, SData& lhsr,
|
||||
IData rhs) VL_PURE {
|
||||
_vl_insert_II(obits, lhsr, rhs, lsb + obits - 1, lsb, rbits);
|
||||
static inline void VL_ASSIGNSEL_II(int rbits, int obits, int lsb, SData& lhsr, IData rhs) VL_PURE {
|
||||
_vl_insert_II(lhsr, rhs, lsb + obits - 1, lsb, rbits);
|
||||
}
|
||||
static inline void VL_ASSIGNSEL_IIII(int rbits, int obits, int lsb, IData& lhsr,
|
||||
IData rhs) VL_PURE {
|
||||
_vl_insert_II(obits, lhsr, rhs, lsb + obits - 1, lsb, rbits);
|
||||
static inline void VL_ASSIGNSEL_II(int rbits, int obits, int lsb, IData& lhsr, IData rhs) VL_PURE {
|
||||
_vl_insert_II(lhsr, rhs, lsb + obits - 1, lsb, rbits);
|
||||
}
|
||||
static inline void VL_ASSIGNSEL_QIII(int rbits, int obits, int lsb, QData& lhsr,
|
||||
IData rhs) VL_PURE {
|
||||
_vl_insert_QQ(obits, lhsr, rhs, lsb + obits - 1, lsb, rbits);
|
||||
static inline void VL_ASSIGNSEL_QI(int rbits, int obits, int lsb, QData& lhsr, IData rhs) VL_PURE {
|
||||
_vl_insert_QQ(lhsr, rhs, lsb + obits - 1, lsb, rbits);
|
||||
}
|
||||
static inline void VL_ASSIGNSEL_QQII(int rbits, int obits, int lsb, QData& lhsr,
|
||||
QData rhs) VL_PURE {
|
||||
_vl_insert_QQ(obits, lhsr, rhs, lsb + obits - 1, lsb, rbits);
|
||||
}
|
||||
static inline void VL_ASSIGNSEL_QIIQ(int rbits, int obits, int lsb, QData& lhsr,
|
||||
QData rhs) VL_PURE {
|
||||
_vl_insert_QQ(obits, lhsr, rhs, lsb + obits - 1, lsb, rbits);
|
||||
static inline void VL_ASSIGNSEL_QQ(int rbits, int obits, int lsb, QData& lhsr, QData rhs) VL_PURE {
|
||||
_vl_insert_QQ(lhsr, rhs, lsb + obits - 1, lsb, rbits);
|
||||
}
|
||||
// static inline void VL_ASSIGNSEL_IIIW(int obits, int lsb, IData& lhsr, WDataInP const rwp)
|
||||
// VL_MT_SAFE { Illegal, as lhs width >= rhs width
|
||||
static inline void VL_ASSIGNSEL_WIII(int rbits, int obits, int lsb, WDataOutP owp,
|
||||
IData rhs) VL_MT_SAFE {
|
||||
_vl_insert_WI(obits, owp, rhs, lsb + obits - 1, lsb, rbits);
|
||||
static inline void VL_ASSIGNSEL_WI(int rbits, int obits, int lsb, WDataOutP owp,
|
||||
IData rhs) VL_MT_SAFE {
|
||||
_vl_insert_WI(owp, rhs, lsb + obits - 1, lsb, rbits);
|
||||
}
|
||||
static inline void VL_ASSIGNSEL_WIIQ(int rbits, int obits, int lsb, WDataOutP owp,
|
||||
QData rhs) VL_MT_SAFE {
|
||||
_vl_insert_WQ(obits, owp, rhs, lsb + obits - 1, lsb, rbits);
|
||||
static inline void VL_ASSIGNSEL_WQ(int rbits, int obits, int lsb, WDataOutP owp,
|
||||
QData rhs) VL_MT_SAFE {
|
||||
_vl_insert_WQ(owp, rhs, lsb + obits - 1, lsb, rbits);
|
||||
}
|
||||
static inline void VL_ASSIGNSEL_WIIW(int rbits, int obits, int lsb, WDataOutP owp,
|
||||
WDataInP const rwp) VL_MT_SAFE {
|
||||
_vl_insert_WW(obits, owp, rwp, lsb + obits - 1, lsb, rbits);
|
||||
static inline void VL_ASSIGNSEL_WW(int rbits, int obits, int lsb, WDataOutP owp,
|
||||
WDataInP const rwp) VL_MT_SAFE {
|
||||
_vl_insert_WW(owp, rwp, lsb + obits - 1, lsb, rbits);
|
||||
}
|
||||
|
||||
//======================================================================
|
||||
// Triops
|
||||
|
||||
static inline WDataOutP VL_COND_WIWW(int obits, int, int, int, WDataOutP owp, int cond,
|
||||
WDataInP const w1p, WDataInP const w2p) VL_MT_SAFE {
|
||||
static inline WDataOutP VL_COND_WIWW(int obits, WDataOutP owp, int cond, WDataInP const w1p,
|
||||
WDataInP const w2p) VL_MT_SAFE {
|
||||
const int words = VL_WORDS_I(obits);
|
||||
for (int i = 0; i < words; ++i) owp[i] = cond ? w1p[i] : w2p[i];
|
||||
return owp;
|
||||
@@ -2040,40 +2040,40 @@ static inline WDataOutP VL_CONST_W_2X(int obits, WDataOutP o, EData d1, EData d0
|
||||
static inline WDataOutP VL_CONST_W_3X(int obits, WDataOutP o, EData d2, EData d1,
|
||||
EData d0) VL_MT_SAFE {
|
||||
o[0] = d0; o[1] = d1; o[2] = d2;
|
||||
VL_C_END_(obits,3);
|
||||
VL_C_END_(obits, 3);
|
||||
}
|
||||
static inline WDataOutP VL_CONST_W_4X(int obits, WDataOutP o,
|
||||
EData d3, EData d2, EData d1, EData d0) VL_MT_SAFE {
|
||||
o[0] = d0; o[1] = d1; o[2] = d2; o[3] = d3;
|
||||
VL_C_END_(obits,4);
|
||||
VL_C_END_(obits, 4);
|
||||
}
|
||||
static inline WDataOutP VL_CONST_W_5X(int obits, WDataOutP o,
|
||||
EData d4,
|
||||
EData d3, EData d2, EData d1, EData d0) VL_MT_SAFE {
|
||||
o[0] = d0; o[1] = d1; o[2] = d2; o[3] = d3;
|
||||
o[4] = d4;
|
||||
VL_C_END_(obits,5);
|
||||
VL_C_END_(obits, 5);
|
||||
}
|
||||
static inline WDataOutP VL_CONST_W_6X(int obits, WDataOutP o,
|
||||
EData d5, EData d4,
|
||||
EData d3, EData d2, EData d1, EData d0) VL_MT_SAFE {
|
||||
o[0] = d0; o[1] = d1; o[2] = d2; o[3] = d3;
|
||||
o[4] = d4; o[5] = d5;
|
||||
VL_C_END_(obits,6);
|
||||
VL_C_END_(obits, 6);
|
||||
}
|
||||
static inline WDataOutP VL_CONST_W_7X(int obits, WDataOutP o,
|
||||
EData d6, EData d5, EData d4,
|
||||
EData d3, EData d2, EData d1, EData d0) VL_MT_SAFE {
|
||||
o[0] = d0; o[1] = d1; o[2] = d2; o[3] = d3;
|
||||
o[4] = d4; o[5] = d5; o[6] = d6;
|
||||
VL_C_END_(obits,7);
|
||||
VL_C_END_(obits, 7);
|
||||
}
|
||||
static inline WDataOutP VL_CONST_W_8X(int obits, WDataOutP o,
|
||||
EData d7, EData d6, EData d5, EData d4,
|
||||
EData d3, EData d2, EData d1, EData d0) VL_MT_SAFE {
|
||||
o[0] = d0; o[1] = d1; o[2] = d2; o[3] = d3;
|
||||
o[4] = d4; o[5] = d5; o[6] = d6; o[7] = d7;
|
||||
VL_C_END_(obits,8);
|
||||
VL_C_END_(obits, 8);
|
||||
}
|
||||
//
|
||||
static inline WDataOutP VL_CONSTHI_W_1X(int obits, int lsb, WDataOutP obase,
|
||||
@@ -2184,15 +2184,14 @@ inline std::string VL_CVT_PACK_STR_NI(IData lhs) VL_PURE {
|
||||
inline std::string VL_CONCATN_NNN(const std::string& lhs, const std::string& rhs) VL_PURE {
|
||||
return lhs + rhs;
|
||||
}
|
||||
inline std::string VL_REPLICATEN_NNQ(int, int, int, const std::string& lhs, IData rep) VL_PURE {
|
||||
inline std::string VL_REPLICATEN_NNQ(const std::string& lhs, IData rep) VL_PURE {
|
||||
std::string out;
|
||||
out.reserve(lhs.length() * rep);
|
||||
for (unsigned times = 0; times < rep; ++times) out += lhs;
|
||||
return out;
|
||||
}
|
||||
inline std::string VL_REPLICATEN_NNI(int obits, int lbits, int rbits, const std::string& lhs,
|
||||
IData rep) VL_PURE {
|
||||
return VL_REPLICATEN_NNQ(obits, lbits, rbits, lhs, rep);
|
||||
inline std::string VL_REPLICATEN_NNI(const std::string& lhs, IData rep) VL_PURE {
|
||||
return VL_REPLICATEN_NNQ(lhs, rep);
|
||||
}
|
||||
|
||||
inline IData VL_LEN_IN(const std::string& ld) { return ld.length(); }
|
||||
@@ -2217,31 +2216,31 @@ extern void VL_TIMEFORMAT_IINI(int units, int precision, const std::string& suff
|
||||
extern IData VL_VALUEPLUSARGS_INW(int rbits, const std::string& ld, WDataOutP rwp) VL_MT_SAFE;
|
||||
inline IData VL_VALUEPLUSARGS_INI(int rbits, const std::string& ld, CData& rdr) VL_MT_SAFE {
|
||||
VlWide<2> rwp;
|
||||
IData got = VL_VALUEPLUSARGS_INW(rbits, ld, rwp);
|
||||
const IData got = VL_VALUEPLUSARGS_INW(rbits, ld, rwp);
|
||||
if (got) rdr = rwp[0];
|
||||
return got;
|
||||
}
|
||||
inline IData VL_VALUEPLUSARGS_INI(int rbits, const std::string& ld, SData& rdr) VL_MT_SAFE {
|
||||
VlWide<2> rwp;
|
||||
IData got = VL_VALUEPLUSARGS_INW(rbits, ld, rwp);
|
||||
const IData got = VL_VALUEPLUSARGS_INW(rbits, ld, rwp);
|
||||
if (got) rdr = rwp[0];
|
||||
return got;
|
||||
}
|
||||
inline IData VL_VALUEPLUSARGS_INI(int rbits, const std::string& ld, IData& rdr) VL_MT_SAFE {
|
||||
VlWide<2> rwp;
|
||||
IData got = VL_VALUEPLUSARGS_INW(rbits, ld, rwp);
|
||||
const IData got = VL_VALUEPLUSARGS_INW(rbits, ld, rwp);
|
||||
if (got) rdr = rwp[0];
|
||||
return got;
|
||||
}
|
||||
inline IData VL_VALUEPLUSARGS_INQ(int rbits, const std::string& ld, QData& rdr) VL_MT_SAFE {
|
||||
VlWide<2> rwp;
|
||||
IData got = VL_VALUEPLUSARGS_INW(rbits, ld, rwp);
|
||||
const IData got = VL_VALUEPLUSARGS_INW(rbits, ld, rwp);
|
||||
if (got) rdr = VL_SET_QW(rwp);
|
||||
return got;
|
||||
}
|
||||
inline IData VL_VALUEPLUSARGS_INQ(int rbits, const std::string& ld, double& rdr) VL_MT_SAFE {
|
||||
VlWide<2> rwp;
|
||||
IData got = VL_VALUEPLUSARGS_INW(rbits, ld, rwp);
|
||||
const IData got = VL_VALUEPLUSARGS_INW(rbits, ld, rwp);
|
||||
if (got) rdr = VL_CVT_D_Q(VL_SET_QW(rwp));
|
||||
return got;
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
+14
-10
@@ -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,14 @@
|
||||
#include "verilated.h"
|
||||
#include "verilated_syms.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <deque>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <numeric>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#ifdef VL_THREADED
|
||||
# include <functional>
|
||||
# include <queue>
|
||||
@@ -277,7 +281,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 +303,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 +316,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 +338,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
|
||||
@@ -549,8 +553,8 @@ public: // But only for verilated*.cpp
|
||||
const VerilatedLockGuard lock{s().m_exportMutex};
|
||||
const auto& it = s().m_exportMap.find(namep);
|
||||
if (VL_LIKELY(it != s().m_exportMap.end())) return it->second;
|
||||
std::string msg = (std::string{"%Error: Testbench C called "} + namep
|
||||
+ " but no such DPI export function name exists in ANY model");
|
||||
const std::string msg = (std::string{"%Error: Testbench C called "} + namep
|
||||
+ " but no such DPI export function name exists in ANY model");
|
||||
VL_FATAL_MT("unknown", 0, "", msg.c_str());
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -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,116 @@
|
||||
// -*- 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 general profiling header
|
||||
///
|
||||
/// This file is not part of the Verilated public-facing API.
|
||||
/// It is only for internal use by Verilated library routines.
|
||||
///
|
||||
//=============================================================================
|
||||
|
||||
#ifndef VERILATOR_VERILATED_PROFILER_H_
|
||||
#define VERILATOR_VERILATED_PROFILER_H_
|
||||
|
||||
#include "verilatedos.h"
|
||||
#include "verilated.h" // for VerilatedMutex and clang annotations
|
||||
|
||||
#include <deque>
|
||||
#include <string>
|
||||
|
||||
// Profile record, private class used only by this header
|
||||
class VerilatedProfilerRec final {
|
||||
const std::string m_name; // Hashed name of mtask/etc
|
||||
const size_t m_counterNumber = 0; // Which counter has data
|
||||
public:
|
||||
// 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; }
|
||||
};
|
||||
|
||||
// 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
|
||||
|
||||
public:
|
||||
// METHODS
|
||||
VerilatedProfiler() = default;
|
||||
~VerilatedProfiler() = 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});
|
||||
}
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
template <std::size_t T_Entries>
|
||||
void VerilatedProfiler<T_Entries>::write(const char* modelp,
|
||||
const std::string& filename) VL_MT_SAFE {
|
||||
static VerilatedMutex s_mutex;
|
||||
const VerilatedLockGuard lock{s_mutex};
|
||||
|
||||
// On the first call we create the file. On later calls we append.
|
||||
// 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
|
||||
// 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
|
||||
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;
|
||||
|
||||
// TODO Perhaps merge with verilated_coverage output format, so can
|
||||
// have a common merging and reporting tool, etc.
|
||||
fprintf(fp, "// Verilated model profile-guided optimization data dump file\n");
|
||||
fprintf(fp, "`verilator_config\n");
|
||||
|
||||
for (const auto& it : m_records) {
|
||||
const std::string& name = it.name();
|
||||
fprintf(fp, "profile_data -model \"%s\" -mtask \"%s\" -cost 64'd%" PRIu64 "\n", modelp,
|
||||
name.c_str(), m_counters[it.counterNumber()]);
|
||||
}
|
||||
|
||||
std::fclose(fp);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -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.
|
||||
@@ -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 vluint8_t* wp = m_bufp;
|
||||
while (true) {
|
||||
const ssize_t remaining = (m_cp - wp);
|
||||
if (remaining == 0) break;
|
||||
@@ -204,7 +204,7 @@ void VerilatedSave::flush() VL_MT_UNSAFE_ONE {
|
||||
if (VL_UNCOVERABLE(errno != EAGAIN && errno != EINTR)) {
|
||||
// LCOV_EXCL_START
|
||||
// write failed, presume error (perhaps out of disk space)
|
||||
std::string msg = std::string{__FUNCTION__} + ": " + std::strerror(errno);
|
||||
const std::string msg = std::string{__FUNCTION__} + ": " + std::strerror(errno);
|
||||
VL_FATAL_MT("", 0, "", msg.c_str());
|
||||
close();
|
||||
break;
|
||||
|
||||
@@ -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.
|
||||
@@ -279,7 +279,7 @@ 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 vluint32_t len = rhs.length();
|
||||
os << len;
|
||||
return os.write(rhs.data(), len);
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
@@ -25,6 +25,9 @@
|
||||
#include "verilated_threads.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <fstream>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
//=============================================================================
|
||||
// Globals
|
||||
@@ -145,7 +148,7 @@ void VlThreadPool::profileAppendAll(const VlProfileRec& rec) VL_MT_SAFE_EXCLUDES
|
||||
}
|
||||
}
|
||||
|
||||
void VlThreadPool::profileDump(const char* filenamep, vluint64_t ticksElapsed)
|
||||
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););
|
||||
@@ -159,13 +162,23 @@ void VlThreadPool::profileDump(const char* filenamep, vluint64_t ticksElapsed)
|
||||
|
||||
// TODO Perhaps merge with verilated_coverage output format, so can
|
||||
// have a common merging and reporting tool, etc.
|
||||
fprintf(fp, "VLPROFTHREAD 1.0 # Verilator thread profile dump version 1.0\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",
|
||||
fprintf(fp, "VLPROFTHREAD 1.1 # Verilator thread profile dump version 1.1\n");
|
||||
fprintf(fp, "VLPROF arg --threads %" PRIu64 "\n", vluint64_t(m_workers.size() + 1));
|
||||
fprintf(fp, "VLPROF arg +verilator+prof+threads+start+%" PRIu64 "\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());
|
||||
fprintf(fp, "VLPROF stat yields %" PRIu64 "\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) {
|
||||
@@ -177,20 +190,35 @@ void VlThreadPool::profileDump(const char* filenamep, vluint64_t ticksElapsed)
|
||||
case VlProfileRec::TYPE_BARRIER: //
|
||||
printing = true;
|
||||
break;
|
||||
case VlProfileRec::TYPE_EVAL:
|
||||
if (!printing) break;
|
||||
fprintf(fp,
|
||||
"VLPROF eval start %" PRIu64 " elapsed %" PRIu64 " 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 %" PRIu64 " elapsed %" PRIu64
|
||||
" 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 end %" VL_PRI64 "u elapsed %" VL_PRI64 "u"
|
||||
" predict_time %u cpu %u on thread %u\n",
|
||||
ei.m_mtaskId, ei.m_startTime, ei.m_endTime,
|
||||
(ei.m_endTime - ei.m_startTime), ei.m_predictTime, ei.m_cpu, thread_id);
|
||||
" start %" PRIu64 " elapsed %" PRIu64
|
||||
" 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", ticksElapsed);
|
||||
fprintf(fp, "VLPROF stat ticks %" PRIu64 "\n", tickEnd - tickStart);
|
||||
|
||||
std::fclose(fp);
|
||||
}
|
||||
|
||||
+31
-15
@@ -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.
|
||||
@@ -43,7 +43,7 @@
|
||||
#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
|
||||
@@ -131,21 +131,36 @@ public:
|
||||
class VlProfileRec final {
|
||||
protected:
|
||||
friend class VlThreadPool;
|
||||
enum VlProfileE { TYPE_MTASK_RUN, TYPE_BARRIER };
|
||||
VlProfileE m_type = TYPE_BARRIER; // Record type
|
||||
vluint32_t m_mtaskId = 0; // Mtask we're logging
|
||||
vluint32_t m_predictTime = 0; // How long scheduler predicted would take
|
||||
vluint64_t m_startTime = 0; // Tick at start of execution
|
||||
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 startRecord(vluint64_t time, uint32_t mtask, uint32_t predict) {
|
||||
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_predictTime = predict;
|
||||
m_predictStart = predictStart;
|
||||
m_predictCost = predictCost;
|
||||
m_startTime = time;
|
||||
m_cpu = getcpu();
|
||||
}
|
||||
@@ -153,7 +168,7 @@ public:
|
||||
static int getcpu() { // Return current executing CPU
|
||||
#if defined(__linux)
|
||||
return sched_getcpu();
|
||||
#elif defined(__APPLE__)
|
||||
#elif defined(__APPLE__) && !defined(__arm64__)
|
||||
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
|
||||
@@ -202,12 +217,12 @@ private:
|
||||
// Store the size atomically, so we can spin wait
|
||||
std::atomic<size_t> m_ready_size;
|
||||
|
||||
VlThreadPool* m_poolp; // Our associated thread pool
|
||||
VlThreadPool* const m_poolp; // Our associated thread pool
|
||||
|
||||
bool m_profiling; // Is profiling enabled?
|
||||
const 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);
|
||||
|
||||
@@ -259,7 +274,7 @@ class VlThreadPool final {
|
||||
|
||||
// MEMBERS
|
||||
std::vector<VlWorkerThread*> m_workers; // our workers
|
||||
bool m_profiling; // is profiling enabled?
|
||||
const 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
|
||||
@@ -292,7 +307,8 @@ public:
|
||||
return &(t_profilep->back());
|
||||
}
|
||||
void profileAppendAll(const VlProfileRec& rec) VL_MT_SAFE_EXCLUDES(m_mutex);
|
||||
void profileDump(const char* filenamep, vluint64_t ticksElapsed) 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);
|
||||
|
||||
+23
-16
@@ -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.
|
||||
@@ -27,6 +27,8 @@
|
||||
#include "verilated.h"
|
||||
#include "verilated_trace_defs.h"
|
||||
|
||||
#include <bitset>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -141,7 +143,9 @@ private:
|
||||
};
|
||||
|
||||
vluint32_t* m_sigs_oldvalp; // Old value store
|
||||
EData* m_sigs_enabledp; // Bit vector of enabled codes (nullptr = all on)
|
||||
vluint64_t m_timeLastDump; // 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 traciong
|
||||
std::vector<CallbackRecord> m_fullCbs; // Routines to perform full dump
|
||||
std::vector<CallbackRecord> m_chgCbs; // Routines to perform incremental dump
|
||||
@@ -150,7 +154,8 @@ private:
|
||||
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
|
||||
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; // Time resolution (ns/ms etc)
|
||||
double m_timeUnit; // Time units (ns/ms etc)
|
||||
@@ -170,27 +175,22 @@ private:
|
||||
#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;
|
||||
|
||||
// Buffers handed to worker for processing
|
||||
VerilatedThreadQueue<vluint32_t*> m_buffersToWorker;
|
||||
// Buffers returned from worker after processing
|
||||
VerilatedThreadQueue<vluint32_t*> m_buffersFromWorker;
|
||||
// Write pointer into current buffer
|
||||
vluint32_t* m_traceBufferWritep;
|
||||
// End of trace buffer
|
||||
vluint32_t* m_traceBufferEndp;
|
||||
// The worker thread itself
|
||||
std::unique_ptr<std::thread> m_workerThread;
|
||||
|
||||
// Get a new trace buffer that can be populated. May block if none available
|
||||
vluint32_t* getTraceBuffer();
|
||||
|
||||
// Write pointer into current buffer
|
||||
vluint32_t* m_traceBufferWritep;
|
||||
|
||||
// End of trace buffer
|
||||
vluint32_t* m_traceBufferEndp;
|
||||
|
||||
// The worker thread itself
|
||||
std::unique_ptr<std::thread> m_workerThread;
|
||||
|
||||
// The function executed by the worker thread
|
||||
void workerThreadMain();
|
||||
|
||||
@@ -213,7 +213,6 @@ protected:
|
||||
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; }
|
||||
void fullDump(bool value) { m_fullDump = value; }
|
||||
vluint64_t timeLastDump() { return m_timeLastDump; }
|
||||
|
||||
@@ -223,12 +222,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(vluint32_t code, const char* namep, vluint32_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();
|
||||
@@ -257,6 +259,9 @@ 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);
|
||||
@@ -269,9 +274,11 @@ public:
|
||||
void addChgCb(dumpCb_t cb, void* userp) VL_MT_SAFE;
|
||||
void addCleanupCb(dumpCb_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);
|
||||
|
||||
//=========================================================================
|
||||
// Hot path internal interface to Verilator generated code
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
+105
-24
@@ -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.
|
||||
@@ -267,7 +267,7 @@ template <> void VerilatedTrace<VL_DERIVED_T>::flushBase() {
|
||||
// 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)
|
||||
// This calls 'flush' on the derived class (which must then get any mutex)
|
||||
reinterpret_cast<VL_DERIVED_T*>(selfp)->flush();
|
||||
}
|
||||
|
||||
@@ -282,6 +282,7 @@ template <> void VerilatedTrace<VL_DERIVED_T>::onExit(void* selfp) {
|
||||
template <>
|
||||
VerilatedTrace<VL_DERIVED_T>::VerilatedTrace()
|
||||
: m_sigs_oldvalp{nullptr}
|
||||
, m_sigs_enabledp{nullptr}
|
||||
, m_timeLastDump{0}
|
||||
, m_fullDump{true}
|
||||
, m_nextCode{0}
|
||||
@@ -302,6 +303,7 @@ VerilatedTrace<VL_DERIVED_T>::VerilatedTrace()
|
||||
|
||||
template <> VerilatedTrace<VL_DERIVED_T>::~VerilatedTrace() {
|
||||
if (m_sigs_oldvalp) VL_DO_CLEAR(delete[] m_sigs_oldvalp, m_sigs_oldvalp = nullptr);
|
||||
if (m_sigs_enabledp) VL_DO_CLEAR(delete[] m_sigs_enabledp, m_sigs_enabledp = nullptr);
|
||||
Verilated::removeFlushCb(VerilatedTrace<VL_DERIVED_T>::onFlush, this);
|
||||
Verilated::removeExitCb(VerilatedTrace<VL_DERIVED_T>::onExit, this);
|
||||
#ifdef VL_TRACE_THREADED
|
||||
@@ -320,9 +322,10 @@ template <> void VerilatedTrace<VL_DERIVED_T>::traceInit() VL_MT_UNSAFE {
|
||||
m_nextCode = 1;
|
||||
m_numSignals = 0;
|
||||
m_maxBits = 0;
|
||||
m_sigs_enabledVec.clear();
|
||||
|
||||
// Call all initialize callbacks, which will:
|
||||
// - Call decl* for each signal
|
||||
// - Call decl* for each signal (these eventually call ::declCode)
|
||||
// - Store the base code
|
||||
for (vluint32_t i = 0; i < m_initCbs.size(); ++i) {
|
||||
const CallbackRecord& cbr = m_initCbs[i];
|
||||
@@ -338,6 +341,23 @@ template <> void VerilatedTrace<VL_DERIVED_T>::traceInit() VL_MT_UNSAFE {
|
||||
// holding previous signal values.
|
||||
if (!m_sigs_oldvalp) m_sigs_oldvalp = new vluint32_t[nextCode()];
|
||||
|
||||
// Apply enables
|
||||
if (m_sigs_enabledp) VL_DO_CLEAR(delete[] m_sigs_enabledp, m_sigs_enabledp = nullptr);
|
||||
if (!m_sigs_enabledVec.empty()) {
|
||||
// Else if was empty, m_sigs_enabledp = nullptr to short circuit tests
|
||||
// But it isn't, so alloc one bit for each code to indicate enablement
|
||||
// We don't want to still use m_signs_enabledVec as std::vector<bool> is not
|
||||
// guarenteed to be fast
|
||||
m_sigs_enabledp = new vluint32_t[1 + VL_WORDS_I(nextCode())]{0};
|
||||
m_sigs_enabledVec.reserve(nextCode());
|
||||
for (size_t code = 0; code < nextCode(); ++code) {
|
||||
if (m_sigs_enabledVec[code]) {
|
||||
m_sigs_enabledp[VL_BITWORD_I(code)] |= 1U << VL_BITBIT_I(code);
|
||||
}
|
||||
}
|
||||
m_sigs_enabledVec.clear();
|
||||
}
|
||||
|
||||
// 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);
|
||||
@@ -356,10 +376,38 @@ template <> void VerilatedTrace<VL_DERIVED_T>::traceInit() VL_MT_UNSAFE {
|
||||
}
|
||||
|
||||
template <>
|
||||
void VerilatedTrace<VL_DERIVED_T>::declCode(vluint32_t code, vluint32_t bits, bool tri) {
|
||||
bool VerilatedTrace<VL_DERIVED_T>::declCode(vluint32_t code, const char* namep, vluint32_t bits,
|
||||
bool tri) {
|
||||
if (VL_UNCOVERABLE(!code)) {
|
||||
VL_FATAL_MT(__FILE__, __LINE__, "", "Internal: internal trace problem, code 0 is illegal");
|
||||
}
|
||||
// To keep it simple, this is O(enables * signals), but we expect few enables
|
||||
std::string declName = namePrefix() + namep;
|
||||
bool enabled = false;
|
||||
if (m_dumpvars.empty()) enabled = true;
|
||||
for (const auto& item : m_dumpvars) {
|
||||
const int dumpvarsLevel = item.first;
|
||||
const char* dvp = item.second.c_str();
|
||||
const char* np = declName.c_str();
|
||||
while (*dvp && *dvp == *np) {
|
||||
++dvp;
|
||||
++np;
|
||||
}
|
||||
if (*dvp) continue; // Didn't match dumpvar item
|
||||
if (*np && *np != ' ') continue; // e.g. "t" isn't a match for "top"
|
||||
int levels = 0;
|
||||
while (*np) {
|
||||
if (*np++ == ' ') ++levels;
|
||||
}
|
||||
if (levels > dumpvarsLevel) continue; // Too deep
|
||||
// We only need to set first code word if it's a multicode signal
|
||||
// as that's all we'll check for later
|
||||
if (m_sigs_enabledVec.size() <= code) m_sigs_enabledVec.resize((code + 1024) * 2);
|
||||
m_sigs_enabledVec[code] = true;
|
||||
enabled = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// 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);
|
||||
@@ -367,6 +415,7 @@ void VerilatedTrace<VL_DERIVED_T>::declCode(vluint32_t code, vluint32_t bits, bo
|
||||
m_nextCode = std::max(m_nextCode, code + codesNeeded);
|
||||
++m_numSignals;
|
||||
m_maxBits = std::max(m_maxBits, bits);
|
||||
return enabled;
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
@@ -392,6 +441,19 @@ 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>::dumpvars(int level, const std::string& hier) VL_MT_SAFE {
|
||||
if (level == 0) {
|
||||
m_dumpvars.clear(); // empty = everything on
|
||||
} else {
|
||||
// Convert Verilog . separators to trace space separators
|
||||
std::string hierSpaced = hier;
|
||||
for (auto& i : hierSpaced) {
|
||||
if (i == '.') i = ' ';
|
||||
}
|
||||
m_dumpvars.push_back(std::make_pair(level, hierSpaced));
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
void VerilatedTrace<VL_DERIVED_T>::dump(vluint64_t timeui) VL_MT_SAFE_EXCLUDES(m_mutex) {
|
||||
@@ -400,8 +462,8 @@ void VerilatedTrace<VL_DERIVED_T>::dump(vluint64_t timeui) VL_MT_SAFE_EXCLUDES(m
|
||||
// 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",
|
||||
VL_PRINTF_MT("%%Warning: previous dump at t=%" PRIu64 ", requesting t=%" PRIu64
|
||||
", dump call ignored\n",
|
||||
m_timeLastDump, timeui);
|
||||
return;
|
||||
} // LCOV_EXCL_STOP
|
||||
@@ -481,8 +543,8 @@ void VerilatedTrace<VL_DERIVED_T>::addCallbackRecord(std::vector<CallbackRecord>
|
||||
VL_MT_SAFE_EXCLUDES(m_mutex) {
|
||||
const VerilatedLockGuard lock{m_mutex};
|
||||
if (VL_UNCOVERABLE(timeLastDump() != 0)) { // LCOV_EXCL_START
|
||||
std::string msg = (std::string{"Internal: "} + __FILE__ + "::" + __FUNCTION__
|
||||
+ " called with already open file");
|
||||
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);
|
||||
@@ -504,9 +566,14 @@ template <> void VerilatedTrace<VL_DERIVED_T>::addCleanupCb(dumpCb_t cb, void* u
|
||||
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;
|
||||
|
||||
template <> void VerilatedTrace<VL_DERIVED_T>::pushNamePrefix(const std::string& prefix) {
|
||||
m_namePrefixStack.push_back(m_namePrefixStack.back() + prefix);
|
||||
}
|
||||
|
||||
template <> void VerilatedTrace<VL_DERIVED_T>::popNamePrefix(unsigned count) {
|
||||
while (count--) m_namePrefixStack.pop_back();
|
||||
assert(!m_namePrefixStack.empty());
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
@@ -518,44 +585,58 @@ template <> void VerilatedTrace<VL_DERIVED_T>::module(const std::string& name) V
|
||||
// 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);
|
||||
const uint32_t code = oldp - m_sigs_oldvalp;
|
||||
*oldp = newval; // Still copy even if not tracing so chg doesn't call full
|
||||
if (VL_UNLIKELY(m_sigs_enabledp && !(VL_BITISSET_W(m_sigs_enabledp, code)))) return;
|
||||
self()->emitBit(code, 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);
|
||||
const uint32_t code = oldp - m_sigs_oldvalp;
|
||||
*oldp = newval; // Still copy even if not tracing so chg doesn't call full
|
||||
if (VL_UNLIKELY(m_sigs_enabledp && !(VL_BITISSET_W(m_sigs_enabledp, code)))) return;
|
||||
self()->emitCData(code, 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);
|
||||
const uint32_t code = oldp - m_sigs_oldvalp;
|
||||
*oldp = newval; // Still copy even if not tracing so chg doesn't call full
|
||||
if (VL_UNLIKELY(m_sigs_enabledp && !(VL_BITISSET_W(m_sigs_enabledp, code)))) return;
|
||||
self()->emitSData(code, 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);
|
||||
const uint32_t code = oldp - m_sigs_oldvalp;
|
||||
*oldp = newval; // Still copy even if not tracing so chg doesn't call full
|
||||
if (VL_UNLIKELY(m_sigs_enabledp && !(VL_BITISSET_W(m_sigs_enabledp, code)))) return;
|
||||
self()->emitIData(code, newval, bits);
|
||||
}
|
||||
|
||||
template <>
|
||||
void VerilatedTrace<VL_DERIVED_T>::fullQData(vluint32_t* oldp, QData newval, int bits) {
|
||||
const uint32_t code = oldp - m_sigs_oldvalp;
|
||||
*reinterpret_cast<QData*>(oldp) = newval;
|
||||
self()->emitQData(oldp - m_sigs_oldvalp, newval, bits);
|
||||
if (VL_UNLIKELY(m_sigs_enabledp && !(VL_BITISSET_W(m_sigs_enabledp, code)))) return;
|
||||
self()->emitQData(code, newval, bits);
|
||||
}
|
||||
|
||||
template <>
|
||||
void VerilatedTrace<VL_DERIVED_T>::fullWData(vluint32_t* oldp, const WData* newvalp, int bits) {
|
||||
const uint32_t code = oldp - m_sigs_oldvalp;
|
||||
for (int i = 0; i < VL_WORDS_I(bits); ++i) oldp[i] = newvalp[i];
|
||||
self()->emitWData(oldp - m_sigs_oldvalp, newvalp, bits);
|
||||
if (VL_UNLIKELY(m_sigs_enabledp && !(VL_BITISSET_W(m_sigs_enabledp, code)))) return;
|
||||
self()->emitWData(code, newvalp, bits);
|
||||
}
|
||||
|
||||
template <> void VerilatedTrace<VL_DERIVED_T>::fullDouble(vluint32_t* oldp, double newval) {
|
||||
// cppcheck-suppress invalidPointerCast
|
||||
const uint32_t code = oldp - m_sigs_oldvalp;
|
||||
*reinterpret_cast<double*>(oldp) = newval;
|
||||
self()->emitDouble(oldp - m_sigs_oldvalp, newval);
|
||||
if (VL_UNLIKELY(m_sigs_enabledp && !(VL_BITISSET_W(m_sigs_enabledp, code)))) return;
|
||||
// cppcheck-suppress invalidPointerCast
|
||||
self()->emitDouble(code, newval);
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
@@ -655,7 +736,7 @@ static inline void cvtQDataToStr(char* dstp, QData value) {
|
||||
void verilated_trace_imp_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)
|
||||
|
||||
#define SELF_CHECK_TS(scale) \
|
||||
|
||||
+21
-12
@@ -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.
|
||||
@@ -28,6 +28,14 @@
|
||||
#error "verilated_types.h should only be included by verilated.h"
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
#include <deque>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <unordered_set>
|
||||
#include <utility>
|
||||
|
||||
//===================================================================
|
||||
// String formatters (required by below containers)
|
||||
|
||||
@@ -45,22 +53,22 @@ extern std::string VL_TO_STRING_W(int words, const WDataInP obj);
|
||||
#define VL_SIG16(name, msb, lsb) SData name ///< Declare signal, 9-16 bits
|
||||
#define VL_SIG64(name, msb, lsb) QData name ///< Declare signal, 33-64 bits
|
||||
#define VL_SIG(name, msb, lsb) IData name ///< Declare signal, 17-32 bits
|
||||
#define VL_SIGW(name, msb, lsb, words) WData name[words] ///< Declare signal, 65+ bits
|
||||
#define VL_SIGW(name, msb, lsb, words) VlWide<words> name ///< Declare signal, 65+ bits
|
||||
#define VL_IN8(name, msb, lsb) CData name ///< Declare input signal, 1-8 bits
|
||||
#define VL_IN16(name, msb, lsb) SData name ///< Declare input signal, 9-16 bits
|
||||
#define VL_IN64(name, msb, lsb) QData name ///< Declare input signal, 33-64 bits
|
||||
#define VL_IN(name, msb, lsb) IData name ///< Declare input signal, 17-32 bits
|
||||
#define VL_INW(name, msb, lsb, words) WData name[words] ///< Declare input signal, 65+ bits
|
||||
#define VL_INW(name, msb, lsb, words) VlWide<words> name ///< Declare input signal, 65+ bits
|
||||
#define VL_INOUT8(name, msb, lsb) CData name ///< Declare bidir signal, 1-8 bits
|
||||
#define VL_INOUT16(name, msb, lsb) SData name ///< Declare bidir signal, 9-16 bits
|
||||
#define VL_INOUT64(name, msb, lsb) QData name ///< Declare bidir signal, 33-64 bits
|
||||
#define VL_INOUT(name, msb, lsb) IData name ///< Declare bidir signal, 17-32 bits
|
||||
#define VL_INOUTW(name, msb, lsb, words) WData name[words] ///< Declare bidir signal, 65+ bits
|
||||
#define VL_INOUTW(name, msb, lsb, words) VlWide<words> name ///< Declare bidir signal, 65+ bits
|
||||
#define VL_OUT8(name, msb, lsb) CData name ///< Declare output signal, 1-8 bits
|
||||
#define VL_OUT16(name, msb, lsb) SData name ///< Declare output signal, 9-16 bits
|
||||
#define VL_OUT64(name, msb, lsb) QData name ///< Declare output signal, 33-64bits
|
||||
#define VL_OUT(name, msb, lsb) IData name ///< Declare output signal, 17-32 bits
|
||||
#define VL_OUTW(name, msb, lsb, words) WData name[words] ///< Declare output signal, 65+ bits
|
||||
#define VL_OUTW(name, msb, lsb, words) VlWide<words> name ///< Declare output signal, 65+ bits
|
||||
|
||||
//===================================================================
|
||||
// Shuffle RNG
|
||||
@@ -79,13 +87,14 @@ public:
|
||||
// Readmem/Writemem operation classes
|
||||
|
||||
class VlReadMem final {
|
||||
bool m_hex; // Hex format
|
||||
int m_bits; // Bit width of values
|
||||
const bool m_hex; // Hex format
|
||||
const int m_bits; // Bit width of values
|
||||
const std::string& m_filename; // Filename
|
||||
QData m_end; // End address (as specified by user)
|
||||
const QData m_end; // End address (as specified by user)
|
||||
FILE* m_fp; // File handle for filename
|
||||
QData m_addr; // Next address to read
|
||||
int m_linenum; // Line number last read from file
|
||||
bool m_anyAddr = false; // Had address directive in the file
|
||||
public:
|
||||
VlReadMem(bool hex, int bits, const std::string& filename, QData start, QData end);
|
||||
~VlReadMem();
|
||||
@@ -96,8 +105,8 @@ public:
|
||||
};
|
||||
|
||||
class VlWriteMem final {
|
||||
bool m_hex; // Hex format
|
||||
int m_bits; // Bit width of values
|
||||
const bool m_hex; // Hex format
|
||||
const int m_bits; // Bit width of values
|
||||
FILE* m_fp; // File handle for filename
|
||||
QData m_addr; // Next address to write
|
||||
public:
|
||||
@@ -848,8 +857,8 @@ template <class T_Value, std::size_t T_Depth> struct VlUnpacked final {
|
||||
WData* data() { return &m_storage[0]; }
|
||||
const WData* data() const { return &m_storage[0]; }
|
||||
|
||||
T_Value& operator[](size_t index) { return m_storage[index]; };
|
||||
const T_Value& operator[](size_t index) const { return m_storage[index]; };
|
||||
T_Value& operator[](size_t index) { return m_storage[index]; }
|
||||
const T_Value& operator[](size_t index) const { return m_storage[index]; }
|
||||
|
||||
// Dumping. Verilog: str = $sformatf("%p", assoc)
|
||||
std::string to_string() const {
|
||||
|
||||
+21
-16
@@ -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.
|
||||
@@ -273,7 +273,7 @@ void VerilatedVcd::printStr(const char* str) {
|
||||
void VerilatedVcd::printQuad(vluint64_t n) {
|
||||
constexpr size_t LEN_STR_QUAD = 40;
|
||||
char buf[LEN_STR_QUAD];
|
||||
VL_SNPRINTF(buf, LEN_STR_QUAD, "%" VL_PRI64 "u", n);
|
||||
VL_SNPRINTF(buf, LEN_STR_QUAD, "%" PRIu64, n);
|
||||
printStr(buf);
|
||||
}
|
||||
|
||||
@@ -281,7 +281,7 @@ void VerilatedVcd::bufferResize(vluint64_t minsize) {
|
||||
// minsize is size of largest write. We buffer at least 8 times as much data,
|
||||
// writing when we are 3/4 full (with thus 2*minsize remaining free)
|
||||
if (VL_UNLIKELY(minsize > m_wrChunkSize)) {
|
||||
char* oldbufp = m_wrBufp;
|
||||
const char* oldbufp = m_wrBufp;
|
||||
m_wrChunkSize = minsize * 2;
|
||||
m_wrBufp = new char[m_wrChunkSize * 8];
|
||||
std::memcpy(m_wrBufp, oldbufp, m_writep - oldbufp);
|
||||
@@ -298,7 +298,7 @@ void VerilatedVcd::bufferFlush() VL_MT_UNSAFE_ONE {
|
||||
// When it gets nearly full we dump it using this routine which calls write()
|
||||
// This is much faster than using buffered I/O
|
||||
if (VL_UNLIKELY(!isOpen())) return;
|
||||
char* wp = m_wrBufp;
|
||||
const char* wp = m_wrBufp;
|
||||
while (true) {
|
||||
const ssize_t remaining = (m_writep - wp);
|
||||
if (remaining == 0) break;
|
||||
@@ -311,7 +311,7 @@ void VerilatedVcd::bufferFlush() VL_MT_UNSAFE_ONE {
|
||||
if (VL_UNCOVERABLE(errno != EAGAIN && errno != EINTR)) {
|
||||
// LCOV_EXCL_START
|
||||
// write failed, presume error (perhaps out of disk space)
|
||||
std::string msg
|
||||
const std::string msg
|
||||
= std::string{"VerilatedVcd::bufferFlush: "} + std::strerror(errno);
|
||||
VL_FATAL_MT("", 0, "", msg.c_str());
|
||||
closeErr();
|
||||
@@ -386,7 +386,7 @@ void VerilatedVcd::dumpHeader() {
|
||||
const std::string& decl = i.second;
|
||||
|
||||
// Determine difference between the old and new names
|
||||
const char* hiername = hiernamestr.c_str();
|
||||
const char* const hiername = hiernamestr.c_str();
|
||||
const char* lp = lastName;
|
||||
const char* np = hiername;
|
||||
lastName = hiername;
|
||||
@@ -426,8 +426,9 @@ void VerilatedVcd::dumpHeader() {
|
||||
case VLT_TRACE_SCOPE_UNION: printStr("union "); break;
|
||||
default: printStr("module ");
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
printStr("module ");
|
||||
}
|
||||
|
||||
for (; *np && *np != ' ' && *np != '\t'; np++) {
|
||||
if (*np == '[') {
|
||||
@@ -462,7 +463,7 @@ void VerilatedVcd::declare(vluint32_t code, const char* name, const char* wirep,
|
||||
int arraynum, bool tri, bool bussed, int msb, int lsb) {
|
||||
const int bits = ((msb > lsb) ? (msb - lsb) : (lsb - msb)) + 1;
|
||||
|
||||
VerilatedTrace<VerilatedVcd>::declCode(code, bits, tri);
|
||||
const bool enabled = VerilatedTrace<VerilatedVcd>::declCode(code, name, bits, tri);
|
||||
|
||||
if (m_suffixes.size() <= nextCode() * VL_TRACE_SUFFIX_ENTRY_SIZE) {
|
||||
m_suffixes.resize(nextCode() * VL_TRACE_SUFFIX_ENTRY_SIZE * 2, 0);
|
||||
@@ -471,16 +472,15 @@ void VerilatedVcd::declare(vluint32_t code, const char* name, const char* wirep,
|
||||
// Make sure write buffer is large enough (one character per bit), plus header
|
||||
bufferResize(bits + 1024);
|
||||
|
||||
if (!enabled) return;
|
||||
|
||||
// Split name into basename
|
||||
// Spaces and tabs aren't legal in VCD signal names, so:
|
||||
// Space separates each level of scope
|
||||
// Tab separates final scope from signal name
|
||||
// Tab sorts before spaces, so signals nicely will print before scopes
|
||||
// Note the hiername may be nothing, if so we'll add "\t{name}"
|
||||
std::string nameasstr = name;
|
||||
if (!moduleName().empty()) {
|
||||
nameasstr = moduleName() + scopeEscape() + nameasstr; // Optional ->module prefix
|
||||
}
|
||||
std::string nameasstr = namePrefix() + name;
|
||||
std::string hiername;
|
||||
std::string basename;
|
||||
for (const char* cp = nameasstr.c_str(); *cp; cp++) {
|
||||
@@ -608,6 +608,7 @@ static inline void VerilatedVcdCCopyAndAppendNewLine(char* writep, const char* s
|
||||
|
||||
void VerilatedVcd::finishLine(vluint32_t code, char* writep) {
|
||||
const char* const suffixp = m_suffixes.data() + code * VL_TRACE_SUFFIX_ENTRY_SIZE;
|
||||
VL_DEBUG_IFDEF(assert(suffixp[0]););
|
||||
VerilatedVcdCCopyAndAppendNewLine(writep, suffixp);
|
||||
|
||||
// Now write back the write pointer incremented by the actual size of the
|
||||
@@ -830,16 +831,19 @@ float flo = 0.0f;
|
||||
|
||||
void vcdInit(void*, VerilatedVcd* vcdp, vluint32_t) {
|
||||
vcdp->scopeEscape('.');
|
||||
vcdp->module("top");
|
||||
vcdp->pushNamePrefix("top.");
|
||||
/**/ vcdp->declBus(0x2, "v1", -1, 0, 5, 1);
|
||||
/**/ vcdp->declBus(0x3, "v2", -1, 0, 6, 1);
|
||||
/**/ vcdp->module("top.sub1");
|
||||
/**/ vcdp->pushNamePrefix("sub1.");
|
||||
/***/ vcdp->declBit(0x4, "s1", -1, 0);
|
||||
/***/ vcdp->declBit(0x5, "ch", -1, 0);
|
||||
/**/ vcdp->module("top.sub2");
|
||||
/**/ vcdp->popNamePrefix();
|
||||
/**/ vcdp->pushNamePrefix("sub2.");
|
||||
/***/ vcdp->declArray(0x6, "s2", -1, 0, 40, 3);
|
||||
/**/ vcdp->popNamePrefix();
|
||||
vcdp->popNamePrefix();
|
||||
// Note need to add 3 for next code.
|
||||
vcdp->module("top2");
|
||||
vcdp->pushNamePrefix("top2.");
|
||||
/**/ vcdp->declBus(0x2, "t2v1", -1, 0, 4, 1);
|
||||
/**/ vcdp->declTriBit(0x10, "io1", -1, 0);
|
||||
/**/ vcdp->declTriBus(0x12, "io5", -1, 0, 4, 0);
|
||||
@@ -851,6 +855,7 @@ void vcdInit(void*, VerilatedVcd* vcdp, vluint32_t) {
|
||||
/**/ // Note need to add 4 for next code.
|
||||
/**/ vcdp->declTriQuad(0x24, "tq", -1, 0, 63, 0);
|
||||
/**/ // Note need to add 4 for next code.
|
||||
vcdp->popNamePrefix();
|
||||
}
|
||||
|
||||
void vcdFull(void*, VerilatedVcd* vcdp) {
|
||||
|
||||
@@ -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.
|
||||
@@ -74,7 +74,7 @@ private:
|
||||
int m_modDepth = 0; // Depth of module hierarchy
|
||||
|
||||
char* m_wrBufp; // Output buffer
|
||||
char* m_wrFlushp; // Output buffer flush trigger location
|
||||
const char* m_wrFlushp; // Output buffer flush trigger location
|
||||
char* m_writep; // Write pointer into output buffer
|
||||
vluint64_t m_wrChunkSize; // Output buffer size
|
||||
vluint64_t m_wroteBytes = 0; // Number of bytes written to this file
|
||||
@@ -328,6 +328,7 @@ template <> void VerilatedTrace<VerilatedVcd>::set_time_unit(const char* unitp);
|
||||
template <> void VerilatedTrace<VerilatedVcd>::set_time_unit(const std::string& unit);
|
||||
template <> void VerilatedTrace<VerilatedVcd>::set_time_resolution(const char* unitp);
|
||||
template <> void VerilatedTrace<VerilatedVcd>::set_time_resolution(const std::string& unit);
|
||||
template <> void VerilatedTrace<VerilatedVcd>::dumpvars(int level, const std::string& hier);
|
||||
#endif // DOXYGEN
|
||||
|
||||
//=============================================================================
|
||||
@@ -346,7 +347,7 @@ public:
|
||||
explicit VerilatedVcdC(VerilatedVcdFile* filep = nullptr)
|
||||
: m_sptrace{filep} {}
|
||||
/// Destruct, flush, and close the dump
|
||||
~VerilatedVcdC() { close(); }
|
||||
virtual ~VerilatedVcdC() { close(); }
|
||||
|
||||
public:
|
||||
// METHODS - User called
|
||||
@@ -356,7 +357,7 @@ public:
|
||||
/// Open a new VCD file
|
||||
/// This includes a complete header dump each time it is called,
|
||||
/// just as if this object was deleted and reconstructed.
|
||||
void open(const char* filename) VL_MT_SAFE { m_sptrace.open(filename); }
|
||||
virtual void open(const char* filename) VL_MT_SAFE { m_sptrace.open(filename); }
|
||||
/// Continue a VCD dump by rotating to a new file name
|
||||
/// The header is only in the first file created, this allows
|
||||
/// "cat" to be used to combine the header plus any number of data files.
|
||||
@@ -392,6 +393,11 @@ 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 VerilatedVcd* spTrace() { return &m_sptrace; }
|
||||
|
||||
@@ -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.
|
||||
@@ -27,6 +27,17 @@
|
||||
//======================================================================
|
||||
//======================================================================
|
||||
|
||||
void VerilatedVcdSc::open(const char* filename) {
|
||||
if (!sc_core::sc_get_curr_simcontext()->elaboration_done()) {
|
||||
vl_fatal(__FILE__, __LINE__, "VerilatedVcdSc",
|
||||
("%Error: VerilatedVcdSc::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());
|
||||
}
|
||||
VerilatedVcdC::open(filename);
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// SystemC 2.1.v1
|
||||
// cppcheck-suppress unusedFunction
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user