mirror of
https://github.com/verilator/verilator.git
synced 2026-10-02 16:13:34 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eab46d547d | ||
|
|
3dd552c4a2 | ||
|
|
23bb045a72 | ||
|
|
7c834ad118 | ||
|
|
8e2617ab8d | ||
|
|
24fcae4f49 | ||
|
|
ce18674d88 | ||
|
|
6b8d9b5c36 | ||
|
|
81bf95763c | ||
|
|
2d64077fd0 | ||
|
|
38faebcf20 | ||
|
|
48d177a9d0 | ||
|
|
3b3a7f7354 | ||
|
|
99cd2818a1 | ||
|
|
5765e099a6 | ||
|
|
175d59ecba | ||
|
|
3bd3d01968 | ||
|
|
85e2a6bb45 | ||
|
|
84efd239a5 | ||
|
|
6a69813326 | ||
|
|
2c9dcc3913 | ||
|
|
20ea1ca018 | ||
|
|
0abde90933 | ||
|
|
e01b69198a | ||
|
|
53cd9d2403 | ||
|
|
3d0f5fc078 | ||
|
|
54eedcc739 | ||
|
|
ae6f5844da | ||
|
|
1bea845ceb | ||
|
|
d581582339 | ||
|
|
4eabc1992e | ||
|
|
316eb24bbb | ||
|
|
f0a8824efc | ||
|
|
345a5d5646 | ||
|
|
464679c78b | ||
|
|
28eeec1cf4 | ||
|
|
7d0dce3267 | ||
|
|
9e29625207 | ||
|
|
a767da4f3f | ||
|
|
7bd96c2876 | ||
|
|
70fd64dcd6 | ||
|
|
bb2822f4b5 | ||
|
|
ad21108b63 | ||
|
|
e6808a787c | ||
|
|
1fb2762725 | ||
|
|
cce55941d3 | ||
|
|
6c8d95e0e2 | ||
|
|
216a178b28 | ||
|
|
6594a54a95 | ||
|
|
a9a4cf061a | ||
|
|
b7f0e204cb | ||
|
|
e6a15f233b | ||
|
|
e0edb596ea | ||
|
|
f2fb77c15a | ||
|
|
772a3a97eb | ||
|
|
6c310836a1 | ||
|
|
75416a3016 | ||
|
|
ebef78a13e | ||
|
|
e71baca39b | ||
|
|
18eb210313 | ||
|
|
7d38a5e1f9 | ||
|
|
4386077e2d | ||
|
|
49dbfd2131 | ||
|
|
a80fce5ac1 | ||
|
|
891b981cab | ||
|
|
2dd87b8384 | ||
|
|
062eb85075 | ||
|
|
e1f6802f5f | ||
|
|
6cfcd50f12 | ||
|
|
bcadb0b3b3 | ||
|
|
0df561f873 | ||
|
|
238fc24684 | ||
|
|
936855c81c | ||
|
|
61ad9d4651 | ||
|
|
f07f6a26a8 | ||
|
|
4a5a56f8ef | ||
|
|
7d44bba95c | ||
|
|
6e6f1045b8 | ||
|
|
5dd3221759 | ||
|
|
09edb467f6 | ||
|
|
ffb187ae15 | ||
|
|
b4a8be07f3 | ||
|
|
4968a2abc5 | ||
|
|
91159da30d | ||
|
|
c9ad61b4fb | ||
|
|
3f0dcd8c0e | ||
|
|
e1eb41fe77 | ||
|
|
498ab23355 | ||
|
|
5d6a053f98 | ||
|
|
929aeebf12 | ||
|
|
00bd947385 | ||
|
|
d4ef86afc0 | ||
|
|
1856cad816 | ||
|
|
91e2d1d2a0 | ||
|
|
f29f30dce0 | ||
|
|
e7ba6ef492 | ||
|
|
de4016dcff | ||
|
|
bbeb382cbb | ||
|
|
385c166830 | ||
|
|
410e6ff203 | ||
|
|
8b47c4e307 | ||
|
|
6d1b42bedb | ||
|
|
f0a4bd28b6 | ||
|
|
2879684f21 | ||
|
|
0437d0abea | ||
|
|
0286f588bf | ||
|
|
042fb76837 | ||
|
|
795e66eac9 | ||
|
|
aae0615ffd | ||
|
|
8127a79cb1 | ||
|
|
057ca497dd | ||
|
|
66b1611649 | ||
|
|
7f5220a6ca | ||
|
|
e41e26717b | ||
|
|
7a8184d206 | ||
|
|
13bf2f19ac | ||
|
|
1d5ebfd0b1 | ||
|
|
dfc11da2ce | ||
|
|
191af2e87b | ||
|
|
0985b82760 | ||
|
|
26f4b5a69a | ||
|
|
5c7a6e278f | ||
|
|
ae1ab8aaaa | ||
|
|
18c25d1b6f | ||
|
|
5888a2c399 | ||
|
|
c00603704e | ||
|
|
786bc4b04f | ||
|
|
5eca20f849 | ||
|
|
0a3a582949 | ||
|
|
08fec0534d | ||
|
|
5bf92c9d3a | ||
|
|
a8bbf7231b | ||
|
|
83c171012d | ||
|
|
229d854607 | ||
|
|
562460606f | ||
|
|
46f70b1cbb | ||
|
|
a547133efe | ||
|
|
cf445898ce | ||
|
|
98f68e46d6 | ||
|
|
27660b271d | ||
|
|
895e374860 | ||
|
|
4c7f051247 | ||
|
|
e68afa53a8 | ||
|
|
cc47ba2404 | ||
|
|
2238fa46ed | ||
|
|
de8b040e31 | ||
|
|
4ffc48d194 | ||
|
|
2433848408 | ||
|
|
e602f7febc | ||
|
|
f607b32938 | ||
|
|
c7a088faa5 | ||
|
|
30f6c0e105 | ||
|
|
38b9fa7b93 | ||
|
|
39a31fc17f | ||
|
|
899a7df14a | ||
|
|
7a8c425103 | ||
|
|
0e8ce59022 | ||
|
|
77ac76a158 | ||
|
|
8108b97050 | ||
|
|
a1c3491dea | ||
|
|
8bba96a84e | ||
|
|
6cd9b25a53 | ||
|
|
0431b1909c | ||
|
|
907665e2e8 | ||
|
|
61e8836fbd | ||
|
|
0e921b5dff | ||
|
|
7ef37d6e17 | ||
|
|
dce227684a | ||
|
|
158e112752 | ||
|
|
ec992c7f5e | ||
|
|
e7d63c7644 | ||
|
|
6464e8fee6 | ||
|
|
047d66a657 | ||
|
|
55c23360d9 | ||
|
|
c378d32c85 | ||
|
|
3d9540c58c | ||
|
|
39724eb916 | ||
|
|
48dddd4ae7 | ||
|
|
9c00fd10de | ||
|
|
9309d0b00f | ||
|
|
038b5d32a3 | ||
|
|
706920ba19 | ||
|
|
39492a0726 | ||
|
|
df1170fea9 | ||
|
|
f0e1d204fa | ||
|
|
8ece0a8a5f | ||
|
|
1373b81e7c | ||
|
|
d3601dd561 | ||
|
|
f685cf1d0c | ||
|
|
d5fcf0c153 | ||
|
|
5f9810070d | ||
|
|
923efa004b | ||
|
|
869e8eab3c | ||
|
|
b51d197117 | ||
|
|
e4f0a8952c | ||
|
|
072ee425f4 | ||
|
|
a4c2819be2 | ||
|
|
2a274f9c19 | ||
|
|
b4d5a20670 | ||
|
|
6339159b04 | ||
|
|
aec019991c | ||
|
|
33e6a17747 | ||
|
|
ecf508ec23 | ||
|
|
a5bcfc0509 | ||
|
|
1899096ff4 | ||
|
|
6e219f5831 | ||
|
|
de1bb5aeb6 | ||
|
|
b52d94273c | ||
|
|
e655c85489 | ||
|
|
dee7210231 | ||
|
|
cbd073ed08 | ||
|
|
09ebc0c163 | ||
|
|
d2ede75c71 | ||
|
|
3e03fef3e3 | ||
|
|
0f583f4b33 | ||
|
|
f175db74a5 | ||
|
|
8d5e37a413 | ||
|
|
8b9b7178a2 | ||
|
|
a2f49063e2 | ||
|
|
f3f34baa73 | ||
|
|
abe9ecd225 | ||
|
|
67409af38d | ||
|
|
b7d1c34aa6 | ||
|
|
92809b95c9 | ||
|
|
b18690cbe2 | ||
|
|
96155365b2 | ||
|
|
3e5067feb1 | ||
|
|
3ec687a0cf | ||
|
|
365034d7dd | ||
|
|
09aa9f87d8 | ||
|
|
97963fb8c9 | ||
|
|
ee1643ce39 | ||
|
|
a82cdcfe48 | ||
|
|
1b439703ff | ||
|
|
4cc5943f90 | ||
|
|
5fad666678 | ||
|
|
e12bf35996 | ||
|
|
d34fccec22 | ||
|
|
429437f1b9 | ||
|
|
c6e7d87960 | ||
|
|
716320f3ca | ||
|
|
1d12b47cb8 | ||
|
|
1bc1ee9e08 | ||
|
|
53f50463bc | ||
|
|
7ab91e660f | ||
|
|
2f0e230522 | ||
|
|
280f674ce9 | ||
|
|
a92c66d512 | ||
|
|
c45eedcb02 | ||
|
|
a9a49345ba | ||
|
|
8d960a2eb9 | ||
|
|
3e623b8959 | ||
|
|
1b1991d53d | ||
|
|
6d0f39d841 | ||
|
|
3087501b6c | ||
|
|
b429319bc0 | ||
|
|
247e855dbf | ||
|
|
1aec645510 | ||
|
|
3ea2038d3d | ||
|
|
942cb5e87e | ||
|
|
37a3a7cdce | ||
|
|
435a27b66a | ||
|
|
b31a7cdcbf | ||
|
|
ac61548e6a | ||
|
|
f5ace0f72a | ||
|
|
e498b73933 | ||
|
|
ff69bdbc6f | ||
|
|
0c1e184cb7 | ||
|
|
e97541dcbc | ||
|
|
7b3eb22865 | ||
|
|
d55f065ce2 | ||
|
|
86af244636 | ||
|
|
2c9e2b2e3c | ||
|
|
33c8bf886e | ||
|
|
ef71a089a6 | ||
|
|
5fc98cce0d | ||
|
|
b9101c3d6a | ||
|
|
6aab0f627c | ||
|
|
6b97673d0a | ||
|
|
5d8c1ce84e | ||
|
|
33c9591a4b | ||
|
|
87e8736823 | ||
|
|
c0da16bfcd | ||
|
|
a4ddc5b3ac | ||
|
|
91e4010039 | ||
|
|
486b6580d8 | ||
|
|
9c4ef27d49 | ||
|
|
33577eaa68 | ||
|
|
d5e19661bd | ||
|
|
799afac05b | ||
|
|
3ba36dc30c | ||
|
|
641024c235 | ||
|
|
d9598db117 | ||
|
|
2e4da07a15 | ||
|
|
40f4411b69 | ||
|
|
c75de0f37c | ||
|
|
74c4c1bf44 | ||
|
|
60a637921c | ||
|
|
22312b3c9c | ||
|
|
2e26e44538 | ||
|
|
24e79ecc68 | ||
|
|
5b532a1812 | ||
|
|
f3867d7f80 | ||
|
|
fb90e47e70 | ||
|
|
68046244dd | ||
|
|
b1507060ad | ||
|
|
ffbd595d88 | ||
|
|
ed5bc1e69c | ||
|
|
9734931f67 | ||
|
|
0048b04540 | ||
|
|
c361932fe2 | ||
|
|
2d8feabe54 | ||
|
|
1b511dd130 | ||
|
|
52024f4d80 | ||
|
|
735fa6287f | ||
|
|
7eb407fe2b | ||
|
|
897d5c58b3 | ||
|
|
dc9086512b | ||
|
|
0029d068c7 | ||
|
|
de388b3dc8 | ||
|
|
fb904d53cd | ||
|
|
600cc02de3 | ||
|
|
946d0cd219 | ||
|
|
4d0b964e36 | ||
|
|
2b12ab4d5a | ||
|
|
8114957e6d | ||
|
|
50edef4ab2 | ||
|
|
e5a991988f | ||
|
|
e85eb6d0f4 | ||
|
|
6949f35f22 | ||
|
|
e0391b93c4 | ||
|
|
4a5e775a2b | ||
|
|
323f019350 | ||
|
|
98053c2d4c | ||
|
|
aab338760c | ||
|
|
ab9a2b1728 | ||
|
|
6a38d3bcf3 | ||
|
|
76f3cbdf4c | ||
|
|
d45d58b6bf | ||
|
|
f32a422330 | ||
|
|
74d4be28dd | ||
|
|
b4a31bd292 | ||
|
|
cc1adf9b38 | ||
|
|
1601b3b6b0 | ||
|
|
61cbdd1a19 | ||
|
|
a3ee6131a3 | ||
|
|
6dfddaa453 | ||
|
|
de696b7092 | ||
|
|
9165233657 | ||
|
|
aa3a417e97 | ||
|
|
996f48fcf0 | ||
|
|
81d83f629f | ||
|
|
5e3b0bf348 | ||
|
|
4a31463299 | ||
|
|
8a5471e175 | ||
|
|
605fd9f8e1 | ||
|
|
2bda43875d | ||
|
|
11edc9e7a7 | ||
|
|
3b9b823511 | ||
|
|
da0ecf59c6 | ||
|
|
e5b1fdf668 | ||
|
|
204fb82975 | ||
|
|
37839e2709 | ||
|
|
dbaedb5995 | ||
|
|
0a832e90bd | ||
|
|
b4e908d04d | ||
|
|
4619d29b78 | ||
|
|
c63b697636 | ||
|
|
06d29d6fda | ||
|
|
c0f7bc4b5e | ||
|
|
7139c9ae59 | ||
|
|
0ae00fc921 | ||
|
|
fe456cb83d | ||
|
|
a8432ed4a4 | ||
|
|
04f910b747 | ||
|
|
1c3de70155 | ||
|
|
b73642f8a8 | ||
|
|
479b497528 | ||
|
|
31b55d3844 | ||
|
|
dbf4e08d09 | ||
|
|
274359e6ee | ||
|
|
8687dcbce1 | ||
|
|
03dfbdb7b1 | ||
|
|
3c8519f245 | ||
|
|
4d2cc3ebdd | ||
|
|
6e2758ae26 | ||
|
|
4637e06ad2 | ||
|
|
764399256c | ||
|
|
f4ca4edc64 | ||
|
|
872a1216a7 | ||
|
|
8c75674591 | ||
|
|
e6244ca204 | ||
|
|
f540362e36 | ||
|
|
2be6699a6a | ||
|
|
09c10492ab | ||
|
|
c8e4b1fc84 | ||
|
|
0de7cece5b | ||
|
|
a3413a6749 | ||
|
|
b104ab9491 | ||
|
|
269c5dce60 | ||
|
|
a39c81c63f | ||
|
|
d699247269 | ||
|
|
7caafb4014 | ||
|
|
f1546abf09 | ||
|
|
3083562f6f | ||
|
|
da2ee70462 | ||
|
|
7e9dda3c5e | ||
|
|
0b96f88875 | ||
|
|
f13ffe2098 | ||
|
|
bca5d26583 | ||
|
|
660bc757f1 | ||
|
|
ca927fe587 | ||
|
|
9df8966f4a | ||
|
|
3429f41489 | ||
|
|
0c7c4924ee | ||
|
|
8f40d6617e | ||
|
|
af9e85bda1 | ||
|
|
717f45d117 | ||
|
|
35c53865fb | ||
|
|
a1d1d6d3d4 | ||
|
|
d17f812827 | ||
|
|
3916758529 | ||
|
|
2396181bc5 | ||
|
|
6e8640bf1b | ||
|
|
c2c7c7bd9a | ||
|
|
071a1c4adb | ||
|
|
d5b2dda2e8 | ||
|
|
2ac281eb3e | ||
|
|
5e81543448 | ||
|
|
b32f925468 | ||
|
|
fdeb6bcae0 | ||
|
|
76232cd9e7 | ||
|
|
4da9b5e491 | ||
|
|
c4504a9221 | ||
|
|
65de8359e7 | ||
|
|
f6fab74436 | ||
|
|
350ba264e8 | ||
|
|
29e24818a1 | ||
|
|
71cd6f7b90 | ||
|
|
84ba253791 | ||
|
|
fce158b8ad | ||
|
|
da13ba6c67 | ||
|
|
7618133298 | ||
|
|
0d1698f81d | ||
|
|
362d642c87 | ||
|
|
e4c96d5be5 | ||
|
|
f488701adc | ||
|
|
8ff2bf51c5 | ||
|
|
a2490a55a9 | ||
|
|
20189f5191 | ||
|
|
06b796c6bd | ||
|
|
ad4edf6c68 | ||
|
|
4100f20a69 | ||
|
|
bedf946fb2 | ||
|
|
b9e67157c6 | ||
|
|
b30b2a183b | ||
|
|
9ab3bcdde3 | ||
|
|
5df3bbe188 | ||
|
|
8cf12416c0 | ||
|
|
b7c2c83c88 | ||
|
|
3b6da93331 | ||
|
|
b4642d3fd4 | ||
|
|
88a2b0b911 | ||
|
|
954e127f1d | ||
|
|
7654add5e5 | ||
|
|
85a37ea53f | ||
|
|
b337acebcc | ||
|
|
fb9ca54c95 | ||
|
|
1a15d41523 | ||
|
|
e378cc5791 | ||
|
|
748c189c79 | ||
|
|
b89be6c4b9 | ||
|
|
df207807b6 | ||
|
|
1f2b40cff1 | ||
|
|
734400fd37 | ||
|
|
f19979d928 | ||
|
|
19be7a53da | ||
|
|
e56af34fb0 |
+3
-1
@@ -9,15 +9,17 @@
|
||||
.*.swp
|
||||
*.tmp
|
||||
*.tex
|
||||
*.pdf
|
||||
/Makefile
|
||||
README
|
||||
TAGS
|
||||
autom4te.cache
|
||||
config.cache
|
||||
config.status
|
||||
configure
|
||||
dddrun*
|
||||
doxygen-doc
|
||||
gdbrun*
|
||||
internals.txt
|
||||
verilator.pdf
|
||||
verilator.txt
|
||||
verilator_bin*
|
||||
|
||||
@@ -3,7 +3,310 @@ Revision history for Verilator
|
||||
The contributors that suggested a given feature are shown in []. [by ...]
|
||||
indicates the contributor was also the author of the fix; Thanks!
|
||||
|
||||
* Verilator 3.822 2011/10/20
|
||||
* Verilator 3.848 2013-06-02
|
||||
|
||||
** Support interfaces and modports, bug102. [Byron Bradley, Jeremy Bennett]
|
||||
|
||||
*** Duplicate clock gate optimization on by default, bug621.
|
||||
|
||||
**** Fix arrayed input compile error, bug645. [Krzysztof Jankowski]
|
||||
|
||||
**** Fix GCC version runtime changes, bug651. [Jeremy Bennett]
|
||||
|
||||
**** Fix packed array select internal error, bug652. [Krzysztof Jankowski]
|
||||
|
||||
|
||||
* Verilator 3.847 2013-05-11
|
||||
|
||||
*** Add ALWCOMBORDER warning. [KC Buckenmaier]
|
||||
|
||||
*** Add --pins-sc-uint and --pins-sc-biguint, bug638. [Alex Hornung]
|
||||
|
||||
**** Support "signal[vec]++".
|
||||
|
||||
**** Fix simulation error when inputs and MULTIDRIVEN, bug634. [Ted Campbell]
|
||||
|
||||
**** Fix module resolution with __, bug631. [Jason McMullan]
|
||||
|
||||
**** Fix packed array non-zero right index select crash, bug642. [Krzysztof Jankowski]
|
||||
|
||||
**** Fix nested union crash, bug643. [Krzysztof Jankowski]
|
||||
|
||||
|
||||
* Verilator 3.846 2013-03-09
|
||||
|
||||
** IEEE 1800-2012 is now the default language. This adds 4 new keywords
|
||||
and updates the svdpi.h and vpi_user.h header files.
|
||||
|
||||
*** Add --report-unoptflat, bug611. [Jeremy Bennett]
|
||||
|
||||
*** Add duplicate clock gate optimization, msg980. [Varun Koyyalagunta]
|
||||
Disabled unless -OD or -O3 used, please try it as may get some
|
||||
significant speedups.
|
||||
|
||||
*** Fix wrong dot resolution under inlining. [Art Stamness]
|
||||
|
||||
**** Support pattern assignment features, bug616, bug617, bug618. [Ed Lander]
|
||||
|
||||
**** Support bind in $unit, bug602. [Ed Lander]
|
||||
|
||||
**** Support <number>'() sized casts, bug628. [Ed Lander]
|
||||
|
||||
**** Fix DETECTARRAY on packed structures, bug610. [Jeremy Bennett]
|
||||
|
||||
**** Fix LITENDIAN on unpacked structures, bug614. [Wai Sum Mong]
|
||||
|
||||
**** Fix 32-bit OS VPI scan issue, bug615. [Jeremy Bennett, Rich Porter]
|
||||
|
||||
**** Fix opening a VerilatedVcdC file multiple times, msg1021. [Frederic Requin]
|
||||
|
||||
**** Fix UNOPTFLAT circular array bounds crossing, bug630. [Jie Xu]
|
||||
|
||||
|
||||
* Verilator 3.845 2013/02/04
|
||||
|
||||
*** Fix nested packed arrays and struct, bug600. [Jeremy Bennett]
|
||||
Packed arrays are now represented as a single linear vector in
|
||||
Verilated models. This may affect packed arrays that are public or
|
||||
accessed via the VPI.
|
||||
|
||||
*** Support wires with data types, bug608. [Ed Lander]
|
||||
|
||||
*** Support bind, to module names only, bug602. [Ed Lander]
|
||||
|
||||
*** Support VPI product info, warning calls, etc, bug588. [Rick Porter]
|
||||
|
||||
*** Support $left, $right and related functions, bug448. [Iztok Jeras]
|
||||
|
||||
*** Support inside expressions.
|
||||
|
||||
*** Define SYSTEMVERILOG, SV_COV_START and other IEEE mandated predefines.
|
||||
|
||||
**** Fix pin width mismatch error, bug595. [Alex Solomatnikov]
|
||||
|
||||
**** Fix implicit one bit parameter selection, bug603. [Jeremy Bennett]
|
||||
|
||||
**** Fix signed/unsigned parameter misconversion, bug606. [Jeremy Bennett]
|
||||
|
||||
**** Fix segfault on multidimensional dotted arrays, bug607. [Jie Xu]
|
||||
|
||||
**** Fix per-bit array output connection error, bug414. [Jan Egil Ruud]
|
||||
|
||||
**** Fix package logic var compile error.
|
||||
|
||||
**** Fix enums with X values.
|
||||
|
||||
|
||||
* Verilator 3.844 2013/01/09
|
||||
|
||||
*** Support "unsigned int" DPI import functions, msg966. [Alex Lee]
|
||||
|
||||
*** Fix package resolution of parameters, bug586. [Jeremy Bennett]
|
||||
|
||||
**** Fix non-integer vpi_get_value, bug587. [Rich Porter]
|
||||
|
||||
**** Fix task inlining under $display and case, bug589, bug598. [Holger Waechtler]
|
||||
|
||||
**** Fix package import of non-localparam parameter, bug474, bug591. [Jeremy Bennett]
|
||||
|
||||
**** Fix package import of package imports, partial bug592. [Jeremy Bennett]
|
||||
|
||||
**** Fix package import preventing local var, bug599. [Jeremy Bennett]
|
||||
|
||||
**** Fix array extraction of implicit vars, bug601. [Joe Eiler]
|
||||
|
||||
|
||||
* Verilator 3.843 2012/12/01
|
||||
|
||||
*** Add +1364-1995ext and similar language options, bug532. [Jeremy Bennett]
|
||||
|
||||
**** Fix mis-optimized identical submodule subtract, bug581. [Charlie Brej]
|
||||
|
||||
**** Fix crash on dotted references into dead modules, bug583. [Jeremy Bennett]
|
||||
|
||||
**** Fix compile issues on MSVCC, bug571, bug577. [Amir Gonnen]
|
||||
|
||||
**** Fix --debug overriding preceding --dump-treei, bug580. [Jeremy Bennett]
|
||||
|
||||
|
||||
* Verilator 3.842 2012/11/03
|
||||
|
||||
**** Add -x-initial-edge, bug570. [Jeremy Bennett]
|
||||
|
||||
**** Fix parameter pins interspersed with cells broke in 3.840. [Bernard Deadman]
|
||||
|
||||
**** Fix large shift error on large shift constants. [David Welch]
|
||||
|
||||
**** Fix $display mangling on GCC 4.7 and speed up, msg927, bug373, bug574. [R Diez]
|
||||
|
||||
**** Fix array of struct references giving false error, bug566. [Julius Baxter]
|
||||
|
||||
**** Fix missing var access functions when no DPI, bug572. [Amir Gonnen]
|
||||
|
||||
**** Fix name collision on unnamed blocks, bug567. [Chandan Egbert]
|
||||
|
||||
**** Fix name collision on task inputs, bug569. [Chandan Egbert]
|
||||
|
||||
|
||||
* Verilator 3.841 2012/09/03
|
||||
|
||||
*** Add --savable to support model save/restore. [Jeremy Bennett]
|
||||
|
||||
*** Support '{} assignment pattern on structures, part of bug355.
|
||||
|
||||
**** Fix double-deep parameter cell WIDTHs, bug541. [Hiroki Honda]
|
||||
|
||||
**** Fix imports under multiple instantiated cells, bug542. [Alex Solomatnikov]
|
||||
|
||||
**** Fix defparam in generate broke in 3.840, bug543. [Alex Solomatnikov]
|
||||
|
||||
**** Fix duplicate begin error broke in 3.840, bug548. [Alex Solomatnikov]
|
||||
|
||||
**** Fix triangle symbol resolution error broke in 3.840, bug550. [Ted Campbell]
|
||||
|
||||
|
||||
* Verilator 3.840 2012/07/31 Beta
|
||||
|
||||
** Rewrote tristate handling; supports tri0, tri1, tristate bit selects,
|
||||
concatenates and pullup/pulldowns, bug395, bug56, bug54, bug51.
|
||||
[Alex Solomatnikov, Lane Brooks, et al]
|
||||
|
||||
** Support packed structures and unions, bug181.
|
||||
Note this was a major internal change that may lead to some instability.
|
||||
|
||||
*** Support tri0 and tri1, bug462. [Alex Solomatnikov]
|
||||
|
||||
*** Support nmos and pmos, bug488. [Alex Solomatnikov]
|
||||
|
||||
*** Add INITIALDLY warning on initial assignments, bug478. [Alex Solomatnikov]
|
||||
|
||||
*** Add PINMISSING and PINNOCONNECT lint checks.
|
||||
|
||||
*** Add --converge-limit option.
|
||||
|
||||
*** Fix generate operators not short circuiting, bug413. [by Jeremy Bennett]
|
||||
|
||||
*** Fix parameters not supported in constant functions, bug474. [Alex Solomatnikov]
|
||||
|
||||
**** Fix duplicate warnings/errors, bug516. [Alex Solomatnikov]
|
||||
|
||||
**** Fix signed extending biops with WIDTH warning off, bug511. [Junji Hashimoto]
|
||||
|
||||
**** Fix ITOD internal error on real conversions, bug491. [Alex Solomatnikov]
|
||||
|
||||
**** Fix input and real loosing real data type, bug501. [Alex Solomatnikov]
|
||||
|
||||
**** Fix imports causing symbol table error, bug490. [Alex Solomatnikov]
|
||||
|
||||
**** Fix newlines in radix values, bug507. [Walter Lavino]
|
||||
|
||||
**** Fix loop error message to report line, bug513. [Jeremy Bennett]
|
||||
|
||||
**** Fix false UNUSED warning on file system calls.
|
||||
|
||||
**** Fix GCC 4.7.0 compile warnings, bug530. [Jeremy Bennett]
|
||||
|
||||
**** Fix svdpi.h compile error on Apple OS.
|
||||
|
||||
**** Fix compile error under git submodules, bug534. [Aurelien Francillon]
|
||||
|
||||
|
||||
* Verilator 3.833 2012/04/15
|
||||
|
||||
*** Support += and -= in standard for loops, bug463. [Alex Solomatnikov]
|
||||
|
||||
*** Fix processing unused parametrized modules, bug469, bug470. [Alex Solomatnikov]
|
||||
|
||||
**** Add SELRANGE as warning instead of error, bug477. [Alex Solomatnikov]
|
||||
|
||||
**** Add readme.pdf and internal.pdf and doxygen, bug483. [by Jeremy Bennett]
|
||||
|
||||
**** Fix change detections on arrays, bug364. [John Stevenson, Alex Solomatnikov]
|
||||
|
||||
**** Fix signed array warning, bug456. [Alex Solomatnikov]
|
||||
|
||||
**** Fix genvar and begin under generate, bug461. [Alex Solomatnikov]
|
||||
|
||||
**** Fix real constant parameter functions, bug475. [Alex Solomatnikov]
|
||||
|
||||
**** Fix and document --gdb option, bug454. [Jeremy Bennett]
|
||||
|
||||
**** Fix OpenSolaris compile error. [Sanjay Singh]
|
||||
|
||||
|
||||
* Verilator 3.832 2012/03/07
|
||||
|
||||
*** Fix memory delayed assignments from multiple clock domains. [Andrew Ling]
|
||||
|
||||
*** Support arrayed SystemC I/O pins. [Christophe Joly]
|
||||
|
||||
*** Report MULTIDRIVEN on memories set in multiple clock domains.
|
||||
|
||||
*** Report ENDLABEL on mismatching end labels, bug450. [Iztok Jeras]
|
||||
|
||||
**** Fix expansion of back-slashed escaped macros, bug441. [Alberto Del Rio]
|
||||
|
||||
**** Fix inheriting real and signed type across untyped parameters.
|
||||
|
||||
**** Fix core dump with over 100 deep UNOPTFLAT, bug432. [Joe Eiler]
|
||||
|
||||
**** Fix false command not found warning in makefiles. [Ruben Diez]
|
||||
|
||||
**** Fix hang when functions inside begin block. [David Welch]
|
||||
|
||||
**** Fix hang on recursive substitution `defines, bug443. [Alex Solomatnikov]
|
||||
|
||||
|
||||
* Verilator 3.831 2012/01/20
|
||||
|
||||
** Support SystemC 2.3.0 prerelease. This requires setting the new
|
||||
SYSTEMC_INCLUDE and SYSTEMC_LIBDIR variables in place of now
|
||||
deprecated SYSTEMC and SYSTEMC_ARCH. [Iztok Jeras]
|
||||
|
||||
**** Suppress VARHIDDEN on dpi import arguments. [Ruben Diez]
|
||||
|
||||
**** Support "generate for (genvar i=0; ...". [David Kravitz]
|
||||
|
||||
**** Fix dpi exports with > 32 bit but < 64 bit args, bug423. [Chandan Egbert]
|
||||
|
||||
**** Fix array of instantiations with sub-range output, bug414. [Jeremy Bennett]
|
||||
|
||||
**** Fix BLKSEQ warnings on variables declared inside always. [Ruben Diez]
|
||||
|
||||
|
||||
* Verilator 3.830 2011/11/27
|
||||
|
||||
** With "--language VAMS" support a touch of Verilog AMS. [Holger Waechtler]
|
||||
|
||||
*** Add sc_bv attribute to force bit vectors, bug402. [by Stefan Wallentowitz]
|
||||
|
||||
**** Search for user -y paths before default current directory. [Ruben Diez]
|
||||
|
||||
**** Support constants in sensitivity lists, bug412. [Jeremy Bennett]
|
||||
|
||||
**** Support $system. [Ruben Diez]
|
||||
|
||||
**** Support $sscanf with %g. [Holger Waechtler]
|
||||
|
||||
**** Indicate 'exiting due to errors' if errors, not warnings. [Ruben Diez]
|
||||
|
||||
**** Fix bad result with if-else-return optimization, bug420. [Alex Solomatnikov]
|
||||
|
||||
**** Fix reporting not found modules if generate-off, bug403. [Jeremy Bennett]
|
||||
|
||||
**** Fix $display with %d following %g. [Holger Waechtler]
|
||||
|
||||
|
||||
* Verilator 3.824 2011/10/25
|
||||
|
||||
*** Fix "always @ (* )", bug403, bug404. [Walter Lavino]
|
||||
|
||||
*** Add ASSIGNIN as suppressable error. [Jeremy Bennett]
|
||||
|
||||
**** Fix 3.823 constructor core dump on Debian, bug401. [Ahmed El-Mahmoudy]
|
||||
|
||||
|
||||
* Verilator 3.823 2011/10/20
|
||||
|
||||
*** Support $ceil, $floor, etc. [Alex Solomatnikov]
|
||||
|
||||
@@ -1942,7 +2245,7 @@ of input ports exists for tracing.
|
||||
|
||||
This uses outline mode in Emacs. See C-h m [M-x describe-mode].
|
||||
|
||||
Copyright 2001-2011 by Wilson Snyder. This program is free software; you
|
||||
Copyright 2001-2013 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.
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
src/Makefile$
|
||||
src/Makefile_obj$
|
||||
include/verilated.mk$
|
||||
test_regress/.gdbinit$
|
||||
config.cache$
|
||||
config.status$
|
||||
verilator.log
|
||||
@@ -34,3 +35,6 @@ nodist/
|
||||
/simv.daidir/
|
||||
/vc_hdrs.h$
|
||||
/csrc/
|
||||
doxygen-doc/.*
|
||||
TAGS
|
||||
.*~
|
||||
|
||||
+50
-19
@@ -9,7 +9,7 @@
|
||||
#
|
||||
#*****************************************************************************
|
||||
#
|
||||
# Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
# Copyright 2003-2013 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,11 +54,13 @@ srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
HOST = @HOST@
|
||||
|
||||
DOXYGEN = doxygen
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
MAKEINFO = makeinfo
|
||||
POD2TEXT = pod2text
|
||||
POD2LATEXFIX = $(srcdir)/src/pod2latexfix
|
||||
PERL = @PERL@
|
||||
|
||||
# Destination prefix for RPMs
|
||||
@@ -100,7 +102,8 @@ SHELL = /bin/sh
|
||||
|
||||
SUBDIRS = src test_verilated test_c test_sc test_sp test_regress test_vcs
|
||||
|
||||
INFOS = README internals.txt verilator.txt verilator.html verilator.1 verilator.pdf
|
||||
INFOS = README README.html README.pdf internals.txt internals.html \
|
||||
internals.pdf verilator.txt verilator.html verilator.1 verilator.pdf
|
||||
|
||||
# Files that can be generated, but should be up to date for a distribution.
|
||||
DISTDEP = info Makefile
|
||||
@@ -110,6 +113,7 @@ DISTFILES_INC = $(INFOS) .gitignore Artistic COPYING COPYING.LESSER \
|
||||
Changes TODO \
|
||||
MANIFEST.SKIP \
|
||||
bin/* \
|
||||
doxygen-mainpage doxygen.config veripool-logo.png \
|
||||
install-sh configure mkinstalldirs *.pod \
|
||||
include/*.[chv]* \
|
||||
include/*.in \
|
||||
@@ -117,11 +121,13 @@ DISTFILES_INC = $(INFOS) .gitignore Artistic COPYING COPYING.LESSER \
|
||||
include/vltstd/*.[chv]* \
|
||||
.*attributes */.*attributes */*/.*attributes \
|
||||
src/.*ignore src/*.in src/*.cpp src/*.[chly] src/astgen src/bisonpre src/*fix \
|
||||
src/.gdbinit \
|
||||
src/*.pl src/*.pod \
|
||||
test_*/.*ignore test_*/Makefile* test_*/*.cpp \
|
||||
test_*/*.pl test_*/*.v test_*/*.vc test_*/*.vh \
|
||||
test_verilated/vgen*.pl \
|
||||
test_regress/t/tsub/*.v* \
|
||||
test_regress/t/t*/*.sv* \
|
||||
test_regress/t/t*/*.v* \
|
||||
test_regress/t/*.cpp \
|
||||
test_regress/t/*.h \
|
||||
test_regress/t/*.dat \
|
||||
@@ -164,7 +170,7 @@ verilator_exe verilator_bin verilator_bin_dbg:
|
||||
(cd src && $(MAKE) $(OBJCACHE_JOBS) )
|
||||
|
||||
.PHONY:msg_test
|
||||
msg_test:
|
||||
msg_test: all_nomsg
|
||||
@echo "Build complete!"
|
||||
@echo
|
||||
@echo "Type 'make test' to test."
|
||||
@@ -215,15 +221,7 @@ verilator.html: ${srcdir}/bin/verilator
|
||||
# PDF needs DIST variables; but having configure.ac as dependency isn't detected
|
||||
verilator.pdf: ${srcdir}/bin/verilator Makefile
|
||||
pod2latex --full --out verilator.tex ${srcdir}/bin/verilator
|
||||
cat < verilator.tex \
|
||||
| sed 's/\\begin{document}/\\usepackage[left=1.7in,right=1.7in,top=1.3in,bottom=1.3in]{geometry}\n\\begin{document}/' \
|
||||
| sed 's/\\begin{document}/\\usepackage[pdftex,bookmarks=true,bookmarksnumbered=true,hypertexnames=false,breaklinks=true,linkbordercolor={0 0 1}]{hyperref}\n\\begin{document}/' \
|
||||
| sed 's/\\begin{document}/\\usepackage{fancyhdr} \\pagestyle{fancy}\n\\begin{document}/' \
|
||||
| sed 's/\\begin{document}/\\setlength{\\parindent}{0pt} \\setlength{\\parskip}{\\baselineskip}\n\\begin{document}/' \
|
||||
| sed 's/\\begin{document}/\\title{$(DISTTITLE)} \\date{${DISTDATE}} \\author{Wilson Snyder\\\\ http:\/\/www.veripool.org}\n\\begin{document}/' \
|
||||
| sed 's/\\begin{document}/\\lhead[$(DISTTITLE)]{$(DISTTITLE)}\n\\begin{document}/' \
|
||||
| sed 's/\\tableofcontents/\\begin{titlepage} \\maketitle \\end{titlepage}\n\\tableofcontents/' \
|
||||
> verilator2.tex
|
||||
$(PERL) $(POD2LATEXFIX) "$(DISTTITLE)" "${DISTDATE}" < verilator.tex > verilator2.tex
|
||||
mv verilator2.tex verilator.tex
|
||||
pdflatex verilator.tex
|
||||
pdflatex verilator.tex
|
||||
@@ -233,10 +231,34 @@ README: readme.pod
|
||||
-rm -f $@
|
||||
$(POD2TEXT) --loose $< > $@
|
||||
|
||||
README.html: readme.pod
|
||||
pod2html $< >$@
|
||||
|
||||
# PDF needs DIST variables; but having configure.ac as dependency isn't detected
|
||||
README.pdf: readme.pod Makefile
|
||||
pod2latex --full --out README.tex readme.pod
|
||||
$(PERL) $(POD2LATEXFIX) "$(DISTTITLE) README File" "${DISTDATE}" < README.tex > README2.tex
|
||||
mv README2.tex README.tex
|
||||
pdflatex README.tex
|
||||
pdflatex README.tex
|
||||
-rm -f README.toc README.aux README.idx README.out
|
||||
|
||||
internals.txt: internals.pod
|
||||
-rm -f $@
|
||||
$(POD2TEXT) --loose $< > $@
|
||||
|
||||
internals.html: internals.pod
|
||||
pod2html $< >$@
|
||||
|
||||
# PDF needs DIST variables; but having configure.ac as dependency isn't detected
|
||||
internals.pdf: internals.pod Makefile
|
||||
pod2latex --full --out internals.tex internals.pod
|
||||
$(PERL) $(POD2LATEXFIX) "$(DISTTITLE) Internals Manual" "${DISTDATE}" < internals.tex > internals2.tex
|
||||
mv internals2.tex internals.tex
|
||||
pdflatex internals.tex
|
||||
pdflatex internals.tex
|
||||
-rm -f internals.toc internals.aux internals.idx internals.out
|
||||
|
||||
# See uninstall also - don't put wildcards in this variable, it might uninstall other stuff
|
||||
VL_INST_BIN_FILES = verilator verilator_bin verilator_bin_dbg \
|
||||
verilator_includer verilator_profcfunc
|
||||
@@ -313,7 +335,8 @@ uninstall:
|
||||
-rmdir $(DESTDIR)$(pkgdatadir)/examples
|
||||
-rmdir $(DESTDIR)$(pkgdatadir)
|
||||
|
||||
install: all_nomsg installbin installman installdata install-msg
|
||||
install: all_nomsg install-all
|
||||
install-all: installbin installman installdata install-msg
|
||||
|
||||
install-here: installman ftp
|
||||
|
||||
@@ -376,14 +399,17 @@ endif
|
||||
# VERILATOR_AUTHOR_SITE
|
||||
endif
|
||||
|
||||
# Use --xml flag to see the cppcheck code to use for suppression
|
||||
CPPCHECK = cppcheck
|
||||
CPPCHECK_FLAGS = --enable=all --inline-suppr --suppress=unusedScopedObject
|
||||
CPPCHECK_FLAGS = --enable=all --inline-suppr --suppress=unusedScopedObject --suppress=cstyleCast
|
||||
CPPCHECK_FLAGS += --xml
|
||||
CPPCHECK_CPP = $(wildcard $(srcdir)/include/*.cpp $(srcdir)/src/*.cpp)
|
||||
CPPCHECK_DEP = $(subst .cpp,.cppcheck,$(CPPCHECK_CPP))
|
||||
CPPCHECK_INC = -I$(srcdir)/include -I$(srcdir)/src/obj_dbg -I$(srcdir)/src
|
||||
|
||||
cppcheck: $(CPPCHECK_DEP)
|
||||
%.cppcheck: %.cpp
|
||||
$(CPPCHECK) $(CPPCHECK_FLAGS) -DVL_DEBUG=1 -I$(srcdir)/include -I$(srcdir)/src $<
|
||||
$(CPPCHECK) $(CPPCHECK_FLAGS) -DVL_DEBUG=1 $(CPPCHECK_INC) $<
|
||||
|
||||
ftp: info
|
||||
|
||||
@@ -433,14 +459,19 @@ clean mostlyclean distclean maintainer-clean::
|
||||
|
||||
distclean maintainer-clean::
|
||||
rm -f Makefile config.status config.cache config.log verilator_bin* TAGS
|
||||
rm -f include/verilated.mk
|
||||
rm -f include/verilated.mk include/verilated_config.h
|
||||
|
||||
TAGFILES=${srcdir}/*/*.cpp ${srcdir}/*/*.h ${srcdir}/*/[a-z]*.in \
|
||||
${srcdir}/[a-z]*.in ${srcdir}/*.pod
|
||||
TAGFILES=${srcdir}/*/*.cpp ${srcdir}/*/*.h ${srcdir}/*/*.in \
|
||||
${srcdir}/*.in ${srcdir}/*.pod
|
||||
|
||||
TAGS: $(TAGFILES)
|
||||
etags $(TAGFILES)
|
||||
|
||||
.PHONY: doxygen
|
||||
|
||||
doxygen:
|
||||
$(DOXYGEN) doxygen.config
|
||||
|
||||
######################################################################
|
||||
# Test targets
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// DESCRIPTION: Verilator: List of To Do issues.
|
||||
//
|
||||
// Copyright 2004-2011 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2004-2013 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.
|
||||
@@ -62,7 +62,7 @@ Usability:
|
||||
* Print version/etc message at runtime. (4.000?)
|
||||
Include number of lines of code, percent comments, code complexity measurement
|
||||
<-80chars------------------------------------------------------------------->
|
||||
Verilator 3.600 - fast, free, open-sourced. Copyright 2001-2011.
|
||||
Verilator 3.600 - fast, free, open-sourced. Copyright 2001-2013.
|
||||
Verilated #### modules, #### instances, ##### sigs,
|
||||
#### non-comment lines, ##### ops, ### KB model size
|
||||
* Default the --l2name to remove extra "v" level of hierarchy (flag to make "top")
|
||||
|
||||
+633
-180
File diff suppressed because it is too large
Load Diff
+64
-6
@@ -14,6 +14,19 @@ use vars qw ($Debug);
|
||||
|
||||
#======================================================================
|
||||
|
||||
# Old version 1 dump nodes with no dtypep's
|
||||
our %Ver1_Non_Dtyped = map {$_ => 1} qw(
|
||||
ACTIVE ALWAYS ALWAYSPOST ALWAYSPUBLIC ATTROF BEGIN BREAK CASE CASEITEM
|
||||
CCALL CELL CELLINLINE CFILE CFUNC CHANGEDET CLOCKING COMMENT CONTINUE
|
||||
COVERDECL COVERINC COVERTOGGLE CRETURN CSTMT DEFPARAM DISABLE DISPLAY DOT
|
||||
DPIEXPORT FCLOSE FFLUSH FINAL FINISH FOPEN GENCASE GENERATE GENFOR GENIF
|
||||
IF IMPLICIT INITARRAY INITIAL JUMPGO JUMPLABEL MODULE NETLIST
|
||||
NOTFOUNDMODULE PACKAGE PACKAGEIMPORT PARSEREF PIN PORT PRAGMA PRIMITIVE
|
||||
PSLASSERT PSLCOVER PSLDEFCLOCK PULL RANGE READMEM REPEAT RETURN SCCTOR
|
||||
SCDTOR SCHDR SCIMP SCIMPHDR SCINT SCOPE SELBIT SELEXTRACT SELMINUS
|
||||
SELPLUS SENGATE SENITEM SENTREE SFORMAT SFORMATF STOP SYSIGNORE SYSTEMT
|
||||
TASK TASKREF TEXT TOPSCOPE TYPEDEFFWD TYPETABLE UCSTMT UDPTABLE
|
||||
UDPTABLELINE UNTILSTABLE VASSERT WHILE );
|
||||
|
||||
#======================================================================
|
||||
# main
|
||||
@@ -79,27 +92,72 @@ sub diff_file {
|
||||
my $a = shift;
|
||||
my $b = shift;
|
||||
# Compare the two tree files
|
||||
my $tmp_a = "/tmp/$$.a";
|
||||
my $tmp_b = "/tmp/$$.b";
|
||||
(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";
|
||||
|
||||
filter ($a, $tmp_a);
|
||||
filter ($b, $tmp_b);
|
||||
my $vera = version_from($a);
|
||||
my $verb = version_from($b);
|
||||
my $verCvt = (($vera < 0x3900 && $verb >= 0x3900)
|
||||
|| ($vera >= 0x3900 && $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;
|
||||
}
|
||||
|
||||
sub version_from {
|
||||
my $fn = shift;
|
||||
# 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;
|
||||
}
|
||||
|
||||
sub filter {
|
||||
my $fn1 = shift;
|
||||
my $fn2 = shift;
|
||||
my $verCvt = shift;
|
||||
# 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/;
|
||||
$line =~ s!\@dt=0x\(G?/?([^)]+)\)!$1!g; # NEW: @dt -> OLD: non @dt format
|
||||
# # Below Ver1_Non_Dtyped may replace above further
|
||||
if ($line =~ /: ([A-Z]+) /) {
|
||||
my $type = $1;
|
||||
next if $type =~ 'DTYPE';
|
||||
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;
|
||||
}
|
||||
if ($Ver1_Non_Dtyped{$type}) {
|
||||
$line =~ s! w[0-9]+!!g;
|
||||
}
|
||||
}
|
||||
$line =~ s!\@dt=0$!NoW!g; # NEW: dt=null -> common format
|
||||
$line =~ s!\@dt=0 !NoW !g; # NEW: dt=null -> common format
|
||||
$line =~ s! s?w0$! NoW!g; # OLD: no width -> common format
|
||||
$line =~ s! s?w0 ! NoW !g; # OLD: no width -> common format
|
||||
}
|
||||
print $f2 $line;
|
||||
}
|
||||
$f1->close;
|
||||
@@ -177,7 +235,7 @@ Do not show differences in line numbering.
|
||||
|
||||
The latest version is available from L<http://www.veripool.org/verilator>.
|
||||
|
||||
Copyright 2005-2011 by Wilson Snyder. This package is free software; you can
|
||||
Copyright 2005-2013 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.
|
||||
|
||||
@@ -193,5 +251,5 @@ C<verilator>
|
||||
|
||||
######################################################################
|
||||
### Local Variables:
|
||||
### compile-command: "$V4/bin/verilator_difftree $V4/test_c/obj_dir/V*_03_*.tree $V4N/test_c/obj_dir/V*_03_*.tree"
|
||||
### compile-command: "$V4/bin/verilator_difftree {$V4D,$V4}/test_regress/obj_dir/t_EXAMPLE/V*_03_*.tree"
|
||||
### End:
|
||||
|
||||
@@ -3,7 +3,7 @@ eval 'exec perl -wS $0 ${1+"$@"}'
|
||||
if 0;
|
||||
# DESCRIPTION: Print include statements for each ARGV
|
||||
#
|
||||
# Copyright 2003-2011 by Wilson Snyder. This package is free software; you can
|
||||
# Copyright 2003-2013 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.
|
||||
######################################################################
|
||||
|
||||
@@ -208,7 +208,7 @@ Displays this message and program version and exits.
|
||||
|
||||
The latest version is available from L<http://www.veripool.org/>.
|
||||
|
||||
Copyright 2007-2011 by Wilson Snyder. Verilator is free software; you can
|
||||
Copyright 2007-2013 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.
|
||||
|
||||
|
||||
+6
-3
@@ -1,12 +1,14 @@
|
||||
# DESCRIPTION: Process this file with autoconf to produce a configure script.
|
||||
#
|
||||
# Copyright 2003-2011 by Wilson Snyder. Verilator is free software; you can
|
||||
# Copyright 2003-2013 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.
|
||||
|
||||
AC_INIT([Verilator],[3.823 2011/10/20])
|
||||
#AC_INIT([Verilator],[#.### YYYY-MM-DD])
|
||||
#AC_INIT([Verilator],[#.### devel])
|
||||
AC_INIT([Verilator],[3.848 2013-06-02])
|
||||
AC_CONFIG_HEADER(src/config_build.h)
|
||||
AC_CONFIG_FILES(Makefile src/Makefile src/Makefile_obj include/verilated.mk)
|
||||
AC_CONFIG_FILES(Makefile src/Makefile src/Makefile_obj include/verilated.mk include/verilated_config.h)
|
||||
|
||||
AC_MSG_RESULT([configuring for $PACKAGE_STRING])
|
||||
|
||||
@@ -128,6 +130,7 @@ _MY_CXX_CHECK_OPT(-Wno-sign-compare)
|
||||
_MY_CXX_CHECK_OPT(-Wno-uninitialized)
|
||||
_MY_CXX_CHECK_OPT(-Wno-unused-parameter)
|
||||
_MY_CXX_CHECK_OPT(-Wno-unused-variable)
|
||||
_MY_CXX_CHECK_OPT(-Wno-unused-but-set-variable)
|
||||
AC_SUBST(CFG_CXXFLAGS_NO_UNUSED)
|
||||
|
||||
# Checks for library functions.
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
/*! \mainpage Verilator Doxygen Documentation
|
||||
*
|
||||
* \section intro_sec Introduction
|
||||
*
|
||||
* This is a full doxygen analysis of the Verilator source tree.
|
||||
*/
|
||||
+1772
File diff suppressed because it is too large
Load Diff
@@ -1 +1,2 @@
|
||||
verilated.mk
|
||||
verilated_config.h
|
||||
|
||||
+69
-20
@@ -1,7 +1,7 @@
|
||||
// -*- C++ -*-
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2013 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,23 +27,20 @@
|
||||
#include "verilated_imp.h"
|
||||
#include <cctype>
|
||||
|
||||
#define VL_VALUE_STRING_MAX_WIDTH 1024 ///< Max static char array for VL_VALUE_STRING
|
||||
#define VL_VALUE_STRING_MAX_WIDTH 8192 ///< Max static char array for VL_VALUE_STRING
|
||||
|
||||
//===========================================================================
|
||||
// Global variables
|
||||
|
||||
// Slow path variables
|
||||
int Verilated::s_randReset = 0;
|
||||
VerilatedVoidCb Verilated::s_flushCb = NULL;
|
||||
|
||||
// Keep below together in one cache line
|
||||
int Verilated::s_debug = 0;
|
||||
bool Verilated::s_calcUnusedSigs = false;
|
||||
bool Verilated::s_gotFinish = false;
|
||||
bool Verilated::s_assertOn = true;
|
||||
Verilated::Serialized Verilated::s_s;
|
||||
VL_THREAD const VerilatedScope* Verilated::t_dpiScopep = NULL;
|
||||
VL_THREAD const char* Verilated::t_dpiFilename = "";
|
||||
VL_THREAD int Verilated::t_dpiLineno = 0;
|
||||
struct Verilated::CommandArgValues Verilated::s_args = {0, NULL};
|
||||
|
||||
VerilatedImp VerilatedImp::s_s;
|
||||
|
||||
@@ -81,6 +78,18 @@ void vl_fatal (const char* filename, int linenum, const char* hier, const char*
|
||||
}
|
||||
#endif
|
||||
|
||||
//===========================================================================
|
||||
// Overall class init
|
||||
|
||||
Verilated::Serialized::Serialized() {
|
||||
s_randReset = 0;
|
||||
s_debug = 0;
|
||||
s_calcUnusedSigs = false;
|
||||
s_gotFinish = false;
|
||||
s_assertOn = true;
|
||||
s_fatalOnVpiError = true; // retains old default behaviour
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
// Random reset -- Only called at init time, so don't inline.
|
||||
|
||||
@@ -301,7 +310,7 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
|
||||
const char *ep = pos;
|
||||
while (ep[0] && ep[0]!='%') ep++;
|
||||
if (ep != pos) {
|
||||
output += string(pos, ep-pos);
|
||||
output.append(pos, ep-pos);
|
||||
pos += ep-pos-1;
|
||||
}
|
||||
} else { // Format character
|
||||
@@ -333,7 +342,9 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
|
||||
case 'e':
|
||||
case 'f':
|
||||
case 'g': {
|
||||
const int lbits = va_arg(ap, int);
|
||||
double d = va_arg(ap, double);
|
||||
if (lbits) {} // UNUSED - always 64
|
||||
strncpy(tmpf, pctp, pos-pctp+1);
|
||||
tmpf[pos-pctp+1] = '\0';
|
||||
sprintf(tmp, tmpf, d);
|
||||
@@ -344,9 +355,9 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
|
||||
// Deal with all read-and-print somethings
|
||||
const int lbits = va_arg(ap, int);
|
||||
QData ld = 0;
|
||||
WData qlwp[2];
|
||||
WDataInP lwp;
|
||||
if (lbits <= VL_QUADSIZE) {
|
||||
WData qlwp[2];
|
||||
ld = _VL_VA_ARG_Q(ap, lbits);
|
||||
VL_SET_WQ(qlwp,ld);
|
||||
lwp = qlwp;
|
||||
@@ -592,17 +603,28 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
|
||||
_vl_vsss_read(fp,floc,fromp, tmp, "0123456789+-xXzZ?_");
|
||||
if (!tmp[0]) goto done;
|
||||
vlsint64_t ld;
|
||||
sscanf(tmp,"%" VL_PRI64 "d",&ld);
|
||||
sscanf(tmp,"%30" VL_PRI64 "d",&ld);
|
||||
VL_SET_WQ(owp,ld);
|
||||
break;
|
||||
}
|
||||
case 'f':
|
||||
case 'e':
|
||||
case 'g': { // Real number
|
||||
_vl_vsss_skipspace(fp,floc,fromp);
|
||||
_vl_vsss_read(fp,floc,fromp, tmp, "+-.0123456789eE");
|
||||
if (!tmp[0]) goto done;
|
||||
union { double r; vlsint64_t ld; } u;
|
||||
u.r = strtod(tmp, NULL);
|
||||
VL_SET_WQ(owp,u.ld);
|
||||
break;
|
||||
}
|
||||
case 't': // FALLTHRU // Time
|
||||
case 'u': { // Unsigned decimal
|
||||
_vl_vsss_skipspace(fp,floc,fromp);
|
||||
_vl_vsss_read(fp,floc,fromp, tmp, "0123456789+-xXzZ?_");
|
||||
if (!tmp[0]) goto done;
|
||||
QData ld;
|
||||
sscanf(tmp,"%" VL_PRI64 "u",&ld);
|
||||
sscanf(tmp,"%30" VL_PRI64 "u",&ld);
|
||||
VL_SET_WQ(owp,ld);
|
||||
break;
|
||||
}
|
||||
@@ -737,9 +759,10 @@ void VL_FCLOSE_I(IData fdi) {
|
||||
}
|
||||
|
||||
void VL_SFORMAT_X(int obits, void* destp, const char* formatp, ...) {
|
||||
VL_STATIC_OR_THREAD string output; // static only for speed
|
||||
output = "";
|
||||
va_list ap;
|
||||
va_start(ap,formatp);
|
||||
string output;
|
||||
_vl_vsformat(output, formatp, ap);
|
||||
va_end(ap);
|
||||
|
||||
@@ -747,9 +770,10 @@ void VL_SFORMAT_X(int obits, void* destp, const char* formatp, ...) {
|
||||
}
|
||||
|
||||
string VL_SFORMATF_NX(const char* formatp, ...) {
|
||||
VL_STATIC_OR_THREAD string output; // static only for speed
|
||||
output = "";
|
||||
va_list ap;
|
||||
va_start(ap,formatp);
|
||||
string output;
|
||||
_vl_vsformat(output, formatp, ap);
|
||||
va_end(ap);
|
||||
|
||||
@@ -757,9 +781,10 @@ string VL_SFORMATF_NX(const char* formatp, ...) {
|
||||
}
|
||||
|
||||
void VL_WRITEF(const char* formatp, ...) {
|
||||
VL_STATIC_OR_THREAD string output; // static only for speed
|
||||
output = "";
|
||||
va_list ap;
|
||||
va_start(ap,formatp);
|
||||
string output;
|
||||
_vl_vsformat(output, formatp, ap);
|
||||
va_end(ap);
|
||||
|
||||
@@ -768,12 +793,13 @@ void VL_WRITEF(const char* formatp, ...) {
|
||||
}
|
||||
|
||||
void VL_FWRITEF(IData fpi, const char* formatp, ...) {
|
||||
VL_STATIC_OR_THREAD string output; // static only for speed
|
||||
output = "";
|
||||
FILE* fp = VL_CVT_I_FP(fpi);
|
||||
if (VL_UNLIKELY(!fp)) return;
|
||||
|
||||
va_list ap;
|
||||
va_start(ap,formatp);
|
||||
string output;
|
||||
_vl_vsformat(output, formatp, ap);
|
||||
va_end(ap);
|
||||
|
||||
@@ -924,14 +950,25 @@ void VL_READMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords,
|
||||
}
|
||||
}
|
||||
|
||||
IData VL_SYSTEM_IQ(QData lhs) {
|
||||
IData lhsw[2]; VL_SET_WQ(lhsw, lhs);
|
||||
return VL_SYSTEM_IW(2, lhsw);
|
||||
}
|
||||
IData VL_SYSTEM_IW(int lhswords, WDataInP filenamep) {
|
||||
char filenamez[VL_TO_STRING_MAX_WORDS*VL_WORDSIZE+1];
|
||||
_VL_VINT_TO_STRING(lhswords*VL_WORDSIZE, filenamez, filenamep);
|
||||
int code = system(filenamez);
|
||||
return code >> 8; // Want exit status
|
||||
}
|
||||
|
||||
IData VL_TESTPLUSARGS_I(const char* formatp) {
|
||||
string match = VerilatedImp::argPlusMatch(formatp);
|
||||
const string& match = VerilatedImp::argPlusMatch(formatp);
|
||||
if (match == "") return 0;
|
||||
else return 1;
|
||||
}
|
||||
|
||||
IData VL_VALUEPLUSARGS_IW(int rbits, const char* prefixp, char fmt, WDataOutP rwp) {
|
||||
string match = VerilatedImp::argPlusMatch(prefixp);
|
||||
const string& match = VerilatedImp::argPlusMatch(prefixp);
|
||||
const char* dp = match.c_str() + 1 /*leading + */ + strlen(prefixp);
|
||||
if (match == "") return 0;
|
||||
VL_ZERO_RESET_W(rbits, rwp);
|
||||
@@ -940,7 +977,7 @@ IData VL_VALUEPLUSARGS_IW(int rbits, const char* prefixp, char fmt, WDataOutP rw
|
||||
break;
|
||||
case 'd':
|
||||
vlsint64_t ld;
|
||||
sscanf(dp,"%" VL_PRI64 "d",&ld);
|
||||
sscanf(dp,"%30" VL_PRI64 "d",&ld);
|
||||
VL_SET_WQ(rwp,ld);
|
||||
break;
|
||||
case 'b':
|
||||
@@ -967,7 +1004,7 @@ IData VL_VALUEPLUSARGS_IW(int rbits, const char* prefixp, char fmt, WDataOutP rw
|
||||
}
|
||||
|
||||
const char* vl_mc_scan_plusargs(const char* prefixp) {
|
||||
string match = VerilatedImp::argPlusMatch(prefixp);
|
||||
const string& match = VerilatedImp::argPlusMatch(prefixp);
|
||||
static VL_THREAD char outstr[VL_VALUE_STRING_MAX_WIDTH];
|
||||
if (match == "") return NULL;
|
||||
strncpy(outstr, match.c_str()+strlen(prefixp)+1, // +1 to skip the "+"
|
||||
@@ -1029,9 +1066,19 @@ void Verilated::flushCb(VerilatedVoidCb cb) {
|
||||
}
|
||||
|
||||
void Verilated::commandArgs(int argc, const char** argv) {
|
||||
s_args.argc = argc;
|
||||
s_args.argv = argv;
|
||||
VerilatedImp::commandArgs(argc,argv);
|
||||
}
|
||||
|
||||
const char* Verilated::commandArgsPlusMatch(const char* prefixp) {
|
||||
return VerilatedImp::argPlusMatch(prefixp).c_str();
|
||||
}
|
||||
|
||||
void Verilated::internalsDump() {
|
||||
VerilatedImp::internalsDump();
|
||||
}
|
||||
|
||||
void Verilated::scopesDump() {
|
||||
VerilatedImp::scopesDump();
|
||||
}
|
||||
@@ -1058,6 +1105,7 @@ VerilatedModule::~VerilatedModule() {
|
||||
//======================================================================
|
||||
// VerilatedVar:: Methods
|
||||
|
||||
// cppcheck-suppress unusedFunction // Used by applications
|
||||
vluint32_t VerilatedVar::entSize() const {
|
||||
vluint32_t size = 1;
|
||||
switch (vltype()) {
|
||||
@@ -1154,6 +1202,7 @@ void VerilatedScope::varInsert(int finalize, const char* namep, void* datap,
|
||||
m_varsp->insert(make_pair(namep,var));
|
||||
}
|
||||
|
||||
// cppcheck-suppress unusedFunction // Used by applications
|
||||
VerilatedVar* VerilatedScope::varFind(const char* namep) const {
|
||||
if (VL_LIKELY(m_varsp)) {
|
||||
VerilatedVarNameMap::iterator it = m_varsp->find(namep);
|
||||
|
||||
+80
-18
@@ -1,7 +1,7 @@
|
||||
// -*- C++ -*-
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2013 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,7 @@
|
||||
#ifndef _VERILATED_H_
|
||||
#define _VERILATED_H_ 1 ///< Header Guard
|
||||
|
||||
#include "verilated_config.h"
|
||||
#include "verilatedos.h"
|
||||
|
||||
#include <cassert>
|
||||
@@ -219,19 +220,31 @@ struct Verilated {
|
||||
// MEMBERS
|
||||
private:
|
||||
// Slow path variables
|
||||
static int s_randReset; ///< Random reset: 0=all 0s, 1=all 1s, 2=random
|
||||
static VerilatedVoidCb s_flushCb; ///< Flush callback function
|
||||
|
||||
// Fast path
|
||||
static int s_debug; ///< See accessors... only when VL_DEBUG set
|
||||
static bool s_calcUnusedSigs; ///< Waves file on, need all signals calculated
|
||||
static bool s_gotFinish; ///< A $finish statement executed
|
||||
static bool s_assertOn; ///< Assertions are enabled
|
||||
static struct Serialized { // All these members serialized/deserialized
|
||||
// Slow path
|
||||
int s_randReset; ///< Random reset: 0=all 0s, 1=all 1s, 2=random
|
||||
// Fast path
|
||||
int s_debug; ///< See accessors... only when VL_DEBUG set
|
||||
bool s_calcUnusedSigs; ///< Waves file on, need all signals calculated
|
||||
bool s_gotFinish; ///< A $finish statement executed
|
||||
bool s_assertOn; ///< Assertions are enabled
|
||||
bool s_fatalOnVpiError; ///< Stop on vpi error/unsupported
|
||||
Serialized();
|
||||
} s_s;
|
||||
|
||||
static VL_THREAD const VerilatedScope* t_dpiScopep; ///< DPI context scope
|
||||
static VL_THREAD const char* t_dpiFilename; ///< DPI context filename
|
||||
static VL_THREAD int t_dpiLineno; ///< DPI context line number
|
||||
|
||||
// no need to be save-restored (serialized) the
|
||||
// assumption is that the restore is allowed to pass different arguments
|
||||
static struct CommandArgValues {
|
||||
int argc;
|
||||
const char** argv;
|
||||
} s_args;
|
||||
|
||||
public:
|
||||
|
||||
// METHODS - User called
|
||||
@@ -241,29 +254,32 @@ public:
|
||||
/// 0 = Set to zeros
|
||||
/// 1 = Set all bits to one
|
||||
/// 2 = Randomize all bits
|
||||
static void randReset(int val) { s_randReset=val; }
|
||||
static int randReset() { return s_randReset; } ///< Return randReset value
|
||||
static void randReset(int val) { s_s.s_randReset=val; }
|
||||
static int randReset() { return s_s.s_randReset; } ///< Return randReset value
|
||||
|
||||
/// Enable debug of internal verilated code
|
||||
static inline void debug(int level) { s_debug = level; }
|
||||
static inline void debug(int level) { s_s.s_debug = level; }
|
||||
#ifdef VL_DEBUG
|
||||
static inline int debug() { return s_debug; } ///< Return debug value
|
||||
static inline int debug() { return s_s.s_debug; } ///< Return debug value
|
||||
#else
|
||||
static inline int debug() { return 0; } ///< Constant 0 debug, so C++'s optimizer rips up
|
||||
#endif
|
||||
/// Enable calculation of unused signals
|
||||
static void calcUnusedSigs(bool flag) { s_calcUnusedSigs=flag; }
|
||||
static bool calcUnusedSigs() { return s_calcUnusedSigs; } ///< Return calcUnusedSigs value
|
||||
static void calcUnusedSigs(bool flag) { s_s.s_calcUnusedSigs=flag; }
|
||||
static bool calcUnusedSigs() { return s_s.s_calcUnusedSigs; } ///< Return calcUnusedSigs value
|
||||
/// Did the simulation $finish?
|
||||
static void gotFinish(bool flag) { s_gotFinish=flag; }
|
||||
static bool gotFinish() { return s_gotFinish; } ///< Return if got a $finish
|
||||
static void gotFinish(bool flag) { s_s.s_gotFinish=flag; }
|
||||
static bool gotFinish() { return s_s.s_gotFinish; } ///< Return if got a $finish
|
||||
/// Allow traces to at some point be enabled (disables some optimizations)
|
||||
static void traceEverOn(bool flag) {
|
||||
if (flag) { calcUnusedSigs(flag); }
|
||||
}
|
||||
/// Enable/disable assertions
|
||||
static void assertOn(bool flag) { s_assertOn=flag; }
|
||||
static bool assertOn() { return s_assertOn; }
|
||||
static void assertOn(bool flag) { s_s.s_assertOn=flag; }
|
||||
static bool assertOn() { return s_s.s_assertOn; }
|
||||
/// Enable/disable vpi fatal
|
||||
static void fatalOnVpiError(bool flag) { s_s.s_fatalOnVpiError=flag; }
|
||||
static bool fatalOnVpiError() { return s_s.s_fatalOnVpiError; }
|
||||
/// Flush callback for VCD waves
|
||||
static void flushCb(VerilatedVoidCb cb);
|
||||
static void flushCall() { if (s_flushCb) (*s_flushCb)(); }
|
||||
@@ -271,6 +287,17 @@ public:
|
||||
/// Record command line arguments, for retrieval by $test$plusargs/$value$plusargs
|
||||
static void commandArgs(int argc, const char** argv);
|
||||
static void commandArgs(int argc, char** argv) { commandArgs(argc,(const char**)argv); }
|
||||
static CommandArgValues* getCommandArgs() {return &s_args;}
|
||||
static const char* commandArgsPlusMatch(const char* prefixp);
|
||||
|
||||
/// Produce name & version for (at least) VPI
|
||||
static const char* productName() { return VERILATOR_PRODUCT; }
|
||||
static const char* productVersion() { return VERILATOR_VERSION; }
|
||||
|
||||
/// For debugging, print much of the Verilator internal state.
|
||||
/// The output of this function may change in future
|
||||
/// releases - contact the authors before production use.
|
||||
static void internalsDump();
|
||||
|
||||
/// For debugging, print text list of all scope names with
|
||||
/// dpiImport/Export context. This function may change in future
|
||||
@@ -292,6 +319,8 @@ public:
|
||||
static const char* dpiFilenamep() { return t_dpiFilename; }
|
||||
static int dpiLineno() { return t_dpiLineno; }
|
||||
static int exportFuncNum(const char* namep);
|
||||
static size_t serializedSize() { return sizeof(s_s); }
|
||||
static void* serializedPtr() { return &s_s; }
|
||||
};
|
||||
|
||||
//=========================================================================
|
||||
@@ -349,6 +378,10 @@ extern IData VL_SSCANF_IWX(int lbits, WDataInP lwp, const char* formatp, ...);
|
||||
|
||||
extern void VL_SFORMAT_X(int obits, void* destp, const char* formatp, ...);
|
||||
|
||||
extern IData VL_SYSTEM_IW(int lhsnwords, WDataInP lhs);
|
||||
extern IData VL_SYSTEM_IQ(QData lhs);
|
||||
inline IData VL_SYSTEM_II(IData lhs) { return VL_SYSTEM_IQ(lhs); }
|
||||
|
||||
extern IData VL_TESTPLUSARGS_I(const char* formatp);
|
||||
extern IData VL_VALUEPLUSARGS_IW(int rbits, const char* prefixp, char fmt, WDataOutP rwp);
|
||||
extern const char* vl_mc_scan_plusargs(const char* prefixp); // PLIish
|
||||
@@ -519,6 +552,7 @@ static inline void VL_ASSIGNBIT_WO(int, int bit, WDataOutP owp, IData) {
|
||||
//===================================================================
|
||||
// SYSTEMC OPERATORS
|
||||
// Copying verilog format to systemc integers and bit vectors.
|
||||
// Get a SystemC variable
|
||||
|
||||
#define VL_ASSIGN_ISI(obits,vvar,svar) { (vvar) = VL_CLEAN_II((obits),(obits),(svar).read()); }
|
||||
#define VL_ASSIGN_QSQ(obits,vvar,svar) { (vvar) = VL_CLEAN_QQ((obits),(obits),(svar).read()); }
|
||||
@@ -536,7 +570,21 @@ static inline void VL_ASSIGNBIT_WO(int, int bit, WDataOutP owp, IData) {
|
||||
owp[words-1] &= VL_MASK_I(obits); \
|
||||
}
|
||||
|
||||
#define VL_ASSIGN_ISU(obits,vvar,svar) { (vvar) = VL_CLEAN_II((obits),(obits),(svar).read().to_uint()); }
|
||||
#define VL_ASSIGN_QSU(obits,vvar,svar) { (vvar) = VL_CLEAN_QQ((obits),(obits),(svar).read().to_uint64()); }
|
||||
#define VL_ASSIGN_WSB(obits,owp,svar) { \
|
||||
int words = VL_WORDS_I(obits); \
|
||||
sc_biguint<obits> _butemp = (svar).read(); \
|
||||
for (int i=0; i < words; i++) { \
|
||||
int msb = ((i+1)*VL_WORDSIZE) - 1; \
|
||||
msb = (msb >= obits) ? (obits-1) : msb; \
|
||||
owp[i] = _butemp.range(msb,i*VL_WORDSIZE).to_uint(); \
|
||||
} \
|
||||
owp[words-1] &= VL_MASK_I(obits); \
|
||||
}
|
||||
|
||||
// Copying verilog format from systemc integers and bit vectors.
|
||||
// Set a SystemC variable
|
||||
|
||||
#define VL_ASSIGN_SII(obits,svar,vvar) { (svar).write(vvar); }
|
||||
#define VL_ASSIGN_SQQ(obits,svar,vvar) { (svar).write(vvar); }
|
||||
@@ -558,6 +606,20 @@ static inline void VL_ASSIGNBIT_WO(int, int bit, WDataOutP owp, IData) {
|
||||
svar.write(_bvtemp); \
|
||||
}
|
||||
|
||||
#define VL_ASSIGN_SUI(obits,svar,rd) { (svar).write(rd); }
|
||||
#define VL_ASSIGN_SUQ(obits,svar,rd) { (svar).write(rd); }
|
||||
#define VL_ASSIGN_SBI(obits,svar,rd) { (svar).write(rd); }
|
||||
#define VL_ASSIGN_SBQ(obits,svar,rd) { (svar).write(rd); }
|
||||
#define VL_ASSIGN_SBW(obits,svar,rwp) { \
|
||||
sc_biguint<obits> _butemp; \
|
||||
for (int i=0; i < VL_WORDS_I(obits); i++) { \
|
||||
int msb = ((i+1)*VL_WORDSIZE) - 1; \
|
||||
msb = (msb >= obits) ? (obits-1) : msb; \
|
||||
_butemp.range(msb,i*VL_WORDSIZE) = rwp[i]; \
|
||||
} \
|
||||
svar.write(_butemp); \
|
||||
}
|
||||
|
||||
//===================================================================
|
||||
// Extending sizes
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
######################################################################
|
||||
# DESCRIPTION: Makefile commands for all verilated target files
|
||||
#
|
||||
# Copyright 2003-2011 by Wilson Snyder. Verilator is free software; you can
|
||||
# Copyright 2003-2013 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.
|
||||
######################################################################
|
||||
@@ -93,10 +93,10 @@ VM_SUPPORT += $(VM_SUPPORT_FAST) $(VM_SUPPORT_SLOW)
|
||||
##### SystemC or SystemPerl builds
|
||||
|
||||
ifeq ($(VM_SP_OR_SC),1)
|
||||
CPPFLAGS += $(SYSTEMC_CXX_FLAGS) -I$(SYSTEMC)/include
|
||||
LDFLAGS += $(SYSTEMC_CXX_FLAGS) -L$(SYSTEMC)/lib-$(VM_SC_TARGET_ARCH)
|
||||
CPPFLAGS += $(SYSTEMC_CXX_FLAGS) -I$(SYSTEMC_INCLUDE)
|
||||
LDFLAGS += $(SYSTEMC_CXX_FLAGS) -L$(SYSTEMC_LIBDIR)
|
||||
SC_LIBS = -lsystemc
|
||||
ifneq ($(wildcard $(SYSTEMC)/lib-$(VM_SC_TARGET_ARCH)/*numeric_bit*),)
|
||||
ifneq ($(wildcard $(SYSTEMC_LIBDIR)/*numeric_bit*),)
|
||||
# Systemc 1.2.1beta
|
||||
SC_LIBS += -lnumeric_bit -lqt
|
||||
endif
|
||||
|
||||
+2
-3
@@ -1,11 +1,10 @@
|
||||
// -*- C++ -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2013 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,7 +22,7 @@
|
||||
`define _VERILATED_V_ 1
|
||||
|
||||
// Hide verilator pragmas from other tools
|
||||
`ifdef verilator `else
|
||||
`ifdef VERILATOR `else
|
||||
`define coverage_block_off
|
||||
`endif
|
||||
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 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.
|
||||
//
|
||||
// Verilator is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
//*************************************************************************
|
||||
///
|
||||
/// \file
|
||||
/// \brief Verilator: Auto version information include for all Verilated C files
|
||||
///
|
||||
/// Code available from: http://www.veripool.org/verilator
|
||||
///
|
||||
//*************************************************************************
|
||||
|
||||
|
||||
///**** Product and Version name
|
||||
|
||||
// Autoconf substitutes this with the strings from AC_INIT.
|
||||
#define VERILATOR_PRODUCT "@PACKAGE_NAME@"
|
||||
#define VERILATOR_VERSION "@PACKAGE_VERSION@"
|
||||
@@ -1,7 +1,7 @@
|
||||
// -*- C++ -*-
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2009-2011 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2009-2013 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.
|
||||
@@ -104,9 +104,6 @@ int svHigh(const svOpenArrayHandle h, int d) {
|
||||
int svIncrement(const svOpenArrayHandle h, int d) {
|
||||
_VL_SVDPI_UNIMP(); return 0;
|
||||
}
|
||||
int svLength(const svOpenArrayHandle h, int d) {
|
||||
_VL_SVDPI_UNIMP(); return 0;
|
||||
}
|
||||
int svDimensions(const svOpenArrayHandle h) {
|
||||
_VL_SVDPI_UNIMP(); return 0;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// -*- C++ -*-
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2013 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License.
|
||||
// Version 2.0.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// -*- C++ -*-
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2010-2011 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2010-2013 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
-5
@@ -1,7 +1,7 @@
|
||||
// -*- C++ -*-
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2009-2011 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2009-2013 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.
|
||||
@@ -55,7 +55,9 @@ class VerilatedImp {
|
||||
// MEMBERS
|
||||
static VerilatedImp s_s; ///< Static Singleton; One and only static this
|
||||
|
||||
ArgVec m_argVec; ///< Argument list
|
||||
// Nothing here is save-restored; users expected to re-register appropriately
|
||||
|
||||
ArgVec m_argVec; ///< Argument list (NOT save-restored, may want different results)
|
||||
bool m_argVecLoaded; ///< Ever loaded argument list
|
||||
UserMap m_userMap; ///< Map of <(scope,userkey), userData>
|
||||
ScopeNameMap m_nameMap; ///< Map of <scope_name, scope pointer>
|
||||
@@ -76,6 +78,18 @@ public: // But only for verilated*.cpp
|
||||
m_fdps[2] = stderr;
|
||||
}
|
||||
~VerilatedImp() {}
|
||||
static void internalsDump() {
|
||||
VL_PRINTF("internalsDump:\n");
|
||||
VL_PRINTF(" Argv:");
|
||||
for (ArgVec::iterator it=s_s.m_argVec.begin(); it!=s_s.m_argVec.end(); ++it) {
|
||||
VL_PRINTF(" %s",it->c_str());
|
||||
}
|
||||
VL_PRINTF("\n");
|
||||
VL_PRINTF(" Version: %s %s\n", Verilated::productName(), Verilated::productVersion());
|
||||
scopesDump();
|
||||
exportsDump();
|
||||
userDump();
|
||||
}
|
||||
|
||||
// METHODS - arguments
|
||||
static void commandArgs(int argc, const char** argv) {
|
||||
@@ -127,6 +141,14 @@ private:
|
||||
}
|
||||
}
|
||||
}
|
||||
static void userDump() {
|
||||
bool first = true;
|
||||
for (UserMap::iterator it=s_s.m_userMap.begin(); it!=s_s.m_userMap.end(); ++it) {
|
||||
if (first) { VL_PRINTF(" userDump:\n"); first=false; }
|
||||
VL_PRINTF(" DPI_USER_DATA scope %p key %p: %p\n",
|
||||
it->first.first, it->first.second, it->second);
|
||||
}
|
||||
}
|
||||
|
||||
public: // But only for verilated*.cpp
|
||||
// METHODS - scope name
|
||||
@@ -148,9 +170,8 @@ public: // But only for verilated*.cpp
|
||||
ScopeNameMap::iterator it=s_s.m_nameMap.find(scopep->name());
|
||||
if (it != s_s.m_nameMap.end()) s_s.m_nameMap.erase(it);
|
||||
}
|
||||
|
||||
static void scopesDump() {
|
||||
VL_PRINTF("scopesDump:\n");
|
||||
VL_PRINTF(" scopesDump:\n");
|
||||
for (ScopeNameMap::iterator it=s_s.m_nameMap.begin(); it!=s_s.m_nameMap.end(); ++it) {
|
||||
const VerilatedScope* scopep = it->second;
|
||||
scopep->scopeDump();
|
||||
@@ -192,6 +213,13 @@ public: // But only for verilated*.cpp
|
||||
}
|
||||
return "*UNKNOWN*";
|
||||
}
|
||||
static void exportsDump() {
|
||||
bool first = true;
|
||||
for (ExportNameMap::iterator it=s_s.m_exportMap.begin(); it!=s_s.m_exportMap.end(); ++it) {
|
||||
if (first) { VL_PRINTF(" exportDump:\n"); first=false; }
|
||||
VL_PRINTF(" DPI_EXPORT_NAME %05d: %s\n", it->second, it->first);
|
||||
}
|
||||
}
|
||||
// We don't free up m_exportMap until the end, because we can't be sure
|
||||
// what other models are using the assigned funcnum's.
|
||||
|
||||
|
||||
@@ -0,0 +1,233 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//=============================================================================
|
||||
//
|
||||
// THIS MODULE IS PUBLICLY LICENSED
|
||||
//
|
||||
// Copyright 2001-2013 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.
|
||||
//
|
||||
// This is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
// for more details.
|
||||
//
|
||||
//=============================================================================
|
||||
///
|
||||
/// \file
|
||||
/// \brief C++ Tracing in VCD Format
|
||||
///
|
||||
/// AUTHOR: Wilson Snyder
|
||||
///
|
||||
//=============================================================================
|
||||
|
||||
#include "verilatedos.h"
|
||||
#include "verilated.h"
|
||||
#include "verilated_save.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <cerrno>
|
||||
|
||||
#if defined(_WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__)
|
||||
# include <io.h>
|
||||
#else
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifndef O_LARGEFILE // For example on WIN32
|
||||
# define O_LARGEFILE 0
|
||||
#endif
|
||||
#ifndef O_NONBLOCK
|
||||
# define O_NONBLOCK 0
|
||||
#endif
|
||||
|
||||
// CONSTANTS
|
||||
static const char* VLTSAVE_HEADER_STR = "verilatorsave01\n"; ///< Value of first bytes of each file
|
||||
static const char* VLTSAVE_TRAILER_STR = "vltsaved"; ///< Value of last bytes of each file
|
||||
|
||||
//=============================================================================
|
||||
//=============================================================================
|
||||
//=============================================================================
|
||||
// Searalization
|
||||
|
||||
bool VerilatedDeserialize::readDiffers (const void* __restrict datap, size_t size) {
|
||||
bufferCheck();
|
||||
const vluint8_t* __restrict dp = (const vluint8_t* __restrict)datap;
|
||||
vluint8_t miss = 0;
|
||||
while (size--) {
|
||||
miss |= (*dp++ ^ *m_cp++);
|
||||
}
|
||||
return (miss!=0);
|
||||
}
|
||||
|
||||
VerilatedDeserialize& VerilatedDeserialize::readAssert (const void* __restrict datap, size_t size) {
|
||||
if (VL_UNLIKELY(readDiffers(datap,size))) {
|
||||
string msg = (string)"Can't deserialize save-restore file as was made from different model";
|
||||
vl_fatal(filename().c_str(), 0, "", msg.c_str());
|
||||
close();
|
||||
}
|
||||
return *this; // For function chaining
|
||||
}
|
||||
|
||||
void VerilatedSerialize::header() {
|
||||
VerilatedSerialize& os = *this; // So can cut and paste standard << code below
|
||||
assert((strlen(VLTSAVE_HEADER_STR) & 7) == 0); // Keep aligned
|
||||
os.write(VLTSAVE_HEADER_STR, strlen(VLTSAVE_HEADER_STR));
|
||||
|
||||
// Verilated doesn't do it itself, as if we're not using save/restore
|
||||
// it doesn't need to compile this stuff in
|
||||
os.write(Verilated::serializedPtr(), Verilated::serializedSize());
|
||||
}
|
||||
|
||||
void VerilatedDeserialize::header() {
|
||||
VerilatedDeserialize& os = *this; // So can cut and paste standard >> code below
|
||||
if (VL_UNLIKELY(os.readDiffers(VLTSAVE_HEADER_STR, strlen(VLTSAVE_HEADER_STR)))) {
|
||||
string msg = (string)"Can't deserialize; file has wrong header signature";
|
||||
vl_fatal(filename().c_str(), 0, "", msg.c_str());
|
||||
close();
|
||||
}
|
||||
os.read(Verilated::serializedPtr(), Verilated::serializedSize());
|
||||
}
|
||||
|
||||
void VerilatedSerialize::trailer() {
|
||||
VerilatedSerialize& os = *this; // So can cut and paste standard << code below
|
||||
assert((strlen(VLTSAVE_TRAILER_STR) & 7) == 0); // Keep aligned
|
||||
os.write(VLTSAVE_TRAILER_STR, strlen(VLTSAVE_TRAILER_STR));
|
||||
}
|
||||
|
||||
void VerilatedDeserialize::trailer() {
|
||||
VerilatedDeserialize& os = *this; // So can cut and paste standard >> code below
|
||||
if (VL_UNLIKELY(os.readDiffers(VLTSAVE_TRAILER_STR, strlen(VLTSAVE_TRAILER_STR)))) {
|
||||
string msg = (string)"Can't deserialize; file has wrong end-of-file signature";
|
||||
vl_fatal(filename().c_str(), 0, "", msg.c_str());
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//=============================================================================
|
||||
//=============================================================================
|
||||
// Opening/Closing
|
||||
|
||||
void VerilatedSave::open (const char* filenamep) {
|
||||
if (isOpen()) return;
|
||||
VL_DEBUG_IF(VL_PRINTF("-vltSave: opening save file %s\n",filenamep););
|
||||
|
||||
if (filenamep[0]=='|') {
|
||||
assert(0); // Not supported yet.
|
||||
} else {
|
||||
// cppcheck-suppress duplicateExpression
|
||||
m_fd = ::open (filenamep, O_CREAT|O_WRONLY|O_TRUNC|O_LARGEFILE|O_NONBLOCK
|
||||
, 0666);
|
||||
if (m_fd<0) {
|
||||
// User code can check isOpen()
|
||||
m_isOpen = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
m_isOpen = true;
|
||||
m_filename = filenamep;
|
||||
m_cp = m_bufp;
|
||||
header();
|
||||
}
|
||||
|
||||
void VerilatedRestore::open (const char* filenamep) {
|
||||
if (isOpen()) return;
|
||||
VL_DEBUG_IF(VL_PRINTF("-vltRestore: opening restore file %s\n",filenamep););
|
||||
|
||||
if (filenamep[0]=='|') {
|
||||
assert(0); // Not supported yet.
|
||||
} else {
|
||||
// cppcheck-suppress duplicateExpression
|
||||
m_fd = ::open (filenamep, O_CREAT|O_RDONLY|O_LARGEFILE
|
||||
, 0666);
|
||||
if (m_fd<0) {
|
||||
// User code can check isOpen()
|
||||
m_isOpen = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
m_isOpen = true;
|
||||
m_filename = filenamep;
|
||||
m_cp = m_bufp;
|
||||
m_endp = m_bufp;
|
||||
header();
|
||||
}
|
||||
|
||||
void VerilatedSave::close () {
|
||||
if (!isOpen()) return;
|
||||
trailer();
|
||||
flush();
|
||||
m_isOpen = false;
|
||||
::close(m_fd); // May get error, just ignore it
|
||||
}
|
||||
|
||||
void VerilatedRestore::close () {
|
||||
if (!isOpen()) return;
|
||||
trailer();
|
||||
flush();
|
||||
m_isOpen = false;
|
||||
::close(m_fd); // May get error, just ignore it
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
// Buffer management
|
||||
|
||||
void VerilatedSave::flush() {
|
||||
if (VL_UNLIKELY(!isOpen())) return;
|
||||
vluint8_t* wp = m_bufp;
|
||||
while (1) {
|
||||
ssize_t remaining = (m_cp - wp);
|
||||
if (remaining==0) break;
|
||||
errno = 0;
|
||||
ssize_t got = ::write (m_fd, wp, remaining);
|
||||
if (got>0) {
|
||||
wp += got;
|
||||
} else if (got < 0) {
|
||||
if (errno != EAGAIN && errno != EINTR) {
|
||||
// write failed, presume error (perhaps out of disk space)
|
||||
string msg = string(__FUNCTION__)+": "+strerror(errno);
|
||||
vl_fatal("",0,"",msg.c_str());
|
||||
close();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
m_cp = m_bufp; // Reset buffer
|
||||
}
|
||||
|
||||
void VerilatedRestore::fill() {
|
||||
if (VL_UNLIKELY(!isOpen())) return;
|
||||
// Move remaining characters down to start of buffer. (No memcpy, overlaps allowed)
|
||||
vluint8_t* rp = m_bufp;
|
||||
for (vluint8_t* sp=m_cp; rp < m_endp;) *rp++ = *sp++; // Overlaps
|
||||
m_endp = m_bufp + (m_endp - m_cp);
|
||||
m_cp = m_bufp; // Reset buffer
|
||||
// Read into buffer starting at m_endp
|
||||
while (1) {
|
||||
ssize_t remaining = (m_bufp+bufferSize() - m_endp);
|
||||
if (remaining==0) break;
|
||||
errno = 0;
|
||||
ssize_t got = ::read (m_fd, m_endp, remaining);
|
||||
if (got>0) {
|
||||
m_endp += got;
|
||||
} else if (got < 0) {
|
||||
if (errno != EAGAIN && errno != EINTR) {
|
||||
// write failed, presume error (perhaps out of disk space)
|
||||
string msg = string(__FUNCTION__)+": "+strerror(errno);
|
||||
vl_fatal("",0,"",msg.c_str());
|
||||
close();
|
||||
break;
|
||||
}
|
||||
} else { // got==0, EOF
|
||||
// Fill buffer from here to end with NULLs so reader's don't need to check eof each character.
|
||||
while (m_endp < m_bufp+bufferSize()) *m_endp++ = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
// Serialization of types
|
||||
|
||||
|
||||
@@ -0,0 +1,234 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//=============================================================================
|
||||
//
|
||||
// THIS MODULE IS PUBLICLY LICENSED
|
||||
//
|
||||
// Copyright 2012-2013 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.
|
||||
//
|
||||
// This is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
// for more details.
|
||||
//
|
||||
//=============================================================================
|
||||
///
|
||||
/// \file
|
||||
/// \brief Save-restore serialization of verilated modules
|
||||
///
|
||||
/// AUTHOR: Wilson Snyder
|
||||
///
|
||||
//=============================================================================
|
||||
|
||||
#ifndef _VERILATED_SAVE_C_H_
|
||||
#define _VERILATED_SAVE_C_H_ 1
|
||||
|
||||
#include "verilatedos.h"
|
||||
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
//=============================================================================
|
||||
// VerilatedSerialBase - internal base class for common code between VerilatedSerialize and VerilatedDeserialize
|
||||
|
||||
class VerilatedSerialBase {
|
||||
protected:
|
||||
// MEMBERS
|
||||
// For speed, keep m_cp as the first member of this structure
|
||||
vluint8_t* m_cp; ///< Current pointer into m_bufp buffer
|
||||
vluint8_t* m_bufp; ///< Output buffer
|
||||
bool m_isOpen; ///< True indicates open file/stream
|
||||
string m_filename;
|
||||
|
||||
inline static size_t bufferSize() { return 256*1024; } // See below for slack calculation
|
||||
inline static size_t bufferInsertSize() { return 16*1024; }
|
||||
|
||||
// CREATORS
|
||||
VerilatedSerialBase() {
|
||||
m_isOpen = false;
|
||||
m_bufp = new vluint8_t [bufferSize()];
|
||||
m_cp = m_bufp;
|
||||
}
|
||||
public:
|
||||
// CREATORS
|
||||
virtual ~VerilatedSerialBase() {
|
||||
close();
|
||||
if (m_bufp) { delete m_bufp; m_bufp=NULL; }
|
||||
}
|
||||
// METHODS
|
||||
bool isOpen() const { return m_isOpen; }
|
||||
string filename() const { return m_filename; }
|
||||
virtual void close() { flush(); }
|
||||
virtual void flush() {}
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
// VerilatedSerialize - convert structures to a stream representation
|
||||
|
||||
class VerilatedSerialize : public VerilatedSerialBase {
|
||||
protected:
|
||||
virtual void close() { flush(); }
|
||||
virtual void flush() {}
|
||||
void header();
|
||||
void trailer();
|
||||
public:
|
||||
// CREATORS
|
||||
VerilatedSerialize() {}
|
||||
virtual ~VerilatedSerialize() { close(); }
|
||||
// METHODS
|
||||
VerilatedSerialize& bufferCheck() {
|
||||
// Flush the write buffer if there's not enough space left for new information
|
||||
// We only call this once per vector, so we need enough slop for a very wide "b###" line
|
||||
if (VL_UNLIKELY(m_cp > (m_bufp+(bufferSize()-bufferInsertSize())))) {
|
||||
flush();
|
||||
}
|
||||
return *this; // For function chaining
|
||||
}
|
||||
inline VerilatedSerialize& write (const void* __restrict datap, size_t size) {
|
||||
const vluint8_t* __restrict dp = (const vluint8_t* __restrict)datap;
|
||||
while (size) {
|
||||
bufferCheck();
|
||||
size_t blk = size; if (blk>bufferInsertSize()) blk = bufferInsertSize();
|
||||
const vluint8_t* __restrict maxp = dp + blk;
|
||||
while (dp < maxp) *m_cp++ = *dp++;
|
||||
size -= blk;
|
||||
}
|
||||
return *this; // For function chaining
|
||||
}
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
// VerilatedDeserial - load structures from a stream representation
|
||||
|
||||
class VerilatedDeserialize : public VerilatedSerialBase {
|
||||
protected:
|
||||
vluint8_t* m_endp; ///< Last valid byte in m_bufp buffer
|
||||
virtual void fill() = 0;
|
||||
void header();
|
||||
void trailer();
|
||||
public:
|
||||
// CREATORS
|
||||
VerilatedDeserialize() { m_endp = NULL; }
|
||||
virtual ~VerilatedDeserialize() { close(); }
|
||||
// METHODS
|
||||
inline VerilatedDeserialize& read (void* __restrict datap, size_t size) {
|
||||
vluint8_t* __restrict dp = (vluint8_t* __restrict)datap;
|
||||
while (size) {
|
||||
bufferCheck();
|
||||
size_t blk = size; if (blk>bufferInsertSize()) blk = bufferInsertSize();
|
||||
const vluint8_t* __restrict maxp = dp + blk;
|
||||
while (dp < maxp) *dp++ = *m_cp++;
|
||||
size -= blk;
|
||||
}
|
||||
return *this; // For function chaining
|
||||
}
|
||||
// Read a datum and compare with expected value
|
||||
bool readDiffers (const void* __restrict datap, size_t size);
|
||||
VerilatedDeserialize& readAssert (const void* __restrict datap, size_t size);
|
||||
VerilatedDeserialize& readAssert (vluint64_t data) { return readAssert(&data, sizeof(data)); }
|
||||
VerilatedDeserialize& bufferCheck() {
|
||||
// Flush the write buffer if there's not enough space left for new information
|
||||
// We only call this once per vector, so we need enough slop for a very wide "b###" line
|
||||
if (VL_UNLIKELY((m_cp+bufferInsertSize()) > m_endp)) {
|
||||
fill();
|
||||
}
|
||||
return *this; // For function chaining
|
||||
}
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
// VerilatedSave - serialize to a file
|
||||
|
||||
class VerilatedSave : public VerilatedSerialize {
|
||||
private:
|
||||
int m_fd; ///< File descriptor we're writing to
|
||||
|
||||
public:
|
||||
// CREATORS
|
||||
VerilatedSave() { m_fd=-1; }
|
||||
virtual ~VerilatedSave() { close(); }
|
||||
// METHODS
|
||||
void open(const char* filenamep); ///< Open the file; call isOpen() to see if errors
|
||||
void open(const string& filename) { open(filename.c_str()); }
|
||||
virtual void close();
|
||||
virtual void flush();
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
// VerilatedRestore - deserialize from a file
|
||||
|
||||
class VerilatedRestore : public VerilatedDeserialize {
|
||||
private:
|
||||
int m_fd; ///< File descriptor we're writing to
|
||||
|
||||
public:
|
||||
// CREATORS
|
||||
VerilatedRestore() { m_fd=-1; }
|
||||
virtual ~VerilatedRestore() { close(); }
|
||||
|
||||
// METHODS
|
||||
void open(const char* filenamep); ///< Open the file; call isOpen() to see if errors
|
||||
void open(const string& filename) { open(filename.c_str()); }
|
||||
virtual void close();
|
||||
virtual void flush() {}
|
||||
virtual void fill();
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
|
||||
inline VerilatedSerialize& operator<<(VerilatedSerialize& os, vluint64_t& rhs) {
|
||||
return os.write(&rhs, sizeof(rhs));
|
||||
}
|
||||
inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, vluint64_t& rhs){
|
||||
return os.read(&rhs, sizeof(rhs));
|
||||
}
|
||||
inline VerilatedSerialize& operator<<(VerilatedSerialize& os, vluint32_t& rhs) {
|
||||
return os.write(&rhs, sizeof(rhs));
|
||||
}
|
||||
inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, vluint32_t& rhs) {
|
||||
return os.read(&rhs, sizeof(rhs));
|
||||
}
|
||||
inline VerilatedSerialize& operator<<(VerilatedSerialize& os, vluint16_t& rhs) {
|
||||
return os.write(&rhs, sizeof(rhs));
|
||||
}
|
||||
inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, vluint16_t& rhs) {
|
||||
return os.read(&rhs, sizeof(rhs));
|
||||
}
|
||||
inline VerilatedSerialize& operator<<(VerilatedSerialize& os, vluint8_t& rhs) {
|
||||
return os.write(&rhs, sizeof(rhs));
|
||||
}
|
||||
inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, vluint8_t& rhs) {
|
||||
return os.read(&rhs, sizeof(rhs));
|
||||
}
|
||||
inline VerilatedSerialize& operator<<(VerilatedSerialize& os, bool& rhs) {
|
||||
return os.write(&rhs, sizeof(rhs));
|
||||
}
|
||||
inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, bool& rhs) {
|
||||
return os.read(&rhs, sizeof(rhs));
|
||||
}
|
||||
inline VerilatedSerialize& operator<<(VerilatedSerialize& os, double& rhs) {
|
||||
return os.write(&rhs, sizeof(rhs));
|
||||
}
|
||||
inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, double& rhs) {
|
||||
return os.read(&rhs, sizeof(rhs));
|
||||
}
|
||||
inline VerilatedSerialize& operator<<(VerilatedSerialize& os, float& rhs) {
|
||||
return os.write(&rhs, sizeof(rhs));
|
||||
}
|
||||
inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, float& rhs) {
|
||||
return os.read(&rhs, sizeof(rhs));
|
||||
}
|
||||
inline VerilatedSerialize& operator<<(VerilatedSerialize& os, string& rhs) {
|
||||
vluint32_t len=rhs.length();
|
||||
os<<len;
|
||||
return os.write(rhs.data(), len);
|
||||
}
|
||||
inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, string& rhs) {
|
||||
vluint32_t len;
|
||||
os>>len;
|
||||
rhs.resize(len);
|
||||
return os.read((void*)rhs.data(), len);
|
||||
}
|
||||
|
||||
#endif // guard
|
||||
@@ -1,7 +1,7 @@
|
||||
// -*- C++ -*-
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2009-2011 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2009-2013 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License.
|
||||
// Version 2.0.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// -*- C++ -*-
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2013 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License.
|
||||
// Version 2.0.
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
// -*- SystemC -*-
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//=============================================================================
|
||||
//
|
||||
// THIS MODULE IS PUBLICLY LICENSED
|
||||
//
|
||||
// Copyright 2001-2011 by Wilson Snyder. This program is free software;
|
||||
// Copyright 2001-2013 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.
|
||||
//
|
||||
@@ -141,6 +141,7 @@ void VerilatedVcd::openNext (bool incFilename) {
|
||||
if (m_filename[0]=='|') {
|
||||
assert(0); // Not supported yet.
|
||||
} else {
|
||||
// cppcheck-suppress duplicateExpression
|
||||
m_fd = ::open (m_filename.c_str(), O_CREAT|O_WRONLY|O_TRUNC|O_LARGEFILE|O_NONBLOCK
|
||||
, 0666);
|
||||
if (m_fd<0) {
|
||||
@@ -156,6 +157,8 @@ void VerilatedVcd::openNext (bool incFilename) {
|
||||
|
||||
void VerilatedVcd::makeNameMap() {
|
||||
// Take signal information from each module and build m_namemapp
|
||||
deleteNameMap();
|
||||
m_nextCode = 1;
|
||||
m_namemapp = new NameMap;
|
||||
for (vluint32_t ent = 0; ent< m_callbacks.size(); ent++) {
|
||||
VerilatedVcdCallInfo *cip = m_callbacks[ent];
|
||||
@@ -182,15 +185,20 @@ void VerilatedVcd::makeNameMap() {
|
||||
newname += hiername;
|
||||
newmapp->insert(make_pair(newname,decl));
|
||||
}
|
||||
delete m_namemapp; m_namemapp=NULL;
|
||||
deleteNameMap();
|
||||
m_namemapp = newmapp;
|
||||
}
|
||||
}
|
||||
|
||||
void VerilatedVcd::deleteNameMap() {
|
||||
if (m_namemapp) { delete m_namemapp; m_namemapp=NULL; }
|
||||
}
|
||||
|
||||
VerilatedVcd::~VerilatedVcd() {
|
||||
close();
|
||||
if (m_wrBufp) { delete[] m_wrBufp; m_wrBufp=NULL; }
|
||||
if (m_sigs_oldvalp) { delete[] m_sigs_oldvalp; m_sigs_oldvalp=NULL; }
|
||||
deleteNameMap();
|
||||
// Remove from list of traces
|
||||
vector<VerilatedVcd*>::iterator pos = find(s_vcdVecp.begin(), s_vcdVecp.end(), this);
|
||||
if (pos != s_vcdVecp.end()) { s_vcdVecp.erase(pos); }
|
||||
@@ -413,7 +421,7 @@ void VerilatedVcd::dumpHeader () {
|
||||
assert (m_modDepth==0);
|
||||
|
||||
// Reclaim storage
|
||||
delete m_namemapp;
|
||||
deleteNameMap();
|
||||
}
|
||||
|
||||
void VerilatedVcd::module (string name) {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
// -*- SystemC -*-
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//=============================================================================
|
||||
//
|
||||
// THIS MODULE IS PUBLICLY LICENSED
|
||||
//
|
||||
// Copyright 2001-2011 by Wilson Snyder. This program is free software;
|
||||
// Copyright 2001-2013 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.
|
||||
//
|
||||
@@ -57,7 +57,8 @@ typedef void (*VerilatedVcdCallback_t)(VerilatedVcd* vcdp, void* userthis, vluin
|
||||
|
||||
//=============================================================================
|
||||
// VerilatedVcd
|
||||
/// Create a SystemPerl VCD dump
|
||||
/// Base class to create a Verilator VCD dump
|
||||
/// This is an internally used class - see VerilatedVcdC for what to call from applications
|
||||
|
||||
class VerilatedVcd {
|
||||
private:
|
||||
@@ -100,6 +101,7 @@ private:
|
||||
void closeErr();
|
||||
void openNext();
|
||||
void makeNameMap();
|
||||
void deleteNameMap();
|
||||
void printIndent (int levelchange);
|
||||
void printStr (const char* str);
|
||||
void printQuad (vluint64_t n);
|
||||
@@ -400,8 +402,12 @@ public:
|
||||
bool isOpen() const { return m_sptrace.isOpen(); }
|
||||
// METHODS
|
||||
/// 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) { 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.
|
||||
void openNext (bool incFilename=true) { m_sptrace.openNext(incFilename); }
|
||||
/// Set size in megabytes after which new file should be created
|
||||
void rolloverMB(size_t rolloverMB) { m_sptrace.rolloverMB(rolloverMB); };
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
// -*- SystemC -*-
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//=============================================================================
|
||||
//
|
||||
// THIS MODULE IS PUBLICLY LICENSED
|
||||
//
|
||||
// Copyright 2001-2011 by Wilson Snyder. This program is free software;
|
||||
// Copyright 2001-2013 by Wilson Snyder. This program is free software;
|
||||
// you can redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||
//
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
// -*- SystemC -*-
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//=============================================================================
|
||||
//
|
||||
// THIS MODULE IS PUBLICLY LICENSED
|
||||
//
|
||||
// Copyright 2001-2011 by Wilson Snyder. This program is free software;
|
||||
// Copyright 2001-2013 by Wilson Snyder. This program is free software;
|
||||
// you can redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||
//
|
||||
@@ -76,6 +76,8 @@ private:
|
||||
#ifdef NC_SYSTEMC
|
||||
// Cadence Incisive has these as abstract functions so we must create them
|
||||
virtual void set_time_unit( int exponent10_seconds ) {} // deprecated
|
||||
#endif
|
||||
#if defined(NC_SYSTEMC) || (SYSTEMC_VERSION>=20111100)
|
||||
virtual void set_time_unit( double v, sc_time_unit tu ) {}
|
||||
#endif
|
||||
|
||||
|
||||
+333
-2
@@ -1,7 +1,7 @@
|
||||
// -*- C++ -*-
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2009-2011 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2009-2013 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License.
|
||||
// Version 2.0.
|
||||
@@ -31,3 +31,334 @@ VerilatedVpi VerilatedVpi::s_s; // Singleton
|
||||
vluint8_t* VerilatedVpio::s_freeHead = NULL;
|
||||
|
||||
//======================================================================
|
||||
|
||||
const char* VerilatedVpiError::strFromVpiVal(PLI_INT32 vpiVal) {
|
||||
static const char *names[] = {
|
||||
"*undefined*",
|
||||
"vpiBinStrVal",
|
||||
"vpiOctStrVal",
|
||||
"vpiDecStrVal",
|
||||
"vpiHexStrVal",
|
||||
"vpiScalarVal",
|
||||
"vpiIntVal",
|
||||
"vpiRealVal",
|
||||
"vpiStringVal",
|
||||
"vpiVectorVal",
|
||||
"vpiStrengthVal",
|
||||
"vpiTimeVal",
|
||||
"vpiObjTypeVal",
|
||||
"vpiSuppressVal",
|
||||
"vpiShortIntVal",
|
||||
"vpiLongIntVal",
|
||||
"vpiShortRealVal",
|
||||
"vpiRawTwoStateVal",
|
||||
"vpiRawFourStateVal",
|
||||
};
|
||||
if (vpiVal < 0) return names[0];
|
||||
return names[(vpiVal<=vpiRawFourStateVal)?vpiVal:0];
|
||||
}
|
||||
const char* VerilatedVpiError::strFromVpiObjType(PLI_INT32 vpiVal) {
|
||||
static const char *names[] = {
|
||||
"*undefined*",
|
||||
"vpiAlways",
|
||||
"vpiAssignStmt",
|
||||
"vpiAssignment",
|
||||
"vpiBegin",
|
||||
"vpiCase",
|
||||
"vpiCaseItem",
|
||||
"vpiConstant",
|
||||
"vpiContAssign",
|
||||
"vpiDeassign",
|
||||
"vpiDefParam",
|
||||
"vpiDelayControl",
|
||||
"vpiDisable",
|
||||
"vpiEventControl",
|
||||
"vpiEventStmt",
|
||||
"vpiFor",
|
||||
"vpiForce",
|
||||
"vpiForever",
|
||||
"vpiFork",
|
||||
"vpiFuncCall",
|
||||
"vpiFunction",
|
||||
"vpiGate",
|
||||
"vpiIf",
|
||||
"vpiIfElse",
|
||||
"vpiInitial",
|
||||
"vpiIntegerVar",
|
||||
"vpiInterModPath",
|
||||
"vpiIterator",
|
||||
"vpiIODecl",
|
||||
"vpiMemory",
|
||||
"vpiMemoryWord",
|
||||
"vpiModPath",
|
||||
"vpiModule",
|
||||
"vpiNamedBegin",
|
||||
"vpiNamedEvent",
|
||||
"vpiNamedFork",
|
||||
"vpiNet",
|
||||
"vpiNetBit",
|
||||
"vpiNullStmt",
|
||||
"vpiOperation",
|
||||
"vpiParamAssign",
|
||||
"vpiParameter",
|
||||
"vpiPartSelect",
|
||||
"vpiPathTerm",
|
||||
"vpiPort",
|
||||
"vpiPortBit",
|
||||
"vpiPrimTerm",
|
||||
"vpiRealVar",
|
||||
"vpiReg",
|
||||
"vpiRegBit",
|
||||
"vpiRelease",
|
||||
"vpiRepeat",
|
||||
"vpiRepeatControl",
|
||||
"vpiSchedEvent",
|
||||
"vpiSpecParam",
|
||||
"vpiSwitch",
|
||||
"vpiSysFuncCall",
|
||||
"vpiSysTaskCall",
|
||||
"vpiTableEntry",
|
||||
"vpiTask",
|
||||
"vpiTaskCall",
|
||||
"vpiTchk",
|
||||
"vpiTchkTerm",
|
||||
"vpiTimeVar",
|
||||
"vpiTimeQueue",
|
||||
"vpiUdp",
|
||||
"vpiUdpDefn",
|
||||
"vpiUserSystf",
|
||||
"vpiVarSelect",
|
||||
"vpiWait",
|
||||
"vpiWhile",
|
||||
"*undefined*",
|
||||
"*undefined*",
|
||||
"*undefined*",
|
||||
"*undefined*",
|
||||
"*undefined*",
|
||||
"*undefined*",
|
||||
"*undefined*",
|
||||
"*undefined*",
|
||||
"*undefined*",
|
||||
"*undefined*",
|
||||
"*undefined*",
|
||||
"*undefined*",
|
||||
"*undefined*",
|
||||
"*undefined*",
|
||||
"*undefined*",
|
||||
"*undefined*",
|
||||
"*undefined*",
|
||||
"*undefined*",
|
||||
"*undefined*",
|
||||
"*undefined*",
|
||||
"*undefined*",
|
||||
"*undefined*",
|
||||
"*undefined*",
|
||||
"*undefined*",
|
||||
"*undefined*",
|
||||
"*undefined*",
|
||||
"*undefined*",
|
||||
"*undefined*",
|
||||
"*undefined*",
|
||||
"*undefined*",
|
||||
"*undefined*",
|
||||
"*undefined*",
|
||||
"*undefined*",
|
||||
"*undefined*",
|
||||
"vpiAttribute",
|
||||
"vpiBitSelect",
|
||||
"vpiCallback",
|
||||
"vpiDelayTerm",
|
||||
"vpiDelayDevice",
|
||||
"vpiFrame",
|
||||
"vpiGateArray",
|
||||
"vpiModuleArray",
|
||||
"vpiPrimitiveArray",
|
||||
"vpiNetArray",
|
||||
"vpiRange",
|
||||
"vpiRegArray",
|
||||
"vpiSwitchArray",
|
||||
"vpiUdpArray",
|
||||
"*undefined*",
|
||||
"*undefined*",
|
||||
"*undefined*",
|
||||
"*undefined*",
|
||||
"*undefined*",
|
||||
"*undefined*",
|
||||
"*undefined*",
|
||||
"*undefined*",
|
||||
"*undefined*",
|
||||
"vpiContAssignBit",
|
||||
"vpiNamedEventArray",
|
||||
"vpiIndexedPartSelect",
|
||||
"*undefined*",
|
||||
"*undefined*",
|
||||
"vpiGenScopeArray",
|
||||
"vpiGenScope",
|
||||
"vpiGenVar"
|
||||
};
|
||||
if (vpiVal < 0) return names[0];
|
||||
return names[(vpiVal<=vpiGenVar)?vpiVal:0];
|
||||
}
|
||||
const char* VerilatedVpiError::strFromVpiMethod(PLI_INT32 vpiVal) {
|
||||
static const char *names[] = {
|
||||
"vpiCondition",
|
||||
"vpiDelay",
|
||||
"vpiElseStmt",
|
||||
"vpiForIncStmt",
|
||||
"vpiForInitStmt",
|
||||
"vpiHighConn",
|
||||
"vpiLhs",
|
||||
"vpiIndex",
|
||||
"vpiLeftRange",
|
||||
"vpiLowConn",
|
||||
"vpiParent",
|
||||
"vpiRhs",
|
||||
"vpiRightRange",
|
||||
"vpiScope",
|
||||
"vpiSysTfCall",
|
||||
"vpiTchkDataTerm",
|
||||
"vpiTchkNotifier",
|
||||
"vpiTchkRefTerm",
|
||||
"vpiArgument",
|
||||
"vpiBit",
|
||||
"vpiDriver",
|
||||
"vpiInternalScope",
|
||||
"vpiLoad",
|
||||
"vpiModDataPathIn",
|
||||
"vpiModPathIn",
|
||||
"vpiModPathOut",
|
||||
"vpiOperand",
|
||||
"vpiPortInst",
|
||||
"vpiProcess",
|
||||
"vpiVariables",
|
||||
"vpiUse",
|
||||
"vpiExpr",
|
||||
"vpiPrimitive",
|
||||
"vpiStmt"
|
||||
};
|
||||
if (vpiVal>vpiStmt || vpiVal<vpiCondition) {
|
||||
return "*undefined*";
|
||||
}
|
||||
return names[vpiVal-vpiCondition];
|
||||
}
|
||||
const char* VerilatedVpiError::strFromVpiCallbackReason(PLI_INT32 vpiVal) {
|
||||
static const char *names[] = {
|
||||
"*undefined*",
|
||||
"cbValueChange",
|
||||
"cbStmt",
|
||||
"cbForce",
|
||||
"cbRelease",
|
||||
"cbAtStartOfSimTime",
|
||||
"cbReadWriteSynch",
|
||||
"cbReadOnlySynch",
|
||||
"cbNextSimTime",
|
||||
"cbAfterDelay",
|
||||
"cbEndOfCompile",
|
||||
"cbStartOfSimulation",
|
||||
"cbEndOfSimulation",
|
||||
"cbError",
|
||||
"cbTchkViolation",
|
||||
"cbStartOfSave",
|
||||
"cbEndOfSave",
|
||||
"cbStartOfRestart",
|
||||
"cbEndOfRestart",
|
||||
"cbStartOfReset",
|
||||
"cbEndOfReset",
|
||||
"cbEnterInteractive",
|
||||
"cbExitInteractive",
|
||||
"cbInteractiveScopeChange",
|
||||
"cbUnresolvedSystf",
|
||||
"cbAssign",
|
||||
"cbDeassign",
|
||||
"cbDisable",
|
||||
"cbPLIError",
|
||||
"cbSignal",
|
||||
"cbNBASynch",
|
||||
"cbAtEndOfSimTime"
|
||||
};
|
||||
if (vpiVal < 0) return names[0];
|
||||
return names[(vpiVal<=cbAtEndOfSimTime)?vpiVal:0];
|
||||
}
|
||||
const char* VerilatedVpiError::strFromVpiProp(PLI_INT32 vpiVal) {
|
||||
static const char *names[] = {
|
||||
"*undefined or other*",
|
||||
"vpiType",
|
||||
"vpiName",
|
||||
"vpiFullName",
|
||||
"vpiSize",
|
||||
"vpiFile",
|
||||
"vpiLineNo",
|
||||
"vpiTopModule",
|
||||
"vpiCellInstance",
|
||||
"vpiDefName",
|
||||
"vpiProtected",
|
||||
"vpiTimeUnit",
|
||||
"vpiTimePrecision",
|
||||
"vpiDefNetType",
|
||||
"vpiUnconnDrive",
|
||||
"vpiDefFile",
|
||||
"vpiDefLineNo",
|
||||
"vpiScalar",
|
||||
"vpiVector",
|
||||
"vpiExplicitName",
|
||||
"vpiDirection",
|
||||
"vpiConnByName",
|
||||
"vpiNetType",
|
||||
"vpiExplicitScalared",
|
||||
"vpiExplicitVectored",
|
||||
"vpiExpanded",
|
||||
"vpiImplicitDecl",
|
||||
"vpiChargeStrength",
|
||||
"vpiArray",
|
||||
"vpiPortIndex",
|
||||
"vpiTermIndex",
|
||||
"vpiStrength0",
|
||||
"vpiStrength1",
|
||||
"vpiPrimType",
|
||||
"vpiPolarity",
|
||||
"vpiDataPolarity",
|
||||
"vpiEdge",
|
||||
"vpiPathType",
|
||||
"vpiTchkType",
|
||||
"vpiOpType",
|
||||
"vpiConstType",
|
||||
"vpiBlocking",
|
||||
"vpiCaseType",
|
||||
"vpiFuncType",
|
||||
"vpiNetDeclAssign",
|
||||
"vpiUserDefn",
|
||||
"vpiScheduled",
|
||||
"*undefined*",
|
||||
"*undefined*",
|
||||
"vpiActive",
|
||||
"vpiAutomatic",
|
||||
"vpiCell",
|
||||
"vpiConfig",
|
||||
"vpiConstantSelect",
|
||||
"vpiDecompile",
|
||||
"vpiDefAttribute",
|
||||
"vpiDelayType",
|
||||
"vpiIteratorType",
|
||||
"vpiLibrary",
|
||||
"*undefined*",
|
||||
"vpiOffset",
|
||||
"vpiResolvedNetType",
|
||||
"vpiSaveRestartID",
|
||||
"vpiSaveRestartLocation",
|
||||
"vpiValid",
|
||||
"vpiSigned",
|
||||
"vpiStop",
|
||||
"vpiFinish",
|
||||
"vpiReset",
|
||||
"vpiSetInteractiveScope",
|
||||
"vpiLocalParam",
|
||||
"vpiModPathHasIfNone",
|
||||
"vpiIndexedPartSelectType",
|
||||
"vpiIsMemory",
|
||||
"vpiIsProtected"
|
||||
};
|
||||
if (vpiVal == vpiUndefined) {
|
||||
return "vpiUndefined";
|
||||
}
|
||||
return names[(vpiVal<=vpiIsProtected)?vpiVal:0];
|
||||
}
|
||||
|
||||
+617
-101
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
// -*- C++ -*-
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2013 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.
|
||||
@@ -78,8 +78,12 @@
|
||||
# else
|
||||
# error "Unsupported compiler for VL_THREADED: No thread-local declarator"
|
||||
# endif
|
||||
# define VL_STATIC_OR_THREAD ///< Static if unthreaded, as some strings can be faster
|
||||
// ///< if non-dynamic and can't do "static VL_THREAD string"
|
||||
#else
|
||||
# define VL_THREAD ///< Storage class for thread-local storage
|
||||
# define VL_STATIC_OR_THREAD static ///< Static if unthreaded, as some strings can be faster
|
||||
// ///< if non-dynamic and can't do "static VL_THREAD string"
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
+11
-5
@@ -7,7 +7,7 @@
|
||||
* This file contains the constant definitions, structure definitions,
|
||||
* and routine declarations used by SystemVerilog DPI.
|
||||
*
|
||||
* This file is from the SystemVerilog IEEE 1800-2009 Annex I.
|
||||
* This file is from the SystemVerilog IEEE 1800-2012 Annex I.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDED_SVDPI
|
||||
@@ -27,25 +27,31 @@ typedef signed __int32 int32_t;
|
||||
typedef signed __int8 int8_t;
|
||||
#elif defined(__MINGW32__)
|
||||
#include <stdint.h>
|
||||
#elif defined(__APPLE__)
|
||||
#include <stdint.h>
|
||||
#elif defined(__linux)
|
||||
#include <inttypes.h>
|
||||
#else
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
/* Use to export a symbol from application */
|
||||
#if defined (_MSC_VER)
|
||||
/* Use to import a symbol into dll */
|
||||
#ifndef DPI_DLLISPEC
|
||||
#if (defined(_MSC_VER) || defined(__MINGW32__) || defined(__CYGWIN__))
|
||||
#define DPI_DLLISPEC __declspec(dllimport)
|
||||
#else
|
||||
#define DPI_DLLISPEC
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Use to import a symbol into application */
|
||||
#if defined (_MSC_VER)
|
||||
/* Use to export a symbol from dll */
|
||||
#ifndef DPI_DLLESPEC
|
||||
#if (defined(_MSC_VER) || defined(__MINGW32__) || defined(__CYGWIN__))
|
||||
#define DPI_DLLESPEC __declspec(dllexport)
|
||||
#else
|
||||
#define DPI_DLLESPEC
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Use to mark a function as external */
|
||||
#ifndef DPI_EXTERN
|
||||
|
||||
+21
-21
@@ -1,7 +1,7 @@
|
||||
/*******************************************************************************
|
||||
* vpi_user.h
|
||||
*
|
||||
* IEEE Std 1800 Programming Language Interface (PLI)
|
||||
* IEEE Std 1800-2012 Programming Language Interface (PLI)
|
||||
*
|
||||
* This file contains the constant definitions, structure definitions, and
|
||||
* routine declarations used by the SystemVerilog Verification Procedural
|
||||
@@ -61,9 +61,9 @@ typedef char PLI_BYTE8;
|
||||
typedef unsigned char PLI_UBYTE8;
|
||||
#endif
|
||||
|
||||
/* Use to export a symbol */
|
||||
/* Use to import a symbol */
|
||||
|
||||
#if WIN32
|
||||
#if (defined(_MSC_VER) || defined(__MINGW32__) || defined(__CYGWIN__))
|
||||
#ifndef PLI_DLLISPEC
|
||||
#define PLI_DLLISPEC __declspec(dllimport)
|
||||
#define VPI_USER_DEFINED_DLLISPEC 1
|
||||
@@ -74,9 +74,9 @@ typedef unsigned char PLI_UBYTE8;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Use to import a symbol */
|
||||
/* Use to export a symbol */
|
||||
|
||||
#if WIN32
|
||||
#if (defined(_MSC_VER) || defined(__MINGW32__) || defined(__CYGWIN__))
|
||||
#ifndef PLI_DLLESPEC
|
||||
#define PLI_DLLESPEC __declspec(dllexport)
|
||||
#define VPI_USER_DEFINED_DLLESPEC 1
|
||||
@@ -438,12 +438,12 @@ typedef PLI_UINT32 *vpiHandle;
|
||||
#define vpiPlusOp 2 /* unary plus */
|
||||
#define vpiNotOp 3 /* unary not */
|
||||
#define vpiBitNegOp 4 /* bitwise negation */
|
||||
#define vpiUnaryAndOp 5 /* bitwise reduction and */
|
||||
#define vpiUnaryNandOp 6 /* bitwise reduction nand */
|
||||
#define vpiUnaryOrOp 7 /* bitwise reduction or */
|
||||
#define vpiUnaryNorOp 8 /* bitwise reduction nor */
|
||||
#define vpiUnaryXorOp 9 /* bitwise reduction xor */
|
||||
#define vpiUnaryXNorOp 10 /* bitwise reduction xnor */
|
||||
#define vpiUnaryAndOp 5 /* bitwise reduction AND */
|
||||
#define vpiUnaryNandOp 6 /* bitwise reduction NAND */
|
||||
#define vpiUnaryOrOp 7 /* bitwise reduction OR */
|
||||
#define vpiUnaryNorOp 8 /* bitwise reduction NOR */
|
||||
#define vpiUnaryXorOp 9 /* bitwise reduction XOR */
|
||||
#define vpiUnaryXNorOp 10 /* bitwise reduction XNOR */
|
||||
#define vpiSubOp 11 /* binary subtraction */
|
||||
#define vpiDivOp 12 /* binary division */
|
||||
#define vpiModOp 13 /* binary modulus */
|
||||
@@ -459,17 +459,17 @@ typedef PLI_UINT32 *vpiHandle;
|
||||
#define vpiRShiftOp 23 /* binary right shift */
|
||||
#define vpiAddOp 24 /* binary addition */
|
||||
#define vpiMultOp 25 /* binary multiplication */
|
||||
#define vpiLogAndOp 26 /* binary logical and */
|
||||
#define vpiLogOrOp 27 /* binary logical or */
|
||||
#define vpiBitAndOp 28 /* binary bitwise and */
|
||||
#define vpiBitOrOp 29 /* binary bitwise or */
|
||||
#define vpiBitXorOp 30 /* binary bitwise xor */
|
||||
#define vpiBitXNorOp 31 /* binary bitwise xnor */
|
||||
#define vpiLogAndOp 26 /* binary logical AND */
|
||||
#define vpiLogOrOp 27 /* binary logical OR */
|
||||
#define vpiBitAndOp 28 /* binary bitwise AND */
|
||||
#define vpiBitOrOp 29 /* binary bitwise OR */
|
||||
#define vpiBitXorOp 30 /* binary bitwise XOR */
|
||||
#define vpiBitXNorOp 31 /* binary bitwise XNOR */
|
||||
#define vpiBitXnorOp vpiBitXNorOp /* added with 1364-2001 */
|
||||
#define vpiConditionOp 32 /* ternary conditional */
|
||||
#define vpiConcatOp 33 /* n-ary concatenation */
|
||||
#define vpiMultiConcatOp 34 /* repeated concatenation */
|
||||
#define vpiEventOrOp 35 /* event or */
|
||||
#define vpiEventOrOp 35 /* event OR */
|
||||
#define vpiNullOp 36 /* null operation */
|
||||
#define vpiListOp 37 /* list of expressions */
|
||||
#define vpiMinTypMaxOp 38 /* min:typ:max: delay expression */
|
||||
@@ -536,7 +536,7 @@ typedef PLI_UINT32 *vpiHandle;
|
||||
same subtypes as vpiNetType */
|
||||
#define vpiSaveRestartID 62 /* unique ID for save/restart data */
|
||||
#define vpiSaveRestartLocation 63 /* name of save/restart data file */
|
||||
/* vpiValid,vpiValidTrue,vpiValidFalse are deprecated in 1800-2009 */
|
||||
/* vpiValid,vpiValidTrue,vpiValidFalse were deprecated in 1800-2009 */
|
||||
#define vpiValid 64 /* reentrant task/func frame or automatic
|
||||
variable is valid */
|
||||
#define vpiValidFalse 0
|
||||
@@ -661,7 +661,7 @@ typedef struct t_vpi_arrayvalue
|
||||
{
|
||||
PLI_INT32 *integers; /* integer values */
|
||||
PLI_INT16 *shortints; /* short integer values */
|
||||
PLI_INT16 *longints; /* long integer values */
|
||||
PLI_INT64 *longints; /* long integer values */
|
||||
PLI_BYTE8 *rawvals; /* 2/4-state vector elements */
|
||||
struct t_vpi_vecval *vectors; /* 4-state vector elements */
|
||||
struct t_vpi_time *times; /* time values */
|
||||
@@ -944,7 +944,7 @@ XXTERN PLI_INT32 vpi_compare_objects PROTO_PARAMS((vpiHandle object1,
|
||||
vpiHandle object2));
|
||||
XXTERN PLI_INT32 vpi_chk_error PROTO_PARAMS((p_vpi_error_info
|
||||
error_info_p));
|
||||
/* vpi_free_object() is deprecated in 1800-2009 */
|
||||
/* vpi_free_object() was deprecated in 1800-2009 */
|
||||
XXTERN PLI_INT32 vpi_free_object PROTO_PARAMS((vpiHandle object));
|
||||
XXTERN PLI_INT32 vpi_release_handle PROTO_PARAMS((vpiHandle object));
|
||||
XXTERN PLI_INT32 vpi_get_vlog_info PROTO_PARAMS((p_vpi_vlog_info
|
||||
|
||||
+570
-73
@@ -14,32 +14,6 @@ the first for reference for developers and debugging problems.
|
||||
|
||||
See also the Verilator internals presentation at http://www.veripool.org.
|
||||
|
||||
=head1 ADDING A NEW FEATURE
|
||||
|
||||
Generally what would you do to add a new feature?
|
||||
|
||||
=over 4
|
||||
|
||||
File a bug (if there isn't already) so others know what you're working on.
|
||||
|
||||
Make a testcase in the test_regress/t/t_EXAMPLE format, see TESTING Below.
|
||||
|
||||
If grammar changes are needed, look at the git version of VerilogPerl's
|
||||
src/VParseGrammar.y, as this grammar supports the full SystemVerilog
|
||||
language and has a lot of back-and-forth with Verilator's grammar. Copy
|
||||
the appropriate rules to src/verilog.y and modify the productions.
|
||||
|
||||
If a new Ast type is needed, add it to V3AstNodes.h.
|
||||
|
||||
Now you can run "test_regress/t/t_{new testcase}.pl --debug" and it'll
|
||||
probably fail but you'll see a test_regress/obj_dir/t_{newtestcase}/*.tree
|
||||
file which you can examine to see if the parsing worked. See also the
|
||||
sections below on debugging.
|
||||
|
||||
Modify the later visitor functions to process the new feature as needed.
|
||||
|
||||
=back
|
||||
|
||||
=head1 CODE FLOWS
|
||||
|
||||
=head2 Verilator Flow
|
||||
@@ -52,7 +26,11 @@ preprocessing, then lexical analysis with Flex and parsing with Bison.
|
||||
This produces an abstract syntax tree (AST) representation of the design,
|
||||
which is what is visible in the .tree files described below.
|
||||
|
||||
Cells are then linked, which will read and parse additional files as above.
|
||||
Verilator then makes a series of passes over the AST, progressively refining
|
||||
and optimizing it.
|
||||
|
||||
Cells in the AST first linked, which will read and parse additional files as
|
||||
above.
|
||||
|
||||
Functions, variable and other references are linked to their definitions.
|
||||
|
||||
@@ -87,6 +65,96 @@ hints, and performs additional constant propagation.
|
||||
|
||||
Verilator finally writes the C++ modules.
|
||||
|
||||
=head2 Key Classes Used in the Verilator Flow
|
||||
|
||||
=over 4
|
||||
|
||||
=item C<AstNode>
|
||||
|
||||
The AST is represented at the top level by the class C<AstNode>. This abstract
|
||||
class has derived classes for the individual components (e.g. C<AstGenerate>
|
||||
for a generate block) or groups of components (e.g. C<AstNodeFTask> for
|
||||
functions and tasks, which in turn has C<AstFunc> and C<AstTask> as derived
|
||||
classes).
|
||||
|
||||
Each C<AstNode> has pointers to up to four children, accessed by the
|
||||
C<op1p> through C<op4p> methods. These methods are then abstracted in a
|
||||
specific Ast* node class to a more specific name. For example with the
|
||||
C<AstIf> node (for C<if> statements), C<ifsp> calls C<op1p> to give the
|
||||
pointer to the AST for the "then" block, while C<elsesp> calls C<op2p> to
|
||||
give the pointer to the AST for the "else" block, or NULL if there is not
|
||||
one.
|
||||
|
||||
C<AstNode> has the concept of a next and previous AST - for example the
|
||||
next and previous statements in a block. Pointers to the AST for these
|
||||
statements (if they exist) can be obtained using the C<back> and C<next>
|
||||
methods.
|
||||
|
||||
It is useful to remember that the derived class C<AstNetlist> is at the top
|
||||
of the tree, so checking for this class is the standard way to see if you
|
||||
are at the top of the tree.
|
||||
|
||||
By convention, each function/method uses the variable C<nodep> as a pointer
|
||||
to the C<AstNode> currently being processed.
|
||||
|
||||
=item C<AstNVistor>
|
||||
|
||||
The passes are implemented by AST visitor classes (see L</Visitor
|
||||
Functions>). These are implemented by subclasses of the abstract class,
|
||||
C<AstNVisitor>. Each pass creates an instance of the visitor class, which
|
||||
in turn implements a method to perform the pass.
|
||||
|
||||
=item C<V3Graph>
|
||||
|
||||
A number of passes use graph algorithms, and the class C<V3Graph> is provided
|
||||
to represent those graphs. Graphs are directed, and algorithms are provided to
|
||||
manipulate the graphs and to output them in I<GraphViz> dot format (see
|
||||
L<http://www.graphviz.org/>). C<V3Graph.h> provides documentation of this
|
||||
class.
|
||||
|
||||
=item C<V3GraphVertex>
|
||||
|
||||
This is the base class for vertices in a graph. Vertices have an associated
|
||||
C<fanout>, C<color> and C<rank>, which may be used in algorithms for ordering
|
||||
the graph. A generic C<user>/C<userp> member variable is also provided.
|
||||
|
||||
Virtual methods are provided to specify the name, color, shape and style to be
|
||||
used in dot output. Typically users provided derived classes from
|
||||
C<V3GraphVertex> which will reimplement these methods.
|
||||
|
||||
Iterators are provided to access in and out edges. Typically these are used in
|
||||
the form:
|
||||
|
||||
for (V3GraphEdge *edgep = vertexp->inBeginp();
|
||||
edgep;
|
||||
edgep = edgep->inNextp()) {
|
||||
|
||||
=item C<V3GraphEdge>
|
||||
|
||||
This is the base class for directed edges between pairs of vertices. Edges
|
||||
have an associated C<weight> and may also be made C<cutable>. A generic
|
||||
C<user>/C<userp> member variable is also provided.
|
||||
|
||||
Accessors, C<fromp> and C<top> return the "from" and "to" vertices
|
||||
respectively.
|
||||
|
||||
Virtual methods are provided to specify the label, color and style to be
|
||||
used in dot output. Typically users provided derived classes from
|
||||
C<V3GraphEdge> which will reimplement these methods.
|
||||
|
||||
=item C<V3GraphAlg>
|
||||
|
||||
This is the base class for graph algorithms. It implements a C<bool> method,
|
||||
C<followEdge> which algorithms can use to decide whether an edge is
|
||||
followed. This method returns true if the graph edge has weight greater than
|
||||
one and a user function, C<edgeFuncp> (supplied in the constructor) returns
|
||||
C<true>.
|
||||
|
||||
A number of predefined derived algorithm classes and access methods are
|
||||
provided and documented in C<V3GraphAlg.cpp>.
|
||||
|
||||
=back
|
||||
|
||||
=head2 Verilated Flow
|
||||
|
||||
The evaluation loop outputted by Verilator is designed to allow a single
|
||||
@@ -120,64 +188,307 @@ changed; if clear, checking those signals for changes may be skipped.
|
||||
To match the indentation of Verilator C++ sources, use 4 spaces per level,
|
||||
and leave tabs at 8 columns, so every other indent level is a tab stop.
|
||||
|
||||
In Emacs, use in your ~/.emacs
|
||||
All files should contain the magic header to insure standard indentation:
|
||||
|
||||
(add-hook 'c-mode-common-hook '(lambda ()
|
||||
(c-set-style "cc-mode"))))
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
|
||||
This sets indentation to the cc-mode defaults. (Verilator predates a
|
||||
CC-mode change of several years ago which overrides the defaults with GNU
|
||||
style indentation; the c-set-style undoes that.)
|
||||
|
||||
=head2 The C<astgen> script
|
||||
|
||||
Some of the code implementing passes is extremely repetitive, and must be
|
||||
implemented for each sub-class of C<AstNode>. However, while repetitive,
|
||||
there is more variability than can be handled in C++ macros.
|
||||
|
||||
In Verilator this is implemented by using a Perl script, C<astgen> to
|
||||
pre-process the C++ code. For example in C<V3Const.cpp> this is used to
|
||||
implement the C<visit()> functions for each binary operation using the
|
||||
TREEOP macro.
|
||||
|
||||
The original C++ source code is transformed into C++ code in the C<obj_opt>
|
||||
and C<obj_dbg> sub-directories (the former for the optimized version of
|
||||
Verilator, the latter for the debug version). So for example C<V3Const.cpp>
|
||||
into C<V3Const__gen.cpp>.
|
||||
|
||||
=head2 Visitor Functions
|
||||
|
||||
There's three ways data is passed between visitor functions.
|
||||
Verilator uses the I<Visitor> design pattern to implement its refinement
|
||||
and optimization passes. This allows separation of the pass algorithm from
|
||||
the AST on which it operates. Wikipedia provides an introduction to the
|
||||
concept at L<http://en.wikipedia.org/wiki/Visitor_pattern>.
|
||||
|
||||
1. A visitor-class member variable. This is generally for passing "parent"
|
||||
information down to children. m_modp is a common example. It's set to
|
||||
NULL in the constructor, where that node (AstModule visitor) sets it, then
|
||||
the children are iterated, then it's cleared. Children under an AstModule
|
||||
will see it set, while nodes elsewhere will see it clear. If there can be
|
||||
nested items (for example an AstFor under an AstFor) the variable needs to
|
||||
be save-set-restored in the AstFor visitor, otherwise exiting the lower for
|
||||
will loose the upper for's setting.
|
||||
As noted above, all visitors are derived classes of C<AstNvisitor>. All
|
||||
derived classes of C<AstNode> implement the C<accept> method, which takes
|
||||
as argument a reference to an instance or a C<AstNVisitor> derived class
|
||||
and applies the visit method of the C<AstNVisitor> to the invoking AstNode
|
||||
instance (i.e. C<this>).
|
||||
|
||||
One possible difficulty is that a call to C<accept> may perform an edit
|
||||
which destroys the node it receives as argument. The
|
||||
C<acceptSubtreeReturnEdits> method of C<AstNode> is provided to apply
|
||||
C<accept> and return the resulting node, even if the original node is
|
||||
destroyed (if it is not destroyed it will just return the original node).
|
||||
|
||||
The behavior of the visitor classes is achieved by overloading the C<visit>
|
||||
function for the different C<AstNode> derived classes. If a specific
|
||||
implementation is not found, the system will look in turn for overloaded
|
||||
implementations up the inheritance hierarchy. For example calling C<accept>
|
||||
on C<AstIf> will look in turn for:
|
||||
|
||||
void visit (AstIf* nodep, AstNUser* vup)
|
||||
void visit (AstNodeIf* nodep, AstNUser* vup)
|
||||
void visit (AstNodeStmt* nodep, AstNUser* vup)
|
||||
void visit (AstNode* nodep, AstNUser* vup)
|
||||
|
||||
There are three ways data is passed between visitor functions.
|
||||
|
||||
=over 4
|
||||
|
||||
=item 1.
|
||||
|
||||
A visitor-class member variable. This is generally for passing "parent"
|
||||
information down to children. C<m_modp> is a common example. It's set to
|
||||
NULL in the constructor, where that node (C<AstModule> visitor) sets it,
|
||||
then the children are iterated, then it's cleared. Children under an
|
||||
C<AstModule> will see it set, while nodes elsewhere will see it clear. If
|
||||
there can be nested items (for example an C<AstFor> under an C<AstFor>) the
|
||||
variable needs to be save-set-restored in the C<AstFor> visitor, otherwise
|
||||
exiting the lower for will lose the upper for's setting.
|
||||
|
||||
=item 2.
|
||||
|
||||
User attributes. Each C<AstNode> (B<Note.> The AST node, not the visitor)
|
||||
has five user attributes, which may be accessed as an integer using the
|
||||
C<user1()> through C<user5()> methods, or as a pointer (of type
|
||||
C<AstNuser>) using the C<user1p()> through C<user5p()> methods (a common
|
||||
technique lifted from graph traversal packages).
|
||||
|
||||
2. User() attributes. Each node has 5 ->user() number or ->userp() pointer
|
||||
utility values (a common technique lifted from graph traversal packages).
|
||||
A visitor first clears the one it wants to use by calling
|
||||
AstNode::user#ClearTree(), then it can mark any node's user() with whatever
|
||||
data it wants. Readers just call nodep->user(), but may need to cast
|
||||
appropriately, so you'll often see nodep->userp()->castSOMETYPE(). At the
|
||||
top of each visitor are comments describing how the user() stuff applies to
|
||||
that visitor class. For example:
|
||||
C<AstNode::user#ClearTree()>, then it can mark any node's user() with whatever
|
||||
data it wants. Readers just call C<< nodep->user() >>, but may need to cast
|
||||
appropriately, so you'll often see C<< nodep->userp()->castSOMETYPE() >>. At
|
||||
the top of each visitor are comments describing how the C<user()> stuff
|
||||
applies to that visitor class. For example:
|
||||
|
||||
// NODE STATE
|
||||
// Cleared entire netlist
|
||||
// AstModule::user1p() // bool. True to inline this module
|
||||
|
||||
This says that at the AstNetlist user1ClearTree() is called. Each
|
||||
AstModule's is user1() is used to indicate if we're going to inline it.
|
||||
This says that at the C<AstNetlist> C<user1ClearTree()> is called. Each
|
||||
C<AstModule>'s C<user1()> is used to indicate if we're going to inline it.
|
||||
|
||||
These comments are important to make sure a user#() on a given AstNode type
|
||||
is never being used for two different purposes.
|
||||
These comments are important to make sure a C<user#()> on a given C<AstNode>
|
||||
type is never being used for two different purposes.
|
||||
|
||||
Note that calling user#ClearTree is fast, it doesn't walk the tree, so it's
|
||||
ok to call fairly often. For example, it's commonly called on every
|
||||
Note that calling C<user#ClearTree> is fast, it doesn't walk the tree, so
|
||||
it's ok to call fairly often. For example, it's commonly called on every
|
||||
module.
|
||||
|
||||
3. Parameters can be passed between the visitors in close to the "normal"
|
||||
function caller to callee way. This is the second "vup" parameter that is
|
||||
ignored on most of the visitor functions. V3Width does this, but it proved
|
||||
more messy than the above and is deprecated. (V3Width was nearly the first
|
||||
module written. Someday this scheme may be removed, as it slows the
|
||||
program down to have to pass vup everywhere.)
|
||||
=item 3.
|
||||
|
||||
Parameters can be passed between the visitors in close to the "normal"
|
||||
function caller to callee way. This is the second C<vup> parameter of type
|
||||
C<AstNuser> that is ignored on most of the visitor functions. V3Width does
|
||||
this, but it proved more messy than the above and is deprecated. (V3Width
|
||||
was nearly the first module written. Someday this scheme may be removed,
|
||||
as it slows the program down to have to pass vup everywhere.)
|
||||
|
||||
=back
|
||||
|
||||
=head2 Iterators
|
||||
|
||||
C<AstNode> provides a set of iterators to facilitate walking over the
|
||||
tree. Each takes two arguments, a visitor, C<v>, of type C<AstNVisitor> and
|
||||
an optional pointer user data, C<vup>, of type C<AstNuser*>. The second is
|
||||
one of the ways to pass parameters to visitors described in L</Visitor
|
||||
Functions>, but its use is no deprecated and should be used for new visitor
|
||||
classes.
|
||||
|
||||
=over 4
|
||||
|
||||
=item C<iterate()>
|
||||
|
||||
This just applies the C<accept> method of the C<AstNode> to the visitor
|
||||
function.
|
||||
|
||||
=item C<iterateAndNextIgnoreEdit>
|
||||
|
||||
Applies the C<accept> method of each C<AstNode> in a list (i.e. connected
|
||||
by C<nextp> and C<backp> pointers).
|
||||
|
||||
=item C<iterateAndNext>
|
||||
|
||||
Applies the C<accept> method of each C<AstNode> in a list. If a node is
|
||||
edited by the call to C<accept>, apply C<accept> again, until the node does
|
||||
not change.
|
||||
|
||||
=item C<iterateListBackwards>
|
||||
|
||||
Applies the C<accept> method of each C<AstNode> in a list, starting with
|
||||
the last one.
|
||||
|
||||
=item C<iterateChildren>
|
||||
|
||||
Apply the C<iterateAndNext> method on each child C<op1p> through C<op4p> in
|
||||
turn.
|
||||
|
||||
=item C<iterateChildrenBackwards>
|
||||
|
||||
Apply the C<iterateListBackwards> method on each child C<op1p> through
|
||||
C<op4p> in turn.
|
||||
|
||||
=back
|
||||
|
||||
=head2 Identifying derived classes
|
||||
|
||||
A common requirement is to identify the specific C<AstNode> class we are
|
||||
dealing with. For example a visitor might not implement separate C<visit>
|
||||
methods for C<AstIf> and C<AstGenIf>, but just a single method for the base
|
||||
class:
|
||||
|
||||
void visit (AstNodeIf* nodep, AstNUser* vup)
|
||||
|
||||
However that method might want to specify additional code if it is called
|
||||
for C<AstGenIf>. Verilator does this by providing a C<castSOMETYPE()>
|
||||
method for each possible node type, using C++ C<dynamic_cast>. This either
|
||||
returns a pointer to the object cast to that type (if it is of class
|
||||
C<SOMETYPE>, or a derived class of C<SOMETYPE>) or else NULL. So our
|
||||
C<visit> method could use:
|
||||
|
||||
if (nodep->castAstGenIf()) {
|
||||
<code specific to AstGenIf>
|
||||
}
|
||||
|
||||
A common test is for C<AstNetlist>, which is the node at the root of the
|
||||
AST.
|
||||
|
||||
=head1 TESTING
|
||||
|
||||
To write a test see notes in the forum and in the verilator.txt manual.
|
||||
For an overview of how to write a test see the BUGS section of the
|
||||
Verilator primary manual.
|
||||
|
||||
Note you can run the regression tests in parallel; see the
|
||||
test_regress/driver.pl script -j flag.
|
||||
It is important to add tests for failures as well as success (for example to
|
||||
check that an error message is correctly triggered).
|
||||
|
||||
Tests that fail should by convenition have the suffix C<_bad> in their name,
|
||||
and include C<fails =E<gt> 1> in either their C<compile> or C<execute> step as
|
||||
appropriate.
|
||||
|
||||
=head2 Controlling the Test Driver
|
||||
|
||||
Test drivers are written in PERL. All invoke the main test driver script,
|
||||
which can provide detailed help on all the features available when writing
|
||||
a test driver.
|
||||
|
||||
test_regress/t/driver.pl --help
|
||||
|
||||
For convenience, a summary of the most commonly used features is provided
|
||||
here. All drivers require a call to C<compile> subroutine to compile the
|
||||
test. For run-time tests, this is followed by a call to the C<execute>
|
||||
subroutine. Both of these functions can optionally be provided with a hash
|
||||
table as argument specifying additonal options.
|
||||
|
||||
The test driver assumes by default that the source Verilog file name
|
||||
matches the PERL driver name. So a test whose driver is C<t/t_mytest.pl>
|
||||
will expect a Verilog source file C<t/t_mytest.v>. This can be changed
|
||||
using the C<top_filename> subroutine, for example
|
||||
|
||||
top_filename("t/t_myothertest.v");
|
||||
|
||||
By default all tests will run with major simulators (Icarus Verilog, NC,
|
||||
VCS, ModelSim) as well as Verilator, to allow results to be
|
||||
compared. However if you wish a test only to be used with Verilator, you
|
||||
can use the following:
|
||||
|
||||
$Self->{vlt} or $Self->skip("Verilator only test");
|
||||
|
||||
Of the many options that can be set through arguments to C<compiler> and
|
||||
C<execute>, the following are particularly useful:
|
||||
|
||||
=over 4
|
||||
|
||||
=item C<verilator_flags2>
|
||||
|
||||
A list of flags to be passed to verilator when compiling.
|
||||
|
||||
=item C<fails>
|
||||
|
||||
Set to 1 to indicate that the compilation or execution is intended to fail.
|
||||
|
||||
=back
|
||||
|
||||
For example the following would specify that compilation requires two
|
||||
defines and is expected to fail.
|
||||
|
||||
compile (
|
||||
verilator_flags2 => ["-DSMALL_CLOCK -DGATED_COMMENT"],
|
||||
fails => 1,
|
||||
);
|
||||
|
||||
=head2 Regression Testing for Developers
|
||||
|
||||
Developers will also want to call ./configure with two extra flags:
|
||||
|
||||
=over 4
|
||||
|
||||
=item --enable-ccwarn
|
||||
|
||||
Causes the build to stop on warnings as well as errors. A good way to
|
||||
ensure no sloppy code gets added, however it can be painful when it comes
|
||||
to testing, since third party code used in the tests (e.g. SystemC) may not
|
||||
be warning free.
|
||||
|
||||
=item --enable-longtests
|
||||
|
||||
In addition to the standard C, SystemC and SystemPerl tests also run the
|
||||
tests in the C<test_vcs>, C<test_verilated> and C<test_regress> directories
|
||||
when using I<make test>. This is disabled by default as SystemC/SystemPerl
|
||||
installation problems would otherwise falsely indicate a Verilator problem.
|
||||
|
||||
=back
|
||||
|
||||
When enabling the long tests, some additional PERL modules are needed, which
|
||||
you can install using cpan.
|
||||
|
||||
cpan install Unix::Processors
|
||||
|
||||
There are some traps to avoid when running regression tests
|
||||
|
||||
=over 4
|
||||
|
||||
=item *
|
||||
|
||||
The regression tests will assume that you have a version of SystemPerl to
|
||||
match. Typically if working on Verilator from git, also use SystemPerl from
|
||||
git.
|
||||
|
||||
=item *
|
||||
|
||||
When checking the MANIFEST, the test will barf on unexpected code in the
|
||||
Verilator tree. So make sure to keep any such code outside the tree.
|
||||
|
||||
=item *
|
||||
|
||||
Not all Linux systems install Perldoc by default. This is needed for the
|
||||
I<--help> option to Verilator, and also for regression testing. This can be
|
||||
installed using cpan:
|
||||
|
||||
cpan install Pod::Perldoc
|
||||
|
||||
Many Linux systems also offer a standard package for this. Red
|
||||
Hat/Fedora/Centos offer I<perl-Pod-Perldoc>, while Debian/Ubuntu/Linux Mint
|
||||
offer I<perl-doc>.
|
||||
|
||||
=item *
|
||||
|
||||
Running regression may exhaust resources on some Linux systems, particularly
|
||||
file handles and user processes. Increase these to respectively 16,384 and
|
||||
4,096. The method of doing this is system dependent, but on Fedora Linux it
|
||||
would require editing the C</etc/security/limits.conf> file as root.
|
||||
|
||||
=back
|
||||
|
||||
=head1 DEBUGGING
|
||||
|
||||
@@ -207,27 +518,32 @@ viewers let us know; ZGRViewer isn't great for large graphs.
|
||||
Tree files are dumps of the AST Tree and are produced between every major
|
||||
algorithmic stage. An example:
|
||||
|
||||
NETLIST 0x90fb00 <e1> {a0} w0
|
||||
1: MODULE 0x912b20 <e8822> {a8} w0 top L2 [P]
|
||||
*1:2: VAR 0x91a780 <e74#> {a22} w70 out_wide [O] WIRE
|
||||
1:2:1: BASICDTYPE 0x91a3c0 <e73> {a22} w70 [logic]
|
||||
NETLIST 0x90fb00 <e1> {a0}
|
||||
1: MODULE 0x912b20 <e8822> {a8} top L2 [P]
|
||||
*1:2: VAR 0x91a780 <e74#> {a22} @dt=0xa2e640(w32) out_wide [O] WIRE
|
||||
1:2:1: BASICDTYPE 0xa2e640 <e2149> {e24} @dt=this(sw32) integer kwd=integer range=[31:0]
|
||||
|
||||
=over 4
|
||||
|
||||
"1:2:" indicates the hierarchy the VAR is op2p under the MODULE.
|
||||
The following summarizes the above example dump, with more detail on each
|
||||
field in the section below.
|
||||
|
||||
"1:2:" indicates the hierarchy of the C<VAR> is the C<op2p> pointer under
|
||||
the C<MODULE>, which in turn is the C<op1p> pointer under the C<NETLIST>
|
||||
|
||||
"VAR" is the AstNodeType.
|
||||
|
||||
"0x91a780" is the address of this node.
|
||||
|
||||
"<e74>" means the 74th edit to the netlist was the last modification to
|
||||
this node. A trailing # indicates this node changed since the last tree
|
||||
dump was made. You can gdb break on this edit; see below.
|
||||
this node.
|
||||
|
||||
"{a22}" indicates this node is related to line 22 in the source filename
|
||||
"a", where "a" is the first file read, "z" the 36th, and "aa" the 37th.
|
||||
"a", where "a" is the first file read, "z" the 26th, and "aa" the 27th.
|
||||
|
||||
"w70" indicates the width is 70 bits. sw70 would be signed 70 bits.
|
||||
"@dt=0x..." indicates the address of the data type this node contains.
|
||||
|
||||
"w32" indicates the width is 32 bits.
|
||||
|
||||
"out_wide" is the name of the node, in this case the name of the variable.
|
||||
|
||||
@@ -236,22 +552,203 @@ variable is an output.
|
||||
|
||||
=back
|
||||
|
||||
In more detail the following fields are dumped common to all nodes. They
|
||||
are produced by the C<AstNode::dump()> method:
|
||||
|
||||
=over 4
|
||||
|
||||
=item Tree Hierarchy
|
||||
|
||||
The dump lines begin with numbers and colons to indicate the child node
|
||||
hierarchy. As noted above in L</Key Classes Used in the Verilator Flow>,
|
||||
C<AstNode> has lists of items at the same level in the AST, connected by
|
||||
the C<nextp()> and C<prevp()> pointers. These appear as nodes at the same
|
||||
level. For example after inlining:
|
||||
|
||||
NETLIST 0x929c1c8 <e1> {a0} w0
|
||||
1: MODULE 0x92bac80 <e3144> {e14} w0 TOP_t L1 [P]
|
||||
1:1: CELLINLINE 0x92bab18 <e3686#> {e14} w0 v -> t
|
||||
1:1: CELLINLINE 0x92bc1d8 <e3688#> {e24} w0 v__DOT__i_test_gen -> test_gen
|
||||
...
|
||||
1: MODULE 0x92b9bb0 <e503> {e47} w0 test_gen L3
|
||||
...
|
||||
|
||||
=item AstNode type
|
||||
|
||||
The textual name of this node AST type (always in capitals). Many of these
|
||||
correspond directly to Verilog entities (for example C<MODULE> and
|
||||
C<TASK>), but others are internal to Verialtor (for example C<NETLIST> and
|
||||
C<BASICDTYPE>).
|
||||
|
||||
=item Address of the node
|
||||
|
||||
A hexadecimal address of the node in memory. Useful for examining with the
|
||||
debugger.
|
||||
|
||||
=item Last edit number
|
||||
|
||||
Of the form C<< <ennnn> >> or C<< <ennnn#> >> , where C<nnnn> is the number
|
||||
of the last edit to modify this node. The trailing C<#> indicates the node
|
||||
has been edited since the last tree dump (which typically means in the last
|
||||
refinement or optimization pass). GDB can watch for this, see L</Debugging
|
||||
with GDB>.
|
||||
|
||||
=item Source file and line
|
||||
|
||||
Of the form C<< {xxnnnn} >>, where C{xx} is the filename letter (or
|
||||
letters) and C<nnnn> is the line number within that file. The first file is
|
||||
C<a>, the 26th is C<z>, the 27th is C<aa> and so on.
|
||||
|
||||
=item User pointers
|
||||
|
||||
Shows the value of the node's user1p...user5p, if non-NULL.
|
||||
|
||||
=item Data type
|
||||
|
||||
Many nodes have an explicit data type. "@dt=0x..." indicates the address
|
||||
of the data type (AstNodeDType) this node uses.
|
||||
|
||||
If a data type is present and is numberic, it then prints the width of the
|
||||
item. This field is a squence of flag characters and width data as follows:
|
||||
|
||||
C<s> if the node is signed.
|
||||
|
||||
C<d> if the node is a double (i.e a floating point entity).
|
||||
|
||||
C<w> always present, indicating this is the width field.
|
||||
|
||||
C<u> if the node is unsized.
|
||||
|
||||
C</nnnn> if the node is unsized, where C<nnnn> is the minimum width.
|
||||
|
||||
=item Name of the entity represented by the node if it exists
|
||||
|
||||
For example for a C<VAR> it is the name of the variable.
|
||||
|
||||
=back
|
||||
|
||||
Many nodes follow these fields with additional node specific
|
||||
information. Thus the C<VARREF> node will print either C<[LV]> or C<[RV]>
|
||||
to indicate a left value or right value, followed by the node of the
|
||||
variable being referred to. For example:
|
||||
|
||||
1:2:1:1: VARREF 0x92c2598 <e509> {e24} w0 clk [RV] <- VAR 0x92a2e90 <e79> {e18} w0 clk [I] INPUT
|
||||
|
||||
In general, examine the C<dump()> method in C<V3AstNodes.cpp> of the node
|
||||
type in question to determine additional fields that may be printed.
|
||||
|
||||
The C<MODULE> has a list of C<CELLINLINE> nodes referred to by its
|
||||
C<op1p()> pointer, connected by C<nextp()> and C<prevp()> pointers.
|
||||
|
||||
Similarly the C<NETLIST> has a list of modules referred to by its C<op1p()>
|
||||
pointer.
|
||||
|
||||
=head2 Debugging with GDB
|
||||
|
||||
The test_regress/driver.pl script accepts --debug --gdb to start Verilator
|
||||
under gdb. You can also use --debug --gdbbt to just backtrace and then
|
||||
exit gdb.
|
||||
under gdb and break when an error is hit or the program is about to exit.
|
||||
You can also use --debug --gdbbt to just backtrace and then exit gdb. To
|
||||
debug the Verilated executable, use --gdbsim.
|
||||
|
||||
If you wish to start Verilator under GDB (or another debugger), then you
|
||||
can use --debug and look at the underlying invocation of verilator_dgb. For
|
||||
example
|
||||
|
||||
t/t_alw_dly.pl --debug
|
||||
|
||||
shows it invokes the command:
|
||||
|
||||
../verilator_bin_dbg --prefix Vt_alw_dly --x-assign unique --debug
|
||||
-cc -Mdir obj_dir/t_alw_dly --debug-check -f input.vc t/t_alw_dly.v
|
||||
|
||||
Start GDB, then C<start> with the remaining arguments.
|
||||
|
||||
gdb ../verilator_bin_dbg
|
||||
...
|
||||
(gdb) start --prefix Vt_alw_dly --x-assign unique --debug -cc -Mdir
|
||||
obj_dir/t_alw_dly --debug-check -f input.vc t/t_alw_dly.v
|
||||
> obj_dir/t_alw_dly/vlt_compile.log
|
||||
...
|
||||
Temporary breakpoint 1, main (argc=13, argv=0xbfffefa4, env=0xbfffefdc)
|
||||
at ../Verilator.cpp:615
|
||||
615 ios::sync_with_stdio();
|
||||
(gdb)
|
||||
|
||||
You can then continue execution with breakpoints as required.
|
||||
|
||||
To break at a specific edit number which changed a node (presumably to find
|
||||
what made a <e####> line in the tree dumps):
|
||||
|
||||
watch AstNode::s_editCntGbl==####
|
||||
|
||||
To print a node:
|
||||
|
||||
pn nodep
|
||||
# or: call nodep->dumpGdb() # aliased to "pn" in src/.gdbinit
|
||||
pnt nodep
|
||||
# or: call nodep->dumpTreeGdb() # aliased to "pnt" in src/.gdbinit
|
||||
|
||||
When GDB halts, it is useful to understand that the backtrace will commonly
|
||||
show the iterator functions between each invocation of C<visit> in the
|
||||
backtrace. You will typically see a frame sequence something like
|
||||
|
||||
...
|
||||
visit()
|
||||
iterateChildren()
|
||||
iterateAndNext()
|
||||
accept()
|
||||
visit()
|
||||
...
|
||||
|
||||
=head1 ADDING A NEW FEATURE
|
||||
|
||||
Generally what would you do to add a new feature?
|
||||
|
||||
=over 4
|
||||
|
||||
=item 1.
|
||||
|
||||
File a bug (if there isn't already) so others know what you're working on.
|
||||
|
||||
=item 2.
|
||||
|
||||
Make a testcase in the test_regress/t/t_EXAMPLE format, see L<TESTING>.
|
||||
|
||||
=item 3.
|
||||
|
||||
If grammar changes are needed, look at the git version of VerilogPerl's
|
||||
src/VParseGrammar.y, as this grammar supports the full SystemVerilog
|
||||
language and has a lot of back-and-forth with Verilator's grammar. Copy
|
||||
the appropriate rules to src/verilog.y and modify the productions.
|
||||
|
||||
=item 4.
|
||||
|
||||
If a new Ast type is needed, add it to V3AstNodes.h.
|
||||
|
||||
=back
|
||||
|
||||
Now you can run "test_regress/t/t_{new testcase}.pl --debug" and it'll
|
||||
probably fail but you'll see a test_regress/obj_dir/t_{newtestcase}/*.tree
|
||||
file which you can examine to see if the parsing worked. See also the
|
||||
sections above on debugging.
|
||||
|
||||
Modify the later visitor functions to process the new feature as needed.
|
||||
|
||||
=head2 Adding a new pass
|
||||
|
||||
For more substantial changes you may need to add a new pass. The simplest way
|
||||
to do this is to copy the C<.cpp> and C<.h> files from an existing
|
||||
pass. You'll need to add a call into your pass from the C<process()> function
|
||||
in C<src/verilator.cpp>.
|
||||
|
||||
To get your pass to build you'll need to add its binary filename to the list
|
||||
in C<src/Makefile_obj.in> and reconfigure.
|
||||
|
||||
=head1 DISTRIBUTION
|
||||
|
||||
The latest version is available from L<http://www.veripool.org/>.
|
||||
|
||||
Copyright 2008-2011 by Wilson Snyder. Verilator is free software; you can
|
||||
Copyright 2008-2013 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.
|
||||
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/perl -w
|
||||
######################################################################
|
||||
#
|
||||
# Copyright 2007-2011 by Wilson Snyder. This package is free software; you
|
||||
# Copyright 2007-2013 by Wilson Snyder. This package is free software; you
|
||||
# can redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/perl -w
|
||||
######################################################################
|
||||
#
|
||||
# Copyright 2007-2011 by Wilson Snyder. This package is free software; you
|
||||
# Copyright 2007-2013 by Wilson Snyder. This package is free software; you
|
||||
# can redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
+1
-1
@@ -143,7 +143,7 @@ Displays this message and program version and exits.
|
||||
|
||||
=head1 DISTRIBUTION
|
||||
|
||||
Copyright 2005-2011 by Wilson Snyder. Verilator is free software; you can
|
||||
Copyright 2005-2013 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.
|
||||
|
||||
|
||||
+1
-1
@@ -184,7 +184,7 @@ Displays this message and program version and exits.
|
||||
|
||||
=head1 DISTRIBUTION
|
||||
|
||||
Copyright 2005-2011 by Wilson Snyder. Verilator is free software; you can
|
||||
Copyright 2005-2013 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.
|
||||
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/perl -w
|
||||
######################################################################
|
||||
#
|
||||
# Copyright 2007-2011 by Wilson Snyder. This package is free software; you
|
||||
# Copyright 2007-2013 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.
|
||||
|
||||
+24
-2
@@ -13,6 +13,7 @@ use vars qw ($Debug);
|
||||
# main
|
||||
|
||||
our $Opt_Stage = 0;
|
||||
our $Opt_Jobs = calc_jobs();
|
||||
|
||||
autoflush STDOUT 1;
|
||||
autoflush STDERR 1;
|
||||
@@ -21,11 +22,13 @@ if (! GetOptions (
|
||||
"debug" => sub { $Debug = 1; },
|
||||
"<>" => sub { die "%Error: Unknown parameter: $_[0]\n"; },
|
||||
"stage=i" => \$Opt_Stage,
|
||||
"j=i" => \$Opt_Jobs,
|
||||
)) {
|
||||
die "%Error: Bad usage, try 'install_test --help'\n";
|
||||
}
|
||||
|
||||
test();
|
||||
exit(0);
|
||||
|
||||
#######################################################################
|
||||
|
||||
@@ -47,7 +50,7 @@ sub test {
|
||||
run("/bin/rm -rf $blddir");
|
||||
run("/bin/mkdir -p $blddir");
|
||||
run("cd $blddir && $srcdir/configure --prefix $prefix");
|
||||
run("cd $blddir && make -j");
|
||||
run("cd $blddir && make -j $Opt_Jobs");
|
||||
}
|
||||
|
||||
# Install it under the prefix
|
||||
@@ -121,6 +124,16 @@ sub cleanenv {
|
||||
|
||||
#######################################################################
|
||||
|
||||
sub calc_jobs {
|
||||
my $ok = eval "
|
||||
use Unix::Processors;
|
||||
return Unix::Processors->new->max_online;
|
||||
";
|
||||
$ok && !$@ or return 1;
|
||||
print "driver.pl: Found $ok cores, using -j ",$ok+1,"\n" if $Debug;
|
||||
return $ok + 1;
|
||||
}
|
||||
|
||||
sub run {
|
||||
# Run a system command, check errors
|
||||
my $command = shift;
|
||||
@@ -157,11 +170,20 @@ required.
|
||||
|
||||
Displays this message and program version and exits.
|
||||
|
||||
=item -j I<jobs>
|
||||
|
||||
Specify make -j flag. Defaults to number of cores + 1 if Perl's
|
||||
Unix::Processors is installed, else 1.
|
||||
|
||||
=item -stage I<stage>
|
||||
|
||||
Runs a specific test stage (see the script).
|
||||
|
||||
=back
|
||||
|
||||
=head1 DISTRIBUTION
|
||||
|
||||
Copyright 2009-2011 by Wilson Snyder. This package is free software; you
|
||||
Copyright 2009-2013 by Wilson Snyder. This package is free software; you
|
||||
can redistribute it and/or modify it under the terms of either the GNU
|
||||
Lesser General Public License Version 3 or the Perl Artistic License
|
||||
Version 2.0.
|
||||
|
||||
+1
-1
@@ -28,7 +28,7 @@ invoke_atsim - Invoke tool under "modules" command
|
||||
|
||||
=head1 DISTRIBUTION
|
||||
|
||||
Copyright 2005-2011 by Wilson Snyder. This package is free software; you
|
||||
Copyright 2005-2013 by Wilson Snyder. This package is free software; you
|
||||
can redistribute it and/or modify it under the terms of either the GNU
|
||||
Lesser General Public License Version 3 or the Perl Artistic License
|
||||
Version 2.0.
|
||||
|
||||
+1
-1
@@ -28,7 +28,7 @@ invoke_iccr - Invoke tool under "modules" command
|
||||
|
||||
=head1 DISTRIBUTION
|
||||
|
||||
Copyright 2007-2011 by Wilson Snyder. This package is free software; you
|
||||
Copyright 2007-2013 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.
|
||||
|
||||
@@ -28,7 +28,7 @@ invoke_ncverilog - Invoke tool under "modules" command
|
||||
|
||||
=head1 DISTRIBUTION
|
||||
|
||||
Copyright 2005-2011 by Wilson Snyder. This package is free software; you
|
||||
Copyright 2005-2013 by Wilson Snyder. This package is free software; you
|
||||
can redistribute it and/or modify it under the terms of either the GNU
|
||||
Lesser General Public License Version 3 or the Perl Artistic License
|
||||
Version 2.0.
|
||||
|
||||
+1
-1
@@ -28,7 +28,7 @@ invoke_vcs - Invoke tool under "modules" command
|
||||
|
||||
=head1 DISTRIBUTION
|
||||
|
||||
Copyright 2005-2011 by Wilson Snyder. This package is free software; you
|
||||
Copyright 2005-2013 by Wilson Snyder. This package is free software; you
|
||||
can redistribute it and/or modify it under the terms of either the GNU
|
||||
Lesser General Public License Version 3 or the Perl Artistic License
|
||||
Version 2.0.
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/perl -w
|
||||
######################################################################
|
||||
#
|
||||
# Copyright 2010-2011 by Wilson Snyder. This package is free software; you
|
||||
# Copyright 2010-2013 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.
|
||||
|
||||
@@ -331,7 +331,7 @@ Displays this message and program version and exits.
|
||||
|
||||
=head1 DISTRIBUTION
|
||||
|
||||
Copyright 2005-2011 by Wilson Snyder. Verilator is free software; you can
|
||||
Copyright 2005-2013 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.
|
||||
|
||||
|
||||
+22
-30
@@ -9,7 +9,7 @@ This is the Verilator Package README file.
|
||||
|
||||
=head1 DISTRIBUTION
|
||||
|
||||
This package is Copyright 2003-2011 by Wilson Snyder. (Report bugs to
|
||||
This package is Copyright 2003-2013 by Wilson Snyder. (Report bugs to
|
||||
L<http://www.veripool.org/>.)
|
||||
|
||||
Verilator is free software; you can redistribute it and/or modify it under
|
||||
@@ -24,14 +24,14 @@ more details.
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Verilator converts synthesizable (not behavioral) Verilog code into C++ or
|
||||
SystemC code. It is not a complete simulator, just a translator.
|
||||
Verilator converts synthesizable (generally not behavioral) Verilog code
|
||||
into C++ or SystemC code. It is not a complete simulator, just a
|
||||
translator.
|
||||
|
||||
Verilator is invoked with parameters similar to GCC or Synopsys's VCS. It
|
||||
reads the specified Verilog code, lints it, and optionally adds coverage
|
||||
code. For C++ format, it outputs .cpp and .h files. For SystemC format,
|
||||
it outputs .sp files for the SystemPerl preprocessor available at
|
||||
http://www.veripool.org.
|
||||
it outputs .cpp and .h files using the standard SystemC headers.
|
||||
|
||||
The resulting files are then compiled with C++. The user writes a little
|
||||
C++ wrapper file, which instantiates the top level module. This is
|
||||
@@ -41,14 +41,11 @@ The resulting executable will perform the actual simulation.
|
||||
|
||||
=head1 SUPPORTED SYSTEMS
|
||||
|
||||
Verilator is developed and has primary testing on:
|
||||
|
||||
SuSE 11.1 AMD64 i686-linux-2.6.27, GCC 4.3.2
|
||||
|
||||
Versions have also built on Redhat Linux, Macs OS-X, HPUX and Solaris. It
|
||||
should run with minor porting on any Linix-ish platform. Verilator also
|
||||
works on Windows under Cygwin, and Windows under MinGW (gcc -mno-cygwin).
|
||||
Verilated output (not Verilator itself) compiles under MSVC++ 2008.
|
||||
Verilator is developed and has primary testing on Ubuntu. Versions have
|
||||
also built on Redhat Linux, Macs OS-X, HPUX and Solaris. It should run
|
||||
with minor porting on any Linix-ish platform. Verilator also works on
|
||||
Windows under Cygwin, and Windows under MinGW (gcc -mno-cygwin). Verilated
|
||||
output (not Verilator itself) compiles under MSVC++ 2008 and newer.
|
||||
|
||||
=head1 INSTALLATION
|
||||
|
||||
@@ -71,15 +68,11 @@ Download the latest package from that site, and decompress.
|
||||
=item
|
||||
|
||||
If you will be using SystemC (vs straight C++ output), download SystemC
|
||||
2.0.1 from L<http://www.systemc.org>. Follow their installation
|
||||
instructions. You will need to set the SYSTEMC environment variable to
|
||||
point to this download. Also, setenv SYSTEMC_ARCH to the architecture name
|
||||
you used with SystemC, generally 'linux' or 'cygwin'.
|
||||
|
||||
Verilator assumes you did a make in the SystemC kit directory and SYSTEMC
|
||||
points to that directory. There must be appropriate files in
|
||||
C<$SYSTEMC/include> and C<$SYSTEMC/lib-linux> for SystemC compilation to
|
||||
work.
|
||||
from L<http://www.systemc.org>. Follow their installation instructions.
|
||||
You will need to set SYSTEMC_INCLUDE to point to the include directory with
|
||||
systemc.h in it, and SYSTEMC_LIBDIR to points to the directory with
|
||||
libsystemc.a in it. (Older installations may set SYSTEMC and SYSTEMC_ARCH
|
||||
instead.)
|
||||
|
||||
=item
|
||||
|
||||
@@ -101,8 +94,8 @@ C<cd> to the Verilator directory containing this README.
|
||||
|
||||
You now have to decide how you're going to eventually install the kit.
|
||||
|
||||
Note Verilator builds the current value of VERILATOR_ROOT, SYSTEMC,
|
||||
SYSTEMC_ARCH, SYSTEMPERL, and SYSTEMPERL_INCLUDE as defaults into the
|
||||
Note Verilator builds the current value of VERILATOR_ROOT, SYSTEMC_INCLUDE,
|
||||
SYSTEMC_LIBDIR, SYSTEMPERL, and SYSTEMPERL_INCLUDE as defaults into the
|
||||
executable, so try to have them correct before configuring.
|
||||
|
||||
=over 4
|
||||
@@ -111,7 +104,7 @@ executable, so try to have them correct before configuring.
|
||||
|
||||
Our personal favorite is to always run Verilator from the kit directory.
|
||||
This allows the easiest experimentation and upgrading. It's also how most
|
||||
EDA tools operate; to run any of them you point to the tarball.
|
||||
EDA tools operate; to run you point to the tarball, no install is needed.
|
||||
|
||||
export VERILATOR_ROOT=`pwd` # if your shell is bash
|
||||
setenv VERILATOR_ROOT `pwd` # if your shell is csh
|
||||
@@ -160,11 +153,10 @@ PATH.
|
||||
|
||||
Type C<make> to compile Verilator.
|
||||
|
||||
Type C<make test_c> to check the compilation.
|
||||
Type C<make test> to check the compilation.
|
||||
|
||||
Type C<make test> for a more complete test. You may get a error about the
|
||||
Bit::Vector Perl package. You will need to install it and SystemPerl if
|
||||
you want all tests to pass.
|
||||
Configure with C<--enable-longtests> for more complete developer tests.
|
||||
Additional packages may be required for these tests.
|
||||
|
||||
You may get a error about a typedef conflict for uint32_t. Edit
|
||||
verilated.h to change the typedef to work, probably to @samp{typedef
|
||||
@@ -199,7 +191,7 @@ The directories in the kit after de-taring are as follows:
|
||||
bin/verilator => Compiler Wrapper invoked to Verilate code
|
||||
include/ => Files that should be in your -I compiler path
|
||||
include/verilated*.cpp => Global routines to link into your simulator
|
||||
include/verilated.h => Global headers
|
||||
include/verilated*.h => Global headers
|
||||
include/verilated.v => Stub defines for linting
|
||||
include/verilated.mk => Common makefile
|
||||
src/ => Translator source code
|
||||
|
||||
-197
@@ -1,197 +0,0 @@
|
||||
\input texinfo @c -*-texinfo-*-
|
||||
@c %**start of header
|
||||
@setfilename readme.info
|
||||
@settitle Verilator Installation
|
||||
@c %**end of header
|
||||
|
||||
@c DESCRIPTION: TexInfo: DOCUMENT source run through texinfo to produce README file
|
||||
@c Use 'make README' to produce the output file
|
||||
@c Before release, run C-u C-c C-u C-a (texinfo-all-menus-update)
|
||||
|
||||
@node Top, Copyright, (dir), (dir)
|
||||
@chapter Verilator
|
||||
|
||||
This is the Verilator Package.
|
||||
|
||||
@menu
|
||||
* Copyright::
|
||||
* Description::
|
||||
* Obtaining Distribution::
|
||||
* Directory Structure::
|
||||
* Supported Systems::
|
||||
* Installation::
|
||||
* Limitations::
|
||||
@end menu
|
||||
|
||||
@node Copyright, Description, Top, Top
|
||||
@section Copyright
|
||||
|
||||
This package is Copyright 2003-2011 by Wilson Snyder @email{wsnyder@@wsnyder.org}.
|
||||
|
||||
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. (See the
|
||||
documentation for more details.)
|
||||
|
||||
This program is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
@node Description, Obtaining Distribution, Copyright, Top
|
||||
@section Description
|
||||
|
||||
Verilator converts synthesizable (not behavioral) Verilog code into C++ or
|
||||
SystemC code. It is not a complete simulator, just a translator.
|
||||
|
||||
Verilator is invoked with parameters similar to GCC or Synopsys's VCS. It
|
||||
reads the specified Verilog code, lints it, and optionally adds coverage
|
||||
code. For C++ format, it outputs .cpp and .h files. For SystemC format,
|
||||
it outputs .sp files for the SystemPerl preprocessor available at
|
||||
http://www.veripool.org.
|
||||
|
||||
The resulting files are then compiled with C++. The user writes a little
|
||||
C++ wrapper file, which instantiates the top level module. This is
|
||||
compiled in C++, and linked with the Verilated files.
|
||||
|
||||
The resulting executable will perform the actual simulation.
|
||||
|
||||
@node Obtaining Distribution, Directory Structure, Description, Top
|
||||
@section Obtaining Distribution
|
||||
|
||||
The latest version is available at
|
||||
@uref{http://www.veripool.org/verilator}
|
||||
|
||||
Download the latest package from that site, and decompress.
|
||||
@samp{tar xvzf verilator_version.tgz}
|
||||
|
||||
@node Directory Structure, Supported Systems, Obtaining Distribution, Top
|
||||
@section Directory Structure
|
||||
|
||||
The directories after de-taring are as follows:
|
||||
|
||||
@itemize @bullet
|
||||
@item bin/verilator => Compiler Wrapper invoked on user Verilog code
|
||||
@item include/ => Files that should be in your -I compiler path
|
||||
@item include/verilated.cpp => Global routines to link into your simulator
|
||||
@item include/verilated.h => Global headers
|
||||
@item include/verilated.v => Stub defines for linting
|
||||
@item include/verilated.mk => Common makefile
|
||||
@item src/ => Translator source code
|
||||
@item test_v => Example Verilog code for other test dirs
|
||||
@item test_c => Example Verilog->C++ conversion
|
||||
@item test_sc => Example Verilog->SystemC conversion
|
||||
@item test_sp => Example Verilog->SystemPerl conversion
|
||||
@item test_vcs => Example Verilog->VCS conversion (test the test)
|
||||
@item test_verilated => Internal tests
|
||||
@item test_regress => Internal tests
|
||||
@end itemize
|
||||
|
||||
@node Supported Systems, Installation, Directory Structure, Top
|
||||
@section Supported Systems
|
||||
|
||||
This version of verilator has been built and tested on:
|
||||
|
||||
@itemize @bullet
|
||||
@item SuSE AMD64 i686-linux-2.6.5
|
||||
@end itemize
|
||||
|
||||
Other users report success with Redhat Linux 2.4, Windows under
|
||||
Cygwin, HPUX and Solaris. It should run with minor porting on any
|
||||
Unix system.
|
||||
|
||||
@node Installation, Limitations, Supported Systems, Top
|
||||
@section Installation
|
||||
|
||||
@enumerate
|
||||
@item
|
||||
If you will be using SystemC (vs straight C++ output), download
|
||||
SystemC 2.0.1 from @url{http://www.systemc.org}. Follow their
|
||||
installation instructions. As described in the System-Perl README,
|
||||
you will need to set SYSTEMC and/or SYSTEMC_KIT to point to this
|
||||
download. Also, set SYSTEMC_ARCH to the architecture name you used
|
||||
with SystemC, generally 'linux' or 'cygwin'.
|
||||
|
||||
@item
|
||||
If you will be using SystemC, download and install Verilog-Perl,
|
||||
@url{http://search.cpan.org/search?module=Verilog::Language}.
|
||||
|
||||
@item
|
||||
If you will be using SystemC, download and install System-Perl,
|
||||
@url{http://search.cpan.org/search?module=SystemC::Netlist}. Note
|
||||
you'll need to set a @samp{SYSTEMPERL} environment variable to point
|
||||
to the downloaded kit. Optionally also set @samp{SYSTEMPERL_INCLUDE}
|
||||
to point to the installed headers.
|
||||
|
||||
@item
|
||||
@code{cd} to the Verilator directory containing this README.
|
||||
|
||||
@item
|
||||
Type @samp{./configure} to configure Verilator for your system.
|
||||
|
||||
If you are configuring Verilator to be part of a RPM or other
|
||||
distribution package system, you may want to use the --enable-defenv
|
||||
configure flag. This will take the current value of VERILATOR_ROOT,
|
||||
SYSTEMC, SYSTEMC_ARCH, SYSTEMPERL, and SYSTEMPERL_INCLUDE and build
|
||||
them as defaults into the executable.
|
||||
|
||||
@item
|
||||
Type @samp{make} to compile Verilator.
|
||||
|
||||
On Cygwin (Windows) you may get a error about libperl.a not being
|
||||
found. You need to copy your perl libraries as follows.
|
||||
|
||||
@enumerate
|
||||
@item
|
||||
Type @samp{perl -MExtUtils::Embed -e ldopts}
|
||||
@item
|
||||
It will show a directory name ending in /CORE. cd to that directory.
|
||||
@item
|
||||
@samp{cp libperl5_6_1.a libperl.a}
|
||||
@item
|
||||
@samp{cp libperl5_6_1.dll libperl.dll}
|
||||
@item
|
||||
@samp{cp libperl5_6_1.def libperl.def}
|
||||
@end enumerate
|
||||
|
||||
@item
|
||||
Type @samp{make test} to check the compilation.
|
||||
|
||||
You may get a error about the Bit::Vector perl package. You will need to install
|
||||
it if you want the tests to pass. (Try @samp{make test_c} for a smaller test that
|
||||
doesn't require it.)
|
||||
|
||||
You may get a error about a typedef conflict for uint32_t. Edit verilated.h to change
|
||||
the typedef to work, probably to @samp{typedef unsigned long uint32_t;}.
|
||||
|
||||
If you get warnings, you might want to edit @samp{include/verilated.mk} to delete the
|
||||
lines that define VK_CPPFLAGS_WALL.
|
||||
|
||||
@item
|
||||
|
||||
There is no installation at present; this package runs from the
|
||||
distribution directory. Programs should set the environment variable
|
||||
VERILATOR_ROOT to point to this distribution, then execute
|
||||
$VERILATOR_ROOT/bin/verilator, which will find the path to all needed
|
||||
files.
|
||||
|
||||
Verilator assumes you did a make in the SystemC kit directory. If not, you will need
|
||||
to populate @samp{$SYSTEMC/include} and @samp{$SYSTEMC/lib-linux} appropriately.
|
||||
|
||||
If you will be modifying Verilator, you will probably want a second
|
||||
stable copy of this kit for others to use while you experiment.
|
||||
|
||||
@item
|
||||
Detailed documentation and the man page can be seen by running:
|
||||
|
||||
bin/verilator --help
|
||||
|
||||
or reading verilator.txt in the same directory as this README.
|
||||
|
||||
@end enumerate
|
||||
|
||||
@node Limitations, , Installation, Top
|
||||
@section Limitations
|
||||
|
||||
See verilator.txt (or execute @samp{bin/verilator --help}) for limitations.
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
# DESCRIPTION: Verilator: GDB startup file with useful defines
|
||||
#
|
||||
# Copyright 2012-2013 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.
|
||||
|
||||
define pn
|
||||
call $arg0->dumpGdb()
|
||||
end
|
||||
document pn
|
||||
Verilator: Print single AstNode NODEP
|
||||
end
|
||||
|
||||
define pnt
|
||||
call $arg0->dumpTreeGdb()
|
||||
end
|
||||
document pnt
|
||||
Verilator: Print AstNode NODEP's tree
|
||||
end
|
||||
|
||||
define dtf
|
||||
call AstNode::dumpTreeFileGdb(0)
|
||||
end
|
||||
document dtf
|
||||
Verilator: Dump AstNode tree to file
|
||||
end
|
||||
|
||||
define watchedit
|
||||
watch AstNode::s_editCntGbl==$arg0
|
||||
end
|
||||
document watchedit
|
||||
Verilator: Create watch on where a edit number is made
|
||||
end
|
||||
+5
-3
@@ -7,7 +7,7 @@
|
||||
#
|
||||
#*****************************************************************************
|
||||
#
|
||||
# Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
# Copyright 2003-2013 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.
|
||||
@@ -65,12 +65,14 @@ dbg: ../verilator_bin_dbg
|
||||
cd obj_dbg && $(MAKE) TGT=../$@ VL_DEBUG=1 -f ../Makefile_obj
|
||||
|
||||
prefiles::
|
||||
|
||||
ifneq ($(UNDER_GIT),) # If local git tree... Else don't burden users
|
||||
prefiles:: config_rev.h
|
||||
ifneq ($(UNDER_GIT),) # If local git tree... Else don't burden users
|
||||
# This output goes into srcdir if locally configured, as we need to distribute it as part of the kit.
|
||||
config_rev.h: ${srcdir}/config_rev.pl ${srcdir}/../.git/logs/HEAD
|
||||
$(PERL) ${srcdir}/config_rev.pl ${srcdir} >$@
|
||||
else
|
||||
config_rev.h: ${srcdir}/config_rev.pl
|
||||
$(PERL) ${srcdir}/config_rev.pl ${srcdir} >$@
|
||||
endif
|
||||
|
||||
maintainer-copy::
|
||||
|
||||
+6
-3
@@ -7,7 +7,7 @@
|
||||
#
|
||||
#*****************************************************************************
|
||||
#
|
||||
# Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
# Copyright 2003-2013 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,7 +27,7 @@ config_srcdir = @srcdir@
|
||||
ifeq ($(config_srcdir),.)
|
||||
srcdir = ..
|
||||
else # Run an experiment
|
||||
ifeq ($(shell -e $(config_srcdir)/../Makefile_obj.in),)
|
||||
ifeq ($(wildcard $(config_srcdir)/../Makefile_obj.in),)
|
||||
srcdir = $(config_srcdir)
|
||||
else
|
||||
srcdir = $(config_srcdir)/..
|
||||
@@ -111,6 +111,8 @@ endif
|
||||
ifeq ($(CFG_WITH_DEFENV),yes)
|
||||
CPPFLAGS += -DDEFENV_SYSTEMC=\"$(SYSTEMC)\"
|
||||
CPPFLAGS += -DDEFENV_SYSTEMC_ARCH=\"$(SYSTEMC_ARCH)\"
|
||||
CPPFLAGS += -DDEFENV_SYSTEMC_INCLUDE=\"$(SYSTEMC_INCLUDE)\"
|
||||
CPPFLAGS += -DDEFENV_SYSTEMC_LIBDIR=\"$(SYSTEMC_LIBDIR)\"
|
||||
CPPFLAGS += -DDEFENV_SYSTEMPERL=\"$(SYSTEMPERL)\"
|
||||
CPPFLAGS += -DDEFENV_SYSTEMPERL_INCLUDE=\"$(SYSTEMPERL_INCLUDE)\"
|
||||
ifeq ($(VERILATOR_ROOT),) # Use what we're given, or intuit
|
||||
@@ -180,6 +182,7 @@ RAW_OBJS = \
|
||||
V3EmitCSyms.o \
|
||||
V3EmitMk.o \
|
||||
V3EmitV.o \
|
||||
V3EmitXml.o \
|
||||
V3Error.o \
|
||||
V3Expand.o \
|
||||
V3File.o \
|
||||
@@ -195,7 +198,6 @@ RAW_OBJS = \
|
||||
V3Inst.o \
|
||||
V3Life.o \
|
||||
V3LifePost.o \
|
||||
V3Link.o \
|
||||
V3LinkCells.o \
|
||||
V3LinkDot.o \
|
||||
V3LinkJump.o \
|
||||
@@ -217,6 +219,7 @@ RAW_OBJS = \
|
||||
V3SplitAs.o \
|
||||
V3Stats.o \
|
||||
V3StatsReport.o \
|
||||
V3String.o \
|
||||
V3Subst.o \
|
||||
V3Table.o \
|
||||
V3Task.o \
|
||||
|
||||
+20
-13
@@ -1,13 +1,12 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: Break always into sensitivity active domains
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2013 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.
|
||||
@@ -163,16 +162,22 @@ public:
|
||||
// Active AssignDly replacement functions
|
||||
|
||||
class ActiveDlyVisitor : public ActiveBaseVisitor {
|
||||
public:
|
||||
enum CheckType { CT_SEQ, CT_COMBO, CT_INITIAL };
|
||||
private:
|
||||
bool m_combo; // Combo logic
|
||||
CheckType m_check; // Combo logic or other
|
||||
AstNode* m_alwaysp; // Always we're under
|
||||
AstNode* m_assignp; // In assign
|
||||
// VISITORS
|
||||
virtual void visit(AstAssignDly* nodep, AstNUser*) {
|
||||
if (m_combo) {
|
||||
if (m_check != CT_SEQ) {
|
||||
// Convert to a non-delayed assignment
|
||||
UINFO(5," ASSIGNDLY "<<nodep<<endl);
|
||||
nodep->v3warn(COMBDLY,"Delayed assignments (<=) in non-clocked (non flop or latch) block; suggest blocking assignments (=).");
|
||||
if (m_check == CT_INITIAL) {
|
||||
nodep->v3warn(INITIALDLY,"Delayed assignments (<=) in initial or final block; suggest blocking assignments (=).");
|
||||
} else {
|
||||
nodep->v3warn(COMBDLY,"Delayed assignments (<=) in non-clocked (non flop or latch) block; suggest blocking assignments (=).");
|
||||
}
|
||||
AstNode* newp = new AstAssign (nodep->fileline(),
|
||||
nodep->lhsp()->unlinkFrBack(),
|
||||
nodep->rhsp()->unlinkFrBack());
|
||||
@@ -181,7 +186,7 @@ private:
|
||||
}
|
||||
}
|
||||
virtual void visit(AstAssign* nodep, AstNUser*) {
|
||||
if (!m_combo) {
|
||||
if (m_check == CT_SEQ) {
|
||||
AstNode* las = m_assignp;
|
||||
m_assignp = nodep;
|
||||
nodep->lhsp()->iterateAndNext(*this);
|
||||
@@ -190,7 +195,7 @@ private:
|
||||
}
|
||||
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
||||
AstVar* varp=nodep->varp();
|
||||
if (!m_combo
|
||||
if (m_check == CT_SEQ
|
||||
&& m_assignp
|
||||
&& !varp->isUsedLoopIdx() // Ignore loop indicies
|
||||
&& !varp->isTemp()
|
||||
@@ -212,9 +217,9 @@ private:
|
||||
}
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
ActiveDlyVisitor(AstNode* nodep, bool combo) {
|
||||
ActiveDlyVisitor(AstNode* nodep, CheckType check) {
|
||||
m_alwaysp = nodep;
|
||||
m_combo = combo;
|
||||
m_check = check;
|
||||
m_assignp = NULL;
|
||||
nodep->accept(*this);
|
||||
}
|
||||
@@ -251,6 +256,7 @@ private:
|
||||
virtual void visit(AstInitial* nodep, AstNUser*) {
|
||||
// Relink to IACTIVE, unless already under it
|
||||
UINFO(4," INITIAL "<<nodep<<endl);
|
||||
ActiveDlyVisitor dlyvisitor (nodep, ActiveDlyVisitor::CT_INITIAL);
|
||||
AstActive* wantactivep = m_namer.getIActive(nodep->fileline());
|
||||
nodep->unlinkFrBack();
|
||||
wantactivep->addStmtsp(nodep);
|
||||
@@ -283,6 +289,7 @@ private:
|
||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||
return;
|
||||
}
|
||||
ActiveDlyVisitor dlyvisitor (nodep, ActiveDlyVisitor::CT_INITIAL);
|
||||
if (!m_scopeFinalp) {
|
||||
m_scopeFinalp = new AstCFunc(nodep->fileline(), "_final", m_namer.scopep());
|
||||
m_scopeFinalp->argTypes(EmitCBaseVisitor::symClassVar());
|
||||
@@ -353,10 +360,10 @@ private:
|
||||
|
||||
// Warn and/or convert any delayed assignments
|
||||
if (combo && !sequent) {
|
||||
ActiveDlyVisitor dlyvisitor (nodep, true);
|
||||
ActiveDlyVisitor dlyvisitor (nodep, ActiveDlyVisitor::CT_COMBO);
|
||||
}
|
||||
else if (!combo && sequent) {
|
||||
ActiveDlyVisitor dlyvisitor (nodep, false);
|
||||
ActiveDlyVisitor dlyvisitor (nodep, ActiveDlyVisitor::CT_SEQ);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstAlways* nodep, AstNUser*) {
|
||||
@@ -394,7 +401,7 @@ private:
|
||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||
} else if (nodep->varrefp()) {
|
||||
// V3LinkResolve should have cleaned most of these up
|
||||
if (nodep->varrefp()->width()>1) nodep->v3error("Unsupported: Non-single bit wide signal pos/negedge sensitivity: "
|
||||
if (!nodep->varrefp()->width1()) nodep->v3error("Unsupported: Non-single bit wide signal pos/negedge sensitivity: "
|
||||
<<nodep->varrefp()->prettyName());
|
||||
m_itemSequent = true;
|
||||
nodep->varrefp()->varp()->usedClock(true);
|
||||
|
||||
+2
-4
@@ -1,14 +1,12 @@
|
||||
// -*- C++ -*-
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: Break always into sensitivity block domains
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2013 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.
|
||||
|
||||
+2
-3
@@ -1,13 +1,12 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: Break always into sensitivity active domains
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2013 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.
|
||||
|
||||
+2
-4
@@ -1,14 +1,12 @@
|
||||
// -*- C++ -*-
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: Break always into sensitivity block domains
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2013 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.
|
||||
|
||||
+5
-4
@@ -1,13 +1,12 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: Collect and print statistics
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2005-2011 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2005-2013 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -63,6 +62,7 @@ private:
|
||||
nodep->displayType(AstDisplayType::DT_WRITE);
|
||||
nodep->fmtp()->text(assertDisplayMessage(nodep, prefix, nodep->fmtp()->text()));
|
||||
AstNode* timesp = nodep->fmtp()->exprsp(); if (timesp) timesp->unlinkFrBack();
|
||||
// cppcheck-suppress nullPointer
|
||||
timesp = timesp->addNext(new AstTime(nodep->fileline()));
|
||||
nodep->fmtp()->exprsp(timesp);
|
||||
if (!nodep->fmtp()->scopeNamep() && nodep->fmtp()->formatScopeTracking()) {
|
||||
@@ -137,6 +137,7 @@ private:
|
||||
if (nodep->castPslAssert()) ifp->branchPred(AstBranchPred::BP_UNLIKELY);
|
||||
//
|
||||
AstNode* newp = new AstAlways (nodep->fileline(),
|
||||
VAlwaysKwd::ALWAYS,
|
||||
sentreep,
|
||||
bodysp);
|
||||
// Install it
|
||||
@@ -177,7 +178,7 @@ private:
|
||||
// VISITORS //========== Case assertions
|
||||
virtual void visit(AstCase* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
if (!nodep->user1Inc()) {
|
||||
if (!nodep->user1SetOnce()) {
|
||||
bool has_default=false;
|
||||
for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) {
|
||||
if (itemp->isDefault()) has_default=true;
|
||||
|
||||
+2
-4
@@ -1,14 +1,12 @@
|
||||
// -*- C++ -*-
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: Assertion expansion
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2005-2011 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2005-2013 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.
|
||||
|
||||
+2
-3
@@ -1,13 +1,12 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: Collect and print statistics
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2005-2011 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2005-2013 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.
|
||||
|
||||
+2
-4
@@ -1,14 +1,12 @@
|
||||
// -*- C++ -*-
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: Assertion pre-expansion
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2005-2011 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2005-2013 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.
|
||||
|
||||
+100
-22
@@ -1,13 +1,12 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: Ast node structures
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2013 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -52,6 +51,9 @@ bool AstUser3InUse::s_userBusy=false;
|
||||
bool AstUser4InUse::s_userBusy=false;
|
||||
bool AstUser5InUse::s_userBusy=false;
|
||||
|
||||
int AstNodeDType::s_uniqueNum = 0;
|
||||
|
||||
|
||||
//######################################################################
|
||||
// V3AstType
|
||||
|
||||
@@ -71,14 +73,12 @@ void AstNode::init() {
|
||||
m_op3p = NULL;
|
||||
m_op4p = NULL;
|
||||
m_iterpp = NULL;
|
||||
m_dtypep = NULL;
|
||||
m_clonep = NULL;
|
||||
m_cloneCnt = 0;
|
||||
// Attributes
|
||||
m_numeric = (int)AstNumeric::UNSIGNED;
|
||||
m_didWidth = false;
|
||||
m_doingWidth = false;
|
||||
m_width = 0;
|
||||
m_widthMin = 0;
|
||||
m_user1p = NULL;
|
||||
m_user1Cnt = 0;
|
||||
m_user2p = NULL;
|
||||
@@ -228,15 +228,6 @@ string AstNode::quoteName(const string& namein) {
|
||||
return out;
|
||||
}
|
||||
|
||||
int AstNode::widthPow2() const {
|
||||
// I.e. width 30 returns 32, width 32 returns 32.
|
||||
uint32_t width = this->width();
|
||||
for (int p2=30; p2>=0; p2--) {
|
||||
if (width > (1UL<<p2)) return (1UL<<(p2+1));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
//######################################################################
|
||||
// Insertion
|
||||
|
||||
@@ -245,7 +236,7 @@ inline void AstNode::debugTreeChange(const char* prefix, int lineno, bool next)
|
||||
// Called on all major tree changers.
|
||||
// Only for use for those really nasty bugs relating to internals
|
||||
// Note this may be null.
|
||||
//if (debug()) cout<<"-treeChange: V3Ast.cpp:"<<lineno<<" Tree Change for "<<prefix<<": "<<(void*)this<<endl;
|
||||
//if (debug()) cout<<"-treeChange: V3Ast.cpp:"<<lineno<<" Tree Change for "<<prefix<<": "<<(void*)this<<" <e"<<AstNode::s_editCntGbl<<">"<<endl;
|
||||
//if (debug()) {
|
||||
// cout<<"-treeChange: V3Ast.cpp:"<<lineno<<" Tree Change for "<<prefix<<endl;
|
||||
// v3Global.rootp()->dumpTree(cout,"-treeChange: ");
|
||||
@@ -719,6 +710,7 @@ void AstNode::deleteTree() {
|
||||
if (!this) return;
|
||||
UASSERT(m_backp==NULL,"Delete called on node with backlink still set\n");
|
||||
this->debugTreeChange("-delTree: ", __LINE__, true);
|
||||
this->editCountInc();
|
||||
// MUST be depth first!
|
||||
deleteTreeIter();
|
||||
}
|
||||
@@ -766,13 +758,17 @@ void AstNode::iterateAndNext(AstNVisitor& v, AstNUser* vup) {
|
||||
// Future versions of this function may require the node to have a back to be iterated;
|
||||
// there's no lower level reason yet though the back must exist.
|
||||
AstNode* nodep=this;
|
||||
#ifdef VL_DEBUG // Otherwise too hot of a function for debug
|
||||
if (VL_UNLIKELY(nodep && !nodep->m_backp)) nodep->v3fatalSrc("iterateAndNext node has no back");
|
||||
#endif
|
||||
while (nodep) {
|
||||
AstNode* niterp = nodep;
|
||||
AstNode* niterp = nodep; // This address may get stomped via m_iterpp if the node is edited
|
||||
ASTNODE_PREFETCH(nodep->m_nextp);
|
||||
// cppcheck-suppress nullPointer
|
||||
niterp->m_iterpp = &niterp;
|
||||
niterp->accept(v, vup);
|
||||
// accept may do a replaceNode and change niterp on us...
|
||||
//if (niterp != nodep) UINFO(1,"iterateAndNext edited "<<(void*)nodep<<" now into "<<(void*)niterp<<endl); // niterp maybe NULL, so need cast
|
||||
if (!niterp) return;
|
||||
niterp->m_iterpp = NULL;
|
||||
if (VL_UNLIKELY(niterp!=nodep)) { // Edited it
|
||||
@@ -854,6 +850,9 @@ AstNode* AstNode::acceptSubtreeReturnEdits(AstNVisitor& v, AstNUser* vup) {
|
||||
void AstNode::cloneRelinkTree() {
|
||||
if (!this) return;
|
||||
for (AstNode* nodep=this; nodep; nodep=nodep->m_nextp) {
|
||||
if (m_dtypep && m_dtypep->clonep()) {
|
||||
m_dtypep = m_dtypep->clonep()->castNodeDType();
|
||||
}
|
||||
nodep->cloneRelink();
|
||||
nodep->m_op1p->cloneRelinkTree();
|
||||
nodep->m_op2p->cloneRelinkTree();
|
||||
@@ -874,8 +873,7 @@ bool AstNode::sameTreeIter(AstNode* node2p, bool ignNext) {
|
||||
if (this==NULL && node2p==NULL) return true;
|
||||
if (this==NULL || node2p==NULL) return false;
|
||||
if (this->type() != node2p->type()
|
||||
|| this->width() != node2p->width()
|
||||
|| this->numeric() != node2p->numeric()
|
||||
|| this->dtypep() != node2p->dtypep()
|
||||
|| !this->same(node2p)) {
|
||||
return false;
|
||||
}
|
||||
@@ -947,6 +945,26 @@ void AstNode::checkTree() {
|
||||
}
|
||||
}
|
||||
|
||||
void AstNode::dumpGdb() { // For GDB only
|
||||
if (!this) { cout<<"This=NULL"<<endl; return; }
|
||||
dumpGdbHeader();
|
||||
cout<<" "; dump(cout); cout<<endl;
|
||||
}
|
||||
void AstNode::dumpGdbHeader() const { // For GDB only
|
||||
if (!this) { cout<<"This=NULL"<<endl; return; }
|
||||
dumpPtrs(cout);
|
||||
cout<<" Fileline = "<<fileline()<<endl;
|
||||
}
|
||||
void AstNode::dumpTreeGdb() { // For GDB only
|
||||
if (!this) { cout<<"This=NULL"<<endl; return; }
|
||||
dumpGdbHeader();
|
||||
dumpTree(cout);
|
||||
}
|
||||
void AstNode::dumpTreeFileGdb(const char* filenamep) { // For GDB only
|
||||
string filename = filenamep ? filenamep : v3Global.debugFilename("debug.tree",98);
|
||||
v3Global.rootp()->dumpTreeFile(filename);
|
||||
}
|
||||
|
||||
void AstNode::dumpPtrs(ostream& os) const {
|
||||
os<<"This="<<typeName()<<" "<<(void*)this;
|
||||
os<<" back="<<(void*)backp();
|
||||
@@ -993,11 +1011,13 @@ void AstNode::dumpTreeAndNext(ostream& os, const string& indent, int maxDepth) {
|
||||
void AstNode::dumpTreeFile(const string& filename, bool append) {
|
||||
if (v3Global.opt.dumpTree()) {
|
||||
{ // Write log & close
|
||||
UINFO(2,"Dumping "<<filename<<endl);
|
||||
const auto_ptr<ofstream> logsp (V3File::new_ofstream(filename, append));
|
||||
if (logsp->fail()) v3fatalSrc("Can't write "<<filename);
|
||||
*logsp<<"Tree Dump from <e"<<dec<<editCountLast()<<">";
|
||||
*logsp<<"Verilator Tree Dump (format 0x3900) from <e"<<dec<<editCountLast()<<">";
|
||||
*logsp<<" to <e"<<dec<<editCountGbl()<<">"<<endl;
|
||||
if (editCountGbl()==editCountLast()) {
|
||||
if (editCountGbl()==editCountLast()
|
||||
&& !(v3Global.opt.dumpTree()>=9)) {
|
||||
*logsp<<endl;
|
||||
*logsp<<"No changes since last dump!\n";
|
||||
} else {
|
||||
@@ -1022,7 +1042,7 @@ void AstNode::v3errorEnd(ostringstream& str) const {
|
||||
nsstr<<str.str();
|
||||
if (debug()) {
|
||||
nsstr<<endl;
|
||||
nsstr<<"-node: "<<this<<endl;
|
||||
nsstr<<"-node: "; ((AstNode*)this)->dump(nsstr); nsstr<<endl;
|
||||
}
|
||||
m_fileline->v3errorEnd(nsstr);
|
||||
} else {
|
||||
@@ -1030,6 +1050,64 @@ void AstNode::v3errorEnd(ostringstream& str) const {
|
||||
}
|
||||
}
|
||||
|
||||
string AstNode::warnMore() const {
|
||||
if (this) return this->fileline()->warnMore();
|
||||
else return V3Error::warnMore();
|
||||
}
|
||||
|
||||
//======================================================================
|
||||
// Data type conversion
|
||||
|
||||
void AstNode::dtypeChgSigned(bool flag) {
|
||||
if (!dtypep()) this->v3fatalSrc("No dtype when changing to (un)signed");
|
||||
dtypeChgWidthSigned(dtypep()->width(), dtypep()->widthMin(),
|
||||
flag ? AstNumeric::SIGNED : AstNumeric::UNSIGNED);
|
||||
}
|
||||
void AstNode::dtypeChgWidth(int width, int widthMin) {
|
||||
if (!dtypep()) this->v3fatalSrc("No dtype when changing width"); // Use ChgWidthSigned(...UNSIGNED) otherwise
|
||||
dtypeChgWidthSigned(width, widthMin, dtypep()->numeric());
|
||||
}
|
||||
|
||||
void AstNode::dtypeChgWidthSigned(int width, int widthMin, AstNumeric numeric) {
|
||||
if (!dtypep()) {
|
||||
// We allow dtypep() to be null, as before/during widthing dtypes are not resolved
|
||||
dtypeSetLogicSized(width, widthMin, numeric);
|
||||
} else {
|
||||
if (width==dtypep()->width()
|
||||
&& widthMin==dtypep()->widthMin()
|
||||
&& numeric==dtypep()->numeric()) return; // Correct already
|
||||
// FUTURE: We may be pointing at a two state data type, and this may
|
||||
// convert it to logic. Since the AstVar remains correct, we
|
||||
// work OK but this assumption may break in the future.
|
||||
// Note we can't just clone and do a widthForce, as if it's a BasicDType
|
||||
// the msb() indications etc will be incorrect.
|
||||
dtypeSetLogicSized(width, widthMin, numeric);
|
||||
}
|
||||
}
|
||||
|
||||
AstNodeDType* AstNode::findBasicDType(AstBasicDTypeKwd kwd) const {
|
||||
// For 'simple' types we use the global directory. These are all unsized.
|
||||
// More advanced types land under the module/task/etc
|
||||
return v3Global.rootp()->typeTablep()
|
||||
->findBasicDType(fileline(), kwd);
|
||||
}
|
||||
AstNodeDType* AstNode::findBitDType(int width, int widthMin, AstNumeric numeric) const {
|
||||
return v3Global.rootp()->typeTablep()
|
||||
->findLogicBitDType(fileline(), AstBasicDTypeKwd::BIT, width, widthMin, numeric);
|
||||
}
|
||||
AstNodeDType* AstNode::findLogicDType(int width, int widthMin, AstNumeric numeric) const {
|
||||
return v3Global.rootp()->typeTablep()
|
||||
->findLogicBitDType(fileline(), AstBasicDTypeKwd::LOGIC, width, widthMin, numeric);
|
||||
}
|
||||
AstNodeDType* AstNode::findLogicRangeDType(VNumRange range, int widthMin, AstNumeric numeric) const {
|
||||
return v3Global.rootp()->typeTablep()
|
||||
->findLogicBitDType(fileline(), AstBasicDTypeKwd::LOGIC, range, widthMin, numeric);
|
||||
}
|
||||
AstBasicDType* AstNode::findInsertSameDType(AstBasicDType* nodep) {
|
||||
return v3Global.rootp()->typeTablep()
|
||||
->findInsertSameDType(nodep);
|
||||
}
|
||||
|
||||
//######################################################################
|
||||
// AstNVisitor
|
||||
|
||||
|
||||
+451
-88
@@ -1,14 +1,12 @@
|
||||
// -*- C++ -*-
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: Ast node structure
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2013 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,15 +24,22 @@
|
||||
#include "verilatedos.h"
|
||||
#include "V3Error.h"
|
||||
#include "V3Number.h"
|
||||
#include "V3Global.h"
|
||||
#include <vector>
|
||||
#include <cmath>
|
||||
#include <map>
|
||||
|
||||
#include "V3Ast__gen_classes.h" // From ./astgen
|
||||
// Things like:
|
||||
// class V3AstNode;
|
||||
|
||||
// Hint class so we can choose constructors
|
||||
class AstLogicPacked {};
|
||||
class VFlagLogicPacked {};
|
||||
class VFlagBitPacked {};
|
||||
class VFlagChildDType {}; // Used by parser.y to select constructor that sets childDType
|
||||
|
||||
// For broken() function, return error string if have a match
|
||||
#define BROKEN_RTN(test) do { if (VL_UNLIKELY(test)) return # test; } while(0)
|
||||
|
||||
//######################################################################
|
||||
|
||||
@@ -45,6 +50,7 @@ public:
|
||||
// enum en {...};
|
||||
// const char* ascii() const {...};
|
||||
enum en m_e;
|
||||
// cppcheck-suppress uninitVar // responsiblity of each subclass
|
||||
inline AstType () {}
|
||||
inline AstType (en _e) : m_e(_e) {}
|
||||
explicit inline AstType (int _e) : m_e(static_cast<en>(_e)) {}
|
||||
@@ -57,28 +63,40 @@ public:
|
||||
|
||||
//######################################################################
|
||||
|
||||
enum VSignedState {
|
||||
// This can't be in the fancy class as the lexer union will get upset
|
||||
signedst_UNSIGNED=0, signedst_SIGNED=1, signedst_NOSIGN=2
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
||||
class AstNumeric {
|
||||
public:
|
||||
enum en {
|
||||
UNSIGNED,
|
||||
SIGNED,
|
||||
DOUBLE
|
||||
// Limited to 2 bits, unless change V3Ast's packing function
|
||||
NOSIGN,
|
||||
_ENUM_MAX // Leave last
|
||||
};
|
||||
enum en m_e;
|
||||
const char* ascii() const {
|
||||
static const char* names[] = {
|
||||
"UNSIGNED","SIGNED","DOUBLE"
|
||||
"UNSIGNED","SIGNED","NOSIGN"
|
||||
};
|
||||
return names[m_e];
|
||||
};
|
||||
inline AstNumeric () : m_e(UNSIGNED) {}
|
||||
inline AstNumeric (en _e) : m_e(_e) {}
|
||||
inline AstNumeric (VSignedState signst) {
|
||||
if (signst==signedst_UNSIGNED) m_e=UNSIGNED;
|
||||
else if (signst==signedst_SIGNED) m_e=SIGNED;
|
||||
else m_e=NOSIGN;
|
||||
}
|
||||
explicit inline AstNumeric (int _e) : m_e(static_cast<en>(_e)) {}
|
||||
operator en () const { return m_e; }
|
||||
inline bool isDouble() const { return m_e==DOUBLE; }
|
||||
inline bool isSigned() const { return m_e==SIGNED; }
|
||||
inline bool isUnsigned() const { return m_e==UNSIGNED; }
|
||||
inline bool isNosign() const { return m_e==NOSIGN; }
|
||||
// No isUnsigned() as it's ambiguous if NOSIGN should be included or not.
|
||||
};
|
||||
inline bool operator== (AstNumeric lhs, AstNumeric rhs) { return (lhs.m_e == rhs.m_e); }
|
||||
inline bool operator== (AstNumeric lhs, AstNumeric::en rhs) { return (lhs.m_e == rhs); }
|
||||
@@ -205,7 +223,18 @@ class AstAttrType {
|
||||
public:
|
||||
enum en {
|
||||
ILLEGAL,
|
||||
EXPR_BITS, // V3Const converts to constant
|
||||
//
|
||||
DIM_BITS, // V3Const converts to constant
|
||||
DIM_DIMENSIONS, // V3Width converts to constant
|
||||
DIM_HIGH, // V3Width processes
|
||||
DIM_INCREMENT, // V3Width processes
|
||||
DIM_LEFT, // V3Width processes
|
||||
DIM_LOW, // V3Width processes
|
||||
DIM_RIGHT, // V3Width processes
|
||||
DIM_SIZE, // V3Width processes
|
||||
DIM_UNPK_DIMENSIONS, // V3Width converts to constant
|
||||
//
|
||||
MEMBER_BASE, // V3LinkResolve creates for AstPreSel, V3LinkParam removes
|
||||
//
|
||||
VAR_BASE, // V3LinkResolve creates for AstPreSel, V3LinkParam removes
|
||||
VAR_CLOCK, // V3LinkParse moves to AstVar::attrScClocked
|
||||
@@ -215,15 +244,19 @@ public:
|
||||
VAR_PUBLIC_FLAT_RD, // V3LinkParse moves to AstVar::sigPublic
|
||||
VAR_PUBLIC_FLAT_RW, // V3LinkParse moves to AstVar::sigPublic
|
||||
VAR_ISOLATE_ASSIGNMENTS, // V3LinkParse moves to AstVar::attrIsolateAssign
|
||||
VAR_SC_BV, // V3LinkParse moves to AstVar::attrScBv
|
||||
VAR_SFORMAT // V3LinkParse moves to AstVar::attrSFormat
|
||||
};
|
||||
enum en m_e;
|
||||
const char* ascii() const {
|
||||
static const char* names[] = {
|
||||
"%E-AT", "EXPR_BITS", "VAR_BASE",
|
||||
"VAR_CLOCK", "VAR_CLOCK_ENABLE", "VAR_PUBLIC",
|
||||
"%E-AT",
|
||||
"DIM_BITS", "DIM_DIMENSIONS", "DIM_HIGH", "DIM_INCREMENT", "DIM_LEFT",
|
||||
"DIM_LOW", "DIM_RIGHT", "DIM_SIZE", "DIM_UNPK_DIMENSIONS",
|
||||
"MEMBER_BASE",
|
||||
"VAR_BASE", "VAR_CLOCK", "VAR_CLOCK_ENABLE", "VAR_PUBLIC",
|
||||
"VAR_PUBLIC_FLAT", "VAR_PUBLIC_FLAT_RD","VAR_PUBLIC_FLAT_RW",
|
||||
"VAR_ISOLATE_ASSIGNMENTS", "VAR_SFORMAT"
|
||||
"VAR_ISOLATE_ASSIGNMENTS", "VAR_SC_BV", "VAR_SFORMAT"
|
||||
};
|
||||
return names[m_e];
|
||||
};
|
||||
@@ -248,8 +281,12 @@ public:
|
||||
STRING,
|
||||
// Internal types for mid-steps
|
||||
SCOPEPTR, CHARPTR,
|
||||
// Unsigned and two state; fundamental types
|
||||
UINT32, UINT64,
|
||||
// Internal types, eliminated after parsing
|
||||
LOGIC_IMPLICIT
|
||||
LOGIC_IMPLICIT,
|
||||
// Leave last
|
||||
_ENUM_MAX
|
||||
};
|
||||
enum en m_e;
|
||||
const char* ascii() const {
|
||||
@@ -259,7 +296,9 @@ public:
|
||||
"real", "shortint", "shortreal", "time",
|
||||
"string",
|
||||
"VerilatedScope*", "char*",
|
||||
"LOGIC_IMPLICIT"
|
||||
"IData", "QData",
|
||||
"LOGIC_IMPLICIT",
|
||||
" MAX"
|
||||
};
|
||||
return names[m_e];
|
||||
};
|
||||
@@ -270,33 +309,48 @@ public:
|
||||
"double", "short int", "float", "long long",
|
||||
"const char*",
|
||||
"dpiScope", "const char*",
|
||||
""
|
||||
"IData", "QData",
|
||||
"svLogic", // Though shouldn't be needed
|
||||
" MAX"
|
||||
};
|
||||
return names[m_e];
|
||||
};
|
||||
static void test() {
|
||||
UASSERT(0==strcmp(AstBasicDTypeKwd(_ENUM_MAX).ascii()," MAX"),"Enum array mismatch");
|
||||
UASSERT(0==strcmp(AstBasicDTypeKwd(_ENUM_MAX).dpiType()," MAX"),"Enum array mismatch");
|
||||
}
|
||||
inline AstBasicDTypeKwd () : m_e(UNKNOWN) {}
|
||||
inline AstBasicDTypeKwd (en _e) : m_e(_e) {}
|
||||
explicit inline AstBasicDTypeKwd (int _e) : m_e(static_cast<en>(_e)) {}
|
||||
operator en () const { return m_e; }
|
||||
int width() const {
|
||||
switch (m_e) {
|
||||
case BIT: return 1;
|
||||
case BIT: return 1; // scalar, can't bit extract unless ranged
|
||||
case BYTE: return 8;
|
||||
case CHANDLE: return 64;
|
||||
case INT: return 32;
|
||||
case INTEGER: return 32;
|
||||
case LOGIC: return 1;
|
||||
case LOGIC: return 1; // scalar, can't bit extract unless ranged
|
||||
case LONGINT: return 64;
|
||||
case DOUBLE: return 64;
|
||||
case FLOAT: return 32;
|
||||
case DOUBLE: return 64; // opaque
|
||||
case FLOAT: return 32; // opaque
|
||||
case SHORTINT: return 16;
|
||||
case TIME: return 64;
|
||||
case STRING: return 64; // Just the pointer, for today
|
||||
case STRING: return 64; // opaque // Just the pointer, for today
|
||||
case SCOPEPTR: return 0; // opaque
|
||||
case CHARPTR: return 0; // opaque
|
||||
case UINT32: return 32;
|
||||
case UINT64: return 64;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
bool isSigned() const {
|
||||
return m_e==BYTE || m_e==SHORTINT || m_e==INT || m_e==LONGINT || m_e==INTEGER;
|
||||
return m_e==BYTE || m_e==SHORTINT || m_e==INT || m_e==LONGINT || m_e==INTEGER
|
||||
|| m_e==DOUBLE || m_e==FLOAT;
|
||||
}
|
||||
bool isUnsigned() const {
|
||||
return m_e==CHANDLE || m_e==STRING || m_e==SCOPEPTR || m_e==CHARPTR
|
||||
|| m_e==UINT32 || m_e==UINT64;
|
||||
}
|
||||
bool isFourstate() const {
|
||||
return m_e==INTEGER || m_e==LOGIC || m_e==LOGIC_IMPLICIT;
|
||||
@@ -305,15 +359,22 @@ public:
|
||||
return (m_e==BIT || m_e==BYTE || m_e==CHANDLE || m_e==INT || m_e==LONGINT || m_e==SHORTINT
|
||||
|| m_e==STRING || m_e==DOUBLE || m_e==FLOAT);
|
||||
}
|
||||
bool isIntNumeric() const { // Enum increment supported
|
||||
return (m_e==BIT || m_e==BYTE || m_e==INT || m_e==INTEGER || m_e==LOGIC
|
||||
|| m_e==LONGINT || m_e==SHORTINT || m_e==UINT32 || m_e==UINT64);
|
||||
}
|
||||
bool isSloppy() const { // Don't be as anal about width warnings
|
||||
return !(m_e==LOGIC || m_e==BIT);
|
||||
}
|
||||
bool isBitLogic() const { // Don't be as anal about width warnings
|
||||
bool isBitLogic() const { // Bit/logic vector types; can form a packed array
|
||||
return (m_e==LOGIC || m_e==BIT);
|
||||
}
|
||||
bool isDpiUnsupported() const {
|
||||
return (m_e==LOGIC || m_e==TIME);
|
||||
}
|
||||
bool isDpiUnsignable() const { // Can add "unsigned" to DPI
|
||||
return (m_e==BYTE || m_e==SHORTINT || m_e==INT || m_e==LONGINT || m_e==INTEGER);
|
||||
}
|
||||
bool isOpaque() const { // IE not a simple number we can bit optimize
|
||||
return (m_e==STRING || m_e==SCOPEPTR || m_e==CHARPTR || m_e==DOUBLE || m_e==FLOAT);
|
||||
}
|
||||
@@ -327,13 +388,6 @@ public:
|
||||
|
||||
//######################################################################
|
||||
|
||||
enum AstSignedState {
|
||||
// This can't be in the fancy class as the lexer union will get upset
|
||||
signedst_NOP=0, signedst_SIGNED=1, signedst_UNSIGNED=2
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
||||
class AstVarType {
|
||||
public:
|
||||
enum en {
|
||||
@@ -350,11 +404,14 @@ public:
|
||||
WIRE,
|
||||
IMPLICITWIRE,
|
||||
TRIWIRE,
|
||||
TRI0,
|
||||
TRI1,
|
||||
PORT, // Temp type used in parser only
|
||||
BLOCKTEMP,
|
||||
MODULETEMP,
|
||||
STMTTEMP,
|
||||
XTEMP
|
||||
XTEMP,
|
||||
IFACEREF // Used to link Interfaces between modules
|
||||
};
|
||||
enum en m_e;
|
||||
inline AstVarType () : m_e(UNKNOWN) {}
|
||||
@@ -365,9 +422,17 @@ public:
|
||||
static const char* names[] = {
|
||||
"?","GPARAM","LPARAM","GENVAR",
|
||||
"VAR","INPUT","OUTPUT","INOUT",
|
||||
"SUPPLY0","SUPPLY1","WIRE","IMPLICITWIRE","TRIWIRE","PORT",
|
||||
"BLOCKTEMP","MODULETEMP","STMTTEMP","XTEMP"};
|
||||
"SUPPLY0","SUPPLY1","WIRE","IMPLICITWIRE",
|
||||
"TRIWIRE","TRI0","TRI1",
|
||||
"PORT",
|
||||
"BLOCKTEMP","MODULETEMP","STMTTEMP","XTEMP",
|
||||
"IFACEREF"};
|
||||
return names[m_e]; }
|
||||
bool isSignal() const { return (m_e==WIRE || m_e==IMPLICITWIRE
|
||||
|| m_e==TRIWIRE
|
||||
|| m_e==TRI0 || m_e==TRI1
|
||||
|| m_e==SUPPLY0 || m_e==SUPPLY1
|
||||
|| m_e==VAR); }
|
||||
};
|
||||
inline bool operator== (AstVarType lhs, AstVarType rhs) { return (lhs.m_e == rhs.m_e); }
|
||||
inline bool operator== (AstVarType lhs, AstVarType::en rhs) { return (lhs.m_e == rhs); }
|
||||
@@ -407,6 +472,30 @@ public:
|
||||
|
||||
//######################################################################
|
||||
|
||||
class VAlwaysKwd {
|
||||
public:
|
||||
enum en {
|
||||
ALWAYS,
|
||||
ALWAYS_FF,
|
||||
ALWAYS_LATCH,
|
||||
ALWAYS_COMB
|
||||
};
|
||||
enum en m_e;
|
||||
inline VAlwaysKwd () : m_e(ALWAYS) {}
|
||||
inline VAlwaysKwd (en _e) : m_e(_e) {}
|
||||
explicit inline VAlwaysKwd (int _e) : m_e(static_cast<en>(_e)) {}
|
||||
operator en () const { return m_e; }
|
||||
const char* ascii() const {
|
||||
static const char* names[] = {
|
||||
"always","always_ff","always_latch","always_comb"};
|
||||
return names[m_e]; }
|
||||
};
|
||||
inline bool operator== (VAlwaysKwd lhs, VAlwaysKwd rhs) { return (lhs.m_e == rhs.m_e); }
|
||||
inline bool operator== (VAlwaysKwd lhs, VAlwaysKwd::en rhs) { return (lhs.m_e == rhs); }
|
||||
inline bool operator== (VAlwaysKwd::en lhs, VAlwaysKwd rhs) { return (lhs == rhs.m_e); }
|
||||
|
||||
//######################################################################
|
||||
|
||||
class AstCaseType {
|
||||
public:
|
||||
enum en {
|
||||
@@ -458,10 +547,7 @@ class AstParseRefExp {
|
||||
public:
|
||||
enum en {
|
||||
PX_NONE, // Used in V3LinkParse only
|
||||
PX_VAR_MEM,
|
||||
PX_VAR_ANY,
|
||||
PX_TASK,
|
||||
PX_FUNC
|
||||
PX_TEXT // Unknown ID component
|
||||
};
|
||||
enum en m_e;
|
||||
inline AstParseRefExp() : m_e(PX_NONE) {}
|
||||
@@ -470,7 +556,7 @@ public:
|
||||
operator en () const { return m_e; }
|
||||
const char* ascii() const {
|
||||
static const char* names[] = {
|
||||
"","VAR_MEM","VAR_ANY","TASK","FUNC"};
|
||||
"","TEXT","PREDOT"};
|
||||
return names[m_e]; }
|
||||
};
|
||||
inline bool operator== (AstParseRefExp lhs, AstParseRefExp rhs) { return (lhs.m_e == rhs.m_e); }
|
||||
@@ -478,6 +564,88 @@ public:
|
||||
inline bool operator== (AstParseRefExp::en lhs, AstParseRefExp rhs) { return (lhs == rhs.m_e); }
|
||||
inline ostream& operator<<(ostream& os, AstParseRefExp rhs) { return os<<rhs.ascii(); }
|
||||
|
||||
//######################################################################
|
||||
// VNumRange - Structure containing numberic range information
|
||||
// See also AstRange, which is a symbolic version of this
|
||||
|
||||
struct VNumRange {
|
||||
int m_hi; // HI part, HI always >= LO
|
||||
int m_lo; // LO
|
||||
union {
|
||||
int mu_flags;
|
||||
struct {
|
||||
bool m_ranged:1; // Has a range
|
||||
bool m_littleEndian:1; // Bit vector is little endian
|
||||
};
|
||||
};
|
||||
inline bool operator== (const VNumRange& rhs) const {
|
||||
return m_hi == rhs.m_hi
|
||||
&& m_lo == rhs.m_lo
|
||||
&& mu_flags == rhs.mu_flags; }
|
||||
inline bool operator< (const VNumRange& rhs) const {
|
||||
if ( (m_hi < rhs.m_hi)) return true;
|
||||
if (!(m_hi == rhs.m_hi)) return false; // lhs > rhs
|
||||
if ( (m_lo < rhs.m_lo)) return true;
|
||||
if (!(m_lo == rhs.m_lo)) return false; // lhs > rhs
|
||||
if ( (mu_flags < rhs.mu_flags)) return true;
|
||||
if (!(mu_flags == rhs.mu_flags)) return false; // lhs > rhs
|
||||
return false;
|
||||
}
|
||||
//
|
||||
VNumRange() : m_hi(0), m_lo(0), mu_flags(0) {}
|
||||
VNumRange(int hi, int lo, bool littleEndian)
|
||||
: m_hi(0), m_lo(0), mu_flags(0)
|
||||
{ init(hi,lo,littleEndian); }
|
||||
~VNumRange() {}
|
||||
// MEMBERS
|
||||
void init(int hi, int lo, bool littleEndian) {
|
||||
m_hi=hi; m_lo=lo; mu_flags=0; m_ranged=true; m_littleEndian=littleEndian;
|
||||
}
|
||||
int hi() const { return m_hi; }
|
||||
int lo() const { return m_lo; }
|
||||
int left() const { return littleEndian()?lo():hi(); } // How to show a declaration
|
||||
int right() const { return littleEndian()?hi():lo(); }
|
||||
int elements() const { return hi()-lo()+1; }
|
||||
bool ranged() const { return m_ranged; }
|
||||
bool littleEndian() const { return m_littleEndian; }
|
||||
int hiMaxSelect() const { return (lo()<0 ? hi()-lo() : hi()); } // Maximum value a [] select may index
|
||||
bool representableByWidth() const // Could be represented by just width=1, or [width-1:0]
|
||||
{ return (!m_ranged || (m_lo==0 && m_hi>=1 && !m_littleEndian)); }
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
||||
struct VBasicTypeKey {
|
||||
int m_width; // From AstNodeDType: Bit width of operation
|
||||
int m_widthMin; // From AstNodeDType: If unsized, bitwidth of minimum implementation
|
||||
AstNumeric m_numeric; // From AstNodeDType: Node is signed
|
||||
AstBasicDTypeKwd m_keyword; // From AstBasicDType: What keyword created basic type
|
||||
VNumRange m_nrange; // From AstBasicDType: Numeric msb/lsb (if non-opaque keyword)
|
||||
inline bool operator== (const VBasicTypeKey& rhs) const {
|
||||
return m_width == rhs.m_width
|
||||
&& m_widthMin == rhs.m_widthMin
|
||||
&& m_numeric == rhs.m_numeric
|
||||
&& m_keyword == rhs.m_keyword
|
||||
&& m_nrange == rhs.m_nrange; }
|
||||
inline bool operator< (const VBasicTypeKey& rhs) const {
|
||||
if ( (m_width < rhs.m_width)) return true;
|
||||
if (!(m_width == rhs.m_width)) return false; // lhs > rhs
|
||||
if ( (m_widthMin < rhs.m_widthMin)) return true;
|
||||
if (!(m_widthMin == rhs.m_widthMin)) return false; // lhs > rhs
|
||||
if ( (m_numeric < rhs.m_numeric)) return true;
|
||||
if (!(m_numeric == rhs.m_numeric)) return false; // lhs > rhs
|
||||
if ( (m_keyword < rhs.m_keyword)) return true;
|
||||
if (!(m_keyword == rhs.m_keyword)) return false; // lhs > rhs
|
||||
if ( (m_nrange < rhs.m_nrange)) return true;
|
||||
if (!(m_nrange == rhs.m_nrange)) return false; // lhs > rhs
|
||||
return false; }
|
||||
VBasicTypeKey(int width, int widthMin, AstNumeric numeric, AstBasicDTypeKwd kwd,
|
||||
VNumRange nrange)
|
||||
: m_width(width), m_widthMin(widthMin), m_numeric(numeric),
|
||||
m_keyword(kwd), m_nrange(nrange) {}
|
||||
~VBasicTypeKey() {}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
// AstNUser - Generic pointer base class for AST User nodes.
|
||||
// - Also used to allow parameter passing up/down iterate calls
|
||||
@@ -487,13 +655,13 @@ class LinkVP;
|
||||
class OrderBlockNU;
|
||||
class OrderVarNU;
|
||||
class V3GraphVertex;
|
||||
class V3SymTable;
|
||||
class VSymEnt;
|
||||
struct AstNUser {
|
||||
AstNUser* p() { return this; } // So can take address of temporary: iterate(...,AstNUser(args).p())
|
||||
// Casters
|
||||
WidthVP* c() { return ((WidthVP*)this); }
|
||||
LinkVP* castLinkVP() { return ((LinkVP*)this); }
|
||||
V3SymTable* castSymTable() { return ((V3SymTable*)this); }
|
||||
VSymEnt* castSymEnt() { return ((VSymEnt*)this); }
|
||||
AstNode* castNode() { return ((AstNode*)this); }
|
||||
OrderBlockNU* castOrderBlock() { return ((OrderBlockNU*)this); }
|
||||
OrderVarNU* castOrderVar() { return ((OrderVarNU*)this); }
|
||||
@@ -644,7 +812,7 @@ protected:
|
||||
RelinkWhatEn m_chg;
|
||||
AstNode** m_iterpp;
|
||||
public:
|
||||
AstNRelinker() { m_backp=NULL; m_chg=RELINK_BAD; m_iterpp=NULL;}
|
||||
AstNRelinker() { m_oldp=NULL; m_backp=NULL; m_chg=RELINK_BAD; m_iterpp=NULL;}
|
||||
void relink(AstNode* newp);
|
||||
AstNode* oldp() const { return m_oldp; }
|
||||
void dump(ostream& str=cout) const;
|
||||
@@ -686,11 +854,14 @@ public:
|
||||
// Creating from raw data (sameHash functions)
|
||||
V3Hash() { setBoth(1,0); }
|
||||
V3Hash(uint32_t val) { setBoth(1,val); }
|
||||
V3Hash(void* vp) { setBoth(1,cvtToHash(vp)); }
|
||||
V3Hash(const void* vp) { setBoth(1,cvtToHash(vp)); }
|
||||
V3Hash(const string& name);
|
||||
V3Hash(V3Hash lh, V3Hash rh) {
|
||||
setBoth(1,lh.hshval()*31+rh.hshval());
|
||||
}
|
||||
V3Hash(V3Hash h1, V3Hash h2) {
|
||||
setBoth(1,h1.hshval()*31+h2.hshval()); }
|
||||
V3Hash(V3Hash h1, V3Hash h2, V3Hash h3) {
|
||||
setBoth(1,(h1.hshval()*31+h2.hshval())*31+h3.hshval()); }
|
||||
V3Hash(V3Hash h1, V3Hash h2, V3Hash h3, V3Hash h4) {
|
||||
setBoth(1,((h1.hshval()*31+h2.hshval())*31+h3.hshval())*31+h4.hshval()); }
|
||||
};
|
||||
ostream& operator<<(ostream& os, V3Hash rhs);
|
||||
|
||||
@@ -720,18 +891,17 @@ class AstNode {
|
||||
static vluint64_t s_editCntGbl; // Global edit counter
|
||||
static vluint64_t s_editCntLast;// Global edit counter, last value for printing * near node #s
|
||||
|
||||
AstNodeDType* m_dtypep; // Data type of output or assignment (etc)
|
||||
|
||||
AstNode* m_clonep; // Pointer to clone of/ source of this module (for *LAST* cloneTree() ONLY)
|
||||
int m_cloneCnt; // Mark of when userp was set
|
||||
static int s_cloneCntGbl; // Count of which userp is set
|
||||
|
||||
// Attributes
|
||||
uint32_t m_numeric:2; // Node is real/signed - important that bitfields remain unsigned
|
||||
bool m_didWidth:1; // Did V3Width computation
|
||||
bool m_doingWidth:1; // Inside V3Width
|
||||
// // Space for more bools here
|
||||
|
||||
int m_width; // Bit width of operation
|
||||
int m_widthMin; // If unsized, bitwidth of minimum implementation
|
||||
// This member ordering both allows 64 bit alignment and puts associated data together
|
||||
AstNUser* m_user1p; // Pointer to any information the user iteration routine wants
|
||||
uint32_t m_user1Cnt; // Mark of when userp was set
|
||||
@@ -805,6 +975,7 @@ public:
|
||||
AstNode* op2p() const { return m_op2p; }
|
||||
AstNode* op3p() const { return m_op3p; }
|
||||
AstNode* op4p() const { return m_op4p; }
|
||||
AstNodeDType* dtypep() const { return m_dtypep; }
|
||||
AstNode* clonep() const { return ((m_cloneCnt==s_cloneCntGbl)?m_clonep:NULL); }
|
||||
AstNode* firstAbovep() const { return ((backp() && backp()->nextp()!=this) ? backp() : NULL); } // Returns NULL when second or later in list
|
||||
bool brokeExists() const;
|
||||
@@ -845,29 +1016,22 @@ public:
|
||||
string prettyTypeName() const; // "VARREF name" for error messages
|
||||
FileLine* fileline() const { return m_fileline; }
|
||||
void fileline(FileLine* fl) { m_fileline=fl; }
|
||||
int width() const { return m_width; }
|
||||
bool width1() const { return width()==1; }
|
||||
int widthWords() const { return VL_WORDS_I(width()); }
|
||||
int widthMin() const { return m_widthMin?m_widthMin:m_width; } // If sized, the size, if unsized the min digits to represent it
|
||||
int widthPow2() const;
|
||||
int widthInstrs() const { return isWide()?widthWords():1; }
|
||||
bool widthSized() const { return !m_widthMin || m_widthMin==m_width; }
|
||||
void width(int width, int sized) { m_width=width; m_widthMin=sized; }
|
||||
void widthFrom(AstNode* fromp) { if (fromp) { m_width=fromp->m_width; m_widthMin=fromp->m_widthMin; }}
|
||||
void widthSignedFrom(AstNode* fromp) { widthFrom(fromp); numericFrom(fromp); }
|
||||
void numericFrom(AstNode* fromp) { numeric(fromp->numeric()); }
|
||||
void numeric(AstNumeric flag) { m_numeric = (int)flag; if (flag.isDouble()) width(64,64); }
|
||||
AstNumeric numeric() const { return AstNumeric(m_numeric); }
|
||||
bool isDouble() const { return numeric().isDouble(); }
|
||||
bool isSigned() const { return numeric().isSigned(); }
|
||||
void isSigned(bool flag) { numeric(flag ? AstNumeric::SIGNED : AstNumeric::UNSIGNED); }
|
||||
bool isUnsigned() const { return numeric().isUnsigned(); }
|
||||
bool width1() const;
|
||||
int widthInstrs() const;
|
||||
void didWidth(bool flag) { m_didWidth=flag; }
|
||||
bool didWidth() const { return m_didWidth; }
|
||||
bool didWidthAndSet() { if (didWidth()) return true; didWidth(true); return false;}
|
||||
void doingWidth(bool flag) { m_doingWidth=flag; }
|
||||
bool doingWidth() const { return m_doingWidth; }
|
||||
|
||||
//TODO stomp these width functions out, and call via dtypep() instead
|
||||
int width() const;
|
||||
int widthMin() const;
|
||||
int widthWords() const { return VL_WORDS_I(width()); }
|
||||
bool isQuad() const { return (width()>VL_WORDSIZE && width()<=VL_QUADSIZE); }
|
||||
bool isWide() const { return (width()>VL_QUADSIZE); }
|
||||
bool isDouble() const;
|
||||
bool isSigned() const;
|
||||
|
||||
AstNUser* user1p() const {
|
||||
// Slows things down measurably, so disabled by default
|
||||
@@ -878,6 +1042,7 @@ public:
|
||||
int user1() const { return user1p()->castInt(); }
|
||||
void user1(int val) { user1p(AstNUser::fromInt(val)); }
|
||||
int user1Inc() { int v=user1(); user1(v+1); return v; }
|
||||
int user1SetOnce() { int v=user1(); if (!v) user1(1); return v; } // Better for cache than user1Inc()
|
||||
static void user1ClearTree() { AstUser1InUse::clear(); } // Clear userp()'s across the entire tree
|
||||
|
||||
AstNUser* user2p() const {
|
||||
@@ -887,6 +1052,7 @@ public:
|
||||
int user2() const { return user2p()->castInt(); }
|
||||
void user2(int val) { user2p(AstNUser::fromInt(val)); }
|
||||
int user2Inc() { int v=user2(); user2(v+1); return v; }
|
||||
int user2SetOnce() { int v=user2(); if (!v) user2(1); return v; }
|
||||
static void user2ClearTree() { AstUser2InUse::clear(); }
|
||||
|
||||
AstNUser* user3p() const {
|
||||
@@ -896,6 +1062,7 @@ public:
|
||||
int user3() const { return user3p()->castInt(); }
|
||||
void user3(int val) { user3p(AstNUser::fromInt(val)); }
|
||||
int user3Inc() { int v=user3(); user3(v+1); return v; }
|
||||
int user3SetOnce() { int v=user3(); if (!v) user3(1); return v; }
|
||||
static void user3ClearTree() { AstUser3InUse::clear(); }
|
||||
|
||||
AstNUser* user4p() const {
|
||||
@@ -905,6 +1072,7 @@ public:
|
||||
int user4() const { return user4p()->castInt(); }
|
||||
void user4(int val) { user4p(AstNUser::fromInt(val)); }
|
||||
int user4Inc() { int v=user4(); user4(v+1); return v; }
|
||||
int user4SetOnce() { int v=user4(); if (!v) user4(1); return v; }
|
||||
static void user4ClearTree() { AstUser4InUse::clear(); }
|
||||
|
||||
AstNUser* user5p() const {
|
||||
@@ -914,6 +1082,7 @@ public:
|
||||
int user5() const { return user5p()->castInt(); }
|
||||
void user5(int val) { user5p(AstNUser::fromInt(val)); }
|
||||
int user5Inc() { int v=user5(); user5(v+1); return v; }
|
||||
int user5SetOnce() { int v=user5(); if (!v) user5(1); return v; }
|
||||
static void user5ClearTree() { AstUser5InUse::clear(); }
|
||||
|
||||
vluint64_t editCount() const { return m_editCount; }
|
||||
@@ -930,15 +1099,46 @@ public:
|
||||
bool isAllOnes();
|
||||
bool isAllOnesV(); // Verilog width rules apply
|
||||
|
||||
// METHODS
|
||||
// METHODS - data type changes especially for initial creation
|
||||
void dtypep(AstNodeDType* nodep) { if (m_dtypep != nodep) { m_dtypep = nodep; editCountInc(); } }
|
||||
void dtypeFrom(AstNode* fromp) { if (fromp) { dtypep(fromp->dtypep()); }}
|
||||
void dtypeChgSigned(bool flag=true);
|
||||
void dtypeChgWidth(int width, int widthMin);
|
||||
void dtypeChgWidthSigned(int width, int widthMin, AstNumeric numeric);
|
||||
void dtypeSetBitSized(int width, int widthMin, AstNumeric numeric) { dtypep(findBitDType(width,widthMin,numeric)); }
|
||||
void dtypeSetLogicSized(int width, int widthMin, AstNumeric numeric) { dtypep(findLogicDType(width,widthMin,numeric)); }
|
||||
void dtypeSetLogicBool() { dtypep(findLogicBoolDType()); }
|
||||
void dtypeSetDouble() { dtypep(findDoubleDType()); }
|
||||
void dtypeSetSigned32() { dtypep(findSigned32DType()); }
|
||||
void dtypeSetUInt32() { dtypep(findUInt32DType()); } // Twostate
|
||||
void dtypeSetUInt64() { dtypep(findUInt64DType()); } // Twostate
|
||||
|
||||
// Data type locators
|
||||
AstNodeDType* findLogicBoolDType() { return findBasicDType(AstBasicDTypeKwd::LOGIC); }
|
||||
AstNodeDType* findDoubleDType() { return findBasicDType(AstBasicDTypeKwd::DOUBLE); }
|
||||
AstNodeDType* findSigned32DType() { return findBasicDType(AstBasicDTypeKwd::INTEGER); }
|
||||
AstNodeDType* findUInt32DType() { return findBasicDType(AstBasicDTypeKwd::UINT32); } // Twostate
|
||||
AstNodeDType* findUInt64DType() { return findBasicDType(AstBasicDTypeKwd::UINT64); } // Twostate
|
||||
AstNodeDType* findBitDType(int width, int widthMin, AstNumeric numeric) const;
|
||||
AstNodeDType* findLogicDType(int width, int widthMin, AstNumeric numeric) const;
|
||||
AstNodeDType* findLogicRangeDType(VNumRange range, int widthMin, AstNumeric numeric) const;
|
||||
AstNodeDType* findBasicDType(AstBasicDTypeKwd kwd) const;
|
||||
AstBasicDType* findInsertSameDType(AstBasicDType* nodep);
|
||||
|
||||
// METHODS - dump and error
|
||||
void v3errorEnd(ostringstream& str) const;
|
||||
string warnMore() const;
|
||||
virtual void dump(ostream& str=cout);
|
||||
void dumpGdb(); // For GDB only
|
||||
void dumpGdbHeader() const;
|
||||
|
||||
// METHODS - Tree modifications
|
||||
AstNode* addNext(AstNode* newp); // Returns this, adds to end of list
|
||||
AstNode* addNextNull(AstNode* newp); // Returns this, adds to end of list, NULL is OK
|
||||
void addNextHere(AstNode* newp); // Adds after speced node
|
||||
void addPrev(AstNode* newp) { replaceWith(newp); newp->addNext(this); }
|
||||
void addHereThisAsNext(AstNode* newp); // Adds at old place of this, this becomes next
|
||||
void replaceWith(AstNode* newp); // Replace current node in tree with new node
|
||||
void v3errorEnd(ostringstream& str) const;
|
||||
virtual void dump(ostream& str=cout);
|
||||
AstNode* unlinkFrBack(AstNRelinker* linkerp=NULL); // Unlink this from whoever points to it.
|
||||
AstNode* unlinkFrBackWithNext(AstNRelinker* linkerp=NULL); // Unlink this from whoever points to it, keep entire next list with unlinked node
|
||||
void swapWith(AstNode* bp);
|
||||
@@ -955,12 +1155,17 @@ public:
|
||||
void checkTree(); // User Interface version
|
||||
void dumpPtrs(ostream& str=cout) const;
|
||||
void dumpTree(ostream& str=cout, const string& indent=" ", int maxDepth=0);
|
||||
void dumpTree(const string& indent, int maxDepth=0) { dumpTree(cout,indent,maxDepth); }
|
||||
void dumpTreeGdb(); // For GDB only
|
||||
void dumpTreeAndNext(ostream& str=cout, const string& indent=" ", int maxDepth=0);
|
||||
void dumpTreeFile(const string& filename, bool append=false);
|
||||
static void dumpTreeFileGdb(const char* filenamep=NULL);
|
||||
|
||||
// METHODS - queries
|
||||
virtual bool isSplittable() const { return true; } // Else a $display, etc, that must be ordered with other displays
|
||||
virtual bool isPure() const { return true; } // Else a $display, etc, that must be ordered with other displays
|
||||
virtual bool isBrancher() const { return false; } // Changes control flow, disable some optimizations
|
||||
virtual bool isGateOptimizable() const { return true; } // Else a AstTime etc that can't be pushed out
|
||||
virtual bool isGateDedupable() const { return isGateOptimizable(); } // GateDedupable is a slightly larger superset of GateOptimzable (eg, AstNodeIf)
|
||||
virtual bool isSubstOptimizable() const { return true; } // Else a AstTime etc that can't be substituted out
|
||||
virtual bool isPredictOptimizable() const { return true; } // Else a AstTime etc which output can't be predicted from input
|
||||
virtual bool isOutputter() const { return false; } // Else creates output or exits, etc, not unconsumed
|
||||
@@ -968,8 +1173,10 @@ public:
|
||||
virtual int instrCount() const { return 0; }
|
||||
virtual V3Hash sameHash() const { return V3Hash(V3Hash::Illegal()); } // Not a node that supports it
|
||||
virtual bool same(AstNode* otherp) const { return true; }
|
||||
virtual bool hasDType() const { return false; } // Iff has a data type; dtype() must be non null
|
||||
virtual AstNodeDType* getChildDTypep() const { return NULL; } // Iff has a non-null childDTypep(), as generic node function
|
||||
virtual bool maybePointedTo() const { return false; } // Another AstNode* may have a pointer into this node, other then normal front/back/etc.
|
||||
virtual bool broken() const { return false; }
|
||||
virtual const char* broken() const { return NULL; }
|
||||
|
||||
// INVOKERS
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) = 0;
|
||||
@@ -987,7 +1194,7 @@ public:
|
||||
// AstAlways* castAlways();
|
||||
};
|
||||
|
||||
inline ostream& operator<<(ostream& os, AstNode* rhs) { rhs->dump(os); return os;}
|
||||
inline ostream& operator<<(ostream& os, AstNode* rhs) { if (!rhs) os<<"NULL"; else rhs->dump(os); return os; }
|
||||
inline void AstNRelinker::relink(AstNode* newp) { newp->AstNode::relink(this); }
|
||||
|
||||
//######################################################################
|
||||
@@ -1004,6 +1211,7 @@ struct AstNodeMath : public AstNode {
|
||||
: AstNode(fl) {}
|
||||
ASTNODE_BASE_FUNCS(NodeMath)
|
||||
// METHODS
|
||||
virtual bool hasDType() const { return true; }
|
||||
virtual string emitVerilog() = 0; /// Format string for verilog writing; see V3EmitV
|
||||
virtual string emitC() = 0;
|
||||
virtual string emitSimpleOperator() { return ""; }
|
||||
@@ -1028,7 +1236,7 @@ struct AstNodeUniop : public AstNodeMath {
|
||||
// Unary math
|
||||
AstNodeUniop(FileLine* fl, AstNode* lhsp)
|
||||
: AstNodeMath(fl) {
|
||||
if (lhsp) widthSignedFrom(lhsp);
|
||||
dtypeFrom(lhsp);
|
||||
setOp1p(lhsp); }
|
||||
ASTNODE_BASE_FUNCS(NodeUniop)
|
||||
AstNode* lhsp() const { return op1p()->castNode(); }
|
||||
@@ -1108,8 +1316,8 @@ struct AstNodeBiComAsv : public AstNodeBiCom {
|
||||
struct AstNodeCond : public AstNodeTriop {
|
||||
AstNodeCond(FileLine* fl, AstNode* condp, AstNode* expr1p, AstNode* expr2p)
|
||||
: AstNodeTriop(fl, condp, expr1p, expr2p) {
|
||||
if (expr1p) widthSignedFrom(expr1p);
|
||||
else if (expr2p) widthSignedFrom(expr2p);
|
||||
if (expr1p) dtypeFrom(expr1p);
|
||||
else if (expr2p) dtypeFrom(expr2p);
|
||||
}
|
||||
ASTNODE_BASE_FUNCS(NodeCond)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, const V3Number& ths) {
|
||||
@@ -1128,7 +1336,7 @@ struct AstNodeCond : public AstNodeTriop {
|
||||
};
|
||||
|
||||
struct AstNodePreSel : public AstNode {
|
||||
// Something that becomes a AstSel
|
||||
// Something that becomes an AstSel
|
||||
AstNodePreSel(FileLine* fl, AstNode* lhs, AstNode* rhs, AstNode* ths)
|
||||
: AstNode(fl) {
|
||||
setOp1p(lhs); setOp2p(rhs); setNOp3p(ths); }
|
||||
@@ -1153,15 +1361,15 @@ struct AstNodeStmt : public AstNode {
|
||||
: AstNode(fl) {}
|
||||
ASTNODE_BASE_FUNCS(NodeStmt)
|
||||
// METHODS
|
||||
virtual void addNextStmt(AstNode* newp, AstNode* belowp); // Stop statement searchback here
|
||||
virtual void addBeforeStmt(AstNode* newp, AstNode* belowp); // Stop statement searchback here
|
||||
virtual void addNextStmt(AstNode* newp, AstNode* belowp); // Stop statement searchback here
|
||||
virtual void addBeforeStmt(AstNode* newp, AstNode* belowp); // Stop statement searchback here
|
||||
};
|
||||
|
||||
struct AstNodeAssign : public AstNodeStmt {
|
||||
AstNodeAssign(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
||||
: AstNodeStmt(fl) {
|
||||
setOp1p(rhsp); setOp2p(lhsp);
|
||||
if (lhsp) widthSignedFrom(lhsp);
|
||||
dtypeFrom(lhsp);
|
||||
}
|
||||
ASTNODE_BASE_FUNCS(NodeAssign)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp)=0; // Clone single node, just get same type back.
|
||||
@@ -1170,6 +1378,7 @@ struct AstNodeAssign : public AstNodeStmt {
|
||||
AstNode* lhsp() const { return op2p()->castNode(); } // op2 = Assign to
|
||||
void rhsp(AstNode* np) { setOp1p(np); }
|
||||
void lhsp(AstNode* np) { setOp2p(np); }
|
||||
virtual bool hasDType() const { return true; }
|
||||
virtual bool cleanRhs() { return true; }
|
||||
virtual int instrCount() const { return widthInstrs(); }
|
||||
virtual V3Hash sameHash() const { return V3Hash(); }
|
||||
@@ -1210,6 +1419,7 @@ public:
|
||||
void addIfsp(AstNode* newp) { addOp2p(newp); }
|
||||
void addElsesp(AstNode* newp) { addOp3p(newp); }
|
||||
virtual bool isGateOptimizable() const { return false; }
|
||||
virtual bool isGateDedupable() const { return true; }
|
||||
virtual int instrCount() const { return instrCountBranch(); }
|
||||
virtual V3Hash sameHash() const { return V3Hash(); }
|
||||
virtual bool same(AstNode* samep) const { return true; }
|
||||
@@ -1252,19 +1462,22 @@ private:
|
||||
string m_name; // Name of variable
|
||||
string m_hiername; // Scope converted into name-> for emitting
|
||||
bool m_hierThis; // Hiername points to "this" function
|
||||
void init();
|
||||
public:
|
||||
AstNodeVarRef(FileLine* fl, const string& name, bool lvalue)
|
||||
: AstNodeMath(fl), m_lvalue(lvalue), m_varp(NULL), m_varScopep(NULL),
|
||||
m_packagep(NULL), m_name(name), m_hierThis(false) {
|
||||
init();
|
||||
}
|
||||
AstNodeVarRef(FileLine* fl, const string& name, AstVar* varp, bool lvalue)
|
||||
: AstNodeMath(fl), m_lvalue(lvalue), m_varp(varp), m_varScopep(NULL),
|
||||
m_packagep(NULL), m_name(name), m_hierThis(false) {
|
||||
// May have varp==NULL
|
||||
if (m_varp) widthSignedFrom((AstNode*)m_varp);
|
||||
init();
|
||||
}
|
||||
ASTNODE_BASE_FUNCS(NodeVarRef)
|
||||
virtual bool broken() const;
|
||||
virtual bool hasDType() const { return true; }
|
||||
virtual const char* broken() const;
|
||||
virtual int instrCount() const { return widthInstrs(); }
|
||||
virtual void cloneRelink();
|
||||
virtual string name() const { return m_name; } // * = Var name
|
||||
@@ -1305,14 +1518,137 @@ public:
|
||||
};
|
||||
|
||||
struct AstNodeDType : public AstNode {
|
||||
// Data type
|
||||
AstNodeDType(FileLine* fl) : AstNode(fl) {}
|
||||
private:
|
||||
// Ideally width() would migrate to BasicDType as that's where it makes sense,
|
||||
// but it's currently so prevalent in the code we leave it here.
|
||||
// Note the below members are included in AstTypeTable::Key lookups
|
||||
int m_width; // (also in AstTypeTable::Key) Bit width of operation
|
||||
int m_widthMin; // (also in AstTypeTable::Key) If unsized, bitwidth of minimum implementation
|
||||
AstNumeric m_numeric; // (also in AstTypeTable::Key) Node is signed
|
||||
// Other members
|
||||
bool m_generic; // Simple globally referenced type, don't garbage collect
|
||||
static int s_uniqueNum; // Unique number assigned to each dtype during creation for IEEE matching
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
AstNodeDType(FileLine* fl) : AstNode(fl) {
|
||||
m_width=0; m_widthMin=0; m_generic=false;
|
||||
}
|
||||
ASTNODE_BASE_FUNCS(NodeDType)
|
||||
// Accessors
|
||||
// ACCESSORS
|
||||
virtual void dump(ostream& str);
|
||||
virtual void dumpSmall(ostream& str);
|
||||
virtual bool hasDType() const { return true; }
|
||||
virtual AstBasicDType* basicp() const = 0; // (Slow) recurse down to find basic data type
|
||||
virtual AstNodeDType* skipRefp() const = 0; // recurses over typedefs to next non-typeref type
|
||||
virtual int widthAlignBytes() const = 0; // (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this)
|
||||
virtual int widthTotalBytes() const = 0; // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,...
|
||||
virtual bool maybePointedTo() const { return true; }
|
||||
virtual AstNodeDType* virtRefDTypep() const { return NULL; } // Iff has a non-null refDTypep(), as generic node function
|
||||
virtual void virtRefDTypep(AstNodeDType* nodep) { } // Iff has refDTypep(), set as generic node function
|
||||
//
|
||||
// Changing the width may confuse the data type resolution, so must clear TypeTable cache after use.
|
||||
void widthForce(int width, int sized) { m_width=width; m_widthMin=sized; }
|
||||
// For backward compatibility inherit width and signing from the subDType/base type
|
||||
void widthFromSub(AstNodeDType* nodep) { m_width=nodep->m_width; m_widthMin=nodep->m_widthMin; m_numeric=nodep->m_numeric; }
|
||||
//
|
||||
int width() const { return m_width; }
|
||||
void numeric(AstNumeric flag) { m_numeric = flag; }
|
||||
bool isSigned() const { return m_numeric.isSigned(); }
|
||||
bool isNosign() const { return m_numeric.isNosign(); }
|
||||
AstNumeric numeric() const { return m_numeric; }
|
||||
int widthWords() const { return VL_WORDS_I(width()); }
|
||||
int widthMin() const { return m_widthMin?m_widthMin:m_width; } // If sized, the size, if unsized the min digits to represent it
|
||||
int widthPow2() const;
|
||||
void widthMinFromWidth() { m_widthMin = m_width; }
|
||||
bool widthSized() const { return !m_widthMin || m_widthMin==m_width; }
|
||||
bool generic() const { return m_generic; }
|
||||
void generic(bool flag) { m_generic = flag; }
|
||||
AstNodeDType* dtypeDimensionp(int depth);
|
||||
pair<uint32_t,uint32_t> dimensions(bool includeBasic);
|
||||
uint32_t arrayUnpackedElements(); // 1, or total multiplication of all dimensions
|
||||
static int uniqueNumInc() { return ++s_uniqueNum; }
|
||||
};
|
||||
|
||||
struct AstNodeClassDType : public AstNodeDType {
|
||||
private:
|
||||
// TYPES
|
||||
typedef map<string,AstMemberDType*> MemberNameMap;
|
||||
// MEMBERS
|
||||
bool m_packed;
|
||||
MemberNameMap m_members;
|
||||
public:
|
||||
AstNodeClassDType(FileLine* fl, AstNumeric numericUnpack)
|
||||
: AstNodeDType(fl) {
|
||||
// AstNumeric::NOSIGN overloaded to indicate not packed
|
||||
m_packed = (numericUnpack != AstNumeric::NOSIGN);
|
||||
numeric(numericUnpack.isSigned() ? AstNumeric::SIGNED : AstNumeric::UNSIGNED);
|
||||
}
|
||||
ASTNODE_BASE_FUNCS(NodeClassDType)
|
||||
virtual const char* broken() const;
|
||||
virtual void dump(ostream& str);
|
||||
// For basicp() we reuse the size to indicate a "fake" basic type of same size
|
||||
virtual AstBasicDType* basicp() const { return findLogicDType(width(),width(),numeric())->castBasicDType(); }
|
||||
virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; }
|
||||
virtual int widthAlignBytes() const; // (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this)
|
||||
virtual int widthTotalBytes() const; // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,...
|
||||
// op1 = members
|
||||
AstMemberDType* membersp() const { return op1p()->castMemberDType(); } // op1 = AstMember list
|
||||
void addMembersp(AstNode* nodep) { addNOp1p(nodep); }
|
||||
bool packed() const { return m_packed; }
|
||||
void clearCache() { m_members.clear(); }
|
||||
void repairMemberCache();
|
||||
AstMemberDType* findMember(const string& name) const {
|
||||
MemberNameMap::const_iterator it = m_members.find(name);
|
||||
return (it==m_members.end()) ? NULL : it->second;
|
||||
}
|
||||
int lsb() const { return 0; }
|
||||
int msb() const { return dtypep()->width()-1; } // Packed classes look like arrays
|
||||
VNumRange declRange() const { return VNumRange(msb(), lsb(), false); }
|
||||
};
|
||||
|
||||
struct AstNodeArrayDType : public AstNodeDType {
|
||||
// Array data type, ie "some_dtype var_name [2:0]"
|
||||
// Children: DTYPE (moved to refDTypep() in V3Width)
|
||||
// Children: RANGE (array bounds)
|
||||
private:
|
||||
AstNodeDType* m_refDTypep; // Elements of this type (after widthing)
|
||||
AstNode* rangenp() const { return op2p(); } // op2 = Array(s) of variable
|
||||
public:
|
||||
AstNodeArrayDType(FileLine* fl) : AstNodeDType(fl) {
|
||||
m_refDTypep = NULL;
|
||||
}
|
||||
ASTNODE_BASE_FUNCS(NodeArrayDType)
|
||||
virtual void dump(ostream& str);
|
||||
virtual void dumpSmall(ostream& str);
|
||||
virtual const char* broken() const { BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists())
|
||||
|| (!m_refDTypep && childDTypep()))); return NULL; }
|
||||
virtual void cloneRelink() { if (m_refDTypep && m_refDTypep->clonep()) {
|
||||
m_refDTypep = m_refDTypep->clonep()->castNodeDType();
|
||||
}}
|
||||
virtual bool same(AstNode* samep) const {
|
||||
AstNodeArrayDType* sp = samep->castNodeArrayDType();
|
||||
return (msb()==sp->msb()
|
||||
&& subDTypep()==sp->subDTypep()
|
||||
&& rangenp()->sameTree(sp->rangenp())); } // HashedDT doesn't recurse, so need to check children
|
||||
virtual V3Hash sameHash() const { return V3Hash(V3Hash(m_refDTypep),V3Hash(msb()),V3Hash(lsb())); }
|
||||
AstNodeDType* getChildDTypep() const { return childDTypep(); }
|
||||
AstNodeDType* childDTypep() const { return op1p()->castNodeDType(); } // op1 = Range of variable
|
||||
void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); }
|
||||
AstNodeDType* subDTypep() const { return m_refDTypep ? m_refDTypep : childDTypep(); }
|
||||
void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; }
|
||||
virtual AstNodeDType* virtRefDTypep() const { return m_refDTypep; }
|
||||
virtual void virtRefDTypep(AstNodeDType* nodep) { refDTypep(nodep); }
|
||||
AstRange* rangep() const { return op2p()->castRange(); } // op2 = Array(s) of variable
|
||||
void rangep(AstRange* nodep);
|
||||
// METHODS
|
||||
virtual AstBasicDType* basicp() const { return subDTypep()->basicp(); } // (Slow) recurse down to find basic data type
|
||||
virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; }
|
||||
virtual int widthAlignBytes() const { return subDTypep()->widthAlignBytes(); }
|
||||
virtual int widthTotalBytes() const { return elementsConst() * subDTypep()->widthTotalBytes(); }
|
||||
int msb() const;
|
||||
int lsb() const;
|
||||
int elementsConst() const;
|
||||
VNumRange declRange() const;
|
||||
};
|
||||
|
||||
struct AstNodeSel : public AstNodeBiop {
|
||||
@@ -1325,6 +1661,7 @@ struct AstNodeSel : public AstNodeBiop {
|
||||
AstNode* bitp() const { return op2p()->castNode(); } // op2 = Msb selection expression
|
||||
void bitp(AstNode* nodep) { setOp2p(nodep); }
|
||||
int bitConst() const;
|
||||
virtual bool hasDType() const { return true; }
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
@@ -1408,7 +1745,7 @@ public:
|
||||
addNOp2p(pinsp);
|
||||
}
|
||||
ASTNODE_BASE_FUNCS(NodeFTaskRef)
|
||||
virtual bool broken() const { return m_taskp && !m_taskp->brokeExists(); }
|
||||
virtual const char* broken() const { BROKEN_RTN(m_taskp && !m_taskp->brokeExists()); return NULL; }
|
||||
virtual void cloneRelink() { if (m_taskp && m_taskp->clonep()) {
|
||||
m_taskp = m_taskp->clonep()->castNodeFTask();
|
||||
}}
|
||||
@@ -1444,13 +1781,15 @@ private:
|
||||
bool m_modPublic:1; // Module has public references
|
||||
bool m_modTrace:1; // Tracing this module
|
||||
bool m_inLibrary:1; // From a library, no error if not used, never top level
|
||||
bool m_dead:1; // LinkDot believes is dead; will remove in Dead visitors
|
||||
bool m_internal:1; // Internally created
|
||||
int m_level; // 1=top module, 2=cell off top module, ...
|
||||
int m_varNum; // Incrementing variable number
|
||||
public:
|
||||
AstNodeModule(FileLine* fl, const string& name)
|
||||
: AstNode (fl)
|
||||
,m_name(name), m_origName(name)
|
||||
,m_modPublic(false), m_modTrace(false), m_inLibrary(false)
|
||||
,m_modPublic(false), m_modTrace(false), m_inLibrary(false), m_dead(false), m_internal(false)
|
||||
,m_level(0), m_varNum(0) { }
|
||||
ASTNODE_BASE_FUNCS(NodeModule)
|
||||
virtual void dump(ostream& str);
|
||||
@@ -1475,6 +1814,10 @@ public:
|
||||
bool modPublic() const { return m_modPublic; }
|
||||
void modTrace(bool flag) { m_modTrace = flag; }
|
||||
bool modTrace() const { return m_modTrace; }
|
||||
void dead(bool flag) { m_dead = flag; }
|
||||
bool dead() const { return m_dead; }
|
||||
void internal(bool flag) { m_internal = flag; }
|
||||
bool internal() const { return m_internal; }
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
@@ -1488,10 +1831,30 @@ public:
|
||||
//######################################################################
|
||||
// Inline ACCESSORS
|
||||
|
||||
inline int AstNode::width() const { return dtypep() ? dtypep()->width() : 0; }
|
||||
inline int AstNode::widthMin() const { return dtypep() ? dtypep()->widthMin() : 0; }
|
||||
inline bool AstNode::width1() const { return dtypep() && dtypep()->width()==1; } // V3Const uses to know it can optimize
|
||||
inline int AstNode::widthInstrs() const { return (!dtypep() ? 1 : (dtypep()->isWide() ? dtypep()->widthWords() : 1)); }
|
||||
inline bool AstNode::isDouble() const { return dtypep() && dtypep()->castBasicDType() && dtypep()->castBasicDType()->isDouble(); }
|
||||
inline bool AstNode::isSigned() const { return dtypep() && dtypep()->isSigned(); }
|
||||
|
||||
inline bool AstNode::isZero() { return (this->castConst() && this->castConst()->num().isEqZero()); }
|
||||
inline bool AstNode::isNeqZero() { return (this->castConst() && this->castConst()->num().isNeqZero()); }
|
||||
inline bool AstNode::isOne() { return (this->castConst() && this->castConst()->num().isEqOne()); }
|
||||
inline bool AstNode::isAllOnes() { return (this->castConst() && this->castConst()->num().isEqAllOnes(this->width())); }
|
||||
inline bool AstNode::isAllOnesV() { return (this->castConst() && this->castConst()->num().isEqAllOnes(this->widthMin())); }
|
||||
inline bool AstNode::isAllOnes() { return (this->castConst() && this->castConst()->isEqAllOnes()); }
|
||||
inline bool AstNode::isAllOnesV() { return (this->castConst() && this->castConst()->isEqAllOnesV()); }
|
||||
|
||||
inline void AstNodeVarRef::init() { if (m_varp) dtypep(m_varp->dtypep()); }
|
||||
|
||||
inline void AstNodeArrayDType::rangep(AstRange* nodep) { setOp2p(nodep); }
|
||||
inline int AstNodeArrayDType::msb() const { return rangep()->msbConst(); }
|
||||
inline int AstNodeArrayDType::lsb() const { return rangep()->lsbConst(); }
|
||||
inline int AstNodeArrayDType::elementsConst() const { return rangep()->elementsConst(); }
|
||||
inline VNumRange AstNodeArrayDType::declRange() const { return VNumRange(msb(), lsb(), rangep()->littleEndian()); }
|
||||
|
||||
inline void AstIfaceRefDType::cloneRelink() {
|
||||
if (m_cellp && m_cellp->clonep()) m_cellp = m_cellp->clonep()->castCell();
|
||||
if (m_ifacep && m_ifacep->clonep()) m_ifacep = m_ifacep->clonep()->castIface();
|
||||
if (m_modportp && m_modportp->clonep()) m_modportp = m_modportp->clonep()->castModport(); }
|
||||
|
||||
#endif // Guard
|
||||
|
||||
+373
-74
@@ -1,13 +1,12 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: Ast node structures
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2013 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -36,8 +35,22 @@
|
||||
// Special methods
|
||||
|
||||
// We need these here, because the classes they point to aren't defined when we declare the class
|
||||
bool AstNodeVarRef::broken() const { return ((m_varScopep && !m_varScopep->brokeExists())
|
||||
|| (m_varp && !m_varp->brokeExists())); }
|
||||
const char* AstIfaceRefDType::broken() const {
|
||||
BROKEN_RTN(m_ifacep && !m_ifacep->brokeExists());
|
||||
BROKEN_RTN(m_cellp && !m_cellp->brokeExists());
|
||||
BROKEN_RTN(m_modportp && !m_modportp->brokeExists());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
AstIface* AstIfaceRefDType::ifaceViaCellp() const {
|
||||
return ((m_cellp && m_cellp->modp()) ? m_cellp->modp()->castIface() : m_ifacep);
|
||||
}
|
||||
|
||||
const char* AstNodeVarRef::broken() const {
|
||||
BROKEN_RTN(m_varScopep && !m_varScopep->brokeExists());
|
||||
BROKEN_RTN(m_varp && !m_varp->brokeExists());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void AstNodeVarRef::cloneRelink() {
|
||||
if (m_varp && m_varp->clonep()) { m_varp = m_varp->clonep()->castVar(); }
|
||||
@@ -47,6 +60,28 @@ int AstNodeSel::bitConst() const {
|
||||
AstConst* constp=bitp()->castConst(); return (constp?constp->toSInt():0);
|
||||
}
|
||||
|
||||
void AstNodeClassDType::repairMemberCache() {
|
||||
clearCache();
|
||||
for (AstMemberDType* itemp = membersp(); itemp; itemp=itemp->nextp()->castMemberDType()) {
|
||||
if (m_members.find(itemp->name())!=m_members.end()) { itemp->v3error("Duplicate declaration of member name: "<<itemp->prettyName()); }
|
||||
else m_members.insert(make_pair(itemp->name(), itemp));
|
||||
}
|
||||
}
|
||||
|
||||
const char* AstNodeClassDType::broken() const {
|
||||
set<AstMemberDType*> exists;
|
||||
for (AstMemberDType* itemp = membersp(); itemp; itemp=itemp->nextp()->castMemberDType()) {
|
||||
exists.insert(itemp);
|
||||
}
|
||||
for (MemberNameMap::const_iterator it=m_members.begin(); it!=m_members.end(); ++it) {
|
||||
if (VL_UNLIKELY(exists.find(it->second) == exists.end())) {
|
||||
this->v3error("Internal: Structure member broken: "<<it->first);
|
||||
return "member broken";
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int AstBasicDType::widthAlignBytes() const {
|
||||
if (width()<=8) return 1;
|
||||
else if (width()<=16) return 2;
|
||||
@@ -61,29 +96,63 @@ int AstBasicDType::widthTotalBytes() const {
|
||||
else return widthWords()*(VL_WORDSIZE/8);
|
||||
}
|
||||
|
||||
int AstNodeClassDType::widthTotalBytes() const {
|
||||
if (width()<=8) return 1;
|
||||
else if (width()<=16) return 2;
|
||||
else if (isQuad()) return 8;
|
||||
else return widthWords()*(VL_WORDSIZE/8);
|
||||
}
|
||||
|
||||
int AstNodeClassDType::widthAlignBytes() const {
|
||||
// Could do max across members but that would be slow,
|
||||
// instead intuit based on total structure size
|
||||
if (width()<=8) return 1;
|
||||
else if (width()<=16) return 2;
|
||||
else if (width()<=32) return 4;
|
||||
else return 8;
|
||||
}
|
||||
|
||||
bool AstVar::isSigPublic() const {
|
||||
return (m_sigPublic || (v3Global.opt.allPublic() && !isTemp() && !isGenVar()));
|
||||
}
|
||||
|
||||
bool AstVar::isScQuad() const {
|
||||
return (isSc() && isQuad() && !isScBv());
|
||||
return (isSc() && isQuad() && !isScBv() && !isScBigUint());
|
||||
}
|
||||
|
||||
bool AstVar::isScBv() const {
|
||||
return (isSc() && width() >= v3Global.opt.pinsBv());
|
||||
return ((isSc() && width() >= v3Global.opt.pinsBv()) || m_attrScBv);
|
||||
}
|
||||
|
||||
bool AstVar::isScUint() const {
|
||||
return ((isSc() && v3Global.opt.pinsScUint() && width() >= 2 && width() <= 64) && !isScBv());
|
||||
}
|
||||
|
||||
bool AstVar::isScBigUint() const {
|
||||
return ((isSc() && v3Global.opt.pinsScBigUint() && width() >= 65 && width() <= 512) && !isScBv());
|
||||
}
|
||||
|
||||
void AstVar::combineType(AstVarType type) {
|
||||
// These flags get combined with the existing settings of the flags.
|
||||
// We don't test varType for certain types, instead set flags since
|
||||
// when we combine wires cross-hierarchy we need a union of all characteristics.
|
||||
if (type == AstVarType::SUPPLY0) type = AstVarType::WIRE;
|
||||
if (type == AstVarType::SUPPLY1) type = AstVarType::WIRE;
|
||||
m_varType=type; // For debugging prints only
|
||||
// These flags get combined with the existing settings of the flags.
|
||||
if (type==AstVarType::INPUT || type==AstVarType::INOUT)
|
||||
m_input = true;
|
||||
if (type==AstVarType::OUTPUT || type==AstVarType::INOUT)
|
||||
if (type==AstVarType::OUTPUT || type==AstVarType::INOUT) {
|
||||
m_output = true;
|
||||
if (type==AstVarType::INOUT || type==AstVarType::TRIWIRE)
|
||||
m_declOutput = true;
|
||||
}
|
||||
if (type==AstVarType::INOUT || type==AstVarType::TRIWIRE
|
||||
|| type==AstVarType::TRI0 || type==AstVarType::TRI1)
|
||||
m_tristate = true;
|
||||
if (type==AstVarType::TRI0)
|
||||
m_isPulldown = true;
|
||||
if (type==AstVarType::TRI1)
|
||||
m_isPullup = true;
|
||||
}
|
||||
|
||||
string AstVar::verilogKwd() const {
|
||||
@@ -221,6 +290,9 @@ string AstVar::dpiArgType(bool named, bool forReturn) const {
|
||||
}
|
||||
} else {
|
||||
arg = basicp()->keyword().dpiType();
|
||||
if (basicp()->keyword().isDpiUnsignable() && !basicp()->isSigned()) {
|
||||
arg = "unsigned "+arg;
|
||||
}
|
||||
if (!forReturn && isOutput()) arg += "*";
|
||||
}
|
||||
if (named) arg += " "+name();
|
||||
@@ -228,7 +300,11 @@ string AstVar::dpiArgType(bool named, bool forReturn) const {
|
||||
}
|
||||
|
||||
string AstVar::scType() const {
|
||||
if (isScBv()) {
|
||||
if (isScBigUint()) {
|
||||
return (string("sc_biguint<")+cvtToStr(widthMin())+"> "); // Keep the space so don't get >>
|
||||
} else if (isScUint()) {
|
||||
return (string("sc_uint<")+cvtToStr(widthMin())+"> "); // Keep the space so don't get >>
|
||||
} else if (isScBv()) {
|
||||
return (string("sc_bv<")+cvtToStr(widthMin())+"> "); // Keep the space so don't get >>
|
||||
} else if (widthMin() == 1) {
|
||||
return "bool";
|
||||
@@ -245,7 +321,7 @@ string AstVar::scType() const {
|
||||
}
|
||||
}
|
||||
|
||||
AstNodeDType* AstVar::dtypeDimensionp(int dimension) const {
|
||||
AstNodeDType* AstNodeDType::dtypeDimensionp(int dimension) {
|
||||
// dimension passed from AstArraySel::dimension
|
||||
// Dimension 0 means the VAR itself, 1 is the closest SEL to the AstVar,
|
||||
// which is the lowest in the dtype list.
|
||||
@@ -257,19 +333,29 @@ AstNodeDType* AstVar::dtypeDimensionp(int dimension) const {
|
||||
// DECL: VAR a (ARRAYSEL0 (ARRAYSEL1 (ARRAYSEL2 (DT RANGE3))))
|
||||
// *or* VAR a (ARRAYSEL0 (ARRAYSEL1 (ARRAYSEL2 (ARRAYSEL3 (DT))))
|
||||
// SEL1 needs to select from entire variable which is a pointer to ARRAYSEL0
|
||||
// TODO this function should be removed in favor of recursing the dtype(),
|
||||
// as that allows for more complicated data types.
|
||||
int dim = 0;
|
||||
for (AstNodeDType* dtypep=this->dtypep(); dtypep; ) {
|
||||
for (AstNodeDType* dtypep=this; dtypep; ) {
|
||||
dtypep = dtypep->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node
|
||||
if (AstArrayDType* adtypep = dtypep->castArrayDType()) {
|
||||
if (AstNodeArrayDType* adtypep = dtypep->castNodeArrayDType()) {
|
||||
if ((dim++)==dimension) {
|
||||
return dtypep;
|
||||
}
|
||||
dtypep = adtypep->dtypep();
|
||||
dtypep = adtypep->subDTypep();
|
||||
continue;
|
||||
}
|
||||
else if (AstBasicDType* adtypep = dtypep->castBasicDType()) {
|
||||
// AstBasicDType - nothing below, return null
|
||||
if (adtypep->rangep()) {
|
||||
if (adtypep->isRanged()) {
|
||||
if ((dim++) == dimension) {
|
||||
return adtypep;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
else if (AstNodeClassDType* adtypep = dtypep->castNodeClassDType()) {
|
||||
if (adtypep->packed()) {
|
||||
if ((dim++) == dimension) {
|
||||
return adtypep;
|
||||
}
|
||||
@@ -282,13 +368,13 @@ AstNodeDType* AstVar::dtypeDimensionp(int dimension) const {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint32_t AstVar::arrayElements() const {
|
||||
uint32_t AstNodeDType::arrayUnpackedElements() {
|
||||
uint32_t entries=1;
|
||||
for (AstNodeDType* dtypep=this->dtypep(); dtypep; ) {
|
||||
for (AstNodeDType* dtypep=this; dtypep; ) {
|
||||
dtypep = dtypep->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node
|
||||
if (AstArrayDType* adtypep = dtypep->castArrayDType()) {
|
||||
if (AstUnpackArrayDType* adtypep = dtypep->castUnpackArrayDType()) {
|
||||
entries *= adtypep->elementsConst();
|
||||
dtypep = adtypep->dtypep();
|
||||
dtypep = adtypep->subDTypep();
|
||||
}
|
||||
else {
|
||||
// AstBasicDType - nothing below, 1
|
||||
@@ -298,45 +384,41 @@ uint32_t AstVar::arrayElements() const {
|
||||
return entries;
|
||||
}
|
||||
|
||||
pair<uint32_t,uint32_t> AstVar::dimensions() const {
|
||||
pair<uint32_t,uint32_t> AstNodeDType::dimensions(bool includeBasic) {
|
||||
// How many array dimensions (packed,unpacked) does this Var have?
|
||||
uint32_t packed = 0;
|
||||
uint32_t unpacked = 0;
|
||||
for (AstNodeDType* dtypep=this->dtypep(); dtypep; ) {
|
||||
for (AstNodeDType* dtypep=this; dtypep; ) {
|
||||
dtypep = dtypep->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node
|
||||
if (AstArrayDType* adtypep = dtypep->castArrayDType()) {
|
||||
if (adtypep->isPacked()) packed += 1;
|
||||
else unpacked += 1;
|
||||
dtypep = adtypep->dtypep();
|
||||
if (AstNodeArrayDType* adtypep = dtypep->castNodeArrayDType()) {
|
||||
if (adtypep->castPackArrayDType()) packed++;
|
||||
else unpacked++;
|
||||
dtypep = adtypep->subDTypep();
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
// AstBasicDType - nothing below, 1
|
||||
break;
|
||||
else if (AstBasicDType* adtypep = dtypep->castBasicDType()) {
|
||||
if (includeBasic && adtypep->isRanged()) packed++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return make_pair(packed, unpacked);
|
||||
}
|
||||
|
||||
// Special operators
|
||||
int AstArraySel::dimension(AstNode* nodep) {
|
||||
// How many dimensions is this reference from the base variable?
|
||||
// nodep is typically the fromp() of a select; thus the first select
|
||||
// is selecting from the entire variable type - effectively dimension 0.
|
||||
// Dimension passed to AstVar::dtypeDimensionp; see comments there
|
||||
int dim = 0;
|
||||
while (nodep) {
|
||||
if (nodep->castNodeSel()) { dim++; nodep=nodep->castNodeSel()->fromp(); continue; }
|
||||
if (nodep->castNodePreSel()) { dim++; nodep=nodep->castNodePreSel()->fromp(); continue; }
|
||||
break;
|
||||
int AstNodeDType::widthPow2() const {
|
||||
// I.e. width 30 returns 32, width 32 returns 32.
|
||||
uint32_t width = this->width();
|
||||
for (int p2=30; p2>=0; p2--) {
|
||||
if (width > (1UL<<p2)) return (1UL<<(p2+1));
|
||||
}
|
||||
return dim;
|
||||
return 1;
|
||||
}
|
||||
|
||||
AstNode* AstArraySel::baseFromp(AstNode* nodep) { ///< What is the base variable (or const) this dereferences?
|
||||
// Else AstArraySel etc; search for the base
|
||||
while (nodep) {
|
||||
if (nodep->castArraySel()) { nodep=nodep->castArraySel()->fromp(); continue; }
|
||||
else if (nodep->castSel()) { nodep=nodep->castSel()->fromp(); continue; }
|
||||
// AstNodeSelPre stashes the associated variable under a ATTROF so it isn't constified
|
||||
// AstNodeSelPre stashes the associated variable under an ATTROF of AstAttrType::VAR_BASE/MEMBER_BASE so it isn't constified
|
||||
else if (nodep->castAttrOf()) { nodep=nodep->castAttrOf()->fromp(); continue; }
|
||||
else if (nodep->castNodePreSel()) {
|
||||
if (nodep->castNodePreSel()->attrp()) {
|
||||
@@ -351,10 +433,12 @@ AstNode* AstArraySel::baseFromp(AstNode* nodep) { ///< What is the base variable
|
||||
return nodep;
|
||||
}
|
||||
|
||||
bool AstScope::broken() const {
|
||||
return ((m_aboveScopep && !m_aboveScopep->brokeExists())
|
||||
|| (m_aboveCellp && !m_aboveCellp->brokeExists())
|
||||
|| !m_modp || !m_modp->brokeExists());
|
||||
const char* AstScope::broken() const {
|
||||
BROKEN_RTN(m_aboveScopep && !m_aboveScopep->brokeExists());
|
||||
BROKEN_RTN(m_aboveCellp && !m_aboveCellp->brokeExists());
|
||||
BROKEN_RTN(!m_modp);
|
||||
BROKEN_RTN(m_modp && !m_modp->brokeExists());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void AstScope::cloneRelink() {
|
||||
@@ -431,6 +515,96 @@ bool AstSenTree::hasCombo() {
|
||||
return false;
|
||||
}
|
||||
|
||||
void AstTypeTable::clearCache() {
|
||||
// When we mass-change widthMin in V3WidthCommit, we need to correct the table.
|
||||
// Just clear out the maps; the search functions will be used to rebuild the map
|
||||
for (int i=0; i<(int)(AstBasicDTypeKwd::_ENUM_MAX); ++i) {
|
||||
m_basicps[i] = NULL;
|
||||
}
|
||||
for (int isbit=0; isbit<_IDX0_MAX; ++isbit) {
|
||||
for (int numer=0; numer<AstNumeric::_ENUM_MAX; ++numer) {
|
||||
LogicMap& mapr = m_logicMap[isbit][numer];
|
||||
mapr.clear();
|
||||
}
|
||||
}
|
||||
m_detailedMap.clear();
|
||||
// Clear generic()'s so dead detection will work
|
||||
for (AstNode* nodep = typesp(); nodep; nodep=nodep->nextp()) {
|
||||
if (AstBasicDType* bdtypep = nodep->castBasicDType()) {
|
||||
bdtypep->generic(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AstTypeTable::repairCache() {
|
||||
// After we mass-change widthMin in V3WidthCommit, we need to correct the table.
|
||||
clearCache();
|
||||
for (AstNode* nodep = typesp(); nodep; nodep=nodep->nextp()) {
|
||||
if (AstBasicDType* bdtypep = nodep->castBasicDType()) {
|
||||
(void)findInsertSameDType(bdtypep);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AstBasicDType* AstTypeTable::findBasicDType(FileLine* fl, AstBasicDTypeKwd kwd) {
|
||||
if (m_basicps[kwd]) return m_basicps[kwd];
|
||||
//
|
||||
AstBasicDType* new1p = new AstBasicDType(fl, kwd);
|
||||
// Because the detailed map doesn't update this map,
|
||||
// check the detailed map for this same node
|
||||
// Also adds this new node to the detailed map
|
||||
AstBasicDType* newp = findInsertSameDType(new1p);
|
||||
if (newp != new1p) new1p->deleteTree();
|
||||
else addTypesp(newp);
|
||||
//
|
||||
m_basicps[kwd] = newp;
|
||||
return newp;
|
||||
}
|
||||
|
||||
AstBasicDType* AstTypeTable::findLogicBitDType(FileLine* fl, AstBasicDTypeKwd kwd,
|
||||
int width, int widthMin, AstNumeric numeric) {
|
||||
int idx = IDX0_LOGIC;
|
||||
if (kwd == AstBasicDTypeKwd::LOGIC) idx = IDX0_LOGIC;
|
||||
else if (kwd == AstBasicDTypeKwd::BIT) idx = IDX0_BIT;
|
||||
else fl->v3fatalSrc("Bad kwd for findLogicBitDType");
|
||||
pair<int,int> widths = make_pair(width,widthMin);
|
||||
LogicMap& mapr = m_logicMap[idx][(int)numeric];
|
||||
LogicMap::const_iterator it = mapr.find(widths);
|
||||
if (it != mapr.end()) return it->second;
|
||||
//
|
||||
AstBasicDType* new1p = new AstBasicDType(fl, kwd, numeric, width, widthMin);
|
||||
// Because the detailed map doesn't update this map,
|
||||
// check the detailed map for this same node, and if found update this map
|
||||
// Also adds this new node to the detailed map
|
||||
AstBasicDType* newp = findInsertSameDType(new1p);
|
||||
if (newp != new1p) new1p->deleteTree();
|
||||
else addTypesp(newp);
|
||||
//
|
||||
mapr.insert(make_pair(widths,newp));
|
||||
return newp;
|
||||
}
|
||||
|
||||
AstBasicDType* AstTypeTable::findLogicBitDType(FileLine* fl, AstBasicDTypeKwd kwd,
|
||||
VNumRange range, int widthMin, AstNumeric numeric) {
|
||||
AstBasicDType* new1p = new AstBasicDType(fl, kwd, numeric, range, widthMin);
|
||||
AstBasicDType* newp = findInsertSameDType(new1p);
|
||||
if (newp != new1p) new1p->deleteTree();
|
||||
else addTypesp(newp);
|
||||
return newp;
|
||||
}
|
||||
|
||||
AstBasicDType* AstTypeTable::findInsertSameDType(AstBasicDType* nodep) {
|
||||
VBasicTypeKey key (nodep->width(), nodep->widthMin(), nodep->numeric(),
|
||||
nodep->keyword(), nodep->nrange());
|
||||
DetailedMap& mapr = m_detailedMap;
|
||||
DetailedMap::const_iterator it = mapr.find(key);
|
||||
if (it != mapr.end()) return it->second;
|
||||
mapr.insert(make_pair(key,nodep));
|
||||
nodep->generic(true);
|
||||
// No addTypesp; the upper function that called new() is responsible for adding
|
||||
return nodep;
|
||||
}
|
||||
|
||||
//======================================================================
|
||||
// Special walking tree inserters
|
||||
|
||||
@@ -496,23 +670,34 @@ void AstWhile::addNextStmt(AstNode* newp, AstNode* belowp) {
|
||||
//======================================================================
|
||||
// Per-type Debugging
|
||||
|
||||
void AstNode::dump(ostream& os) {
|
||||
os<<typeName()<<" "<<(void*)this
|
||||
void AstNode::dump(ostream& str) {
|
||||
str<<typeName()<<" "<<(void*)this
|
||||
//<<" "<<(void*)this->m_backp
|
||||
<<" <e"<<dec<<editCount()
|
||||
<<((editCount()>=editCountLast())?"#>":">")
|
||||
<<" {"<<fileline()->filenameLetters()<<dec<<fileline()->lineno()<<"}"
|
||||
<<" "<<(isSigned()?"s":"")
|
||||
<<(isDouble()?"d":"")
|
||||
<<"w"<<(widthSized()?"":"u")<<width();
|
||||
if (!widthSized()) os<<"/"<<widthMin();
|
||||
if (name()!="") os<<" "<<AstNode::quoteName(name());
|
||||
<<" <e"<<dec<<editCount()
|
||||
<<((editCount()>=editCountLast())?"#>":">")
|
||||
<<" {"<<fileline()->filenameLetters()<<dec<<fileline()->lineno()<<"}";
|
||||
if (user1p()) str<<" u1="<<(void*)user1p();
|
||||
if (user2p()) str<<" u2="<<(void*)user2p();
|
||||
if (user3p()) str<<" u3="<<(void*)user3p();
|
||||
if (user4p()) str<<" u4="<<(void*)user4p();
|
||||
if (user5p()) str<<" u5="<<(void*)user5p();
|
||||
if (hasDType()) {
|
||||
if (dtypep()==this) str<<" @dt="<<"this@";
|
||||
else str<<" @dt="<<(void*)dtypep()<<"@"; // Final @ so less likely to by accident think it's nodep
|
||||
if (AstNodeDType* dtp = dtypep()) {
|
||||
dtp->dumpSmall(str);
|
||||
}
|
||||
} else { // V3Broken will throw an error
|
||||
if (dtypep()) str<<" %Error-dtype-exp=null,got="<<(void*)dtypep();
|
||||
}
|
||||
if (name()!="") str<<" "<<AstNode::quoteName(name());
|
||||
}
|
||||
|
||||
void AstArrayDType::dump(ostream& str) {
|
||||
void AstAlways::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
if (isPacked()) str<<" [PACKED]";
|
||||
if (keyword() != VAlwaysKwd::ALWAYS) str<<" ["<<keyword().ascii()<<"]";
|
||||
}
|
||||
|
||||
void AstArraySel::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
str<<" [start:"<<start()<<"] [length:"<<length()<<"]";
|
||||
@@ -522,9 +707,9 @@ void AstAttrOf::dump(ostream& str) {
|
||||
str<<" ["<<attrType().ascii()<<"]";
|
||||
}
|
||||
void AstBasicDType::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
str<<" ["<<keyword().ascii()<<"]";
|
||||
if (implicit()) str<<" [IMPLICIT]";
|
||||
this->AstNodeDType::dump(str);
|
||||
str<<" kwd="<<keyword().ascii();
|
||||
if (isRanged() && !rangep()) str<<" range=["<<left()<<":"<<right()<<"]";
|
||||
}
|
||||
void AstCCast::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
@@ -543,17 +728,36 @@ void AstDisplay::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
//str<<" "<<displayType().ascii();
|
||||
}
|
||||
void AstEnumItemRef::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
str<<" -> ";
|
||||
if (itemp()) { itemp()->dump(str); }
|
||||
else { str<<"UNLINKED"; }
|
||||
}
|
||||
void AstIfaceRefDType::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
if (cellName()!="") { str<<" cell="<<cellName(); }
|
||||
if (ifaceName()!="") { str<<" if="<<ifaceName(); }
|
||||
if (modportName()!="") { str<<" mp="<<modportName(); }
|
||||
if (cellp()) { str<<" -> "; cellp()->dump(str); }
|
||||
else if (ifacep()) { str<<" -> "; ifacep()->dump(str); }
|
||||
else { str<<" -> UNLINKED"; }
|
||||
}
|
||||
void AstIfaceRefDType::dumpSmall(ostream& str) {
|
||||
this->AstNodeDType::dumpSmall(str);
|
||||
str<<"iface";
|
||||
}
|
||||
void AstJumpGo::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
str<<" -> ";
|
||||
if (labelp()) { labelp()->dump(str); }
|
||||
else { str<<"%Error:UNLINKED"; }
|
||||
}
|
||||
void AstEnumItemRef::dump(ostream& str) {
|
||||
void AstModportVarRef::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
str<<" -> ";
|
||||
if (itemp()) { itemp()->dump(str); }
|
||||
else { str<<"UNLINKED"; }
|
||||
str<<" "<<varType();
|
||||
if (varp()) { str<<" -> "; varp()->dump(str); }
|
||||
else { str<<" -> UNLINKED"; }
|
||||
}
|
||||
void AstPin::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
@@ -566,38 +770,118 @@ void AstRange::dump(ostream& str) {
|
||||
if (littleEndian()) str<<" [LITTLE]";
|
||||
}
|
||||
void AstRefDType::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
this->AstNodeDType::dump(str);
|
||||
if (defp()) { str<<" -> "; defp()->dump(str); }
|
||||
else { str<<" -> UNLINKED"; }
|
||||
}
|
||||
void AstVarXRef::dump(ostream& str) {
|
||||
void AstNodeClassDType::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
if (lvalue()) str<<" [LV] => ";
|
||||
else str<<" [RV] <- ";
|
||||
str<<dotted()<<". - ";
|
||||
if (inlinedDots()!="") str<<" flat.="<<inlinedDots()<<" - ";
|
||||
if (varScopep()) { varScopep()->dump(str); }
|
||||
else if (varp()) { varp()->dump(str); }
|
||||
else { str<<"UNLINKED"; }
|
||||
if (packed()) str<<" [PACKED]";
|
||||
}
|
||||
void AstNodeDType::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
if (generic()) str<<" [GENERIC]";
|
||||
if (AstNodeDType* dtp = virtRefDTypep()) {
|
||||
str<<" refdt="<<(void*)(dtp);
|
||||
dtp->dumpSmall(str);
|
||||
}
|
||||
}
|
||||
void AstNodeDType::dumpSmall(ostream& str) {
|
||||
str<<"("
|
||||
<<(generic()?"G/":"")
|
||||
<<((isSigned()&&!isDouble())?"s":"")
|
||||
<<(isNosign()?"n":"")
|
||||
<<(isDouble()?"d":"")
|
||||
<<"w"<<(widthSized()?"":"u")<<width();
|
||||
if (!widthSized()) str<<"/"<<widthMin();
|
||||
str<<")";
|
||||
}
|
||||
void AstNodeArrayDType::dumpSmall(ostream& str) {
|
||||
this->AstNodeDType::dumpSmall(str);
|
||||
if (castPackArrayDType()) str<<"p"; else str<<"u";
|
||||
str<<"["<<declRange().left()<<":"<<declRange().right()<<"]";
|
||||
}
|
||||
void AstNodeArrayDType::dump(ostream& str) {
|
||||
this->AstNodeDType::dump(str);
|
||||
str<<" ["<<declRange().left()<<":"<<declRange().right()<<"]";
|
||||
}
|
||||
void AstNodeModule::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
str<<" L"<<level();
|
||||
if (modPublic()) str<<" [P]";
|
||||
if (inLibrary()) str<<" [LIB]";
|
||||
if (dead()) str<<" [DEAD]";
|
||||
}
|
||||
void AstPackageImport::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
str<<" -> "<<packagep();
|
||||
}
|
||||
void AstSel::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
if (declRange().ranged()) {
|
||||
str<<" decl["<<declRange().left()<<":"<<declRange().right()<<"]";
|
||||
if (declElWidth()!=1) str<<"/"<<declElWidth();
|
||||
}
|
||||
}
|
||||
void AstTypeTable::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
for (int i=0; i<(int)(AstBasicDTypeKwd::_ENUM_MAX); ++i) {
|
||||
if (AstBasicDType* subnodep=m_basicps[i]) {
|
||||
str<<endl; // Newline from caller, so newline first
|
||||
str<<"\t\t"<<setw(8)<<AstBasicDTypeKwd(i).ascii();
|
||||
str<<" -> ";
|
||||
subnodep->dump(str);
|
||||
}
|
||||
}
|
||||
for (int isbit=0; isbit<2; ++isbit) {
|
||||
for (int issigned=0; issigned<AstNumeric::_ENUM_MAX; ++issigned) {
|
||||
LogicMap& mapr = m_logicMap[isbit][issigned];
|
||||
for (LogicMap::const_iterator it = mapr.begin(); it != mapr.end(); ++it) {
|
||||
AstBasicDType* dtypep = it->second;
|
||||
str<<endl; // Newline from caller, so newline first
|
||||
stringstream nsstr;
|
||||
nsstr<<(isbit?"bw":"lw")
|
||||
<<it->first.first<<"/"<<it->first.second;
|
||||
str<<"\t\t"<<setw(8)<<nsstr.str();
|
||||
if (issigned) str<<" s"; else str<<" u";
|
||||
str<<" -> ";
|
||||
dtypep->dump(str);
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
DetailedMap& mapr = m_detailedMap;
|
||||
for (DetailedMap::const_iterator it = mapr.begin(); it != mapr.end(); ++it) {
|
||||
AstBasicDType* dtypep = it->second;
|
||||
str<<endl; // Newline from caller, so newline first
|
||||
stringstream nsstr;
|
||||
str<<"\t\tdetailed -> ";
|
||||
dtypep->dump(str);
|
||||
}
|
||||
}
|
||||
// Note get newline from caller too.
|
||||
}
|
||||
|
||||
void AstVarScope::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
if (isCircular()) str<<" [CIRC]";
|
||||
if (varp()) { str<<" -> "; varp()->dump(str); }
|
||||
else { str<<" ->UNLINKED"; }
|
||||
}
|
||||
void AstVarXRef::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
if (packagep()) { str<<" pkg="<<(void*)packagep(); }
|
||||
if (lvalue()) str<<" [LV] => ";
|
||||
else str<<" [RV] <- ";
|
||||
str<<dotted()<<". - ";
|
||||
if (inlinedDots()!="") str<<" inline.="<<inlinedDots()<<" - ";
|
||||
if (varScopep()) { varScopep()->dump(str); }
|
||||
else if (varp()) { varp()->dump(str); }
|
||||
else { str<<"UNLINKED"; }
|
||||
}
|
||||
void AstVarRef::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
if (packagep()) { str<<" pkg="<<(void*)packagep(); }
|
||||
if (lvalue()) str<<" [LV] => ";
|
||||
else str<<" [RV] <- ";
|
||||
if (varScopep()) { varScopep()->dump(str); }
|
||||
@@ -614,9 +898,11 @@ void AstVar::dump(ostream& str) {
|
||||
else if (isOutput()) str<<" [O]";
|
||||
}
|
||||
if (isConst()) str<<" [CONST]";
|
||||
if (isPullup()) str<<" [PULLUP]";
|
||||
if (isPulldown()) str<<" [PULLDOWN]";
|
||||
if (isUsedClock()) str<<" [CLK]";
|
||||
if (isSigPublic()) str<<" [P]";
|
||||
if (isUsedLoopIdx()) str<<" [LOOP]";
|
||||
if (isUsedLoopIdx()) str<<" [LOOP]";
|
||||
if (attrClockEn()) str<<" [aCLKEN]";
|
||||
if (attrIsolateAssign()) str<<" [aISO]";
|
||||
if (attrFileDescr()) str<<" [aFD]";
|
||||
@@ -636,6 +922,16 @@ void AstParseRef::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
str<<" ["<<expect().ascii()<<"]";
|
||||
}
|
||||
void AstPackageRef::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
if (packagep()) { str<<" pkg="<<(void*)packagep(); }
|
||||
str<<" -> ";
|
||||
if (packagep()) { packagep()->dump(str); }
|
||||
else { str<<"UNLINKED"; }
|
||||
}
|
||||
void AstDot::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
}
|
||||
void AstActive::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
str<<" => ";
|
||||
@@ -644,6 +940,7 @@ void AstActive::dump(ostream& str) {
|
||||
}
|
||||
void AstNodeFTaskRef::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
if (packagep()) { str<<" pkg="<<(void*)packagep(); }
|
||||
str<<" -> ";
|
||||
if (dotted()!="") { str<<dotted()<<". - "; }
|
||||
if (taskp()) { taskp()->dump(str); }
|
||||
@@ -660,6 +957,8 @@ void AstNodeFTask::dump(ostream& str) {
|
||||
void AstBegin::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
if (unnamed()) str<<" [UNNAMED]";
|
||||
if (generate()) str<<" [GEN]";
|
||||
if (genforp()) str<<" [GENFOR]";
|
||||
}
|
||||
void AstCoverDecl::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
|
||||
+1056
-395
File diff suppressed because it is too large
Load Diff
+103
-21
@@ -1,13 +1,12 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: Removal of named begin blocks
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2013 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.
|
||||
@@ -45,9 +44,31 @@
|
||||
|
||||
//######################################################################
|
||||
|
||||
class BeginState {
|
||||
private:
|
||||
// NODE STATE
|
||||
//Entire netlist:
|
||||
// AstNodeFTask::user1 -> bool, 1=processed
|
||||
AstUser1InUse m_inuser1;
|
||||
bool m_anyFuncInBegin;
|
||||
public:
|
||||
BeginState() {
|
||||
m_anyFuncInBegin = false;
|
||||
}
|
||||
~BeginState() {}
|
||||
void userMarkChanged(AstNodeFTask* nodep) {
|
||||
nodep->user1(true);
|
||||
m_anyFuncInBegin = true;
|
||||
}
|
||||
bool anyFuncInBegin() const { return m_anyFuncInBegin; }
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
||||
class BeginVisitor : public AstNVisitor {
|
||||
private:
|
||||
// STATE
|
||||
BeginState* m_statep; // Current global state
|
||||
AstNodeModule* m_modp; // Current module
|
||||
AstNodeFTask* m_ftaskp; // Current function/task
|
||||
string m_namedScope; // Name of begin blocks above us
|
||||
@@ -70,9 +91,27 @@ private:
|
||||
m_modp = NULL;
|
||||
}
|
||||
virtual void visit(AstNodeFTask* nodep, AstNUser*) {
|
||||
m_ftaskp = nodep;
|
||||
nodep->iterateChildren(*this);
|
||||
m_ftaskp = NULL;
|
||||
UINFO(8," "<<nodep<<endl);
|
||||
// Rename it
|
||||
if (m_unnamedScope != "") {
|
||||
nodep->name(m_unnamedScope+"__DOT__"+nodep->name());
|
||||
UINFO(8," rename to "<<nodep->name()<<endl);
|
||||
m_statep->userMarkChanged(nodep);
|
||||
}
|
||||
// BEGIN wrapping a function rename that function, but don't affect the inside function's variables
|
||||
// We then restart with empty naming; so that any begin's inside the function will rename inside the function
|
||||
// Process children
|
||||
string oldScope = m_namedScope;
|
||||
string oldUnnamed = m_unnamedScope;
|
||||
{
|
||||
m_namedScope = "";
|
||||
m_unnamedScope = "";
|
||||
m_ftaskp = nodep;
|
||||
nodep->iterateChildren(*this);
|
||||
m_ftaskp = NULL;
|
||||
}
|
||||
m_namedScope = oldScope;
|
||||
m_unnamedScope = oldUnnamed;
|
||||
}
|
||||
virtual void visit(AstBegin* nodep, AstNUser*) {
|
||||
// Begin blocks were only useful in variable creation, change names and delete
|
||||
@@ -80,7 +119,7 @@ private:
|
||||
string oldScope = m_namedScope;
|
||||
string oldUnnamed = m_unnamedScope;
|
||||
{
|
||||
//UINFO(8,"nname "<<m_namedScope<<endl);
|
||||
UINFO(8,"nname "<<m_namedScope<<endl);
|
||||
if (nodep->name() != "") { // Else unneeded unnamed block
|
||||
// Create data for dotted variable resolution
|
||||
string dottedname = nodep->name() + "__DOT__"; // So always found
|
||||
@@ -95,25 +134,33 @@ private:
|
||||
if (m_unnamedScope=="") m_unnamedScope = ident;
|
||||
else m_unnamedScope = m_unnamedScope + "__DOT__"+ident;
|
||||
// Create CellInline for dotted var resolution
|
||||
AstCellInline* inlinep = new AstCellInline(nodep->fileline(),
|
||||
m_unnamedScope, "__BEGIN__");
|
||||
m_modp->addInlinesp(inlinep); // Must be parsed before any AstCells
|
||||
if (!m_ftaskp) {
|
||||
AstCellInline* inlinep = new AstCellInline(nodep->fileline(),
|
||||
m_unnamedScope, "__BEGIN__");
|
||||
m_modp->addInlinesp(inlinep); // Must be parsed before any AstCells
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remap var names and replace lower Begins
|
||||
nodep->iterateChildren(*this);
|
||||
|
||||
if (AstNode* stmtsp = nodep->stmtsp()) {
|
||||
stmtsp->unlinkFrBackWithNext();
|
||||
nodep->replaceWith(stmtsp);
|
||||
} else {
|
||||
nodep->unlinkFrBack();
|
||||
}
|
||||
pushDeletep(nodep); nodep=NULL;
|
||||
nodep->stmtsp()->iterateAndNext(*this);
|
||||
if (nodep->genforp()) nodep->v3fatalSrc("GENFORs should have been expanded earlier");
|
||||
}
|
||||
m_namedScope = oldScope;
|
||||
m_unnamedScope = oldUnnamed;
|
||||
|
||||
// Cleanup
|
||||
AstNode* addsp = NULL;
|
||||
if (AstNode* stmtsp = nodep->stmtsp()) {
|
||||
stmtsp->unlinkFrBackWithNext();
|
||||
if (addsp) { addsp = addsp->addNextNull(stmtsp); } else { addsp = stmtsp; }
|
||||
}
|
||||
if (addsp) {
|
||||
nodep->replaceWith(addsp);
|
||||
} else {
|
||||
nodep->unlinkFrBack();
|
||||
}
|
||||
pushDeletep(nodep); nodep=NULL;
|
||||
}
|
||||
virtual void visit(AstVar* nodep, AstNUser*) {
|
||||
if (m_unnamedScope != "") {
|
||||
@@ -139,6 +186,7 @@ private:
|
||||
virtual void visit(AstScopeName* nodep, AstNUser*) {
|
||||
// If there's a %m in the display text, we add a special node that will contain the name()
|
||||
// Similar code in V3Inline
|
||||
if (nodep->user1SetOnce()) return; // Don't double-add text's
|
||||
if (m_namedScope != "") {
|
||||
// To keep correct visual order, must add before other Text's
|
||||
AstNode* afterp = nodep->scopeAttrp();
|
||||
@@ -173,7 +221,8 @@ private:
|
||||
}
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
BeginVisitor(AstNetlist* nodep) {
|
||||
BeginVisitor(AstNetlist* nodep, BeginState* statep) {
|
||||
m_statep = statep;
|
||||
m_modp = NULL;
|
||||
m_ftaskp = NULL;
|
||||
m_repeatNum = 0;
|
||||
@@ -183,10 +232,43 @@ public:
|
||||
virtual ~BeginVisitor() {}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
||||
class BeginRelinkVisitor : public AstNVisitor {
|
||||
// Replace tasks with new pointer
|
||||
private:
|
||||
// NODE STATE
|
||||
// Input:
|
||||
// AstNodeFTask::user1p // Node replaced, rename it
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstNodeFTaskRef* nodep, AstNUser*) {
|
||||
if (nodep->taskp()->user1()) { // It was converted
|
||||
UINFO(9, " relinkFTask "<<nodep<<endl);
|
||||
nodep->name(nodep->taskp()->name());
|
||||
}
|
||||
nodep->iterateChildren(*this);
|
||||
}
|
||||
//--------------------
|
||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
}
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
BeginRelinkVisitor(AstNetlist* nodep, BeginState*) {
|
||||
nodep->accept(*this);
|
||||
}
|
||||
virtual ~BeginRelinkVisitor() {}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
// Task class functions
|
||||
|
||||
void V3Begin::debeginAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
BeginVisitor bvisitor (nodep);
|
||||
BeginState state;
|
||||
{ BeginVisitor bvisitor (nodep,&state); }
|
||||
if (state.anyFuncInBegin()) {
|
||||
BeginRelinkVisitor brvisitor (nodep,&state);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-4
@@ -1,14 +1,12 @@
|
||||
// -*- C++ -*-
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: Removal of named begin blocks
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2013 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.
|
||||
|
||||
+2
-3
@@ -1,13 +1,12 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: Branch prediction
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2013 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.
|
||||
|
||||
+2
-4
@@ -1,14 +1,12 @@
|
||||
// -*- C++ -*-
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: Branch prediction
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2013 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+39
-17
@@ -1,13 +1,12 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: Find broken links in tree
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2013 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.
|
||||
@@ -57,7 +56,7 @@ public:
|
||||
// METHODS
|
||||
static void deleted(const AstNode* nodep) {
|
||||
// Called by operator delete on any node - only if VL_LEAK_CHECKS
|
||||
if (debug()) cout<<"-nodeDel: "<<(void*)(nodep)<<endl;
|
||||
if (debug()>=9) cout<<"-nodeDel: "<<(void*)(nodep)<<endl;
|
||||
NodeMap::iterator iter = s_nodes.find(nodep);
|
||||
if (iter==s_nodes.end() || !(iter->second & FLAG_ALLOCATED)) {
|
||||
((AstNode*)(nodep))->v3fatalSrc("Deleting AstNode object that was never tracked or already deleted\n");
|
||||
@@ -66,7 +65,7 @@ public:
|
||||
}
|
||||
static void addNewed(const AstNode* nodep) {
|
||||
// Called by operator new on any node - only if VL_LEAK_CHECKS
|
||||
if (debug()) cout<<"-nodeNew: "<<(void*)(nodep)<<endl;
|
||||
if (debug()>=9) cout<<"-nodeNew: "<<(void*)(nodep)<<endl;
|
||||
NodeMap::iterator iter = s_nodes.find(nodep);
|
||||
if (iter!=s_nodes.end() || (iter->second & FLAG_ALLOCATED)) {
|
||||
((AstNode*)(nodep))->v3fatalSrc("Newing AstNode object that is already allocated\n");
|
||||
@@ -147,7 +146,7 @@ public:
|
||||
&& (it->first->backp() ? backs==1 : backs==0)) {
|
||||
// Use only AstNode::dump instead of the virtual one, as there
|
||||
// may be varp() and other cross links that are bad.
|
||||
if (debug()) {
|
||||
if (v3Global.opt.debugCheck()) {
|
||||
cerr<<"%Error: LeakedNode"<<(it->first->backp()?"Back: ":": ");
|
||||
((AstNode*)(it->first))->AstNode::dump(cerr);
|
||||
cerr<<endl;
|
||||
@@ -203,15 +202,30 @@ class BrokenCheckVisitor : public AstNVisitor {
|
||||
private:
|
||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||
BrokenTable::setUnder(nodep,true);
|
||||
if (nodep->broken()) {
|
||||
nodep->v3fatalSrc("Broken link in node (or something without maybePointedTo)\n");
|
||||
if (const char* whyp=nodep->broken()) {
|
||||
nodep->v3fatalSrc("Broken link in node (or something without maybePointedTo): "<<whyp);
|
||||
}
|
||||
if (v3Global.assertWidthsSame()) {
|
||||
if (nodep->width() != nodep->widthMin()) {
|
||||
nodep->v3fatalSrc("Width != WidthMin\n");
|
||||
if (nodep->dtypep()) {
|
||||
if (!nodep->dtypep()->brokeExists()) { nodep->v3fatalSrc("Broken link in node->dtypep() to "<<(void*)nodep->dtypep()); }
|
||||
else if (!nodep->dtypep()->castNodeDType()) { nodep->v3fatalSrc("Non-dtype link in node->dtypep() to "<<(void*)nodep->dtypep()); }
|
||||
}
|
||||
if (v3Global.assertDTypesResolved()) {
|
||||
if (nodep->hasDType()) {
|
||||
if (!nodep->dtypep()) nodep->v3fatalSrc("No dtype on node with hasDType(): "<<nodep->prettyTypeName());
|
||||
} else {
|
||||
if (nodep->dtypep()) nodep->v3fatalSrc("DType on node without hasDType(): "<<nodep->prettyTypeName());
|
||||
}
|
||||
if (!nodep->width() && nodep->castNodeMath()) {
|
||||
nodep->v3fatalSrc("Math node has no assigned width\n");
|
||||
if (nodep->getChildDTypep()) nodep->v3fatalSrc("childDTypep() non-null on node after should have removed");
|
||||
if (AstNodeDType* dnodep = nodep->castNodeDType()) {
|
||||
if (dnodep->width() != dnodep->widthMin()
|
||||
&& v3Global.assertWidthsMatch()) {
|
||||
dnodep->v3fatalSrc("Width != WidthMin");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (v3Global.assertWidthsMatch()) {
|
||||
if (nodep->width() != nodep->widthMin()) {
|
||||
nodep->v3fatalSrc("Width != WidthMin");
|
||||
}
|
||||
}
|
||||
nodep->iterateChildren(*this);
|
||||
@@ -230,10 +244,18 @@ public:
|
||||
|
||||
void V3Broken::brokenAll(AstNetlist* nodep) {
|
||||
//UINFO(9,__FUNCTION__<<": "<<endl);
|
||||
BrokenTable::prepForTree();
|
||||
BrokenMarkVisitor mvisitor (nodep);
|
||||
BrokenCheckVisitor cvisitor (nodep);
|
||||
BrokenTable::doneWithTree();
|
||||
static bool inBroken = false;
|
||||
if (inBroken) {
|
||||
// A error called by broken can recurse back into broken; avoid this
|
||||
UINFO(1,"Broken called under broken, skipping recursion.\n");
|
||||
} else {
|
||||
inBroken = true;
|
||||
BrokenTable::prepForTree();
|
||||
BrokenMarkVisitor mvisitor (nodep);
|
||||
BrokenCheckVisitor cvisitor (nodep);
|
||||
BrokenTable::doneWithTree();
|
||||
inBroken = false;
|
||||
}
|
||||
}
|
||||
|
||||
void V3Broken::addNewed(AstNode* nodep) {
|
||||
|
||||
+2
-4
@@ -1,14 +1,12 @@
|
||||
// -*- C++ -*-
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: Find broken links in tree
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2013 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
-4
@@ -1,13 +1,12 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: Break case statements up and add Unknown assigns
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2013 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.
|
||||
@@ -197,7 +196,7 @@ private:
|
||||
}
|
||||
}
|
||||
}
|
||||
// Defaults were moved to last in the caseitem list by V3Link
|
||||
// Defaults were moved to last in the caseitem list by V3LinkDot
|
||||
if (itemp->isDefault()) { // Case statement's default... Fill the table
|
||||
for (uint32_t i=0; i<(1UL<<m_caseWidth); i++) {
|
||||
if (!m_valueItem[i]) m_valueItem[i] = itemp;
|
||||
|
||||
+2
-4
@@ -1,14 +1,12 @@
|
||||
// -*- C++ -*-
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: Break case statements up and add Unknown assigns
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2013 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
-5
@@ -1,13 +1,12 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: Add C++ casts across expression size changes
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2004-2011 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2004-2013 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.
|
||||
@@ -77,8 +76,7 @@ private:
|
||||
AstNRelinker relinkHandle;
|
||||
nodep->unlinkFrBack(&relinkHandle);
|
||||
//
|
||||
AstCCast* castp = new AstCCast (nodep->fileline(), nodep, needsize);
|
||||
castp->width(needsize, nodep->widthMin());
|
||||
AstCCast* castp = new AstCCast (nodep->fileline(), nodep, needsize, nodep->widthMin());
|
||||
relinkHandle.relink(castp);
|
||||
//if (debug()>8) castp->dumpTree(cout,"-castins: ");
|
||||
//
|
||||
|
||||
+2
-4
@@ -1,14 +1,12 @@
|
||||
// -*- C++ -*-
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: Add C++ casts across expression size changes
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2004-2011 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2004-2013 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.
|
||||
|
||||
+6
-7
@@ -1,13 +1,12 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: Clock Domain Crossing Lint
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2013 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.
|
||||
@@ -361,7 +360,7 @@ private:
|
||||
CdcEitherVertex* traceAsyncRecurse(CdcEitherVertex* vertexp, bool mark) {
|
||||
// First pass: Return vertex of any hazardous stuff attached, or NULL if OK
|
||||
// If first pass returns true, second pass calls asyncPath() on appropriate nodes
|
||||
if (vertexp->user()>=m_userGeneration) return false; // Processed - prevent loop
|
||||
if (vertexp->user()>=m_userGeneration) return NULL; // Processed - prevent loop
|
||||
vertexp->user(m_userGeneration);
|
||||
|
||||
CdcEitherVertex* mark_outp = NULL;
|
||||
@@ -384,7 +383,7 @@ private:
|
||||
CdcEitherVertex* eFromVertexp = (CdcEitherVertex*)edgep->fromp();
|
||||
eFromVertexp->asyncPath(true);
|
||||
}
|
||||
return false;
|
||||
return NULL;
|
||||
}
|
||||
// Also ok if from flop, but partially trace the flop so more obvious to users
|
||||
if (vvertexp->fromFlop()) {
|
||||
@@ -392,7 +391,7 @@ private:
|
||||
CdcEitherVertex* eFromVertexp = (CdcEitherVertex*)edgep->fromp();
|
||||
eFromVertexp->asyncPath(true);
|
||||
}
|
||||
return false;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -527,7 +526,7 @@ private:
|
||||
}
|
||||
}
|
||||
}
|
||||
sort(report.begin(), report.end());
|
||||
stable_sort(report.begin(), report.end());
|
||||
for (deque<string>::iterator it = report.begin(); it!=report.end(); ++it) {
|
||||
*ofp << *it;
|
||||
}
|
||||
|
||||
+2
-4
@@ -1,14 +1,12 @@
|
||||
// -*- C++ -*-
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: Break always into sensitivity block domains
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2013 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.
|
||||
|
||||
+49
-17
@@ -1,13 +1,12 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: Add temporaries, such as for changed nodes
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2013 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.
|
||||
@@ -59,6 +58,12 @@ private:
|
||||
AstScope* m_scopetopp; // Scope under TOPSCOPE
|
||||
AstCFunc* m_chgFuncp; // Change function we're building
|
||||
|
||||
// CONSTANTS
|
||||
enum MiscConsts {
|
||||
DETECTARRAY_MAX_INDEXES = 256 // How many indexes before error
|
||||
// Ok to increase this, but may result in much slower model
|
||||
};
|
||||
|
||||
// METHODS
|
||||
static int debug() {
|
||||
static int level = -1;
|
||||
@@ -66,14 +71,35 @@ private:
|
||||
return level;
|
||||
}
|
||||
|
||||
AstNode* aselIfNeeded(bool isArray, int index, AstNode* childp) {
|
||||
if (isArray) {
|
||||
return new AstArraySel(childp->fileline(), childp,
|
||||
new AstConst(childp->fileline(), index));
|
||||
} else {
|
||||
return childp;
|
||||
}
|
||||
}
|
||||
|
||||
void genChangeDet(AstVarScope* vscp) {
|
||||
#ifdef NEW_ORDERING
|
||||
vscp->v3fatalSrc("Not applicable\n");
|
||||
#endif
|
||||
AstVar* varp = vscp->varp();
|
||||
vscp->v3warn(IMPERFECTSCH,"Imperfect scheduling of variable: "<<vscp);
|
||||
if (!varp->dtypeSkipRefp()->castBasicDType()) {
|
||||
vscp->v3error("Unsupported: Can't detect changes on arrayed variable (probably with UNOPTFLAT warning suppressed): "<<varp->prettyName());
|
||||
AstUnpackArrayDType* arrayp = varp->dtypeSkipRefp()->castUnpackArrayDType();
|
||||
AstStructDType *structp = varp->dtypeSkipRefp()->castStructDType();
|
||||
bool isArray = arrayp;
|
||||
bool isStruct = structp && structp->packed();
|
||||
int elements = isArray ? arrayp->elementsConst() : 1;
|
||||
if (isArray && (elements > DETECTARRAY_MAX_INDEXES)) {
|
||||
vscp->v3warn(E_DETECTARRAY, "Unsupported: Can't detect more than "<<cvtToStr(DETECTARRAY_MAX_INDEXES)
|
||||
<<" array indexes (probably with UNOPTFLAT warning suppressed): "<<varp->prettyName()<<endl
|
||||
<<vscp->warnMore()
|
||||
<<"... Could recompile with DETECTARRAY_MAX_INDEXES increased to at least "<<cvtToStr(elements));
|
||||
} else if (!isArray && !isStruct
|
||||
&& !varp->dtypeSkipRefp()->castBasicDType()) {
|
||||
if (debug()) varp->dumpTree(cout,"-DETECTARRAY-");
|
||||
vscp->v3warn(E_DETECTARRAY, "Unsupported: Can't detect changes on complex variable (probably with UNOPTFLAT warning suppressed): "<<varp->prettyName());
|
||||
} else {
|
||||
string newvarname = "__Vchglast__"+vscp->scopep()->nameDotless()+"__"+varp->shortName();
|
||||
// Create: VARREF(_last)
|
||||
@@ -84,17 +110,23 @@ private:
|
||||
m_topModp->addStmtp(newvarp);
|
||||
AstVarScope* newvscp = new AstVarScope(vscp->fileline(), m_scopetopp, newvarp);
|
||||
m_scopetopp->addVarp(newvscp);
|
||||
AstChangeDet* changep
|
||||
= new AstChangeDet (vscp->fileline(),
|
||||
new AstVarRef(vscp->fileline(), vscp, false),
|
||||
new AstVarRef(vscp->fileline(), newvscp, false),
|
||||
false);
|
||||
m_chgFuncp->addStmtsp(changep);
|
||||
AstAssign* initp
|
||||
= new AstAssign (vscp->fileline(),
|
||||
new AstVarRef(vscp->fileline(), newvscp, true),
|
||||
new AstVarRef(vscp->fileline(), vscp, false));
|
||||
m_chgFuncp->addFinalsp(initp);
|
||||
for (int index=0; index<elements; ++index) {
|
||||
AstChangeDet* changep
|
||||
= new AstChangeDet (vscp->fileline(),
|
||||
aselIfNeeded(isArray, index,
|
||||
new AstVarRef(vscp->fileline(), vscp, false)),
|
||||
aselIfNeeded(isArray, index,
|
||||
new AstVarRef(vscp->fileline(), newvscp, false)),
|
||||
false);
|
||||
m_chgFuncp->addStmtsp(changep);
|
||||
AstAssign* initp
|
||||
= new AstAssign (vscp->fileline(),
|
||||
aselIfNeeded(isArray, index,
|
||||
new AstVarRef(vscp->fileline(), newvscp, true)),
|
||||
aselIfNeeded(isArray, index,
|
||||
new AstVarRef(vscp->fileline(), vscp, false)));
|
||||
m_chgFuncp->addFinalsp(initp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,7 +160,7 @@ private:
|
||||
virtual void visit(AstVarScope* nodep, AstNUser*) {
|
||||
if (nodep->isCircular()) {
|
||||
UINFO(8," CIRC "<<nodep<<endl);
|
||||
if (!nodep->user1Inc()) {
|
||||
if (!nodep->user1SetOnce()) {
|
||||
genChangeDet(nodep);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-4
@@ -1,14 +1,12 @@
|
||||
// -*- C++ -*-
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: Pre C-Emit stage changes
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2013 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+24
-11
@@ -1,13 +1,12 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: Add temporaries, such as for clean nodes
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2013 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -24,7 +23,7 @@
|
||||
// For each math operator, if it requires a clean operand,
|
||||
// and the operand is dirty, insert a CLEAN node.
|
||||
// Resize operands to C++ 32/64/wide types.
|
||||
// Copy all width() values to minWidth() so RANGE, etc can still see orig widths
|
||||
// Copy all width() values to widthMin() so RANGE, etc can still see orig widths
|
||||
//
|
||||
//*************************************************************************
|
||||
|
||||
@@ -47,9 +46,11 @@ private:
|
||||
// NODE STATE
|
||||
// Entire netlist:
|
||||
// AstNode::user() -> CleanState. For this node, 0==UNKNOWN
|
||||
// AstNode::user2() -> bool. True indicates minWidth has been propagated
|
||||
// AstNode::user2() -> bool. True indicates widthMin has been propagated
|
||||
// AstNodeDType::user3() -> AstNodeDType*. Alternative node with C size
|
||||
AstUser1InUse m_inuser1;
|
||||
AstUser2InUse m_inuser2;
|
||||
AstUser3InUse m_inuser3;
|
||||
|
||||
// TYPES
|
||||
enum CleanState { CS_UNKNOWN, CS_CLEAN, CS_DIRTY };
|
||||
@@ -70,16 +71,28 @@ private:
|
||||
else if (nodep->width()<=VL_QUADSIZE) return VL_QUADSIZE;
|
||||
else return nodep->widthWords()*VL_WORDSIZE;
|
||||
}
|
||||
void setCppWidth (AstNode* nodep, int width, int widthMin) {
|
||||
void setCppWidth (AstNode* nodep) {
|
||||
nodep->user2(true); // Don't resize it again
|
||||
nodep->width(width, widthMin);
|
||||
AstNodeDType* old_dtypep = nodep->dtypep();
|
||||
int width=cppWidth(nodep); // widthMin is unchanged
|
||||
if (old_dtypep->width() != width) {
|
||||
// Since any given dtype's cppWidth() is the same, we can just
|
||||
// remember one convertion for each, and reuse it
|
||||
if (AstNodeDType* new_dtypep = old_dtypep->user3p()->castNode()->castNodeDType()) {
|
||||
nodep->dtypep(new_dtypep);
|
||||
} else {
|
||||
nodep->dtypeChgWidth(width, nodep->widthMin());
|
||||
AstNodeDType* new_dtypep2 = nodep->dtypep();
|
||||
if (new_dtypep2 == old_dtypep) nodep->v3fatalSrc("Dtype didn't change when width changed");
|
||||
old_dtypep->user3p(new_dtypep2); // Remember for next time
|
||||
}
|
||||
}
|
||||
}
|
||||
void computeCppWidth (AstNode* nodep) {
|
||||
if (!nodep->user2()) {
|
||||
if (!nodep->user2() && nodep->hasDType()) {
|
||||
if (nodep->castVar() || nodep->castNodeDType()) { // Don't want to change variable widths!
|
||||
setCppWidth(nodep, nodep->width(), nodep->width()); // set widthMin anyways so can see it later
|
||||
} else {
|
||||
setCppWidth(nodep, cppWidth(nodep), nodep->widthMin());
|
||||
setCppWidth(nodep);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -116,7 +129,7 @@ private:
|
||||
AstNode* cleanp = new AstAnd (nodep->fileline(),
|
||||
new AstConst (nodep->fileline(), mask),
|
||||
nodep);
|
||||
setCppWidth (cleanp, cppWidth(nodep), nodep->widthMin());
|
||||
cleanp->dtypeFrom(nodep); // Otherwise the AND normally picks LHS
|
||||
relinkHandle.relink(cleanp);
|
||||
}
|
||||
void insureClean(AstNode* nodep) {
|
||||
|
||||
+2
-4
@@ -1,14 +1,12 @@
|
||||
// -*- C++ -*-
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: Pre C-Emit stage changes
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2013 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.
|
||||
|
||||
+6
-7
@@ -1,14 +1,12 @@
|
||||
// -*- C++ -*-
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: Break always into sensitivity active domains
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2008-2011 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2008-2013 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.
|
||||
@@ -686,6 +684,7 @@ class GaterVisitor : public GaterBaseVisitor {
|
||||
AstNode* bodyp = nodep->bodysp()->cloneTree(true);
|
||||
|
||||
AstAlways* alwp = new AstAlways(nodep->fileline(),
|
||||
nodep->keyword(),
|
||||
sensesp,
|
||||
bodyp);
|
||||
|
||||
@@ -705,7 +704,7 @@ class GaterVisitor : public GaterBaseVisitor {
|
||||
virtual void visit(AstAlways* nodep, AstNUser*) {
|
||||
if (debug()>=9) cout<<endl<<endl<<endl;
|
||||
UINFO(5, "Gater: ALWAYS: "<<nodep<<endl);
|
||||
if (nodep->user4Inc()) return;
|
||||
if (nodep->user4SetOnce()) return;
|
||||
|
||||
clear();
|
||||
|
||||
@@ -862,9 +861,9 @@ class GaterVisitor : public GaterBaseVisitor {
|
||||
m_stmtVscp = NULL;
|
||||
m_stmtInPli = false;
|
||||
}
|
||||
if (!nodep->isSplittable()) {
|
||||
if (!nodep->isPure() || nodep->isBrancher()) {
|
||||
// May also be a new statement (above if); if so we mark it immediately
|
||||
UINFO(9," NotSplittable "<<nodep<<endl);
|
||||
UINFO(9," NotPure "<<nodep<<endl);
|
||||
scoreboardPli(nodep);
|
||||
}
|
||||
{
|
||||
|
||||
+2
-4
@@ -1,14 +1,12 @@
|
||||
// -*- C++ -*-
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: Break always into clock gated blocks
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2013 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.
|
||||
|
||||
+6
-8
@@ -1,13 +1,12 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: Clocking POS/NEGEDGE insertion
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2013 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -83,10 +82,9 @@ private:
|
||||
AstVarScope* getCreateLastClk(AstVarScope* vscp) {
|
||||
if (vscp->user1p()) return ((AstVarScope*)vscp->user1p());
|
||||
AstVar* varp = vscp->varp();
|
||||
if (varp->width()!=1) varp->v3error("Unsupported: Clock edge on non-single bit signal: "<<varp->prettyName());
|
||||
string newvarname = ((string)"__Vclklast__"+vscp->scopep()->nameDotless()+"__"+varp->shortName());
|
||||
AstVar* newvarp = new AstVar (vscp->fileline(), AstVarType::MODULETEMP, newvarname, AstLogicPacked(), 1);
|
||||
newvarp->width(1,1);
|
||||
if (!varp->width1()) varp->v3error("Unsupported: Clock edge on non-single bit signal: "<<varp->prettyName());
|
||||
string newvarname = ((string)"__Vclklast__"+vscp->scopep()->nameDotless()+"__"+varp->name());
|
||||
AstVar* newvarp = new AstVar (vscp->fileline(), AstVarType::MODULETEMP, newvarname, VFlagLogicPacked(), 1);
|
||||
m_modp->addStmtp(newvarp);
|
||||
AstVarScope* newvscp = new AstVarScope(vscp->fileline(), m_scopep, newvarp);
|
||||
vscp->user1p(newvscp);
|
||||
@@ -104,7 +102,7 @@ private:
|
||||
AstVarScope* getCreateLocalVar(FileLine* fl, const string& name, AstVar* examplep, int width) {
|
||||
AstVar* newvarp;
|
||||
if (width) {
|
||||
newvarp = new AstVar (fl, AstVarType::BLOCKTEMP, name, AstLogicPacked(), width);
|
||||
newvarp = new AstVar (fl, AstVarType::BLOCKTEMP, name, VFlagLogicPacked(), width);
|
||||
} else {
|
||||
newvarp = new AstVar (fl, AstVarType::BLOCKTEMP, name, examplep); // No range; 1 bit.
|
||||
}
|
||||
|
||||
+2
-4
@@ -1,14 +1,12 @@
|
||||
// -*- C++ -*-
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: Clocking POS/NEGEDGE insertion
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2013 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.
|
||||
|
||||
+2
-3
@@ -1,13 +1,12 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: Combine common code into functions
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2013 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.
|
||||
|
||||
+2
-4
@@ -1,14 +1,12 @@
|
||||
// -*- C++ -*-
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: Combine common code into functions
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2013 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.
|
||||
|
||||
+5
-5
@@ -1,13 +1,12 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: Configuration Files
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2010-2011 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2010-2013 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 +25,7 @@
|
||||
#include <set>
|
||||
|
||||
#include "V3Global.h"
|
||||
#include "V3String.h"
|
||||
#include "V3Config.h"
|
||||
|
||||
//######################################################################
|
||||
@@ -62,7 +62,7 @@ class V3ConfigIgnores {
|
||||
|
||||
IgnFiles m_ignWilds; // Ignores for each wildcarded filename
|
||||
IgnFiles m_ignFiles; // Ignores for each non-wildcarded filename
|
||||
|
||||
|
||||
static V3ConfigIgnores s_singleton; // Singleton (not via local static, as that's slow)
|
||||
|
||||
V3ConfigIgnores() { m_lastLineno = -1; }
|
||||
@@ -90,7 +90,7 @@ class V3ConfigIgnores {
|
||||
it = m_ignFiles.find(filename);
|
||||
// Make new list for this file of all matches
|
||||
for (IgnFiles::iterator fnit = m_ignWilds.begin(); fnit != m_ignWilds.end(); ++fnit) {
|
||||
if (V3Options::wildmatch(filename.c_str(), fnit->first.c_str())) {
|
||||
if (VString::wildmatch(filename.c_str(), fnit->first.c_str())) {
|
||||
for (IgnLines::iterator lit = fnit->second.begin(); lit != fnit->second.end(); ++lit) {
|
||||
it->second.insert(*lit);
|
||||
}
|
||||
|
||||
+2
-4
@@ -1,14 +1,12 @@
|
||||
// -*- C++ -*-
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: Configuration Files
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2010-2011 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2010-2013 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.
|
||||
|
||||
+239
-113
@@ -1,13 +1,12 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: Constant folding
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2013 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.
|
||||
@@ -104,9 +103,12 @@ private:
|
||||
bool m_warn; // Output warnings
|
||||
bool m_doExpensive; // Enable computationally expensive optimizations
|
||||
bool m_doNConst; // Enable non-constant-child simplifications
|
||||
bool m_doShort; // Remove expressions that short circuit
|
||||
bool m_doV; // Verilog, not C++ conversion
|
||||
bool m_doGenerate; // Postpone width checking inside generate
|
||||
AstNodeModule* m_modp; // Current module
|
||||
AstNode* m_scopep; // Current scope
|
||||
AstAttrOf* m_attrp; // Current attribute
|
||||
|
||||
// METHODS
|
||||
static int debug() {
|
||||
@@ -149,7 +151,7 @@ private:
|
||||
// BIASV(CONSTa,BIASV(b...,BIASV(CONSTc,d...))) // hits operandAsvUp
|
||||
// BIASV(CONSTa,BIASV(CONSTc,BIASV(c...,d...))) // hits operandAsvConst
|
||||
// BIASV(BIASV(CONSTa,CONSTc),BIASV(c...,d...))) // hits normal constant propagation
|
||||
// BIASV(CONST_a_c,BIASV(c...,d...)))
|
||||
// BIASV(CONST_a_c,BIASV(c...,d...)))
|
||||
//
|
||||
// Idea for the future: All BiComAsvs could be lists, sorted by if they're constant
|
||||
AstNodeBiComAsv* bnodep = nodep->castNodeBiComAsv();
|
||||
@@ -171,13 +173,16 @@ private:
|
||||
return rnodep->lhsp()->castConst();
|
||||
}
|
||||
static bool operandAndOrSame(AstNode* nodep) {
|
||||
// OR( AND(VAL,x), AND(VAL,y)) -> AND(VAL,OR(x,y))
|
||||
// OR( AND(x,VAL), AND(y,VAL)) -> AND(OR(x,y),VAL)
|
||||
AstNodeBiop* np = nodep->castNodeBiop();
|
||||
AstNodeBiop* lp = np->lhsp()->castNodeBiop();
|
||||
AstNodeBiop* rp = np->rhsp()->castNodeBiop();
|
||||
return (lp && rp
|
||||
&& lp->width()==rp->width()
|
||||
&& lp->type()==rp->type()
|
||||
&& operandsSame(lp->lhsp(),rp->lhsp()));
|
||||
&& (operandsSame(lp->lhsp(),rp->lhsp())
|
||||
|| operandsSame(lp->rhsp(),rp->rhsp())));
|
||||
}
|
||||
static bool matchOrAndNot(AstNodeBiop* nodep) {
|
||||
// AstOr{$a, AstAnd{AstNot{$b}, $c}} if $a.width1, $a==$b => AstOr{$a,$c}
|
||||
@@ -228,11 +233,13 @@ private:
|
||||
}
|
||||
bool operandHugeShiftL(AstNodeBiop* nodep) {
|
||||
return (nodep->rhsp()->castConst()
|
||||
&& nodep->rhsp()->castConst()->toUInt() >= (uint32_t)(nodep->width()));
|
||||
&& nodep->rhsp()->castConst()->toUInt() >= (uint32_t)(nodep->width())
|
||||
&& isTPure(nodep->lhsp()));
|
||||
}
|
||||
bool operandHugeShiftR(AstNodeBiop* nodep) {
|
||||
return (nodep->rhsp()->castConst()
|
||||
&& nodep->rhsp()->castConst()->toUInt() >= (uint32_t)(nodep->lhsp()->width()));
|
||||
&& nodep->rhsp()->castConst()->toUInt() >= (uint32_t)(nodep->lhsp()->width())
|
||||
&& isTPure(nodep->lhsp()));
|
||||
}
|
||||
bool operandIsTwo(AstNode* nodep) {
|
||||
return (nodep->castConst()
|
||||
@@ -353,34 +360,50 @@ private:
|
||||
return nodep;
|
||||
}
|
||||
|
||||
bool isTPure(AstNode* nodep) {
|
||||
// Pure checks - if this node and all nodes under it are free of
|
||||
// side effects can do this optimization
|
||||
// Eventually we'll recurse through tree when unknown, memoizing results so far,
|
||||
// but for now can disable en-mass until V3Purify takes effect.
|
||||
return m_doShort || nodep->castVarRef() || nodep->castConst();
|
||||
}
|
||||
|
||||
// Extraction checks
|
||||
bool warnSelect(AstSel* nodep) {
|
||||
AstNode* basefromp = AstArraySel::baseFromp(nodep);
|
||||
if (AstNodeVarRef* varrefp = basefromp->castNodeVarRef()) {
|
||||
AstVar* varp = varrefp->varp();
|
||||
if (!varp->dtypep()) varp->v3fatalSrc("Data type lost");
|
||||
AstBasicDType* bdtypep = varp->basicp(); if (!bdtypep) varp->v3fatalSrc("Select of non-selectable type");
|
||||
if (m_warn
|
||||
&& nodep->lsbp()->castConst()
|
||||
&& nodep->widthp()->castConst()
|
||||
&& (!bdtypep->rangep() || bdtypep->msb())) { // else it's non-resolvable parameterized
|
||||
if (nodep->lsbp()->castConst()->num().isFourState()
|
||||
|| nodep->widthp()->castConst()->num().isFourState()) {
|
||||
nodep->v3error("Selection index is constantly unknown or tristated: "
|
||||
"lsb="<<nodep->lsbp()->name()<<" width="<<nodep->widthp()->name());
|
||||
// Replacing nodep will make a mess above, so we replace the offender
|
||||
replaceZero(nodep->lsbp());
|
||||
}
|
||||
else if ((nodep->msbConst() > bdtypep->msbMaxSelect())
|
||||
|| (nodep->lsbConst() > bdtypep->msbMaxSelect())) {
|
||||
// See also warning in V3Width
|
||||
nodep->v3error("Selection index out of range: "
|
||||
<<nodep->msbConst()<<":"<<nodep->lsbConst()
|
||||
<<" outside "<<bdtypep->msbMaxSelect()<<":0"
|
||||
<<(bdtypep->lsb()>=0 ? ""
|
||||
:" (adjusted +"+cvtToStr(-bdtypep->lsb())+" to account for negative lsb)"));
|
||||
// Don't replace with zero, we'll do it later
|
||||
}
|
||||
if (m_doGenerate) {
|
||||
// Never checked yet
|
||||
V3Width::widthParamsEdit(nodep);
|
||||
nodep->iterateChildren(*this); // May need "constifying"
|
||||
}
|
||||
// Find range of dtype we are selecting from
|
||||
// Similar code in V3Unknown::AstSel
|
||||
bool doit = true;
|
||||
if (m_warn
|
||||
&& nodep->lsbp()->castConst()
|
||||
&& nodep->widthp()->castConst()
|
||||
&& doit) {
|
||||
int maxDeclBit = nodep->declRange().hiMaxSelect()*nodep->declElWidth() + (nodep->declElWidth()-1);
|
||||
if (nodep->lsbp()->castConst()->num().isFourState()
|
||||
|| nodep->widthp()->castConst()->num().isFourState()) {
|
||||
nodep->v3error("Selection index is constantly unknown or tristated: "
|
||||
"lsb="<<nodep->lsbp()->name()<<" width="<<nodep->widthp()->name());
|
||||
// Replacing nodep will make a mess above, so we replace the offender
|
||||
replaceZero(nodep->lsbp());
|
||||
}
|
||||
else if (nodep->declRange().ranged()
|
||||
&& (nodep->msbConst() > maxDeclBit
|
||||
|| nodep->lsbConst() > maxDeclBit)) {
|
||||
// See also warning in V3Width
|
||||
// Must adjust by element width as declRange() is in number of elements
|
||||
nodep->v3warn(SELRANGE, "Selection index out of range: "
|
||||
<<(nodep->msbConst()/nodep->declElWidth())
|
||||
<<":"<<(nodep->lsbConst()/nodep->declElWidth())
|
||||
<<" outside "<<nodep->declRange().hiMaxSelect()<<":0"
|
||||
<<(nodep->declRange().lo()>=0 ? ""
|
||||
:(" (adjusted +"+cvtToStr(-nodep->declRange().lo())
|
||||
+" to account for negative lsb)")));
|
||||
UINFO(1," Related Raw index is "<<nodep->msbConst()<<":"<<nodep->lsbConst()<<endl);
|
||||
// Don't replace with zero, we'll do it later
|
||||
}
|
||||
}
|
||||
return false; // Not a transform, so NOP
|
||||
@@ -392,7 +415,10 @@ private:
|
||||
return node1p->sameTree(node2p);
|
||||
}
|
||||
else if (node1p->castVarRef() && node2p->castVarRef()) {
|
||||
return node1p->sameTree(node2p);
|
||||
// Avoid comparing widthMin's, which results in lost optimization attempts
|
||||
// If cleanup sameTree to be smarter, this can be restored.
|
||||
//return node1p->sameTree(node2p);
|
||||
return node1p->same(node2p);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
@@ -407,7 +433,7 @@ private:
|
||||
AstVarRef* elsevarp = elsep->lhsp()->castVarRef();
|
||||
if (!ifvarp || !elsevarp) return false;
|
||||
if (ifvarp->isWide()) return false; // Would need temporaries, so not worth it
|
||||
if (ifvarp->varp() != elsevarp->varp()) return false;
|
||||
if (!ifvarp->sameTree(elsevarp)) return false;
|
||||
return true;
|
||||
}
|
||||
bool operandIfIf(AstNodeIf* nodep) {
|
||||
@@ -430,7 +456,7 @@ private:
|
||||
oldp->v3fatalSrc("Already constant??\n");
|
||||
}
|
||||
AstNode* newp = new AstConst(oldp->fileline(), num);
|
||||
newp->widthSignedFrom(oldp);
|
||||
newp->dtypeFrom(oldp);
|
||||
if (debug()>5) oldp->dumpTree(cout," const_old: ");
|
||||
if (debug()>5) newp->dumpTree(cout," _new: ");
|
||||
oldp->replaceWith(newp);
|
||||
@@ -455,6 +481,21 @@ private:
|
||||
void replaceZero(AstNode* nodep) {
|
||||
replaceNum(nodep, 0); nodep=NULL;
|
||||
}
|
||||
void replaceZeroChkPure(AstNode* nodep, AstNode* checkp) {
|
||||
// For example, "0 * n" -> 0 if n has no side effects
|
||||
// Else strength reduce it to 0 & n.
|
||||
// If ever change the operation note AstAnd rule specially ignores this created pattern
|
||||
if (isTPure(checkp)) {
|
||||
replaceNum(nodep, 0); nodep=NULL;
|
||||
} else {
|
||||
AstNode* newp = new AstAnd(nodep->fileline(),
|
||||
new AstConst(nodep->fileline(), 0),
|
||||
checkp->unlinkFrBack());
|
||||
newp->dtypeFrom(nodep);
|
||||
nodep->replaceWith(newp);
|
||||
nodep->deleteTree(); nodep=NULL;
|
||||
}
|
||||
}
|
||||
void replaceAllOnes (AstNode* nodep) {
|
||||
V3Number ones (nodep->fileline(), nodep->width(), 0);
|
||||
ones.setMask(nodep->width());
|
||||
@@ -497,10 +538,24 @@ private:
|
||||
void replaceWChild(AstNode* nodep, AstNode* childp) {
|
||||
// NODE(..., CHILD(...)) -> CHILD(...)
|
||||
childp->unlinkFrBackWithNext();
|
||||
childp->widthSignedFrom(nodep);
|
||||
childp->dtypeFrom(nodep);
|
||||
nodep->replaceWith(childp);
|
||||
nodep->deleteTree(); nodep=NULL;
|
||||
}
|
||||
|
||||
//! Replace a ternary node with its RHS after iterating
|
||||
//! Used with short-circuting, where the RHS has not yet been iterated.
|
||||
void replaceWIteratedRhs(AstNodeTriop* nodep) {
|
||||
if (AstNode *rhsp = nodep->rhsp()) rhsp->iterateAndNext(*this);
|
||||
replaceWChild(nodep, nodep->rhsp()); // May have changed
|
||||
}
|
||||
|
||||
//! Replace a ternary node with its THS after iterating
|
||||
//! Used with short-circuting, where the THS has not yet been iterated.
|
||||
void replaceWIteratedThs(AstNodeTriop* nodep) {
|
||||
if (AstNode *thsp = nodep->thsp()) thsp->iterateAndNext(*this);
|
||||
replaceWChild(nodep, nodep->thsp()); // May have changed
|
||||
}
|
||||
void replaceWLhs(AstNodeUniop* nodep) {
|
||||
// Keep LHS, remove RHS
|
||||
replaceWChild(nodep, nodep->lhsp());
|
||||
@@ -557,7 +612,9 @@ private:
|
||||
//nodep->dumpTree(cout, " repAsvRUp_new: ");
|
||||
}
|
||||
void replaceAndOr (AstNodeBiop* nodep) {
|
||||
// Or(And(CONSTll,lr),And(CONSTrl==ll,rr)) -> And(CONSTll,Or(lr,rr))
|
||||
// OR (AND (CONSTll,lr), AND(CONSTrl==ll,rr)) -> AND (CONSTll, OR(lr,rr))
|
||||
// OR (AND (CONSTll,lr), AND(CONSTrl, rr=lr)) -> AND (OR(ll,rl), rr)
|
||||
// nodep ^lp ^llp ^lrp ^rp ^rlp ^rrp
|
||||
// (Or/And may also be reversed)
|
||||
AstNodeBiop* lp = nodep->lhsp()->unlinkFrBack()->castNodeBiop();
|
||||
AstNode* llp = lp->lhsp()->unlinkFrBack();
|
||||
@@ -566,12 +623,23 @@ private:
|
||||
AstNode* rlp = rp->lhsp()->unlinkFrBack();
|
||||
AstNode* rrp = rp->rhsp()->unlinkFrBack();
|
||||
nodep->replaceWith(lp);
|
||||
lp->lhsp(llp);
|
||||
lp->rhsp(nodep);
|
||||
nodep->lhsp(lrp);
|
||||
nodep->rhsp(rrp);
|
||||
rp->deleteTree();
|
||||
rlp->deleteTree();
|
||||
if (operandsSame(llp,rlp)) {
|
||||
lp->lhsp(llp);
|
||||
lp->rhsp(nodep);
|
||||
nodep->lhsp(lrp);
|
||||
nodep->rhsp(rrp);
|
||||
rp->deleteTree();
|
||||
rlp->deleteTree();
|
||||
} else if (operandsSame(lrp, rrp)) {
|
||||
lp->lhsp(nodep);
|
||||
lp->rhsp(rrp);
|
||||
nodep->lhsp(llp);
|
||||
nodep->rhsp(rlp);
|
||||
rp->deleteTree();
|
||||
lrp->deleteTree();
|
||||
} else {
|
||||
nodep->v3fatalSrc("replaceAndOr on something operandAndOrSame shouldn't have matched");
|
||||
}
|
||||
//nodep->dumpTree(cout, " repAndOr_new: ");
|
||||
}
|
||||
void replaceShiftSame (AstNodeBiop* nodep) {
|
||||
@@ -599,7 +667,7 @@ private:
|
||||
AstNode* newp = (nodep->castExtendS()
|
||||
? (new AstExtendS(nodep->fileline(), arg0p))->castNode()
|
||||
: (new AstExtend (nodep->fileline(), arg0p))->castNode());
|
||||
newp->widthSignedFrom(nodep);
|
||||
newp->dtypeFrom(nodep);
|
||||
nodep->replaceWith(newp); nodep->deleteTree(); nodep=NULL;
|
||||
}
|
||||
void replacePowShift (AstNodeBiop* nodep) { // Pow or PowS
|
||||
@@ -608,8 +676,8 @@ private:
|
||||
AstShiftL* newp = new AstShiftL(nodep->fileline(),
|
||||
new AstConst(nodep->fileline(), 1),
|
||||
rhsp);
|
||||
newp->widthSignedFrom(nodep);
|
||||
newp->lhsp()->widthSignedFrom(nodep);
|
||||
newp->dtypeFrom(nodep);
|
||||
newp->lhsp()->dtypeFrom(nodep);
|
||||
nodep->replaceWith(newp); nodep->deleteTree(); nodep=NULL;
|
||||
}
|
||||
void replaceMulShift (AstMul* nodep) { // Mul, but not MulS as not simple shift
|
||||
@@ -618,7 +686,7 @@ private:
|
||||
AstNode* opp = nodep->rhsp()->unlinkFrBack();
|
||||
AstShiftL* newp = new AstShiftL(nodep->fileline(),
|
||||
opp, new AstConst(nodep->fileline(), amount));
|
||||
newp->widthSignedFrom(nodep);
|
||||
newp->dtypeFrom(nodep);
|
||||
nodep->replaceWith(newp); nodep->deleteTree(); nodep=NULL;
|
||||
}
|
||||
void replaceDivShift (AstDiv* nodep) { // Mul, but not MulS as not simple shift
|
||||
@@ -627,7 +695,7 @@ private:
|
||||
AstNode* opp = nodep->lhsp()->unlinkFrBack();
|
||||
AstShiftR* newp = new AstShiftR(nodep->fileline(),
|
||||
opp, new AstConst(nodep->fileline(), amount));
|
||||
newp->widthSignedFrom(nodep);
|
||||
newp->dtypeFrom(nodep);
|
||||
nodep->replaceWith(newp); nodep->deleteTree(); nodep=NULL;
|
||||
}
|
||||
void replaceShiftOp (AstNodeBiop* nodep) {
|
||||
@@ -687,11 +755,11 @@ private:
|
||||
newp = new AstShiftL(nodep->fileline(), ap,
|
||||
new AstConst(nodep->fileline(), newshift));
|
||||
}
|
||||
newp->widthSignedFrom(nodep);
|
||||
newp->dtypeFrom(nodep);
|
||||
newp = new AstAnd (nodep->fileline(),
|
||||
newp,
|
||||
new AstConst (nodep->fileline(), mask));
|
||||
newp->widthSignedFrom(nodep);
|
||||
newp->dtypeFrom(nodep);
|
||||
nodep->replaceWith(newp); nodep->deleteTree(); nodep=NULL;
|
||||
//newp->dumpTree(cout, " repShiftShift_new: ");
|
||||
newp->accept(*this); // Further reduce, either node may have more reductions.
|
||||
@@ -710,7 +778,7 @@ private:
|
||||
AstSel* sel2p = nextp->lhsp()->castSel(); if (!sel2p) return false;
|
||||
AstVarRef* varref1p = sel1p->fromp()->castVarRef(); if (!varref1p) return false;
|
||||
AstVarRef* varref2p = sel2p->fromp()->castVarRef(); if (!varref2p) return false;
|
||||
if (varref1p->varp() != varref2p->varp()) return false;
|
||||
if (!varref1p->sameTree(varref2p)) return false;
|
||||
AstConst* con1p = sel1p->lsbp()->castConst(); if (!con1p) return false;
|
||||
AstConst* con2p = sel2p->lsbp()->castConst(); if (!con2p) return false;
|
||||
// We need to make sure there's no self-references involved in either
|
||||
@@ -761,7 +829,7 @@ private:
|
||||
bool replaceNodeAssign(AstNodeAssign* nodep) {
|
||||
if (nodep->lhsp()->castVarRef()
|
||||
&& nodep->rhsp()->castVarRef()
|
||||
&& nodep->lhsp()->sameTree(nodep->rhsp())
|
||||
&& nodep->lhsp()->castVarRef()->sameNoLvalue(nodep->rhsp()->castVarRef())
|
||||
&& !nodep->castAssignDly()) {
|
||||
// X = X. Quite pointless, though X <= X may override another earlier assignment
|
||||
if (nodep->castAssignW()) {
|
||||
@@ -811,16 +879,14 @@ private:
|
||||
// Form ranges
|
||||
AstSel* sel1p = new AstSel(conp->fileline(), rhsp, lsb1, msb1-lsb1+1);
|
||||
AstSel* sel2p = new AstSel(conp->fileline(), rhs2p, lsb2, msb2-lsb2+1);
|
||||
sel1p->width(msb1-lsb1+1,msb1-lsb1+1);
|
||||
sel2p->width(msb2-lsb2+1,msb2-lsb2+1);
|
||||
// Make new assigns of same flavor as old one
|
||||
//*** Not cloneTree; just one node.
|
||||
AstNode* newp = NULL;
|
||||
if (!need_temp) {
|
||||
AstNodeAssign* asn1ap=nodep->cloneType(lc1p, sel1p)->castNodeAssign();
|
||||
AstNodeAssign* asn2ap=nodep->cloneType(lc2p, sel2p)->castNodeAssign();
|
||||
asn1ap->width(msb1-lsb1+1,msb1-lsb1+1);
|
||||
asn2ap->width(msb2-lsb2+1,msb2-lsb2+1);
|
||||
asn1ap->dtypeFrom(sel1p);
|
||||
asn2ap->dtypeFrom(sel2p);
|
||||
// cppcheck-suppress nullPointer // addNext deals with it
|
||||
newp = newp->addNext(asn1ap);
|
||||
// cppcheck-suppress nullPointer // addNext deals with it
|
||||
@@ -832,9 +898,9 @@ private:
|
||||
string name1 = ((string)"__Vconcswap"+cvtToStr(m_modp->varNumGetInc()));
|
||||
string name2 = ((string)"__Vconcswap"+cvtToStr(m_modp->varNumGetInc()));
|
||||
AstVar* temp1p = new AstVar(sel1p->fileline(), AstVarType::BLOCKTEMP, name1,
|
||||
AstLogicPacked(), msb1-lsb1+1);
|
||||
VFlagLogicPacked(), msb1-lsb1+1);
|
||||
AstVar* temp2p = new AstVar(sel2p->fileline(), AstVarType::BLOCKTEMP, name2,
|
||||
AstLogicPacked(), msb2-lsb2+1);
|
||||
VFlagLogicPacked(), msb2-lsb2+1);
|
||||
m_modp->addStmtp(temp1p);
|
||||
m_modp->addStmtp(temp2p);
|
||||
AstNodeAssign* asn1ap=nodep->cloneType
|
||||
@@ -849,10 +915,10 @@ private:
|
||||
AstNodeAssign* asn2bp=nodep->cloneType
|
||||
(lc2p, new AstVarRef(sel2p->fileline(), temp2p, false))
|
||||
->castNodeAssign();
|
||||
asn1ap->width(msb1-lsb1+1,msb1-lsb1+1);
|
||||
asn1bp->width(msb1-lsb1+1,msb1-lsb1+1);
|
||||
asn2ap->width(msb2-lsb2+1,msb2-lsb2+1);
|
||||
asn2bp->width(msb2-lsb2+1,msb2-lsb2+1);
|
||||
asn1ap->dtypeFrom(temp1p);
|
||||
asn1bp->dtypeFrom(temp1p);
|
||||
asn2ap->dtypeFrom(temp2p);
|
||||
asn2bp->dtypeFrom(temp2p);
|
||||
// This order matters
|
||||
// cppcheck-suppress nullPointer // addNext deals with it
|
||||
newp = newp->addNext(asn1ap);
|
||||
@@ -898,7 +964,7 @@ private:
|
||||
AstAnd* newp = new AstAnd(nodep->fileline(),
|
||||
new AstConst(nodep->fileline(), val),
|
||||
fromp);
|
||||
newp->width(nodep->width(), nodep->width()); // widthMin no longer applicable
|
||||
newp->dtypeSetLogicSized(nodep->width(), nodep->width(), AstNumeric::UNSIGNED); // widthMin no longer applicable if different C-expanded width
|
||||
nodep->replaceWith(newp);
|
||||
nodep->deleteTree(); nodep=NULL;
|
||||
if (debug()>=9) newp->dumpTree(cout," _new: ");
|
||||
@@ -912,7 +978,7 @@ private:
|
||||
AstNode* errorp = simvis.whyNotNodep(); if (!errorp) errorp = nodep;
|
||||
nodep->v3error("Expecting expression to be constant, but can't determine constant for "
|
||||
<<nodep->prettyTypeName()<<endl
|
||||
<<V3Error::msgPrefix(V3ErrorCode::EC_ERROR,false)<<errorp->fileline()<<"... Location of non-constant "
|
||||
<<errorp->warnMore()<<"... Location of non-constant "
|
||||
<<errorp->prettyTypeName()<<": "<<simvis.whyNotMessage());
|
||||
replaceZero(nodep); nodep=NULL;
|
||||
} else {
|
||||
@@ -1049,8 +1115,8 @@ private:
|
||||
// expression, not the potentially smaller lsb1p's width
|
||||
newlsbp = new AstAdd(lsb1p->fileline(),
|
||||
lsb2p, new AstExtend(lsb1p->fileline(), lsb1p));
|
||||
newlsbp->widthFrom(lsb2p); // Unsigned
|
||||
newlsbp->castAdd()->rhsp()->widthFrom(lsb2p); // Unsigned
|
||||
newlsbp->dtypeFrom(lsb2p); // Unsigned
|
||||
newlsbp->castAdd()->rhsp()->dtypeFrom(lsb2p);
|
||||
}
|
||||
AstSel* newp = new AstSel(nodep->fileline(),
|
||||
fromp,
|
||||
@@ -1110,7 +1176,7 @@ private:
|
||||
fromp,
|
||||
new AstConst(lsbp->fileline(), lsbp->toUInt() % fromp->width()),
|
||||
widthp);
|
||||
newp->widthSignedFrom(nodep);
|
||||
newp->dtypeFrom(nodep);
|
||||
nodep->replaceWith(newp); nodep->deleteTree(); nodep=NULL;
|
||||
}
|
||||
|
||||
@@ -1128,7 +1194,7 @@ private:
|
||||
bilhsp, lsbp->cloneTree(true), widthp->cloneTree(true)));
|
||||
fromp->rhsp(new AstSel(nodep->fileline(),
|
||||
birhsp, lsbp, widthp));
|
||||
fromp->widthSignedFrom(nodep);
|
||||
fromp->dtypeFrom(nodep);
|
||||
nodep->replaceWith(fromp); nodep->deleteTree(); nodep=NULL;
|
||||
}
|
||||
void replaceSelIntoUniop(AstSel* nodep) {
|
||||
@@ -1141,16 +1207,22 @@ private:
|
||||
AstNode* bilhsp = fromp->lhsp()->unlinkFrBack();
|
||||
//
|
||||
fromp->lhsp(new AstSel(nodep->fileline(),
|
||||
bilhsp, lsbp->cloneTree(true), widthp->cloneTree(true)));
|
||||
fromp->widthSignedFrom(nodep);
|
||||
bilhsp, lsbp, widthp));
|
||||
fromp->dtypeFrom(nodep);
|
||||
nodep->replaceWith(fromp); nodep->deleteTree(); nodep=NULL;
|
||||
}
|
||||
|
||||
virtual void visit(AstAttrOf* nodep, AstNUser*) {
|
||||
AstAttrOf* oldAttr = m_attrp;
|
||||
m_attrp = nodep;
|
||||
nodep->iterateChildren(*this);
|
||||
m_attrp = oldAttr;
|
||||
}
|
||||
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
if (!nodep->varp()) nodep->v3fatalSrc("Not linked");
|
||||
bool did=false;
|
||||
if (m_doV && nodep->varp()->hasSimpleInit() && !nodep->backp()->castAttrOf()) {
|
||||
if (m_doV && nodep->varp()->hasSimpleInit() && !m_attrp) {
|
||||
//if (debug()) nodep->varp()->valuep()->dumpTree(cout," visitvaref: ");
|
||||
nodep->varp()->valuep()->iterateAndNext(*this);
|
||||
if (operandConst(nodep->varp()->valuep())
|
||||
@@ -1193,16 +1265,6 @@ private:
|
||||
// Not constant propagated (for today) because AstMath::isOpaque is set
|
||||
// Someday if lower is constant, convert to quoted "string".
|
||||
|
||||
virtual void visit(AstAttrOf* nodep, AstNUser*) {
|
||||
// Don't iterate children, don't want to lose VarRef.
|
||||
if (nodep->attrType()==AstAttrType::EXPR_BITS) {
|
||||
if (!nodep->fromp() || !nodep->fromp()->widthMin()) nodep->v3fatalSrc("Unsized expression");
|
||||
V3Number num (nodep->fileline(), 32, nodep->fromp()->widthMin());
|
||||
replaceNum(nodep, num); nodep=NULL;
|
||||
} else {
|
||||
nodep->v3fatalSrc("Missing ATTR type case");
|
||||
}
|
||||
}
|
||||
bool onlySenItemInSenTree(AstNodeSenItem* nodep) {
|
||||
// Only one if it's not in a list
|
||||
return (!nodep->nextp() && nodep->backp()->nextp() != nodep);
|
||||
@@ -1211,6 +1273,7 @@ private:
|
||||
nodep->iterateChildren(*this);
|
||||
if (m_doNConst
|
||||
&& (nodep->sensp()->castConst()
|
||||
|| nodep->sensp()->castEnumItemRef()
|
||||
|| (nodep->varrefp() && nodep->varrefp()->varp()->isParam()))) {
|
||||
// Constants in sensitivity lists may be removed (we'll simplify later)
|
||||
if (nodep->isClocked()) { // A constant can never get a pos/negexge
|
||||
@@ -1239,6 +1302,9 @@ private:
|
||||
if (!senvarp) sensp->v3fatalSrc("Non-varref sensitivity variable");
|
||||
sensp->replaceWith(senvarp);
|
||||
sensp->deleteTree(); sensp=NULL;
|
||||
} else if (!m_doNConst // Deal with later when doNConst missing
|
||||
&& (nodep->sensp()->castEnumItemRef()
|
||||
|| nodep->sensp()->castConst())) {
|
||||
} else {
|
||||
if (nodep->hasVar() && !nodep->varrefp()) nodep->v3fatalSrc("Null sensitivity variable");
|
||||
}
|
||||
@@ -1338,6 +1404,7 @@ private:
|
||||
for (AstNodeSenItem* nextp, * senp = nodep->sensesp()->castNodeSenItem();
|
||||
senp; senp=nextp) {
|
||||
nextp=senp->nextp()->castNodeSenItem();
|
||||
// cppcheck-suppress unassignedVariable // cppcheck bug
|
||||
SenItemCmp cmp;
|
||||
if (nextp && !cmp(senp, nextp)) {
|
||||
// Something's out of order, sort it
|
||||
@@ -1346,7 +1413,7 @@ private:
|
||||
for (AstNodeSenItem* senp = nodep->sensesp()->castNodeSenItem(); senp; senp=senp->nextp()->castNodeSenItem()) {
|
||||
vec.push_back(senp);
|
||||
}
|
||||
sort(vec.begin(), vec.end(), SenItemCmp());
|
||||
stable_sort(vec.begin(), vec.end(), SenItemCmp());
|
||||
for (vector<AstNodeSenItem*>::iterator it=vec.begin(); it!=vec.end(); ++it) {
|
||||
(*it)->unlinkFrBack();
|
||||
}
|
||||
@@ -1356,7 +1423,7 @@ private:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Pass2, remove dup edges
|
||||
for (AstNodeSenItem* nextp, * senp = nodep->sensesp()->castNodeSenItem();
|
||||
senp; senp=nextp) {
|
||||
@@ -1399,6 +1466,9 @@ private:
|
||||
virtual void visit(AstAssignAlias* nodep, AstNUser*) {
|
||||
// Don't perform any optimizations, keep the alias around
|
||||
}
|
||||
virtual void visit(AstAssignVarScope* nodep, AstNUser*) {
|
||||
// Don't perform any optimizations, the node won't be linked yet
|
||||
}
|
||||
virtual void visit(AstAssignW* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
if (m_doNConst && replaceNodeAssign(nodep)) return;
|
||||
@@ -1601,6 +1671,12 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
// Simplify
|
||||
virtual void visit(AstBasicDType* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
nodep->cvtRangeConst();
|
||||
}
|
||||
|
||||
//-----
|
||||
// Jump elimination
|
||||
|
||||
@@ -1648,34 +1724,40 @@ private:
|
||||
// v--- *1* These ops are always first, as we warn before replacing
|
||||
// v--- *V* This op is a verilog op, only in m_doV mode
|
||||
// v--- *C* This op works on all constant children, allowed in m_doConst mode
|
||||
// v--- *S* This op specifies a type should use short-circuting of its lhs op
|
||||
|
||||
TREEOP1("AstSel{warnSelect(nodep)}", "NEVER");
|
||||
// Generic constants on both side. Do this first to avoid other replacements
|
||||
TREEOPC("AstNodeBiop {$lhsp.castConst, $rhsp.castConst}", "replaceConst(nodep)");
|
||||
TREEOPC("AstNodeUniop{$lhsp.castConst, !nodep->isOpaque()}", "replaceConst(nodep)");
|
||||
// Zero on one side or the other
|
||||
TREEOP ("AstAdd {$lhsp.isZero, $rhsp}", "replaceWRhs(nodep)");
|
||||
TREEOP ("AstAnd {$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
|
||||
TREEOP ("AstAnd {$lhsp.isZero, $rhsp, isTPure($rhsp)}", "replaceZero(nodep)"); // Can't use replaceZeroChkPure as we make this pattern in ChkPure
|
||||
// This visit function here must allow for short-circuiting.
|
||||
TREEOPS("AstLogAnd {$lhsp.isZero}", "replaceZero(nodep)");
|
||||
TREEOP ("AstLogAnd{$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
|
||||
// This visit function here must allow for short-circuiting.
|
||||
TREEOPS("AstLogOr {$lhsp.isOne}", "replaceNum(nodep, 1)");
|
||||
TREEOP ("AstLogOr {$lhsp.isZero, $rhsp}", "replaceWRhs(nodep)");
|
||||
TREEOP ("AstDiv {$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
|
||||
TREEOP ("AstDivS {$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
|
||||
TREEOP ("AstMul {$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
|
||||
TREEOP ("AstMulS {$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
|
||||
TREEOP ("AstPow {$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
|
||||
TREEOP ("AstPowS {$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
|
||||
TREEOP ("AstDiv {$lhsp.isZero, $rhsp}", "replaceZeroChkPure(nodep,$rhsp)");
|
||||
TREEOP ("AstDivS {$lhsp.isZero, $rhsp}", "replaceZeroChkPure(nodep,$rhsp)");
|
||||
TREEOP ("AstMul {$lhsp.isZero, $rhsp}", "replaceZeroChkPure(nodep,$rhsp)");
|
||||
TREEOP ("AstMulS {$lhsp.isZero, $rhsp}", "replaceZeroChkPure(nodep,$rhsp)");
|
||||
TREEOP ("AstPow {$lhsp.isZero, $rhsp}", "replaceZeroChkPure(nodep,$rhsp)");
|
||||
TREEOP ("AstPowS {$lhsp.isZero, $rhsp}", "replaceZeroChkPure(nodep,$rhsp)");
|
||||
TREEOP ("AstOr {$lhsp.isZero, $rhsp}", "replaceWRhs(nodep)");
|
||||
TREEOP ("AstShiftL{$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
|
||||
TREEOP ("AstShiftR{$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
|
||||
TREEOP ("AstShiftRS{$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
|
||||
TREEOP ("AstShiftL{$lhsp.isZero, $rhsp}", "replaceZeroChkPure(nodep,$rhsp)");
|
||||
TREEOP ("AstShiftR{$lhsp.isZero, $rhsp}", "replaceZeroChkPure(nodep,$rhsp)");
|
||||
TREEOP ("AstShiftRS{$lhsp.isZero, $rhsp}", "replaceZeroChkPure(nodep,$rhsp)");
|
||||
TREEOP ("AstXor {$lhsp.isZero, $rhsp}", "replaceWRhs(nodep)");
|
||||
TREEOP ("AstXnor {$lhsp.isZero, $rhsp}", "AstNot{$rhsp}");
|
||||
TREEOP ("AstSub {$lhsp.isZero, $rhsp}", "AstNegate{$rhsp}");
|
||||
TREEOP ("AstAdd {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
|
||||
TREEOP ("AstAnd {$lhsp, $rhsp.isZero}", "replaceZero(nodep)");
|
||||
TREEOP ("AstLogAnd{$lhsp, $rhsp.isZero}", "replaceZero(nodep)");
|
||||
TREEOP ("AstAnd {$lhsp, $rhsp.isZero}", "replaceZeroChkPure(nodep,$lhsp)");
|
||||
TREEOP ("AstLogAnd{$lhsp, $rhsp.isZero}", "replaceZeroChkPure(nodep,$lhsp)");
|
||||
TREEOP ("AstLogOr {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
|
||||
TREEOP ("AstMul {$lhsp, $rhsp.isZero}", "replaceZero(nodep)");
|
||||
TREEOP ("AstMulS {$lhsp, $rhsp.isZero}", "replaceZero(nodep)");
|
||||
TREEOP ("AstMul {$lhsp, $rhsp.isZero}", "replaceZeroChkPure(nodep,$lhsp)");
|
||||
TREEOP ("AstMulS {$lhsp, $rhsp.isZero}", "replaceZeroChkPure(nodep,$lhsp)");
|
||||
TREEOP ("AstOr {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
|
||||
TREEOP ("AstShiftL{$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
|
||||
TREEOP ("AstShiftR{$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
|
||||
@@ -1686,12 +1768,12 @@ private:
|
||||
// Non-zero on one side or the other
|
||||
TREEOP ("AstAnd {$lhsp.isAllOnes, $rhsp}", "replaceWRhs(nodep)");
|
||||
TREEOP ("AstLogAnd{$lhsp.isNeqZero, $rhsp}", "replaceWRhs(nodep)");
|
||||
TREEOP ("AstOr {$lhsp.isAllOnes, $rhsp}", "replaceWLhs(nodep)"); //->allOnes
|
||||
TREEOP ("AstOr {$lhsp.isAllOnes, $rhsp, isTPure($rhsp)}", "replaceWLhs(nodep)"); //->allOnes
|
||||
TREEOP ("AstLogOr {$lhsp.isNeqZero, $rhsp}", "replaceNum(nodep,1)");
|
||||
TREEOP ("AstAnd {$lhsp, $rhsp.isAllOnes}", "replaceWLhs(nodep)");
|
||||
TREEOP ("AstLogAnd{$lhsp, $rhsp.isNeqZero}", "replaceWLhs(nodep)");
|
||||
TREEOP ("AstOr {$lhsp, $rhsp.isAllOnes}", "replaceWRhs(nodep)"); //->allOnes
|
||||
TREEOP ("AstLogOr {$lhsp, $rhsp.isNeqZero}", "replaceNum(nodep,1)");
|
||||
TREEOP ("AstOr {$lhsp, $rhsp.isAllOnes, isTPure($lhsp)}", "replaceWRhs(nodep)"); //->allOnes
|
||||
TREEOP ("AstLogOr {$lhsp, $rhsp.isNeqZero, isTPure($lhsp)}", "replaceNum(nodep,1)");
|
||||
TREEOP ("AstXor {$lhsp.isAllOnes, $rhsp}", "AstNot{$rhsp}");
|
||||
TREEOP ("AstXnor {$lhsp.isAllOnes, $rhsp}", "replaceWRhs(nodep)");
|
||||
TREEOP ("AstMul {$lhsp.isOne, $rhsp}", "replaceWRhs(nodep)");
|
||||
@@ -1709,11 +1791,14 @@ private:
|
||||
TREEOPC("AstNodeCond{$condp.isZero, $expr1p.castConst, $expr2p.castConst}", "replaceWChild(nodep,$expr2p)");
|
||||
TREEOPC("AstNodeCond{$condp.isNeqZero, $expr1p.castConst, $expr2p.castConst}", "replaceWChild(nodep,$expr1p)");
|
||||
TREEOP ("AstNodeCond{$condp, operandsSame($expr1p,,$expr2p)}","replaceWChild(nodep,$expr1p)");
|
||||
// This visit function here must allow for short-circuiting.
|
||||
TREEOPS("AstCond {$lhsp.isZero}", "replaceWIteratedThs(nodep)");
|
||||
TREEOPS("AstCond {$lhsp.isNeqZero}", "replaceWIteratedRhs(nodep)");
|
||||
TREEOP ("AstCond{$condp->castNot(), $expr1p, $expr2p}", "AstCond{$condp->op1p(), $expr2p, $expr1p}");
|
||||
TREEOP ("AstNodeCond{$condp.width1, $expr1p.width1, $expr1p.isAllOnes, $expr2p}", "AstOr {$condp, $expr2p}"); // a?1:b == a|b
|
||||
TREEOP ("AstNodeCond{$condp.width1, $expr1p.width1, $expr1p, $expr2p.isZero}", "AstAnd{$condp, $expr1p}"); // a?b:0 == a&b
|
||||
TREEOP ("AstNodeCond{$condp.width1, $expr1p.width1, $expr1p, $expr2p.isAllOnes}", "AstOr {AstNot{$condp}, $expr1p}"); // a?b:1 == ~a|b
|
||||
TREEOP ("AstNodeCond{$condp.width1, $expr1p.width1, $expr1p.isZero, $expr2p}", "AstAnd{AstNot{$condp}, $expr2p}"); // a?0:b == ~a&b
|
||||
TREEOP ("AstNodeCond{$condp.width1, $expr1p.width1, $expr1p.isAllOnes, $expr2p}", "AstLogOr {$condp, $expr2p}"); // a?1:b == a||b
|
||||
TREEOP ("AstNodeCond{$condp.width1, $expr1p.width1, $expr1p, $expr2p.isZero}", "AstLogAnd{$condp, $expr1p}"); // a?b:0 == a&&b
|
||||
TREEOP ("AstNodeCond{$condp.width1, $expr1p.width1, $expr1p, $expr2p.isAllOnes}", "AstLogOr {AstNot{$condp}, $expr1p}"); // a?b:1 == ~a||b
|
||||
TREEOP ("AstNodeCond{$condp.width1, $expr1p.width1, $expr1p.isZero, $expr2p}", "AstLogAnd{AstNot{$condp}, $expr2p}"); // a?0:b == ~a&&b
|
||||
TREEOP ("AstNodeCond{!$condp.width1, operandBoolShift(nodep->condp())}", "replaceBoolShift(nodep->condp())");
|
||||
// Prefer constants on left, since that often needs a shift, it lets constant red remove the shift
|
||||
TREEOP ("AstNodeBiCom{!$lhsp.castConst, $rhsp.castConst}", "swapSides(nodep)");
|
||||
@@ -1838,9 +1923,9 @@ private:
|
||||
TREEOPV("AstOneHot{$lhsp.width1}", "replaceWLhs(nodep)");
|
||||
TREEOPV("AstOneHot0{$lhsp.width1}", "replaceNum(nodep,1)");
|
||||
// Binary AND/OR is faster than logical and/or (usually)
|
||||
TREEOPV("AstLogAnd{$lhsp.width1, $rhsp.width1}", "AstAnd{$lhsp,$rhsp}");
|
||||
TREEOPV("AstLogOr {$lhsp.width1, $rhsp.width1}", "AstOr{$lhsp,$rhsp}");
|
||||
TREEOPV("AstLogNot{$lhsp.width1}", "AstNot{$lhsp}");
|
||||
TREEOPV("AstLogAnd{$lhsp.width1, $rhsp.width1, isTPure($lhsp), isTPure($rhsp)}", "AstAnd{$lhsp,$rhsp}");
|
||||
TREEOPV("AstLogOr {$lhsp.width1, $rhsp.width1, isTPure($lhsp), isTPure($rhsp)}", "AstOr{$lhsp,$rhsp}");
|
||||
TREEOPV("AstLogNot{$lhsp.width1, isTPure($lhsp)}", "AstNot{$lhsp}");
|
||||
// CONCAT(CONCAT({a},{b}),{c}) -> CONCAT({a},CONCAT({b},{c}))
|
||||
// CONCAT({const},CONCAT({const},{c})) -> CONCAT((constifiedCONC{const|const},{c}))
|
||||
TREEOPV("AstConcat{operandConcatMove(nodep)}", "moveConcat(nodep)");
|
||||
@@ -1882,6 +1967,8 @@ private:
|
||||
TREEOPV("AstSel{$fromp.castXnor,$lhsp.castConst}", "replaceSelIntoUniop(nodep)");
|
||||
// Conversions
|
||||
TREEOPV("AstRedXnor{$lhsp}", "AstNot{AstRedXor{$lhsp}}"); // Just eliminate XNOR's
|
||||
// This visit function here must allow for short-circuiting.
|
||||
TREEOPS("AstLogIf {$lhsp.isZero}", "replaceNum(nodep, 1)");
|
||||
TREEOPV("AstLogIf {$lhsp, $rhsp}", "AstLogOr{AstLogNot{$lhsp},$rhsp}");
|
||||
TREEOPV("AstLogIff{$lhsp, $rhsp}", "AstLogNot{AstXor{$lhsp,$rhsp}}");
|
||||
// Strings
|
||||
@@ -1915,27 +2002,32 @@ public:
|
||||
// Processing Mode Enum
|
||||
enum ProcMode {
|
||||
PROC_PARAMS,
|
||||
PROC_GENERATE,
|
||||
PROC_LIVE,
|
||||
PROC_V_WARN,
|
||||
PROC_V_NOWARN,
|
||||
PROC_V_EXPENSIVE,
|
||||
PROC_CPP
|
||||
};
|
||||
|
||||
|
||||
// CONSTUCTORS
|
||||
ConstVisitor(ProcMode pmode) {
|
||||
m_params = false;
|
||||
m_required = false;
|
||||
m_doExpensive = false;
|
||||
m_doNConst = false;
|
||||
m_doShort = true; // Presently always done
|
||||
m_doV = false;
|
||||
m_doGenerate = false; // Inside generate conditionals
|
||||
m_warn = false;
|
||||
m_wremove = true; // Overridden in visitors
|
||||
m_modp = NULL;
|
||||
m_scopep = NULL;
|
||||
m_attrp = NULL;
|
||||
//
|
||||
switch (pmode) {
|
||||
case PROC_PARAMS: m_doV = true; m_doNConst = true; m_params = true; m_required = true; break;
|
||||
case PROC_GENERATE: m_doV = true; m_doNConst = true; m_params = true; m_required = true; m_doGenerate = true; break;
|
||||
case PROC_LIVE: break;
|
||||
case PROC_V_WARN: m_doV = true; m_doNConst = true; m_warn = true; break;
|
||||
case PROC_V_NOWARN: m_doV = true; m_doNConst = true; break;
|
||||
@@ -1954,12 +2046,46 @@ public:
|
||||
//######################################################################
|
||||
// Const class functions
|
||||
|
||||
//! Force this cell node's parameter list to become a constant
|
||||
//! @return Pointer to the edited node.
|
||||
AstNode* V3Const::constifyParamsEdit(AstNode* nodep) {
|
||||
//if (debug()>0) nodep->dumpTree(cout," forceConPRE : ");
|
||||
// Resize even if the node already has a width, because burried in the treee we may
|
||||
// have a node we just created with signing, etc, that isn't sized yet.
|
||||
nodep = V3Width::widthParamsEdit(nodep); // Make sure we've sized everything first
|
||||
ConstVisitor visitor (ConstVisitor::PROC_PARAMS);
|
||||
// Resize even if the node already has a width, because buried in the tree
|
||||
// we may have a node we just created with signing, etc, that isn't sized yet.
|
||||
|
||||
// Make sure we've sized everything first
|
||||
nodep = V3Width::widthParamsEdit(nodep);
|
||||
ConstVisitor visitor(ConstVisitor::PROC_PARAMS);
|
||||
if (AstVar* varp=nodep->castVar()) {
|
||||
// If a var wants to be constified, it's really a param, and
|
||||
// we want the value to be constant. We aren't passed just the
|
||||
// init value because we need widthing above to handle the var's type.
|
||||
if (varp->valuep()) visitor.mainAcceptEdit(varp->valuep());
|
||||
} else {
|
||||
nodep = visitor.mainAcceptEdit(nodep);
|
||||
}
|
||||
// Because we do edits, nodep links may get trashed and core dump this.
|
||||
//if (debug()>0) nodep->dumpTree(cout," forceConDONE: ");
|
||||
return nodep;
|
||||
}
|
||||
|
||||
//! Force this cell node's parameter list to become a constant inside generate.
|
||||
//! If we are inside a generated "if", "case" or "for", we don't want to
|
||||
//! trigger warnings when we deal with the width. It is possible that these
|
||||
//! are spurious, existing within sub-expressions that will not actually be
|
||||
//! generated. Since such occurrences, must be constant, in order to be
|
||||
//! someting a generate block can depend on, we can wait until later to do the
|
||||
//! width check.
|
||||
//! @return Pointer to the edited node.
|
||||
AstNode* V3Const::constifyGenerateParamsEdit(AstNode* nodep) {
|
||||
//if (debug()>0) nodep->dumpTree(cout," forceConPRE : ");
|
||||
// Resize even if the node already has a width, because buried in the tree
|
||||
// we may have a node we just created with signing, etc, that isn't sized
|
||||
// yet.
|
||||
|
||||
// Make sure we've sized everything first
|
||||
nodep = V3Width::widthGenerateParamsEdit(nodep);
|
||||
ConstVisitor visitor(ConstVisitor::PROC_GENERATE);
|
||||
if (AstVar* varp=nodep->castVar()) {
|
||||
// If a var wants to be constified, it's really a param, and
|
||||
// we want the value to be constant. We aren't passed just the
|
||||
|
||||
+3
-6
@@ -1,14 +1,12 @@
|
||||
// -*- C++ -*-
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: Propagate constants across AST
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2013 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -31,9 +29,8 @@
|
||||
|
||||
class V3Const {
|
||||
public:
|
||||
// Force this cell node's parameter list to become a constant
|
||||
// Return new node that may have replaced nodep
|
||||
static AstNode* constifyParamsEdit(AstNode* nodep);
|
||||
static AstNode* constifyGenerateParamsEdit(AstNode* nodep);
|
||||
// Only do constant pushing, without removing dead logic
|
||||
static void constifyAllLive(AstNetlist* nodep);
|
||||
// Everything that's possible
|
||||
|
||||
+14
-11
@@ -1,13 +1,12 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: Netlist (top level) functions
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2013 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.
|
||||
@@ -65,6 +64,7 @@ private:
|
||||
bool m_checkBlock; // Should this block get covered?
|
||||
AstNodeModule* m_modp; // Current module to add statement to
|
||||
bool m_inToggleOff; // In function/task etc
|
||||
bool m_inModOff; // In module with no coverage
|
||||
FileMap m_fileps; // Column counts for each fileline
|
||||
string m_beginHier; // AstBegin hier name for user coverage points
|
||||
|
||||
@@ -87,7 +87,7 @@ private:
|
||||
if (prettyName.find("._") != string::npos)
|
||||
return "Inlined leading underscore";
|
||||
}
|
||||
if ((nodep->width()*nodep->arrayElements()) > 256) return "Wide bus/array > 256 bits";
|
||||
if ((nodep->width()*nodep->dtypep()->arrayUnpackedElements()) > 256) return "Wide bus/array > 256 bits";
|
||||
// We allow this, though tracing doesn't
|
||||
// if (nodep->arrayp(1)) return "Unsupported: Multi-dimensional array";
|
||||
return NULL;
|
||||
@@ -125,9 +125,11 @@ private:
|
||||
// VISITORS - BOTH
|
||||
virtual void visit(AstNodeModule* nodep, AstNUser*) {
|
||||
m_modp = nodep;
|
||||
m_inModOff = nodep->isTop(); // Ignore coverage on top module; it's a shell we created
|
||||
m_fileps.clear();
|
||||
nodep->iterateChildren(*this);
|
||||
m_modp = NULL;
|
||||
m_inModOff = true;
|
||||
}
|
||||
|
||||
// VISITORS - TOGGLE COVERAGE
|
||||
@@ -141,7 +143,7 @@ private:
|
||||
}
|
||||
virtual void visit(AstVar* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
if (m_modp && !m_inToggleOff
|
||||
if (m_modp && !m_inModOff && !m_inToggleOff
|
||||
&& nodep->fileline()->coverageOn() && v3Global.opt.coverageToggle()) {
|
||||
const char* disablep = varIgnoreToggle(nodep);
|
||||
if (disablep) {
|
||||
@@ -193,7 +195,7 @@ private:
|
||||
const ToggleEnt& above,
|
||||
AstVar* varp, AstVar* chgVarp) { // Constant
|
||||
if (AstBasicDType* bdtypep = dtypep->castBasicDType()) {
|
||||
if (bdtypep->rangep()) {
|
||||
if (bdtypep->isRanged()) {
|
||||
for (int index_docs=bdtypep->lsb(); index_docs<bdtypep->msb()+1; index_docs++) {
|
||||
int index_code = index_docs - bdtypep->lsb();
|
||||
ToggleEnt newent (above.m_comment+string("[")+cvtToStr(index_docs)+"]",
|
||||
@@ -210,13 +212,13 @@ private:
|
||||
varp, chgVarp);
|
||||
}
|
||||
}
|
||||
else if (AstArrayDType* adtypep = dtypep->castArrayDType()) {
|
||||
else if (AstUnpackArrayDType* adtypep = dtypep->castUnpackArrayDType()) {
|
||||
for (int index_docs=adtypep->lsb(); index_docs<=adtypep->msb()+1; ++index_docs) {
|
||||
int index_code = index_docs - adtypep->lsb();
|
||||
ToggleEnt newent (above.m_comment+string("[")+cvtToStr(index_docs)+"]",
|
||||
new AstArraySel(varp->fileline(), above.m_varRefp->cloneTree(true), index_code),
|
||||
new AstArraySel(varp->fileline(), above.m_chgRefp->cloneTree(true), index_code));
|
||||
toggleVarRecurse(adtypep->dtypeSkipRefp(), depth+1,
|
||||
toggleVarRecurse(adtypep->subDTypep()->skipRefp(), depth+1,
|
||||
newent,
|
||||
varp, chgVarp);
|
||||
newent.cleanup();
|
||||
@@ -232,7 +234,7 @@ private:
|
||||
UINFO(4," IF: "<<nodep<<endl);
|
||||
if (m_checkBlock) {
|
||||
nodep->ifsp()->iterateAndNext(*this);
|
||||
if (m_checkBlock
|
||||
if (m_checkBlock && !m_inModOff
|
||||
&& nodep->fileline()->coverageOn() && v3Global.opt.coverageLine()) { // if a "if" branch didn't disable it
|
||||
if (!nodep->backp()->castIf()
|
||||
|| nodep->backp()->castIf()->elsesp()!=nodep) { // Ignore if else; did earlier
|
||||
@@ -244,7 +246,7 @@ private:
|
||||
if (nodep->elsesp()) {
|
||||
m_checkBlock = true;
|
||||
nodep->elsesp()->iterateAndNext(*this);
|
||||
if (m_checkBlock
|
||||
if (m_checkBlock && !m_inModOff
|
||||
&& nodep->fileline()->coverageOn() && v3Global.opt.coverageLine()) { // if a "else" branch didn't disable it
|
||||
UINFO(4," COVER: "<<nodep<<endl);
|
||||
if (nodep->elsesp()->castIf()) {
|
||||
@@ -259,7 +261,7 @@ private:
|
||||
}
|
||||
virtual void visit(AstCaseItem* nodep, AstNUser*) {
|
||||
UINFO(4," CASEI: "<<nodep<<endl);
|
||||
if (m_checkBlock
|
||||
if (m_checkBlock && !m_inModOff
|
||||
&& nodep->fileline()->coverageOn() && v3Global.opt.coverageLine()) {
|
||||
nodep->bodysp()->iterateAndNext(*this);
|
||||
if (m_checkBlock) { // if the case body didn't disable it
|
||||
@@ -328,6 +330,7 @@ public:
|
||||
m_checkBlock = true;
|
||||
m_beginHier = "";
|
||||
m_inToggleOff = false;
|
||||
m_inModOff = true;
|
||||
rootp->iterateChildren(*this);
|
||||
}
|
||||
virtual ~CoverageVisitor() {}
|
||||
|
||||
+2
-4
@@ -1,14 +1,12 @@
|
||||
// -*- C++ -*-
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: Coverage modules/signals together
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2013 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: Netlist (top level) functions
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2013 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
// -*- C++ -*-
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: Coverage modules/signals together
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2013 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
-17
@@ -1,13 +1,12 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: Dead code elimination
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2013 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.
|
||||
@@ -22,6 +21,8 @@
|
||||
// Remove any unreferenced modules
|
||||
// Remove any unreferenced variables
|
||||
//
|
||||
// TODO: A graph would make the process of circular and interlinked
|
||||
// dependencies easier to resolve.
|
||||
// NOTE: If redo this, consider using maybePointedTo()/broken() ish scheme
|
||||
// instead of needing as many visitors.
|
||||
//*************************************************************************
|
||||
@@ -70,19 +71,21 @@ class DeadVisitor : public AstNVisitor {
|
||||
private:
|
||||
// NODE STATE
|
||||
// Entire Netlist:
|
||||
// AstNodeModule::user() -> int. Count of number of cells referencing this module.
|
||||
// AstVar::user() -> int. Count of number of references
|
||||
// AstVarScope::user() -> int. Count of number of references
|
||||
// AstNodeModule::user1() -> int. Count of number of cells referencing this module.
|
||||
// AstVar::user1() -> int. Count of number of references
|
||||
// AstVarScope::user1() -> int. Count of number of references
|
||||
// AstNodeDType::user1() -> int. Count of number of references
|
||||
AstUser1InUse m_inuser1;
|
||||
|
||||
// TYPES
|
||||
typedef multimap<AstVarScope*,AstNodeAssign*> AssignMap;
|
||||
|
||||
// STATE
|
||||
vector<AstVar*> m_varsp; // List of all encountered to avoid another loop through tree
|
||||
vector<AstNode*> m_varEtcsp; // List of all encountered to avoid another loop through tree
|
||||
vector<AstVarScope*> m_vscsp; // List of all encountered to avoid another loop through tree
|
||||
AssignMap m_assignMap; // List of all simple assignments for each variable
|
||||
bool m_elimUserVars; // Allow removal of user's vars
|
||||
bool m_elimDTypes; // Allow removal of DTypes
|
||||
bool m_sideEffect; // Side effects discovered in assign RHS
|
||||
|
||||
// METHODS
|
||||
@@ -92,13 +95,29 @@ private:
|
||||
return level;
|
||||
}
|
||||
|
||||
void checkAll(AstNode* nodep) {
|
||||
if (nodep != nodep->dtypep()) { // NodeDTypes reference themselves
|
||||
if (AstNode* subnodep = nodep->dtypep()) subnodep->user1Inc();
|
||||
}
|
||||
if (AstNode* subnodep = nodep->getChildDTypep()) subnodep->user1Inc();
|
||||
}
|
||||
void checkDType(AstNodeDType* nodep) {
|
||||
if (!nodep->generic() // Don't remove generic types
|
||||
&& m_elimDTypes) { // dtypes stick around until post-widthing
|
||||
m_varEtcsp.push_back(nodep);
|
||||
}
|
||||
if (AstNode* subnodep = nodep->virtRefDTypep()) subnodep->user1Inc();
|
||||
}
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstCell* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
checkAll(nodep);
|
||||
nodep->modp()->user1Inc();
|
||||
}
|
||||
virtual void visit(AstNodeVarRef* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
checkAll(nodep);
|
||||
if (nodep->varScopep()) {
|
||||
nodep->varScopep()->user1Inc();
|
||||
nodep->varScopep()->varp()->user1Inc();
|
||||
@@ -112,29 +131,44 @@ private:
|
||||
}
|
||||
virtual void visit(AstNodeFTaskRef* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
checkAll(nodep);
|
||||
if (nodep->packagep()) {
|
||||
nodep->packagep()->user1Inc();
|
||||
}
|
||||
}
|
||||
virtual void visit(AstRefDType* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
checkDType(nodep);
|
||||
checkAll(nodep);
|
||||
if (nodep->packagep()) {
|
||||
nodep->packagep()->user1Inc();
|
||||
}
|
||||
}
|
||||
virtual void visit(AstNodeDType* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
checkDType(nodep);
|
||||
checkAll(nodep);
|
||||
}
|
||||
virtual void visit(AstEnumItemRef* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
checkAll(nodep);
|
||||
if (nodep->packagep()) {
|
||||
nodep->packagep()->user1Inc();
|
||||
}
|
||||
}
|
||||
virtual void visit(AstVarScope* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
m_vscsp.push_back(nodep);
|
||||
checkAll(nodep);
|
||||
if (mightElim(nodep->varp())) {
|
||||
m_vscsp.push_back(nodep);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstVar* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
m_varsp.push_back(nodep);
|
||||
checkAll(nodep);
|
||||
if (mightElim(nodep)) {
|
||||
m_varEtcsp.push_back(nodep);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void visit(AstNodeAssign* nodep, AstNUser*) {
|
||||
@@ -142,20 +176,24 @@ private:
|
||||
// Similar code in V3Life
|
||||
m_sideEffect = false;
|
||||
nodep->rhsp()->iterateAndNext(*this);
|
||||
checkAll(nodep);
|
||||
// Has to be direct assignment without any EXTRACTing.
|
||||
AstVarRef* varrefp = nodep->lhsp()->castVarRef();
|
||||
if (varrefp && !m_sideEffect
|
||||
&& varrefp->varScopep()) { // For simplicity, we only remove post-scoping
|
||||
m_assignMap.insert(make_pair(varrefp->varScopep(), nodep));
|
||||
checkAll(varrefp); // Must track reference to dtype()
|
||||
} else { // Track like any other statement
|
||||
nodep->lhsp()->iterateAndNext(*this);
|
||||
}
|
||||
checkAll(nodep);
|
||||
}
|
||||
|
||||
//-----
|
||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||
if (nodep->isOutputter()) m_sideEffect=true;
|
||||
nodep->iterateChildren(*this);
|
||||
checkAll(nodep);
|
||||
}
|
||||
|
||||
// METHODS
|
||||
@@ -168,7 +206,7 @@ private:
|
||||
AstNodeModule* nextmodp;
|
||||
for (AstNodeModule* modp = v3Global.rootp()->modulesp(); modp; modp=nextmodp) {
|
||||
nextmodp = modp->nextp()->castNodeModule();
|
||||
if (modp->level()>2 && modp->user1()==0) {
|
||||
if (modp->level()>2 && modp->user1()==0 && !modp->internal()) {
|
||||
// > 2 because L1 is the wrapper, L2 is the top user module
|
||||
UINFO(4," Dead module "<<modp<<endl);
|
||||
// And its children may now be killable too; correct counts
|
||||
@@ -180,7 +218,7 @@ private:
|
||||
}
|
||||
}
|
||||
}
|
||||
bool canElim(AstVar* nodep) {
|
||||
bool mightElim(AstVar* nodep) {
|
||||
return (!nodep->isSigPublic() // Can't elim publics!
|
||||
&& !nodep->isIO()
|
||||
&& (nodep->isTemp() || nodep->isParam() || m_elimUserVars));
|
||||
@@ -189,7 +227,7 @@ private:
|
||||
// Delete any unused varscopes
|
||||
for (vector<AstVarScope*>::iterator it = m_vscsp.begin(); it!=m_vscsp.end(); ++it) {
|
||||
AstVarScope* vscp = *it;
|
||||
if (vscp->user1() == 0 && canElim(vscp->varp())) {
|
||||
if (vscp->user1() == 0) {
|
||||
UINFO(4," Dead "<<vscp<<endl);
|
||||
pair <AssignMap::iterator,AssignMap::iterator> eqrange = m_assignMap.equal_range(vscp);
|
||||
for (AssignMap::iterator it = eqrange.first; it != eqrange.second; ++it) {
|
||||
@@ -200,8 +238,8 @@ private:
|
||||
vscp->unlinkFrBack()->deleteTree(); vscp=NULL;
|
||||
}
|
||||
}
|
||||
for (vector<AstVar*>::iterator it = m_varsp.begin(); it!=m_varsp.end(); ++it) {
|
||||
if ((*it)->user1() == 0 && canElim((*it))) {
|
||||
for (vector<AstNode*>::iterator it = m_varEtcsp.begin(); it!=m_varEtcsp.end(); ++it) {
|
||||
if ((*it)->user1() == 0) {
|
||||
UINFO(4," Dead "<<(*it)<<endl);
|
||||
(*it)->unlinkFrBack()->deleteTree(); (*it)=NULL;
|
||||
}
|
||||
@@ -210,14 +248,19 @@ private:
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
DeadVisitor(AstNetlist* nodep, bool elimUserVars) {
|
||||
DeadVisitor(AstNetlist* nodep, bool elimUserVars, bool elimDTypes) {
|
||||
m_elimUserVars = elimUserVars;
|
||||
m_elimDTypes = elimDTypes;
|
||||
m_sideEffect = false;
|
||||
// Prepare to remove some datatypes
|
||||
nodep->typeTablep()->clearCache();
|
||||
// Operate on whole netlist
|
||||
nodep->accept(*this);
|
||||
deadCheckVar();
|
||||
// Modules after vars, because might be vars we delete inside a mod we delete
|
||||
deadCheckMod();
|
||||
// We may have removed some datatypes, cleanup
|
||||
nodep->typeTablep()->repairCache();
|
||||
}
|
||||
virtual ~DeadVisitor() {}
|
||||
};
|
||||
@@ -225,7 +268,15 @@ public:
|
||||
//######################################################################
|
||||
// Dead class functions
|
||||
|
||||
void V3Dead::deadifyAll(AstNetlist* nodep, bool elimUserVars) {
|
||||
void V3Dead::deadifyModules(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
DeadVisitor visitor (nodep, elimUserVars);
|
||||
DeadVisitor visitor (nodep, false, false);
|
||||
}
|
||||
void V3Dead::deadifyDTypes(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
DeadVisitor visitor (nodep, false, true);
|
||||
}
|
||||
void V3Dead::deadifyAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
DeadVisitor visitor (nodep, true, true);
|
||||
}
|
||||
|
||||
+7
-5
@@ -1,14 +1,12 @@
|
||||
// -*- C++ -*-
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: Dead branch elimination
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2013 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -31,8 +29,12 @@
|
||||
|
||||
class V3Dead {
|
||||
public:
|
||||
// Modules, no vars/dtypes
|
||||
static void deadifyModules(AstNetlist* nodep);
|
||||
// Modules, Data types
|
||||
static void deadifyDTypes(AstNetlist* nodep);
|
||||
// Everything that's possible
|
||||
static void deadifyAll(AstNetlist* nodep, bool elimUserVars);
|
||||
static void deadifyAll(AstNetlist* nodep);
|
||||
};
|
||||
|
||||
#endif // Guard
|
||||
|
||||
+63
-47
@@ -1,13 +1,12 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: Add temporaries, such as for delayed nodes
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2013 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,14 +73,15 @@ private:
|
||||
// NODE STATE
|
||||
// Cleared each module:
|
||||
// AstVarScope::user1p() -> AstVarScope*. Points to temp var created.
|
||||
// AstVarScope::user2p() -> AstActive*. Points to activity block of signal
|
||||
// AstVarScope::user2p() -> AstActive*. Points to activity block of signal (valid when AstVarScope::user1p is valid)
|
||||
// AstVarScope::user4p() -> AstAlwaysPost*. Post block for this variable
|
||||
// AstVarScope::user5() -> VarUsage. Tracks delayed vs non-delayed usage
|
||||
// AstVar::user2() -> bool. Set true if already made warning
|
||||
// AstVar::user4() -> int. Vector number, for assignment creation
|
||||
// AstVarRef::user2() -> bool. Set true if already processed
|
||||
// AstAlwaysPost::user2() -> ActActive*. Points to activity block of signal (valid when AstAlwaysPost::user4p is valid)
|
||||
// AstAlwaysPost::user4() -> AstIf*. Last IF (__Vdlyvset__) created under this AlwaysPost
|
||||
// Cleared each scope:
|
||||
// Cleared each scope/active:
|
||||
// AstAssignDly::user3() -> AstVarScope*. __Vdlyvset__ created for this assign
|
||||
// AstAlwaysPost::user3() -> AstVarScope*. __Vdlyvset__ last referenced in IF
|
||||
AstUser1InUse m_inuser1;
|
||||
@@ -124,16 +124,16 @@ private:
|
||||
AstVar* varp;
|
||||
AstNodeModule* addmodp = oldvarscp->scopep()->modp();
|
||||
// We need a new AstVar, but only one for all scopes, to match the new AstVarScope
|
||||
VarMap::iterator iter = m_modVarMap.find(make_pair(addmodp,name));
|
||||
if (iter != m_modVarMap.end()) {
|
||||
VarMap::iterator it = m_modVarMap.find(make_pair(addmodp,name));
|
||||
if (it != m_modVarMap.end()) {
|
||||
// Created module's AstVar earlier under some other scope
|
||||
varp = iter->second;
|
||||
varp = it->second;
|
||||
} else {
|
||||
if (width==0) {
|
||||
varp = new AstVar (oldvarscp->fileline(), AstVarType::BLOCKTEMP, name, oldvarscp->varp());
|
||||
varp->widthSignedFrom(oldvarscp);
|
||||
} else {
|
||||
varp = new AstVar (oldvarscp->fileline(), AstVarType::BLOCKTEMP, name, AstLogicPacked(), width);
|
||||
varp->dtypeFrom(oldvarscp);
|
||||
} else { // Used for vset and dimensions, so can zero init
|
||||
varp = new AstVar (oldvarscp->fileline(), AstVarType::BLOCKTEMP, name, VFlagBitPacked(), width);
|
||||
}
|
||||
addmodp->addStmtp(varp);
|
||||
m_modVarMap.insert(make_pair(make_pair(addmodp, name), varp));
|
||||
@@ -144,6 +144,40 @@ private:
|
||||
return varscp;
|
||||
}
|
||||
|
||||
AstActive* createActivePost(AstVarRef* varrefp) {
|
||||
AstActive* newactp = new AstActive (varrefp->fileline(), "sequentdly",
|
||||
m_activep->sensesp());
|
||||
m_activep->addNext(newactp);
|
||||
return newactp;
|
||||
}
|
||||
void checkActivePost(AstVarRef* varrefp, AstActive* oldactivep) {
|
||||
// Check for MULTIDRIVEN, and if so make new sentree that joins old & new sentree
|
||||
if (!oldactivep) varrefp->v3fatalSrc("<= old dly assignment not put under sensitivity block");
|
||||
if (oldactivep->sensesp() != m_activep->sensesp()) {
|
||||
if (!varrefp->varp()->fileline()->warnIsOff(V3ErrorCode::MULTIDRIVEN)
|
||||
&& !varrefp->varp()->user2()) {
|
||||
varrefp->varp()->v3warn(MULTIDRIVEN,"Signal has multiple driving blocks: "<<varrefp->varp()->prettyName()<<endl
|
||||
<<varrefp->warnMore()<<"... Location of first driving block"<<endl
|
||||
<<oldactivep->warnMore()<<"... Location of other driving block");
|
||||
varrefp->varp()->user2(true);
|
||||
}
|
||||
UINFO(4,"AssignDupDlyVar: "<<varrefp<<endl);
|
||||
UINFO(4," Act: "<<m_activep<<endl);
|
||||
UINFO(4," Act: "<<oldactivep<<endl);
|
||||
// Make a new sensitivity list, which is the combination of both blocks
|
||||
AstNodeSenItem* sena = m_activep->sensesp()->sensesp()->cloneTree(true);
|
||||
AstNodeSenItem* senb = oldactivep->sensesp()->sensesp()->cloneTree(true);
|
||||
AstSenTree* treep = new AstSenTree(m_activep->fileline(), sena);
|
||||
if (senb) treep->addSensesp(senb);
|
||||
if (AstSenTree* storep = oldactivep->sensesStorep()) {
|
||||
storep->unlinkFrBack();
|
||||
pushDeletep(storep);
|
||||
}
|
||||
oldactivep->sensesStorep(treep);
|
||||
oldactivep->sensesp(treep);
|
||||
}
|
||||
}
|
||||
|
||||
AstNode* createDlyArray(AstAssignDly* nodep, AstNode* lhsp) {
|
||||
// Create delayed assignment
|
||||
// See top of this file for transformation
|
||||
@@ -225,6 +259,7 @@ private:
|
||||
//
|
||||
//=== Setting/not setting boolean: __Vdlyvset__
|
||||
AstVarScope* setvscp;
|
||||
AstAssignPre* setinitp = NULL;
|
||||
|
||||
if (nodep->user3p()) {
|
||||
// Simplistic optimization. If the previous statement in same scope was also a =>,
|
||||
@@ -236,11 +271,9 @@ private:
|
||||
} else { // Create new one
|
||||
string setvarname = (string("__Vdlyvset__")+oldvarp->shortName()+"__v"+cvtToStr(modVecNum));
|
||||
setvscp = createVarSc(varrefp->varScopep(), setvarname, 1);
|
||||
AstAssignPre* setinitp
|
||||
= new AstAssignPre (nodep->fileline(),
|
||||
new AstVarRef(nodep->fileline(), setvscp, true),
|
||||
new AstConst(nodep->fileline(), 0));
|
||||
m_activep->addStmtsp(setinitp);
|
||||
setinitp = new AstAssignPre (nodep->fileline(),
|
||||
new AstVarRef(nodep->fileline(), setvscp, true),
|
||||
new AstConst(nodep->fileline(), 0));
|
||||
AstAssign* setassignp
|
||||
= new AstAssign (nodep->fileline(),
|
||||
new AstVarRef(nodep->fileline(), setvscp, true),
|
||||
@@ -269,11 +302,18 @@ private:
|
||||
UINFO(9," For "<<setvscp<<endl);
|
||||
UINFO(9," & "<<varrefp<<endl);
|
||||
AstAlwaysPost* finalp = varrefp->varScopep()->user4p()->castNode()->castAlwaysPost();
|
||||
if (!finalp) {
|
||||
if (finalp) {
|
||||
AstActive* oldactivep = finalp->user2p()->castNode()->castActive();
|
||||
checkActivePost(varrefp, oldactivep);
|
||||
if (setinitp) oldactivep->addStmtsp(setinitp);
|
||||
} else { // first time we've dealt with this memory
|
||||
finalp = new AstAlwaysPost(nodep->fileline(), NULL/*sens*/, NULL/*body*/);
|
||||
UINFO(9," Created "<<finalp<<endl);
|
||||
m_activep->addStmtsp(finalp);
|
||||
AstActive* newactp = createActivePost(varrefp);
|
||||
newactp->addStmtsp(finalp);
|
||||
varrefp->varScopep()->user4p(finalp);
|
||||
finalp->user2p(newactp);
|
||||
if (setinitp) newactp->addStmtsp(setinitp);
|
||||
}
|
||||
AstIf* postLogicp;
|
||||
if (finalp->user3p()->castNode() == setvscp) {
|
||||
@@ -292,7 +332,6 @@ private:
|
||||
finalp->user4p(postLogicp); // and the associated IF, as we may be able to reuse it
|
||||
}
|
||||
postLogicp->addIfsp(new AstAssign(nodep->fileline(), selectsp, valreadp));
|
||||
|
||||
return newlhsp;
|
||||
}
|
||||
|
||||
@@ -316,6 +355,7 @@ private:
|
||||
m_activep = nodep;
|
||||
bool oldinit = m_inInitial;
|
||||
m_inInitial = nodep->hasInitial();
|
||||
AstNode::user3ClearTree(); // Two sets to same variable in different actives must use different vars.
|
||||
nodep->iterateChildren(*this);
|
||||
m_inInitial = oldinit;
|
||||
}
|
||||
@@ -342,6 +382,7 @@ private:
|
||||
m_inDly = false;
|
||||
m_nextDlyp = NULL;
|
||||
}
|
||||
|
||||
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
||||
if (!nodep->user2Inc()) { // Not done yet
|
||||
if (m_inDly && nodep->lvalue()) {
|
||||
@@ -354,30 +395,7 @@ private:
|
||||
AstVarScope* dlyvscp = oldvscp->user1p()->castNode()->castVarScope();
|
||||
if (dlyvscp) { // Multiple use of delayed variable
|
||||
AstActive* oldactivep = dlyvscp->user2p()->castNode()->castActive();
|
||||
if (!oldactivep) nodep->v3fatalSrc("<= old dly assignment not put under sensitivity block");
|
||||
if (oldactivep->sensesp() != m_activep->sensesp()) {
|
||||
if (!nodep->varp()->fileline()->warnIsOff(V3ErrorCode::MULTIDRIVEN)
|
||||
&& !nodep->varp()->user2()) {
|
||||
nodep->varp()->v3warn(MULTIDRIVEN,"Signal has multiple driving blocks: "<<nodep->varp()->prettyName());
|
||||
nodep->v3warn(MULTIDRIVEN,"... Location of first driving block");
|
||||
oldactivep->v3warn(MULTIDRIVEN,"... Location of other driving block");
|
||||
nodep->varp()->user2(true);
|
||||
}
|
||||
UINFO(4,"AssignDupDlyVar: "<<nodep<<endl);
|
||||
UINFO(4," Act: "<<m_activep<<endl);
|
||||
UINFO(4," Act: "<<oldactivep<<endl);
|
||||
// Make a new sensitivity list, which is the combination of both blocks
|
||||
AstNodeSenItem* sena = m_activep->sensesp()->sensesp()->cloneTree(true);
|
||||
AstNodeSenItem* senb = oldactivep->sensesp()->sensesp()->cloneTree(true);
|
||||
AstSenTree* treep = new AstSenTree(m_activep->fileline(), sena);
|
||||
if (senb) treep->addSensesp(senb);
|
||||
if (AstSenTree* storep = oldactivep->sensesStorep()) {
|
||||
storep->unlinkFrBack();
|
||||
pushDeletep(storep);
|
||||
}
|
||||
oldactivep->sensesStorep(treep);
|
||||
oldactivep->sensesp(treep);
|
||||
}
|
||||
checkActivePost(nodep, oldactivep);
|
||||
}
|
||||
if (!dlyvscp) { // First use of this delayed variable
|
||||
string newvarname = (string("__Vdly__")+nodep->varp()->shortName());
|
||||
@@ -393,12 +411,10 @@ private:
|
||||
postp->lhsp()->user2(true); // Don't detect this assignment
|
||||
oldvscp->user1p(dlyvscp); // So we can find it later
|
||||
// Make new ACTIVE with identical sensitivity tree
|
||||
AstActive* newactp = new AstActive (nodep->fileline(), "sequentdly",
|
||||
m_activep->sensesp());
|
||||
AstActive* newactp = createActivePost(nodep);
|
||||
dlyvscp->user2p(newactp);
|
||||
newactp->addStmtsp(prep); // Add to FRONT of statements
|
||||
newactp->addStmtsp(postp);
|
||||
m_activep->addNext(newactp);
|
||||
dlyvscp->user2p(newactp);
|
||||
}
|
||||
AstVarRef* newrefp = new AstVarRef(nodep->fileline(), dlyvscp, true);
|
||||
newrefp->user2(true); // No reason to do it again
|
||||
|
||||
+2
-4
@@ -1,14 +1,12 @@
|
||||
// -*- C++ -*-
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: Pre C-Emit stage changes
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2013 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.
|
||||
|
||||
+4
-4
@@ -1,13 +1,12 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: Prevent very deep expressions
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2013 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 +67,8 @@ private:
|
||||
// Width, not widthMin, as we may be in middle of BITSEL expression which
|
||||
// though it's one bit wide, needs the mask in the upper bits.
|
||||
// (Someday we'll have a valid bitmask instead of widths....)
|
||||
AstLogicPacked(), nodep->width());
|
||||
// See t_func_crc for an example test that requires this
|
||||
VFlagLogicPacked(), nodep->width());
|
||||
if (!m_funcp) nodep->v3fatalSrc("Deep expression not under a function");
|
||||
m_funcp->addInitsp(varp);
|
||||
// Replace node tree with reference to var
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user