mirror of
https://github.com/verilator/verilator.git
synced 2026-10-02 16:13:34 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
55f0d4ddd8 | ||
|
|
6d66fcaa57 | ||
|
|
26e79ca889 | ||
|
|
62eb247c1e | ||
|
|
c5fd583b2c | ||
|
|
117db3e11c | ||
|
|
3f82fd2f37 | ||
|
|
e9c46afcf7 | ||
|
|
3234fa15ef | ||
|
|
7ef84df852 | ||
|
|
4e2884b509 | ||
|
|
03100020ab | ||
|
|
8bfb5cc5e9 | ||
|
|
cf6d07aafa | ||
|
|
85c3179dbd | ||
|
|
bfbca34eb0 | ||
|
|
b73edc0564 | ||
|
|
6ba90e3a50 | ||
|
|
e8edbad18c | ||
|
|
c86fec5307 | ||
|
|
6e476255ca | ||
|
|
27af9b6b06 | ||
|
|
f8208fa961 | ||
|
|
87b9cb49ad | ||
|
|
b2da0772e6 | ||
|
|
4f73e0850e | ||
|
|
b6a39db627 | ||
|
|
3a83b06572 | ||
|
|
fe5bf01b25 | ||
|
|
5559ec903b | ||
|
|
18750028b2 | ||
|
|
6b88648c67 | ||
|
|
58ee803cb4 | ||
|
|
894ff73c7d | ||
|
|
8031f0ed7f | ||
|
|
3a56b5da47 | ||
|
|
fedcb6d26a | ||
|
|
eed3c5e543 | ||
|
|
e26ab67e25 | ||
|
|
e77b7427b4 | ||
|
|
475e4207cc | ||
|
|
71b2eed32c | ||
|
|
6cf50e6579 | ||
|
|
69468708e2 | ||
|
|
5da5678e64 | ||
|
|
a428e7f618 | ||
|
|
0eb5a0a539 | ||
|
|
a1c1ff9981 | ||
|
|
2029ade18c | ||
|
|
5f8f474c0c | ||
|
|
f705f9b275 | ||
|
|
91e706ec1f | ||
|
|
dcf351f847 | ||
|
|
06744b664a | ||
|
|
d3049d9c89 | ||
|
|
1f2abb9c0f | ||
|
|
9f0d7e50a5 | ||
|
|
5f262a8f11 | ||
|
|
f62bc6a2e5 | ||
|
|
d7e4bc1379 | ||
|
|
cd2d6575c6 | ||
|
|
b46f656d17 | ||
|
|
58fd602bbd | ||
|
|
9cc95704cd | ||
|
|
5f5a3dbb0a | ||
|
|
f8f53df4ec | ||
|
|
56b85cc63c | ||
|
|
90aca97e66 | ||
|
|
6ce2a52c5f | ||
|
|
1f56312132 | ||
|
|
3aa290cddb | ||
|
|
1d1eb4fedb | ||
|
|
266ff41386 | ||
|
|
02331e5536 | ||
|
|
621c51589a | ||
|
|
4a58e859a4 | ||
|
|
48d393d8f5 | ||
|
|
321552d998 | ||
|
|
a985a1f9f5 | ||
|
|
d532a36739 | ||
|
|
b631b5927b | ||
|
|
adb39ceb98 | ||
|
|
84b91b19ca | ||
|
|
aaea68d3d6 | ||
|
|
2accba2e71 | ||
|
|
8f4f4eb5ae | ||
|
|
c5aabb3c6e | ||
|
|
60c2d136e1 | ||
|
|
cae6ec16ba | ||
|
|
30601c77d4 | ||
|
|
b0f4cf3c9c | ||
|
|
c41dfcf6ad | ||
|
|
2e10555f03 | ||
|
|
6b2ee0fcf3 | ||
|
|
0dbdbffba7 | ||
|
|
9c5dd8d767 | ||
|
|
fff0ebb5f3 | ||
|
|
d34275150c | ||
|
|
d04eb977c2 | ||
|
|
fb4928b2f5 | ||
|
|
5c39420d91 | ||
|
|
14fcfd8a40 | ||
|
|
ff19dd94f9 | ||
|
|
b6913ff9b3 | ||
|
|
4573fd3069 | ||
|
|
6cf6d9f7e1 | ||
|
|
28e35a64ea | ||
|
|
091818483a | ||
|
|
3b43556c41 | ||
|
|
ed39c66715 | ||
|
|
446b0e4e5e | ||
|
|
6e3e8318d0 | ||
|
|
17b8b660f0 | ||
|
|
40bceea68a | ||
|
|
b655c17c09 | ||
|
|
a3813f94fc | ||
|
|
c70540a825 | ||
|
|
9caffe330b | ||
|
|
8d8c5da812 | ||
|
|
55bb766c15 | ||
|
|
c18df68ead | ||
|
|
3996e94c39 | ||
|
|
1bdf017f9e | ||
|
|
93790c1dc6 | ||
|
|
ba8c11b25d | ||
|
|
ca57edfa0b | ||
|
|
ccb6545c32 | ||
|
|
d146dbc9d7 | ||
|
|
b4eaaccc88 | ||
|
|
c9ed9e74f2 | ||
|
|
587c7c70f5 | ||
|
|
749ff021b6 | ||
|
|
85c5765c00 | ||
|
|
9e76078939 | ||
|
|
334e0e1ca6 | ||
|
|
dce4519995 | ||
|
|
45bbae80e7 | ||
|
|
d37709a922 | ||
|
|
2560ae9bc1 | ||
|
|
2bdd3ca353 | ||
|
|
8a8aab1aae | ||
|
|
85d790ff79 | ||
|
|
68afc96a9f | ||
|
|
94efaa7675 | ||
|
|
180af74a50 | ||
|
|
88af0d3509 | ||
|
|
97633f7bed | ||
|
|
053e016388 | ||
|
|
2d61e0270e | ||
|
|
3a23afb0bc | ||
|
|
470f12ff46 | ||
|
|
4422de0c6c | ||
|
|
8a708f52f7 | ||
|
|
bcefc17631 | ||
|
|
daf19e241e | ||
|
|
b5f5b1fdf9 | ||
|
|
801b718953 | ||
|
|
f571658aa4 | ||
|
|
5d233b8c09 | ||
|
|
00724597f4 | ||
|
|
c659940ea8 | ||
|
|
23539eb55c | ||
|
|
e69bf418de | ||
|
|
0e1fcd38bb | ||
|
|
e74186565d | ||
|
|
7e54281e26 | ||
|
|
15f512bdee | ||
|
|
ecfe0283e2 | ||
|
|
3b874f759c | ||
|
|
9c9b4ed4e0 | ||
|
|
4f6d80c602 | ||
|
|
b50542531d | ||
|
|
8ab28d1d12 | ||
|
|
9567da22f8 | ||
|
|
36814b7681 | ||
|
|
82235e6c6f | ||
|
|
a8310f35f2 | ||
|
|
85989af031 | ||
|
|
cf9ffd16dd | ||
|
|
0602537cce | ||
|
|
24e32420b7 | ||
|
|
39c494260b | ||
|
|
761b9c9290 | ||
|
|
27686d8c2f | ||
|
|
d2b007005d | ||
|
|
f1ef30a5bb | ||
|
|
f1d9437c55 | ||
|
|
bcba5075e8 | ||
|
|
d6e8b0263c | ||
|
|
9aba617bad | ||
|
|
c24f7b1391 | ||
|
|
d4e27b635f | ||
|
|
c996d2870c | ||
|
|
bbd59f8a22 | ||
|
|
d3d359e757 | ||
|
|
ae763ea93d | ||
|
|
236b9e9761 | ||
|
|
e42c9dfd84 | ||
|
|
bebf5b291b | ||
|
|
1e3dcd203d | ||
|
|
cc7da63dec | ||
|
|
1baa2a2558 | ||
|
|
e63ff77b15 | ||
|
|
6cf9468477 | ||
|
|
b277bc8750 | ||
|
|
ba9da64207 | ||
|
|
9cb9f9c80b | ||
|
|
7a65df7636 | ||
|
|
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 | ||
|
|
7737aa20e8 | ||
|
|
ead046201c | ||
|
|
0aa7c3f659 | ||
|
|
4aa7222022 | ||
|
|
86e3c78776 | ||
|
|
40076287ea | ||
|
|
ca81db8edf | ||
|
|
ae68a80e98 | ||
|
|
beb7c58375 | ||
|
|
e080b9d565 | ||
|
|
ca2db37039 | ||
|
|
194825f78e | ||
|
|
55bd765ea0 | ||
|
|
b03d61e2cf | ||
|
|
6fc0e5167b | ||
|
|
0065be011f | ||
|
|
3f7cbce58c | ||
|
|
246b62e322 | ||
|
|
7c2fdd1ee9 | ||
|
|
f77aa2623c | ||
|
|
20847a3ff5 | ||
|
|
eb6d42acf9 | ||
|
|
094d676a8b | ||
|
|
71306ceb1d | ||
|
|
8bbfc7fc22 | ||
|
|
19baba12b1 | ||
|
|
15b8819136 | ||
|
|
3fae8ade05 | ||
|
|
f9bbf31d65 | ||
|
|
df1da3dda9 | ||
|
|
c83f2a4abd | ||
|
|
ad53833040 | ||
|
|
bc8c85668a | ||
|
|
d12a3dde45 | ||
|
|
301c878c0f | ||
|
|
bd55bfa071 | ||
|
|
6d2f09b579 | ||
|
|
4bfea7f54d | ||
|
|
55906486d8 | ||
|
|
d5478e6e08 | ||
|
|
d88d85c172 | ||
|
|
59c3c536c7 | ||
|
|
a007458cb8 | ||
|
|
d051912f21 | ||
|
|
a547158a50 | ||
|
|
95f2351aa0 | ||
|
|
698aaffb0b | ||
|
|
73eccecbf8 | ||
|
|
ae4a261463 | ||
|
|
c9f0d0cec2 | ||
|
|
4fa1e45d45 | ||
|
|
1b3d252bfe | ||
|
|
a9ba4a9fcd | ||
|
|
7f49619875 | ||
|
|
696660639a | ||
|
|
da4323062d | ||
|
|
a901e171b2 | ||
|
|
6e41d532fe | ||
|
|
4fc78ffb58 | ||
|
|
8137f41fc3 | ||
|
|
2e9471797d | ||
|
|
344248cea0 | ||
|
|
2789e3dba5 | ||
|
|
cca759a41e | ||
|
|
4f7b3d8882 | ||
|
|
2b330b78b7 | ||
|
|
d47ca1912b | ||
|
|
3fd2108b10 | ||
|
|
96e2a407f4 | ||
|
|
cdf18c96f4 | ||
|
|
53acaa05b8 | ||
|
|
fb85679068 | ||
|
|
9558e14479 | ||
|
|
4af0af93bf | ||
|
|
df4bc950fe | ||
|
|
250394f72b | ||
|
|
ca83fd6dc1 | ||
|
|
d5e9e7cd2b | ||
|
|
9a96f621ef | ||
|
|
5d7ce096c6 | ||
|
|
c9f8109c06 | ||
|
|
a20b4f2864 | ||
|
|
44a19d2a0a | ||
|
|
02f3beb8db | ||
|
|
3269cc3d90 | ||
|
|
fb70a1f4ab | ||
|
|
df0aa483ce | ||
|
|
c83f12a55c | ||
|
|
9704f59566 | ||
|
|
2923893d34 | ||
|
|
890dab0742 | ||
|
|
607e26b041 | ||
|
|
ea75290f65 | ||
|
|
a176054118 | ||
|
|
9a697dc5f5 | ||
|
|
cfdb852843 | ||
|
|
2e67a91982 | ||
|
|
074ca9330d | ||
|
|
f0d7cdcb20 | ||
|
|
40d961e059 | ||
|
|
e5de759236 | ||
|
|
e26a75c59d | ||
|
|
8701145b40 | ||
|
|
a2558886c8 | ||
|
|
f818ee86ae | ||
|
|
ad0dbdaa9c | ||
|
|
a9f14b294f | ||
|
|
a435ae98f9 | ||
|
|
481b261458 | ||
|
|
48df52d743 | ||
|
|
0af0d3b171 | ||
|
|
8287cf35e7 | ||
|
|
fab7924cc2 | ||
|
|
0ab739e8b1 | ||
|
|
2dcd4d171b | ||
|
|
e7f4d18c3d | ||
|
|
1611362c22 | ||
|
|
2327698160 | ||
|
|
71c1f00ec2 | ||
|
|
6574a126ef | ||
|
|
1e68086355 | ||
|
|
326cc8fd67 | ||
|
|
4afcb421bd | ||
|
|
8d21917035 | ||
|
|
4ca7f8834c | ||
|
|
b43299c8da | ||
|
|
b763809f5e | ||
|
|
2cb97f7475 | ||
|
|
6283df7491 | ||
|
|
acc4490370 | ||
|
|
f85c1a995a | ||
|
|
809e5fda8a | ||
|
|
dce245da5a | ||
|
|
d261c4cd27 | ||
|
|
c33299d542 | ||
|
|
ebdf8a5f3c | ||
|
|
c8852d183f | ||
|
|
9f161b20ef | ||
|
|
40f9d64973 | ||
|
|
4a2e68a0fd | ||
|
|
bcd90d3401 | ||
|
|
114af7d33f | ||
|
|
7b83d2de49 | ||
|
|
850de5913d | ||
|
|
bb9ee46f40 | ||
|
|
e94fc1305b | ||
|
|
3e4e8feb29 | ||
|
|
fedf347b1a | ||
|
|
285277a50b | ||
|
|
323c96f42f | ||
|
|
7dee344ea9 | ||
|
|
65bce588e4 | ||
|
|
233ff1b744 | ||
|
|
0837e39787 | ||
|
|
86db565a21 | ||
|
|
d6ac5e5001 | ||
|
|
e6443f1981 | ||
|
|
d13e6c73db | ||
|
|
79ca7f3cb5 | ||
|
|
cfd07ccd34 | ||
|
|
48047d523a | ||
|
|
eeb8fc2626 | ||
|
|
3d1baf3f2f | ||
|
|
4e382d6765 | ||
|
|
582963375d | ||
|
|
56c7c1bcc8 | ||
|
|
f88e57ddb8 | ||
|
|
9d98e012e4 | ||
|
|
d305a774f0 | ||
|
|
16b0c8d353 | ||
|
|
55da4fdbf6 | ||
|
|
ed2fbd8f25 | ||
|
|
42199bc8e5 | ||
|
|
7c5318768c | ||
|
|
aba25aab19 | ||
|
|
f99bd33f91 | ||
|
|
a6a6ce83f0 | ||
|
|
f4908a9758 | ||
|
|
5e4ca4b76a | ||
|
|
1e938d0e90 | ||
|
|
f3704f4c05 | ||
|
|
8800efe953 | ||
|
|
a320c4584e | ||
|
|
3841850168 | ||
|
|
beb3885840 | ||
|
|
06967c0c46 | ||
|
|
9a382c572c | ||
|
|
44b6c371db | ||
|
|
00970be996 | ||
|
|
aca4ab015f | ||
|
|
68b63d5783 | ||
|
|
4b499f2bb1 | ||
|
|
ed17581f92 | ||
|
|
a46c4ec912 | ||
|
|
930cbeec17 | ||
|
|
10689ffaba | ||
|
|
29b0ea0af9 | ||
|
|
57d00946be | ||
|
|
ef51de72c9 | ||
|
|
c807bf1e0e | ||
|
|
2525b3fb05 | ||
|
|
9163ce0f6e | ||
|
|
d776638f53 | ||
|
|
83fff41312 | ||
|
|
dd7d9bc95b | ||
|
|
f8eabbc100 | ||
|
|
7ed18ac62d | ||
|
|
3ac707c645 | ||
|
|
8e9a1e0bf3 | ||
|
|
bc31b5d27a | ||
|
|
936738b750 | ||
|
|
7c3048ab9c | ||
|
|
64719f3ace | ||
|
|
a11a5f04d5 | ||
|
|
eb5c035dde | ||
|
|
c3887efbf3 | ||
|
|
495585830d | ||
|
|
6715cb9880 | ||
|
|
41b167d23c | ||
|
|
7ea8b54210 | ||
|
|
bcea39a858 | ||
|
|
fb560abac4 | ||
|
|
ba93a08b40 | ||
|
|
2be6b3481c | ||
|
|
6ef44a6fbb | ||
|
|
2afe40a0b5 | ||
|
|
e57d004718 | ||
|
|
d780d0aabb | ||
|
|
0f9e3f0767 | ||
|
|
381972c923 | ||
|
|
845d7ad718 | ||
|
|
f1b6c0c559 | ||
|
|
e39eddf3fe | ||
|
|
72218fb475 | ||
|
|
9a3e497c22 | ||
|
|
85d510cd48 | ||
|
|
786c65ea5f | ||
|
|
10e6f61125 | ||
|
|
cdd06e7236 | ||
|
|
48603c0ee2 | ||
|
|
63f30492be | ||
|
|
0e8772290d | ||
|
|
6cfc5798b0 | ||
|
|
6be275f5d4 |
+3
-1
@@ -9,15 +9,17 @@
|
|||||||
.*.swp
|
.*.swp
|
||||||
*.tmp
|
*.tmp
|
||||||
*.tex
|
*.tex
|
||||||
|
*.pdf
|
||||||
/Makefile
|
/Makefile
|
||||||
README
|
README
|
||||||
|
TAGS
|
||||||
autom4te.cache
|
autom4te.cache
|
||||||
config.cache
|
config.cache
|
||||||
config.status
|
config.status
|
||||||
configure
|
configure
|
||||||
dddrun*
|
dddrun*
|
||||||
|
doxygen-doc
|
||||||
gdbrun*
|
gdbrun*
|
||||||
internals.txt
|
internals.txt
|
||||||
verilator.pdf
|
|
||||||
verilator.txt
|
verilator.txt
|
||||||
verilator_bin*
|
verilator_bin*
|
||||||
|
|||||||
@@ -22,8 +22,11 @@
|
|||||||
src/Makefile$
|
src/Makefile$
|
||||||
src/Makefile_obj$
|
src/Makefile_obj$
|
||||||
include/verilated.mk$
|
include/verilated.mk$
|
||||||
|
test_regress/.gdbinit$
|
||||||
config.cache$
|
config.cache$
|
||||||
config.status$
|
config.status$
|
||||||
|
verilator.log
|
||||||
|
verilator.tex
|
||||||
verilator_bin.*
|
verilator_bin.*
|
||||||
.vcsmx_rebuild$
|
.vcsmx_rebuild$
|
||||||
autom4te\.cache/
|
autom4te\.cache/
|
||||||
@@ -32,3 +35,6 @@ nodist/
|
|||||||
/simv.daidir/
|
/simv.daidir/
|
||||||
/vc_hdrs.h$
|
/vc_hdrs.h$
|
||||||
/csrc/
|
/csrc/
|
||||||
|
doxygen-doc/.*
|
||||||
|
TAGS
|
||||||
|
.*~
|
||||||
|
|||||||
+179
-74
@@ -9,7 +9,7 @@
|
|||||||
#
|
#
|
||||||
#*****************************************************************************
|
#*****************************************************************************
|
||||||
#
|
#
|
||||||
# Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
# Copyright 2003-2014 by Wilson Snyder. This program is free software; you can
|
||||||
# redistribute it and/or modify it under the terms of either the GNU
|
# redistribute it and/or modify it under the terms of either the GNU
|
||||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
# Version 2.0.
|
# Version 2.0.
|
||||||
@@ -54,11 +54,13 @@ srcdir = @srcdir@
|
|||||||
VPATH = @srcdir@
|
VPATH = @srcdir@
|
||||||
HOST = @HOST@
|
HOST = @HOST@
|
||||||
|
|
||||||
|
DOXYGEN = doxygen
|
||||||
INSTALL = @INSTALL@
|
INSTALL = @INSTALL@
|
||||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||||
INSTALL_DATA = @INSTALL_DATA@
|
INSTALL_DATA = @INSTALL_DATA@
|
||||||
MAKEINFO = makeinfo
|
MAKEINFO = makeinfo
|
||||||
POD2TEXT = pod2text
|
POD2TEXT = pod2text
|
||||||
|
POD2LATEXFIX = $(srcdir)/src/pod2latexfix
|
||||||
PERL = @PERL@
|
PERL = @PERL@
|
||||||
|
|
||||||
# Destination prefix for RPMs
|
# Destination prefix for RPMs
|
||||||
@@ -88,7 +90,10 @@ pkgdatadir = @pkgdatadir@
|
|||||||
datarootdir = @datarootdir@
|
datarootdir = @datarootdir@
|
||||||
|
|
||||||
# Compile options
|
# Compile options
|
||||||
|
CFG_WITH_CCWARN = @CFG_WITH_CCWARN@
|
||||||
CFG_WITH_DEFENV = @CFG_WITH_DEFENV@
|
CFG_WITH_DEFENV = @CFG_WITH_DEFENV@
|
||||||
|
CFG_WITH_LONGTESTS = @CFG_WITH_LONGTESTS@
|
||||||
|
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||||
|
|
||||||
#### End of system configuration section. ####
|
#### End of system configuration section. ####
|
||||||
######################################################################
|
######################################################################
|
||||||
@@ -97,29 +102,33 @@ SHELL = /bin/sh
|
|||||||
|
|
||||||
SUBDIRS = src test_verilated test_c test_sc test_sp test_regress test_vcs
|
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.
|
# Files that can be generated, but should be up to date for a distribution.
|
||||||
DISTDEP = info Makefile
|
DISTDEP = info Makefile
|
||||||
# Files to distribute.
|
|
||||||
DISTBIN = $(wildcard bin/verilator-*)
|
|
||||||
|
|
||||||
DISTFILES_INC = $(INFOS) .gitignore Artistic COPYING COPYING.LESSER \
|
DISTFILES_INC = $(INFOS) .gitignore Artistic COPYING COPYING.LESSER \
|
||||||
*.in *.ac \
|
*.in *.ac \
|
||||||
Changes TODO \
|
Changes TODO \
|
||||||
MANIFEST.SKIP \
|
MANIFEST.SKIP \
|
||||||
bin/* \
|
bin/* \
|
||||||
|
doxygen-mainpage doxygen.config veripool-logo.png \
|
||||||
install-sh configure mkinstalldirs *.pod \
|
install-sh configure mkinstalldirs *.pod \
|
||||||
include/*.[chv]* \
|
include/*.[chv]* \
|
||||||
include/*.in \
|
include/*.in \
|
||||||
include/.*ignore \
|
include/.*ignore \
|
||||||
include/vltstd/*.[chv]* \
|
include/vltstd/*.[chv]* \
|
||||||
.*attributes */.*attributes */*/.*attributes \
|
.*attributes */.*attributes */*/.*attributes \
|
||||||
src/.*ignore src/*.in src/*.cpp src/*.[chly] src/astgen src/bisonpre src/*fix \
|
src/.*ignore src/*.in src/*.cpp src/*.[chly] \
|
||||||
|
src/astgen src/bisonpre src/*fix src/cppcheck_filtered \
|
||||||
|
src/.gdbinit \
|
||||||
src/*.pl src/*.pod \
|
src/*.pl src/*.pod \
|
||||||
test_*/.*ignore test_*/Makefile* test_*/*.cpp \
|
test_*/.*ignore test_*/Makefile* test_*/*.cpp \
|
||||||
test_*/*.pl test_*/*.v test_*/*.vc test_*/vlint \
|
test_*/*.pl test_*/*.v test_*/*.vc test_*/*.vh \
|
||||||
test_verilated/vgen*.pl \
|
test_verilated/vgen*.pl \
|
||||||
|
test_regress/t/t*/*.sv* \
|
||||||
|
test_regress/t/t*/*.v* \
|
||||||
test_regress/t/*.cpp \
|
test_regress/t/*.cpp \
|
||||||
test_regress/t/*.h \
|
test_regress/t/*.h \
|
||||||
test_regress/t/*.dat \
|
test_regress/t/*.dat \
|
||||||
@@ -128,16 +137,14 @@ DISTFILES_INC = $(INFOS) .gitignore Artistic COPYING COPYING.LESSER \
|
|||||||
test_regress/t/*.pl \
|
test_regress/t/*.pl \
|
||||||
test_regress/t/*.pf \
|
test_regress/t/*.pf \
|
||||||
test_regress/t/*.v* \
|
test_regress/t/*.v* \
|
||||||
verilator.* \
|
|
||||||
|
|
||||||
INST_PROJ_FILES = \
|
INST_PROJ_FILES = \
|
||||||
bin/verilator \
|
bin/verilator \
|
||||||
bin/verilator_includer \
|
bin/verilator_includer \
|
||||||
bin/verilator_profcfunc \
|
bin/verilator_profcfunc \
|
||||||
include/verilated.[chv]* \
|
|
||||||
include/verilated.mk \
|
include/verilated.mk \
|
||||||
include/verilatedos.[chv]* \
|
include/*.[chv]* \
|
||||||
include/verilated_*.[chv]* \
|
include/vltstd/*.[chv]* \
|
||||||
|
|
||||||
INST_PROJ_BIN_FILES = \
|
INST_PROJ_BIN_FILES = \
|
||||||
verilator_bin \
|
verilator_bin \
|
||||||
@@ -145,8 +152,6 @@ INST_PROJ_BIN_FILES = \
|
|||||||
|
|
||||||
DISTFILES := $(DISTFILES_INC)
|
DISTFILES := $(DISTFILES_INC)
|
||||||
|
|
||||||
VL_INST_MAN_FILES = verilator.1
|
|
||||||
|
|
||||||
ifeq ($(OBJCACHE_JOBS),)
|
ifeq ($(OBJCACHE_JOBS),)
|
||||||
ifneq ($(OBJCACHE_HOSTS),)
|
ifneq ($(OBJCACHE_HOSTS),)
|
||||||
export OBJCACHE_JOBS := -j $(shell objcache --jobs "$(OBJCACHE_HOSTS)")
|
export OBJCACHE_JOBS := -j $(shell objcache --jobs "$(OBJCACHE_HOSTS)")
|
||||||
@@ -166,14 +171,14 @@ verilator_exe verilator_bin verilator_bin_dbg:
|
|||||||
(cd src && $(MAKE) $(OBJCACHE_JOBS) )
|
(cd src && $(MAKE) $(OBJCACHE_JOBS) )
|
||||||
|
|
||||||
.PHONY:msg_test
|
.PHONY:msg_test
|
||||||
msg_test:
|
msg_test: all_nomsg
|
||||||
@echo "Build complete!"
|
@echo "Build complete!"
|
||||||
@echo
|
@echo
|
||||||
@echo "Type 'make test' to test."
|
@echo "Type 'make test' to test."
|
||||||
@echo
|
@echo
|
||||||
|
|
||||||
.PHONY:test
|
.PHONY:test
|
||||||
ifeq ($(VERILATOR_AUTHOR_SITE),1) # Local... Else don't burden users
|
ifeq ($(CFG_WITH_LONGTESTS),yes) # Local... Else don't burden users
|
||||||
test: test_vcs test_c test_sc test_sp test_verilated test_regress
|
test: test_vcs test_c test_sc test_sp test_verilated test_regress
|
||||||
else
|
else
|
||||||
test: test_c test_sc test_sp
|
test: test_c test_sc test_sp
|
||||||
@@ -205,26 +210,19 @@ test_regress: all_nomsg
|
|||||||
info: $(INFOS)
|
info: $(INFOS)
|
||||||
|
|
||||||
# Use --no-split to avoid creating filenames > 14 chars.
|
# Use --no-split to avoid creating filenames > 14 chars.
|
||||||
verilator.1: bin/verilator
|
verilator.1: ${srcdir}/bin/verilator
|
||||||
pod2man $< $@
|
pod2man $< $@
|
||||||
|
|
||||||
verilator.txt: bin/verilator
|
verilator.txt: ${srcdir}/bin/verilator
|
||||||
$(POD2TEXT) $< $@
|
$(POD2TEXT) $< $@
|
||||||
|
|
||||||
verilator.html: bin/verilator
|
verilator.html: ${srcdir}/bin/verilator
|
||||||
pod2html $< >$@
|
pod2html $< >$@
|
||||||
|
|
||||||
verilator.pdf: bin/verilator $(DISTCONFIG)
|
# PDF needs DIST variables; but having configure.ac as dependency isn't detected
|
||||||
pod2latex --full --out verilator.tex bin/verilator
|
verilator.pdf: ${srcdir}/bin/verilator Makefile
|
||||||
cat < verilator.tex \
|
pod2latex --full --out verilator.tex ${srcdir}/bin/verilator
|
||||||
| sed 's/\\begin{document}/\\usepackage[left=1.7in,right=1.7in,top=1.3in,bottom=1.3in]{geometry}\n\\begin{document}/' \
|
$(PERL) $(POD2LATEXFIX) "$(DISTTITLE)" "${DISTDATE}" < verilator.tex > verilator2.tex
|
||||||
| 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
|
|
||||||
mv verilator2.tex verilator.tex
|
mv verilator2.tex verilator.tex
|
||||||
pdflatex verilator.tex
|
pdflatex verilator.tex
|
||||||
pdflatex verilator.tex
|
pdflatex verilator.tex
|
||||||
@@ -234,15 +232,57 @@ README: readme.pod
|
|||||||
-rm -f $@
|
-rm -f $@
|
||||||
$(POD2TEXT) --loose $< > $@
|
$(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
|
internals.txt: internals.pod
|
||||||
-rm -f $@
|
-rm -f $@
|
||||||
$(POD2TEXT) --loose $< > $@
|
$(POD2TEXT) --loose $< > $@
|
||||||
|
|
||||||
# See uninstall also
|
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 \
|
VL_INST_BIN_FILES = verilator verilator_bin verilator_bin_dbg \
|
||||||
verilator_includer verilator_profcfunc
|
verilator_includer verilator_profcfunc
|
||||||
# Some scripts go into both the search path and pkgdatadir,
|
# Some scripts go into both the search path and pkgdatadir,
|
||||||
# so they can be found by the user, and under $VERILATOR_ROOT.
|
# so they can be found by the user, and under $VERILATOR_ROOT.
|
||||||
|
|
||||||
|
# See uninstall also - don't put wildcards in this variable, it might uninstall other stuff
|
||||||
|
VL_INST_MAN_FILES = verilator.1
|
||||||
|
|
||||||
|
VL_INST_INC_BLDDIR_FILES = \
|
||||||
|
include/verilated.mk \
|
||||||
|
|
||||||
|
# Files under srcdir, instead of build time
|
||||||
|
VL_INST_INC_SRCDIR_FILES = \
|
||||||
|
include/*.[chv]* \
|
||||||
|
include/vltstd/*.[chv]* \
|
||||||
|
|
||||||
|
VL_INST_DATA_SRCDIR_FILES = \
|
||||||
|
test_v/*.[chv]* \
|
||||||
|
test_c/*.[chv]* test_c/Makefile test_c/Makefile_obj \
|
||||||
|
test_sc/*.[chv]* test_sc/Makefile test_sc/Makefile_obj \
|
||||||
|
test_sp/Makefile test_sp/Makefile_obj \
|
||||||
|
|
||||||
installbin:
|
installbin:
|
||||||
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(bindir)
|
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(bindir)
|
||||||
( cd ${srcdir}/bin ; $(INSTALL_PROGRAM) verilator $(DESTDIR)$(bindir)/verilator )
|
( cd ${srcdir}/bin ; $(INSTALL_PROGRAM) verilator $(DESTDIR)$(bindir)/verilator )
|
||||||
@@ -252,37 +292,68 @@ installbin:
|
|||||||
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(pkgdatadir)/bin
|
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(pkgdatadir)/bin
|
||||||
( cd ${srcdir}/bin ; $(INSTALL_PROGRAM) verilator_includer $(DESTDIR)$(pkgdatadir)/bin/verilator_includer )
|
( cd ${srcdir}/bin ; $(INSTALL_PROGRAM) verilator_includer $(DESTDIR)$(pkgdatadir)/bin/verilator_includer )
|
||||||
|
|
||||||
|
# Man files can either be part of the original kit, or built in current directory
|
||||||
|
# So important we use $< so VPATH is searched
|
||||||
installman: $(VL_INST_MAN_FILES)
|
installman: $(VL_INST_MAN_FILES)
|
||||||
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(mandir)/man1
|
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(mandir)/man1
|
||||||
for p in $(VL_INST_MAN_FILES) ; do \
|
for p in $< ; do \
|
||||||
$(INSTALL_PROGRAM) $$p $(DESTDIR)$(mandir)/man1/$$p; \
|
$(INSTALL_DATA) $$p $(DESTDIR)$(mandir)/man1/$$p; \
|
||||||
done
|
done
|
||||||
|
|
||||||
installdata:
|
installdata:
|
||||||
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(pkgdatadir)/include/vltstd $(DESTDIR)$(pkgdatadir)/examples
|
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(pkgdatadir)/include/vltstd
|
||||||
cp -r include/*.* $(DESTDIR)$(pkgdatadir)/include
|
for p in $(VL_INST_INC_BLDDIR_FILES) ; do \
|
||||||
cp -r ${srcdir}/include/*.* $(DESTDIR)$(pkgdatadir)/include
|
$(INSTALL_DATA) $$p $(DESTDIR)$(pkgdatadir)/$$p; \
|
||||||
cp -r ${srcdir}/include/vltstd/*.* $(DESTDIR)$(pkgdatadir)/include/vltstd
|
done
|
||||||
cp -r ${srcdir}/test_c $(DESTDIR)$(pkgdatadir)/examples
|
cd $(srcdir) \
|
||||||
cp -r ${srcdir}/test_sc $(DESTDIR)$(pkgdatadir)/examples
|
; for p in $(VL_INST_INC_SRCDIR_FILES) ; do \
|
||||||
cp -r ${srcdir}/test_sp $(DESTDIR)$(pkgdatadir)/examples
|
$(INSTALL_DATA) $$p $(DESTDIR)$(pkgdatadir)/$$p; \
|
||||||
cp -r ${srcdir}/test_v $(DESTDIR)$(pkgdatadir)/examples
|
done
|
||||||
|
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(pkgdatadir)/examples/test_c
|
||||||
|
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(pkgdatadir)/examples/test_sc
|
||||||
|
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(pkgdatadir)/examples/test_sp
|
||||||
|
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(pkgdatadir)/examples/test_v
|
||||||
|
cd $(srcdir) \
|
||||||
|
; for p in $(VL_INST_DATA_SRCDIR_FILES) ; do \
|
||||||
|
$(INSTALL_DATA) $$p $(DESTDIR)$(pkgdatadir)/examples/$$p; \
|
||||||
|
done
|
||||||
|
|
||||||
VL_INST_DATA_FILES = verilator.1
|
# We don't trust rm -rf, so rmdir instead as it will fail if user put in other files
|
||||||
install: all_nomsg installbin installman installdata install-msg
|
uninstall:
|
||||||
|
-cd $(DESTDIR)$(bindir) && rm -f $(VL_INST_BIN_FILES)
|
||||||
|
-cd $(DESTDIR)$(pkgdatadir)/bin && rm -f $(VL_INST_BIN_FILES)
|
||||||
|
-cd $(DESTDIR)$(mandir)/man1 && rm -f $(VL_INST_MAN_FILES)
|
||||||
|
-cd $(DESTDIR)$(pkgdatadir) && rm -f $(VL_INST_INC_BLDDIR_FILES)
|
||||||
|
-cd $(DESTDIR)$(pkgdatadir) && rm -f $(VL_INST_INC_SRCDIR_FILES)
|
||||||
|
-cd $(DESTDIR)$(pkgdatadir)/examples && rm -f $(VL_INST_DATA_SRCDIR_FILES)
|
||||||
|
-rmdir $(DESTDIR)$(pkgdatadir)/bin
|
||||||
|
-rmdir $(DESTDIR)$(pkgdatadir)/include/vltstd
|
||||||
|
-rmdir $(DESTDIR)$(pkgdatadir)/include
|
||||||
|
-rmdir $(DESTDIR)$(pkgdatadir)/examples/test_c
|
||||||
|
-rmdir $(DESTDIR)$(pkgdatadir)/examples/test_sc
|
||||||
|
-rmdir $(DESTDIR)$(pkgdatadir)/examples/test_sp
|
||||||
|
-rmdir $(DESTDIR)$(pkgdatadir)/examples/test_v
|
||||||
|
-rmdir $(DESTDIR)$(pkgdatadir)/examples
|
||||||
|
-rmdir $(DESTDIR)$(pkgdatadir)
|
||||||
|
|
||||||
|
install: all_nomsg install-all
|
||||||
|
install-all: installbin installman installdata install-msg
|
||||||
|
|
||||||
install-here: installman ftp
|
install-here: installman ftp
|
||||||
|
|
||||||
ifeq ($(VERILATOR_AUTHOR_SITE),1) # Local... Else don't burden users
|
ifeq ($(VERILATOR_AUTHOR_SITE),1) # Local... Else don't burden users
|
||||||
|
DISTNAMEREV = $(shell sed -e '/DTVERSION/!d' -e 's/.*verilator_\([^"]*\).*/\1/' -e q ${srcdir}/src/config_rev.h)
|
||||||
|
|
||||||
DIRPROJECT := $(shell project_dir --project)
|
DIRPROJECT := $(shell project_dir --project)
|
||||||
|
VERILATOR_CAD_DIR = $(CAD_DIR)/verilator/$(DISTNAMEREV)/$(DIRPROJECT_ARCH)
|
||||||
INST_PROJ_CVS = cp_if_cvs_diff
|
INST_PROJ_CVS = cp_if_cvs_diff
|
||||||
|
|
||||||
install-project: dist
|
install-project: dist
|
||||||
@echo "Install-project to $(DIRPROJECT)"
|
@echo "Install-project to $(DIRPROJECT)"
|
||||||
strip verilator_bin*
|
strip verilator_bin*
|
||||||
$(MAKE) install-project-quick
|
$(MAKE) install-project-quick
|
||||||
for p in verilator.1 ; do \
|
for p in $(VL_INST_MAN_FILES) ; do \
|
||||||
$(INSTALL_PROGRAM) -m 0666 $$p $(DIRPROJECT_PREFIX)/man/man1/$$p; \
|
$(INSTALL_DATA) $$p $(DIRPROJECT_PREFIX)/man/man1/$$p; \
|
||||||
done
|
done
|
||||||
$(INST_PROJ_CVS) $(DISTNAME).tgz $(DIRPROJECT)/hw/utils/verilator/verilator.tgz
|
$(INST_PROJ_CVS) $(DISTNAME).tgz $(DIRPROJECT)/hw/utils/verilator/verilator.tgz
|
||||||
rm $(DISTNAME).tgz
|
rm $(DISTNAME).tgz
|
||||||
@@ -299,44 +370,75 @@ endif
|
|||||||
for p in $(INST_PROJ_BIN_FILES) ; do \
|
for p in $(INST_PROJ_BIN_FILES) ; do \
|
||||||
$(INST_PROJ_CVS) $$p $(DIRPROJECT)/hw/utils/verilator/$$p-$(DIRPROJECT_ARCH); \
|
$(INST_PROJ_CVS) $$p $(DIRPROJECT)/hw/utils/verilator/$$p-$(DIRPROJECT_ARCH); \
|
||||||
done
|
done
|
||||||
|
|
||||||
|
install-cadtools: dist
|
||||||
|
@echo "Install-project to $(CAD_DIR)"
|
||||||
|
strip verilator_bin*
|
||||||
|
$(MAKE) install-cadtools-quick
|
||||||
|
$(SHELL) ${srcdir}/mkinstalldirs $(VERILATOR_CAD_DIR)/man/man1
|
||||||
|
for p in $(VL_INST_MAN_FILES) ; do \
|
||||||
|
$(INSTALL_DATA) $$p $(VERILATOR_CAD_DIR)/man/man1/$$p; \
|
||||||
|
done
|
||||||
|
$(INST_PROJ_CVS) $(DISTNAME).tgz $(VERILATOR_CAD_DIR)/verilator.tgz
|
||||||
|
rm $(DISTNAME).tgz
|
||||||
|
|
||||||
|
install-cadtools-quick:
|
||||||
|
ifeq ($(CFG_WITH_DEFENV),yes)
|
||||||
|
@echo "%Error: Reconfigure with './configure --disable-defenv' to avoid hardcoded paths."
|
||||||
|
false
|
||||||
endif
|
endif
|
||||||
|
@echo "Install-cadtools-quick (no strip) to $(VERILATOR_CAD_DIR)"
|
||||||
|
$(SHELL) ${srcdir}/mkinstalldirs $(VERILATOR_CAD_DIR)/include/vltstd
|
||||||
|
$(SHELL) ${srcdir}/mkinstalldirs $(VERILATOR_CAD_DIR)/bin
|
||||||
|
for p in $(INST_PROJ_FILES) ; do \
|
||||||
|
$(INST_PROJ_CVS) $$p $(VERILATOR_CAD_DIR)/$$p; \
|
||||||
|
done
|
||||||
|
for p in $(INST_PROJ_BIN_FILES) ; do \
|
||||||
|
$(INST_PROJ_CVS) $$p $(VERILATOR_CAD_DIR)/$$p; \
|
||||||
|
done
|
||||||
|
|
||||||
|
# VERILATOR_AUTHOR_SITE
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Use --xml flag to see the cppcheck code to use for suppression
|
||||||
|
CPPCHECK = src/cppcheck_filtered
|
||||||
|
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 $(CPPCHECK_INC) $<
|
||||||
|
|
||||||
ftp: info
|
ftp: info
|
||||||
|
|
||||||
install-msg:
|
install-msg:
|
||||||
@echo "Installed!"
|
@echo "Installed!"
|
||||||
@echo
|
@echo
|
||||||
@echo "Add to your startup file (for bash or csh, as appropriate):"
|
@echo "Fod documentation see 'man verilator' or 'verilator --help'"
|
||||||
@echo " export VERILATOR_ROOT="`pwd`
|
@echo "For forums and to report bugs see http://www.veripool.org/verilator"
|
||||||
@echo " setenv VERILATOR_ROOT "`pwd` " ; export VERILATOR_ROOT "
|
|
||||||
@echo
|
|
||||||
@echo "See 'verilator.txt' for documentation."
|
|
||||||
@echo
|
@echo
|
||||||
|
|
||||||
uninstall:
|
IN_WILD := ${srcdir}/*.in ${srcdir}/*/*.in
|
||||||
-cd $(DESTDIR)$(mandir)/man1 && rm -f $(VL_INST_MAN_FILES)
|
|
||||||
-cd $(DESTDIR)$(bindir) && rm -f $(VL_INST_BIN_FILES)
|
|
||||||
-rm -f $(DESTDIR)$(pkgdatadir)
|
|
||||||
|
|
||||||
# autoheader might not change config_build.h.in, so touch a stamp file.
|
# autoheader might not change config_build.h.in, so touch it
|
||||||
IN_WILD := ${srcdir}/*.in ${srcdir}/*/*.in ${srcdir}/*/*/*.in \
|
${srcdir}/config_build.h: ${srcdir}/config_build.h.in configure
|
||||||
*.in */*.in */*.in
|
|
||||||
|
|
||||||
${srcdir}/config_build.h.in: stamp-h.in
|
|
||||||
${srcdir}/stamp-h.in: configure.ac $(wildcard $(IN_WILD))
|
|
||||||
cd ${srcdir} && autoheader
|
cd ${srcdir} && autoheader
|
||||||
echo timestamp > ${srcdir}/stamp-h.in
|
touch $@
|
||||||
config_build.h: stamp-h
|
Makefile: Makefile.in config.status $(IN_WILD)
|
||||||
stamp-h: config_build.h.in config.status
|
|
||||||
./config.status
|
|
||||||
Makefile: Makefile.in config.status
|
|
||||||
./config.status
|
|
||||||
src/Makefile: src/Makefile.in config.status
|
|
||||||
./config.status
|
./config.status
|
||||||
|
src/Makefile: src/Makefile.in Makefile
|
||||||
config.status: configure
|
config.status: configure
|
||||||
./config.status --recheck
|
./config.status --recheck
|
||||||
|
|
||||||
configure: configure.ac
|
configure: configure.ac
|
||||||
|
ifeq ($(CFG_WITH_CCWARN),yes) # Local... Else don't burden users
|
||||||
|
autoconf --warnings=all
|
||||||
|
else
|
||||||
autoconf
|
autoconf
|
||||||
|
endif
|
||||||
|
|
||||||
maintainer-clean::
|
maintainer-clean::
|
||||||
@echo "This command is intended for maintainers to use;"
|
@echo "This command is intended for maintainers to use;"
|
||||||
@@ -358,14 +460,19 @@ clean mostlyclean distclean maintainer-clean::
|
|||||||
|
|
||||||
distclean maintainer-clean::
|
distclean maintainer-clean::
|
||||||
rm -f Makefile config.status config.cache config.log verilator_bin* TAGS
|
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 \
|
TAGFILES=${srcdir}/*/*.cpp ${srcdir}/*/*.h ${srcdir}/*/*.in \
|
||||||
${srcdir}/[a-z]*.in ${srcdir}/*.pod
|
${srcdir}/*.in ${srcdir}/*.pod
|
||||||
|
|
||||||
TAGS: $(TAGFILES)
|
TAGS: $(TAGFILES)
|
||||||
etags $(TAGFILES)
|
etags $(TAGFILES)
|
||||||
|
|
||||||
|
.PHONY: doxygen
|
||||||
|
|
||||||
|
doxygen:
|
||||||
|
$(DOXYGEN) doxygen.config
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
# Test targets
|
# Test targets
|
||||||
|
|
||||||
@@ -377,14 +484,12 @@ dist-file-list:
|
|||||||
######################################################################
|
######################################################################
|
||||||
# Distributions
|
# Distributions
|
||||||
|
|
||||||
DISTCONFIG = ${srcdir}/src/config_build.h.in
|
DISTTITLE := Verilator $(word 1,$(PACKAGE_VERSION))
|
||||||
|
DISTNAME := verilator-$(word 1,$(PACKAGE_VERSION))
|
||||||
DISTTITLE := $(shell sed -e '/DTVERSION/!d' -e 's/[^0-9]*\([0-9.a-z]*\).*/verilator-\1/' -e 's/v/V/' -e q $(DISTCONFIG))
|
DISTDATEPRE := $(word 2,$(PACKAGE_VERSION))
|
||||||
DISTNAME := $(shell sed -e '/DTVERSION/!d' -e 's/[^0-9]*\([0-9.a-z]*\).*/verilator-\1/' -e q $(DISTCONFIG))
|
DISTDATE := $(subst /,-,$(DISTDATEPRE))
|
||||||
DISTDATEPRE := $(shell sed -e '/DTVERSION/!d' -e 's/.*\([1-2][0-9][0-9][0-9].[0-9]*[0-9].[0-9]*[0-9]\).*/\1/' -e q $(DISTCONFIG))
|
|
||||||
|
|
||||||
DISTTAGNAME := $(subst .,_,$(subst -,_,$(DISTNAME)))
|
DISTTAGNAME := $(subst .,_,$(subst -,_,$(DISTNAME)))
|
||||||
DISTDATE := $(subst /,-,$(DISTDATEPRE))
|
|
||||||
|
|
||||||
tag:
|
tag:
|
||||||
svnorcvs tag $(DISTTAGNAME)
|
svnorcvs tag $(DISTTAGNAME)
|
||||||
|
|||||||
@@ -1,134 +1,146 @@
|
|||||||
// DESCRIPTION: Verilator: List of To Do issues.
|
// DESCRIPTION: Verilator: List of To Do issues.
|
||||||
//
|
//
|
||||||
// Copyright 2004-2010 by Wilson Snyder. This program is free software; you can
|
// Copyright 2004-2014 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
|
|
||||||
|
|
||||||
Features:
|
Language support:
|
||||||
Latch optimizations {Need here}
|
* Fix ordering of each bit separately in a signal (mips)
|
||||||
Task I/Os connecting to non-simple variables.
|
|
||||||
Fix ordering of each bit separately in a signal (mips)
|
|
||||||
assign b[3:0] = b[7:4]; assign b[7:4] = in;
|
assign b[3:0] = b[7:4]; assign b[7:4] = in;
|
||||||
Support gate primitives/ cell libraries from xilinx, etc
|
* Support UDP gate primitives/ cell libraries
|
||||||
Assign dont_care value to an 1'bzzz assignment
|
(have code for combos - problem is sequential udps)
|
||||||
Function to eval combo logic after /*verilator public*/ functions [gwaters]
|
* Function to eval combo logic after /*verilator public*/ functions [gwaters]
|
||||||
Support generated clocks (correctness)
|
* Support generated clocks (correctness)
|
||||||
?gcov coverage
|
* Real numbers
|
||||||
Selectable SystemC types based on widths (see notes below)
|
* Recursive functions
|
||||||
Coverage
|
* Verilog configuration files
|
||||||
Points should be per-scope like everything else rather then per-module
|
* Structs/unions (have starting point)
|
||||||
Expression coverage (see notes)
|
* DPI to define C/C++ calls from Verilog
|
||||||
Constant functions for widths, etc, IE "input [log2(PARAM):0] xx;"
|
* Expression coverage (see notes)
|
||||||
More Verilog 2001 Support
|
* Better tristate support
|
||||||
(* *) Attributes (just ignore -- preprocessor?)
|
|
||||||
Real numbers (NEVER)
|
|
||||||
Recursive functions (NEVER)
|
|
||||||
Verilog configuration files (NEVER)
|
|
||||||
DPI to define C/C++ calls from Verilog
|
|
||||||
|
|
||||||
Long-term Features
|
Long-term Features
|
||||||
Assertions
|
* Assertions
|
||||||
VHDL parser [Philips]
|
* Tristate support
|
||||||
Tristate support
|
* Multithreaded execution
|
||||||
SystemPerl integration
|
|
||||||
Multithreaded execution
|
Configure/Make/Install
|
||||||
|
* Full MSVC++ compilation (does scons support this?) (4.000?)
|
||||||
|
* Distribute with flex/bison already expanded?
|
||||||
|
Flex library not needed. Probably too difficult to be worth it.
|
||||||
|
* Integrate SystemPerl coverage
|
||||||
|
see the SystemPerl git branch coverage_only
|
||||||
|
(Note in /usr/include there are no upper cased include files.)
|
||||||
|
Coverage.pm -- Need all functionality, but in C?
|
||||||
|
Coverage/Item.pm -- Need all functionality, but in C?
|
||||||
|
Coverage/ItemKey.pm -- Need all functionality, but in C?
|
||||||
|
sp_preproc -- Some steps in here need to be moved to generated C
|
||||||
|
-- -- note uses Verilog::Getopt
|
||||||
|
src/Sp.cpp -- n/a
|
||||||
|
src/SpCommon.h -- mostly overlaps verilatedos.h
|
||||||
|
src/SpCoverage.cpp/h -- All needed
|
||||||
|
src/SpFunctor.cpp/h -- No longer used
|
||||||
|
src/SpTraceVcd.cpp/h -- MOVED
|
||||||
|
src/SpTraceVcdC.cpp/h -- MOVED
|
||||||
|
src/sp_log.cpp/h -- Not needed
|
||||||
|
src/systemperl.h -- some stuff may be cut
|
||||||
|
vcoverage -- Need all functionality, but in C?
|
||||||
|
|
||||||
Testing:
|
Testing:
|
||||||
Capture all inputs into global "rerun it" file
|
* Move test_c/sp/v/verilated into test_regress format (4.000?)
|
||||||
Code to make wrapper that sets signals, so can do comparison checks
|
* Capture all inputs into global "rerun it" file
|
||||||
New random program generator
|
* Code to make wrapper that sets signals, so can do comparison checks
|
||||||
Better graph viewer with search and zoom
|
* New random program generator
|
||||||
Port and test against opencores.org code
|
* Better graph viewer with search and zoom
|
||||||
|
* Port and test against opencores.org code
|
||||||
|
* // verilator debug in code so can see only tree affecting those nodes
|
||||||
|
|
||||||
Usability:
|
Usability:
|
||||||
Better reporting of unopt problems, including what lines of code
|
* Detect and pre-remove most UNOPTFLATs (4.000)
|
||||||
Report more errors (all of them?) before exiting [Eugene Weber]
|
* Better reporting of unopt problems, including what lines of code
|
||||||
|
* Report more errors (all of them?) before exiting [Eugene Weber]
|
||||||
|
* Auto-create scons config files
|
||||||
|
* 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-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")
|
||||||
|
|
||||||
|
Lint:
|
||||||
|
* CDCRSTLOGIC should allow filtering with paths
|
||||||
|
"waive CDCRSTLOGIC --from a.b.sig --to a.c.sig --via OR"
|
||||||
|
|
||||||
Internal Code:
|
Internal Code:
|
||||||
Eliminate the AstNUser* passed to all visitors; its only needed in V3Width,
|
* Eliminate the AstNUser* passed to all visitors; its only needed in V3Width,
|
||||||
and removing it will speed up and simplify all the other code.
|
and removing it will speed up and simplify all the other code.
|
||||||
V3Graph should be templated container type, taking in Vertex + Edge types
|
* V3Graph should be templated container type, taking in Vertex + Edge types
|
||||||
|
* Rename V3PreLex etc to match VerilogPerl filenames
|
||||||
|
* Instead of string, have an VEncodedString/VIdString which contains __DOT__ish
|
||||||
|
things, to reduce bugs. Also add _20 trailing space to \ encoded names. (4.000)
|
||||||
|
|
||||||
|
Runtime:
|
||||||
|
* New evalulation loop ~/src/verilator/notes/event_loop.txt (4.000?)
|
||||||
|
* Remove all private internal functions from top level wrapper header, move
|
||||||
|
to new level (4.000?)
|
||||||
|
* Completely standalone simulation (4.000)
|
||||||
|
main() records arguments for $test$plusvars
|
||||||
|
instantiates top,
|
||||||
|
does tracing (support $dump?)
|
||||||
|
calls top->simulateForever()
|
||||||
|
exits
|
||||||
|
|
||||||
Performance:
|
Performance:
|
||||||
Constant propagation
|
* Latch optimizations
|
||||||
|
* Constant propagation
|
||||||
Extra cleaning AND: 1 & ((VARREF >> 1) | ((&VARREF >> 1) & VARREF))
|
Extra cleaning AND: 1 & ((VARREF >> 1) | ((&VARREF >> 1) & VARREF))
|
||||||
Extra shift (perhaps due to clean): if (1 & CAST (VARREF >> #))
|
Extra shift (perhaps due to clean): if (1 & CAST (VARREF >> #))
|
||||||
Gated clock and latch conversion to flops. [JeanPaul Vanitegem]
|
* Gated clock and latch conversion to flops. [JeanPaul Vanitegem]
|
||||||
Could propagate the AND into pos/negedges and let domaining optimize.
|
Could propagate the AND into pos/negedges and let domaining optimize.
|
||||||
Negedge reset
|
* Negedge reset
|
||||||
Switch to remove negedges that don't matter
|
Switch to remove negedges that don't matter
|
||||||
Can't remove async resets from control flops (like in syncronizers)
|
Can't remove async resets from control flops (like in syncronizers)
|
||||||
If all references to array have a constant index, blow up into separate signals-per-index
|
* If all references to array have a constant index, blow up into separate signals-per-index
|
||||||
Multithreaded execution
|
* Bit-multiply for faster bit swapping and a=b[1,3,2] random bit reorderings.
|
||||||
Bit-multiply for faster bit swapping and a=b[1,3,2] random bit reorderings.
|
* Move _last sets and all other combo logic inside master
|
||||||
Move _last sets and all other combo logic inside master
|
|
||||||
if() that triggers on all possible sense items
|
if() that triggers on all possible sense items
|
||||||
Rewrite and combine V3Life, V3Subst
|
* Rewrite and combine V3Life, V3Subst
|
||||||
If block temp only ever set in one place to constant, propagate it
|
If block temp only ever set in one place to constant, propagate it
|
||||||
Used in t_mem for array delayed assignments
|
Used in t_mem for array delayed assignments
|
||||||
Replace variables if set later in same cfunc branch
|
Replace variables if set later in same cfunc branch
|
||||||
See for example duplicate sets of _narrow in cycle 90/91 of t_select_plusloop
|
See for example duplicate sets of _narrow in cycle 90/91 of t_select_plusloop
|
||||||
Same assignment on both if branches
|
* Same assignment on both if branches
|
||||||
"if (a) { ... b=2; } else { ... b=2;}" -> "b=2; if ..."
|
"if (a) { ... b=2; } else { ... b=2;}" -> "b=2; if ..."
|
||||||
Careful though, as b could appear in the statement or multiple times in statement
|
Careful though, as b could appear in the statement or multiple times in statement
|
||||||
(Could just require exatly two 'b's in statement)
|
(Could just require exatly two 'b's in statement)
|
||||||
Simplify XOR/XNOR/AND/OR bit selection trees
|
* Simplify XOR/XNOR/AND/OR bit selection trees
|
||||||
Foo = A[1] ^ A[2] ^ A[3] etc are better as ^ ( A & 32'b...1110 )
|
Foo = A[1] ^ A[2] ^ A[3] etc are better as ^ ( A & 32'b...1110 )
|
||||||
Combine variables into wider elements
|
* Combine variables into wider elements
|
||||||
Parallel statements on different bits should become single signal
|
Parallel statements on different bits should become single signal
|
||||||
Variables that are always consumed in "parallel" can be joined
|
Variables that are always consumed in "parallel" can be joined
|
||||||
Duplicate assignments in gate optimization
|
* Duplicate assignments in gate optimization
|
||||||
Common to have many separate posedge blocks, each with identical
|
Common to have many separate posedge blocks, each with identical
|
||||||
reset_r <= rst_in
|
reset_r <= rst_in
|
||||||
*If signal is used only once (not counting trace), always gate substitute
|
* If signal is used only once (not counting trace), always gate substitute
|
||||||
Don't merge if any combining would form circ logic (out goes back to in)
|
Don't merge if any combining would form circ logic (out goes back to in)
|
||||||
Multiple assignments each bit can become single assign with concat
|
* Multiple assignments each bit can become single assign with concat
|
||||||
Make sure a SEL of a CONCAT can get the single bit back.
|
Make sure a SEL of a CONCAT can get the single bit back.
|
||||||
Usually blocks/values
|
* Usually blocks/values
|
||||||
Enable only after certain time, so VL_TIME_I(32) > 0x1e gets eliminated out
|
Enable only after certain time, so VL_TIME_I(32) > 0x1e gets eliminated out
|
||||||
Better ordering of a<=b, b<=c, put all refs to 'b' next to each other to optimize caching
|
* Better ordering of a<=b, b<=c, put all refs to 'b' next to each other to optimize caching
|
||||||
Allow Split of case statements without a $display/$stop
|
* Allow Split of case statements without a $display/$stop
|
||||||
I-cache packing improvements (what/how?)
|
* I-cache packing improvements (what/how?)
|
||||||
Data cache organization (order of vars in class)
|
* Data cache organization (order of vars in class)
|
||||||
First have clocks,
|
First have clocks,
|
||||||
then bools instead of uint32_t's
|
then bools instead of uint32_t's
|
||||||
then based on what sense list they come from, all outputs, then all inputs
|
then based on what sense list they come from, all outputs, then all inputs
|
||||||
finally have any signals part of a "usually" block, or constant.
|
finally have any signals part of a "usually" block, or constant.
|
||||||
Rather then tracking widths, have a MSB...LSB of this expression
|
* Rather then tracking widths, have a MSB...LSB of this expression
|
||||||
(or better, a bitmask of bits relevant in this expression)
|
(or better, a bitmask of bits relevant in this expression)
|
||||||
Track recirculation and convert into clock-enables
|
* Track recirculation and convert into clock-enables
|
||||||
Clock enables should become new clocking domains for speed
|
* Clock enables should become new clocking domains for speed
|
||||||
If floped(a) & flopped(b) and no other a&b, then instead flop(a&b).
|
* If floped(a) & flopped(b) and no other a&b, then instead flop(a&b).
|
||||||
Sort by output bitselects so can combine more assignments (see DDP example dx_dm signal)
|
* Sort by output bitselects so can combine more assignments (see DDP example dx_dm signal)
|
||||||
|
|
||||||
All of the temp vars that get set, exp pre_ vars and never feedback
|
|
||||||
(not flops) don't need to be stored in the structs, but instead can
|
|
||||||
be per-invocation, and even better register-colored-like to reuse
|
|
||||||
the space. This will greatly reduce the data footprint.
|
|
||||||
|
|
||||||
|
|
||||||
//**********************************************************************
|
|
||||||
//* Eventual tristate bus Stuff allowed (old verilator)
|
|
||||||
|
|
||||||
1) Tristate assignments must be continuous assignments
|
|
||||||
The RHS of a tristate assignment can be the following
|
|
||||||
a) a node (tristate or non-tristate)
|
|
||||||
b) a constant (must be all or no z's)
|
|
||||||
x'b0, x'bz, x{x'bz}, x{x'b0} -> are allowed
|
|
||||||
c) a conditional whose possible values are (a) or (b)
|
|
||||||
|
|
||||||
2) One can lose that fact that a node is a tristate node. This happens
|
|
||||||
if a tristate node is assigned to a 'standard' node, or is used on
|
|
||||||
RHS of a conditional. The following infer tristate signals:
|
|
||||||
a) inout <SIGNAL>
|
|
||||||
b) tri <SIGNAL>
|
|
||||||
c) assigning to 'Z' (maybe through a conditional)
|
|
||||||
Note: tristate-ness of an output port determined only by
|
|
||||||
statements in the module (not the instances it calls)
|
|
||||||
|
|
||||||
4) Tristate variables can't be multidimensional arrays
|
|
||||||
5) Only check tristate contention between modules (not within!)
|
|
||||||
6) Only simple compares with 'Z' are allowed (===)
|
|
||||||
|
|
||||||
|
|||||||
+1183
-324
File diff suppressed because it is too large
Load Diff
+66
-8
@@ -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
|
# main
|
||||||
@@ -79,27 +92,72 @@ sub diff_file {
|
|||||||
my $a = shift;
|
my $a = shift;
|
||||||
my $b = shift;
|
my $b = shift;
|
||||||
# Compare the two tree files
|
# Compare the two tree files
|
||||||
my $tmp_a = "/tmp/$$.a";
|
(my $short_a = $a) =~ s/[^a-zA-Z0-9.]+/_/g;
|
||||||
my $tmp_b = "/tmp/$$.b";
|
(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);
|
my $vera = version_from($a);
|
||||||
filter ($b, $tmp_b);
|
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");
|
system("diff -u $tmp_a $tmp_b");
|
||||||
unlink $tmp_a;
|
unlink $tmp_a;
|
||||||
unlink $tmp_b;
|
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 {
|
sub filter {
|
||||||
my $fn1 = shift;
|
my $fn1 = shift;
|
||||||
my $fn2 = shift;
|
my $fn2 = shift;
|
||||||
|
my $verCvt = shift;
|
||||||
# Remove hex numbers before diffing
|
# Remove hex numbers before diffing
|
||||||
my $f1 = IO::File->new ($fn1) or die "%Error: $! $fn1,";
|
my $f1 = IO::File->new ($fn1) or die "%Error: $! $fn1,";
|
||||||
my $f2 = IO::File->new ($fn2,"w") or die "%Error: $! $fn2,";
|
my $f2 = IO::File->new ($fn2,"w") or die "%Error: $! $fn2,";
|
||||||
while (defined (my $line=$f1->getline())) {
|
while (defined (my $line=$f1->getline())) {
|
||||||
|
same_line:
|
||||||
next if $line =~ / This=/;
|
next if $line =~ / This=/;
|
||||||
$line =~ s/0x[a-f0-9]+/0x/g;
|
$line =~ s/0x[a-f0-9]+/0x/g;
|
||||||
$line =~ s/<e[0-9]+\#?>/<e>/g;
|
$line =~ s/<e[0-9]+\#?>/<e>/g;
|
||||||
$line =~ s/{\d+}/{}/g if !$Opt_Lineno;
|
$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;
|
print $f2 $line;
|
||||||
}
|
}
|
||||||
$f1->close;
|
$f1->close;
|
||||||
@@ -109,7 +167,7 @@ sub filter {
|
|||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
|
|
||||||
sub usage {
|
sub usage {
|
||||||
pod2usage(-verbose=>2, -exitval => 2);
|
pod2usage(-verbose=>2, -exitval=>2, -output=>\*STDOUT);
|
||||||
exit (1);
|
exit (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -177,7 +235,7 @@ Do not show differences in line numbering.
|
|||||||
|
|
||||||
The latest version is available from L<http://www.veripool.org/verilator>.
|
The latest version is available from L<http://www.veripool.org/verilator>.
|
||||||
|
|
||||||
Copyright 2005-2010 by Wilson Snyder. This package is free software; you can
|
Copyright 2005-2014 by Wilson Snyder. This package is free software; you can
|
||||||
redistribute it and/or modify it under the terms of either the GNU Lesser
|
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.
|
General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||||
|
|
||||||
@@ -193,5 +251,5 @@ C<verilator>
|
|||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
### Local Variables:
|
### 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:
|
### End:
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ eval 'exec perl -wS $0 ${1+"$@"}'
|
|||||||
if 0;
|
if 0;
|
||||||
# DESCRIPTION: Print include statements for each ARGV
|
# DESCRIPTION: Print include statements for each ARGV
|
||||||
#
|
#
|
||||||
# Copyright 2003-2010 by Wilson Snyder. This package is free software; you can
|
# Copyright 2003-2014 by Wilson Snyder. This package is free software; you can
|
||||||
# redistribute it and/or modify it under the terms of either the GNU Lesser
|
# 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.
|
# General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|||||||
+17
-3
@@ -39,7 +39,7 @@ profcfunc($Opt_File);
|
|||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
|
|
||||||
sub usage {
|
sub usage {
|
||||||
pod2usage(-verbose=>2, -exitval => 2);
|
pod2usage(-verbose=>2, -exitval=>2, -output=>\*STDOUT);
|
||||||
exit (1);
|
exit (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,6 +118,18 @@ sub profcfunc {
|
|||||||
$groups{type}{"Common code under $design"} += $pct;
|
$groups{type}{"Common code under $design"} += $pct;
|
||||||
$groups{design}{$design} += $pct;
|
$groups{design}{$design} += $pct;
|
||||||
$groups{module}{$design." common code"} += $pct;
|
$groups{module}{$design." common code"} += $pct;
|
||||||
|
} elsif ($func =~ /^VL_[A-Z0-9_]+/
|
||||||
|
|| $func =~ /^_?vl_[a-zA-Z0-9_]+/
|
||||||
|
|| $func =~ /^verilated/i) {
|
||||||
|
$vfunc = sprintf("VLib %s", $func);
|
||||||
|
$groups{type}{'VLib'} += $pct;
|
||||||
|
$groups{design}{'VLib'} += $pct;
|
||||||
|
$groups{module}{'VLib'} += $pct;
|
||||||
|
} elsif ($func =~ /^_mcount_private/) {
|
||||||
|
$vfunc = sprintf("Prof %s", $func);
|
||||||
|
$groups{type}{'Prof'} += $pct;
|
||||||
|
$groups{design}{'Prof'} += $pct;
|
||||||
|
$groups{module}{'Prof'} += $pct;
|
||||||
} else {
|
} else {
|
||||||
$vfunc = sprintf("C++ %s", $func);
|
$vfunc = sprintf("C++ %s", $func);
|
||||||
$groups{type}{'C++'} += $pct;
|
$groups{type}{'C++'} += $pct;
|
||||||
@@ -129,7 +141,7 @@ sub profcfunc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
foreach my $type qw(type design module) {
|
foreach my $type (qw(type design module)) {
|
||||||
my $missing = 100;
|
my $missing = 100;
|
||||||
foreach (sort (keys %{$groups{$type}})) {
|
foreach (sort (keys %{$groups{$type}})) {
|
||||||
$missing -= $groups{$type}{$_};
|
$missing -= $groups{$type}{$_};
|
||||||
@@ -150,8 +162,10 @@ sub profcfunc {
|
|||||||
print("Verilog code profile:\n");
|
print("Verilog code profile:\n");
|
||||||
print(" These are split into three categories:\n");
|
print(" These are split into three categories:\n");
|
||||||
print(" C++: Time in non-Verilated C++ code\n");
|
print(" C++: Time in non-Verilated C++ code\n");
|
||||||
|
print(" Prof: Time in profile overhead\n");
|
||||||
print(" VBlock: Time attributable to a block in a Verilog file and line\n");
|
print(" VBlock: Time attributable to a block in a Verilog file and line\n");
|
||||||
print(" VCommon: Time in a Verilated module, due to all parts of the design\n");
|
print(" VCommon: Time in a Verilated module, due to all parts of the design\n");
|
||||||
|
print(" VLib: Time in Verilated common libraries, called by the Verilated code\n");
|
||||||
print("\n");
|
print("\n");
|
||||||
|
|
||||||
print(" % cumulative self \n");
|
print(" % cumulative self \n");
|
||||||
@@ -208,7 +222,7 @@ Displays this message and program version and exits.
|
|||||||
|
|
||||||
The latest version is available from L<http://www.veripool.org/>.
|
The latest version is available from L<http://www.veripool.org/>.
|
||||||
|
|
||||||
Copyright 2007-2010 by Wilson Snyder. Verilator is free software; you can
|
Copyright 2007-2014 by Wilson Snyder. Verilator is free software; you can
|
||||||
redistribute it and/or modify it under the terms of either the GNU Lesser
|
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.
|
General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||||
|
|
||||||
|
|||||||
+105
-31
@@ -1,35 +1,85 @@
|
|||||||
dnl DESCRIPTION: Process this file with autoconf to produce a configure script.
|
# DESCRIPTION: Process this file with autoconf to produce a configure script.
|
||||||
dnl
|
#
|
||||||
dnl Copyright 2003-2010 by Wilson Snyder. Verilator is free software; you can
|
# Copyright 2003-2014 by Wilson Snyder. Verilator is free software; you can
|
||||||
dnl redistribute it and/or modify it under the terms of either the GNU Lesser
|
# redistribute it and/or modify it under the terms of either the GNU Lesser
|
||||||
dnl General Public License Version 3 or the Perl Artistic License Version 2.0.
|
# General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||||
|
|
||||||
AC_INIT(src/Verilator.cpp)
|
#AC_INIT([Verilator],[#.### YYYY-MM-DD])
|
||||||
|
#AC_INIT([Verilator],[#.### devel])
|
||||||
|
AC_INIT([Verilator],[3.866 2014-11-15])
|
||||||
AC_CONFIG_HEADER(src/config_build.h)
|
AC_CONFIG_HEADER(src/config_build.h)
|
||||||
|
AC_CONFIG_FILES(Makefile src/Makefile src/Makefile_obj include/verilated.mk include/verilated_config.h)
|
||||||
|
|
||||||
dnl Special Substitutions
|
AC_MSG_RESULT([configuring for $PACKAGE_STRING])
|
||||||
AC_ARG_ENABLE(defenv,
|
|
||||||
[AS_HELP_STRING([--disable-defenv], [disable hardcoded default environment variables])],
|
# Special Substitutions - CFG_WITH_DEFENV
|
||||||
CFG_WITH_DEFENV=$enableval,
|
AC_MSG_CHECKING(whether to disable hardcoded paths)
|
||||||
CFG_WITH_DEFENV=yes)
|
AC_ARG_ENABLE([defenv],
|
||||||
|
[AS_HELP_STRING([--disable-defenv],
|
||||||
|
[disable using some hardcoded data paths extracted from some default environment variables (the default is to use hardcoded paths)])],
|
||||||
|
[case "${enableval}" in
|
||||||
|
yes) CFG_WITH_DEFENV=yes ;;
|
||||||
|
no) CFG_WITH_DEFENV=no ;;
|
||||||
|
*) AC_MSG_ERROR([bad value ${enableval} for --disable-defenv]) ;;
|
||||||
|
esac],
|
||||||
|
CFG_WITH_DEFENV=yes)
|
||||||
AC_SUBST(CFG_WITH_DEFENV)
|
AC_SUBST(CFG_WITH_DEFENV)
|
||||||
|
AC_MSG_RESULT($CFG_WITH_DEFENV)
|
||||||
|
|
||||||
dnl Compiler flags
|
# Special Substitutions - CFG_WITH_CCWARN
|
||||||
|
AC_MSG_CHECKING(whether to show and stop on compilation warnings)
|
||||||
|
AC_ARG_ENABLE([ccwarn],
|
||||||
|
[AS_HELP_STRING([--enable-ccwarn],
|
||||||
|
[enable showing and stopping on compilation warnings])],
|
||||||
|
[case "${enableval}" in
|
||||||
|
yes) CFG_WITH_CCWARN=yes ;;
|
||||||
|
no) CFG_WITH_CCWARN=no ;;
|
||||||
|
*) AC_MSG_ERROR([bad value ${enableval} for --enable-ccwarn]) ;;
|
||||||
|
esac],
|
||||||
|
[case "x${VERILATOR_AUTHOR_SITE}" in
|
||||||
|
x) CFG_WITH_CCWARN=no ;;
|
||||||
|
*) CFG_WITH_CCWARN=yes ;;
|
||||||
|
esac]
|
||||||
|
)
|
||||||
|
AC_SUBST(CFG_WITH_CCWARN)
|
||||||
|
AC_MSG_RESULT($CFG_WITH_CCWARN)
|
||||||
|
|
||||||
|
# Special Substitutions - CFG_WITH_LONGTESTS
|
||||||
|
AC_MSG_CHECKING(whether to run long tests)
|
||||||
|
AC_ARG_ENABLE([longtests],
|
||||||
|
[AS_HELP_STRING([--enable-longtests],
|
||||||
|
[enable running long developer tests])],
|
||||||
|
[case "${enableval}" in
|
||||||
|
yes) CFG_WITH_LONGTESTS=yes ;;
|
||||||
|
no) CFG_WITH_LONGTESTS=no ;;
|
||||||
|
*) AC_MSG_ERROR([bad value ${enableval} for --enable-longtests]) ;;
|
||||||
|
esac],
|
||||||
|
[case "x${VERILATOR_AUTHOR_SITE}" in
|
||||||
|
x) CFG_WITH_LONGTESTS=no ;;
|
||||||
|
*) CFG_WITH_LONGTESTS=yes ;;
|
||||||
|
esac]
|
||||||
|
)
|
||||||
|
AC_SUBST(CFG_WITH_LONGTESTS)
|
||||||
|
AC_MSG_RESULT($CFG_WITH_LONGTESTS)
|
||||||
|
|
||||||
|
# Compiler flags
|
||||||
CFLAGS=-I${includedir}
|
CFLAGS=-I${includedir}
|
||||||
CPPFLAGS=-I${includedir}
|
CPPFLAGS=-I${includedir}
|
||||||
CXXFLAGS=-I${includedir}
|
CXXFLAGS=-I${includedir}
|
||||||
LDFLAGS=-L${libdir}
|
LDFLAGS=-L${libdir}
|
||||||
|
|
||||||
dnl Checks for programs.
|
# Checks for programs.
|
||||||
AC_PROG_CC
|
AC_PROG_CC
|
||||||
AC_PROG_CXX
|
AC_PROG_CXX
|
||||||
AC_PROG_INSTALL
|
AC_PROG_INSTALL
|
||||||
|
|
||||||
AC_LANG_PUSH(C++)
|
AC_LANG_PUSH(C++)
|
||||||
AC_MSG_CHECKING([that C++ compiler can compile simple program])
|
AC_MSG_CHECKING([that C++ compiler can compile simple program])
|
||||||
AC_TRY_RUN([int main() { return 0; }],
|
AC_RUN_IFELSE(
|
||||||
|
[AC_LANG_SOURCE([int main() { return 0; }])],
|
||||||
AC_MSG_RESULT(yes),
|
AC_MSG_RESULT(yes),
|
||||||
AC_MSG_RESULT(no);AC_MSG_ERROR([a working C++ compiler is required]))
|
AC_MSG_RESULT(no);AC_MSG_ERROR([a working C++ compiler is required]),
|
||||||
|
AC_MSG_RESULT(yes))
|
||||||
|
|
||||||
AC_PATH_PROG(PERL,perl)
|
AC_PATH_PROG(PERL,perl)
|
||||||
if test "x$PERL" = "x" ; then
|
if test "x$PERL" = "x" ; then
|
||||||
@@ -44,33 +94,57 @@ if test "x$YACC" = "x" ; then
|
|||||||
AC_MSG_ERROR([Cannot find "bison" in your PATH, please install it])
|
AC_MSG_ERROR([Cannot find "bison" in your PATH, please install it])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
dnl Checks for libraries.
|
# Checks for libraries.
|
||||||
|
|
||||||
dnl Checks for header files.
|
# Checks for typedefs, structures
|
||||||
AC_HEADER_STDC
|
|
||||||
AC_HEADER_SYS_WAIT
|
|
||||||
AC_CHECK_HEADERS(fcntl.h unistd.h inttypes.h sys/file.h sys/time.h sys/un.h math.h stdint.h mingw/stdint.h)
|
|
||||||
|
|
||||||
dnl Checks for typedefs, structures
|
|
||||||
AC_CHECK_TYPE(size_t,unsigned int)
|
AC_CHECK_TYPE(size_t,unsigned int)
|
||||||
AC_CHECK_TYPE(uint_t,unsigned int)
|
|
||||||
AC_CHECK_TYPE(ulong_t,unsigned long)
|
|
||||||
AC_TYPE_SIZE_T
|
AC_TYPE_SIZE_T
|
||||||
AC_STRUCT_TM
|
|
||||||
|
|
||||||
dnl Checks for compiler characteristics.
|
# Checks for compiler characteristics.
|
||||||
AC_C_INLINE
|
AC_C_INLINE
|
||||||
|
|
||||||
dnl Checks for library functions.
|
AC_DEFUN([_MY_CXX_CHECK_OPT],
|
||||||
|
[# _MY_CXX_CHECK_OPT(flag) -- Check if compiler supports specific options
|
||||||
|
ACO_SAVE_CXXFLAGS="$CXXFLAGS"
|
||||||
|
# -Werror needed otherwise unknown -Wno-div-by-zero won't report problems
|
||||||
|
CXXFLAGS="$CXXFLAGS $1 -Werror"
|
||||||
|
AC_MSG_CHECKING([whether $CXX accepts $1])
|
||||||
|
AC_COMPILE_IFELSE(
|
||||||
|
[AC_LANG_PROGRAM([],[])],
|
||||||
|
[_my_result=yes],
|
||||||
|
[_my_result=no])
|
||||||
|
AC_MSG_RESULT($_my_result)
|
||||||
|
if test "$_my_result" = "yes" ; then
|
||||||
|
CFG_CXXFLAGS_NO_UNUSED="$CFG_CXXFLAGS_NO_UNUSED $1"
|
||||||
|
fi
|
||||||
|
CXXFLAGS="$ACO_SAVE_CXXFLAGS"
|
||||||
|
])# _MY_CXX_CHECK_OPT
|
||||||
|
|
||||||
dnl Checks for system services
|
# For example, -Wno-div-by-zero isn't in 4.1.2
|
||||||
|
_MY_CXX_CHECK_OPT(-Wno-char-subscripts)
|
||||||
|
_MY_CXX_CHECK_OPT(-Wno-parentheses-equality)
|
||||||
|
# Random code often does / 0. Unfortunately VL_DIV_I(0,0) will warn
|
||||||
|
# without this flag, even though there's a conditional to prevent the divide.
|
||||||
|
# We still don't add no-div-by-zero as it throws message to stdout, though doesn't die.
|
||||||
|
#_MY_CXX_CHECK_OPT(-Wno-div-by-zero)
|
||||||
|
_MY_CXX_CHECK_OPT(-Wno-sign-compare)
|
||||||
|
_MY_CXX_CHECK_OPT(-Wno-uninitialized)
|
||||||
|
_MY_CXX_CHECK_OPT(-Wno-unused-but-set-variable)
|
||||||
|
_MY_CXX_CHECK_OPT(-Wno-unused-parameter)
|
||||||
|
_MY_CXX_CHECK_OPT(-Wno-unused-variable)
|
||||||
|
_MY_CXX_CHECK_OPT(-fbracket-depth=4096)
|
||||||
|
AC_SUBST(CFG_CXXFLAGS_NO_UNUSED)
|
||||||
|
|
||||||
dnl Other install directories
|
# Checks for library functions.
|
||||||
|
|
||||||
|
# Checks for system services
|
||||||
|
|
||||||
|
# Other install directories
|
||||||
pkgdatadir=${datadir}/verilator
|
pkgdatadir=${datadir}/verilator
|
||||||
AC_SUBST(pkgdatadir)
|
AC_SUBST(pkgdatadir)
|
||||||
|
|
||||||
AC_OUTPUT(Makefile src/Makefile src/Makefile_obj include/verilated.mk)
|
AC_OUTPUT
|
||||||
|
|
||||||
AC_MSG_RESULT([])
|
AC_MSG_RESULT([])
|
||||||
AC_MSG_RESULT([Now type 'gmake'])
|
AC_MSG_RESULT([Now type 'make' (or sometimes 'gmake') to build Verilator.])
|
||||||
AC_MSG_RESULT([])
|
AC_MSG_RESULT([])
|
||||||
|
|||||||
@@ -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.mk
|
||||||
|
verilated_config.h
|
||||||
|
|||||||
+238
-43
@@ -1,7 +1,7 @@
|
|||||||
// -*- C++ -*-
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2014 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License.
|
// Lesser General Public License Version 3 or the Perl Artistic License.
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
@@ -26,21 +26,21 @@
|
|||||||
#define _VERILATED_CPP_
|
#define _VERILATED_CPP_
|
||||||
#include "verilated_imp.h"
|
#include "verilated_imp.h"
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#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
|
// Global variables
|
||||||
|
|
||||||
int Verilated::s_randReset = 0;
|
// Slow path variables
|
||||||
int Verilated::s_debug = 1;
|
VerilatedVoidCb Verilated::s_flushCb = NULL;
|
||||||
bool Verilated::s_calcUnusedSigs = false;
|
|
||||||
bool Verilated::s_gotFinish = false;
|
// Keep below together in one cache line
|
||||||
bool Verilated::s_assertOn = true;
|
Verilated::Serialized Verilated::s_s;
|
||||||
VL_THREAD const VerilatedScope* Verilated::t_dpiScopep = NULL;
|
VL_THREAD const VerilatedScope* Verilated::t_dpiScopep = NULL;
|
||||||
VL_THREAD const char* Verilated::t_dpiFilename = "";
|
VL_THREAD const char* Verilated::t_dpiFilename = "";
|
||||||
VL_THREAD int Verilated::t_dpiLineno = 0;
|
VL_THREAD int Verilated::t_dpiLineno = 0;
|
||||||
|
struct Verilated::CommandArgValues Verilated::s_args = {0, NULL};
|
||||||
|
|
||||||
VerilatedImp VerilatedImp::s_s;
|
VerilatedImp VerilatedImp::s_s;
|
||||||
|
|
||||||
@@ -53,6 +53,7 @@ void vl_finish (const char* filename, int linenum, const char* hier) {
|
|||||||
VL_PRINTF("- %s:%d: Verilog $finish\n", filename, linenum);
|
VL_PRINTF("- %s:%d: Verilog $finish\n", filename, linenum);
|
||||||
if (Verilated::gotFinish()) {
|
if (Verilated::gotFinish()) {
|
||||||
VL_PRINTF("- %s:%d: Second verilog $finish, exiting\n", filename, linenum);
|
VL_PRINTF("- %s:%d: Second verilog $finish, exiting\n", filename, linenum);
|
||||||
|
Verilated::flushCall();
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
Verilated::gotFinish(true);
|
Verilated::gotFinish(true);
|
||||||
@@ -62,6 +63,7 @@ void vl_finish (const char* filename, int linenum, const char* hier) {
|
|||||||
#ifndef VL_USER_STOP // Define this to override this function
|
#ifndef VL_USER_STOP // Define this to override this function
|
||||||
void vl_stop (const char* filename, int linenum, const char* hier) {
|
void vl_stop (const char* filename, int linenum, const char* hier) {
|
||||||
Verilated::gotFinish(true);
|
Verilated::gotFinish(true);
|
||||||
|
Verilated::flushCall();
|
||||||
vl_fatal (filename,linenum,hier,"Verilog $stop");
|
vl_fatal (filename,linenum,hier,"Verilog $stop");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -71,10 +73,26 @@ void vl_fatal (const char* filename, int linenum, const char* hier, const char*
|
|||||||
if (0 && hier) {}
|
if (0 && hier) {}
|
||||||
Verilated::gotFinish(true);
|
Verilated::gotFinish(true);
|
||||||
VL_PRINTF("%%Error: %s:%d: %s\n", filename, linenum, msg);
|
VL_PRINTF("%%Error: %s:%d: %s\n", filename, linenum, msg);
|
||||||
|
Verilated::flushCall();
|
||||||
|
|
||||||
|
VL_PRINTF("Aborting...\n");
|
||||||
|
Verilated::flushCall(); // Second flush in case VL_PRINTF does something needing a flush
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
#endif
|
#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.
|
// Random reset -- Only called at init time, so don't inline.
|
||||||
|
|
||||||
@@ -192,7 +210,8 @@ WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, WDataInP lwp, WDataInP rwp, boo
|
|||||||
vluint32_t vn[VL_MULS_MAX_WORDS+1]; // v normalized
|
vluint32_t vn[VL_MULS_MAX_WORDS+1]; // v normalized
|
||||||
|
|
||||||
// Zero for ease of debugging and to save having to zero for shifts
|
// Zero for ease of debugging and to save having to zero for shifts
|
||||||
for (int i=0; i<words; i++) { un[i]=vn[i]=0; }
|
// Note +1 as loop will use extra word
|
||||||
|
for (int i=0; i<words+1; i++) { un[i]=vn[i]=0; }
|
||||||
|
|
||||||
// Algorithm requires divisor MSB to be set
|
// Algorithm requires divisor MSB to be set
|
||||||
// Copy and shift to normalize divisor so MSB of vn[vw-1] is set
|
// Copy and shift to normalize divisor so MSB of vn[vw-1] is set
|
||||||
@@ -278,12 +297,15 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
|
|||||||
// Note also assumes variables < 64 are not wide, this assumption is
|
// Note also assumes variables < 64 are not wide, this assumption is
|
||||||
// sometimes not true in low-level routines written here in verilated.cpp
|
// sometimes not true in low-level routines written here in verilated.cpp
|
||||||
static VL_THREAD char tmp[VL_VALUE_STRING_MAX_WIDTH];
|
static VL_THREAD char tmp[VL_VALUE_STRING_MAX_WIDTH];
|
||||||
|
static VL_THREAD char tmpf[VL_VALUE_STRING_MAX_WIDTH];
|
||||||
|
const char* pctp = NULL; // Most recent %##.##g format
|
||||||
bool inPct = false;
|
bool inPct = false;
|
||||||
bool widthSet = false;
|
bool widthSet = false;
|
||||||
int width = 0;
|
int width = 0;
|
||||||
const char* pos = formatp;
|
const char* pos = formatp;
|
||||||
for (; *pos; ++pos) {
|
for (; *pos; ++pos) {
|
||||||
if (!inPct && pos[0]=='%') {
|
if (!inPct && pos[0]=='%') {
|
||||||
|
pctp = pos;
|
||||||
inPct = true;
|
inPct = true;
|
||||||
widthSet = false;
|
widthSet = false;
|
||||||
width = 0;
|
width = 0;
|
||||||
@@ -292,7 +314,7 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
|
|||||||
const char *ep = pos;
|
const char *ep = pos;
|
||||||
while (ep[0] && ep[0]!='%') ep++;
|
while (ep[0] && ep[0]!='%') ep++;
|
||||||
if (ep != pos) {
|
if (ep != pos) {
|
||||||
output += string(pos, ep-pos);
|
output.append(pos, ep-pos);
|
||||||
pos += ep-pos-1;
|
pos += ep-pos-1;
|
||||||
}
|
}
|
||||||
} else { // Format character
|
} else { // Format character
|
||||||
@@ -305,6 +327,9 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
|
|||||||
widthSet = true;
|
widthSet = true;
|
||||||
width = width*10 + (fmt - '0');
|
width = width*10 + (fmt - '0');
|
||||||
break;
|
break;
|
||||||
|
case '.':
|
||||||
|
inPct = true; // Get more digits
|
||||||
|
break;
|
||||||
case '%':
|
case '%':
|
||||||
output += '%';
|
output += '%';
|
||||||
break;
|
break;
|
||||||
@@ -318,13 +343,25 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
|
|||||||
output += cstrp;
|
output += cstrp;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
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);
|
||||||
|
output += tmp;
|
||||||
|
break;
|
||||||
|
}
|
||||||
default: {
|
default: {
|
||||||
// Deal with all read-and-print somethings
|
// Deal with all read-and-print somethings
|
||||||
const int lbits = va_arg(ap, int);
|
const int lbits = va_arg(ap, int);
|
||||||
QData ld = 0;
|
QData ld = 0;
|
||||||
|
WData qlwp[2];
|
||||||
WDataInP lwp;
|
WDataInP lwp;
|
||||||
if (lbits <= VL_QUADSIZE) {
|
if (lbits <= VL_QUADSIZE) {
|
||||||
WData qlwp[2];
|
|
||||||
ld = _VL_VA_ARG_Q(ap, lbits);
|
ld = _VL_VA_ARG_Q(ap, lbits);
|
||||||
VL_SET_WQ(qlwp,ld);
|
VL_SET_WQ(qlwp,ld);
|
||||||
lwp = qlwp;
|
lwp = qlwp;
|
||||||
@@ -351,14 +388,26 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
|
|||||||
case 'd': { // Signed decimal
|
case 'd': { // Signed decimal
|
||||||
int digits=sprintf(tmp,"%" VL_PRI64 "d",(vlsint64_t)(VL_EXTENDS_QQ(lbits,lbits,ld)));
|
int digits=sprintf(tmp,"%" VL_PRI64 "d",(vlsint64_t)(VL_EXTENDS_QQ(lbits,lbits,ld)));
|
||||||
int needmore = width-digits;
|
int needmore = width-digits;
|
||||||
if (needmore>0) output.append(needmore,' '); // Pre-pad spaces
|
if (needmore>0) {
|
||||||
|
if (pctp && pctp[0] && pctp[1]=='0') { //%0
|
||||||
|
output.append(needmore,'0'); // Pre-pad zero
|
||||||
|
} else {
|
||||||
|
output.append(needmore,' '); // Pre-pad spaces
|
||||||
|
}
|
||||||
|
}
|
||||||
output += tmp;
|
output += tmp;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'u': { // Unsigned decimal
|
case 'u': { // Unsigned decimal
|
||||||
int digits=sprintf(tmp,"%" VL_PRI64 "u",ld);
|
int digits=sprintf(tmp,"%" VL_PRI64 "u",ld);
|
||||||
int needmore = width-digits;
|
int needmore = width-digits;
|
||||||
if (needmore>0) output.append(needmore,' '); // Pre-pad spaces
|
if (needmore>0) {
|
||||||
|
if (pctp && pctp[0] && pctp[1]=='0') { //%0
|
||||||
|
output.append(needmore,'0'); // Pre-pad zero
|
||||||
|
} else {
|
||||||
|
output.append(needmore,' '); // Pre-pad spaces
|
||||||
|
}
|
||||||
|
}
|
||||||
output += tmp;
|
output += tmp;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -558,17 +607,28 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
|
|||||||
_vl_vsss_read(fp,floc,fromp, tmp, "0123456789+-xXzZ?_");
|
_vl_vsss_read(fp,floc,fromp, tmp, "0123456789+-xXzZ?_");
|
||||||
if (!tmp[0]) goto done;
|
if (!tmp[0]) goto done;
|
||||||
vlsint64_t ld;
|
vlsint64_t ld;
|
||||||
sscanf(tmp,"%" VL_PRI64 "d",&ld);
|
sscanf(tmp,"%30" VL_PRI64 "d",&ld);
|
||||||
VL_SET_WQ(owp,ld);
|
VL_SET_WQ(owp,ld);
|
||||||
break;
|
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 't': // FALLTHRU // Time
|
||||||
case 'u': { // Unsigned decimal
|
case 'u': { // Unsigned decimal
|
||||||
_vl_vsss_skipspace(fp,floc,fromp);
|
_vl_vsss_skipspace(fp,floc,fromp);
|
||||||
_vl_vsss_read(fp,floc,fromp, tmp, "0123456789+-xXzZ?_");
|
_vl_vsss_read(fp,floc,fromp, tmp, "0123456789+-xXzZ?_");
|
||||||
if (!tmp[0]) goto done;
|
if (!tmp[0]) goto done;
|
||||||
QData ld;
|
QData ld;
|
||||||
sscanf(tmp,"%" VL_PRI64 "u",&ld);
|
sscanf(tmp,"%30" VL_PRI64 "u",&ld);
|
||||||
VL_SET_WQ(owp,ld);
|
VL_SET_WQ(owp,ld);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -621,6 +681,10 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
|
|||||||
//===========================================================================
|
//===========================================================================
|
||||||
// File I/O
|
// File I/O
|
||||||
|
|
||||||
|
FILE* VL_CVT_I_FP(IData lhs) {
|
||||||
|
return VerilatedImp::fdToFp(lhs);
|
||||||
|
}
|
||||||
|
|
||||||
void _VL_VINT_TO_STRING(int obits, char* destoutp, WDataInP sourcep) {
|
void _VL_VINT_TO_STRING(int obits, char* destoutp, WDataInP sourcep) {
|
||||||
// See also VL_DATA_TO_STRING_NW
|
// See also VL_DATA_TO_STRING_NW
|
||||||
int lsb=obits-1;
|
int lsb=obits-1;
|
||||||
@@ -648,8 +712,8 @@ void _VL_STRING_TO_VINT(int obits, void* destp, int srclen, const char* srcp) {
|
|||||||
for (; i<bytes; i++) { *op++ = 0; }
|
for (; i<bytes; i++) { *op++ = 0; }
|
||||||
}
|
}
|
||||||
|
|
||||||
IData VL_FGETS_IXQ(int obits, void* destp, QData fpq) {
|
IData VL_FGETS_IXI(int obits, void* destp, IData fpi) {
|
||||||
FILE* fp = VL_CVT_Q_FP(fpq);
|
FILE* fp = VL_CVT_I_FP(fpi);
|
||||||
if (VL_UNLIKELY(!fp)) return 0;
|
if (VL_UNLIKELY(!fp)) return 0;
|
||||||
|
|
||||||
// The string needs to be padded with 0's in unused spaces in front of
|
// The string needs to be padded with 0's in unused spaces in front of
|
||||||
@@ -676,32 +740,53 @@ IData VL_FGETS_IXQ(int obits, void* destp, QData fpq) {
|
|||||||
return got;
|
return got;
|
||||||
}
|
}
|
||||||
|
|
||||||
QData VL_FOPEN_QI(QData filename, IData mode) {
|
IData VL_FOPEN_QI(QData filename, IData mode) {
|
||||||
IData fnw[2]; VL_SET_WQ(fnw, filename);
|
IData fnw[2]; VL_SET_WQ(fnw, filename);
|
||||||
return VL_FOPEN_WI(2, fnw, mode);
|
return VL_FOPEN_WI(2, fnw, mode);
|
||||||
}
|
}
|
||||||
QData VL_FOPEN_WI(int fnwords, WDataInP filenamep, IData mode) {
|
IData VL_FOPEN_WI(int fnwords, WDataInP filenamep, IData mode) {
|
||||||
char filenamez[VL_TO_STRING_MAX_WORDS*VL_WORDSIZE+1];
|
char filenamez[VL_TO_STRING_MAX_WORDS*VL_WORDSIZE+1];
|
||||||
_VL_VINT_TO_STRING(fnwords*VL_WORDSIZE, filenamez, filenamep);
|
_VL_VINT_TO_STRING(fnwords*VL_WORDSIZE, filenamez, filenamep);
|
||||||
char modez[5];
|
char modez[5];
|
||||||
_VL_VINT_TO_STRING(VL_WORDSIZE, modez, &mode);
|
_VL_VINT_TO_STRING(VL_WORDSIZE, modez, &mode);
|
||||||
return VL_CVT_FP_Q(fopen(filenamez,modez));
|
return VL_FOPEN_S(filenamez,modez);
|
||||||
|
}
|
||||||
|
IData VL_FOPEN_S(const char* filenamep, const char* modep) {
|
||||||
|
return VerilatedImp::fdNew(fopen(filenamep,modep));
|
||||||
|
}
|
||||||
|
|
||||||
|
void VL_FCLOSE_I(IData fdi) {
|
||||||
|
FILE* fp = VL_CVT_I_FP(fdi);
|
||||||
|
if (VL_UNLIKELY(!fp)) return;
|
||||||
|
fclose(fp);
|
||||||
|
VerilatedImp::fdDelete(fdi);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VL_SFORMAT_X(int obits, void* destp, const char* formatp, ...) {
|
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_list ap;
|
||||||
va_start(ap,formatp);
|
va_start(ap,formatp);
|
||||||
string output;
|
|
||||||
_vl_vsformat(output, formatp, ap);
|
_vl_vsformat(output, formatp, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
_VL_STRING_TO_VINT(obits, destp, (int)output.length(), output.c_str());
|
_VL_STRING_TO_VINT(obits, destp, (int)output.length(), output.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
string VL_SFORMATF_NX(const char* formatp, ...) {
|
void VL_SFORMAT_X(int obits_ignored, string &output, const char* formatp, ...) {
|
||||||
|
if (obits_ignored) {}
|
||||||
|
output = "";
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap,formatp);
|
||||||
|
_vl_vsformat(output, formatp, ap);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
string VL_SFORMATF_NX(const char* formatp, ...) {
|
||||||
|
VL_STATIC_OR_THREAD string output; // static only for speed
|
||||||
|
output = "";
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start(ap,formatp);
|
va_start(ap,formatp);
|
||||||
string output;
|
|
||||||
_vl_vsformat(output, formatp, ap);
|
_vl_vsformat(output, formatp, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
@@ -709,9 +794,10 @@ string VL_SFORMATF_NX(const char* formatp, ...) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void VL_WRITEF(const char* formatp, ...) {
|
void VL_WRITEF(const char* formatp, ...) {
|
||||||
|
VL_STATIC_OR_THREAD string output; // static only for speed
|
||||||
|
output = "";
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start(ap,formatp);
|
va_start(ap,formatp);
|
||||||
string output;
|
|
||||||
_vl_vsformat(output, formatp, ap);
|
_vl_vsformat(output, formatp, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
@@ -719,21 +805,22 @@ void VL_WRITEF(const char* formatp, ...) {
|
|||||||
VL_PRINTF("%s", output.c_str());
|
VL_PRINTF("%s", output.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void VL_FWRITEF(QData fpq, const char* formatp, ...) {
|
void VL_FWRITEF(IData fpi, const char* formatp, ...) {
|
||||||
FILE* fp = VL_CVT_Q_FP(fpq);
|
VL_STATIC_OR_THREAD string output; // static only for speed
|
||||||
|
output = "";
|
||||||
|
FILE* fp = VL_CVT_I_FP(fpi);
|
||||||
if (VL_UNLIKELY(!fp)) return;
|
if (VL_UNLIKELY(!fp)) return;
|
||||||
|
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start(ap,formatp);
|
va_start(ap,formatp);
|
||||||
string output;
|
|
||||||
_vl_vsformat(output, formatp, ap);
|
_vl_vsformat(output, formatp, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
fputs(output.c_str(), fp);
|
fputs(output.c_str(), fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
IData VL_FSCANF_IX(QData fpq, const char* formatp, ...) {
|
IData VL_FSCANF_IX(IData fpi, const char* formatp, ...) {
|
||||||
FILE* fp = VL_CVT_Q_FP(fpq);
|
FILE* fp = VL_CVT_I_FP(fpi);
|
||||||
if (VL_UNLIKELY(!fp)) return 0;
|
if (VL_UNLIKELY(!fp)) return 0;
|
||||||
|
|
||||||
va_list ap;
|
va_list ap;
|
||||||
@@ -826,7 +913,7 @@ void VL_READMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords,
|
|||||||
} else {
|
} else {
|
||||||
needinc = true;
|
needinc = true;
|
||||||
//printf(" Value width=%d @%x = %c\n", width, addr, c);
|
//printf(" Value width=%d @%x = %c\n", width, addr, c);
|
||||||
if (addr >= (IData)(depth+array_lsb) || addr < (IData)(array_lsb)) {
|
if (VL_UNLIKELY(addr >= (IData)(depth+array_lsb) || addr < (IData)(array_lsb))) {
|
||||||
vl_fatal (ofilenamez, linenum, "", "$readmem file address beyond bounds of array");
|
vl_fatal (ofilenamez, linenum, "", "$readmem file address beyond bounds of array");
|
||||||
} else {
|
} else {
|
||||||
int entry = addr - array_lsb;
|
int entry = addr - array_lsb;
|
||||||
@@ -854,7 +941,7 @@ void VL_READMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords,
|
|||||||
_VL_SHIFTL_INPLACE_W(width, datap, (IData)shift);
|
_VL_SHIFTL_INPLACE_W(width, datap, (IData)shift);
|
||||||
datap[0] |= value;
|
datap[0] |= value;
|
||||||
}
|
}
|
||||||
if (value>=(1<<shift)) {
|
if (VL_UNLIKELY(value>=(1<<shift))) {
|
||||||
vl_fatal (ofilenamez, linenum, "", "$readmemb (binary) file contains hex characters");
|
vl_fatal (ofilenamez, linenum, "", "$readmemb (binary) file contains hex characters");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -871,19 +958,30 @@ void VL_READMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords,
|
|||||||
|
|
||||||
// Final checks
|
// Final checks
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
if (end != VL_UL(0xffffffff) && addr != (end+1)) {
|
if (VL_UNLIKELY(end != VL_UL(0xffffffff) && addr != (end+1))) {
|
||||||
vl_fatal (ofilenamez, linenum, "", "$readmem file ended before specified ending-address");
|
vl_fatal (ofilenamez, linenum, "", "$readmem file ended before specified ending-address");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) {
|
IData VL_TESTPLUSARGS_I(const char* formatp) {
|
||||||
string match = VerilatedImp::argPlusMatch(formatp);
|
const string& match = VerilatedImp::argPlusMatch(formatp);
|
||||||
if (match == "") return 0;
|
if (match == "") return 0;
|
||||||
else return 1;
|
else return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
IData VL_VALUEPLUSARGS_IW(int rbits, const char* prefixp, char fmt, WDataOutP rwp) {
|
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);
|
const char* dp = match.c_str() + 1 /*leading + */ + strlen(prefixp);
|
||||||
if (match == "") return 0;
|
if (match == "") return 0;
|
||||||
VL_ZERO_RESET_W(rbits, rwp);
|
VL_ZERO_RESET_W(rbits, rwp);
|
||||||
@@ -892,7 +990,7 @@ IData VL_VALUEPLUSARGS_IW(int rbits, const char* prefixp, char fmt, WDataOutP rw
|
|||||||
break;
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
vlsint64_t ld;
|
vlsint64_t ld;
|
||||||
sscanf(dp,"%" VL_PRI64 "d",&ld);
|
sscanf(dp,"%30" VL_PRI64 "d",&ld);
|
||||||
VL_SET_WQ(rwp,ld);
|
VL_SET_WQ(rwp,ld);
|
||||||
break;
|
break;
|
||||||
case 'b':
|
case 'b':
|
||||||
@@ -919,9 +1017,13 @@ IData VL_VALUEPLUSARGS_IW(int rbits, const char* prefixp, char fmt, WDataOutP rw
|
|||||||
}
|
}
|
||||||
|
|
||||||
const char* vl_mc_scan_plusargs(const char* prefixp) {
|
const char* vl_mc_scan_plusargs(const char* prefixp) {
|
||||||
string match = VerilatedImp::argPlusMatch(prefixp);
|
const string& match = VerilatedImp::argPlusMatch(prefixp);
|
||||||
if (match == "") return 0;
|
static VL_THREAD char outstr[VL_VALUE_STRING_MAX_WIDTH];
|
||||||
else return match.c_str()+strlen(prefixp)+1; // +1 to skip the "+"
|
if (match == "") return NULL;
|
||||||
|
strncpy(outstr, match.c_str()+strlen(prefixp)+1, // +1 to skip the "+"
|
||||||
|
VL_VALUE_STRING_MAX_WIDTH);
|
||||||
|
outstr[VL_VALUE_STRING_MAX_WIDTH-1] = '\0';
|
||||||
|
return outstr;
|
||||||
}
|
}
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
@@ -967,14 +1069,37 @@ const char* Verilated::catName(const char* n1, const char* n2) {
|
|||||||
return strp;
|
return strp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Verilated::flushCb(VerilatedVoidCb cb) {
|
||||||
|
if (s_flushCb == cb) {} // Ok - don't duplicate
|
||||||
|
else if (!s_flushCb) { s_flushCb=cb; }
|
||||||
|
else {
|
||||||
|
// Someday we may allow multiple callbacks ala atexit(), but until then
|
||||||
|
vl_fatal("unknown",0,"", "Verilated::flushCb called twice with different callbacks");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Verilated::commandArgs(int argc, const char** argv) {
|
void Verilated::commandArgs(int argc, const char** argv) {
|
||||||
|
s_args.argc = argc;
|
||||||
|
s_args.argv = argv;
|
||||||
VerilatedImp::commandArgs(argc,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() {
|
void Verilated::scopesDump() {
|
||||||
VerilatedImp::scopesDump();
|
VerilatedImp::scopesDump();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const VerilatedScope* Verilated::scopeFind(const char* namep) {
|
||||||
|
return VerilatedImp::scopeFind(namep);
|
||||||
|
}
|
||||||
|
|
||||||
int Verilated::exportFuncNum(const char* namep) {
|
int Verilated::exportFuncNum(const char* namep) {
|
||||||
return VerilatedImp::exportFind(namep);
|
return VerilatedImp::exportFind(namep);
|
||||||
}
|
}
|
||||||
@@ -990,6 +1115,24 @@ VerilatedModule::~VerilatedModule() {
|
|||||||
if (m_namep) free((void*)m_namep); m_namep=NULL;
|
if (m_namep) free((void*)m_namep); m_namep=NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//======================================================================
|
||||||
|
// VerilatedVar:: Methods
|
||||||
|
|
||||||
|
// cppcheck-suppress unusedFunction // Used by applications
|
||||||
|
vluint32_t VerilatedVar::entSize() const {
|
||||||
|
vluint32_t size = 1;
|
||||||
|
switch (vltype()) {
|
||||||
|
case VLVT_PTR: size=sizeof(void*); break;
|
||||||
|
case VLVT_UINT8: size=sizeof(CData); break;
|
||||||
|
case VLVT_UINT16: size=sizeof(SData); break;
|
||||||
|
case VLVT_UINT32: size=sizeof(IData); break;
|
||||||
|
case VLVT_UINT64: size=sizeof(QData); break;
|
||||||
|
case VLVT_WDATA: size=VL_WORDS_I(range().elements())*sizeof(IData); break;
|
||||||
|
default: size=0; break;
|
||||||
|
}
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
//======================================================================
|
//======================================================================
|
||||||
// VerilatedScope:: Methods
|
// VerilatedScope:: Methods
|
||||||
|
|
||||||
@@ -997,12 +1140,15 @@ VerilatedScope::VerilatedScope() {
|
|||||||
m_callbacksp = NULL;
|
m_callbacksp = NULL;
|
||||||
m_namep = NULL;
|
m_namep = NULL;
|
||||||
m_funcnumMax = 0;
|
m_funcnumMax = 0;
|
||||||
|
m_symsp = NULL;
|
||||||
|
m_varsp = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
VerilatedScope::~VerilatedScope() {
|
VerilatedScope::~VerilatedScope() {
|
||||||
VerilatedImp::scopeErase(this);
|
VerilatedImp::scopeErase(this);
|
||||||
if (m_namep) { delete [] m_namep; m_namep = NULL; }
|
if (m_namep) { delete [] m_namep; m_namep = NULL; }
|
||||||
if (m_callbacksp) { delete [] m_callbacksp; m_callbacksp = NULL; }
|
if (m_callbacksp) { delete [] m_callbacksp; m_callbacksp = NULL; }
|
||||||
|
if (m_varsp) { delete m_varsp; m_varsp = NULL; }
|
||||||
m_funcnumMax = 0; // Force callback table to empty
|
m_funcnumMax = 0; // Force callback table to empty
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1027,10 +1173,10 @@ void VerilatedScope::exportInsert(int finalize, const char* namep, void* cb) {
|
|||||||
// Alternative is to dynamically stretch the array, which is more code, and slower.
|
// Alternative is to dynamically stretch the array, which is more code, and slower.
|
||||||
if (funcnum >= m_funcnumMax) { m_funcnumMax = funcnum+1; }
|
if (funcnum >= m_funcnumMax) { m_funcnumMax = funcnum+1; }
|
||||||
} else {
|
} else {
|
||||||
if (funcnum >= m_funcnumMax) {
|
if (VL_UNLIKELY(funcnum >= m_funcnumMax)) {
|
||||||
vl_fatal(__FILE__,__LINE__,"","Internal: Bad funcnum vs. pre-finalize maximum");
|
vl_fatal(__FILE__,__LINE__,"","Internal: Bad funcnum vs. pre-finalize maximum");
|
||||||
}
|
}
|
||||||
if (!m_callbacksp) { // First allocation
|
if (VL_UNLIKELY(!m_callbacksp)) { // First allocation
|
||||||
m_callbacksp = new void* [m_funcnumMax];
|
m_callbacksp = new void* [m_funcnumMax];
|
||||||
memset(m_callbacksp, 0, m_funcnumMax*sizeof(void*));
|
memset(m_callbacksp, 0, m_funcnumMax*sizeof(void*));
|
||||||
}
|
}
|
||||||
@@ -1038,6 +1184,48 @@ void VerilatedScope::exportInsert(int finalize, const char* namep, void* cb) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VerilatedScope::varInsert(int finalize, const char* namep, void* datap,
|
||||||
|
VerilatedVarType vltype, int vlflags, int dims, ...) {
|
||||||
|
// Grab dimensions
|
||||||
|
// In the future we may just create a large table at emit time and statically construct from that.
|
||||||
|
if (!finalize) return;
|
||||||
|
|
||||||
|
if (!m_varsp) m_varsp = new VerilatedVarNameMap();
|
||||||
|
VerilatedVar var (namep, datap, vltype, (VerilatedVarFlags)vlflags, dims);
|
||||||
|
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap,dims);
|
||||||
|
for (int i=0; i<dims; ++i) {
|
||||||
|
int msb = va_arg(ap,int);
|
||||||
|
int lsb = va_arg(ap,int);
|
||||||
|
if (i==0) {
|
||||||
|
var.m_range.m_left = msb;
|
||||||
|
var.m_range.m_right = lsb;
|
||||||
|
} else if (i==1) {
|
||||||
|
var.m_array.m_left = msb;
|
||||||
|
var.m_array.m_right = lsb;
|
||||||
|
} else {
|
||||||
|
// We could have a linked list of ranges, but really this whole thing needs
|
||||||
|
// to be generalized to support structs and unions, etc.
|
||||||
|
vl_fatal(__FILE__,__LINE__,"",(string("Unsupported multi-dimensional public varInsert: ")+namep).c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
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);
|
||||||
|
if (VL_LIKELY(it != m_varsp->end())) {
|
||||||
|
return &(it->second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
void* VerilatedScope::exportFindNullError(int funcnum) const {
|
void* VerilatedScope::exportFindNullError(int funcnum) const {
|
||||||
// Slowpath - Called only when find has failed
|
// Slowpath - Called only when find has failed
|
||||||
string msg = (string("Testbench C called '")
|
string msg = (string("Testbench C called '")
|
||||||
@@ -1058,10 +1246,17 @@ void* VerilatedScope::exportFindError(int funcnum) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void VerilatedScope::scopeDump() const {
|
void VerilatedScope::scopeDump() const {
|
||||||
VL_PRINTF(" SCOPE: %s\n", name());
|
VL_PRINTF(" SCOPE %p: %s\n", this, name());
|
||||||
for (int i=0; i<m_funcnumMax; i++) {
|
for (int i=0; i<m_funcnumMax; i++) {
|
||||||
if (m_callbacksp && m_callbacksp[i]) {
|
if (m_callbacksp && m_callbacksp[i]) {
|
||||||
VL_PRINTF(" DPI-EXPORT: %s\n", VerilatedImp::exportName(i));
|
VL_PRINTF(" DPI-EXPORT %p: %s\n",
|
||||||
|
m_callbacksp[i], VerilatedImp::exportName(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (VerilatedVarNameMap* varsp = this->varsp()) {
|
||||||
|
for (VerilatedVarNameMap::const_iterator it = varsp->begin();
|
||||||
|
it != varsp->end(); ++it) {
|
||||||
|
VL_PRINTF(" VAR %p: %s\n", &(it->second), it->first);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+343
-69
@@ -1,7 +1,7 @@
|
|||||||
// -*- C++ -*-
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2014 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License.
|
// Lesser General Public License Version 3 or the Perl Artistic License.
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
@@ -28,6 +28,7 @@
|
|||||||
#ifndef _VERILATED_H_
|
#ifndef _VERILATED_H_
|
||||||
#define _VERILATED_H_ 1 ///< Header Guard
|
#define _VERILATED_H_ 1 ///< Header Guard
|
||||||
|
|
||||||
|
#include "verilated_config.h"
|
||||||
#include "verilatedos.h"
|
#include "verilatedos.h"
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
@@ -35,6 +36,7 @@
|
|||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <cmath>
|
||||||
// <iostream> avoided to reduce compile time
|
// <iostream> avoided to reduce compile time
|
||||||
// <string> avoided and instead in verilated_heavy.h to reduce compile time
|
// <string> avoided and instead in verilated_heavy.h to reduce compile time
|
||||||
using namespace std;
|
using namespace std;
|
||||||
@@ -62,11 +64,37 @@ typedef vluint32_t WData; ///< Verilated pack data, >64 bits, as an array
|
|||||||
typedef const WData* WDataInP; ///< Array input to a function
|
typedef const WData* WDataInP; ///< Array input to a function
|
||||||
typedef WData* WDataOutP; ///< Array output from a function
|
typedef WData* WDataOutP; ///< Array output from a function
|
||||||
|
|
||||||
|
typedef void (*VerilatedVoidCb)(void);
|
||||||
|
|
||||||
class SpTraceVcd;
|
class SpTraceVcd;
|
||||||
class SpTraceVcdCFile;
|
class SpTraceVcdCFile;
|
||||||
|
class VerilatedVar;
|
||||||
|
class VerilatedVarNameMap;
|
||||||
class VerilatedVcd;
|
class VerilatedVcd;
|
||||||
class VerilatedVcdC;
|
class VerilatedVcdC;
|
||||||
|
|
||||||
|
enum VerilatedVarType {
|
||||||
|
VLVT_UNKNOWN=0,
|
||||||
|
VLVT_PTR, // Pointer to something
|
||||||
|
VLVT_UINT8, // AKA CData
|
||||||
|
VLVT_UINT16, // AKA SData
|
||||||
|
VLVT_UINT32, // AKA IData
|
||||||
|
VLVT_UINT64, // AKA QData
|
||||||
|
VLVT_WDATA, // AKA WData
|
||||||
|
VLVT_STRING // C++ string
|
||||||
|
};
|
||||||
|
|
||||||
|
enum VerilatedVarFlags {
|
||||||
|
VLVD_IN=1, // == vpiInput
|
||||||
|
VLVD_OUT=2, // == vpiOutput
|
||||||
|
VLVD_INOUT=3, // == vpiInOut
|
||||||
|
VLVD_NODIR=5, // == vpiNoDirection
|
||||||
|
VLVF_MASK_DIR=7, // Bit mask for above directions
|
||||||
|
// Flags
|
||||||
|
VLVF_PUB_RD=(1<<8), // Public readable
|
||||||
|
VLVF_PUB_RW=(1<<9) // Public writable
|
||||||
|
};
|
||||||
|
|
||||||
//=========================================================================
|
//=========================================================================
|
||||||
/// Base class for all Verilated module classes
|
/// Base class for all Verilated module classes
|
||||||
|
|
||||||
@@ -117,7 +145,7 @@ public:
|
|||||||
# define VL_CELL(instname,type) ///< Declare a cell, ala SP_CELL
|
# define VL_CELL(instname,type) ///< Declare a cell, ala SP_CELL
|
||||||
|
|
||||||
/// Declare a module, ala SC_MODULE
|
/// Declare a module, ala SC_MODULE
|
||||||
# define VL_MODULE(modname) struct modname : public VerilatedModule
|
# define VL_MODULE(modname) class modname : public VerilatedModule
|
||||||
|
|
||||||
/// Constructor, ala SC_CTOR
|
/// Constructor, ala SC_CTOR
|
||||||
# define VL_CTOR(modname) modname(const char* __VCname="")
|
# define VL_CTOR(modname) modname(const char* __VCname="")
|
||||||
@@ -136,6 +164,9 @@ public:
|
|||||||
#ifndef VL_PRINTF
|
#ifndef VL_PRINTF
|
||||||
# define VL_PRINTF printf ///< Print ala printf; may redefine if desired
|
# define VL_PRINTF printf ///< Print ala printf; may redefine if desired
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef VL_VPRINTF
|
||||||
|
# define VL_VPRINTF vprintf ///< Print ala vprintf; may redefine if desired
|
||||||
|
#endif
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
/// Verilator symbol table base class
|
/// Verilator symbol table base class
|
||||||
@@ -149,19 +180,25 @@ class VerilatedSyms {
|
|||||||
|
|
||||||
class VerilatedScope {
|
class VerilatedScope {
|
||||||
// Fastpath:
|
// Fastpath:
|
||||||
VerilatedSyms* m_symsp; ///< Symbol table
|
VerilatedSyms* m_symsp; ///< Symbol table
|
||||||
void** m_callbacksp; ///< Callback table pointer (Fastpath)
|
void** m_callbacksp; ///< Callback table pointer (Fastpath)
|
||||||
int m_funcnumMax; ///< Maxium function number stored (Fastpath)
|
int m_funcnumMax; ///< Maxium function number stored (Fastpath)
|
||||||
// 4 bytes padding (on -m64), for rent.
|
// 4 bytes padding (on -m64), for rent.
|
||||||
const char* m_namep; ///< Scope name (Slowpath)
|
VerilatedVarNameMap* m_varsp; ///< Variable map
|
||||||
|
const char* m_namep; ///< Scope name (Slowpath)
|
||||||
|
|
||||||
public: // But internals only - called from VerilatedModule's
|
public: // But internals only - called from VerilatedModule's
|
||||||
VerilatedScope();
|
VerilatedScope();
|
||||||
~VerilatedScope();
|
~VerilatedScope();
|
||||||
void configure(VerilatedSyms* symsp, const char* prefixp, const char* suffixp);
|
void configure(VerilatedSyms* symsp, const char* prefixp, const char* suffixp);
|
||||||
void exportInsert(int finalize, const char* namep, void* cb);
|
void exportInsert(int finalize, const char* namep, void* cb);
|
||||||
|
void varInsert(int finalize, const char* namep, void* datap,
|
||||||
|
VerilatedVarType vltype, int vlflags, int dims, ...);
|
||||||
// ACCESSORS
|
// ACCESSORS
|
||||||
const char* name() const { return m_namep; }
|
const char* name() const { return m_namep; }
|
||||||
inline VerilatedSyms* symsp() const { return m_symsp; }
|
inline VerilatedSyms* symsp() const { return m_symsp; }
|
||||||
|
VerilatedVar* varFind(const char* namep) const;
|
||||||
|
VerilatedVarNameMap* varsp() const { return m_varsp; }
|
||||||
void* exportFindError(int funcnum) const;
|
void* exportFindError(int funcnum) const;
|
||||||
void* exportFindNullError(int funcnum) const;
|
void* exportFindNullError(int funcnum) const;
|
||||||
void scopeDump() const;
|
void scopeDump() const;
|
||||||
@@ -179,19 +216,34 @@ public: // But internals only - called from VerilatedModule's
|
|||||||
//===========================================================================
|
//===========================================================================
|
||||||
/// Verilator global static information class
|
/// Verilator global static information class
|
||||||
|
|
||||||
struct Verilated {
|
class Verilated {
|
||||||
// MEMBERS
|
// 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
|
||||||
static int s_debug; ///< See accessors... only when VL_DEBUG set
|
|
||||||
static bool s_calcUnusedSigs; ///< Waves file on, need all signals calculated
|
static struct Serialized { // All these members serialized/deserialized
|
||||||
static bool s_gotFinish; ///< A $finish statement executed
|
// Slow path
|
||||||
static bool s_assertOn; ///< Assertions are enabled
|
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 VerilatedScope* t_dpiScopep; ///< DPI context scope
|
||||||
static VL_THREAD const char* t_dpiFilename; ///< DPI context filename
|
static VL_THREAD const char* t_dpiFilename; ///< DPI context filename
|
||||||
static VL_THREAD int t_dpiLineno; ///< DPI context line number
|
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:
|
public:
|
||||||
|
|
||||||
// METHODS - User called
|
// METHODS - User called
|
||||||
@@ -201,33 +253,50 @@ public:
|
|||||||
/// 0 = Set to zeros
|
/// 0 = Set to zeros
|
||||||
/// 1 = Set all bits to one
|
/// 1 = Set all bits to one
|
||||||
/// 2 = Randomize all bits
|
/// 2 = Randomize all bits
|
||||||
static void randReset(int val) { s_randReset=val; }
|
static void randReset(int val) { s_s.s_randReset=val; }
|
||||||
static int randReset() { return s_randReset; } ///< Return randReset value
|
static int randReset() { return s_s.s_randReset; } ///< Return randReset value
|
||||||
|
|
||||||
/// Enable debug of internal verilated code
|
/// 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
|
#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
|
#else
|
||||||
static inline int debug() { return 0; } ///< Constant 0 debug, so C++'s optimizer rips up
|
static inline int debug() { return 0; } ///< Constant 0 debug, so C++'s optimizer rips up
|
||||||
#endif
|
#endif
|
||||||
/// Enable calculation of unused signals
|
/// Enable calculation of unused signals
|
||||||
static void calcUnusedSigs(bool flag) { s_calcUnusedSigs=flag; }
|
static void calcUnusedSigs(bool flag) { s_s.s_calcUnusedSigs=flag; }
|
||||||
static bool calcUnusedSigs() { return s_calcUnusedSigs; } ///< Return calcUnusedSigs value
|
static bool calcUnusedSigs() { return s_s.s_calcUnusedSigs; } ///< Return calcUnusedSigs value
|
||||||
/// Did the simulation $finish?
|
/// Did the simulation $finish?
|
||||||
static void gotFinish(bool flag) { s_gotFinish=flag; }
|
static void gotFinish(bool flag) { s_s.s_gotFinish=flag; }
|
||||||
static bool gotFinish() { return s_gotFinish; } ///< Return if got a $finish
|
static bool gotFinish() { return s_s.s_gotFinish; } ///< Return if got a $finish
|
||||||
/// Allow traces to at some point be enabled (disables some optimizations)
|
/// Allow traces to at some point be enabled (disables some optimizations)
|
||||||
static void traceEverOn(bool flag) {
|
static void traceEverOn(bool flag) {
|
||||||
if (flag) { calcUnusedSigs(flag); }
|
if (flag) { calcUnusedSigs(flag); }
|
||||||
}
|
}
|
||||||
/// Enable/disable assertions
|
/// Enable/disable assertions
|
||||||
static void assertOn(bool flag) { s_assertOn=flag; }
|
static void assertOn(bool flag) { s_s.s_assertOn=flag; }
|
||||||
static bool assertOn() { return s_assertOn; }
|
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)(); }
|
||||||
|
|
||||||
/// Record command line arguments, for retrieval by $test$plusargs/$value$plusargs
|
/// Record command line arguments, for retrieval by $test$plusargs/$value$plusargs
|
||||||
static void commandArgs(int argc, const char** argv);
|
static void commandArgs(int argc, const char** argv);
|
||||||
static void commandArgs(int argc, char** argv) { commandArgs(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
|
/// For debugging, print text list of all scope names with
|
||||||
/// dpiImport/Export context. This function may change in future
|
/// dpiImport/Export context. This function may change in future
|
||||||
@@ -237,6 +306,8 @@ public:
|
|||||||
// METHODS - INTERNAL USE ONLY
|
// METHODS - INTERNAL USE ONLY
|
||||||
// Internal: Create a new module name by concatenating two strings
|
// Internal: Create a new module name by concatenating two strings
|
||||||
static const char* catName(const char* n1, const char* n2); // Returns new'ed data
|
static const char* catName(const char* n1, const char* n2); // Returns new'ed data
|
||||||
|
// Internal: Find scope
|
||||||
|
static const VerilatedScope* scopeFind(const char* namep);
|
||||||
// Internal: Get and set DPI context
|
// Internal: Get and set DPI context
|
||||||
static const VerilatedScope* dpiScope() { return t_dpiScopep; }
|
static const VerilatedScope* dpiScope() { return t_dpiScopep; }
|
||||||
static void dpiScope(const VerilatedScope* scopep) { t_dpiScopep=scopep; }
|
static void dpiScope(const VerilatedScope* scopep) { t_dpiScopep=scopep; }
|
||||||
@@ -247,6 +318,8 @@ public:
|
|||||||
static const char* dpiFilenamep() { return t_dpiFilename; }
|
static const char* dpiFilenamep() { return t_dpiFilename; }
|
||||||
static int dpiLineno() { return t_dpiLineno; }
|
static int dpiLineno() { return t_dpiLineno; }
|
||||||
static int exportFuncNum(const char* namep);
|
static int exportFuncNum(const char* namep);
|
||||||
|
static size_t serializedSize() { return sizeof(s_s); }
|
||||||
|
static void* serializedPtr() { return &s_s; }
|
||||||
};
|
};
|
||||||
|
|
||||||
//=========================================================================
|
//=========================================================================
|
||||||
@@ -277,11 +350,14 @@ extern WDataOutP VL_ZERO_RESET_W(int obits, WDataOutP outwp); ///< Zero reset a
|
|||||||
extern WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, WDataInP lwp, WDataInP rwp, bool is_modulus);
|
extern WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, WDataInP lwp, WDataInP rwp, bool is_modulus);
|
||||||
|
|
||||||
/// File I/O
|
/// File I/O
|
||||||
extern IData VL_FGETS_IXQ(int obits, void* destp, QData fpq);
|
extern IData VL_FGETS_IXI(int obits, void* destp, IData fpi);
|
||||||
|
|
||||||
extern QData VL_FOPEN_WI(int fnwords, WDataInP ofilename, IData mode);
|
extern IData VL_FOPEN_S(const char* filenamep, const char* mode);
|
||||||
extern QData VL_FOPEN_QI(QData ofilename, IData mode);
|
extern IData VL_FOPEN_WI(int fnwords, WDataInP ofilename, IData mode);
|
||||||
inline QData VL_FOPEN_II(IData ofilename, IData mode) { return VL_FOPEN_QI(ofilename,mode); }
|
extern IData VL_FOPEN_QI(QData ofilename, IData mode);
|
||||||
|
inline IData VL_FOPEN_II(IData ofilename, IData mode) { return VL_FOPEN_QI(ofilename,mode); }
|
||||||
|
|
||||||
|
extern void VL_FCLOSE_I(IData fdi);
|
||||||
|
|
||||||
extern void VL_READMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords,
|
extern void VL_READMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords,
|
||||||
WDataInP ofilename, void* memp, IData start, IData end);
|
WDataInP ofilename, void* memp, IData start, IData end);
|
||||||
@@ -292,15 +368,19 @@ inline void VL_READMEM_I(bool hex, int width, int depth, int array_lsb, int fnwo
|
|||||||
VL_READMEM_Q(hex, width,depth,array_lsb,fnwords, ofilename,memp,start,end); }
|
VL_READMEM_Q(hex, width,depth,array_lsb,fnwords, ofilename,memp,start,end); }
|
||||||
|
|
||||||
extern void VL_WRITEF(const char* formatp, ...);
|
extern void VL_WRITEF(const char* formatp, ...);
|
||||||
extern void VL_FWRITEF(QData fpq, const char* formatp, ...);
|
extern void VL_FWRITEF(IData fpi, const char* formatp, ...);
|
||||||
|
|
||||||
extern IData VL_FSCANF_IX(QData fpq, const char* formatp, ...);
|
extern IData VL_FSCANF_IX(IData fpi, const char* formatp, ...);
|
||||||
extern IData VL_SSCANF_IIX(int lbits, IData ld, const char* formatp, ...);
|
extern IData VL_SSCANF_IIX(int lbits, IData ld, const char* formatp, ...);
|
||||||
extern IData VL_SSCANF_IQX(int lbits, QData ld, const char* formatp, ...);
|
extern IData VL_SSCANF_IQX(int lbits, QData ld, const char* formatp, ...);
|
||||||
extern IData VL_SSCANF_IWX(int lbits, WDataInP lwp, const char* formatp, ...);
|
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 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_TESTPLUSARGS_I(const char* formatp);
|
||||||
extern IData VL_VALUEPLUSARGS_IW(int rbits, const char* prefixp, char fmt, WDataOutP rwp);
|
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
|
extern const char* vl_mc_scan_plusargs(const char* prefixp); // PLIish
|
||||||
@@ -320,15 +400,24 @@ extern const char* vl_mc_scan_plusargs(const char* prefixp); // PLIish
|
|||||||
#define VL_SET_QW(lwp) ( ((QData)(lwp[0])) | ((QData)(lwp[1])<<((QData)(VL_WORDSIZE)) ))
|
#define VL_SET_QW(lwp) ( ((QData)(lwp[0])) | ((QData)(lwp[1])<<((QData)(VL_WORDSIZE)) ))
|
||||||
#define _VL_SET_QII(ld,rd) ( ((QData)(ld)<<VL_ULL(32)) | (QData)(rd) )
|
#define _VL_SET_QII(ld,rd) ( ((QData)(ld)<<VL_ULL(32)) | (QData)(rd) )
|
||||||
|
|
||||||
|
/// Return FILE* from IData
|
||||||
|
extern FILE* VL_CVT_I_FP(IData lhs);
|
||||||
|
|
||||||
// Use a union to avoid cast-to-different-size warnings
|
// Use a union to avoid cast-to-different-size warnings
|
||||||
/// Return FILE* from QData
|
|
||||||
static inline FILE* VL_CVT_Q_FP(QData lhs) { union { FILE* fp; QData q; } u; u.q=lhs; return u.fp; }
|
|
||||||
/// Return void* from QData
|
/// Return void* from QData
|
||||||
static inline void* VL_CVT_Q_VP(QData lhs) { union { void* fp; QData q; } u; u.q=lhs; return u.fp; }
|
static inline void* VL_CVT_Q_VP(QData lhs) { union { void* fp; QData q; } u; u.q=lhs; return u.fp; }
|
||||||
/// Return QData from FILE*
|
|
||||||
static inline QData VL_CVT_FP_Q(FILE* fp) { union { FILE* fp; QData q; } u; u.q=0; u.fp=fp; return u.q; }
|
|
||||||
/// Return QData from void*
|
/// Return QData from void*
|
||||||
static inline QData VL_CVT_VP_Q(void* fp) { union { void* fp; QData q; } u; u.q=0; u.fp=fp; return u.q; }
|
static inline QData VL_CVT_VP_Q(void* fp) { union { void* fp; QData q; } u; u.q=0; u.fp=fp; return u.q; }
|
||||||
|
/// Return double from QData (bits, not numerically)
|
||||||
|
static inline double VL_CVT_D_Q(QData lhs) { union { double d; QData q; } u; u.q=lhs; return u.d; }
|
||||||
|
/// Return QData from double (bits, not numerically)
|
||||||
|
static inline QData VL_CVT_Q_D(double lhs) { union { double d; QData q; } u; u.d=lhs; return u.q; }
|
||||||
|
/// Return double from QData (numeric)
|
||||||
|
static inline double VL_ITOR_D_I(IData lhs) { return ((double)((vlsint32_t)(lhs))); }
|
||||||
|
/// Return QData from double (numeric)
|
||||||
|
static inline IData VL_RTOI_I_D(double lhs) { return ((vlsint32_t)(VL_TRUNC(lhs))); }
|
||||||
|
/// Return QData from double (numeric)
|
||||||
|
static inline IData VL_RTOIROUND_I_D(double lhs) { return ((vlsint32_t)(VL_ROUND(lhs))); }
|
||||||
|
|
||||||
// Sign extend such that if MSB set, we get ffff_ffff, else 0s
|
// Sign extend such that if MSB set, we get ffff_ffff, else 0s
|
||||||
// (Requires clean input)
|
// (Requires clean input)
|
||||||
@@ -347,6 +436,9 @@ void _VL_DEBUG_PRINT_W(int lbits, WDataInP iwp);
|
|||||||
//=========================================================================
|
//=========================================================================
|
||||||
// Pli macros
|
// Pli macros
|
||||||
|
|
||||||
|
#ifndef VL_TIME_PRECISION
|
||||||
|
# define VL_TIME_PRECISION -12 ///< Timescale units only for for VPI return - picoseconds
|
||||||
|
#endif
|
||||||
#ifndef VL_TIME_MULTIPLIER
|
#ifndef VL_TIME_MULTIPLIER
|
||||||
# define VL_TIME_MULTIPLIER 1
|
# define VL_TIME_MULTIPLIER 1
|
||||||
#endif
|
#endif
|
||||||
@@ -355,9 +447,11 @@ void _VL_DEBUG_PRINT_W(int lbits, WDataInP iwp);
|
|||||||
#if defined(SYSTEMC_VERSION) && (SYSTEMC_VERSION>20011000)
|
#if defined(SYSTEMC_VERSION) && (SYSTEMC_VERSION>20011000)
|
||||||
# define VL_TIME_I() ((IData)(sc_time_stamp().to_default_time_units()*VL_TIME_MULTIPLIER))
|
# define VL_TIME_I() ((IData)(sc_time_stamp().to_default_time_units()*VL_TIME_MULTIPLIER))
|
||||||
# define VL_TIME_Q() ((QData)(sc_time_stamp().to_default_time_units()*VL_TIME_MULTIPLIER))
|
# define VL_TIME_Q() ((QData)(sc_time_stamp().to_default_time_units()*VL_TIME_MULTIPLIER))
|
||||||
|
# define VL_TIME_D() ((double)(sc_time_stamp().to_default_time_units()*VL_TIME_MULTIPLIER))
|
||||||
#else
|
#else
|
||||||
# define VL_TIME_I() ((IData)(sc_time_stamp()*VL_TIME_MULTIPLIER))
|
# define VL_TIME_I() ((IData)(sc_time_stamp()*VL_TIME_MULTIPLIER))
|
||||||
# define VL_TIME_Q() ((QData)(sc_time_stamp()*VL_TIME_MULTIPLIER))
|
# define VL_TIME_Q() ((QData)(sc_time_stamp()*VL_TIME_MULTIPLIER))
|
||||||
|
# define VL_TIME_D() ((double)(sc_time_stamp()*VL_TIME_MULTIPLIER))
|
||||||
extern double sc_time_stamp();
|
extern double sc_time_stamp();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -457,6 +551,7 @@ static inline void VL_ASSIGNBIT_WO(int, int bit, WDataOutP owp, IData) {
|
|||||||
//===================================================================
|
//===================================================================
|
||||||
// SYSTEMC OPERATORS
|
// SYSTEMC OPERATORS
|
||||||
// Copying verilog format to systemc integers and bit vectors.
|
// 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_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()); }
|
#define VL_ASSIGN_QSQ(obits,vvar,svar) { (vvar) = VL_CLEAN_QQ((obits),(obits),(svar).read()); }
|
||||||
@@ -474,7 +569,21 @@ static inline void VL_ASSIGNBIT_WO(int, int bit, WDataOutP owp, IData) {
|
|||||||
owp[words-1] &= VL_MASK_I(obits); \
|
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.
|
// 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_SII(obits,svar,vvar) { (svar).write(vvar); }
|
||||||
#define VL_ASSIGN_SQQ(obits,svar,vvar) { (svar).write(vvar); }
|
#define VL_ASSIGN_SQQ(obits,svar,vvar) { (svar).write(vvar); }
|
||||||
@@ -496,6 +605,20 @@ static inline void VL_ASSIGNBIT_WO(int, int bit, WDataOutP owp, IData) {
|
|||||||
svar.write(_bvtemp); \
|
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
|
// Extending sizes
|
||||||
|
|
||||||
@@ -747,7 +870,7 @@ static inline WDataOutP VL_OR_W(int words, WDataOutP owp,WDataInP lwp,WDataInP r
|
|||||||
}
|
}
|
||||||
// EMIT_RULE: VL_CHANGEXOR: oclean=1; obits=32; lbits==rbits;
|
// EMIT_RULE: VL_CHANGEXOR: oclean=1; obits=32; lbits==rbits;
|
||||||
static inline IData VL_CHANGEXOR_W(int words, WDataInP lwp,WDataInP rwp){
|
static inline IData VL_CHANGEXOR_W(int words, WDataInP lwp,WDataInP rwp){
|
||||||
IData od;
|
IData od = 0;
|
||||||
for (int i=0; (i < words); i++) od |= (lwp[i] ^ rwp[i]);
|
for (int i=0; (i < words); i++) od |= (lwp[i] ^ rwp[i]);
|
||||||
return(od);
|
return(od);
|
||||||
}
|
}
|
||||||
@@ -898,16 +1021,13 @@ static inline WDataOutP VL_SUB_W(int words, WDataOutP owp,WDataInP lwp,WDataInP
|
|||||||
return(owp);
|
return(owp);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Optimization bug in GCC 2.96 and presumably all-pre GCC 3 versions need this workaround
|
// Optimization bug in GCC 2.96 and presumably all-pre GCC 3 versions need this workaround,
|
||||||
#if 1 //defined(__GNUC__) && __GNUC__ < 3
|
// we can't just
|
||||||
static inline IData VL_UNARYMIN_I(IData data) { return -data; }
|
//# define VL_NEGATE_I(data) (-(data))
|
||||||
static inline QData VL_UNARYMIN_Q(QData data) { return -data; }
|
static inline IData VL_NEGATE_I(IData data) { return -data; }
|
||||||
#else
|
static inline QData VL_NEGATE_Q(QData data) { return -data; }
|
||||||
# define VL_UNARYMIN_I(IData data) (-(data))
|
|
||||||
# define VL_UNARYMIN_Q(QData data) (-(data))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static inline WDataOutP VL_UNARYMIN_W(int words, WDataOutP owp,WDataInP lwp){
|
static inline WDataOutP VL_NEGATE_W(int words, WDataOutP owp,WDataInP lwp){
|
||||||
QData carry = 0;
|
QData carry = 0;
|
||||||
for (int i=0; i<words; i++) {
|
for (int i=0; i<words; i++) {
|
||||||
carry = carry + (QData)(IData)(~lwp[i]);
|
carry = carry + (QData)(IData)(~lwp[i]);
|
||||||
@@ -954,18 +1074,18 @@ static inline WDataOutP VL_MULS_WWW(int,int lbits,int, WDataOutP owp,WDataInP lw
|
|||||||
IData lneg = VL_SIGN_I(lbits,lwp[words-1]);
|
IData lneg = VL_SIGN_I(lbits,lwp[words-1]);
|
||||||
if (lneg) { // Negate lhs
|
if (lneg) { // Negate lhs
|
||||||
lwusp = lwstore;
|
lwusp = lwstore;
|
||||||
VL_UNARYMIN_W(words, lwstore, lwp);
|
VL_NEGATE_W(words, lwstore, lwp);
|
||||||
lwstore[words-1] &= VL_MASK_I(lbits); // Clean it
|
lwstore[words-1] &= VL_MASK_I(lbits); // Clean it
|
||||||
}
|
}
|
||||||
IData rneg = VL_SIGN_I(lbits,rwp[words-1]);
|
IData rneg = VL_SIGN_I(lbits,rwp[words-1]);
|
||||||
if (rneg) { // Negate rhs
|
if (rneg) { // Negate rhs
|
||||||
rwusp = rwstore;
|
rwusp = rwstore;
|
||||||
VL_UNARYMIN_W(words, rwstore, rwp);
|
VL_NEGATE_W(words, rwstore, rwp);
|
||||||
rwstore[words-1] &= VL_MASK_I(lbits); // Clean it
|
rwstore[words-1] &= VL_MASK_I(lbits); // Clean it
|
||||||
}
|
}
|
||||||
VL_MUL_W(words,owp,lwusp,rwusp);
|
VL_MUL_W(words,owp,lwusp,rwusp);
|
||||||
owp[words-1] &= VL_MASK_I(lbits); // Clean. Note it's ok for the multiply to overflow into the sign bit
|
owp[words-1] &= VL_MASK_I(lbits); // Clean. Note it's ok for the multiply to overflow into the sign bit
|
||||||
if ((lneg ^ rneg) & 1) { // Negate output (not using UNARYMIN, as owp==lwp)
|
if ((lneg ^ rneg) & 1) { // Negate output (not using NEGATE, as owp==lwp)
|
||||||
QData carry = 0;
|
QData carry = 0;
|
||||||
for (int i=0; i<words; i++) {
|
for (int i=0; i<words; i++) {
|
||||||
carry = carry + (QData)(IData)(~owp[i]);
|
carry = carry + (QData)(IData)(~owp[i]);
|
||||||
@@ -1012,12 +1132,12 @@ static inline WDataOutP VL_DIVS_WWW(int lbits, WDataOutP owp,WDataInP lwp,WDataI
|
|||||||
IData rwstore[VL_MULS_MAX_WORDS];
|
IData rwstore[VL_MULS_MAX_WORDS];
|
||||||
WDataInP ltup = lwp;
|
WDataInP ltup = lwp;
|
||||||
WDataInP rtup = rwp;
|
WDataInP rtup = rwp;
|
||||||
if (lsign) { ltup = _VL_CLEAN_INPLACE_W(lbits, VL_UNARYMIN_W(VL_WORDS_I(lbits), lwstore, lwp)); }
|
if (lsign) { ltup = _VL_CLEAN_INPLACE_W(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), lwstore, lwp)); }
|
||||||
if (rsign) { rtup = _VL_CLEAN_INPLACE_W(lbits, VL_UNARYMIN_W(VL_WORDS_I(lbits), rwstore, rwp)); }
|
if (rsign) { rtup = _VL_CLEAN_INPLACE_W(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), rwstore, rwp)); }
|
||||||
if ((lsign && !rsign) || (!lsign && rsign)) {
|
if ((lsign && !rsign) || (!lsign && rsign)) {
|
||||||
IData qNoSign[VL_MULS_MAX_WORDS];
|
IData qNoSign[VL_MULS_MAX_WORDS];
|
||||||
VL_DIV_WWW(lbits,qNoSign,ltup,rtup);
|
VL_DIV_WWW(lbits,qNoSign,ltup,rtup);
|
||||||
_VL_CLEAN_INPLACE_W(lbits, VL_UNARYMIN_W(VL_WORDS_I(lbits), owp, qNoSign));
|
_VL_CLEAN_INPLACE_W(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), owp, qNoSign));
|
||||||
return owp;
|
return owp;
|
||||||
} else {
|
} else {
|
||||||
return VL_DIV_WWW(lbits,owp,ltup,rtup);
|
return VL_DIV_WWW(lbits,owp,ltup,rtup);
|
||||||
@@ -1031,19 +1151,22 @@ static inline WDataOutP VL_MODDIVS_WWW(int lbits, WDataOutP owp,WDataInP lwp,WDa
|
|||||||
IData rwstore[VL_MULS_MAX_WORDS];
|
IData rwstore[VL_MULS_MAX_WORDS];
|
||||||
WDataInP ltup = lwp;
|
WDataInP ltup = lwp;
|
||||||
WDataInP rtup = rwp;
|
WDataInP rtup = rwp;
|
||||||
if (lsign) { ltup = _VL_CLEAN_INPLACE_W(lbits, VL_UNARYMIN_W(VL_WORDS_I(lbits), lwstore, lwp)); }
|
if (lsign) { ltup = _VL_CLEAN_INPLACE_W(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), lwstore, lwp)); }
|
||||||
if (rsign) { rtup = _VL_CLEAN_INPLACE_W(lbits, VL_UNARYMIN_W(VL_WORDS_I(lbits), rwstore, rwp)); }
|
if (rsign) { rtup = _VL_CLEAN_INPLACE_W(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), rwstore, rwp)); }
|
||||||
if (lsign) { // Only dividend sign matters for modulus
|
if (lsign) { // Only dividend sign matters for modulus
|
||||||
IData qNoSign[VL_MULS_MAX_WORDS];
|
IData qNoSign[VL_MULS_MAX_WORDS];
|
||||||
VL_MODDIV_WWW(lbits,qNoSign,ltup,rtup);
|
VL_MODDIV_WWW(lbits,qNoSign,ltup,rtup);
|
||||||
_VL_CLEAN_INPLACE_W(lbits, VL_UNARYMIN_W(VL_WORDS_I(lbits), owp, qNoSign));
|
_VL_CLEAN_INPLACE_W(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), owp, qNoSign));
|
||||||
return owp;
|
return owp;
|
||||||
} else {
|
} else {
|
||||||
return VL_MODDIV_WWW(lbits,owp,ltup,rtup);
|
return VL_MODDIV_WWW(lbits,owp,ltup,rtup);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define VL_POW_QQI(obits,lbits,rbits,lhs,rhs) VL_POW_QQQ(obits,lbits,rbits,lhs,rhs)
|
||||||
|
|
||||||
static inline IData VL_POW_III(int, int, int rbits, IData lhs, IData rhs) {
|
static inline IData VL_POW_III(int, int, int rbits, IData lhs, IData rhs) {
|
||||||
|
if (VL_UNLIKELY(rhs==0)) return 1;
|
||||||
if (VL_UNLIKELY(lhs==0)) return 0;
|
if (VL_UNLIKELY(lhs==0)) return 0;
|
||||||
IData power = lhs;
|
IData power = lhs;
|
||||||
IData out = 1;
|
IData out = 1;
|
||||||
@@ -1053,10 +1176,8 @@ static inline IData VL_POW_III(int, int, int rbits, IData lhs, IData rhs) {
|
|||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define VL_POW_QQI(obits,lbits,rbits,lhs,rhs) VL_POW_QQQ(obits,lbits,rbits,lhs,rhs)
|
|
||||||
|
|
||||||
static inline QData VL_POW_QQQ(int, int, int rbits, QData lhs, QData rhs) {
|
static inline QData VL_POW_QQQ(int, int, int rbits, QData lhs, QData rhs) {
|
||||||
|
if (VL_UNLIKELY(rhs==0)) return 1;
|
||||||
if (VL_UNLIKELY(lhs==0)) return 0;
|
if (VL_UNLIKELY(lhs==0)) return 0;
|
||||||
QData power = lhs;
|
QData power = lhs;
|
||||||
QData out = VL_ULL(1);
|
QData out = VL_ULL(1);
|
||||||
@@ -1067,6 +1188,36 @@ static inline QData VL_POW_QQQ(int, int, int rbits, QData lhs, QData rhs) {
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define VL_POWSS_QQI(obits,lbits,rbits,lhs,rhs,lsign,rsign) VL_POWSS_QQQ(obits,lbits,rbits,lhs,rhs,lsign,rsign)
|
||||||
|
|
||||||
|
static inline IData VL_POWSS_III(int obits, int, int rbits, IData lhs, IData rhs, bool lsign, bool rsign) {
|
||||||
|
if (VL_UNLIKELY(rhs==0)) return 1;
|
||||||
|
if (rsign && VL_SIGN_I(rbits, rhs)) {
|
||||||
|
if (lhs==0) return 0; // "X"
|
||||||
|
else if (lhs==1) return 1;
|
||||||
|
else if (lsign && lhs==VL_MASK_I(obits)) { //-1
|
||||||
|
if (rhs & 1) return VL_MASK_I(obits); // -1^odd=-1
|
||||||
|
else return 1; // -1^even=1
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return VL_POW_III(obits, obits, rbits, lhs, rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline QData VL_POWSS_QQQ(int obits, int, int rbits, QData lhs, QData rhs, bool lsign, bool rsign) {
|
||||||
|
if (VL_UNLIKELY(rhs==0)) return 1;
|
||||||
|
if (rsign && VL_SIGN_I(rbits, rhs)) {
|
||||||
|
if (lhs==0) return 0; // "X"
|
||||||
|
else if (lhs==1) return 1;
|
||||||
|
else if (lsign && lhs==VL_MASK_I(obits)) { //-1
|
||||||
|
if (rhs & 1) return VL_MASK_I(obits); // -1^odd=-1
|
||||||
|
else return 1; // -1^even=1
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return VL_POW_QQQ(obits, obits, rbits, lhs, rhs);
|
||||||
|
}
|
||||||
|
|
||||||
//===================================================================
|
//===================================================================
|
||||||
// Concat/replication
|
// Concat/replication
|
||||||
|
|
||||||
@@ -1207,6 +1358,120 @@ static inline WDataOutP VL_REPLICATE_WWI(int obits, int lbits, int, WDataOutP ow
|
|||||||
return(owp);
|
return(owp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Left stream operator. Output will always be clean. LHS and RHS must be clean.
|
||||||
|
// Special "fast" versions for slice sizes that are a power of 2. These use
|
||||||
|
// shifts and masks to execute faster than the slower for-loop approach where a
|
||||||
|
// subset of bits is copied in during each iteration.
|
||||||
|
static inline IData VL_STREAML_FAST_III(int, int lbits, int, IData ld, IData rd_log2) {
|
||||||
|
// Pre-shift bits in most-significant slice:
|
||||||
|
//
|
||||||
|
// If lbits is not a multiple of the slice size (i.e., lbits % rd != 0),
|
||||||
|
// then we end up with a "gap" in our reversed result. For example, if we
|
||||||
|
// have a 5-bit Verlilog signal (lbits=5) in an 8-bit C data type:
|
||||||
|
//
|
||||||
|
// ld = ---43210
|
||||||
|
//
|
||||||
|
// (where numbers are the Verilog signal bit numbers and '-' is an unused bit).
|
||||||
|
// Executing the switch statement below with a slice size of two (rd=2,
|
||||||
|
// rd_log2=1) produces:
|
||||||
|
//
|
||||||
|
// ret = 1032-400
|
||||||
|
//
|
||||||
|
// Pre-shifting the bits in the most-significant slice allows us to avoid
|
||||||
|
// this gap in the shuffled data:
|
||||||
|
//
|
||||||
|
// ld_adjusted = --4-3210
|
||||||
|
// ret = 10324---
|
||||||
|
IData ret = ld;
|
||||||
|
if (rd_log2) {
|
||||||
|
vluint32_t lbitsFloor = lbits & ~VL_MASK_I(rd_log2); // max multiple of rd <= lbits
|
||||||
|
vluint32_t lbitsRem = lbits - lbitsFloor; // number of bits in most-sig slice (MSS)
|
||||||
|
IData msbMask = VL_MASK_I(lbitsRem) << lbitsFloor; // mask to sel only bits in MSS
|
||||||
|
ret = (ret & ~msbMask) | ((ret & msbMask) << ((VL_UL(1) << rd_log2) - lbitsRem));
|
||||||
|
}
|
||||||
|
switch (rd_log2) {
|
||||||
|
case 0:
|
||||||
|
ret = ((ret >> 1) & VL_UL(0x55555555)) | ((ret & VL_UL(0x55555555)) << 1); // FALLTHRU
|
||||||
|
case 1:
|
||||||
|
ret = ((ret >> 2) & VL_UL(0x33333333)) | ((ret & VL_UL(0x33333333)) << 2); // FALLTHRU
|
||||||
|
case 2:
|
||||||
|
ret = ((ret >> 4) & VL_UL(0x0f0f0f0f)) | ((ret & VL_UL(0x0f0f0f0f)) << 4); // FALLTHRU
|
||||||
|
case 3:
|
||||||
|
ret = ((ret >> 8) & VL_UL(0x00ff00ff)) | ((ret & VL_UL(0x00ff00ff)) << 8); // FALLTHRU
|
||||||
|
case 4:
|
||||||
|
ret = ((ret >> 16) | (ret << 16));
|
||||||
|
}
|
||||||
|
return ret >> (VL_WORDSIZE - lbits);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline QData VL_STREAML_FAST_QQI(int, int lbits, int, QData ld, IData rd_log2) {
|
||||||
|
// Pre-shift bits in most-significant slice (see comment in VL_STREAML_FAST_III)
|
||||||
|
QData ret = ld;
|
||||||
|
if (rd_log2) {
|
||||||
|
vluint32_t lbitsFloor = lbits & ~VL_MASK_I(rd_log2);
|
||||||
|
vluint32_t lbitsRem = lbits - lbitsFloor;
|
||||||
|
QData msbMask = VL_MASK_Q(lbitsRem) << lbitsFloor;
|
||||||
|
ret = (ret & ~msbMask) | ((ret & msbMask) << ((VL_ULL(1) << rd_log2) - lbitsRem));
|
||||||
|
}
|
||||||
|
switch (rd_log2) {
|
||||||
|
case 0:
|
||||||
|
ret = ((ret >> 1) & VL_ULL(0x5555555555555555)) | ((ret & VL_ULL(0x5555555555555555)) << 1); // FALLTHRU
|
||||||
|
case 1:
|
||||||
|
ret = ((ret >> 2) & VL_ULL(0x3333333333333333)) | ((ret & VL_ULL(0x3333333333333333)) << 2); // FALLTHRU
|
||||||
|
case 2:
|
||||||
|
ret = ((ret >> 4) & VL_ULL(0x0f0f0f0f0f0f0f0f)) | ((ret & VL_ULL(0x0f0f0f0f0f0f0f0f)) << 4); // FALLTHRU
|
||||||
|
case 3:
|
||||||
|
ret = ((ret >> 8) & VL_ULL(0x00ff00ff00ff00ff)) | ((ret & VL_ULL(0x00ff00ff00ff00ff)) << 8); // FALLTHRU
|
||||||
|
case 4:
|
||||||
|
ret = ((ret >> 16) & VL_ULL(0x0000ffff0000ffff)) | ((ret & VL_ULL(0x0000ffff0000ffff)) << 16); // FALLTHRU
|
||||||
|
case 5:
|
||||||
|
ret = ((ret >> 32) | (ret << 32));
|
||||||
|
}
|
||||||
|
return ret >> (VL_QUADSIZE - lbits);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Regular "slow" streaming operators
|
||||||
|
static inline IData VL_STREAML_III(int, int lbits, int, IData ld, IData rd) {
|
||||||
|
IData ret = 0;
|
||||||
|
// Slice size should never exceed the lhs width
|
||||||
|
IData mask = VL_MASK_I(rd);
|
||||||
|
for (int istart=0; istart<lbits; istart+=rd) {
|
||||||
|
int ostart=lbits-rd-istart;
|
||||||
|
ostart = ostart > 0 ? ostart : 0;
|
||||||
|
ret |= ((ld >> istart) & mask) << ostart;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline QData VL_STREAML_QQI(int, int lbits, int, QData ld, IData rd) {
|
||||||
|
QData ret = 0;
|
||||||
|
// Slice size should never exceed the lhs width
|
||||||
|
QData mask = VL_MASK_Q(rd);
|
||||||
|
for (int istart=0; istart<lbits; istart+=rd) {
|
||||||
|
int ostart=lbits-rd-istart;
|
||||||
|
ostart = ostart > 0 ? ostart : 0;
|
||||||
|
ret |= ((ld >> istart) & mask) << ostart;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline WDataOutP VL_STREAML_WWI(int, int lbits, int, WDataOutP owp, WDataInP lwp, IData rd) {
|
||||||
|
VL_ZERO_RESET_W(lbits, owp);
|
||||||
|
// Slice size should never exceed the lhs width
|
||||||
|
int ssize = (rd < (IData)lbits) ? rd : ((IData)lbits);
|
||||||
|
for (int istart=0; istart<lbits; istart+=rd) {
|
||||||
|
int ostart=lbits-rd-istart;
|
||||||
|
ostart = ostart > 0 ? ostart : 0;
|
||||||
|
for (int sbit=0; sbit<ssize && sbit<lbits-istart; sbit++) {
|
||||||
|
// Extract a single bit from lwp and shift it to the correct
|
||||||
|
// location for owp.
|
||||||
|
WData bit= ((lwp[VL_BITWORD_I(istart+sbit)] >> VL_BITBIT_I(istart+sbit)) & 1) << VL_BITBIT_I(ostart+sbit);
|
||||||
|
owp[VL_BITWORD_I(ostart+sbit)] |= bit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return owp;
|
||||||
|
}
|
||||||
|
|
||||||
// Because concats are common and wide, it's valuable to always have a clean output.
|
// Because concats are common and wide, it's valuable to always have a clean output.
|
||||||
// Thus we specify inputs must be clean, so we don't need to clean the output.
|
// Thus we specify inputs must be clean, so we don't need to clean the output.
|
||||||
// Note the bit shifts are always constants, so the adds in these constify out.
|
// Note the bit shifts are always constants, so the adds in these constify out.
|
||||||
@@ -1293,7 +1558,7 @@ static inline void _VL_SHIFTL_INPLACE_W(int obits,WDataOutP iowp,IData rd/*1 or
|
|||||||
static inline WDataOutP VL_SHIFTL_WWI(int obits,int,int,WDataOutP owp,WDataInP lwp, IData rd) {
|
static inline WDataOutP VL_SHIFTL_WWI(int obits,int,int,WDataOutP owp,WDataInP lwp, IData rd) {
|
||||||
int word_shift = VL_BITWORD_I(rd);
|
int word_shift = VL_BITWORD_I(rd);
|
||||||
int bit_shift = VL_BITBIT_I(rd);
|
int bit_shift = VL_BITBIT_I(rd);
|
||||||
if ((int)rd >= obits) {
|
if (rd >= (IData)obits) { // rd may be huge with MSB set
|
||||||
for (int i=0; i < VL_WORDS_I(obits); i++) owp[i] = 0;
|
for (int i=0; i < VL_WORDS_I(obits); i++) owp[i] = 0;
|
||||||
} else if (bit_shift==0) { // Aligned word shift (<<0,<<32,<<64 etc)
|
} else if (bit_shift==0) { // Aligned word shift (<<0,<<32,<<64 etc)
|
||||||
for (int i=0; i < word_shift; i++) owp[i] = 0;
|
for (int i=0; i < word_shift; i++) owp[i] = 0;
|
||||||
@@ -1311,7 +1576,7 @@ static inline WDataOutP VL_SHIFTL_WWI(int obits,int,int,WDataOutP owp,WDataInP l
|
|||||||
static inline WDataOutP VL_SHIFTR_WWI(int obits,int,int,WDataOutP owp,WDataInP lwp, IData rd) {
|
static inline WDataOutP VL_SHIFTR_WWI(int obits,int,int,WDataOutP owp,WDataInP lwp, IData rd) {
|
||||||
int word_shift = VL_BITWORD_I(rd); // Maybe 0
|
int word_shift = VL_BITWORD_I(rd); // Maybe 0
|
||||||
int bit_shift = VL_BITBIT_I(rd);
|
int bit_shift = VL_BITBIT_I(rd);
|
||||||
if ((int)rd >= obits) {
|
if (rd >= (IData)obits) { // rd may be huge with MSB set
|
||||||
for (int i=0; i < VL_WORDS_I(obits); i++) owp[i] = 0;
|
for (int i=0; i < VL_WORDS_I(obits); i++) owp[i] = 0;
|
||||||
} else if (bit_shift==0) { // Aligned word shift (>>0,>>32,>>64 etc)
|
} else if (bit_shift==0) { // Aligned word shift (>>0,>>32,>>64 etc)
|
||||||
int copy_words = (VL_WORDS_I(obits)-word_shift);
|
int copy_words = (VL_WORDS_I(obits)-word_shift);
|
||||||
@@ -1335,29 +1600,37 @@ static inline WDataOutP VL_SHIFTR_WWI(int obits,int,int,WDataOutP owp,WDataInP l
|
|||||||
}
|
}
|
||||||
|
|
||||||
// EMIT_RULE: VL_SHIFTRS: oclean=false; lclean=clean, rclean==clean;
|
// EMIT_RULE: VL_SHIFTRS: oclean=false; lclean=clean, rclean==clean;
|
||||||
static inline IData VL_SHIFTRS_III(int obits, int, int, IData lhs, IData rhs) {
|
static inline IData VL_SHIFTRS_III(int obits, int lbits, int, IData lhs, IData rhs) {
|
||||||
// Note the C standard does not specify the >> operator as a arithmetic shift!
|
// Note the C standard does not specify the >> operator as a arithmetic shift!
|
||||||
IData sign = -(lhs >> (obits-1)); // ffff_ffff if negative
|
// IEEE says signed if output signed, but bit position from lbits;
|
||||||
IData signext = ~(VL_MASK_I(obits) >> rhs); // One with bits where we've shifted "past"
|
// must use lbits for sign; lbits might != obits,
|
||||||
|
// an EXTEND(SHIFTRS(...)) can became a SHIFTRS(...) within same 32/64 bit word length
|
||||||
|
IData sign = -(lhs >> (lbits-1)); // ffff_ffff if negative
|
||||||
|
IData signext = ~(VL_MASK_I(lbits) >> rhs); // One with bits where we've shifted "past"
|
||||||
return (lhs >> rhs) | (sign & VL_CLEAN_II(obits,obits,signext));
|
return (lhs >> rhs) | (sign & VL_CLEAN_II(obits,obits,signext));
|
||||||
}
|
}
|
||||||
static inline QData VL_SHIFTRS_QQI(int obits, int, int, QData lhs, IData rhs) {
|
static inline QData VL_SHIFTRS_QQI(int obits, int lbits, int, QData lhs, IData rhs) {
|
||||||
QData sign = -(lhs >> (obits-1));
|
QData sign = -(lhs >> (lbits-1));
|
||||||
QData signext = ~(VL_MASK_Q(obits) >> rhs);
|
QData signext = ~(VL_MASK_Q(lbits) >> rhs);
|
||||||
return (lhs >> rhs) | (sign & VL_CLEAN_QQ(obits,obits,signext));
|
return (lhs >> rhs) | (sign & VL_CLEAN_QQ(obits,obits,signext));
|
||||||
}
|
}
|
||||||
static inline WDataOutP VL_SHIFTRS_WWI(int obits,int,int,WDataOutP owp,WDataInP lwp, IData rd) {
|
static inline IData VL_SHIFTRS_IQI(int obits, int lbits, int rbits, QData lhs, IData rhs) {
|
||||||
|
return (IData)(VL_SHIFTRS_QQI(obits, lbits, rbits, lhs, rhs));
|
||||||
|
}
|
||||||
|
static inline WDataOutP VL_SHIFTRS_WWI(int obits,int lbits,int,WDataOutP owp,WDataInP lwp, IData rd) {
|
||||||
int word_shift = VL_BITWORD_I(rd);
|
int word_shift = VL_BITWORD_I(rd);
|
||||||
int bit_shift = VL_BITBIT_I(rd);
|
int bit_shift = VL_BITBIT_I(rd);
|
||||||
int lmsw = VL_WORDS_I(obits)-1;
|
int lmsw = VL_WORDS_I(obits)-1;
|
||||||
IData sign = VL_SIGNONES_I(obits,lwp[lmsw]);
|
IData sign = VL_SIGNONES_I(lbits,lwp[lmsw]);
|
||||||
if ((int)rd >= obits) {
|
if (rd >= (IData)obits) { // Shifting past end, sign in all of lbits
|
||||||
for (int i=0; i <= lmsw; i++) owp[i] = sign;
|
for (int i=0; i <= lmsw; i++) owp[i] = sign;
|
||||||
|
owp[lmsw] &= VL_MASK_I(lbits);
|
||||||
} else if (bit_shift==0) { // Aligned word shift (>>0,>>32,>>64 etc)
|
} else if (bit_shift==0) { // Aligned word shift (>>0,>>32,>>64 etc)
|
||||||
int copy_words = (VL_WORDS_I(obits)-word_shift);
|
int copy_words = (VL_WORDS_I(obits)-word_shift);
|
||||||
for (int i=0; i < copy_words; i++) owp[i] = lwp[i+word_shift];
|
for (int i=0; i < copy_words; i++) owp[i] = lwp[i+word_shift];
|
||||||
if (copy_words>=0) owp[copy_words-1] |= ~VL_MASK_I(obits) & sign;
|
if (copy_words>=0) owp[copy_words-1] |= ~VL_MASK_I(obits) & sign;
|
||||||
for (int i=copy_words; i < VL_WORDS_I(obits); i++) owp[i] = sign;
|
for (int i=copy_words; i < VL_WORDS_I(obits); i++) owp[i] = sign;
|
||||||
|
owp[lmsw] &= VL_MASK_I(lbits);
|
||||||
} else {
|
} else {
|
||||||
int loffset = rd & VL_SIZEBITS_I;
|
int loffset = rd & VL_SIZEBITS_I;
|
||||||
int nbitsonright = 32-loffset; // bits that end up in lword (know loffset!=0)
|
int nbitsonright = 32-loffset; // bits that end up in lword (know loffset!=0)
|
||||||
@@ -1372,6 +1645,7 @@ static inline WDataOutP VL_SHIFTRS_WWI(int obits,int,int,WDataOutP owp,WDataInP
|
|||||||
}
|
}
|
||||||
if (words) owp[words-1] |= sign & ~VL_MASK_I(obits-loffset);
|
if (words) owp[words-1] |= sign & ~VL_MASK_I(obits-loffset);
|
||||||
for (int i=words; i<VL_WORDS_I(obits); i++) owp[i] = sign;
|
for (int i=words; i<VL_WORDS_I(obits); i++) owp[i] = sign;
|
||||||
|
owp[lmsw] &= VL_MASK_I(lbits);
|
||||||
}
|
}
|
||||||
return(owp);
|
return(owp);
|
||||||
}
|
}
|
||||||
@@ -1387,7 +1661,7 @@ static inline WDataOutP VL_SHIFTRS_WWI(int obits,int,int,WDataOutP owp,WDataInP
|
|||||||
|
|
||||||
static inline IData VL_BITSEL_IWII(int, int lbits, int, int, WDataInP lwp, IData rd) {
|
static inline IData VL_BITSEL_IWII(int, int lbits, int, int, WDataInP lwp, IData rd) {
|
||||||
int word = VL_BITWORD_I(rd);
|
int word = VL_BITWORD_I(rd);
|
||||||
if (VL_UNLIKELY((int)rd>lbits)) {
|
if (VL_UNLIKELY(rd>(IData)lbits)) {
|
||||||
return ~0; // Spec says you can go outside the range of a array. Don't coredump if so.
|
return ~0; // Spec says you can go outside the range of a array. Don't coredump if so.
|
||||||
// We return all 1's as that's more likely to find bugs (?) than 0's.
|
// We return all 1's as that's more likely to find bugs (?) than 0's.
|
||||||
} else {
|
} else {
|
||||||
@@ -1589,6 +1863,6 @@ static inline WDataOutP VL_CONST_W_9X(int obits, WDataOutP o,
|
|||||||
|
|
||||||
#undef _END
|
#undef _END
|
||||||
|
|
||||||
// Debugging
|
//======================================================================
|
||||||
|
|
||||||
#endif /*_VERILATED_H_*/
|
#endif /*_VERILATED_H_*/
|
||||||
|
|||||||
+25
-11
@@ -2,7 +2,7 @@
|
|||||||
######################################################################
|
######################################################################
|
||||||
# DESCRIPTION: Makefile commands for all verilated target files
|
# DESCRIPTION: Makefile commands for all verilated target files
|
||||||
#
|
#
|
||||||
# Copyright 2003-2010 by Wilson Snyder. Verilator is free software; you can
|
# Copyright 2003-2014 by Wilson Snyder. Verilator is free software; you can
|
||||||
# redistribute it and/or modify it under the terms of either the GNU Lesser
|
# 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.
|
# General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||||
######################################################################
|
######################################################################
|
||||||
@@ -13,12 +13,25 @@ LINK = @CXX@
|
|||||||
AR = ar
|
AR = ar
|
||||||
RANLIB = ranlib
|
RANLIB = ranlib
|
||||||
|
|
||||||
|
CFG_WITH_CCWARN = @CFG_WITH_CCWARN@
|
||||||
|
CFG_WITH_LONGTESTS = @CFG_WITH_LONGTESTS@
|
||||||
|
|
||||||
|
# Compiler flags to use to turn off unused and generated code warnings, such as -Wno-div-by-zero
|
||||||
|
CFG_CXXFLAGS_NO_UNUSED = @CFG_CXXFLAGS_NO_UNUSED@
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
# Programs
|
# Programs
|
||||||
|
|
||||||
SP_PREPROC = sp_preproc
|
SP_PREPROC = sp_preproc
|
||||||
SP_INCLUDER = $(PERL) $(VERILATOR_ROOT)/bin/verilator_includer
|
SP_INCLUDER = $(PERL) $(VERILATOR_ROOT)/bin/verilator_includer
|
||||||
|
|
||||||
|
######################################################################
|
||||||
|
# Make checks
|
||||||
|
|
||||||
|
ifneq ($(words $(CURDIR)),1)
|
||||||
|
$(error Unsupported: GNU Make cannot build in directories containing spaces, build elsewhere: '$(CURDIR)')
|
||||||
|
endif
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
# C Preprocessor flags
|
# C Preprocessor flags
|
||||||
|
|
||||||
@@ -30,18 +43,14 @@ VK_CPPFLAGS_ALWAYS += \
|
|||||||
-DVL_PRINTF=printf \
|
-DVL_PRINTF=printf \
|
||||||
-DVM_TRACE=$(VM_TRACE) \
|
-DVM_TRACE=$(VM_TRACE) \
|
||||||
-DVM_COVERAGE=$(VM_COVERAGE) \
|
-DVM_COVERAGE=$(VM_COVERAGE) \
|
||||||
|
$(CFG_CXXFLAGS_NO_UNUSED) \
|
||||||
|
|
||||||
ifeq ($(VERILATOR_AUTHOR_SITE),1) # Local... Else don't burden users
|
ifeq ($(CFG_WITH_CCWARN),yes) # Local... Else don't burden users
|
||||||
VK_CPPFLAGS_WALL += -Wall \
|
VK_CPPFLAGS_WALL += -Wall \
|
||||||
-Wno-char-subscripts \
|
|
||||||
-Wno-sign-compare \
|
|
||||||
-Wno-unused-parameter \
|
|
||||||
-Wno-unused-variable \
|
|
||||||
-Wno-uninitialized \
|
|
||||||
-Werror
|
-Werror
|
||||||
endif
|
endif
|
||||||
|
|
||||||
CPPFLAGS += -I. $(VK_CPPFLAGS_ALWAYS) $(VK_CPPFLAGS_WALL)
|
CPPFLAGS += -I. $(VK_CPPFLAGS_WALL) $(VK_CPPFLAGS_ALWAYS)
|
||||||
|
|
||||||
VPATH += ..
|
VPATH += ..
|
||||||
VPATH += $(VERILATOR_ROOT)/include
|
VPATH += $(VERILATOR_ROOT)/include
|
||||||
@@ -84,10 +93,10 @@ VM_SUPPORT += $(VM_SUPPORT_FAST) $(VM_SUPPORT_SLOW)
|
|||||||
##### SystemC or SystemPerl builds
|
##### SystemC or SystemPerl builds
|
||||||
|
|
||||||
ifeq ($(VM_SP_OR_SC),1)
|
ifeq ($(VM_SP_OR_SC),1)
|
||||||
CPPFLAGS += $(SYSTEMC_CXX_FLAGS) -I$(SYSTEMC)/include
|
CPPFLAGS += $(SYSTEMC_CXX_FLAGS) -I$(SYSTEMC_INCLUDE)
|
||||||
LDFLAGS += $(SYSTEMC_CXX_FLAGS) -L$(SYSTEMC)/lib-$(VM_SC_TARGET_ARCH)
|
LDFLAGS += $(SYSTEMC_CXX_FLAGS) -L$(SYSTEMC_LIBDIR)
|
||||||
SC_LIBS = -lsystemc
|
SC_LIBS = -lsystemc
|
||||||
ifneq ($(wildcard $(SYSTEMC)/lib-$(VM_SC_TARGET_ARCH)/*numeric_bit*),)
|
ifneq ($(wildcard $(SYSTEMC_LIBDIR)/*numeric_bit*),)
|
||||||
# Systemc 1.2.1beta
|
# Systemc 1.2.1beta
|
||||||
SC_LIBS += -lnumeric_bit -lqt
|
SC_LIBS += -lnumeric_bit -lqt
|
||||||
endif
|
endif
|
||||||
@@ -109,6 +118,10 @@ ifeq ($(VM_SP),1)
|
|||||||
$(SP_PREPROC) -M sp_preproc.d --tree $(VM_PREFIX).sp_tree \
|
$(SP_PREPROC) -M sp_preproc.d --tree $(VM_PREFIX).sp_tree \
|
||||||
--preproc $(VK_CLASSES_SP)
|
--preproc $(VK_CLASSES_SP)
|
||||||
else
|
else
|
||||||
|
ifeq ($(VM_COVERAGE),1)
|
||||||
|
CPPFLAGS += -I$(SYSTEMPERL_INCLUDE)
|
||||||
|
VPATH += $(SYSTEMPERL_INCLUDE)
|
||||||
|
endif
|
||||||
preproc:
|
preproc:
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@@ -182,6 +195,7 @@ debug-make::
|
|||||||
@echo VM_SUPPORT_SLOW: $(VM_SUPPORT_SLOW)
|
@echo VM_SUPPORT_SLOW: $(VM_SUPPORT_SLOW)
|
||||||
@echo VM_GLOBAL_FAST: $(VM_GLOBAL_FAST)
|
@echo VM_GLOBAL_FAST: $(VM_GLOBAL_FAST)
|
||||||
@echo VM_GLOBAL_SLOW: $(VM_GLOBAL_SLOW)
|
@echo VM_GLOBAL_SLOW: $(VM_GLOBAL_SLOW)
|
||||||
|
@echo CPPFLAGS: $(CPPFLAGS)
|
||||||
@echo
|
@echo
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|||||||
+4
-9
@@ -1,11 +1,10 @@
|
|||||||
// -*- C++ -*-
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.org/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2014 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License.
|
// Lesser General Public License Version 3 or the Perl Artistic License.
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
@@ -23,15 +22,11 @@
|
|||||||
`define _VERILATED_V_ 1
|
`define _VERILATED_V_ 1
|
||||||
|
|
||||||
// Hide verilator pragmas from other tools
|
// Hide verilator pragmas from other tools
|
||||||
`ifdef verilator `else
|
`ifdef VERILATOR `else
|
||||||
`define coverage_block_off
|
`define coverage_block_off
|
||||||
`endif
|
`endif
|
||||||
|
|
||||||
// Hide file descriptor difference
|
// Hide file descriptor difference - deprecated - for older versions
|
||||||
`ifdef verilator
|
`define verilator_file_descriptor integer
|
||||||
`define verilator_file_descriptor reg [63:0]
|
|
||||||
`else
|
|
||||||
`define verilator_file_descriptor integer
|
|
||||||
`endif
|
|
||||||
|
|
||||||
`endif // guard
|
`endif // guard
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
|
//*************************************************************************
|
||||||
|
//
|
||||||
|
// Copyright 2003-2014 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-2010 by Wilson Snyder. This program is free software; you can
|
// Copyright 2009-2014 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License.
|
// Lesser General Public License Version 3 or the Perl Artistic License.
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
@@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
#define _VERILATED_DPI_CPP_
|
#define _VERILATED_DPI_CPP_
|
||||||
#include "verilatedos.h"
|
#include "verilatedos.h"
|
||||||
|
#include "verilated_dpi.h"
|
||||||
#include "verilated_imp.h"
|
#include "verilated_imp.h"
|
||||||
|
|
||||||
// On MSVC++ we need svdpi.h to declare exports, not imports
|
// On MSVC++ we need svdpi.h to declare exports, not imports
|
||||||
@@ -103,9 +104,6 @@ int svHigh(const svOpenArrayHandle h, int d) {
|
|||||||
int svIncrement(const svOpenArrayHandle h, int d) {
|
int svIncrement(const svOpenArrayHandle h, int d) {
|
||||||
_VL_SVDPI_UNIMP(); return 0;
|
_VL_SVDPI_UNIMP(); return 0;
|
||||||
}
|
}
|
||||||
int svLength(const svOpenArrayHandle h, int d) {
|
|
||||||
_VL_SVDPI_UNIMP(); return 0;
|
|
||||||
}
|
|
||||||
int svDimensions(const svOpenArrayHandle h) {
|
int svDimensions(const svOpenArrayHandle h) {
|
||||||
_VL_SVDPI_UNIMP(); return 0;
|
_VL_SVDPI_UNIMP(); return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,64 @@
|
|||||||
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
|
//*************************************************************************
|
||||||
|
//
|
||||||
|
// Copyright 2003-2014 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: Common include for all Verilated C files that use DPI
|
||||||
|
///
|
||||||
|
/// This file is included automatically by Verilator at the top of
|
||||||
|
/// all C++ files it generates where DPI is used. It contains
|
||||||
|
/// DPI interface functions required by the Verilated code.
|
||||||
|
///
|
||||||
|
/// Code available from: http://www.veripool.org/verilator
|
||||||
|
///
|
||||||
|
//*************************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef _VERILATED_DPI_H_
|
||||||
|
#define _VERILATED_DPI_H_ 1 ///< Header Guard
|
||||||
|
|
||||||
|
#include "verilated.h" // Presumed done by caller
|
||||||
|
#include "svdpi.h"
|
||||||
|
|
||||||
|
//===================================================================
|
||||||
|
// SETTING OPERATORS
|
||||||
|
|
||||||
|
/// Return svBitVecVal from WData
|
||||||
|
static inline void VL_SET_W_SVBV(int obits, WDataOutP owp, svBitVecVal* lwp) {
|
||||||
|
int words = VL_WORDS_I(obits);
|
||||||
|
for (int i=0; i<words-1; i++) owp[i]=lwp[i];
|
||||||
|
owp[words-1] = lwp[words-1] & VL_MASK_I(obits);
|
||||||
|
}
|
||||||
|
static inline void VL_SET_SVBV_W(int obits, svBitVecVal* owp, WDataInP lwp) {
|
||||||
|
int words = VL_WORDS_I(obits);
|
||||||
|
for (int i=0; i<words-1; i++) owp[i]=lwp[i];
|
||||||
|
owp[words-1] = lwp[words-1] & VL_MASK_I(obits);
|
||||||
|
}
|
||||||
|
static inline void VL_SET_W_SVLV(int obits, WDataOutP owp, svLogicVecVal* lwp) {
|
||||||
|
// Note we ignore X/Z in svLogicVecVal
|
||||||
|
int words = VL_WORDS_I(obits);
|
||||||
|
for (int i=0; i<words-1; i++) owp[i]=lwp[i].aval;
|
||||||
|
owp[words-1] = lwp[words-1].aval & VL_MASK_I(obits);
|
||||||
|
}
|
||||||
|
static inline void VL_SET_SVLV_W(int obits, svLogicVecVal* owp, WDataInP lwp) {
|
||||||
|
// Note we don't create X/Z in svLogicVecVal
|
||||||
|
int words = VL_WORDS_I(obits);
|
||||||
|
for (int i=0; i<words; i++) owp[i].bval=0;
|
||||||
|
for (int i=0; i<words-1; i++) owp[i].aval=lwp[i];
|
||||||
|
owp[words-1].aval = lwp[words-1] & VL_MASK_I(obits);
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================================
|
||||||
|
|
||||||
|
#endif // _VERILATED_DPI_H_
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
// -*- C++ -*-
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2010-2010 by Wilson Snyder. This program is free software; you can
|
// Copyright 2010-2014 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License.
|
// Lesser General Public License Version 3 or the Perl Artistic License.
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
@@ -41,11 +41,15 @@ inline string VL_CVT_PACK_STR_NQ(QData lhs) {
|
|||||||
IData lw[2]; VL_SET_WQ(lw, lhs);
|
IData lw[2]; VL_SET_WQ(lw, lhs);
|
||||||
return VL_CVT_PACK_STR_NW(2, lw);
|
return VL_CVT_PACK_STR_NW(2, lw);
|
||||||
}
|
}
|
||||||
|
inline string VL_CVT_PACK_STR_NQ(string lhs) {
|
||||||
|
return lhs;
|
||||||
|
}
|
||||||
inline string VL_CVT_PACK_STR_NI(IData lhs) {
|
inline string VL_CVT_PACK_STR_NI(IData lhs) {
|
||||||
IData lw[1]; lw[0] = lhs;
|
IData lw[1]; lw[0] = lhs;
|
||||||
return VL_CVT_PACK_STR_NW(1, lw);
|
return VL_CVT_PACK_STR_NW(1, lw);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern void VL_SFORMAT_X(int obits_ignored, string &output, const char* formatp, ...);
|
||||||
extern string VL_SFORMATF_NX(const char* formatp, ...);
|
extern string VL_SFORMATF_NX(const char* formatp, ...);
|
||||||
|
|
||||||
#endif // Guard
|
#endif // Guard
|
||||||
|
|||||||
+74
-14
@@ -1,7 +1,7 @@
|
|||||||
// -*- C++ -*-
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2009-2010 by Wilson Snyder. This program is free software; you can
|
// Copyright 2009-2014 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License.
|
// Lesser General Public License Version 3 or the Perl Artistic License.
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
@@ -31,9 +31,11 @@
|
|||||||
#include "verilatedos.h"
|
#include "verilatedos.h"
|
||||||
#include "verilated.h"
|
#include "verilated.h"
|
||||||
#include "verilated_heavy.h"
|
#include "verilated_heavy.h"
|
||||||
|
#include "verilated_syms.h"
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <deque>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
class VerilatedScope;
|
class VerilatedScope;
|
||||||
@@ -41,13 +43,6 @@ class VerilatedScope;
|
|||||||
//======================================================================
|
//======================================================================
|
||||||
// Types
|
// Types
|
||||||
|
|
||||||
struct VerilatedCStrCmp {
|
|
||||||
// For ordering maps keyed by const char*'s
|
|
||||||
bool operator() (const char *a, const char *b) const {
|
|
||||||
return std::strcmp(a, b) < 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class VerilatedImp {
|
class VerilatedImp {
|
||||||
// Whole class is internal use only - Global information shared between verilated*.cpp files.
|
// Whole class is internal use only - Global information shared between verilated*.cpp files.
|
||||||
|
|
||||||
@@ -55,12 +50,14 @@ class VerilatedImp {
|
|||||||
typedef vector<string> ArgVec;
|
typedef vector<string> ArgVec;
|
||||||
typedef map<pair<const void*,void*>,void*> UserMap;
|
typedef map<pair<const void*,void*>,void*> UserMap;
|
||||||
typedef map<const char*, const VerilatedScope*, VerilatedCStrCmp> ScopeNameMap;
|
typedef map<const char*, const VerilatedScope*, VerilatedCStrCmp> ScopeNameMap;
|
||||||
typedef map<const char*, int> ExportNameMap;
|
typedef map<const char*, int, VerilatedCStrCmp> ExportNameMap;
|
||||||
|
|
||||||
// MEMBERS
|
// MEMBERS
|
||||||
static VerilatedImp s_s; ///< Static Singleton; One and only static this
|
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
|
bool m_argVecLoaded; ///< Ever loaded argument list
|
||||||
UserMap m_userMap; ///< Map of <(scope,userkey), userData>
|
UserMap m_userMap; ///< Map of <(scope,userkey), userData>
|
||||||
ScopeNameMap m_nameMap; ///< Map of <scope_name, scope pointer>
|
ScopeNameMap m_nameMap; ///< Map of <scope_name, scope pointer>
|
||||||
@@ -68,10 +65,31 @@ class VerilatedImp {
|
|||||||
ExportNameMap m_exportMap; ///< Map of <export_func_proto, func number>
|
ExportNameMap m_exportMap; ///< Map of <export_func_proto, func number>
|
||||||
int m_exportNext; ///< Next export funcnum
|
int m_exportNext; ///< Next export funcnum
|
||||||
|
|
||||||
|
// File I/O
|
||||||
|
vector<FILE*> m_fdps; ///< File descriptors
|
||||||
|
deque<IData> m_fdFree; ///< List of free descriptors (SLOW - FOPEN/CLOSE only)
|
||||||
|
|
||||||
public: // But only for verilated*.cpp
|
public: // But only for verilated*.cpp
|
||||||
// CONSTRUCTORS
|
// CONSTRUCTORS
|
||||||
VerilatedImp() : m_argVecLoaded(false), m_exportNext(0) {}
|
VerilatedImp() : m_argVecLoaded(false), m_exportNext(0) {
|
||||||
|
m_fdps.resize(3);
|
||||||
|
m_fdps[0] = stdin;
|
||||||
|
m_fdps[1] = stdout;
|
||||||
|
m_fdps[2] = stderr;
|
||||||
|
}
|
||||||
~VerilatedImp() {}
|
~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
|
// METHODS - arguments
|
||||||
static void commandArgs(int argc, const char** argv) {
|
static void commandArgs(int argc, const char** argv) {
|
||||||
@@ -123,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
|
public: // But only for verilated*.cpp
|
||||||
// METHODS - scope name
|
// METHODS - scope name
|
||||||
@@ -144,9 +170,8 @@ public: // But only for verilated*.cpp
|
|||||||
ScopeNameMap::iterator it=s_s.m_nameMap.find(scopep->name());
|
ScopeNameMap::iterator it=s_s.m_nameMap.find(scopep->name());
|
||||||
if (it != s_s.m_nameMap.end()) s_s.m_nameMap.erase(it);
|
if (it != s_s.m_nameMap.end()) s_s.m_nameMap.erase(it);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void scopesDump() {
|
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) {
|
for (ScopeNameMap::iterator it=s_s.m_nameMap.begin(); it!=s_s.m_nameMap.end(); ++it) {
|
||||||
const VerilatedScope* scopep = it->second;
|
const VerilatedScope* scopep = it->second;
|
||||||
scopep->scopeDump();
|
scopep->scopeDump();
|
||||||
@@ -188,8 +213,43 @@ public: // But only for verilated*.cpp
|
|||||||
}
|
}
|
||||||
return "*UNKNOWN*";
|
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
|
// 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.
|
// what other models are using the assigned funcnum's.
|
||||||
|
|
||||||
|
public: // But only for verilated*.cpp
|
||||||
|
// METHODS - file IO
|
||||||
|
static IData fdNew(FILE* fp) {
|
||||||
|
if (VL_UNLIKELY(!fp)) return 0;
|
||||||
|
// Bit 31 indicates it's a descriptor not a MCD
|
||||||
|
if (s_s.m_fdFree.empty()) {
|
||||||
|
// Need to create more space in m_fdps and m_fdFree
|
||||||
|
size_t start = s_s.m_fdps.size();
|
||||||
|
s_s.m_fdps.resize(start*2);
|
||||||
|
for (size_t i=start; i<start*2; i++) s_s.m_fdFree.push_back((IData)i);
|
||||||
|
}
|
||||||
|
IData idx = s_s.m_fdFree.back(); s_s.m_fdFree.pop_back();
|
||||||
|
s_s.m_fdps[idx] = fp;
|
||||||
|
return (idx | (1UL<<31)); // bit 31 indicates not MCD
|
||||||
|
}
|
||||||
|
static void fdDelete(IData fdi) {
|
||||||
|
IData idx = VL_MASK_I(31) & fdi;
|
||||||
|
if (VL_UNLIKELY(!(fdi & (1ULL<<31)) || idx >= s_s.m_fdps.size())) return;
|
||||||
|
if (VL_UNLIKELY(!s_s.m_fdps[idx])) return; // Already free
|
||||||
|
s_s.m_fdps[idx] = NULL;
|
||||||
|
s_s.m_fdFree.push_back(idx);
|
||||||
|
}
|
||||||
|
static inline FILE* fdToFp(IData fdi) {
|
||||||
|
IData idx = VL_MASK_I(31) & fdi;
|
||||||
|
if (VL_UNLIKELY(!(fdi & (1ULL<<31)) || idx >= s_s.m_fdps.size())) return NULL;
|
||||||
|
return s_s.m_fdps[idx];
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // Guard
|
#endif // Guard
|
||||||
|
|||||||
@@ -0,0 +1,236 @@
|
|||||||
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
// THIS MODULE IS PUBLICLY LICENSED
|
||||||
|
//
|
||||||
|
// Copyright 2001-2014 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 fn = filename();
|
||||||
|
string msg = (string)"Can't deserialize save-restore file as was made from different model";
|
||||||
|
vl_fatal(fn.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 fn = filename();
|
||||||
|
string msg = (string)"Can't deserialize; file has wrong header signature";
|
||||||
|
vl_fatal(fn.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 fn = filename();
|
||||||
|
string msg = (string)"Can't deserialize; file has wrong end-of-file signature";
|
||||||
|
vl_fatal(fn.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-2014 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-2010 by Wilson Snyder. This program is free software; you can
|
// Copyright 2009-2014 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License.
|
// Lesser General Public License Version 3 or the Perl Artistic License.
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
|
|||||||
@@ -0,0 +1,102 @@
|
|||||||
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
|
//*************************************************************************
|
||||||
|
//
|
||||||
|
// Copyright 2003-2014 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: Include to allow symbol inspection
|
||||||
|
///
|
||||||
|
/// This file is for inclusion by files that need to inspect
|
||||||
|
/// the symbol table. It is not included in verilated.h
|
||||||
|
/// as it requires some heavyweight C++ classes.
|
||||||
|
///
|
||||||
|
/// Code available from: http://www.veripool.org/verilator
|
||||||
|
///
|
||||||
|
//*************************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef _VERILATED_SYMS_H_
|
||||||
|
#define _VERILATED_SYMS_H_ 1 ///< Header Guard
|
||||||
|
|
||||||
|
#include "verilated_heavy.h"
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
//======================================================================
|
||||||
|
// Types
|
||||||
|
|
||||||
|
struct VerilatedCStrCmp {
|
||||||
|
/// Ordering maps keyed by const char*'s
|
||||||
|
bool operator() (const char *a, const char *b) const {
|
||||||
|
return std::strcmp(a, b) < 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
/// Verilator range
|
||||||
|
|
||||||
|
// See also V3Ast::VNumRange
|
||||||
|
class VerilatedRange {
|
||||||
|
int m_left;
|
||||||
|
int m_right;
|
||||||
|
protected:
|
||||||
|
friend class VerilatedVar;
|
||||||
|
friend class VerilatedScope;
|
||||||
|
VerilatedRange() : m_left(0), m_right(0) {}
|
||||||
|
void sets(int left, int right) { m_left=left; m_right=right; }
|
||||||
|
public:
|
||||||
|
~VerilatedRange() {}
|
||||||
|
int left() const { return m_left; }
|
||||||
|
int right() const { return m_right; }
|
||||||
|
int elements() const { return (VL_LIKELY(m_left>=m_right)?(m_left-m_right+1):(m_right-m_left+1)); }
|
||||||
|
};
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
/// Verilator variable
|
||||||
|
|
||||||
|
class VerilatedVar {
|
||||||
|
void* m_datap; // Location of data
|
||||||
|
VerilatedVarType m_vltype; // Data type
|
||||||
|
VerilatedVarFlags m_vlflags; // Direction
|
||||||
|
VerilatedRange m_range; // First range
|
||||||
|
VerilatedRange m_array; // Array
|
||||||
|
int m_dims; // Dimensions
|
||||||
|
const char* m_namep; // Name - slowpath
|
||||||
|
protected:
|
||||||
|
friend class VerilatedScope;
|
||||||
|
VerilatedVar(const char* namep, void* datap,
|
||||||
|
VerilatedVarType vltype, VerilatedVarFlags vlflags, int dims)
|
||||||
|
: m_datap(datap), m_vltype(vltype), m_vlflags(vlflags), m_dims(dims), m_namep(namep) {}
|
||||||
|
public:
|
||||||
|
~VerilatedVar() {}
|
||||||
|
void* datap() const { return m_datap; }
|
||||||
|
VerilatedVarType vltype() const { return m_vltype; }
|
||||||
|
VerilatedVarFlags vldir() const { return (VerilatedVarFlags)((int)m_vlflags & VLVF_MASK_DIR); }
|
||||||
|
vluint32_t entSize() const;
|
||||||
|
bool isPublicRW() const { return ((m_vlflags & VLVF_PUB_RW) != 0); }
|
||||||
|
const VerilatedRange& range() const { return m_range; }
|
||||||
|
const VerilatedRange& array() const { return m_array; }
|
||||||
|
const char* name() const { return m_namep; }
|
||||||
|
int dims() const { return m_dims; }
|
||||||
|
};
|
||||||
|
|
||||||
|
//======================================================================
|
||||||
|
/// Types
|
||||||
|
|
||||||
|
class VerilatedVarNameMap : public map<const char*, VerilatedVar, VerilatedCStrCmp> {
|
||||||
|
public:
|
||||||
|
VerilatedVarNameMap() {}
|
||||||
|
~VerilatedVarNameMap() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // Guard
|
||||||
+81
-22
@@ -1,9 +1,9 @@
|
|||||||
// -*- SystemC -*-
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
//
|
//
|
||||||
// THIS MODULE IS PUBLICLY LICENSED
|
// THIS MODULE IS PUBLICLY LICENSED
|
||||||
//
|
//
|
||||||
// Copyright 2001-2010 by Wilson Snyder. This program is free software;
|
// Copyright 2001-2014 by Wilson Snyder. This program is free software;
|
||||||
// you can redistribute it and/or modify it under the terms of either the GNU
|
// 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.
|
// Lesser General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||||
//
|
//
|
||||||
@@ -88,6 +88,11 @@ void VerilatedVcd::open (const char* filename) {
|
|||||||
m_filename = filename;
|
m_filename = filename;
|
||||||
s_vcdVecp.push_back(this);
|
s_vcdVecp.push_back(this);
|
||||||
|
|
||||||
|
// SPDIFF_OFF
|
||||||
|
// Set callback so an early exit will flush us
|
||||||
|
Verilated::flushCb(&flush_all);
|
||||||
|
|
||||||
|
// SPDIFF_ON
|
||||||
openNext (m_rolloverMB!=0);
|
openNext (m_rolloverMB!=0);
|
||||||
if (!isOpen()) return;
|
if (!isOpen()) return;
|
||||||
|
|
||||||
@@ -136,6 +141,7 @@ void VerilatedVcd::openNext (bool incFilename) {
|
|||||||
if (m_filename[0]=='|') {
|
if (m_filename[0]=='|') {
|
||||||
assert(0); // Not supported yet.
|
assert(0); // Not supported yet.
|
||||||
} else {
|
} else {
|
||||||
|
// cppcheck-suppress duplicateExpression
|
||||||
m_fd = ::open (m_filename.c_str(), O_CREAT|O_WRONLY|O_TRUNC|O_LARGEFILE|O_NONBLOCK
|
m_fd = ::open (m_filename.c_str(), O_CREAT|O_WRONLY|O_TRUNC|O_LARGEFILE|O_NONBLOCK
|
||||||
, 0666);
|
, 0666);
|
||||||
if (m_fd<0) {
|
if (m_fd<0) {
|
||||||
@@ -149,10 +155,50 @@ void VerilatedVcd::openNext (bool incFilename) {
|
|||||||
m_wroteBytes = 0;
|
m_wroteBytes = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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];
|
||||||
|
cip->m_code = nextCode();
|
||||||
|
(cip->m_initcb) (this, cip->m_userthis, cip->m_code);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Though not speced, it's illegal to generate a vcd with signals
|
||||||
|
// not under any module - it crashes at least two viewers.
|
||||||
|
// If no scope was specified, prefix everything with a "top"
|
||||||
|
// This comes from user instantiations with no name - IE Vtop("").
|
||||||
|
bool nullScope = false;
|
||||||
|
for (NameMap::iterator it=m_namemapp->begin(); it!=m_namemapp->end(); ++it) {
|
||||||
|
const string& hiername = it->first;
|
||||||
|
if (hiername.size() >= 1 && hiername[0] == '\t') nullScope=true;
|
||||||
|
}
|
||||||
|
if (nullScope) {
|
||||||
|
NameMap* newmapp = new NameMap;
|
||||||
|
for (NameMap::iterator it=m_namemapp->begin(); it!=m_namemapp->end(); ++it) {
|
||||||
|
const string& hiername = it->first;
|
||||||
|
const string& decl = it->second;
|
||||||
|
string newname = string("top");
|
||||||
|
if (hiername[0] != '\t') newname += ' ';
|
||||||
|
newname += hiername;
|
||||||
|
newmapp->insert(make_pair(newname,decl));
|
||||||
|
}
|
||||||
|
deleteNameMap();
|
||||||
|
m_namemapp = newmapp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VerilatedVcd::deleteNameMap() {
|
||||||
|
if (m_namemapp) { delete m_namemapp; m_namemapp=NULL; }
|
||||||
|
}
|
||||||
|
|
||||||
VerilatedVcd::~VerilatedVcd() {
|
VerilatedVcd::~VerilatedVcd() {
|
||||||
close();
|
close();
|
||||||
if (m_wrBufp) { delete[] m_wrBufp; m_wrBufp=NULL; }
|
if (m_wrBufp) { delete[] m_wrBufp; m_wrBufp=NULL; }
|
||||||
if (m_sigs_oldvalp) { delete[] m_sigs_oldvalp; m_sigs_oldvalp=NULL; }
|
if (m_sigs_oldvalp) { delete[] m_sigs_oldvalp; m_sigs_oldvalp=NULL; }
|
||||||
|
deleteNameMap();
|
||||||
// Remove from list of traces
|
// Remove from list of traces
|
||||||
vector<VerilatedVcd*>::iterator pos = find(s_vcdVecp.begin(), s_vcdVecp.end(), this);
|
vector<VerilatedVcd*>::iterator pos = find(s_vcdVecp.begin(), s_vcdVecp.end(), this);
|
||||||
if (pos != s_vcdVecp.end()) { s_vcdVecp.erase(pos); }
|
if (pos != s_vcdVecp.end()) { s_vcdVecp.erase(pos); }
|
||||||
@@ -196,7 +242,7 @@ void VerilatedVcd::printStr (const char* str) {
|
|||||||
|
|
||||||
void VerilatedVcd::printQuad (vluint64_t n) {
|
void VerilatedVcd::printQuad (vluint64_t n) {
|
||||||
char buf [100];
|
char buf [100];
|
||||||
sprintf(buf,"%" VL_PRI64 "u",(long long unsigned)n);
|
sprintf(buf,"%" VL_PRI64 "u", n);
|
||||||
printStr(buf);
|
printStr(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -215,6 +261,20 @@ void VerilatedVcd::printTime (vluint64_t timeui) {
|
|||||||
printQuad(timeui);
|
printQuad(timeui);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VerilatedVcd::bufferResize(vluint64_t minsize) {
|
||||||
|
// minsize is size of largest write. We buffer at least 8 times as much data,
|
||||||
|
// writing when we are 3/4 full (with thus 2*minsize remaining free)
|
||||||
|
if (VL_UNLIKELY(minsize > m_wrChunkSize)) {
|
||||||
|
char* oldbufp = m_wrBufp;
|
||||||
|
m_wrChunkSize = minsize*2;
|
||||||
|
m_wrBufp = new char [m_wrChunkSize * 8];
|
||||||
|
memcpy(m_wrBufp, oldbufp, m_writep - oldbufp);
|
||||||
|
m_writep = m_wrBufp + (m_writep - oldbufp);
|
||||||
|
m_wrFlushp = m_wrBufp + m_wrChunkSize * 6;
|
||||||
|
delete oldbufp; oldbufp=NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void VerilatedVcd::bufferFlush () {
|
void VerilatedVcd::bufferFlush () {
|
||||||
// We add output data to m_writep.
|
// We add output data to m_writep.
|
||||||
// When it gets nearly full we dump it using this routine which calls write()
|
// When it gets nearly full we dump it using this routine which calls write()
|
||||||
@@ -222,10 +282,10 @@ void VerilatedVcd::bufferFlush () {
|
|||||||
if (VL_UNLIKELY(!isOpen())) return;
|
if (VL_UNLIKELY(!isOpen())) return;
|
||||||
char* wp = m_wrBufp;
|
char* wp = m_wrBufp;
|
||||||
while (1) {
|
while (1) {
|
||||||
size_t remaining = (m_writep - wp);
|
ssize_t remaining = (m_writep - wp);
|
||||||
if (remaining==0) break;
|
if (remaining==0) break;
|
||||||
errno = 0;
|
errno = 0;
|
||||||
int got = write (m_fd, wp, remaining);
|
ssize_t got = write (m_fd, wp, remaining);
|
||||||
if (got>0) {
|
if (got>0) {
|
||||||
wp += got;
|
wp += got;
|
||||||
m_wroteBytes += got;
|
m_wroteBytes += got;
|
||||||
@@ -306,16 +366,11 @@ void VerilatedVcd::dumpHeader () {
|
|||||||
printStr("$date "); printStr(ctime(&time_str)); printStr(" $end\n");
|
printStr("$date "); printStr(ctime(&time_str)); printStr(" $end\n");
|
||||||
|
|
||||||
printStr("$timescale ");
|
printStr("$timescale ");
|
||||||
printStr(doubleToTimescale(m_timeRes).c_str());
|
const string& timeResStr = doubleToTimescale(m_timeRes);
|
||||||
|
printStr(timeResStr.c_str());
|
||||||
printStr(" $end\n");
|
printStr(" $end\n");
|
||||||
|
|
||||||
// Take signal information from each module and build m_namemapp
|
makeNameMap();
|
||||||
m_namemapp = new NameMap;
|
|
||||||
for (vluint32_t ent = 0; ent< m_callbacks.size(); ent++) {
|
|
||||||
VerilatedVcdCallInfo *cip = m_callbacks[ent];
|
|
||||||
cip->m_code = nextCode();
|
|
||||||
(cip->m_initcb) (this, cip->m_userthis, cip->m_code);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Signal header
|
// Signal header
|
||||||
assert (m_modDepth==0);
|
assert (m_modDepth==0);
|
||||||
@@ -330,10 +385,11 @@ void VerilatedVcd::dumpHeader () {
|
|||||||
// Print the signal names
|
// Print the signal names
|
||||||
const char* lastName = "";
|
const char* lastName = "";
|
||||||
for (NameMap::iterator it=m_namemapp->begin(); it!=m_namemapp->end(); ++it) {
|
for (NameMap::iterator it=m_namemapp->begin(); it!=m_namemapp->end(); ++it) {
|
||||||
const char* hiername = (*it).first.c_str();
|
const string& hiernamestr = it->first;
|
||||||
const char* decl = (*it).second.c_str();
|
const string& decl = it->second;
|
||||||
|
|
||||||
// Determine difference between the old and new names
|
// Determine difference between the old and new names
|
||||||
|
const char* hiername = hiernamestr.c_str();
|
||||||
const char* lp = lastName;
|
const char* lp = lastName;
|
||||||
const char* np = hiername;
|
const char* np = hiername;
|
||||||
lastName = hiername;
|
lastName = hiername;
|
||||||
@@ -341,7 +397,7 @@ void VerilatedVcd::dumpHeader () {
|
|||||||
// Skip common prefix, it must break at a space or tab
|
// Skip common prefix, it must break at a space or tab
|
||||||
for (; *np && (*np == *lp); np++, lp++) {}
|
for (; *np && (*np == *lp); np++, lp++) {}
|
||||||
while (np!=hiername && *np && *np!=' ' && *np!='\t') { np--; lp--; }
|
while (np!=hiername && *np && *np!=' ' && *np!='\t') { np--; lp--; }
|
||||||
//cout <<"hier "<<hiername<<endl<<" lp "<<lp<<endl<<" np "<<np<<endl;
|
//printf("hier %s\n lp=%s\n np=%s\n",hiername,lp,np);
|
||||||
|
|
||||||
// Any extra spaces in last name are scope ups we need to do
|
// Any extra spaces in last name are scope ups we need to do
|
||||||
bool first = true;
|
bool first = true;
|
||||||
@@ -368,7 +424,7 @@ void VerilatedVcd::dumpHeader () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
printIndent(0);
|
printIndent(0);
|
||||||
printStr(decl);
|
printStr(decl.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
while (m_modDepth>1) {
|
while (m_modDepth>1) {
|
||||||
@@ -381,7 +437,7 @@ void VerilatedVcd::dumpHeader () {
|
|||||||
assert (m_modDepth==0);
|
assert (m_modDepth==0);
|
||||||
|
|
||||||
// Reclaim storage
|
// Reclaim storage
|
||||||
delete m_namemapp;
|
deleteNameMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VerilatedVcd::module (string name) {
|
void VerilatedVcd::module (string name) {
|
||||||
@@ -389,7 +445,7 @@ void VerilatedVcd::module (string name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void VerilatedVcd::declare (vluint32_t code, const char* name, const char* wirep,
|
void VerilatedVcd::declare (vluint32_t code, const char* name, const char* wirep,
|
||||||
int arraynum, bool tri, bool bussed, int msb, int lsb) {
|
int arraynum, bool tri, bool bussed, int msb, int lsb) {
|
||||||
if (!code) { vl_fatal(__FILE__,__LINE__,"","Internal: internal trace problem, code 0 is illegal"); }
|
if (!code) { vl_fatal(__FILE__,__LINE__,"","Internal: internal trace problem, code 0 is illegal"); }
|
||||||
|
|
||||||
int bits = ((msb>lsb)?(msb-lsb):(lsb-msb))+1;
|
int bits = ((msb>lsb)?(msb-lsb):(lsb-msb))+1;
|
||||||
@@ -402,6 +458,9 @@ void VerilatedVcd::declare (vluint32_t code, const char* name, const char* wirep
|
|||||||
m_sigs.reserve(m_nextCode*2); // Power-of-2 allocation speeds things up
|
m_sigs.reserve(m_nextCode*2); // Power-of-2 allocation speeds things up
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make sure write buffer is large enough (one character per bit), plus header
|
||||||
|
bufferResize(bits+1024);
|
||||||
|
|
||||||
// Save declaration info
|
// Save declaration info
|
||||||
VerilatedVcdSig sig = VerilatedVcdSig(code, bits);
|
VerilatedVcdSig sig = VerilatedVcdSig(code, bits);
|
||||||
m_sigs.push_back(sig);
|
m_sigs.push_back(sig);
|
||||||
@@ -480,7 +539,7 @@ void VerilatedVcd::declDouble (vluint32_t code, const char* name, int arraynum
|
|||||||
|
|
||||||
void VerilatedVcd::fullDouble (vluint32_t code, const double newval) {
|
void VerilatedVcd::fullDouble (vluint32_t code, const double newval) {
|
||||||
(*((double*)&m_sigs_oldvalp[code])) = newval;
|
(*((double*)&m_sigs_oldvalp[code])) = newval;
|
||||||
// Buffer can't overflow; we have at least bufferInsertSize() bytes (>>>16 bytes)
|
// Buffer can't overflow before sprintf; we sized during declaration
|
||||||
sprintf(m_writep, "r%.16g", newval);
|
sprintf(m_writep, "r%.16g", newval);
|
||||||
m_writep += strlen(m_writep);
|
m_writep += strlen(m_writep);
|
||||||
*m_writep++=' '; printCode(code); *m_writep++='\n';
|
*m_writep++=' '; printCode(code); *m_writep++='\n';
|
||||||
@@ -488,7 +547,7 @@ void VerilatedVcd::fullDouble (vluint32_t code, const double newval) {
|
|||||||
}
|
}
|
||||||
void VerilatedVcd::fullFloat (vluint32_t code, const float newval) {
|
void VerilatedVcd::fullFloat (vluint32_t code, const float newval) {
|
||||||
(*((float*)&m_sigs_oldvalp[code])) = newval;
|
(*((float*)&m_sigs_oldvalp[code])) = newval;
|
||||||
// Buffer can't overflow; we have at least bufferInsertSize() bytes (>>>16 bytes)
|
// Buffer can't overflow before sprintf; we sized during declaration
|
||||||
sprintf(m_writep, "r%.16g", (double)newval);
|
sprintf(m_writep, "r%.16g", (double)newval);
|
||||||
m_writep += strlen(m_writep);
|
m_writep += strlen(m_writep);
|
||||||
*m_writep++=' '; printCode(code); *m_writep++='\n';
|
*m_writep++=' '; printCode(code); *m_writep++='\n';
|
||||||
@@ -661,5 +720,5 @@ main() {
|
|||||||
|
|
||||||
//********************************************************************
|
//********************************************************************
|
||||||
// Local Variables:
|
// Local Variables:
|
||||||
// compile-command: "mkdir -p ../test_dir && cd ../test_dir && g++ -DVERILATED_VCD_TEST ../src/verilated_vcd_c.cpp -o verilated_vcd_c && ./verilated_vcd_c && cat test.vcd"
|
// compile-command: "mkdir -p ../test_dir && cd ../test_dir && c++ -DVERILATED_VCD_TEST ../src/verilated_vcd_c.cpp -o verilated_vcd_c && ./verilated_vcd_c && cat test.vcd"
|
||||||
// End:
|
// End:
|
||||||
|
|||||||
+23
-10
@@ -1,9 +1,9 @@
|
|||||||
// -*- SystemC -*-
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
//
|
//
|
||||||
// THIS MODULE IS PUBLICLY LICENSED
|
// THIS MODULE IS PUBLICLY LICENSED
|
||||||
//
|
//
|
||||||
// Copyright 2001-2010 by Wilson Snyder. This program is free software;
|
// Copyright 2001-2014 by Wilson Snyder. This program is free software;
|
||||||
// you can redistribute it and/or modify it under the terms of either the GNU
|
// 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.
|
// 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
|
// 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 {
|
class VerilatedVcd {
|
||||||
private:
|
private:
|
||||||
@@ -76,7 +77,9 @@ private:
|
|||||||
vluint64_t m_timeLastDump; ///< Last time we did a dump
|
vluint64_t m_timeLastDump; ///< Last time we did a dump
|
||||||
|
|
||||||
char* m_wrBufp; ///< Output buffer
|
char* m_wrBufp; ///< Output buffer
|
||||||
|
char* m_wrFlushp; ///< Output buffer flush trigger location
|
||||||
char* m_writep; ///< Write pointer into output buffer
|
char* m_writep; ///< Write pointer into output buffer
|
||||||
|
vluint64_t m_wrChunkSize; ///< Output buffer size
|
||||||
vluint64_t m_wroteBytes; ///< Number of bytes written to this file
|
vluint64_t m_wroteBytes; ///< Number of bytes written to this file
|
||||||
|
|
||||||
vluint32_t* m_sigs_oldvalp; ///< Pointer to old signal values
|
vluint32_t* m_sigs_oldvalp; ///< Pointer to old signal values
|
||||||
@@ -86,19 +89,20 @@ private:
|
|||||||
NameMap* m_namemapp; ///< List of names for the header
|
NameMap* m_namemapp; ///< List of names for the header
|
||||||
static vector<VerilatedVcd*> s_vcdVecp; ///< List of all created traces
|
static vector<VerilatedVcd*> s_vcdVecp; ///< List of all created traces
|
||||||
|
|
||||||
inline size_t bufferSize() { return 256*1024; } // See below for slack calculation
|
void bufferResize(vluint64_t minsize);
|
||||||
inline size_t bufferInsertSize() { return 16*1024; }
|
|
||||||
void bufferFlush();
|
void bufferFlush();
|
||||||
void bufferCheck() {
|
inline void bufferCheck() {
|
||||||
// Flush the write buffer if there's not enough space left for new information
|
// 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
|
// We only call this once per vector, so we need enough slop for a very wide "b###" line
|
||||||
if (VL_UNLIKELY(m_writep > (m_wrBufp+(bufferSize()-bufferInsertSize())))) {
|
if (VL_UNLIKELY(m_writep > m_wrFlushp)) {
|
||||||
bufferFlush();
|
bufferFlush();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void closePrev();
|
void closePrev();
|
||||||
void closeErr();
|
void closeErr();
|
||||||
void openNext();
|
void openNext();
|
||||||
|
void makeNameMap();
|
||||||
|
void deleteNameMap();
|
||||||
void printIndent (int levelchange);
|
void printIndent (int levelchange);
|
||||||
void printStr (const char* str);
|
void printStr (const char* str);
|
||||||
void printQuad (vluint64_t n);
|
void printQuad (vluint64_t n);
|
||||||
@@ -109,6 +113,7 @@ private:
|
|||||||
void dumpHeader();
|
void dumpHeader();
|
||||||
void dumpPrep (vluint64_t timeui);
|
void dumpPrep (vluint64_t timeui);
|
||||||
void dumpFull (vluint64_t timeui);
|
void dumpFull (vluint64_t timeui);
|
||||||
|
// cppcheck-suppress functionConst
|
||||||
void dumpDone ();
|
void dumpDone ();
|
||||||
inline void printCode (vluint32_t code) {
|
inline void printCode (vluint32_t code) {
|
||||||
if (code>=(94*94*94)) *m_writep++ = ((char)((code/94/94/94)%94+33));
|
if (code>=(94*94*94)) *m_writep++ = ((char)((code/94/94/94)%94+33));
|
||||||
@@ -116,7 +121,7 @@ private:
|
|||||||
if (code>=(94)) *m_writep++ = ((char)((code/94)%94+33));
|
if (code>=(94)) *m_writep++ = ((char)((code/94)%94+33));
|
||||||
*m_writep++ = ((char)((code)%94+33));
|
*m_writep++ = ((char)((code)%94+33));
|
||||||
}
|
}
|
||||||
string stringCode (vluint32_t code) {
|
static string stringCode (vluint32_t code) {
|
||||||
string out;
|
string out;
|
||||||
if (code>=(94*94*94)) out += ((char)((code/94/94/94)%94+33));
|
if (code>=(94*94*94)) out += ((char)((code/94/94/94)%94+33));
|
||||||
if (code>=(94*94)) out += ((char)((code/94/94)%94+33));
|
if (code>=(94*94)) out += ((char)((code/94/94)%94+33));
|
||||||
@@ -131,14 +136,18 @@ protected:
|
|||||||
public:
|
public:
|
||||||
// CREATORS
|
// CREATORS
|
||||||
VerilatedVcd () : m_isOpen(false), m_rolloverMB(0), m_modDepth(0), m_nextCode(1) {
|
VerilatedVcd () : m_isOpen(false), m_rolloverMB(0), m_modDepth(0), m_nextCode(1) {
|
||||||
m_wrBufp = new char [bufferSize()];
|
|
||||||
m_writep = m_wrBufp;
|
|
||||||
m_namemapp = NULL;
|
m_namemapp = NULL;
|
||||||
m_timeRes = m_timeUnit = 1e-9;
|
m_timeRes = m_timeUnit = 1e-9;
|
||||||
m_timeLastDump = 0;
|
m_timeLastDump = 0;
|
||||||
m_sigs_oldvalp = NULL;
|
m_sigs_oldvalp = NULL;
|
||||||
m_evcd = false;
|
m_evcd = false;
|
||||||
m_scopeEscape = '.'; // Backward compatibility
|
m_scopeEscape = '.'; // Backward compatibility
|
||||||
|
m_fd = 0;
|
||||||
|
m_fullDump = true;
|
||||||
|
m_wrChunkSize = 8*1024;
|
||||||
|
m_wrBufp = new char [m_wrChunkSize*8];
|
||||||
|
m_wrFlushp = m_wrBufp + m_wrChunkSize * 6;
|
||||||
|
m_writep = m_wrBufp;
|
||||||
m_wroteBytes = 0;
|
m_wroteBytes = 0;
|
||||||
}
|
}
|
||||||
~VerilatedVcd();
|
~VerilatedVcd();
|
||||||
@@ -396,8 +405,12 @@ public:
|
|||||||
bool isOpen() const { return m_sptrace.isOpen(); }
|
bool isOpen() const { return m_sptrace.isOpen(); }
|
||||||
// METHODS
|
// METHODS
|
||||||
/// Open a new VCD file
|
/// 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); }
|
void open (const char* filename) { m_sptrace.open(filename); }
|
||||||
/// Continue a VCD dump by rotating to a new file name
|
/// 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); }
|
void openNext (bool incFilename=true) { m_sptrace.openNext(incFilename); }
|
||||||
/// Set size in megabytes after which new file should be created
|
/// Set size in megabytes after which new file should be created
|
||||||
void rolloverMB(size_t rolloverMB) { m_sptrace.rolloverMB(rolloverMB); };
|
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
|
// THIS MODULE IS PUBLICLY LICENSED
|
||||||
//
|
//
|
||||||
// Copyright 2001-2010 by Wilson Snyder. This program is free software;
|
// Copyright 2001-2014 by Wilson Snyder. This program is free software;
|
||||||
// you can redistribute it and/or modify it under the terms of either the GNU
|
// 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.
|
// 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
|
// THIS MODULE IS PUBLICLY LICENSED
|
||||||
//
|
//
|
||||||
// Copyright 2001-2010 by Wilson Snyder. This program is free software;
|
// Copyright 2001-2014 by Wilson Snyder. This program is free software;
|
||||||
// you can redistribute it and/or modify it under the terms of either the GNU
|
// 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.
|
// Lesser General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||||
//
|
//
|
||||||
@@ -76,6 +76,8 @@ private:
|
|||||||
#ifdef NC_SYSTEMC
|
#ifdef NC_SYSTEMC
|
||||||
// Cadence Incisive has these as abstract functions so we must create them
|
// Cadence Incisive has these as abstract functions so we must create them
|
||||||
virtual void set_time_unit( int exponent10_seconds ) {} // deprecated
|
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 ) {}
|
virtual void set_time_unit( double v, sc_time_unit tu ) {}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,364 @@
|
|||||||
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
|
//*************************************************************************
|
||||||
|
//
|
||||||
|
// Copyright 2009-2014 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: VPI implementation code
|
||||||
|
///
|
||||||
|
/// This file must be compiled and linked against all objects
|
||||||
|
/// created from Verilator or called by Verilator that use the VPI.
|
||||||
|
///
|
||||||
|
/// Code available from: http://www.veripool.org/verilator
|
||||||
|
///
|
||||||
|
//=========================================================================
|
||||||
|
|
||||||
|
#include "verilated_vpi.h"
|
||||||
|
|
||||||
|
//======================================================================
|
||||||
|
|
||||||
|
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];
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
+61
-4
@@ -1,7 +1,7 @@
|
|||||||
// -*- C++ -*-
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2014 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License.
|
// Lesser General Public License Version 3 or the Perl Artistic License.
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
@@ -78,8 +78,12 @@
|
|||||||
# else
|
# else
|
||||||
# error "Unsupported compiler for VL_THREADED: No thread-local declarator"
|
# error "Unsupported compiler for VL_THREADED: No thread-local declarator"
|
||||||
# endif
|
# 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
|
#else
|
||||||
# define VL_THREAD ///< Storage class for thread-local storage
|
# 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
|
#endif
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
@@ -91,6 +95,16 @@
|
|||||||
// This is not necessarily the same as #UL, depending on what the IData typedef is.
|
// This is not necessarily the same as #UL, depending on what the IData typedef is.
|
||||||
#define VL_UL(c) ((IData)(c##UL)) ///< Add appropriate suffix to 32-bit constant
|
#define VL_UL(c) ((IData)(c##UL)) ///< Add appropriate suffix to 32-bit constant
|
||||||
|
|
||||||
|
//=========================================================================
|
||||||
|
// C++-2011
|
||||||
|
|
||||||
|
#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
|
||||||
|
# define VL_HAS_UNIQUE_PTR
|
||||||
|
# define VL_UNIQUE_PTR unique_ptr
|
||||||
|
#else
|
||||||
|
# define VL_UNIQUE_PTR auto_ptr
|
||||||
|
#endif
|
||||||
|
|
||||||
//=========================================================================
|
//=========================================================================
|
||||||
// Warning disabled
|
// Warning disabled
|
||||||
|
|
||||||
@@ -126,8 +140,13 @@ typedef unsigned long uint32_t; ///< 32-bit unsigned type (backward compatibili
|
|||||||
typedef long vlsint32_t; ///< 32-bit signed type
|
typedef long vlsint32_t; ///< 32-bit signed type
|
||||||
typedef unsigned long vluint32_t; ///< 32-bit unsigned type
|
typedef unsigned long vluint32_t; ///< 32-bit unsigned type
|
||||||
# endif
|
# endif
|
||||||
|
# if defined(__WORDSIZE) && (__WORDSIZE == 64)
|
||||||
|
typedef long vlsint64_t; ///< 64-bit signed type
|
||||||
|
typedef unsigned long vluint64_t; ///< 64-bit unsigned type
|
||||||
|
# else
|
||||||
typedef long long vlsint64_t; ///< 64-bit signed type
|
typedef long long vlsint64_t; ///< 64-bit signed type
|
||||||
typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
|
typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
|
||||||
|
# endif
|
||||||
|
|
||||||
#elif defined(_WIN32) && defined(_MSC_VER)
|
#elif defined(_WIN32) && defined(_MSC_VER)
|
||||||
|
|
||||||
@@ -141,6 +160,14 @@ typedef unsigned __int32 vluint32_t; ///< 32-bit unsigned type
|
|||||||
typedef signed __int64 vlsint64_t; ///< 64-bit signed type
|
typedef signed __int64 vlsint64_t; ///< 64-bit signed type
|
||||||
typedef unsigned __int64 vluint64_t; ///< 64-bit unsigned type
|
typedef unsigned __int64 vluint64_t; ///< 64-bit unsigned type
|
||||||
|
|
||||||
|
# ifndef _SSIZE_T_DEFINED
|
||||||
|
# ifdef _WIN64
|
||||||
|
typedef signed __int64 ssize_t; ///< signed size_t; returned from read()
|
||||||
|
# else
|
||||||
|
typedef signed __int32 ssize_t; ///< signed size_t; returned from read()
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
|
||||||
#else // Linux or compliant Unix flavors, -m64
|
#else // Linux or compliant Unix flavors, -m64
|
||||||
|
|
||||||
# include <stdint.h> // Linux and most flavors
|
# include <stdint.h> // Linux and most flavors
|
||||||
@@ -149,8 +176,13 @@ typedef uint8_t vluint8_t; ///< 32-bit unsigned type
|
|||||||
typedef uint16_t vluint16_t; ///< 32-bit unsigned type
|
typedef uint16_t vluint16_t; ///< 32-bit unsigned type
|
||||||
typedef int vlsint32_t; ///< 32-bit signed type
|
typedef int vlsint32_t; ///< 32-bit signed type
|
||||||
typedef uint32_t vluint32_t; ///< 32-bit signed type
|
typedef uint32_t vluint32_t; ///< 32-bit signed type
|
||||||
|
# if defined(__WORDSIZE) && (__WORDSIZE == 64)
|
||||||
|
typedef long vlsint64_t; ///< 64-bit signed type
|
||||||
|
typedef unsigned long vluint64_t; ///< 64-bit unsigned type
|
||||||
|
# else
|
||||||
typedef long long vlsint64_t; ///< 64-bit signed type
|
typedef long long vlsint64_t; ///< 64-bit signed type
|
||||||
typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
|
typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//=========================================================================
|
//=========================================================================
|
||||||
@@ -160,7 +192,20 @@ typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
|
|||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
# define VL_PRI64 "I64"
|
# define VL_PRI64 "I64"
|
||||||
#else // Linux or compliant Unix flavors
|
#else // Linux or compliant Unix flavors
|
||||||
# define VL_PRI64 "ll"
|
# if defined(__WORDSIZE) && (__WORDSIZE == 64)
|
||||||
|
# define VL_PRI64 "l"
|
||||||
|
# else
|
||||||
|
# define VL_PRI64 "ll"
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//=========================================================================
|
||||||
|
// File system functions
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
# define VL_DEV_NULL "nul"
|
||||||
|
#else // Linux or compliant Unix flavors
|
||||||
|
# define VL_DEV_NULL "/dev/null"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//=========================================================================
|
//=========================================================================
|
||||||
@@ -199,6 +244,18 @@ typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
|
|||||||
#define VL_BITBIT_I(bit) ((bit)&VL_SIZEBITS_I) ///< Bit number for a bit in a long
|
#define VL_BITBIT_I(bit) ((bit)&VL_SIZEBITS_I) ///< Bit number for a bit in a long
|
||||||
#define VL_BITBIT_Q(bit) ((bit)&VL_SIZEBITS_Q) ///< Bit number for a bit in a quad
|
#define VL_BITBIT_Q(bit) ((bit)&VL_SIZEBITS_Q) ///< Bit number for a bit in a quad
|
||||||
|
|
||||||
|
//=========================================================================
|
||||||
|
// Floating point
|
||||||
|
// #defines, to avoid requiring math.h on all compile runs
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
# define VL_TRUNC(n) (((n)<0) ? ceil((n)) : floor((n)))
|
||||||
|
# define VL_ROUND(n) (((n)<0) ? ceil((n)-0.5) : floor((n)+0.5))
|
||||||
|
#else
|
||||||
|
# define VL_TRUNC(n) trunc(n)
|
||||||
|
# define VL_ROUND(n) round(n)
|
||||||
|
#endif
|
||||||
|
|
||||||
//=========================================================================
|
//=========================================================================
|
||||||
|
|
||||||
#endif /*guard*/
|
#endif /*guard*/
|
||||||
|
|||||||
+12
-6
@@ -7,7 +7,7 @@
|
|||||||
* This file contains the constant definitions, structure definitions,
|
* This file contains the constant definitions, structure definitions,
|
||||||
* and routine declarations used by SystemVerilog DPI.
|
* 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
|
#ifndef INCLUDED_SVDPI
|
||||||
@@ -27,25 +27,31 @@ typedef signed __int32 int32_t;
|
|||||||
typedef signed __int8 int8_t;
|
typedef signed __int8 int8_t;
|
||||||
#elif defined(__MINGW32__)
|
#elif defined(__MINGW32__)
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#elif defined(__linux)
|
#elif defined(__APPLE__)
|
||||||
|
#include <stdint.h>
|
||||||
|
#elif defined(__linux) || (defined(__APPLE__) && defined(__MACH__))
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#else
|
#else
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Use to export a symbol from application */
|
/* Use to import a symbol into dll */
|
||||||
#if defined (_MSC_VER)
|
#ifndef DPI_DLLISPEC
|
||||||
|
#if (defined(_MSC_VER) || defined(__MINGW32__) || defined(__CYGWIN__))
|
||||||
#define DPI_DLLISPEC __declspec(dllimport)
|
#define DPI_DLLISPEC __declspec(dllimport)
|
||||||
#else
|
#else
|
||||||
#define DPI_DLLISPEC
|
#define DPI_DLLISPEC
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Use to import a symbol into application */
|
/* Use to export a symbol from dll */
|
||||||
#if defined (_MSC_VER)
|
#ifndef DPI_DLLESPEC
|
||||||
|
#if (defined(_MSC_VER) || defined(__MINGW32__) || defined(__CYGWIN__))
|
||||||
#define DPI_DLLESPEC __declspec(dllexport)
|
#define DPI_DLLESPEC __declspec(dllexport)
|
||||||
#else
|
#else
|
||||||
#define DPI_DLLESPEC
|
#define DPI_DLLESPEC
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Use to mark a function as external */
|
/* Use to mark a function as external */
|
||||||
#ifndef DPI_EXTERN
|
#ifndef DPI_EXTERN
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
+685
-67
@@ -14,33 +14,516 @@ the first for reference for developers and debugging problems.
|
|||||||
|
|
||||||
See also the Verilator internals presentation at http://www.veripool.org.
|
See also the Verilator internals presentation at http://www.veripool.org.
|
||||||
|
|
||||||
=head1 ADDING A NEW FEATURE
|
=head1 CODE FLOWS
|
||||||
|
|
||||||
Generally what would you do to add a new feature?
|
=head2 Verilator Flow
|
||||||
|
|
||||||
|
The main flow of Verilator can be followed by reading the Verilator.cpp
|
||||||
|
process() function:
|
||||||
|
|
||||||
|
First, the files specified on the command line are read. Reading involves
|
||||||
|
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.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
Parameters are resolved and the design is elaborated.
|
||||||
|
|
||||||
|
Verilator then performs many additional edits and optimizations on the
|
||||||
|
hierarchical design. This includes coverage, assertions, X elimination,
|
||||||
|
inlining, constant propagation, and dead code elimination.
|
||||||
|
|
||||||
|
References in the design are then pseudo-flattened. Each module's variables
|
||||||
|
and functions get "Scope" references. A scope reference is an occurrence of
|
||||||
|
that un-flattened variable in the flattened hierarchy. A module that occurs
|
||||||
|
only once in the hierarchy will have a single scope and single VarScope for
|
||||||
|
each variable. A module that occurs twice will have a scope for each
|
||||||
|
occurrence, and two VarScopes for each variable. This allows optimizations
|
||||||
|
to proceed across the flattened design, while still preserving the
|
||||||
|
hierarchy.
|
||||||
|
|
||||||
|
Additional edits and optimizations proceed on the pseudo-flat design. These
|
||||||
|
include module references, function inlining, loop unrolling, variable
|
||||||
|
lifetime analysis, lookup table creation, always splitting, and logic gate
|
||||||
|
simplifications (pushing inverters, etc).
|
||||||
|
|
||||||
|
Verilator orders the code. Best case, this results in a single "eval"
|
||||||
|
function which has all always statements flowing from top to bottom with no
|
||||||
|
loops.
|
||||||
|
|
||||||
|
Verilator mostly removes the flattening, so that code may be shared between
|
||||||
|
multiple invocations of the same module. It localizes variables, combines
|
||||||
|
identical functions, expands macros to C primitives, adds branch prediction
|
||||||
|
hints, and performs additional constant propagation.
|
||||||
|
|
||||||
|
Verilator finally writes the C++ modules.
|
||||||
|
|
||||||
|
=head2 Key Classes Used in the Verilator Flow
|
||||||
|
|
||||||
=over 4
|
=over 4
|
||||||
|
|
||||||
File a bug (if there isn't already) so others know what you're working on.
|
=item C<AstNode>
|
||||||
|
|
||||||
Make a testcase in the test_regress/t/t_EXAMPLE format, see TESTING Below.
|
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).
|
||||||
|
|
||||||
If grammar changes are needed, look at the git version of VerilogPerl's
|
Each C<AstNode> has pointers to up to four children, accessed by the
|
||||||
src/VParseGrammar.y, as this grammar supports the full SystemVerilog
|
C<op1p> through C<op4p> methods. These methods are then abstracted in a
|
||||||
language and has a lot of back-and-forth with Verilator's grammar. Copy
|
specific Ast* node class to a more specific name. For example with the
|
||||||
the appropriate rules to src/verilog.y and modify the productions.
|
C<AstIf> node (for C<if> statements), C<ifsp> calls C<op2p> to give the
|
||||||
|
pointer to the AST for the "then" block, while C<elsesp> calls C<op3p> to
|
||||||
|
give the pointer to the AST for the "else" block, or NULL if there is not
|
||||||
|
one.
|
||||||
|
|
||||||
If a new Ast type is needed, add it to V3AstNodes.h.
|
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.
|
||||||
|
|
||||||
Now you can run "test_regress/t/t_{new testcase}.pl --debug" and it'll
|
It is useful to remember that the derived class C<AstNetlist> is at the top
|
||||||
probably fail but you'll see a test_regress/obj_dir/t_{newtestcase}/*.tree
|
of the tree, so checking for this class is the standard way to see if you
|
||||||
file which you can examine to see if the parsing worked. See also the
|
are at the top of the tree.
|
||||||
sections below on debugging.
|
|
||||||
|
|
||||||
Modify the later visitor functions to process the new feature as needed.
|
By convention, each function/method uses the variable C<nodep> as a pointer
|
||||||
|
to the C<AstNode> currently being processed.
|
||||||
|
|
||||||
|
=item C<AstNVisitor>
|
||||||
|
|
||||||
|
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 provide 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
|
=back
|
||||||
|
|
||||||
=head1 DEBUG OUTPUT/ TREE FILES
|
=head2 Verilated Flow
|
||||||
|
|
||||||
|
The evaluation loop outputted by Verilator is designed to allow a single
|
||||||
|
function to perform evaluation under most situations.
|
||||||
|
|
||||||
|
On the first evaluation, the Verilated code calls initial blocks, and then
|
||||||
|
"settles" the modules, by evaluating functions (from always statements)
|
||||||
|
until all signals are stable.
|
||||||
|
|
||||||
|
On other evaluations, the Verilated code detects what input signals have
|
||||||
|
changes. If any are clocks, it calls the appropriate sequential functions
|
||||||
|
(from always @ posedge statements). Interspersed with sequential functions
|
||||||
|
it calls combo functions (from always @*). After this is complete, it
|
||||||
|
detects any changes due to combo loops or internally generated clocks, and
|
||||||
|
if one is found must reevaluate the model again.
|
||||||
|
|
||||||
|
For SystemC code, the eval() function is wrapped in a SystemC SC_METHOD,
|
||||||
|
sensitive to all inputs. (Ideally it would only be sensitive to clocks and
|
||||||
|
combo inputs, but tracing requires all signals to cause evaluation, and the
|
||||||
|
performance difference is small.)
|
||||||
|
|
||||||
|
If tracing is enabled, a callback examines all variables in the design for
|
||||||
|
changes, and writes the trace for each change. To accelerate this process
|
||||||
|
the evaluation process records a bitmask of variables that might have
|
||||||
|
changed; if clear, checking those signals for changes may be skipped.
|
||||||
|
|
||||||
|
=head1 CODING CONVENTIONS
|
||||||
|
|
||||||
|
=head2 Indentation style
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
All files should contain the magic header to insure standard indentation:
|
||||||
|
|
||||||
|
// -*- 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
|
||||||
|
|
||||||
|
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>.
|
||||||
|
|
||||||
|
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).
|
||||||
|
|
||||||
|
A visitor first clears the one it wants to use by calling
|
||||||
|
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 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 C<user#()> on a given C<AstNode>
|
||||||
|
type is never being used for two different purposes.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
=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 now deprecated and should I<not> 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
|
||||||
|
|
||||||
|
=head3 Caution on Using Iterators When Child Changes
|
||||||
|
|
||||||
|
Visitors often replace one node with another node; V3Width and V3Const are
|
||||||
|
major examples. A visitor which is the parent of such a replacement needs
|
||||||
|
to be aware that calling iteration may cause the children to change. For
|
||||||
|
example:
|
||||||
|
|
||||||
|
// nodep->lhsp() is 0x1234000
|
||||||
|
nodep->lhsp()->iterateAndNext(...); // and under covers nodep->lhsp() changes
|
||||||
|
// nodep->lhsp() is 0x5678400
|
||||||
|
nodep->lhsp()->iterateAndNext(...);
|
||||||
|
|
||||||
|
Will work fine, as even if the first iterate causes a new node to take the
|
||||||
|
place of the lhsp(), that edit will update nodep->lhsp() and the second
|
||||||
|
call will correctly see the change. Alternatively:
|
||||||
|
|
||||||
|
lp = nodep->lhsp();
|
||||||
|
// nodep->lhsp() is 0x1234000, lp is 0x1234000
|
||||||
|
lp->iterateAndNext(...); **lhsp=NULL;** // and under covers nodep->lhsp() changes
|
||||||
|
// nodep->lhsp() is 0x5678400, lp is 0x1234000
|
||||||
|
lp->iterateAndNext(...);
|
||||||
|
|
||||||
|
This will cause bugs or a core dump, as lp is a dangling pointer. Thus it
|
||||||
|
is advisable to set lhsp=NULL shown in the *'s above to make sure these
|
||||||
|
dangles are avoided. Another alternative used in special cases mostly in
|
||||||
|
V3Width is to use acceptSubtreeReturnEdits, which operates on a single node
|
||||||
|
and returns the new pointer if any. Note acceptSubtreeReturnEdits does not
|
||||||
|
follow nextp() links.
|
||||||
|
|
||||||
|
lp = lp->acceptSubtreeReturnEdits()
|
||||||
|
|
||||||
|
=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
|
||||||
|
|
||||||
|
For an overview of how to write a test see the BUGS section of the
|
||||||
|
Verilator primary manual.
|
||||||
|
|
||||||
|
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 convention 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 additional 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
|
||||||
|
|
||||||
|
=head2 --debug
|
||||||
|
|
||||||
When you run with --debug there are two primary output file types placed into
|
When you run with --debug there are two primary output file types placed into
|
||||||
the obj_dir, .tree and .dot files.
|
the obj_dir, .tree and .dot files.
|
||||||
@@ -66,26 +549,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
|
Tree files are dumps of the AST Tree and are produced between every major
|
||||||
algorithmic stage. An example:
|
algorithmic stage. An example:
|
||||||
|
|
||||||
NETLIST 0x90fb00 <e1> {0} w0
|
NETLIST 0x90fb00 <e1> {a0}
|
||||||
1: MODULE 0x912b20 <e8822> {8} w0 top L2 [P]
|
1: MODULE 0x912b20 <e8822> {a8} top L2 [P]
|
||||||
*1:2: VAR 0x91a780 <e74#> {22} w70 out_wide [O] WIRE
|
*1:2: VAR 0x91a780 <e74#> {a22} @dt=0xa2e640(w32) out_wide [O] WIRE
|
||||||
1:2:1: BASICDTYPE 0x91a3c0 <e73> {22} w70 [logic]
|
1:2:1: BASICDTYPE 0xa2e640 <e2149> {e24} @dt=this(sw32) integer kwd=integer range=[31:0]
|
||||||
|
|
||||||
=over 4
|
=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.
|
"VAR" is the AstNodeType.
|
||||||
|
|
||||||
"0x91a780" is the address of this node.
|
"0x91a780" is the address of this node.
|
||||||
|
|
||||||
"<e74>" means the 74th edit to the netlist was the last modification to
|
"<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
|
this node.
|
||||||
dump was made. You can gdb break on this edit; see below.
|
|
||||||
|
|
||||||
"{22}" indicates this node is related to line 22 in the source.
|
"{a22}" indicates this node is related to line 22 in the source filename
|
||||||
|
"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.
|
"out_wide" is the name of the node, in this case the name of the variable.
|
||||||
|
|
||||||
@@ -94,74 +583,203 @@ variable is an output.
|
|||||||
|
|
||||||
=back
|
=back
|
||||||
|
|
||||||
=head1 TESTING
|
In more detail the following fields are dumped common to all nodes. They
|
||||||
|
are produced by the C<AstNode::dump()> method:
|
||||||
|
|
||||||
To write a test see notes in the forum and in the verilator.txt manual.
|
=over 4
|
||||||
|
|
||||||
Note you can run the regression tests in parallel; see the
|
=item Tree Hierarchy
|
||||||
test_regress/driver.pl script -j flag.
|
|
||||||
|
|
||||||
=head1 VISITOR FUNCTIONS
|
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:
|
||||||
|
|
||||||
=head2 Passing Variables
|
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
|
||||||
|
...
|
||||||
|
|
||||||
There's three ways data is passed between visitor functions.
|
=item AstNode type
|
||||||
|
|
||||||
1. A visitor-class member variable. This is generally for passing "parent"
|
The textual name of this node AST type (always in capitals). Many of these
|
||||||
information down to children. m_modp is a common example. It's set to
|
correspond directly to Verilog entities (for example C<MODULE> and
|
||||||
NULL in the constructor, where that node (AstModule visitor) sets it, then
|
C<TASK>), but others are internal to Verialtor (for example C<NETLIST> and
|
||||||
the children are iterated, then it's cleared. Children under an AstModule
|
C<BASICDTYPE>).
|
||||||
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.
|
|
||||||
|
|
||||||
2. User() attributes. Each node has 5 ->user() number or ->userp() pointer
|
=item Address of the node
|
||||||
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:
|
|
||||||
|
|
||||||
// NODE STATE
|
A hexadecimal address of the node in memory. Useful for examining with the
|
||||||
// Cleared entire netlist
|
debugger.
|
||||||
// AstModule::user1p() // bool. True to inline this module
|
|
||||||
|
|
||||||
This says that at the AstNetlist user1ClearTree() is called. Each
|
=item Last edit number
|
||||||
AstModule's is 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
|
Of the form C<< <ennnn> >> or C<< <ennnn#> >> , where C<nnnn> is the number
|
||||||
is never being used for two different purposes.
|
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>.
|
||||||
|
|
||||||
Note that calling user#ClearTree is fast, it doesn't walk the tree, so it's
|
=item Source file and line
|
||||||
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"
|
Of the form C<< {xxnnnn} >>, where C{xx} is the filename letter (or
|
||||||
function caller to callee way. This is the second "vup" parameter that is
|
letters) and C<nnnn> is the line number within that file. The first file is
|
||||||
ignored on most of the visitor functions. V3Width does this, but it proved
|
C<a>, the 26th is C<z>, the 27th is C<aa> and so on.
|
||||||
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.)
|
|
||||||
|
|
||||||
=head1 DEBUGGING WITH GDB
|
=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 numeric, it then prints the width of the
|
||||||
|
item. This field is a sequence 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
|
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
|
under gdb and break when an error is hit or the program is about to exit.
|
||||||
exit gdb.
|
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
|
To break at a specific edit number which changed a node (presumably to find
|
||||||
what made a <e####> line in the tree dumps):
|
what made a <e####> line in the tree dumps):
|
||||||
|
|
||||||
watch AstNode::s_editCntGbl==####
|
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
|
=head1 DISTRIBUTION
|
||||||
|
|
||||||
The latest version is available from L<http://www.veripool.org/>.
|
The latest version is available from L<http://www.veripool.org/>.
|
||||||
|
|
||||||
Copyright 2008-2010 by Wilson Snyder. Verilator is free software; you can
|
Copyright 2008-2014 by Wilson Snyder. Verilator is free software; you can
|
||||||
redistribute it and/or modify it under the terms of either the GNU Lesser
|
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.
|
General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/perl -w
|
#!/usr/bin/perl -w
|
||||||
######################################################################
|
######################################################################
|
||||||
#
|
#
|
||||||
# Copyright 2007-2010 by Wilson Snyder. This package is free software; you
|
# Copyright 2007-2014 by Wilson Snyder. This package is free software; you
|
||||||
# can redistribute it and/or modify it under the terms of either the GNU
|
# 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
|
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
# Version 2.0.
|
# Version 2.0.
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/perl -w
|
#!/usr/bin/perl -w
|
||||||
######################################################################
|
######################################################################
|
||||||
#
|
#
|
||||||
# Copyright 2007-2010 by Wilson Snyder. This package is free software; you
|
# Copyright 2007-2014 by Wilson Snyder. This package is free software; you
|
||||||
# can redistribute it and/or modify it under the terms of either the GNU
|
# 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
|
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
# Version 2.0.
|
# Version 2.0.
|
||||||
|
|||||||
+2
-2
@@ -38,7 +38,7 @@ cwrite ("graph_export.cpp");
|
|||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
|
|
||||||
sub usage {
|
sub usage {
|
||||||
pod2usage(-verbose=>2, -exitval => 2);
|
pod2usage(-verbose=>2, -exitval=>2, -output=>\*STDOUT);
|
||||||
exit (1);
|
exit (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,7 +143,7 @@ Displays this message and program version and exits.
|
|||||||
|
|
||||||
=head1 DISTRIBUTION
|
=head1 DISTRIBUTION
|
||||||
|
|
||||||
Copyright 2005-2010 by Wilson Snyder. Verilator is free software; you can
|
Copyright 2005-2014 by Wilson Snyder. Verilator is free software; you can
|
||||||
redistribute it and/or modify it under the terms of either the GNU Lesser
|
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.
|
General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -43,7 +43,7 @@ dotwrite();
|
|||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
|
|
||||||
sub usage {
|
sub usage {
|
||||||
pod2usage(-verbose=>2, -exitval => 2);
|
pod2usage(-verbose=>2, -exitval=>2, -output=>\*STDOUT);
|
||||||
exit (1);
|
exit (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -184,7 +184,7 @@ Displays this message and program version and exits.
|
|||||||
|
|
||||||
=head1 DISTRIBUTION
|
=head1 DISTRIBUTION
|
||||||
|
|
||||||
Copyright 2005-2010 by Wilson Snyder. Verilator is free software; you can
|
Copyright 2005-2014 by Wilson Snyder. Verilator is free software; you can
|
||||||
redistribute it and/or modify it under the terms of either the GNU Lesser
|
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.
|
General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/perl -w
|
#!/usr/bin/perl -w
|
||||||
######################################################################
|
######################################################################
|
||||||
#
|
#
|
||||||
# Copyright 2007-2010 by Wilson Snyder. This package is free software; you
|
# Copyright 2007-2014 by Wilson Snyder. This package is free software; you
|
||||||
# can redistribute it and/or modify it under the terms of either the GNU
|
# 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
|
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
# Version 2.0.
|
# Version 2.0.
|
||||||
|
|||||||
+79
-13
@@ -12,17 +12,23 @@ use vars qw ($Debug);
|
|||||||
#======================================================================
|
#======================================================================
|
||||||
# main
|
# main
|
||||||
|
|
||||||
|
our $Opt_Stage = 0;
|
||||||
|
our $Opt_Jobs = calc_jobs();
|
||||||
|
|
||||||
autoflush STDOUT 1;
|
autoflush STDOUT 1;
|
||||||
autoflush STDERR 1;
|
autoflush STDERR 1;
|
||||||
Getopt::Long::config ("no_auto_abbrev");
|
Getopt::Long::config ("no_auto_abbrev");
|
||||||
if (! GetOptions (
|
if (! GetOptions (
|
||||||
"debug" => sub { $Debug = 1; },
|
"debug" => sub { $Debug = 1; },
|
||||||
"<>" => sub { die "%Error: Unknown parameter: $_[0]\n"; },
|
"<>" => sub { die "%Error: Unknown parameter: $_[0]\n"; },
|
||||||
|
"stage=i" => \$Opt_Stage,
|
||||||
|
"j=i" => \$Opt_Jobs,
|
||||||
)) {
|
)) {
|
||||||
die "%Error: Bad usage, try 'install_test --help'\n";
|
die "%Error: Bad usage, try 'install_test --help'\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
test();
|
test();
|
||||||
|
exit(0);
|
||||||
|
|
||||||
#######################################################################
|
#######################################################################
|
||||||
|
|
||||||
@@ -37,33 +43,74 @@ sub test {
|
|||||||
my $srcdir = getcwd();
|
my $srcdir = getcwd();
|
||||||
my $blddir = $srcdir."/test_regress/obj_dir/install_test_bld";
|
my $blddir = $srcdir."/test_regress/obj_dir/install_test_bld";
|
||||||
my $prefix = $srcdir."/test_regress/obj_dir/install_test_prefix";
|
my $prefix = $srcdir."/test_regress/obj_dir/install_test_prefix";
|
||||||
my $testdir = $srcdir."/test_regress/obj_dir/install_test_test";
|
my $testdirp= $srcdir."/test_regress/obj_dir/install_test_testp";
|
||||||
if (1) {
|
my $testdirn= $srcdir."/test_regress/obj_dir/install_test_testn";
|
||||||
|
|
||||||
|
if ($Opt_Stage <= 0) {
|
||||||
run("/bin/rm -rf $blddir");
|
run("/bin/rm -rf $blddir");
|
||||||
run("/bin/mkdir -p $blddir");
|
run("/bin/mkdir -p $blddir");
|
||||||
run("cd $blddir && $srcdir/configure --prefix $prefix");
|
run("cd $blddir && $srcdir/configure --prefix $prefix");
|
||||||
run("cd $blddir && make -j");
|
run("cd $blddir && make -j $Opt_Jobs");
|
||||||
}
|
}
|
||||||
|
|
||||||
# Install it under the prefix
|
# Install it under the prefix
|
||||||
if (1) {
|
if ($Opt_Stage <= 1) {
|
||||||
run("/bin/rm -rf $prefix");
|
run("/bin/rm -rf $prefix");
|
||||||
run("/bin/mkdir -p $prefix");
|
run("/bin/mkdir -p $prefix");
|
||||||
run("cd $blddir && make install");
|
run("cd $blddir && make install");
|
||||||
|
run("test -e $prefix/share/man/man1/verilator.1");
|
||||||
|
run("test -e $prefix/share/verilator/examples/test_c/Makefile");
|
||||||
|
run("test -e $prefix/share/verilator/include/verilated.h");
|
||||||
|
run("test -e $prefix/bin/verilator");
|
||||||
|
run("test -e $prefix/bin/verilator_bin");
|
||||||
|
run("test -e $prefix/bin/verilator_bin_dbg");
|
||||||
|
run("test -e $prefix/bin/verilator_profcfunc");
|
||||||
}
|
}
|
||||||
|
|
||||||
# Run a test using just the path
|
# Run a test using just the path
|
||||||
if (1) {
|
if ($Opt_Stage <= 2) {
|
||||||
run("/bin/rm -rf $testdir");
|
my $dir = $testdirp;
|
||||||
run("/bin/mkdir -p $testdir");
|
run("/bin/rm -rf $dir");
|
||||||
|
run("/bin/mkdir -p $dir");
|
||||||
my $bin1 = $prefix."/bin";
|
my $bin1 = $prefix."/bin";
|
||||||
my $bin2 = $prefix."/share/bin";
|
my $bin2 = $prefix."/share/bin";
|
||||||
IO::File->new(">$testdir/foo.v")->print('module t; initial begin $display("HELLO WORLD"); end endmodule'."\n");
|
write_verilog($dir);
|
||||||
run("cd $testdir && PATH=$bin1:$bin2:\$PATH verilator --cc --exe foo.v");
|
run("cd $dir && PATH=$bin1:$bin2:\$PATH verilator --cc foo.v --exe foo.cpp");
|
||||||
run("cd $testdir/obj_dir && PATH=$bin1:$bin2:\$PATH make -f Vfoo.mk");
|
run("cd $dir/obj_dir && PATH=$bin1:$bin2:\$PATH make -f Vfoo.mk");
|
||||||
#Need .c file for this to work
|
run("cd $dir && PATH=$bin1:$bin2:\$PATH obj_dir/Vfoo");
|
||||||
#run("cd $testdir && PATH=$bin1:$bin2:\$PATH obj_dir/Vfoo");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Run a test using exact path to binary
|
||||||
|
if ($Opt_Stage <= 3) {
|
||||||
|
my $dir = $testdirn;
|
||||||
|
run("/bin/rm -rf $dir");
|
||||||
|
run("/bin/mkdir -p $dir");
|
||||||
|
write_verilog($dir);
|
||||||
|
my $bin1 = $prefix."/bin";
|
||||||
|
my $bin2 = $prefix."/share/bin";
|
||||||
|
run("cd $dir && $bin1/verilator --cc foo.v --exe foo.cpp");
|
||||||
|
run("cd $dir/obj_dir && make -f Vfoo.mk");
|
||||||
|
run("cd $dir/obj_dir && ./Vfoo");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub write_verilog {
|
||||||
|
my $dir = shift;
|
||||||
|
IO::File->new(">$dir/foo.v")->print('module t; initial begin $display("HELLO WORLD"); $finish; end endmodule'."\n");
|
||||||
|
my $fh = IO::File->new(">$dir/foo.cpp");
|
||||||
|
$fh->print('#include "Vfoo.h"' ,"\n");
|
||||||
|
$fh->print('unsigned int main_time = 0;' ,"\n");
|
||||||
|
$fh->print('double sc_time_stamp () {' ,"\n");
|
||||||
|
$fh->print(' return main_time;' ,"\n");
|
||||||
|
$fh->print('}' ,"\n");
|
||||||
|
$fh->print('int main() {' ,"\n");
|
||||||
|
$fh->print(' Vfoo *top = new Vfoo;' ,"\n");
|
||||||
|
$fh->print(' while (!Verilated::gotFinish()) {',"\n");
|
||||||
|
$fh->print(' top->eval();' ,"\n");
|
||||||
|
$fh->print(' main_time++;' ,"\n");
|
||||||
|
$fh->print(' }' ,"\n");
|
||||||
|
$fh->print(' top->final();' ,"\n");
|
||||||
|
$fh->print('}' ,"\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
sub cleanenv {
|
sub cleanenv {
|
||||||
@@ -77,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 {
|
sub run {
|
||||||
# Run a system command, check errors
|
# Run a system command, check errors
|
||||||
my $command = shift;
|
my $command = shift;
|
||||||
@@ -113,11 +170,20 @@ required.
|
|||||||
|
|
||||||
Displays this message and program version and exits.
|
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
|
=back
|
||||||
|
|
||||||
=head1 DISTRIBUTION
|
=head1 DISTRIBUTION
|
||||||
|
|
||||||
Copyright 2009-2010 by Wilson Snyder. This package is free software; you
|
Copyright 2009-2014 by Wilson Snyder. This package is free software; you
|
||||||
can redistribute it and/or modify it under the terms of either the GNU
|
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
|
Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
Version 2.0.
|
Version 2.0.
|
||||||
|
|||||||
Executable
+47
@@ -0,0 +1,47 @@
|
|||||||
|
#!/usr/bin/perl -w
|
||||||
|
# See copyright, etc in below POD section.
|
||||||
|
######################################################################
|
||||||
|
|
||||||
|
require 5.006_001;
|
||||||
|
use strict;
|
||||||
|
|
||||||
|
#======================================================================
|
||||||
|
# main
|
||||||
|
|
||||||
|
eval `modulecmd perl add axiom-athdl`;
|
||||||
|
exec('atsim',@ARGV);
|
||||||
|
|
||||||
|
#######################################################################
|
||||||
|
__END__
|
||||||
|
|
||||||
|
=pod
|
||||||
|
|
||||||
|
=head1 NAME
|
||||||
|
|
||||||
|
invoke_atsim - Invoke tool under "modules" command
|
||||||
|
|
||||||
|
=head1 SYNOPSIS
|
||||||
|
|
||||||
|
invoke_atsim {ncv arguments}
|
||||||
|
|
||||||
|
=head1 DESCRIPTION
|
||||||
|
|
||||||
|
=head1 DISTRIBUTION
|
||||||
|
|
||||||
|
Copyright 2005-2014 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.
|
||||||
|
|
||||||
|
=head1 AUTHORS
|
||||||
|
|
||||||
|
Wilson Snyder <[email protected]>
|
||||||
|
|
||||||
|
=head1 SEE ALSO
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
######################################################################
|
||||||
|
### Local Variables:
|
||||||
|
### compile-command: "./invoke_atsim -help"
|
||||||
|
### End:
|
||||||
+2
-14
@@ -8,21 +8,9 @@ use strict;
|
|||||||
#======================================================================
|
#======================================================================
|
||||||
# main
|
# main
|
||||||
|
|
||||||
delete $ENV{MODULE_VERSION};
|
eval `modulecmd perl add cds-ius`;
|
||||||
_setup_modules();
|
|
||||||
module('add','cadence-ius');
|
|
||||||
exec('iccr',@ARGV);
|
exec('iccr',@ARGV);
|
||||||
|
|
||||||
#######################################################################
|
|
||||||
# Modules package
|
|
||||||
|
|
||||||
sub _setup_modules {
|
|
||||||
# Load the 'module' command into the environment
|
|
||||||
my $init = "$ENV{MODULESHOME}/init/perl";
|
|
||||||
(-f $init) or die "%Error: Script not found: $init,";
|
|
||||||
require $init;
|
|
||||||
}
|
|
||||||
|
|
||||||
#######################################################################
|
#######################################################################
|
||||||
__END__
|
__END__
|
||||||
|
|
||||||
@@ -40,7 +28,7 @@ invoke_iccr - Invoke tool under "modules" command
|
|||||||
|
|
||||||
=head1 DISTRIBUTION
|
=head1 DISTRIBUTION
|
||||||
|
|
||||||
Copyright 2007-2010 by Wilson Snyder. This package is free software; you
|
Copyright 2007-2014 by Wilson Snyder. This package is free software; you
|
||||||
can redistribute it and/or modify it under the terms of either the GNU
|
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
|
Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
Version 2.0.
|
Version 2.0.
|
||||||
|
|||||||
+2
-14
@@ -8,21 +8,9 @@ use strict;
|
|||||||
#======================================================================
|
#======================================================================
|
||||||
# main
|
# main
|
||||||
|
|
||||||
delete $ENV{MODULE_VERSION};
|
eval `modulecmd perl add cds-ius`;
|
||||||
_setup_modules();
|
|
||||||
module('add','cadence-ius');
|
|
||||||
exec('ncverilog',@ARGV);
|
exec('ncverilog',@ARGV);
|
||||||
|
|
||||||
#######################################################################
|
|
||||||
# Modules package
|
|
||||||
|
|
||||||
sub _setup_modules {
|
|
||||||
# Load the 'module' command into the environment
|
|
||||||
my $init = "$ENV{MODULESHOME}/init/perl";
|
|
||||||
(-f $init) or die "%Error: Script not found: $init,";
|
|
||||||
require $init;
|
|
||||||
}
|
|
||||||
|
|
||||||
#######################################################################
|
#######################################################################
|
||||||
__END__
|
__END__
|
||||||
|
|
||||||
@@ -40,7 +28,7 @@ invoke_ncverilog - Invoke tool under "modules" command
|
|||||||
|
|
||||||
=head1 DISTRIBUTION
|
=head1 DISTRIBUTION
|
||||||
|
|
||||||
Copyright 2005-2010 by Wilson Snyder. This package is free software; you
|
Copyright 2005-2014 by Wilson Snyder. This package is free software; you
|
||||||
can redistribute it and/or modify it under the terms of either the GNU
|
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
|
Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
Version 2.0.
|
Version 2.0.
|
||||||
|
|||||||
+2
-14
@@ -8,21 +8,9 @@ use strict;
|
|||||||
#======================================================================
|
#======================================================================
|
||||||
# main
|
# main
|
||||||
|
|
||||||
delete $ENV{MODULE_VERSION};
|
eval `modulecmd perl add synopsys-vcs_mx`;
|
||||||
_setup_modules();
|
|
||||||
module('add','synopsys-vcs');
|
|
||||||
exec('vcs',@ARGV);
|
exec('vcs',@ARGV);
|
||||||
|
|
||||||
#######################################################################
|
|
||||||
# Modules package
|
|
||||||
|
|
||||||
sub _setup_modules {
|
|
||||||
# Load the 'module' command into the environment
|
|
||||||
my $init = "$ENV{MODULESHOME}/init/perl";
|
|
||||||
(-f $init) or die "%Error: Script not found: $init,";
|
|
||||||
require $init;
|
|
||||||
}
|
|
||||||
|
|
||||||
#######################################################################
|
#######################################################################
|
||||||
__END__
|
__END__
|
||||||
|
|
||||||
@@ -40,7 +28,7 @@ invoke_vcs - Invoke tool under "modules" command
|
|||||||
|
|
||||||
=head1 DISTRIBUTION
|
=head1 DISTRIBUTION
|
||||||
|
|
||||||
Copyright 2005-2010 by Wilson Snyder. This package is free software; you
|
Copyright 2005-2014 by Wilson Snyder. This package is free software; you
|
||||||
can redistribute it and/or modify it under the terms of either the GNU
|
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
|
Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
Version 2.0.
|
Version 2.0.
|
||||||
|
|||||||
+3
-1
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/perl -w
|
#!/usr/bin/perl -w
|
||||||
######################################################################
|
######################################################################
|
||||||
#
|
#
|
||||||
# Copyright 2010-2010 by Wilson Snyder. This package is free software; you
|
# Copyright 2010-2014 by Wilson Snyder. This package is free software; you
|
||||||
# can redistribute it and/or modify it under the terms of either the GNU
|
# 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
|
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
# Version 2.0.
|
# Version 2.0.
|
||||||
@@ -81,6 +81,7 @@ sub prep {
|
|||||||
$line =~ s/SP_NOTICE.*// if $sp;
|
$line =~ s/SP_NOTICE.*// if $sp;
|
||||||
$line =~ s/vl_fatal.*// if !$sp;
|
$line =~ s/vl_fatal.*// if !$sp;
|
||||||
$line =~ s/VL_PRINT.*// if !$sp;
|
$line =~ s/VL_PRINT.*// if !$sp;
|
||||||
|
$line =~ s/Copyright \d+-\d+/Copyright #-#/g;
|
||||||
|
|
||||||
push @wf, $line;
|
push @wf, $line;
|
||||||
|
|
||||||
@@ -126,6 +127,7 @@ sub prep {
|
|||||||
#
|
#
|
||||||
$wholefile =~ s/\b(uint[0-9]+_t)/vl$1/g;
|
$wholefile =~ s/\b(uint[0-9]+_t)/vl$1/g;
|
||||||
$wholefile =~ s/%ll/%" VL_PRI64 "/g;
|
$wholefile =~ s/%ll/%" VL_PRI64 "/g;
|
||||||
|
$wholefile =~ s/\(long long unsigned\)n/ n/g; # printQuad
|
||||||
#
|
#
|
||||||
$wholefile =~ s/\bSP_SC_BV/VL_SC_BV/g;
|
$wholefile =~ s/\bSP_SC_BV/VL_SC_BV/g;
|
||||||
$wholefile =~ s/\bSP_UNLIKELY/VL_UNLIKELY/g;
|
$wholefile =~ s/\bSP_UNLIKELY/VL_UNLIKELY/g;
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ print '(query-replace-regexp "(\\([0-9a-z_]+\\))" "\\1" nil nil nil)',"\n";
|
|||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
|
|
||||||
sub usage {
|
sub usage {
|
||||||
pod2usage(-verbose=>2, -exitval => 2);
|
pod2usage(-verbose=>2, -exitval=>2, -output=>\*STDOUT);
|
||||||
exit (1);
|
exit (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -256,7 +256,7 @@ sub gentree {
|
|||||||
'TRACE' => sub { p "TRACE what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
|
'TRACE' => sub { p "TRACE what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
|
||||||
'UCFUNC' => sub { p '$c(';p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p ")"; },
|
'UCFUNC' => sub { p '$c(';p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p ")"; },
|
||||||
'UCSTMT' => sub { p '$c(';p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p ");";nl; },
|
'UCSTMT' => sub { p '$c(';p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p ");";nl; },
|
||||||
'UNARYMIN' => sub { p " -";p1; },
|
'NEGATE' => sub { p " -";p1; },
|
||||||
'VAR' => sub { p_var(); },
|
'VAR' => sub { p_var(); },
|
||||||
'VARPIN' => sub { p "VARPIN what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
|
'VARPIN' => sub { p "VARPIN what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
|
||||||
'VARREF' => sub { a1; },
|
'VARREF' => sub { a1; },
|
||||||
@@ -331,7 +331,7 @@ Displays this message and program version and exits.
|
|||||||
|
|
||||||
=head1 DISTRIBUTION
|
=head1 DISTRIBUTION
|
||||||
|
|
||||||
Copyright 2005-2010 by Wilson Snyder. Verilator is free software; you can
|
Copyright 2005-2014 by Wilson Snyder. Verilator is free software; you can
|
||||||
redistribute it and/or modify it under the terms of either the GNU Lesser
|
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.
|
General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||||
|
|
||||||
|
|||||||
+62
-40
@@ -9,7 +9,7 @@ This is the Verilator Package README file.
|
|||||||
|
|
||||||
=head1 DISTRIBUTION
|
=head1 DISTRIBUTION
|
||||||
|
|
||||||
This package is Copyright 2003-2010 by Wilson Snyder. (Report bugs to
|
This package is Copyright 2003-2014 by Wilson Snyder. (Report bugs to
|
||||||
L<http://www.veripool.org/>.)
|
L<http://www.veripool.org/>.)
|
||||||
|
|
||||||
Verilator is free software; you can redistribute it and/or modify it under
|
Verilator is free software; you can redistribute it and/or modify it under
|
||||||
@@ -24,14 +24,14 @@ more details.
|
|||||||
|
|
||||||
=head1 DESCRIPTION
|
=head1 DESCRIPTION
|
||||||
|
|
||||||
Verilator converts synthesizable (not behavioral) Verilog code into C++ or
|
Verilator converts synthesizable (generally not behavioral) Verilog code
|
||||||
SystemC code. It is not a complete simulator, just a translator.
|
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
|
Verilator is invoked with parameters similar to GCC or Synopsys's VCS. It
|
||||||
reads the specified Verilog code, lints it, and optionally adds coverage
|
reads the specified Verilog code, lints it, and optionally adds coverage
|
||||||
code. For C++ format, it outputs .cpp and .h files. For SystemC format,
|
code. For C++ format, it outputs .cpp and .h files. For SystemC format,
|
||||||
it outputs .sp files for the SystemPerl preprocessor available at
|
it outputs .cpp and .h files using the standard SystemC headers.
|
||||||
http://www.veripool.org.
|
|
||||||
|
|
||||||
The resulting files are then compiled with C++. The user writes a little
|
The resulting files are then compiled with C++. The user writes a little
|
||||||
C++ wrapper file, which instantiates the top level module. This is
|
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
|
=head1 SUPPORTED SYSTEMS
|
||||||
|
|
||||||
Verilator is developed and has primary testing on:
|
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
|
||||||
SuSE 11.1 AMD64 i686-linux-2.6.27, GCC 4.3.2
|
with minor porting on any Linix-ish platform. Verilator also works on
|
||||||
|
Windows under Cygwin, and Windows under MinGW (gcc -mno-cygwin). Verilated
|
||||||
Versions have also built on Redhat Linux, Macs OS-X, HPUX and Solaris. It
|
output (not Verilator itself) compiles under MSVC++ 2008 and newer.
|
||||||
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.
|
|
||||||
|
|
||||||
=head1 INSTALLATION
|
=head1 INSTALLATION
|
||||||
|
|
||||||
@@ -71,16 +68,11 @@ Download the latest package from that site, and decompress.
|
|||||||
=item
|
=item
|
||||||
|
|
||||||
If you will be using SystemC (vs straight C++ output), download SystemC
|
If you will be using SystemC (vs straight C++ output), download SystemC
|
||||||
2.0.1 from L<http://www.systemc.org>. Follow their installation
|
from L<http://www.systemc.org>. Follow their installation instructions.
|
||||||
instructions. As described in the System-Perl README, you will need to set
|
You will need to set SYSTEMC_INCLUDE to point to the include directory with
|
||||||
SYSTEMC and/or SYSTEMC_KIT to point to this download. Also, set
|
systemc.h in it, and SYSTEMC_LIBDIR to points to the directory with
|
||||||
SYSTEMC_ARCH to the architecture name you used with SystemC, generally
|
libsystemc.a in it. (Older installations may set SYSTEMC and SYSTEMC_ARCH
|
||||||
'linux' or 'cygwin'.
|
instead.)
|
||||||
|
|
||||||
=item
|
|
||||||
|
|
||||||
If you will be using SystemPerl or coverage, download and install
|
|
||||||
Verilog-Perl, L<http://www.veripool.org/verilog-perl>.
|
|
||||||
|
|
||||||
=item
|
=item
|
||||||
|
|
||||||
@@ -92,26 +84,59 @@ headers.
|
|||||||
|
|
||||||
=item
|
=item
|
||||||
|
|
||||||
|
You will need the C<flex> and C<bison> packages installed.
|
||||||
|
|
||||||
|
=item
|
||||||
|
|
||||||
C<cd> to the Verilator directory containing this README.
|
C<cd> to the Verilator directory containing this README.
|
||||||
|
|
||||||
=item
|
=item
|
||||||
|
|
||||||
You now have to decide how you're going to eventually install the kit.
|
You now have to decide how you're going to eventually install the kit.
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
=item 1.
|
||||||
|
|
||||||
Our personal favorite is to always run Verilator from the kit directory.
|
Our personal favorite is to always run Verilator from the kit directory.
|
||||||
This allows the easiest experimentation and upgrading. It's also how most
|
This allows the easiest experimentation and upgrading. It's also how most
|
||||||
EDA tools operate; you just 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
|
export VERILATOR_ROOT=`pwd` # if your shell is bash
|
||||||
setenv VERILATOR_ROOT `pwd` # if your shell is csh
|
setenv VERILATOR_ROOT `pwd` # if your shell is csh
|
||||||
./configure
|
./configure
|
||||||
|
|
||||||
|
=item 2.
|
||||||
|
|
||||||
|
To install globally onto a "cad" disk with multiple versions of every tool,
|
||||||
|
and add it to path using Modules/modulecmd:
|
||||||
|
|
||||||
|
unset VERILATOR_ROOT # if your shell is bash
|
||||||
|
unsetenv VERILATOR_ROOT # if your shell is csh
|
||||||
|
# For the tarball, use the version number instead of git describe
|
||||||
|
./configure --prefix /CAD_DISK/verilator/`git describe | sed "s/verilator_//"`
|
||||||
|
|
||||||
|
After installing you'll want a module file like the following:
|
||||||
|
|
||||||
|
set install_root /CAD_DISK/verilator/{version-number-used-above}
|
||||||
|
setenv VERILATOR_ROOT $install_root
|
||||||
|
prepend-path PATH $install_root/bin
|
||||||
|
prepend-path MANPATH $install_root/man
|
||||||
|
|
||||||
|
=item 3.
|
||||||
|
|
||||||
The next option is to install it globally, using the normal system paths:
|
The next option is to install it globally, using the normal system paths:
|
||||||
|
|
||||||
unset VERILATOR_ROOT # if your shell is bash
|
unset VERILATOR_ROOT # if your shell is bash
|
||||||
unsetenv VERILATOR_ROOT # if your shell is csh
|
unsetenv VERILATOR_ROOT # if your shell is csh
|
||||||
./configure
|
./configure
|
||||||
|
|
||||||
|
=item 4.
|
||||||
|
|
||||||
Alternatively you can configure a prefix that install will populate, as
|
Alternatively you can configure a prefix that install will populate, as
|
||||||
most GNU tools support:
|
most GNU tools support:
|
||||||
|
|
||||||
@@ -119,21 +144,19 @@ most GNU tools support:
|
|||||||
unsetenv VERILATOR_ROOT # if your shell is csh
|
unsetenv VERILATOR_ROOT # if your shell is csh
|
||||||
./configure --prefix /opt/verilator-VERSION
|
./configure --prefix /opt/verilator-VERSION
|
||||||
|
|
||||||
Finally, if you are configuring Verilator to be part of a RPM or other
|
Then after installing you will need to add /opt/verilator-VERSION/bin to
|
||||||
distribution package system, you may want to tune the various install
|
PATH.
|
||||||
directories and use the --enable-defenv configure flag. This will take the
|
|
||||||
current value of VERILATOR_ROOT, SYSTEMC, SYSTEMC_ARCH, SYSTEMPERL, and
|
=back
|
||||||
SYSTEMPERL_INCLUDE and build them as defaults into the executable.
|
|
||||||
|
|
||||||
=item
|
=item
|
||||||
|
|
||||||
Type C<make> to compile Verilator.
|
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
|
Configure with C<--enable-longtests> for more complete developer tests.
|
||||||
Bit::Vector Perl package. You will need to install it and SystemPerl if
|
Additional packages may be required for these tests.
|
||||||
you want all tests to pass.
|
|
||||||
|
|
||||||
You may get a error about a typedef conflict for uint32_t. Edit
|
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
|
verilated.h to change the typedef to work, probably to @samp{typedef
|
||||||
@@ -141,16 +164,15 @@ unsigned long uint32_t;}.
|
|||||||
|
|
||||||
=item
|
=item
|
||||||
|
|
||||||
If you used the VERILATOR_ROOT sheme you're done. Programs should set the
|
If you used the VERILATOR_ROOT scheme you're done. Programs should set the
|
||||||
environment variable VERILATOR_ROOT to point to this distribution, then
|
environment variable VERILATOR_ROOT to point to this distribution, then
|
||||||
execute $VERILATOR_ROOT/bin/verilator, which will find the path to all
|
execute $VERILATOR_ROOT/bin/verilator, which will find the path to all
|
||||||
needed files.
|
needed files.
|
||||||
|
|
||||||
If you used the prefix scheme, now do a C<make install>.
|
If you used the prefix scheme, now do a C<make install>. To run verilator,
|
||||||
|
have the verilator binary directory in your PATH (this should already be
|
||||||
Verilator assumes you did a make in the SystemC kit directory. If not, you
|
true if using the default configure), and make sure VERILATOR_ROOT is not
|
||||||
will need to populate C<$SYSTEMC/include> and C<$SYSTEMC/lib-linux>
|
set.
|
||||||
appropriately.
|
|
||||||
|
|
||||||
=back
|
=back
|
||||||
|
|
||||||
@@ -169,7 +191,7 @@ The directories in the kit after de-taring are as follows:
|
|||||||
bin/verilator => Compiler Wrapper invoked to Verilate code
|
bin/verilator => Compiler Wrapper invoked to Verilate code
|
||||||
include/ => Files that should be in your -I compiler path
|
include/ => Files that should be in your -I compiler path
|
||||||
include/verilated*.cpp => Global routines to link into your simulator
|
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.v => Stub defines for linting
|
||||||
include/verilated.mk => Common makefile
|
include/verilated.mk => Common makefile
|
||||||
src/ => Translator source code
|
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-2010 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-2014 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
|
||||||
+20
-25
@@ -7,7 +7,7 @@
|
|||||||
#
|
#
|
||||||
#*****************************************************************************
|
#*****************************************************************************
|
||||||
#
|
#
|
||||||
# Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
# Copyright 2003-2014 by Wilson Snyder. This program is free software; you can
|
||||||
# redistribute it and/or modify it under the terms of either the GNU
|
# redistribute it and/or modify it under the terms of either the GNU
|
||||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
# Version 2.0.
|
# Version 2.0.
|
||||||
@@ -24,6 +24,7 @@
|
|||||||
srcdir = @srcdir@
|
srcdir = @srcdir@
|
||||||
VPATH = @srcdir@
|
VPATH = @srcdir@
|
||||||
PERL = @PERL@
|
PERL = @PERL@
|
||||||
|
EXEEXT = @EXEEXT@
|
||||||
|
|
||||||
#### End of system configuration section. ####
|
#### End of system configuration section. ####
|
||||||
|
|
||||||
@@ -32,21 +33,11 @@ default: dbg opt
|
|||||||
debug: dbg
|
debug: dbg
|
||||||
optimize: opt
|
optimize: opt
|
||||||
|
|
||||||
ifeq ($(OBJCACHE_HOSTS),)
|
ifneq ($(words $(CURDIR)),1)
|
||||||
ifneq ($(SLCHOOSED_HOST),)
|
$(error Unsupported: GNU Make cannot build in directories containing spaces, build elsewhere: '$(CURDIR)')
|
||||||
ifeq ($(VERILATOR_AUTHOR_SITE),1)
|
|
||||||
export OBJCACHE_HOSTS := $(shell rschedule --no-allow-reserved --similar hostnames)
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(OBJCACHE_JOBS),)
|
UNDER_GIT = $(wildcard ${srcdir}/../.git/logs/HEAD)
|
||||||
ifneq ($(OBJCACHE_HOSTS),)
|
|
||||||
export OBJCACHE_JOBS := -j $(shell objcache --jobs "$(OBJCACHE_HOSTS)")
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
|
|
||||||
UNDER_GIT = $(wildcard ../.git/logs/HEAD)
|
|
||||||
|
|
||||||
#*********************************************************************
|
#*********************************************************************
|
||||||
|
|
||||||
@@ -61,26 +52,27 @@ opt: ../verilator_bin
|
|||||||
ifeq ($(VERILATOR_NO_OPT_BUILD),1) # Faster laptop development... One build
|
ifeq ($(VERILATOR_NO_OPT_BUILD),1) # Faster laptop development... One build
|
||||||
../verilator_bin: ../verilator_bin_dbg
|
../verilator_bin: ../verilator_bin_dbg
|
||||||
-rm -rf $@ $@.exe
|
-rm -rf $@ $@.exe
|
||||||
-cp -p $< $@
|
-cp -p $<$(EXEEXT) $@$(EXEEXT)
|
||||||
-cp -p $<.exe $@.exe
|
|
||||||
else
|
else
|
||||||
../verilator_bin: obj_opt prefiles
|
../verilator_bin: obj_opt prefiles
|
||||||
cd obj_opt && $(MAKE) -j 1 TGT=../$@ -f ../Makefile_obj serial
|
cd obj_opt && $(MAKE) -j 1 TGT=../$@ -f ../Makefile_obj serial
|
||||||
cd obj_opt && $(MAKE) $(OBJCACHE_JOBS) TGT=../$@ -f ../Makefile_obj
|
cd obj_opt && $(MAKE) TGT=../$@ -f ../Makefile_obj
|
||||||
endif
|
endif
|
||||||
|
|
||||||
dbg: ../verilator_bin_dbg
|
dbg: ../verilator_bin_dbg
|
||||||
../verilator_bin_dbg: obj_dbg prefiles
|
../verilator_bin_dbg: obj_dbg prefiles
|
||||||
cd obj_dbg && $(MAKE) -j 1 TGT=../$@ VL_DEBUG=1 -f ../Makefile_obj serial
|
cd obj_dbg && $(MAKE) -j 1 TGT=../$@ VL_DEBUG=1 -f ../Makefile_obj serial
|
||||||
cd obj_dbg && $(MAKE) $(OBJCACHE_JOBS) TGT=../$@ VL_DEBUG=1 -f ../Makefile_obj
|
cd obj_dbg && $(MAKE) TGT=../$@ VL_DEBUG=1 -f ../Makefile_obj
|
||||||
|
|
||||||
prefiles::
|
prefiles::
|
||||||
|
|
||||||
ifneq ($(UNDER_GIT),) # If local git tree... Else don't burden users
|
|
||||||
prefiles:: config_rev.h
|
prefiles:: config_rev.h
|
||||||
# This output goes into srcdir, as we need to distribute it as part of the kit.
|
ifneq ($(UNDER_GIT),) # If local git tree... Else don't burden users
|
||||||
config_rev.h: config_rev.pl ../.git/logs/HEAD
|
# This output goes into srcdir if locally configured, as we need to distribute it as part of the kit.
|
||||||
$(PERL) config_rev.pl . >$@
|
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
|
endif
|
||||||
|
|
||||||
maintainer-copy::
|
maintainer-copy::
|
||||||
@@ -92,3 +84,6 @@ clean mostlyclean distclean maintainer-clean::
|
|||||||
|
|
||||||
distclean maintainer-clean::
|
distclean maintainer-clean::
|
||||||
-rm -f Makefile Makefile_obj config_build.h
|
-rm -f Makefile Makefile_obj config_build.h
|
||||||
|
|
||||||
|
maintainer-clean::
|
||||||
|
-rm -f config_rev.h
|
||||||
|
|||||||
+28
-22
@@ -7,7 +7,7 @@
|
|||||||
#
|
#
|
||||||
#*****************************************************************************
|
#*****************************************************************************
|
||||||
#
|
#
|
||||||
# Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
# Copyright 2003-2014 by Wilson Snyder. This program is free software; you can
|
||||||
# redistribute it and/or modify it under the terms of either the GNU
|
# redistribute it and/or modify it under the terms of either the GNU
|
||||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
# Version 2.0.
|
# Version 2.0.
|
||||||
@@ -27,7 +27,7 @@ config_srcdir = @srcdir@
|
|||||||
ifeq ($(config_srcdir),.)
|
ifeq ($(config_srcdir),.)
|
||||||
srcdir = ..
|
srcdir = ..
|
||||||
else # Run an experiment
|
else # Run an experiment
|
||||||
ifeq ($(shell -e $(config_srcdir)/../Makefile_obj.in),)
|
ifeq ($(wildcard $(config_srcdir)/../Makefile_obj.in),)
|
||||||
srcdir = $(config_srcdir)
|
srcdir = $(config_srcdir)
|
||||||
else
|
else
|
||||||
srcdir = $(config_srcdir)/..
|
srcdir = $(config_srcdir)/..
|
||||||
@@ -57,9 +57,11 @@ datarootdir = @datarootdir@
|
|||||||
pkgdatadir = @pkgdatadir@
|
pkgdatadir = @pkgdatadir@
|
||||||
|
|
||||||
# Compile options
|
# Compile options
|
||||||
|
CFG_WITH_CCWARN = @CFG_WITH_CCWARN@
|
||||||
CFG_WITH_DEFENV = @CFG_WITH_DEFENV@
|
CFG_WITH_DEFENV = @CFG_WITH_DEFENV@
|
||||||
CPPFLAGSNOWALL += @CPPFLAGS@
|
CPPFLAGS += @CPPFLAGS@
|
||||||
LDFLAGS += @LDFLAGS@
|
LDFLAGS += @LDFLAGS@
|
||||||
|
EXEEXT = @EXEEXT@
|
||||||
|
|
||||||
#### End of system configuration section. ####
|
#### End of system configuration section. ####
|
||||||
|
|
||||||
@@ -85,17 +87,18 @@ endif
|
|||||||
# -lfl not needed as Flex invoked with %nowrap option
|
# -lfl not needed as Flex invoked with %nowrap option
|
||||||
LIBS = -lm
|
LIBS = -lm
|
||||||
|
|
||||||
CPPFLAGSNOWALL += -MMD
|
CPPFLAGS += -MMD
|
||||||
CPPFLAGSNOWALL += -I. -I$(bldsrc) -I$(srcdir) -I$(incdir)
|
CPPFLAGS += -I. -I$(bldsrc) -I$(srcdir) -I$(incdir)
|
||||||
CPPFLAGSNOWALL += -DYYDEBUG # Required to get nice error messages
|
CPPFLAGS += -DYYDEBUG # Required to get nice error messages
|
||||||
#CPPFLAGSNOWALL += -DVL_LEAK_CHECKS # If running valgrind or other hunting tool
|
#CPPFLAGS += -DVL_LEAK_CHECKS # If running valgrind or other hunting tool
|
||||||
CPPFLAGSNOWALL += $(COPT)
|
CPPFLAGS += $(COPT)
|
||||||
CPPFLAGS = $(CPPFLAGSNOWALL)
|
CPPFLAGS += -MP # Only works on recent GCC versions
|
||||||
ifeq ($(VERILATOR_AUTHOR_SITE),1) # Local... Else don't burden users
|
ifeq ($(CFG_WITH_CCWARN),yes) # Local... Else don't burden users
|
||||||
CPPFLAGSNOWALL += -MP # Only works on recent GCC versions
|
|
||||||
CPPFLAGS += -W -Wall -Wno-unused-parameter -Wno-char-subscripts -Werror
|
CPPFLAGS += -W -Wall -Wno-unused-parameter -Wno-char-subscripts -Werror
|
||||||
#CPPFLAGS += -pedantic-errors
|
#CPPFLAGS += -pedantic-errors
|
||||||
endif
|
endif
|
||||||
|
CPPFLAGSWALL = $(CPPFLAGS)
|
||||||
|
CPPFLAGSNOWALL = $(CPPFLAGS) -Wno-unused
|
||||||
|
|
||||||
ifneq ($(SYSTEMPERL),) # Intuit SYSTEMPERL_INCLUDE as it's new
|
ifneq ($(SYSTEMPERL),) # Intuit SYSTEMPERL_INCLUDE as it's new
|
||||||
SYSTEMPERL_INCLUDE ?= $(SYSTEMPERL)/src
|
SYSTEMPERL_INCLUDE ?= $(SYSTEMPERL)/src
|
||||||
@@ -108,6 +111,8 @@ endif
|
|||||||
ifeq ($(CFG_WITH_DEFENV),yes)
|
ifeq ($(CFG_WITH_DEFENV),yes)
|
||||||
CPPFLAGS += -DDEFENV_SYSTEMC=\"$(SYSTEMC)\"
|
CPPFLAGS += -DDEFENV_SYSTEMC=\"$(SYSTEMC)\"
|
||||||
CPPFLAGS += -DDEFENV_SYSTEMC_ARCH=\"$(SYSTEMC_ARCH)\"
|
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=\"$(SYSTEMPERL)\"
|
||||||
CPPFLAGS += -DDEFENV_SYSTEMPERL_INCLUDE=\"$(SYSTEMPERL_INCLUDE)\"
|
CPPFLAGS += -DDEFENV_SYSTEMPERL_INCLUDE=\"$(SYSTEMPERL_INCLUDE)\"
|
||||||
ifeq ($(VERILATOR_ROOT),) # Use what we're given, or intuit
|
ifeq ($(VERILATOR_ROOT),) # Use what we're given, or intuit
|
||||||
@@ -121,6 +126,7 @@ HEADERS = $(wildcard V*.h v*.h)
|
|||||||
|
|
||||||
ASTGEN = $(srcdir)/astgen
|
ASTGEN = $(srcdir)/astgen
|
||||||
BISONPRE = $(srcdir)/bisonpre
|
BISONPRE = $(srcdir)/bisonpre
|
||||||
|
FLEXFIX = $(srcdir)/flexfix
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
#### Top level
|
#### Top level
|
||||||
@@ -176,6 +182,7 @@ RAW_OBJS = \
|
|||||||
V3EmitCSyms.o \
|
V3EmitCSyms.o \
|
||||||
V3EmitMk.o \
|
V3EmitMk.o \
|
||||||
V3EmitV.o \
|
V3EmitV.o \
|
||||||
|
V3EmitXml.o \
|
||||||
V3Error.o \
|
V3Error.o \
|
||||||
V3Expand.o \
|
V3Expand.o \
|
||||||
V3File.o \
|
V3File.o \
|
||||||
@@ -191,11 +198,11 @@ RAW_OBJS = \
|
|||||||
V3Inst.o \
|
V3Inst.o \
|
||||||
V3Life.o \
|
V3Life.o \
|
||||||
V3LifePost.o \
|
V3LifePost.o \
|
||||||
V3Link.o \
|
|
||||||
V3LinkCells.o \
|
V3LinkCells.o \
|
||||||
V3LinkDot.o \
|
V3LinkDot.o \
|
||||||
V3LinkLevel.o \
|
V3LinkJump.o \
|
||||||
V3LinkLValue.o \
|
V3LinkLValue.o \
|
||||||
|
V3LinkLevel.o \
|
||||||
V3LinkParse.o \
|
V3LinkParse.o \
|
||||||
V3LinkResolve.o \
|
V3LinkResolve.o \
|
||||||
V3Localize.o \
|
V3Localize.o \
|
||||||
@@ -207,18 +214,19 @@ RAW_OBJS = \
|
|||||||
V3PreShell.o \
|
V3PreShell.o \
|
||||||
V3Premit.o \
|
V3Premit.o \
|
||||||
V3Scope.o \
|
V3Scope.o \
|
||||||
V3Signed.o \
|
|
||||||
V3Slice.o \
|
V3Slice.o \
|
||||||
V3Split.o \
|
V3Split.o \
|
||||||
V3SplitAs.o \
|
V3SplitAs.o \
|
||||||
V3Stats.o \
|
V3Stats.o \
|
||||||
V3StatsReport.o \
|
V3StatsReport.o \
|
||||||
|
V3String.o \
|
||||||
V3Subst.o \
|
V3Subst.o \
|
||||||
V3Table.o \
|
V3Table.o \
|
||||||
V3Task.o \
|
V3Task.o \
|
||||||
V3Trace.o \
|
V3Trace.o \
|
||||||
V3TraceDecl.o \
|
V3TraceDecl.o \
|
||||||
V3Tristate.o \
|
V3Tristate.o \
|
||||||
|
V3Undriven.o \
|
||||||
V3Unknown.o \
|
V3Unknown.o \
|
||||||
V3Unroll.o \
|
V3Unroll.o \
|
||||||
V3Width.o \
|
V3Width.o \
|
||||||
@@ -248,8 +256,6 @@ $(TGT): V3Ast__gen_classes.h $(OBJS)
|
|||||||
@echo " Linking $@..."
|
@echo " Linking $@..."
|
||||||
-rm -rf $@ [email protected]
|
-rm -rf $@ [email protected]
|
||||||
${LINK} ${LDFLAGS} -o $@ $(OBJS) $(CCMALLOC) ${LIBS}
|
${LINK} ${LDFLAGS} -o $@ $(OBJS) $(CCMALLOC) ${LIBS}
|
||||||
@-(cp [email protected] $@ || true)
|
|
||||||
# ok if cp failes on linux, it's there to insure executable works on NT
|
|
||||||
|
|
||||||
V3Number_test: V3Number_test.o
|
V3Number_test: V3Number_test.o
|
||||||
${LINK} ${LDFLAGS} -o $@ $^ ${LIBS}
|
${LINK} ${LDFLAGS} -o $@ $^ ${LIBS}
|
||||||
@@ -260,9 +266,9 @@ V3Number_test: V3Number_test.o
|
|||||||
$(PERL) $(ASTGEN) -I$(srcdir) $*.cpp
|
$(PERL) $(ASTGEN) -I$(srcdir) $*.cpp
|
||||||
|
|
||||||
%.o: %.cpp
|
%.o: %.cpp
|
||||||
$(OBJCACHE) ${CXX} ${CPPFLAGS} -c $<
|
$(OBJCACHE) ${CXX} ${CPPFLAGSWALL} -c $<
|
||||||
%.o: %.c
|
%.o: %.c
|
||||||
$(OBJCACHE) ${CC} ${CPPFLAGS} -c $<
|
$(OBJCACHE) ${CC} ${CPPFLAGSWALL} -c $<
|
||||||
|
|
||||||
V3ParseLex.o: V3ParseLex.cpp V3Lexer.yy.cpp V3ParseBison.c
|
V3ParseLex.o: V3ParseLex.cpp V3Lexer.yy.cpp V3ParseBison.c
|
||||||
$(OBJCACHE) ${CXX} ${CPPFLAGSNOWALL} -c $<
|
$(OBJCACHE) ${CXX} ${CPPFLAGSNOWALL} -c $<
|
||||||
@@ -295,15 +301,15 @@ V3Lexer_pregen.yy.cpp: verilog.l V3ParseBison.h $(HEADERS)
|
|||||||
${LEX} --version
|
${LEX} --version
|
||||||
${LEX} ${LFLAGS} -o$@ $<
|
${LEX} ${LFLAGS} -o$@ $<
|
||||||
|
|
||||||
V3Lexer.yy.cpp: V3Lexer_pregen.yy.cpp
|
V3Lexer.yy.cpp: V3Lexer_pregen.yy.cpp $(FLEXFIX)
|
||||||
$(PERL) $(srcdir)/flexfix <$< >$@
|
$(PERL) $(FLEXFIX) V3Lexer <$< >$@
|
||||||
|
|
||||||
V3PreLex_pregen.yy.cpp: V3PreLex.l $(HEADERS)
|
V3PreLex_pregen.yy.cpp: V3PreLex.l $(HEADERS)
|
||||||
${LEX} --version
|
${LEX} --version
|
||||||
${LEX} ${LFLAGS} -o$@ $<
|
${LEX} ${LFLAGS} -o$@ $<
|
||||||
|
|
||||||
V3PreLex.yy.cpp: V3PreLex_pregen.yy.cpp
|
V3PreLex.yy.cpp: V3PreLex_pregen.yy.cpp $(FLEXFIX)
|
||||||
$(PERL) $(srcdir)/flexfix <$< >$@
|
$(PERL) $(FLEXFIX) V3PreLex <$< >$@
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|||||||
+93
-43
@@ -1,13 +1,12 @@
|
|||||||
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Break always into sensitivity active domains
|
// DESCRIPTION: Verilator: Break always into sensitivity active domains
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.org/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
|
||||||
//
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2014 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
@@ -148,7 +147,11 @@ public:
|
|||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
// CONSTUCTORS
|
// CONSTUCTORS
|
||||||
ActiveNamer() {}
|
ActiveNamer() {
|
||||||
|
m_scopep = NULL;
|
||||||
|
m_iActivep = NULL;
|
||||||
|
m_cActivep = NULL;
|
||||||
|
}
|
||||||
virtual ~ActiveNamer() {}
|
virtual ~ActiveNamer() {}
|
||||||
void main(AstScope* nodep) {
|
void main(AstScope* nodep) {
|
||||||
nodep->accept(*this);
|
nodep->accept(*this);
|
||||||
@@ -159,27 +162,65 @@ public:
|
|||||||
// Active AssignDly replacement functions
|
// Active AssignDly replacement functions
|
||||||
|
|
||||||
class ActiveDlyVisitor : public ActiveBaseVisitor {
|
class ActiveDlyVisitor : public ActiveBaseVisitor {
|
||||||
|
public:
|
||||||
|
enum CheckType { CT_SEQ, CT_COMBO, CT_INITIAL };
|
||||||
private:
|
private:
|
||||||
|
CheckType m_check; // Combo logic or other
|
||||||
|
AstNode* m_alwaysp; // Always we're under
|
||||||
|
AstNode* m_assignp; // In assign
|
||||||
// VISITORS
|
// VISITORS
|
||||||
virtual void visit(AstAssignDly* nodep, AstNUser*) {
|
virtual void visit(AstAssignDly* nodep, AstNUser*) {
|
||||||
// Convert to a non-delayed assignment
|
if (m_check != CT_SEQ) {
|
||||||
UINFO(5," ASSIGNDLY "<<nodep<<endl);
|
// Convert to a non-delayed assignment
|
||||||
nodep->v3warn(COMBDLY,"Delayed assignments (<=) in non-clocked (non flop or latch) blocks should be non-delayed assignments (=).");
|
UINFO(5," ASSIGNDLY "<<nodep<<endl);
|
||||||
AstNode* newp = new AstAssign (nodep->fileline(),
|
if (m_check == CT_INITIAL) {
|
||||||
nodep->lhsp()->unlinkFrBack(),
|
nodep->v3warn(INITIALDLY,"Delayed assignments (<=) in initial or final block; suggest blocking assignments (=).");
|
||||||
nodep->rhsp()->unlinkFrBack());
|
} else {
|
||||||
nodep->replaceWith(newp);
|
nodep->v3warn(COMBDLY,"Delayed assignments (<=) in non-clocked (non flop or latch) block; suggest blocking assignments (=).");
|
||||||
nodep->deleteTree(); nodep = NULL;
|
}
|
||||||
|
AstNode* newp = new AstAssign (nodep->fileline(),
|
||||||
|
nodep->lhsp()->unlinkFrBack(),
|
||||||
|
nodep->rhsp()->unlinkFrBack());
|
||||||
|
nodep->replaceWith(newp);
|
||||||
|
nodep->deleteTree(); nodep = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
virtual void visit(AstAssign* nodep, AstNUser*) {
|
||||||
|
if (m_check == CT_SEQ) {
|
||||||
|
AstNode* las = m_assignp;
|
||||||
|
m_assignp = nodep;
|
||||||
|
nodep->lhsp()->iterateAndNext(*this);
|
||||||
|
m_assignp = las;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
||||||
|
AstVar* varp=nodep->varp();
|
||||||
|
if (m_check == CT_SEQ
|
||||||
|
&& m_assignp
|
||||||
|
&& !varp->isUsedLoopIdx() // Ignore loop indicies
|
||||||
|
&& !varp->isTemp()
|
||||||
|
) {
|
||||||
|
// Allow turning off warnings on the always, or the variable also
|
||||||
|
if (!m_alwaysp->fileline()->warnIsOff(V3ErrorCode::BLKSEQ)
|
||||||
|
&& !m_assignp->fileline()->warnIsOff(V3ErrorCode::BLKSEQ)
|
||||||
|
&& !varp->fileline()->warnIsOff(V3ErrorCode::BLKSEQ)
|
||||||
|
) {
|
||||||
|
m_alwaysp->fileline()->modifyWarnOff(V3ErrorCode::BLKSEQ, true); // Complain just once for the entire always
|
||||||
|
varp->fileline()->modifyWarnOff(V3ErrorCode::BLKSEQ, true);
|
||||||
|
nodep->v3warn(BLKSEQ,"Blocking assignments (=) in sequential (flop or latch) block; suggest delayed assignments (<=).");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Empty visitors, speed things up
|
|
||||||
virtual void visit(AstNodeMath* nodep, AstNUser*) {}
|
|
||||||
//--------------------
|
//--------------------
|
||||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
// CONSTUCTORS
|
// CONSTUCTORS
|
||||||
ActiveDlyVisitor(AstNode* nodep) {
|
ActiveDlyVisitor(AstNode* nodep, CheckType check) {
|
||||||
|
m_alwaysp = nodep;
|
||||||
|
m_check = check;
|
||||||
|
m_assignp = NULL;
|
||||||
nodep->accept(*this);
|
nodep->accept(*this);
|
||||||
}
|
}
|
||||||
virtual ~ActiveDlyVisitor() {}
|
virtual ~ActiveDlyVisitor() {}
|
||||||
@@ -197,7 +238,6 @@ private:
|
|||||||
// STATE
|
// STATE
|
||||||
ActiveNamer m_namer; // Tracking of active names
|
ActiveNamer m_namer; // Tracking of active names
|
||||||
AstCFunc* m_scopeFinalp; // Final function for this scope
|
AstCFunc* m_scopeFinalp; // Final function for this scope
|
||||||
AstAlways* m_alwaysp; // Under always
|
|
||||||
bool m_itemCombo; // Found a SenItem combo
|
bool m_itemCombo; // Found a SenItem combo
|
||||||
bool m_itemSequent; // Found a SenItem sequential
|
bool m_itemSequent; // Found a SenItem sequential
|
||||||
|
|
||||||
@@ -216,6 +256,7 @@ private:
|
|||||||
virtual void visit(AstInitial* nodep, AstNUser*) {
|
virtual void visit(AstInitial* nodep, AstNUser*) {
|
||||||
// Relink to IACTIVE, unless already under it
|
// Relink to IACTIVE, unless already under it
|
||||||
UINFO(4," INITIAL "<<nodep<<endl);
|
UINFO(4," INITIAL "<<nodep<<endl);
|
||||||
|
ActiveDlyVisitor dlyvisitor (nodep, ActiveDlyVisitor::CT_INITIAL);
|
||||||
AstActive* wantactivep = m_namer.getIActive(nodep->fileline());
|
AstActive* wantactivep = m_namer.getIActive(nodep->fileline());
|
||||||
nodep->unlinkFrBack();
|
nodep->unlinkFrBack();
|
||||||
wantactivep->addStmtsp(nodep);
|
wantactivep->addStmtsp(nodep);
|
||||||
@@ -248,8 +289,9 @@ private:
|
|||||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
ActiveDlyVisitor dlyvisitor (nodep, ActiveDlyVisitor::CT_INITIAL);
|
||||||
if (!m_scopeFinalp) {
|
if (!m_scopeFinalp) {
|
||||||
m_scopeFinalp = new AstCFunc(nodep->fileline(), "_final", m_namer.scopep());
|
m_scopeFinalp = new AstCFunc(nodep->fileline(), "_final_"+m_namer.scopep()->nameDotless(), m_namer.scopep());
|
||||||
m_scopeFinalp->argTypes(EmitCBaseVisitor::symClassVar());
|
m_scopeFinalp->argTypes(EmitCBaseVisitor::symClassVar());
|
||||||
m_scopeFinalp->addInitsp(new AstCStmt(nodep->fileline(), EmitCBaseVisitor::symTopAssign()+"\n"));
|
m_scopeFinalp->addInitsp(new AstCStmt(nodep->fileline(), EmitCBaseVisitor::symTopAssign()+"\n"));
|
||||||
m_scopeFinalp->dontCombine(true);
|
m_scopeFinalp->dontCombine(true);
|
||||||
@@ -264,42 +306,30 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
virtual void visit(AstAlways* nodep, AstNUser*) {
|
void visitAlways(AstNode* nodep, AstSenTree* oldsensesp) {
|
||||||
// Move always to appropriate ACTIVE based on its sense list
|
// Move always to appropriate ACTIVE based on its sense list
|
||||||
UINFO(4," ALW "<<nodep<<endl);
|
if (oldsensesp
|
||||||
//if (debug()>=9) nodep->dumpTree(cout," Alw: ");
|
&& oldsensesp->sensesp()
|
||||||
|
&& oldsensesp->sensesp()->castSenItem()
|
||||||
if (!nodep->bodysp()) {
|
&& oldsensesp->sensesp()->castSenItem()->isNever()) {
|
||||||
// Empty always. Kill it.
|
|
||||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (nodep->sensesp()
|
|
||||||
&& nodep->sensesp()->sensesp()
|
|
||||||
&& nodep->sensesp()->sensesp()->castSenItem()
|
|
||||||
&& nodep->sensesp()->sensesp()->castSenItem()->isNever()) {
|
|
||||||
// Never executing. Kill it.
|
// Never executing. Kill it.
|
||||||
if (nodep->sensesp()->sensesp()->nextp()) nodep->v3fatalSrc("Never senitem should be alone, else the never should be eliminated.");
|
if (oldsensesp->sensesp()->nextp()) nodep->v3fatalSrc("Never senitem should be alone, else the never should be eliminated.");
|
||||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read sensitivitues
|
// Read sensitivitues
|
||||||
m_alwaysp = nodep;
|
|
||||||
m_itemCombo = false;
|
m_itemCombo = false;
|
||||||
m_itemSequent = false;
|
m_itemSequent = false;
|
||||||
nodep->sensesp()->iterateAndNext(*this);
|
oldsensesp->iterateAndNext(*this);
|
||||||
m_alwaysp = NULL;
|
|
||||||
bool combo = m_itemCombo;
|
bool combo = m_itemCombo;
|
||||||
bool sequent = m_itemSequent;
|
bool sequent = m_itemSequent;
|
||||||
|
|
||||||
if (!combo && !sequent) combo=true; // If no list, Verilog 2000: always @ (*)
|
if (!combo && !sequent) combo=true; // If no list, Verilog 2000: always @ (*)
|
||||||
#ifndef NEW_ORDERING
|
|
||||||
if (combo && sequent) {
|
if (combo && sequent) {
|
||||||
nodep->v3error("Unsupported: Mixed edge (pos/negedge) and activity (no edge) sensitive activity list");
|
nodep->v3error("Unsupported: Mixed edge (pos/negedge) and activity (no edge) sensitive activity list");
|
||||||
sequent = false;
|
sequent = false;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
AstActive* wantactivep = NULL;
|
AstActive* wantactivep = NULL;
|
||||||
if (combo && !sequent) {
|
if (combo && !sequent) {
|
||||||
@@ -311,15 +341,15 @@ private:
|
|||||||
// always (posedge RESET) { if (RESET).... } we know RESET is true.
|
// always (posedge RESET) { if (RESET).... } we know RESET is true.
|
||||||
// Summarize a long list of combo inputs as just "combo"
|
// Summarize a long list of combo inputs as just "combo"
|
||||||
#ifndef __COVERITY__ // Else dead code on next line.
|
#ifndef __COVERITY__ // Else dead code on next line.
|
||||||
if (combo) nodep->sensesp()->addSensesp
|
if (combo) oldsensesp->addSensesp
|
||||||
(new AstSenItem(nodep->fileline(),AstSenItem::Combo()));
|
(new AstSenItem(nodep->fileline(),AstSenItem::Combo()));
|
||||||
#endif
|
#endif
|
||||||
wantactivep = m_namer.getActive(nodep->fileline(), nodep->sensesp());
|
wantactivep = m_namer.getActive(nodep->fileline(), oldsensesp);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete sensitivity list
|
// Delete sensitivity list
|
||||||
if (AstNode* oldsense = nodep->sensesp()) {
|
if (oldsensesp) {
|
||||||
oldsense->unlinkFrBackWithNext()->deleteTree(); oldsense=NULL;
|
oldsensesp->unlinkFrBackWithNext()->deleteTree(); oldsensesp=NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move node to new active
|
// Move node to new active
|
||||||
@@ -328,8 +358,29 @@ private:
|
|||||||
|
|
||||||
// Warn and/or convert any delayed assignments
|
// Warn and/or convert any delayed assignments
|
||||||
if (combo && !sequent) {
|
if (combo && !sequent) {
|
||||||
ActiveDlyVisitor dlyvisitor (nodep);
|
ActiveDlyVisitor dlyvisitor (nodep, ActiveDlyVisitor::CT_COMBO);
|
||||||
}
|
}
|
||||||
|
else if (!combo && sequent) {
|
||||||
|
ActiveDlyVisitor dlyvisitor (nodep, ActiveDlyVisitor::CT_SEQ);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
virtual void visit(AstAlways* nodep, AstNUser*) {
|
||||||
|
// Move always to appropriate ACTIVE based on its sense list
|
||||||
|
UINFO(4," ALW "<<nodep<<endl);
|
||||||
|
//if (debug()>=9) nodep->dumpTree(cout," Alw: ");
|
||||||
|
|
||||||
|
if (!nodep->bodysp()) {
|
||||||
|
// Empty always. Kill it.
|
||||||
|
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
visitAlways(nodep, nodep->sensesp());
|
||||||
|
}
|
||||||
|
virtual void visit(AstAlwaysPublic* nodep, AstNUser*) {
|
||||||
|
// Move always to appropriate ACTIVE based on its sense list
|
||||||
|
UINFO(4," ALWPub "<<nodep<<endl);
|
||||||
|
//if (debug()>=9) nodep->dumpTree(cout," Alw: ");
|
||||||
|
visitAlways(nodep, nodep->sensesp());
|
||||||
}
|
}
|
||||||
virtual void visit(AstSenGate* nodep, AstNUser*) {
|
virtual void visit(AstSenGate* nodep, AstNUser*) {
|
||||||
AstSenItem* subitemp = nodep->sensesp();
|
AstSenItem* subitemp = nodep->sensesp();
|
||||||
@@ -348,7 +399,7 @@ private:
|
|||||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||||
} else if (nodep->varrefp()) {
|
} else if (nodep->varrefp()) {
|
||||||
// V3LinkResolve should have cleaned most of these up
|
// 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());
|
<<nodep->varrefp()->prettyName());
|
||||||
m_itemSequent = true;
|
m_itemSequent = true;
|
||||||
nodep->varrefp()->varp()->usedClock(true);
|
nodep->varrefp()->varp()->usedClock(true);
|
||||||
@@ -366,7 +417,6 @@ public:
|
|||||||
// CONSTUCTORS
|
// CONSTUCTORS
|
||||||
ActiveVisitor(AstNetlist* nodep) {
|
ActiveVisitor(AstNetlist* nodep) {
|
||||||
m_scopeFinalp = NULL;
|
m_scopeFinalp = NULL;
|
||||||
m_alwaysp = NULL;
|
|
||||||
m_itemCombo = false;
|
m_itemCombo = false;
|
||||||
m_itemSequent = false;
|
m_itemSequent = false;
|
||||||
nodep->accept(*this);
|
nodep->accept(*this);
|
||||||
|
|||||||
+2
-4
@@ -1,14 +1,12 @@
|
|||||||
// -*- C++ -*-
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Break always into sensitivity block domains
|
// DESCRIPTION: Verilator: Break always into sensitivity block domains
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.org/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
|
||||||
//
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2014 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
|
|||||||
+5
-3
@@ -1,13 +1,12 @@
|
|||||||
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Break always into sensitivity active domains
|
// DESCRIPTION: Verilator: Break always into sensitivity active domains
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.org/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
|
||||||
//
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2014 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
@@ -133,6 +132,9 @@ private:
|
|||||||
virtual void visit(AstAlways* nodep, AstNUser*) {
|
virtual void visit(AstAlways* nodep, AstNUser*) {
|
||||||
nodep->v3fatalSrc("Node should have been under ACTIVE");
|
nodep->v3fatalSrc("Node should have been under ACTIVE");
|
||||||
}
|
}
|
||||||
|
virtual void visit(AstAlwaysPublic* nodep, AstNUser*) {
|
||||||
|
nodep->v3fatalSrc("Node should have been under ACTIVE");
|
||||||
|
}
|
||||||
virtual void visit(AstFinal* nodep, AstNUser*) {
|
virtual void visit(AstFinal* nodep, AstNUser*) {
|
||||||
nodep->v3fatalSrc("Node should have been deleted");
|
nodep->v3fatalSrc("Node should have been deleted");
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-4
@@ -1,14 +1,12 @@
|
|||||||
// -*- C++ -*-
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Break always into sensitivity block domains
|
// DESCRIPTION: Verilator: Break always into sensitivity block domains
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.org/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
|
||||||
//
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2014 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
|
|||||||
+97
-31
@@ -1,13 +1,12 @@
|
|||||||
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Collect and print statistics
|
// DESCRIPTION: Verilator: Collect and print statistics
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.org/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
|
||||||
//
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2005-2010 by Wilson Snyder. This program is free software; you can
|
// Copyright 2005-2014 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
@@ -57,14 +56,18 @@ private:
|
|||||||
+":"+cvtToStr(nodep->fileline()->lineno())
|
+":"+cvtToStr(nodep->fileline()->lineno())
|
||||||
+": Assertion failed in %m"
|
+": Assertion failed in %m"
|
||||||
+((message != "")?": ":"")+message
|
+((message != "")?": ":"")+message
|
||||||
+"\\n");
|
+"\n");
|
||||||
}
|
}
|
||||||
void replaceDisplay(AstDisplay* nodep, const string& prefix) {
|
void replaceDisplay(AstDisplay* nodep, const string& prefix) {
|
||||||
nodep->displayType(AstDisplayType::DT_WRITE);
|
nodep->displayType(AstDisplayType::DT_WRITE);
|
||||||
nodep->fmtp()->text(assertDisplayMessage(nodep, prefix, nodep->fmtp()->text()));
|
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()));
|
AstNode* timenewp = new AstTime(nodep->fileline());
|
||||||
nodep->fmtp()->exprsp(timesp);
|
if (AstNode* timesp = nodep->fmtp()->exprsp()) {
|
||||||
|
timesp->unlinkFrBackWithNext();
|
||||||
|
timenewp->addNext(timesp);
|
||||||
|
}
|
||||||
|
nodep->fmtp()->exprsp(timenewp);
|
||||||
if (!nodep->fmtp()->scopeNamep() && nodep->fmtp()->formatScopeTracking()) {
|
if (!nodep->fmtp()->scopeNamep() && nodep->fmtp()->formatScopeTracking()) {
|
||||||
nodep->fmtp()->scopeNamep(new AstScopeName(nodep->fileline()));
|
nodep->fmtp()->scopeNamep(new AstScopeName(nodep->fileline()));
|
||||||
}
|
}
|
||||||
@@ -73,25 +76,31 @@ private:
|
|||||||
AstNode* newIfAssertOn(AstNode* nodep) {
|
AstNode* newIfAssertOn(AstNode* nodep) {
|
||||||
// Add a internal if to check assertions are on.
|
// Add a internal if to check assertions are on.
|
||||||
// Don't make this a AND term, as it's unlikely to need to test this.
|
// Don't make this a AND term, as it's unlikely to need to test this.
|
||||||
return new AstIf (nodep->fileline(),
|
AstNode* newp
|
||||||
// If assertions are off, have constant propagation rip them out later
|
= new AstIf (nodep->fileline(),
|
||||||
// This allows syntax errors and such to be detected normally.
|
// If assertions are off, have constant propagation rip them out later
|
||||||
(v3Global.opt.assertOn()
|
// This allows syntax errors and such to be detected normally.
|
||||||
? (AstNode*)(new AstCMath(nodep->fileline(), "Verilated::assertOn()", 1))
|
(v3Global.opt.assertOn()
|
||||||
: (AstNode*)(new AstConst(nodep->fileline(), AstConst::LogicFalse()))),
|
? (AstNode*)(new AstCMath(nodep->fileline(), "Verilated::assertOn()", 1))
|
||||||
nodep, NULL);
|
: (AstNode*)(new AstConst(nodep->fileline(), AstConst::LogicFalse()))),
|
||||||
|
nodep, NULL);
|
||||||
|
newp->user1(true); // Don't assert/cover this if
|
||||||
|
return newp;
|
||||||
}
|
}
|
||||||
|
|
||||||
AstNode* newIfCoverageOn(AstNode* nodep) {
|
AstNode* newIfCoverageOn(AstNode* nodep) {
|
||||||
// Add a internal if to check coverage is on
|
// Add a internal if to check coverage is on
|
||||||
// Don't make this a AND term, as it's unlikely to need to test this.
|
// Don't make this a AND term, as it's unlikely to need to test this.
|
||||||
return new AstIf (nodep->fileline(),
|
AstNode* newp
|
||||||
// If assertions are off, have constant propagation rip them out later
|
= new AstIf (nodep->fileline(),
|
||||||
// This allows syntax errors and such to be detected normally.
|
// If assertions are off, have constant propagation rip them out later
|
||||||
(v3Global.opt.coverage()
|
// This allows syntax errors and such to be detected normally.
|
||||||
? (AstNode*)(new AstConst(nodep->fileline(), AstConst::LogicTrue()))
|
(v3Global.opt.coverage()
|
||||||
: (AstNode*)(new AstConst(nodep->fileline(), AstConst::LogicFalse()))),
|
? (AstNode*)(new AstConst(nodep->fileline(), AstConst::LogicTrue()))
|
||||||
nodep, NULL);
|
: (AstNode*)(new AstConst(nodep->fileline(), AstConst::LogicFalse()))),
|
||||||
|
nodep, NULL);
|
||||||
|
newp->user1(true); // Don't assert/cover this if
|
||||||
|
return newp;
|
||||||
}
|
}
|
||||||
|
|
||||||
AstNode* newFireAssert(AstNode* nodep, const string& message) {
|
AstNode* newFireAssert(AstNode* nodep, const string& message) {
|
||||||
@@ -137,6 +146,7 @@ private:
|
|||||||
if (nodep->castPslAssert()) ifp->branchPred(AstBranchPred::BP_UNLIKELY);
|
if (nodep->castPslAssert()) ifp->branchPred(AstBranchPred::BP_UNLIKELY);
|
||||||
//
|
//
|
||||||
AstNode* newp = new AstAlways (nodep->fileline(),
|
AstNode* newp = new AstAlways (nodep->fileline(),
|
||||||
|
VAlwaysKwd::ALWAYS,
|
||||||
sentreep,
|
sentreep,
|
||||||
bodysp);
|
bodysp);
|
||||||
// Install it
|
// Install it
|
||||||
@@ -173,28 +183,83 @@ private:
|
|||||||
// Bye
|
// Bye
|
||||||
pushDeletep(nodep); nodep=NULL;
|
pushDeletep(nodep); nodep=NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void visit(AstIf* nodep, AstNUser*) {
|
||||||
|
if (nodep->user1SetOnce()) return;
|
||||||
|
if (nodep->uniquePragma() || nodep->unique0Pragma()) {
|
||||||
|
AstNodeIf* ifp = nodep;
|
||||||
|
AstNode* propp = NULL;
|
||||||
|
bool hasDefaultElse = false;
|
||||||
|
do {
|
||||||
|
// If this statement ends with 'else if', then nextIf will point to the
|
||||||
|
// nextIf statement. Otherwise it will be null.
|
||||||
|
AstNodeIf* nextifp = dynamic_cast<AstNodeIf*>(ifp->elsesp());
|
||||||
|
ifp->condp()->iterateAndNext(*this);
|
||||||
|
|
||||||
|
// Recurse into the true case.
|
||||||
|
ifp->ifsp()->iterateAndNext(*this);
|
||||||
|
|
||||||
|
// If the last else is not an else if, recurse into that too.
|
||||||
|
if (ifp->elsesp() && !nextifp) {
|
||||||
|
ifp->elsesp()->iterateAndNext(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build a bitmask of the true predicates
|
||||||
|
AstNode* predp = ifp->condp()->cloneTree(false);
|
||||||
|
if (propp) {
|
||||||
|
propp = new AstConcat(nodep->fileline(), predp, propp);
|
||||||
|
} else {
|
||||||
|
propp = predp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Record if this ends with an 'else' that does not have an if
|
||||||
|
if (ifp->elsesp() && !nextifp) {
|
||||||
|
hasDefaultElse = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ifp = nextifp;
|
||||||
|
} while (ifp);
|
||||||
|
|
||||||
|
AstNode *newifp = nodep->cloneTree(false);
|
||||||
|
bool allow_none = nodep->unique0Pragma();
|
||||||
|
|
||||||
|
// Note: if this ends with an 'else', then we don't need to validate that one of the
|
||||||
|
// predicates evaluates to true.
|
||||||
|
AstNode* ohot = ((allow_none || hasDefaultElse)
|
||||||
|
? (new AstOneHot0(nodep->fileline(), propp))->castNode()
|
||||||
|
: (new AstOneHot (nodep->fileline(), propp))->castNode());
|
||||||
|
AstIf* checkifp = new AstIf (nodep->fileline(),
|
||||||
|
new AstLogNot (nodep->fileline(), ohot),
|
||||||
|
newFireAssert(nodep, "'unique if' statement violated"),
|
||||||
|
newifp);
|
||||||
|
checkifp->branchPred(AstBranchPred::BP_UNLIKELY);
|
||||||
|
nodep->replaceWith(checkifp);
|
||||||
|
pushDeletep(nodep);
|
||||||
|
} else {
|
||||||
|
nodep->iterateChildren(*this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// VISITORS //========== Case assertions
|
// VISITORS //========== Case assertions
|
||||||
virtual void visit(AstCase* nodep, AstNUser*) {
|
virtual void visit(AstCase* nodep, AstNUser*) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
if (!nodep->user1()) {
|
if (!nodep->user1SetOnce()) {
|
||||||
nodep->user1(true);
|
|
||||||
bool has_default=false;
|
bool has_default=false;
|
||||||
for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) {
|
for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) {
|
||||||
if (itemp->isDefault()) has_default=true;
|
if (itemp->isDefault()) has_default=true;
|
||||||
}
|
}
|
||||||
if (nodep->fullPragma()) {
|
if (nodep->fullPragma() || nodep->priorityPragma()) {
|
||||||
// Simply need to add a default if there isn't one already
|
// Simply need to add a default if there isn't one already
|
||||||
m_statAsFull++;
|
++m_statAsFull;
|
||||||
if (!has_default) {
|
if (!has_default) {
|
||||||
nodep->addItemsp(new AstCaseItem(nodep->fileline(), NULL/*DEFAULT*/,
|
nodep->addItemsp(new AstCaseItem(nodep->fileline(), NULL/*DEFAULT*/,
|
||||||
newFireAssert(nodep, "synthesis full_case, but non-match found")));
|
newFireAssert(nodep, "synthesis full_case, but non-match found")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (nodep->parallelPragma()) {
|
if (nodep->parallelPragma() || nodep->uniquePragma() || nodep->unique0Pragma()) {
|
||||||
// Need to check that one, and only one of the case items match at any moment
|
// Need to check that one, and only one of the case items match at any moment
|
||||||
// If there's a default, we allow none to match, else exactly one must match
|
// If there's a default, we allow none to match, else exactly one must match
|
||||||
m_statAsFull++;
|
++m_statAsFull;
|
||||||
if (!has_default && !nodep->itemsp()) {
|
if (!has_default && !nodep->itemsp()) {
|
||||||
// Not parallel, but harmlessly so.
|
// Not parallel, but harmlessly so.
|
||||||
} else {
|
} else {
|
||||||
@@ -208,7 +273,8 @@ private:
|
|||||||
else propp = onep;
|
else propp = onep;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AstNode* ohot = (has_default
|
bool allow_none = has_default || nodep->unique0Pragma();
|
||||||
|
AstNode* ohot = (allow_none
|
||||||
? (new AstOneHot0(nodep->fileline(), propp))->castNode()
|
? (new AstOneHot0(nodep->fileline(), propp))->castNode()
|
||||||
: (new AstOneHot (nodep->fileline(), propp))->castNode());
|
: (new AstOneHot (nodep->fileline(), propp))->castNode());
|
||||||
AstIf* ifp = new AstIf (nodep->fileline(),
|
AstIf* ifp = new AstIf (nodep->fileline(),
|
||||||
@@ -241,18 +307,18 @@ private:
|
|||||||
if (m_beginp && nodep->name() == "") nodep->name(m_beginp->name());
|
if (m_beginp && nodep->name() == "") nodep->name(m_beginp->name());
|
||||||
newPslAssertion(nodep, nodep->propp(), nodep->sentreep(),
|
newPslAssertion(nodep, nodep->propp(), nodep->sentreep(),
|
||||||
nodep->stmtsp(), nodep->name()); nodep=NULL;
|
nodep->stmtsp(), nodep->name()); nodep=NULL;
|
||||||
m_statAsCover++;
|
++m_statAsCover;
|
||||||
}
|
}
|
||||||
virtual void visit(AstPslAssert* nodep, AstNUser*) {
|
virtual void visit(AstPslAssert* nodep, AstNUser*) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
newPslAssertion(nodep, nodep->propp(), nodep->sentreep(),
|
newPslAssertion(nodep, nodep->propp(), nodep->sentreep(),
|
||||||
NULL, nodep->name()); nodep=NULL;
|
NULL, nodep->name()); nodep=NULL;
|
||||||
m_statAsPsl++;
|
++m_statAsPsl;
|
||||||
}
|
}
|
||||||
virtual void visit(AstVAssert* nodep, AstNUser*) {
|
virtual void visit(AstVAssert* nodep, AstNUser*) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
newVAssertion(nodep, nodep->propp()); nodep=NULL;
|
newVAssertion(nodep, nodep->propp()); nodep=NULL;
|
||||||
m_statAsSV++;
|
++m_statAsSV;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void visit(AstNodeModule* nodep, AstNUser*) {
|
virtual void visit(AstNodeModule* nodep, AstNUser*) {
|
||||||
|
|||||||
+2
-4
@@ -1,14 +1,12 @@
|
|||||||
// -*- C++ -*-
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Assertion expansion
|
// DESCRIPTION: Verilator: Assertion expansion
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.org/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
|
||||||
//
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2005-2010 by Wilson Snyder. This program is free software; you can
|
// Copyright 2005-2014 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
|
|||||||
+2
-3
@@ -1,13 +1,12 @@
|
|||||||
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Collect and print statistics
|
// DESCRIPTION: Verilator: Collect and print statistics
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.org/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
|
||||||
//
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2005-2010 by Wilson Snyder. This program is free software; you can
|
// Copyright 2005-2014 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
|
|||||||
+2
-4
@@ -1,14 +1,12 @@
|
|||||||
// -*- C++ -*-
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Assertion pre-expansion
|
// DESCRIPTION: Verilator: Assertion pre-expansion
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.org/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
|
||||||
//
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2005-2010 by Wilson Snyder. This program is free software; you can
|
// Copyright 2005-2014 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
|
|||||||
+151
-45
@@ -1,13 +1,12 @@
|
|||||||
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Ast node structures
|
// DESCRIPTION: Verilator: Ast node structures
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.org/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
|
||||||
//
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2014 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
@@ -52,6 +51,9 @@ bool AstUser3InUse::s_userBusy=false;
|
|||||||
bool AstUser4InUse::s_userBusy=false;
|
bool AstUser4InUse::s_userBusy=false;
|
||||||
bool AstUser5InUse::s_userBusy=false;
|
bool AstUser5InUse::s_userBusy=false;
|
||||||
|
|
||||||
|
int AstNodeDType::s_uniqueNum = 0;
|
||||||
|
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
// V3AstType
|
// V3AstType
|
||||||
|
|
||||||
@@ -71,12 +73,12 @@ void AstNode::init() {
|
|||||||
m_op3p = NULL;
|
m_op3p = NULL;
|
||||||
m_op4p = NULL;
|
m_op4p = NULL;
|
||||||
m_iterpp = NULL;
|
m_iterpp = NULL;
|
||||||
|
m_dtypep = NULL;
|
||||||
m_clonep = NULL;
|
m_clonep = NULL;
|
||||||
m_cloneCnt = 0;
|
m_cloneCnt = 0;
|
||||||
// Attributes
|
// Attributes
|
||||||
m_signed = false;
|
m_didWidth = false;
|
||||||
m_width = 0;
|
m_doingWidth = false;
|
||||||
m_widthMin = 0;
|
|
||||||
m_user1p = NULL;
|
m_user1p = NULL;
|
||||||
m_user1Cnt = 0;
|
m_user1Cnt = 0;
|
||||||
m_user2p = NULL;
|
m_user2p = NULL;
|
||||||
@@ -192,6 +194,7 @@ string AstNode::prettyName(const string& namein) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (pretty.substr(0,4) == "TOP.") pretty.replace(0,4,"");
|
if (pretty.substr(0,4) == "TOP.") pretty.replace(0,4,"");
|
||||||
|
if (pretty.substr(0,5) == "TOP->") pretty.replace(0,5,"");
|
||||||
return pretty;
|
return pretty;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -225,15 +228,6 @@ string AstNode::quoteName(const string& namein) {
|
|||||||
return out;
|
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
|
// Insertion
|
||||||
|
|
||||||
@@ -242,9 +236,12 @@ inline void AstNode::debugTreeChange(const char* prefix, int lineno, bool next)
|
|||||||
// Called on all major tree changers.
|
// Called on all major tree changers.
|
||||||
// Only for use for those really nasty bugs relating to internals
|
// Only for use for those really nasty bugs relating to internals
|
||||||
// Note this may be null.
|
// 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()) {
|
//if (debug()) {
|
||||||
// cout<<"-treeChange: V3Ast.cpp:"<<lineno<<" Tree Change for "<<prefix<<endl;
|
// cout<<"-treeChange: V3Ast.cpp:"<<lineno<<" Tree Change for "<<prefix<<endl;
|
||||||
|
// // Commenting out the section below may crash, as the tree state
|
||||||
|
// // between edits is not always consistent for printing
|
||||||
|
// cout<<"-treeChange: V3Ast.cpp:"<<lineno<<" Tree Change for "<<prefix<<endl;
|
||||||
// v3Global.rootp()->dumpTree(cout,"-treeChange: ");
|
// v3Global.rootp()->dumpTree(cout,"-treeChange: ");
|
||||||
// if (next||1) this->dumpTreeAndNext(cout, prefix);
|
// if (next||1) this->dumpTreeAndNext(cout, prefix);
|
||||||
// else this->dumpTree(cout, prefix);
|
// else this->dumpTree(cout, prefix);
|
||||||
@@ -427,7 +424,7 @@ void AstNode::replaceWith(AstNode* newp) {
|
|||||||
repHandle.relink(newp);
|
repHandle.relink(newp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AstNRelinker::dump(ostream& str) {
|
void AstNRelinker::dump(ostream& str) const {
|
||||||
str<<" BK="<<(uint32_t*)m_backp;
|
str<<" BK="<<(uint32_t*)m_backp;
|
||||||
str<<" ITER="<<(uint32_t*)m_iterpp;
|
str<<" ITER="<<(uint32_t*)m_iterpp;
|
||||||
str<<" CHG="<<(m_chg==RELINK_NEXT?"[NEXT] ":"");
|
str<<" CHG="<<(m_chg==RELINK_NEXT?"[NEXT] ":"");
|
||||||
@@ -567,7 +564,7 @@ void AstNode::relink(AstNRelinker* linkerp) {
|
|||||||
if (linkerp->m_iterpp) {
|
if (linkerp->m_iterpp) {
|
||||||
// If we're iterating over a next() link, we need to follow links off the
|
// If we're iterating over a next() link, we need to follow links off the
|
||||||
// NEW node. Thus we pass iteration information via a pointer in the node.
|
// NEW node. Thus we pass iteration information via a pointer in the node.
|
||||||
// This adds a unfortunate 4 bytes to every AstNode, but is faster than passing
|
// This adds a unfortunate hot 8 bytes to every AstNode, but is faster than passing
|
||||||
// across every function.
|
// across every function.
|
||||||
// If anyone has a cleaner way, I'd be grateful.
|
// If anyone has a cleaner way, I'd be grateful.
|
||||||
*(linkerp->m_iterpp) = newp;
|
*(linkerp->m_iterpp) = newp;
|
||||||
@@ -716,6 +713,7 @@ void AstNode::deleteTree() {
|
|||||||
if (!this) return;
|
if (!this) return;
|
||||||
UASSERT(m_backp==NULL,"Delete called on node with backlink still set\n");
|
UASSERT(m_backp==NULL,"Delete called on node with backlink still set\n");
|
||||||
this->debugTreeChange("-delTree: ", __LINE__, true);
|
this->debugTreeChange("-delTree: ", __LINE__, true);
|
||||||
|
this->editCountInc();
|
||||||
// MUST be depth first!
|
// MUST be depth first!
|
||||||
deleteTreeIter();
|
deleteTreeIter();
|
||||||
}
|
}
|
||||||
@@ -755,6 +753,20 @@ void AstNode::iterateChildren(AstNVisitor& v, AstNUser* vup) {
|
|||||||
if (m_op4p) m_op4p->iterateAndNext(v, vup);
|
if (m_op4p) m_op4p->iterateAndNext(v, vup);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AstNode::iterateChildrenConst(AstNVisitor& v, AstNUser* vup) {
|
||||||
|
// This is a very hot function
|
||||||
|
if (!this) return;
|
||||||
|
ASTNODE_PREFETCH(m_op1p);
|
||||||
|
ASTNODE_PREFETCH(m_op2p);
|
||||||
|
ASTNODE_PREFETCH(m_op3p);
|
||||||
|
ASTNODE_PREFETCH(m_op4p);
|
||||||
|
// if () not needed since iterateAndNext accepts null this, but faster with it.
|
||||||
|
if (m_op1p) m_op1p->iterateAndNextConst(v, vup);
|
||||||
|
if (m_op2p) m_op2p->iterateAndNextConst(v, vup);
|
||||||
|
if (m_op3p) m_op3p->iterateAndNextConst(v, vup);
|
||||||
|
if (m_op4p) m_op4p->iterateAndNextConst(v, vup);
|
||||||
|
}
|
||||||
|
|
||||||
void AstNode::iterateAndNext(AstNVisitor& v, AstNUser* vup) {
|
void AstNode::iterateAndNext(AstNVisitor& v, AstNUser* vup) {
|
||||||
// This is a very hot function
|
// This is a very hot function
|
||||||
// IMPORTANT: If you replace a node that's the target of this iterator,
|
// IMPORTANT: If you replace a node that's the target of this iterator,
|
||||||
@@ -763,18 +775,24 @@ void AstNode::iterateAndNext(AstNVisitor& v, AstNUser* vup) {
|
|||||||
// Future versions of this function may require the node to have a back to be iterated;
|
// 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.
|
// there's no lower level reason yet though the back must exist.
|
||||||
AstNode* nodep=this;
|
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");
|
if (VL_UNLIKELY(nodep && !nodep->m_backp)) nodep->v3fatalSrc("iterateAndNext node has no back");
|
||||||
|
#endif
|
||||||
while (nodep) {
|
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);
|
ASTNODE_PREFETCH(nodep->m_nextp);
|
||||||
|
// Desirable check, but many places where multiple iterations are OK
|
||||||
|
//if (VL_UNLIKELY(niterp->m_iterpp)) niterp->v3fatalSrc("IterateAndNext under iterateAndNext may miss edits");
|
||||||
|
// cppcheck-suppress nullPointer
|
||||||
niterp->m_iterpp = &niterp;
|
niterp->m_iterpp = &niterp;
|
||||||
niterp->accept(v, vup);
|
niterp->accept(v, vup);
|
||||||
// accept may do a replaceNode and change niterp on us...
|
// accept may do a replaceNode and change niterp on us...
|
||||||
if (!niterp) return;
|
//if (niterp != nodep) UINFO(1,"iterateAndNext edited "<<(void*)nodep<<" now into "<<(void*)niterp<<endl); // niterp maybe NULL, so need cast
|
||||||
|
if (!niterp) return; // Perhaps node deleted inside accept
|
||||||
niterp->m_iterpp = NULL;
|
niterp->m_iterpp = NULL;
|
||||||
if (VL_UNLIKELY(niterp!=nodep)) { // Edited it
|
if (VL_UNLIKELY(niterp!=nodep)) { // Edited node inside accept
|
||||||
nodep = niterp;
|
nodep = niterp;
|
||||||
} else { // Same node, just loop
|
} else { // Unchanged node, just continue loop
|
||||||
nodep = niterp->m_nextp;
|
nodep = niterp->m_nextp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -800,11 +818,12 @@ void AstNode::iterateChildrenBackwards(AstNVisitor& v, AstNUser* vup) {
|
|||||||
this->op4p()->iterateListBackwards(v,vup);
|
this->op4p()->iterateListBackwards(v,vup);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AstNode::iterateAndNextIgnoreEdit(AstNVisitor& v, AstNUser* vup) {
|
void AstNode::iterateAndNextConst(AstNVisitor& v, AstNUser* vup) {
|
||||||
// Keep following the current list even if edits change it
|
// Keep following the current list even if edits change it
|
||||||
if (!this) return;
|
if (!this) return;
|
||||||
for (AstNode* nodep=this; nodep; ) {
|
for (AstNode* nodep=this; nodep; ) {
|
||||||
AstNode* nnextp = nodep->m_nextp;
|
AstNode* nnextp = nodep->m_nextp;
|
||||||
|
ASTNODE_PREFETCH(nnextp);
|
||||||
nodep->accept(v, vup);
|
nodep->accept(v, vup);
|
||||||
nodep = nnextp;
|
nodep = nnextp;
|
||||||
}
|
}
|
||||||
@@ -813,7 +832,7 @@ void AstNode::iterateAndNextIgnoreEdit(AstNVisitor& v, AstNUser* vup) {
|
|||||||
AstNode* AstNode::acceptSubtreeReturnEdits(AstNVisitor& v, AstNUser* vup) {
|
AstNode* AstNode::acceptSubtreeReturnEdits(AstNVisitor& v, AstNUser* vup) {
|
||||||
// Some visitors perform tree edits (such as V3Const), and may even
|
// Some visitors perform tree edits (such as V3Const), and may even
|
||||||
// replace/delete the exact nodep that the visitor is called with. If
|
// replace/delete the exact nodep that the visitor is called with. If
|
||||||
// this happens, the parent will loose the handle to the node that was
|
// this happens, the parent will lose the handle to the node that was
|
||||||
// processed.
|
// processed.
|
||||||
// To solve this, this function returns the pointer to the replacement node,
|
// To solve this, this function returns the pointer to the replacement node,
|
||||||
// which in many cases is just the same node that was passed in.
|
// which in many cases is just the same node that was passed in.
|
||||||
@@ -851,6 +870,9 @@ AstNode* AstNode::acceptSubtreeReturnEdits(AstNVisitor& v, AstNUser* vup) {
|
|||||||
void AstNode::cloneRelinkTree() {
|
void AstNode::cloneRelinkTree() {
|
||||||
if (!this) return;
|
if (!this) return;
|
||||||
for (AstNode* nodep=this; nodep; nodep=nodep->m_nextp) {
|
for (AstNode* nodep=this; nodep; nodep=nodep->m_nextp) {
|
||||||
|
if (m_dtypep && m_dtypep->clonep()) {
|
||||||
|
m_dtypep = m_dtypep->clonep()->castNodeDType();
|
||||||
|
}
|
||||||
nodep->cloneRelink();
|
nodep->cloneRelink();
|
||||||
nodep->m_op1p->cloneRelinkTree();
|
nodep->m_op1p->cloneRelinkTree();
|
||||||
nodep->m_op2p->cloneRelinkTree();
|
nodep->m_op2p->cloneRelinkTree();
|
||||||
@@ -862,25 +884,21 @@ void AstNode::cloneRelinkTree() {
|
|||||||
//======================================================================
|
//======================================================================
|
||||||
// Comparison
|
// Comparison
|
||||||
|
|
||||||
bool AstNode::sameTree(AstNode* node2p) {
|
bool AstNode::sameTreeIter(AstNode* node2p, bool ignNext, bool gateOnly) {
|
||||||
return sameTreeIter(node2p, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AstNode::sameTreeIter(AstNode* node2p, bool ignNext) {
|
|
||||||
// Return true if the two trees are identical
|
// Return true if the two trees are identical
|
||||||
if (this==NULL && node2p==NULL) return true;
|
if (this==NULL && node2p==NULL) return true;
|
||||||
if (this==NULL || node2p==NULL) return false;
|
if (this==NULL || node2p==NULL) return false;
|
||||||
if (this->type() != node2p->type()
|
if (this->type() != node2p->type()
|
||||||
|| this->width() != node2p->width()
|
|| this->dtypep() != node2p->dtypep()
|
||||||
|| this->isSigned() != node2p->isSigned()
|
|| !this->same(node2p)
|
||||||
|| !this->same(node2p)) {
|
|| (gateOnly && !this->isGateOptimizable())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return (this->op1p()->sameTreeIter(node2p->op1p(),false)
|
return (this->op1p()->sameTreeIter(node2p->op1p(),false,gateOnly)
|
||||||
&& this->op2p()->sameTreeIter(node2p->op2p(),false)
|
&& this->op2p()->sameTreeIter(node2p->op2p(),false,gateOnly)
|
||||||
&& this->op3p()->sameTreeIter(node2p->op3p(),false)
|
&& this->op3p()->sameTreeIter(node2p->op3p(),false,gateOnly)
|
||||||
&& this->op4p()->sameTreeIter(node2p->op4p(),false)
|
&& this->op4p()->sameTreeIter(node2p->op4p(),false,gateOnly)
|
||||||
&& (ignNext || this->nextp()->sameTreeIter(node2p->nextp(),false))
|
&& (ignNext || this->nextp()->sameTreeIter(node2p->nextp(),false,gateOnly))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -894,8 +912,8 @@ ostream& operator<<(ostream& os, V3Hash rhs) {
|
|||||||
|
|
||||||
V3Hash::V3Hash(const string& name) {
|
V3Hash::V3Hash(const string& name) {
|
||||||
uint32_t val = 0;
|
uint32_t val = 0;
|
||||||
for (const char* c=name.c_str(); *c; c++) {
|
for (string::const_iterator it = name.begin(); it!=name.end(); ++it) {
|
||||||
val = val*31 + *c;
|
val = val*31 + *it;
|
||||||
}
|
}
|
||||||
setBoth(1,val);
|
setBoth(1,val);
|
||||||
}
|
}
|
||||||
@@ -944,7 +962,35 @@ void AstNode::checkTree() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AstNode::dumpPtrs(ostream& os) {
|
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::checkIter() const {
|
||||||
|
if (m_iterpp) {
|
||||||
|
dumpPtrs(cout);
|
||||||
|
// Perhaps something forgot to clear m_iterpp?
|
||||||
|
this->v3fatalSrc("Iteration link should be NULL");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AstNode::dumpPtrs(ostream& os) const {
|
||||||
os<<"This="<<typeName()<<" "<<(void*)this;
|
os<<"This="<<typeName()<<" "<<(void*)this;
|
||||||
os<<" back="<<(void*)backp();
|
os<<" back="<<(void*)backp();
|
||||||
if (nextp()) os<<" next="<<(void*)nextp();
|
if (nextp()) os<<" next="<<(void*)nextp();
|
||||||
@@ -987,14 +1033,16 @@ void AstNode::dumpTreeAndNext(ostream& os, const string& indent, int maxDepth) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AstNode::dumpTreeFile(const string& filename, bool append) {
|
void AstNode::dumpTreeFile(const string& filename, bool append, bool doDump) {
|
||||||
if (v3Global.opt.dumpTree()) {
|
if (v3Global.opt.dumpTree() && doDump) {
|
||||||
{ // Write log & close
|
{ // Write log & close
|
||||||
|
UINFO(2,"Dumping "<<filename<<endl);
|
||||||
const auto_ptr<ofstream> logsp (V3File::new_ofstream(filename, append));
|
const auto_ptr<ofstream> logsp (V3File::new_ofstream(filename, append));
|
||||||
if (logsp->fail()) v3fatalSrc("Can't write "<<filename);
|
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;
|
*logsp<<" to <e"<<dec<<editCountGbl()<<">"<<endl;
|
||||||
if (editCountGbl()==editCountLast()) {
|
if (editCountGbl()==editCountLast()
|
||||||
|
&& !(v3Global.opt.dumpTree()>=9)) {
|
||||||
*logsp<<endl;
|
*logsp<<endl;
|
||||||
*logsp<<"No changes since last dump!\n";
|
*logsp<<"No changes since last dump!\n";
|
||||||
} else {
|
} else {
|
||||||
@@ -1019,7 +1067,7 @@ void AstNode::v3errorEnd(ostringstream& str) const {
|
|||||||
nsstr<<str.str();
|
nsstr<<str.str();
|
||||||
if (debug()) {
|
if (debug()) {
|
||||||
nsstr<<endl;
|
nsstr<<endl;
|
||||||
nsstr<<"-node: "<<this<<endl;
|
nsstr<<"-node: "; ((AstNode*)this)->dump(nsstr); nsstr<<endl;
|
||||||
}
|
}
|
||||||
m_fileline->v3errorEnd(nsstr);
|
m_fileline->v3errorEnd(nsstr);
|
||||||
} else {
|
} else {
|
||||||
@@ -1027,6 +1075,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
|
// AstNVisitor
|
||||||
|
|
||||||
|
|||||||
+613
-130
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,33 @@
|
|||||||
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
|
//*************************************************************************
|
||||||
|
// DESCRIPTION: Verilator: Ast node structure
|
||||||
|
//
|
||||||
|
// Code available from: http://www.veripool.org/verilator
|
||||||
|
//
|
||||||
|
//*************************************************************************
|
||||||
|
//
|
||||||
|
// Copyright 2003-2014 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.
|
||||||
|
//
|
||||||
|
//*************************************************************************
|
||||||
|
|
||||||
|
#ifndef _V3ASTCONSTONLY_H_
|
||||||
|
#define _V3ASTCONSTONLY_H_ 1
|
||||||
|
|
||||||
|
// Include only in visitors that do not not edit nodes, so should use constant iterators
|
||||||
|
#define iterateAndNext error_use_iterateAndNextConst
|
||||||
|
#define iterateChildren error_use_iterateChildrenConst
|
||||||
|
|
||||||
|
#define addNext error_no_addNext_in_ConstOnlyVisitor
|
||||||
|
#define replaceWith error_no_replaceWith_in_ConstOnlyVisitor
|
||||||
|
#define deleteTree error_no_deleteTree_in_ConstOnlyVisitor
|
||||||
|
#define unlinkFrBack error_no_unlinkFrBack_in_ConstOnlyVisitor
|
||||||
|
|
||||||
|
#endif // Guard
|
||||||
+491
-77
@@ -1,13 +1,12 @@
|
|||||||
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Ast node structures
|
// DESCRIPTION: Verilator: Ast node structures
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.org/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
|
||||||
//
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2014 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
@@ -36,8 +35,22 @@
|
|||||||
// Special methods
|
// Special methods
|
||||||
|
|
||||||
// We need these here, because the classes they point to aren't defined when we declare the class
|
// 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())
|
const char* AstIfaceRefDType::broken() const {
|
||||||
|| (m_varp && !m_varp->brokeExists())); }
|
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() {
|
void AstNodeVarRef::cloneRelink() {
|
||||||
if (m_varp && m_varp->clonep()) { m_varp = m_varp->clonep()->castVar(); }
|
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);
|
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 {
|
int AstBasicDType::widthAlignBytes() const {
|
||||||
if (width()<=8) return 1;
|
if (width()<=8) return 1;
|
||||||
else if (width()<=16) return 2;
|
else if (width()<=16) return 2;
|
||||||
@@ -61,29 +96,92 @@ int AstBasicDType::widthTotalBytes() const {
|
|||||||
else return widthWords()*(VL_WORDSIZE/8);
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
AstNodeBiop* AstEq::newTyped(FileLine* fl, AstNode* lhsp, AstNode* rhsp) {
|
||||||
|
if (lhsp->isDouble() && rhsp->isDouble()) {
|
||||||
|
return new AstEqD(fl, lhsp, rhsp);
|
||||||
|
} else {
|
||||||
|
return new AstEq(fl, lhsp, rhsp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AstNodeBiop* AstGte::newTyped(FileLine* fl, AstNode* lhsp, AstNode* rhsp) {
|
||||||
|
if (lhsp->isDouble() && rhsp->isDouble()) {
|
||||||
|
return new AstGteD(fl, lhsp, rhsp);
|
||||||
|
} else if (lhsp->isSigned() && rhsp->isSigned()) {
|
||||||
|
return new AstGteS(fl, lhsp, rhsp);
|
||||||
|
} else {
|
||||||
|
return new AstGte(fl, lhsp, rhsp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AstNodeBiop* AstLte::newTyped(FileLine* fl, AstNode* lhsp, AstNode* rhsp) {
|
||||||
|
if (lhsp->isDouble() && rhsp->isDouble()) {
|
||||||
|
return new AstLteD(fl, lhsp, rhsp);
|
||||||
|
} else if (lhsp->isSigned() && rhsp->isSigned()) {
|
||||||
|
return new AstLteS(fl, lhsp, rhsp);
|
||||||
|
} else {
|
||||||
|
return new AstLte(fl, lhsp, rhsp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool AstVar::isSigPublic() const {
|
bool AstVar::isSigPublic() const {
|
||||||
return (m_sigPublic || (v3Global.opt.allPublic() && !isTemp() && !isGenVar()));
|
return (m_sigPublic || (v3Global.opt.allPublic() && !isTemp() && !isGenVar()));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AstVar::isScQuad() const {
|
bool AstVar::isScQuad() const {
|
||||||
return (isSc() && isQuad() && !isScBv());
|
return (isSc() && isQuad() && !isScBv() && !isScBigUint());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AstVar::isScBv() const {
|
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) {
|
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::SUPPLY0) type = AstVarType::WIRE;
|
||||||
if (type == AstVarType::SUPPLY1) type = AstVarType::WIRE;
|
if (type == AstVarType::SUPPLY1) type = AstVarType::WIRE;
|
||||||
m_varType=type; // For debugging prints only
|
m_varType=type; // For debugging prints only
|
||||||
// These flags get combined with the existing settings of the flags.
|
// These flags get combined with the existing settings of the flags.
|
||||||
if (type==AstVarType::INPUT || type==AstVarType::INOUT)
|
if (type==AstVarType::INPUT || type==AstVarType::INOUT)
|
||||||
m_input = true;
|
m_input = true;
|
||||||
if (type==AstVarType::OUTPUT || type==AstVarType::INOUT)
|
if (type==AstVarType::OUTPUT || type==AstVarType::INOUT) {
|
||||||
m_output = true;
|
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;
|
m_tristate = true;
|
||||||
|
if (type==AstVarType::TRI0)
|
||||||
|
m_isPulldown = true;
|
||||||
|
if (type==AstVarType::TRI1)
|
||||||
|
m_isPullup = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
string AstVar::verilogKwd() const {
|
string AstVar::verilogKwd() const {
|
||||||
@@ -102,7 +200,7 @@ string AstVar::verilogKwd() const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
string AstVar::vlArgType(bool named, bool forReturn) const {
|
string AstVar::vlArgType(bool named, bool forReturn, bool forFunc) const {
|
||||||
if (forReturn) named=false;
|
if (forReturn) named=false;
|
||||||
if (forReturn) v3fatalSrc("verilator internal data is never passed as return, but as first argument");
|
if (forReturn) v3fatalSrc("verilator internal data is never passed as return, but as first argument");
|
||||||
string arg;
|
string arg;
|
||||||
@@ -113,6 +211,10 @@ string AstVar::vlArgType(bool named, bool forReturn) const {
|
|||||||
arg += "const char*";
|
arg += "const char*";
|
||||||
} else if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::SCOPEPTR) {
|
} else if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::SCOPEPTR) {
|
||||||
arg += "const VerilatedScope*";
|
arg += "const VerilatedScope*";
|
||||||
|
} else if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::DOUBLE) {
|
||||||
|
arg += "double";
|
||||||
|
} else if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::FLOAT) {
|
||||||
|
arg += "float";
|
||||||
} else if (strtype) {
|
} else if (strtype) {
|
||||||
if (isInOnly()) arg += "const ";
|
if (isInOnly()) arg += "const ";
|
||||||
arg += "string";
|
arg += "string";
|
||||||
@@ -131,12 +233,49 @@ string AstVar::vlArgType(bool named, bool forReturn) const {
|
|||||||
arg += " (& "+name();
|
arg += " (& "+name();
|
||||||
arg += ")["+cvtToStr(widthWords())+"]";
|
arg += ")["+cvtToStr(widthWords())+"]";
|
||||||
} else {
|
} else {
|
||||||
if (isOutput() || (strtype && isInput())) arg += "&";
|
if (forFunc && (isOutput() || (strtype && isInput()))) arg += "&";
|
||||||
if (named) arg += " "+name();
|
if (named) arg += " "+name();
|
||||||
}
|
}
|
||||||
return arg;
|
return arg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string AstVar::vlEnumType() const {
|
||||||
|
string arg;
|
||||||
|
AstBasicDType* bdtypep = basicp();
|
||||||
|
bool strtype = bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::STRING;
|
||||||
|
if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::CHARPTR) {
|
||||||
|
return "VLVT_PTR";
|
||||||
|
} else if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::SCOPEPTR) {
|
||||||
|
return "VLVT_PTR";
|
||||||
|
} else if (strtype) {
|
||||||
|
arg += "VLVT_STRING";
|
||||||
|
} else if (widthMin() <= 8) {
|
||||||
|
arg += "VLVT_UINT8";
|
||||||
|
} else if (widthMin() <= 16) {
|
||||||
|
arg += "VLVT_UINT16";
|
||||||
|
} else if (widthMin() <= VL_WORDSIZE) {
|
||||||
|
arg += "VLVT_UINT32";
|
||||||
|
} else if (isQuad()) {
|
||||||
|
arg += "VLVT_UINT64";
|
||||||
|
} else if (isWide()) {
|
||||||
|
arg += "VLVT_WDATA";
|
||||||
|
}
|
||||||
|
// else return "VLVT_UNKNOWN"
|
||||||
|
return arg;
|
||||||
|
}
|
||||||
|
|
||||||
|
string AstVar::vlEnumDir() const {
|
||||||
|
if (isInout()) {
|
||||||
|
return "VLVD_INOUT";
|
||||||
|
} else if (isInOnly()) {
|
||||||
|
return "VLVD_IN";
|
||||||
|
} else if (isOutOnly()) {
|
||||||
|
return "VLVD_OUT";
|
||||||
|
} else {
|
||||||
|
return "VLVD_NODIR";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
string AstVar::cPubArgType(bool named, bool forReturn) const {
|
string AstVar::cPubArgType(bool named, bool forReturn) const {
|
||||||
if (forReturn) named=false;
|
if (forReturn) named=false;
|
||||||
string arg;
|
string arg;
|
||||||
@@ -148,7 +287,7 @@ string AstVar::cPubArgType(bool named, bool forReturn) const {
|
|||||||
} else if (isWide()) {
|
} else if (isWide()) {
|
||||||
arg += "uint32_t"; // []'s added later
|
arg += "uint32_t"; // []'s added later
|
||||||
} else {
|
} else {
|
||||||
arg += "uint64_t";
|
arg += "vluint64_t";
|
||||||
}
|
}
|
||||||
if (isWide()) {
|
if (isWide()) {
|
||||||
if (forReturn) v3error("Unsupported: Public functions with >64 bit outputs; make an output of a public task instead");
|
if (forReturn) v3error("Unsupported: Public functions with >64 bit outputs; make an output of a public task instead");
|
||||||
@@ -165,7 +304,6 @@ string AstVar::dpiArgType(bool named, bool forReturn) const {
|
|||||||
if (forReturn) named=false;
|
if (forReturn) named=false;
|
||||||
string arg;
|
string arg;
|
||||||
if (!basicp()) arg = "UNKNOWN";
|
if (!basicp()) arg = "UNKNOWN";
|
||||||
if (isWide()) v3error("Unsupported: DPI functions with vectored outputs > 32-bits");
|
|
||||||
if (basicp()->isBitLogic()) {
|
if (basicp()->isBitLogic()) {
|
||||||
if (widthMin() == 1) {
|
if (widthMin() == 1) {
|
||||||
arg = "unsigned char";
|
arg = "unsigned char";
|
||||||
@@ -181,6 +319,9 @@ string AstVar::dpiArgType(bool named, bool forReturn) const {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
arg = basicp()->keyword().dpiType();
|
arg = basicp()->keyword().dpiType();
|
||||||
|
if (basicp()->keyword().isDpiUnsignable() && !basicp()->isSigned()) {
|
||||||
|
arg = "unsigned "+arg;
|
||||||
|
}
|
||||||
if (!forReturn && isOutput()) arg += "*";
|
if (!forReturn && isOutput()) arg += "*";
|
||||||
}
|
}
|
||||||
if (named) arg += " "+name();
|
if (named) arg += " "+name();
|
||||||
@@ -188,7 +329,11 @@ string AstVar::dpiArgType(bool named, bool forReturn) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
string AstVar::scType() 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 >>
|
return (string("sc_bv<")+cvtToStr(widthMin())+"> "); // Keep the space so don't get >>
|
||||||
} else if (widthMin() == 1) {
|
} else if (widthMin() == 1) {
|
||||||
return "bool";
|
return "bool";
|
||||||
@@ -201,11 +346,11 @@ string AstVar::scType() const {
|
|||||||
return "uint32_t";
|
return "uint32_t";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return "uint64_t";
|
return "vluint64_t";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AstNodeDType* AstVar::dtypeDimensionp(int dimension) const {
|
AstNodeDType* AstNodeDType::dtypeDimensionp(int dimension) {
|
||||||
// dimension passed from AstArraySel::dimension
|
// dimension passed from AstArraySel::dimension
|
||||||
// Dimension 0 means the VAR itself, 1 is the closest SEL to the AstVar,
|
// Dimension 0 means the VAR itself, 1 is the closest SEL to the AstVar,
|
||||||
// which is the lowest in the dtype list.
|
// which is the lowest in the dtype list.
|
||||||
@@ -217,19 +362,29 @@ AstNodeDType* AstVar::dtypeDimensionp(int dimension) const {
|
|||||||
// DECL: VAR a (ARRAYSEL0 (ARRAYSEL1 (ARRAYSEL2 (DT RANGE3))))
|
// DECL: VAR a (ARRAYSEL0 (ARRAYSEL1 (ARRAYSEL2 (DT RANGE3))))
|
||||||
// *or* VAR a (ARRAYSEL0 (ARRAYSEL1 (ARRAYSEL2 (ARRAYSEL3 (DT))))
|
// *or* VAR a (ARRAYSEL0 (ARRAYSEL1 (ARRAYSEL2 (ARRAYSEL3 (DT))))
|
||||||
// SEL1 needs to select from entire variable which is a pointer to ARRAYSEL0
|
// 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;
|
int dim = 0;
|
||||||
for (AstNodeDType* dtypep=this->dtypep(); dtypep; ) {
|
for (AstNodeDType* dtypep=this; dtypep; ) {
|
||||||
dtypep = dtypep->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node
|
dtypep = dtypep->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node
|
||||||
if (AstArrayDType* adtypep = dtypep->castArrayDType()) {
|
if (AstNodeArrayDType* adtypep = dtypep->castNodeArrayDType()) {
|
||||||
if ((dim++)==dimension) {
|
if ((dim++)==dimension) {
|
||||||
return dtypep;
|
return dtypep;
|
||||||
}
|
}
|
||||||
dtypep = adtypep->dtypep();
|
dtypep = adtypep->subDTypep();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (AstBasicDType* adtypep = dtypep->castBasicDType()) {
|
else if (AstBasicDType* adtypep = dtypep->castBasicDType()) {
|
||||||
// AstBasicDType - nothing below, return null
|
// 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) {
|
if ((dim++) == dimension) {
|
||||||
return adtypep;
|
return adtypep;
|
||||||
}
|
}
|
||||||
@@ -242,13 +397,13 @@ AstNodeDType* AstVar::dtypeDimensionp(int dimension) const {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t AstVar::arrayElements() const {
|
uint32_t AstNodeDType::arrayUnpackedElements() {
|
||||||
uint32_t entries=1;
|
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
|
dtypep = dtypep->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node
|
||||||
if (AstArrayDType* adtypep = dtypep->castArrayDType()) {
|
if (AstUnpackArrayDType* adtypep = dtypep->castUnpackArrayDType()) {
|
||||||
entries *= adtypep->elementsConst();
|
entries *= adtypep->elementsConst();
|
||||||
dtypep = adtypep->dtypep();
|
dtypep = adtypep->subDTypep();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// AstBasicDType - nothing below, 1
|
// AstBasicDType - nothing below, 1
|
||||||
@@ -258,43 +413,41 @@ uint32_t AstVar::arrayElements() const {
|
|||||||
return entries;
|
return entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t AstVar::dimensions() const {
|
pair<uint32_t,uint32_t> AstNodeDType::dimensions(bool includeBasic) {
|
||||||
// How many array dimensions does this Var have?
|
// How many array dimensions (packed,unpacked) does this Var have?
|
||||||
uint32_t dim = 0;
|
uint32_t packed = 0;
|
||||||
for (AstNodeDType* dtypep=this->dtypep(); dtypep; ) {
|
uint32_t unpacked = 0;
|
||||||
|
for (AstNodeDType* dtypep=this; dtypep; ) {
|
||||||
dtypep = dtypep->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node
|
dtypep = dtypep->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node
|
||||||
if (AstArrayDType* adtypep = dtypep->castArrayDType()) {
|
if (AstNodeArrayDType* adtypep = dtypep->castNodeArrayDType()) {
|
||||||
dim += 1;
|
if (adtypep->castPackArrayDType()) packed++;
|
||||||
dtypep = adtypep->dtypep();
|
else unpacked++;
|
||||||
|
dtypep = adtypep->subDTypep();
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
else {
|
else if (AstBasicDType* adtypep = dtypep->castBasicDType()) {
|
||||||
// AstBasicDType - nothing below, 1
|
if (includeBasic && adtypep->isRanged()) packed++;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return dim;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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;
|
break;
|
||||||
}
|
}
|
||||||
return dim;
|
return make_pair(packed, unpacked);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 1;
|
||||||
|
}
|
||||||
|
|
||||||
AstNode* AstArraySel::baseFromp(AstNode* nodep) { ///< What is the base variable (or const) this dereferences?
|
AstNode* AstArraySel::baseFromp(AstNode* nodep) { ///< What is the base variable (or const) this dereferences?
|
||||||
// Else AstArraySel etc; search for the base
|
// Else AstArraySel etc; search for the base
|
||||||
while (nodep) {
|
while (nodep) {
|
||||||
if (nodep->castArraySel()) { nodep=nodep->castArraySel()->fromp(); continue; }
|
if (nodep->castArraySel()) { nodep=nodep->castArraySel()->fromp(); continue; }
|
||||||
else if (nodep->castSel()) { nodep=nodep->castSel()->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->castAttrOf()) { nodep=nodep->castAttrOf()->fromp(); continue; }
|
||||||
else if (nodep->castNodePreSel()) {
|
else if (nodep->castNodePreSel()) {
|
||||||
if (nodep->castNodePreSel()->attrp()) {
|
if (nodep->castNodePreSel()->attrp()) {
|
||||||
@@ -309,10 +462,12 @@ AstNode* AstArraySel::baseFromp(AstNode* nodep) { ///< What is the base variable
|
|||||||
return nodep;
|
return nodep;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AstScope::broken() const {
|
const char* AstScope::broken() const {
|
||||||
return ((m_aboveScopep && !m_aboveScopep->brokeExists())
|
BROKEN_RTN(m_aboveScopep && !m_aboveScopep->brokeExists());
|
||||||
|| (m_aboveCellp && !m_aboveCellp->brokeExists())
|
BROKEN_RTN(m_aboveCellp && !m_aboveCellp->brokeExists());
|
||||||
|| !m_modp || !m_modp->brokeExists());
|
BROKEN_RTN(!m_modp);
|
||||||
|
BROKEN_RTN(m_modp && !m_modp->brokeExists());
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AstScope::cloneRelink() {
|
void AstScope::cloneRelink() {
|
||||||
@@ -348,6 +503,26 @@ string AstScopeName::scopeSymName() const {
|
|||||||
out += textp->text();
|
out += textp->text();
|
||||||
}
|
}
|
||||||
if (out.substr(0,10) == "__DOT__TOP") out.replace(0,10,"");
|
if (out.substr(0,10) == "__DOT__TOP") out.replace(0,10,"");
|
||||||
|
if (out.substr(0,7) == "__DOT__") out.replace(0,7,"");
|
||||||
|
if (out.substr(0,1) == ".") out.replace(0,1,"");
|
||||||
|
string::size_type pos;
|
||||||
|
while ((pos=out.find(".")) != string::npos) {
|
||||||
|
out.replace(pos, 1, "__");
|
||||||
|
}
|
||||||
|
while ((pos=out.find("__DOT__")) != string::npos) {
|
||||||
|
out.replace(pos, 7, "__");
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
string AstScopeName::scopeDpiName() const {
|
||||||
|
string out;
|
||||||
|
for (AstText* textp=scopeEntrp(); textp; textp=textp->nextp()->castText()) {
|
||||||
|
out += textp->text();
|
||||||
|
}
|
||||||
|
if (out.substr(0,10) == "__DOT__TOP") out.replace(0,10,"");
|
||||||
|
if (out.substr(0,7) == "__DOT__") out.replace(0,7,"");
|
||||||
|
if (out.substr(0,1) == ".") out.replace(0,1,"");
|
||||||
string::size_type pos;
|
string::size_type pos;
|
||||||
while ((pos=out.find(".")) != string::npos) {
|
while ((pos=out.find(".")) != string::npos) {
|
||||||
out.replace(pos, 1, "__");
|
out.replace(pos, 1, "__");
|
||||||
@@ -387,6 +562,96 @@ bool AstSenTree::hasCombo() {
|
|||||||
return false;
|
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
|
// Special walking tree inserters
|
||||||
|
|
||||||
@@ -452,16 +717,32 @@ void AstWhile::addNextStmt(AstNode* newp, AstNode* belowp) {
|
|||||||
//======================================================================
|
//======================================================================
|
||||||
// Per-type Debugging
|
// Per-type Debugging
|
||||||
|
|
||||||
void AstNode::dump(ostream& os) {
|
void AstNode::dump(ostream& str) {
|
||||||
os<<typeName()<<" "<<(void*)this
|
str<<typeName()<<" "<<(void*)this
|
||||||
//<<" "<<(void*)this->m_backp
|
//<<" "<<(void*)this->m_backp
|
||||||
<<" <e"<<dec<<editCount()
|
<<" <e"<<dec<<editCount()
|
||||||
<<((editCount()>=editCountLast())?"#>":">")
|
<<((editCount()>=editCountLast())?"#>":">")
|
||||||
<<" {"<<dec<<fileline()->lineno()<<"}"
|
<<" {"<<fileline()->filenameLetters()<<dec<<fileline()->lineno()<<"}";
|
||||||
<<" "<<(isSigned()?"s":"")
|
if (user1p()) str<<" u1="<<(void*)user1p();
|
||||||
<<"w"<<(widthSized()?"":"u")<<width();
|
if (user2p()) str<<" u2="<<(void*)user2p();
|
||||||
if (!widthSized()) os<<"/"<<widthMin();
|
if (user3p()) str<<" u3="<<(void*)user3p();
|
||||||
if (name()!="") os<<" "<<AstNode::quoteName(name());
|
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 AstAlways::dump(ostream& str) {
|
||||||
|
this->AstNode::dump(str);
|
||||||
|
if (keyword() != VAlwaysKwd::ALWAYS) str<<" ["<<keyword().ascii()<<"]";
|
||||||
}
|
}
|
||||||
|
|
||||||
void AstArraySel::dump(ostream& str) {
|
void AstArraySel::dump(ostream& str) {
|
||||||
@@ -473,11 +754,11 @@ void AstAttrOf::dump(ostream& str) {
|
|||||||
str<<" ["<<attrType().ascii()<<"]";
|
str<<" ["<<attrType().ascii()<<"]";
|
||||||
}
|
}
|
||||||
void AstBasicDType::dump(ostream& str) {
|
void AstBasicDType::dump(ostream& str) {
|
||||||
this->AstNode::dump(str);
|
this->AstNodeDType::dump(str);
|
||||||
str<<" ["<<keyword().ascii()<<"]";
|
str<<" kwd="<<keyword().ascii();
|
||||||
if (implicit()) str<<" [IMPLICIT]";
|
if (isRanged() && !rangep()) str<<" range=["<<left()<<":"<<right()<<"]";
|
||||||
}
|
}
|
||||||
void AstCast::dump(ostream& str) {
|
void AstCCast::dump(ostream& str) {
|
||||||
this->AstNode::dump(str);
|
this->AstNode::dump(str);
|
||||||
str<<" sz"<<size();
|
str<<" sz"<<size();
|
||||||
}
|
}
|
||||||
@@ -500,49 +781,165 @@ void AstEnumItemRef::dump(ostream& str) {
|
|||||||
if (itemp()) { itemp()->dump(str); }
|
if (itemp()) { itemp()->dump(str); }
|
||||||
else { str<<"UNLINKED"; }
|
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 AstModportFTaskRef::dump(ostream& str) {
|
||||||
|
this->AstNode::dump(str);
|
||||||
|
if (isExport()) str<<" EXPORT";
|
||||||
|
if (isImport()) str<<" IMPORT";
|
||||||
|
if (ftaskp()) { str<<" -> "; ftaskp()->dump(str); }
|
||||||
|
else { str<<" -> UNLINKED"; }
|
||||||
|
}
|
||||||
|
void AstModportVarRef::dump(ostream& str) {
|
||||||
|
this->AstNode::dump(str);
|
||||||
|
str<<" "<<varType();
|
||||||
|
if (varp()) { str<<" -> "; varp()->dump(str); }
|
||||||
|
else { str<<" -> UNLINKED"; }
|
||||||
|
}
|
||||||
void AstPin::dump(ostream& str) {
|
void AstPin::dump(ostream& str) {
|
||||||
this->AstNode::dump(str);
|
this->AstNode::dump(str);
|
||||||
if (modVarp()) { str<<" -> "; modVarp()->dump(str); }
|
if (modVarp()) { str<<" -> "; modVarp()->dump(str); }
|
||||||
else { str<<" ->UNLINKED"; }
|
else { str<<" ->UNLINKED"; }
|
||||||
if (svImplicit()) str<<" [.SV]";
|
if (svImplicit()) str<<" [.SV]";
|
||||||
}
|
}
|
||||||
|
void AstTypedef::dump(ostream& str) {
|
||||||
|
this->AstNode::dump(str);
|
||||||
|
if (attrPublic()) str<<" [PUBLIC]";
|
||||||
|
}
|
||||||
void AstRange::dump(ostream& str) {
|
void AstRange::dump(ostream& str) {
|
||||||
this->AstNode::dump(str);
|
this->AstNode::dump(str);
|
||||||
if (littleEndian()) str<<" [LITTLE]";
|
if (littleEndian()) str<<" [LITTLE]";
|
||||||
}
|
}
|
||||||
void AstRefDType::dump(ostream& str) {
|
void AstRefDType::dump(ostream& str) {
|
||||||
this->AstNode::dump(str);
|
this->AstNodeDType::dump(str);
|
||||||
if (defp()) { str<<" -> "; defp()->dump(str); }
|
if (defp()) { str<<" -> "; defp()->dump(str); }
|
||||||
else { str<<" -> UNLINKED"; }
|
else { str<<" -> UNLINKED"; }
|
||||||
}
|
}
|
||||||
void AstVarXRef::dump(ostream& str) {
|
void AstNodeClassDType::dump(ostream& str) {
|
||||||
this->AstNode::dump(str);
|
this->AstNode::dump(str);
|
||||||
if (lvalue()) str<<" [LV] => ";
|
if (packed()) str<<" [PACKED]";
|
||||||
else str<<" [RV] <- ";
|
}
|
||||||
str<<dotted()<<". - ";
|
void AstNodeDType::dump(ostream& str) {
|
||||||
if (inlinedDots()!="") str<<" flat.="<<inlinedDots()<<" - ";
|
this->AstNode::dump(str);
|
||||||
if (varScopep()) { varScopep()->dump(str); }
|
if (generic()) str<<" [GENERIC]";
|
||||||
else if (varp()) { varp()->dump(str); }
|
if (AstNodeDType* dtp = virtRefDTypep()) {
|
||||||
else { str<<"UNLINKED"; }
|
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();
|
||||||
|
}
|
||||||
|
void AstNodeArrayDType::dump(ostream& str) {
|
||||||
|
this->AstNodeDType::dump(str);
|
||||||
|
str<<" "<<declRange();
|
||||||
}
|
}
|
||||||
void AstNodeModule::dump(ostream& str) {
|
void AstNodeModule::dump(ostream& str) {
|
||||||
this->AstNode::dump(str);
|
this->AstNode::dump(str);
|
||||||
str<<" L"<<level();
|
str<<" L"<<level();
|
||||||
if (modPublic()) str<<" [P]";
|
if (modPublic()) str<<" [P]";
|
||||||
if (inLibrary()) str<<" [LIB]";
|
if (inLibrary()) str<<" [LIB]";
|
||||||
|
if (dead()) str<<" [DEAD]";
|
||||||
}
|
}
|
||||||
void AstPackageImport::dump(ostream& str) {
|
void AstPackageImport::dump(ostream& str) {
|
||||||
this->AstNode::dump(str);
|
this->AstNode::dump(str);
|
||||||
str<<" -> "<<packagep();
|
str<<" -> "<<packagep();
|
||||||
}
|
}
|
||||||
|
void AstSel::dump(ostream& str) {
|
||||||
|
this->AstNode::dump(str);
|
||||||
|
if (declRange().ranged()) {
|
||||||
|
str<<" decl"<<declRange()<<"]";
|
||||||
|
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) {
|
void AstVarScope::dump(ostream& str) {
|
||||||
this->AstNode::dump(str);
|
this->AstNode::dump(str);
|
||||||
if (isCircular()) str<<" [CIRC]";
|
if (isCircular()) str<<" [CIRC]";
|
||||||
if (varp()) { str<<" -> "; varp()->dump(str); }
|
if (varp()) { str<<" -> "; varp()->dump(str); }
|
||||||
else { str<<" ->UNLINKED"; }
|
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) {
|
void AstVarRef::dump(ostream& str) {
|
||||||
this->AstNode::dump(str);
|
this->AstNode::dump(str);
|
||||||
|
if (packagep()) { str<<" pkg="<<(void*)packagep(); }
|
||||||
if (lvalue()) str<<" [LV] => ";
|
if (lvalue()) str<<" [LV] => ";
|
||||||
else str<<" [RV] <- ";
|
else str<<" [RV] <- ";
|
||||||
if (varScopep()) { varScopep()->dump(str); }
|
if (varScopep()) { varScopep()->dump(str); }
|
||||||
@@ -558,8 +955,12 @@ void AstVar::dump(ostream& str) {
|
|||||||
else if (isInput()) str<<" [I]";
|
else if (isInput()) str<<" [I]";
|
||||||
else if (isOutput()) str<<" [O]";
|
else if (isOutput()) str<<" [O]";
|
||||||
}
|
}
|
||||||
if (isUsedClock()) str<<" [C]";
|
if (isConst()) str<<" [CONST]";
|
||||||
|
if (isPullup()) str<<" [PULLUP]";
|
||||||
|
if (isPulldown()) str<<" [PULLDOWN]";
|
||||||
|
if (isUsedClock()) str<<" [CLK]";
|
||||||
if (isSigPublic()) str<<" [P]";
|
if (isSigPublic()) str<<" [P]";
|
||||||
|
if (isUsedLoopIdx()) str<<" [LOOP]";
|
||||||
if (attrClockEn()) str<<" [aCLKEN]";
|
if (attrClockEn()) str<<" [aCLKEN]";
|
||||||
if (attrIsolateAssign()) str<<" [aISO]";
|
if (attrIsolateAssign()) str<<" [aISO]";
|
||||||
if (attrFileDescr()) str<<" [aFD]";
|
if (attrFileDescr()) str<<" [aFD]";
|
||||||
@@ -579,6 +980,16 @@ void AstParseRef::dump(ostream& str) {
|
|||||||
this->AstNode::dump(str);
|
this->AstNode::dump(str);
|
||||||
str<<" ["<<expect().ascii()<<"]";
|
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) {
|
void AstActive::dump(ostream& str) {
|
||||||
this->AstNode::dump(str);
|
this->AstNode::dump(str);
|
||||||
str<<" => ";
|
str<<" => ";
|
||||||
@@ -587,6 +998,7 @@ void AstActive::dump(ostream& str) {
|
|||||||
}
|
}
|
||||||
void AstNodeFTaskRef::dump(ostream& str) {
|
void AstNodeFTaskRef::dump(ostream& str) {
|
||||||
this->AstNode::dump(str);
|
this->AstNode::dump(str);
|
||||||
|
if (packagep()) { str<<" pkg="<<(void*)packagep(); }
|
||||||
str<<" -> ";
|
str<<" -> ";
|
||||||
if (dotted()!="") { str<<dotted()<<". - "; }
|
if (dotted()!="") { str<<dotted()<<". - "; }
|
||||||
if (taskp()) { taskp()->dump(str); }
|
if (taskp()) { taskp()->dump(str); }
|
||||||
@@ -603,6 +1015,8 @@ void AstNodeFTask::dump(ostream& str) {
|
|||||||
void AstBegin::dump(ostream& str) {
|
void AstBegin::dump(ostream& str) {
|
||||||
this->AstNode::dump(str);
|
this->AstNode::dump(str);
|
||||||
if (unnamed()) str<<" [UNNAMED]";
|
if (unnamed()) str<<" [UNNAMED]";
|
||||||
|
if (generate()) str<<" [GEN]";
|
||||||
|
if (genforp()) str<<" [GENFOR]";
|
||||||
}
|
}
|
||||||
void AstCoverDecl::dump(ostream& str) {
|
void AstCoverDecl::dump(ostream& str) {
|
||||||
this->AstNode::dump(str);
|
this->AstNode::dump(str);
|
||||||
|
|||||||
+2103
-594
File diff suppressed because it is too large
Load Diff
+120
-68
@@ -1,13 +1,12 @@
|
|||||||
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Removal of named begin blocks
|
// DESCRIPTION: Verilator: Removal of named begin blocks
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.org/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
|
||||||
//
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2014 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
@@ -45,14 +44,37 @@
|
|||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
|
|
||||||
|
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 {
|
class BeginVisitor : public AstNVisitor {
|
||||||
private:
|
private:
|
||||||
// STATE
|
// STATE
|
||||||
|
BeginState* m_statep; // Current global state
|
||||||
AstNodeModule* m_modp; // Current module
|
AstNodeModule* m_modp; // Current module
|
||||||
AstNodeFTask* m_ftaskp; // Current function/task
|
AstNodeFTask* m_ftaskp; // Current function/task
|
||||||
string m_namedScope; // Name of begin blocks above us
|
string m_namedScope; // Name of begin blocks above us
|
||||||
string m_unnamedScope; // Name of begin blocks, including unnamed blocks
|
string m_unnamedScope; // Name of begin blocks, including unnamed blocks
|
||||||
int m_repeatNum; // Repeat counter
|
int m_repeatNum; // Repeat counter
|
||||||
|
int m_ifDepth; // Current if depth
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
static int debug() {
|
static int debug() {
|
||||||
@@ -69,9 +91,27 @@ private:
|
|||||||
m_modp = NULL;
|
m_modp = NULL;
|
||||||
}
|
}
|
||||||
virtual void visit(AstNodeFTask* nodep, AstNUser*) {
|
virtual void visit(AstNodeFTask* nodep, AstNUser*) {
|
||||||
m_ftaskp = nodep;
|
UINFO(8," "<<nodep<<endl);
|
||||||
nodep->iterateChildren(*this);
|
// Rename it
|
||||||
m_ftaskp = NULL;
|
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*) {
|
virtual void visit(AstBegin* nodep, AstNUser*) {
|
||||||
// Begin blocks were only useful in variable creation, change names and delete
|
// Begin blocks were only useful in variable creation, change names and delete
|
||||||
@@ -79,7 +119,7 @@ private:
|
|||||||
string oldScope = m_namedScope;
|
string oldScope = m_namedScope;
|
||||||
string oldUnnamed = m_unnamedScope;
|
string oldUnnamed = m_unnamedScope;
|
||||||
{
|
{
|
||||||
//UINFO(8,"nname "<<m_namedScope<<endl);
|
UINFO(8,"nname "<<m_namedScope<<endl);
|
||||||
if (nodep->name() != "") { // Else unneeded unnamed block
|
if (nodep->name() != "") { // Else unneeded unnamed block
|
||||||
// Create data for dotted variable resolution
|
// Create data for dotted variable resolution
|
||||||
string dottedname = nodep->name() + "__DOT__"; // So always found
|
string dottedname = nodep->name() + "__DOT__"; // So always found
|
||||||
@@ -94,25 +134,33 @@ private:
|
|||||||
if (m_unnamedScope=="") m_unnamedScope = ident;
|
if (m_unnamedScope=="") m_unnamedScope = ident;
|
||||||
else m_unnamedScope = m_unnamedScope + "__DOT__"+ident;
|
else m_unnamedScope = m_unnamedScope + "__DOT__"+ident;
|
||||||
// Create CellInline for dotted var resolution
|
// Create CellInline for dotted var resolution
|
||||||
AstCellInline* inlinep = new AstCellInline(nodep->fileline(),
|
if (!m_ftaskp) {
|
||||||
m_unnamedScope, "__BEGIN__");
|
AstCellInline* inlinep = new AstCellInline(nodep->fileline(),
|
||||||
m_modp->addInlinesp(inlinep); // Must be parsed before any AstCells
|
m_unnamedScope, "__BEGIN__");
|
||||||
|
m_modp->addInlinesp(inlinep); // Must be parsed before any AstCells
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remap var names and replace lower Begins
|
// Remap var names and replace lower Begins
|
||||||
nodep->iterateChildren(*this);
|
nodep->stmtsp()->iterateAndNext(*this);
|
||||||
|
if (nodep->genforp()) nodep->v3fatalSrc("GENFORs should have been expanded earlier");
|
||||||
if (AstNode* stmtsp = nodep->stmtsp()) {
|
|
||||||
stmtsp->unlinkFrBackWithNext();
|
|
||||||
nodep->replaceWith(stmtsp);
|
|
||||||
} else {
|
|
||||||
nodep->unlinkFrBack();
|
|
||||||
}
|
|
||||||
pushDeletep(nodep); nodep=NULL;
|
|
||||||
}
|
}
|
||||||
m_namedScope = oldScope;
|
m_namedScope = oldScope;
|
||||||
m_unnamedScope = oldUnnamed;
|
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*) {
|
virtual void visit(AstVar* nodep, AstNUser*) {
|
||||||
if (m_unnamedScope != "") {
|
if (m_unnamedScope != "") {
|
||||||
@@ -135,56 +183,10 @@ private:
|
|||||||
m_modp->addStmtp(nodep);
|
m_modp->addStmtp(nodep);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
virtual void visit(AstFor* nodep, AstNUser*) {
|
|
||||||
// So later optimizations don't need to deal with them,
|
|
||||||
// FOR(init,cond,assign,body) -> init,WHILE(cond) { body, assign }
|
|
||||||
AstNode* initsp = nodep->initsp(); if (initsp) initsp->unlinkFrBackWithNext();
|
|
||||||
AstNode* condp = nodep->condp(); if (condp) condp->unlinkFrBackWithNext();
|
|
||||||
AstNode* incsp = nodep->incsp(); if (incsp) incsp->unlinkFrBackWithNext();
|
|
||||||
AstNode* bodysp = nodep->bodysp(); if (bodysp) bodysp->unlinkFrBackWithNext();
|
|
||||||
bodysp = bodysp->addNext(incsp);
|
|
||||||
AstNode* newp = new AstWhile(nodep->fileline(),
|
|
||||||
condp,
|
|
||||||
bodysp);
|
|
||||||
initsp = initsp->addNext(newp);
|
|
||||||
newp = initsp;
|
|
||||||
nodep->replaceWith(newp);
|
|
||||||
nodep->deleteTree(); nodep=NULL;
|
|
||||||
}
|
|
||||||
virtual void visit(AstRepeat* nodep, AstNUser*) {
|
|
||||||
// So later optimizations don't need to deal with them,
|
|
||||||
// REPEAT(count,body) -> loop=count,WHILE(loop>0) { body, loop-- }
|
|
||||||
// Note var can be signed or unsigned based on original number.
|
|
||||||
AstNode* countp = nodep->countp()->unlinkFrBackWithNext();
|
|
||||||
string name = string("__Vrepeat")+cvtToStr(m_repeatNum++);
|
|
||||||
AstVar* varp = new AstVar(nodep->fileline(), AstVarType::BLOCKTEMP, name, AstLogicPacked(), countp->width());
|
|
||||||
m_modp->addStmtp(varp);
|
|
||||||
AstNode* initsp = new AstAssign(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, true),
|
|
||||||
countp);
|
|
||||||
AstNode* decp = new AstAssign(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, true),
|
|
||||||
new AstSub(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, false),
|
|
||||||
new AstConst(nodep->fileline(), 1)));
|
|
||||||
AstNode* condp;
|
|
||||||
if (countp->isSigned()) {
|
|
||||||
condp = new AstGtS(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, false),
|
|
||||||
new AstConst(nodep->fileline(), 0));
|
|
||||||
} else {
|
|
||||||
condp = new AstGt (nodep->fileline(), new AstVarRef(nodep->fileline(), varp, false),
|
|
||||||
new AstConst(nodep->fileline(), 0));
|
|
||||||
}
|
|
||||||
AstNode* bodysp = nodep->bodysp(); if (bodysp) bodysp->unlinkFrBackWithNext();
|
|
||||||
bodysp = bodysp->addNext(decp);
|
|
||||||
AstNode* newp = new AstWhile(nodep->fileline(),
|
|
||||||
condp,
|
|
||||||
bodysp);
|
|
||||||
initsp = initsp->addNext(newp);
|
|
||||||
newp = initsp;
|
|
||||||
nodep->replaceWith(newp);
|
|
||||||
nodep->deleteTree(); nodep=NULL;
|
|
||||||
}
|
|
||||||
virtual void visit(AstScopeName* nodep, AstNUser*) {
|
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()
|
// If there's a %m in the display text, we add a special node that will contain the name()
|
||||||
// Similar code in V3Inline
|
// Similar code in V3Inline
|
||||||
|
if (nodep->user1SetOnce()) return; // Don't double-add text's
|
||||||
if (m_namedScope != "") {
|
if (m_namedScope != "") {
|
||||||
// To keep correct visual order, must add before other Text's
|
// To keep correct visual order, must add before other Text's
|
||||||
AstNode* afterp = nodep->scopeAttrp();
|
AstNode* afterp = nodep->scopeAttrp();
|
||||||
@@ -199,24 +201,74 @@ private:
|
|||||||
// any BEGINs, but V3Coverage adds them all under the module itself.
|
// any BEGINs, but V3Coverage adds them all under the module itself.
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
|
// VISITORS - LINT CHECK
|
||||||
|
virtual void visit(AstIf* nodep, AstNUser*) { // Note not AstNodeIf; other types don't get covered
|
||||||
|
// Check IFDEPTH warning - could be in other transform files if desire
|
||||||
|
int prevIfDepth = m_ifDepth;
|
||||||
|
if (m_ifDepth == -1 || v3Global.opt.ifDepth()<1) { // Turned off
|
||||||
|
} else if (nodep->uniquePragma() || nodep->unique0Pragma() || nodep->priorityPragma()) {
|
||||||
|
m_ifDepth = -1;
|
||||||
|
} else if (++m_ifDepth > v3Global.opt.ifDepth()) {
|
||||||
|
nodep->v3warn(IFDEPTH,"Deep 'if' statement; suggest unique/priority to avoid slow logic");
|
||||||
|
nodep->fileline()->modifyWarnOff(V3ErrorCode::IFDEPTH, true); // Warn only once
|
||||||
|
m_ifDepth = -1;
|
||||||
|
}
|
||||||
|
nodep->iterateChildren(*this);
|
||||||
|
m_ifDepth = prevIfDepth;
|
||||||
|
}
|
||||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
// CONSTUCTORS
|
// CONSTUCTORS
|
||||||
BeginVisitor(AstNetlist* nodep) {
|
BeginVisitor(AstNetlist* nodep, BeginState* statep) {
|
||||||
|
m_statep = statep;
|
||||||
m_modp = NULL;
|
m_modp = NULL;
|
||||||
m_ftaskp = NULL;
|
m_ftaskp = NULL;
|
||||||
m_repeatNum = 0;
|
m_repeatNum = 0;
|
||||||
|
m_ifDepth = 0;
|
||||||
nodep->accept(*this);
|
nodep->accept(*this);
|
||||||
}
|
}
|
||||||
virtual ~BeginVisitor() {}
|
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
|
// Task class functions
|
||||||
|
|
||||||
void V3Begin::debeginAll(AstNetlist* nodep) {
|
void V3Begin::debeginAll(AstNetlist* nodep) {
|
||||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
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
|
// DESCRIPTION: Verilator: Removal of named begin blocks
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.org/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
|
||||||
//
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2014 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
|
|||||||
+4
-5
@@ -1,13 +1,12 @@
|
|||||||
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Branch prediction
|
// DESCRIPTION: Verilator: Branch prediction
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.org/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
|
||||||
//
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2014 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
@@ -95,9 +94,9 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
// CONSTUCTORS
|
// CONSTUCTORS
|
||||||
BranchVisitor(AstNetlist* rootp) {
|
BranchVisitor(AstNetlist* nodep) {
|
||||||
reset();
|
reset();
|
||||||
rootp->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
virtual ~BranchVisitor() {}
|
virtual ~BranchVisitor() {}
|
||||||
};
|
};
|
||||||
|
|||||||
+2
-4
@@ -1,14 +1,12 @@
|
|||||||
// -*- C++ -*-
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Branch prediction
|
// DESCRIPTION: Verilator: Branch prediction
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.org/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
|
||||||
//
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2014 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
|
|||||||
+74
-24
@@ -1,13 +1,12 @@
|
|||||||
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Find broken links in tree
|
// DESCRIPTION: Verilator: Find broken links in tree
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.org/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
|
||||||
//
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2014 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
@@ -38,6 +37,9 @@
|
|||||||
#include "V3Broken.h"
|
#include "V3Broken.h"
|
||||||
#include "V3Ast.h"
|
#include "V3Ast.h"
|
||||||
|
|
||||||
|
// This visitor does not edit nodes, and is called at error-exit, so should use constant iterators
|
||||||
|
#include "V3AstConstOnly.h"
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
|
|
||||||
class BrokenTable : public AstNVisitor {
|
class BrokenTable : public AstNVisitor {
|
||||||
@@ -48,15 +50,16 @@ private:
|
|||||||
typedef map<const AstNode*,int> NodeMap;
|
typedef map<const AstNode*,int> NodeMap;
|
||||||
static NodeMap s_nodes; // Set of all nodes that exist
|
static NodeMap s_nodes; // Set of all nodes that exist
|
||||||
// BITMASK
|
// BITMASK
|
||||||
static const int FLAG_ALLOCATED = 0x01; // new() and not delete()ed
|
enum { FLAG_ALLOCATED = 0x01 }; // new() and not delete()ed
|
||||||
static const int FLAG_IN_TREE = 0x02; // Is in netlist tree
|
enum { FLAG_IN_TREE = 0x02 }; // Is in netlist tree
|
||||||
static const int FLAG_LINKABLE = 0x04; // Is in netlist tree, can be linked to
|
enum { FLAG_LINKABLE = 0x04 }; // Is in netlist tree, can be linked to
|
||||||
static const int FLAG_LEAKED = 0x08; // Known to have been leaked
|
enum { FLAG_LEAKED = 0x08 }; // Known to have been leaked
|
||||||
|
enum { FLAG_UNDER_NOW = 0x10 }; // Is in tree as parent of current node
|
||||||
public:
|
public:
|
||||||
// METHODS
|
// METHODS
|
||||||
static void deleted(const AstNode* nodep) {
|
static void deleted(const AstNode* nodep) {
|
||||||
// Called by operator delete on any node - only if VL_LEAK_CHECKS
|
// 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);
|
NodeMap::iterator iter = s_nodes.find(nodep);
|
||||||
if (iter==s_nodes.end() || !(iter->second & FLAG_ALLOCATED)) {
|
if (iter==s_nodes.end() || !(iter->second & FLAG_ALLOCATED)) {
|
||||||
((AstNode*)(nodep))->v3fatalSrc("Deleting AstNode object that was never tracked or already deleted\n");
|
((AstNode*)(nodep))->v3fatalSrc("Deleting AstNode object that was never tracked or already deleted\n");
|
||||||
@@ -65,13 +68,23 @@ public:
|
|||||||
}
|
}
|
||||||
static void addNewed(const AstNode* nodep) {
|
static void addNewed(const AstNode* nodep) {
|
||||||
// Called by operator new on any node - only if VL_LEAK_CHECKS
|
// 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);
|
NodeMap::iterator iter = s_nodes.find(nodep);
|
||||||
if (iter!=s_nodes.end() || (iter->second & FLAG_ALLOCATED)) {
|
if (iter!=s_nodes.end() || (iter->second & FLAG_ALLOCATED)) {
|
||||||
((AstNode*)(nodep))->v3fatalSrc("Newing AstNode object that is already allocated\n");
|
((AstNode*)(nodep))->v3fatalSrc("Newing AstNode object that is already allocated\n");
|
||||||
}
|
}
|
||||||
if (iter == s_nodes.end()) {
|
if (iter == s_nodes.end()) {
|
||||||
s_nodes.insert(make_pair(nodep,FLAG_ALLOCATED));
|
int flags = FLAG_ALLOCATED; // This int needed to appease GCC 4.1.2
|
||||||
|
s_nodes.insert(make_pair(nodep,flags));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static void setUnder(const AstNode* nodep, bool flag) {
|
||||||
|
// Called by BrokenCheckVisitor when each node entered/exited
|
||||||
|
if (!okIfLinkedTo(nodep)) return;
|
||||||
|
NodeMap::iterator iter = s_nodes.find(nodep);
|
||||||
|
if (iter!=s_nodes.end()) {
|
||||||
|
iter->second &= ~FLAG_UNDER_NOW;
|
||||||
|
if (flag) iter->second |= FLAG_UNDER_NOW;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static void addInTree(AstNode* nodep, bool linkable) {
|
static void addInTree(AstNode* nodep, bool linkable) {
|
||||||
@@ -111,6 +124,14 @@ public:
|
|||||||
if (!(iter->second & FLAG_LINKABLE)) return false;
|
if (!(iter->second & FLAG_LINKABLE)) return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
static bool okIfBelow(const AstNode* nodep) {
|
||||||
|
// Must be linked to and below current node
|
||||||
|
if (!okIfLinkedTo(nodep)) return false;
|
||||||
|
NodeMap::iterator iter = s_nodes.find(nodep);
|
||||||
|
if (iter == s_nodes.end()) return false;
|
||||||
|
if (!(iter->second & FLAG_UNDER_NOW)) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
static void prepForTree() {
|
static void prepForTree() {
|
||||||
#ifndef VL_LEAK_CHECKS
|
#ifndef VL_LEAK_CHECKS
|
||||||
s_nodes.clear();
|
s_nodes.clear();
|
||||||
@@ -129,7 +150,7 @@ public:
|
|||||||
&& (it->first->backp() ? backs==1 : backs==0)) {
|
&& (it->first->backp() ? backs==1 : backs==0)) {
|
||||||
// Use only AstNode::dump instead of the virtual one, as there
|
// Use only AstNode::dump instead of the virtual one, as there
|
||||||
// may be varp() and other cross links that are bad.
|
// may be varp() and other cross links that are bad.
|
||||||
if (debug()) {
|
if (v3Global.opt.debugCheck()) {
|
||||||
cerr<<"%Error: LeakedNode"<<(it->first->backp()?"Back: ":": ");
|
cerr<<"%Error: LeakedNode"<<(it->first->backp()?"Back: ":": ");
|
||||||
((AstNode*)(it->first))->AstNode::dump(cerr);
|
((AstNode*)(it->first))->AstNode::dump(cerr);
|
||||||
cerr<<endl;
|
cerr<<endl;
|
||||||
@@ -152,6 +173,10 @@ bool AstNode::brokeExists() const {
|
|||||||
// Called by node->broken() routines to do table lookup
|
// Called by node->broken() routines to do table lookup
|
||||||
return BrokenTable::okIfLinkedTo(this);
|
return BrokenTable::okIfLinkedTo(this);
|
||||||
}
|
}
|
||||||
|
bool AstNode::brokeExistsAbove() const {
|
||||||
|
// Called by node->broken() routines to do table lookup
|
||||||
|
return BrokenTable::okIfBelow(this);
|
||||||
|
}
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
|
|
||||||
@@ -164,7 +189,7 @@ private:
|
|||||||
// VISITORS
|
// VISITORS
|
||||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||||
BrokenTable::addInTree(nodep, nodep->maybePointedTo());
|
BrokenTable::addInTree(nodep, nodep->maybePointedTo());
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildrenConst(*this);
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
// CONSTUCTORS
|
// CONSTUCTORS
|
||||||
@@ -180,18 +205,35 @@ public:
|
|||||||
class BrokenCheckVisitor : public AstNVisitor {
|
class BrokenCheckVisitor : public AstNVisitor {
|
||||||
private:
|
private:
|
||||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||||
if (nodep->broken()) {
|
BrokenTable::setUnder(nodep,true);
|
||||||
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->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->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()) {
|
if (nodep->width() != nodep->widthMin()) {
|
||||||
nodep->v3fatalSrc("Width != WidthMin\n");
|
nodep->v3fatalSrc("Width != WidthMin");
|
||||||
}
|
|
||||||
if (!nodep->width() && nodep->castNodeMath()) {
|
|
||||||
nodep->v3fatalSrc("Math node has no assigned width\n");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildrenConst(*this);
|
||||||
|
BrokenTable::setUnder(nodep,false);
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
// CONSTUCTORS
|
// CONSTUCTORS
|
||||||
@@ -206,10 +248,18 @@ public:
|
|||||||
|
|
||||||
void V3Broken::brokenAll(AstNetlist* nodep) {
|
void V3Broken::brokenAll(AstNetlist* nodep) {
|
||||||
//UINFO(9,__FUNCTION__<<": "<<endl);
|
//UINFO(9,__FUNCTION__<<": "<<endl);
|
||||||
BrokenTable::prepForTree();
|
static bool inBroken = false;
|
||||||
BrokenMarkVisitor mvisitor (nodep);
|
if (inBroken) {
|
||||||
BrokenCheckVisitor cvisitor (nodep);
|
// A error called by broken can recurse back into broken; avoid this
|
||||||
BrokenTable::doneWithTree();
|
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) {
|
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
|
// DESCRIPTION: Verilator: Find broken links in tree
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.org/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
|
||||||
//
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2014 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
|
|||||||
+32
-22
@@ -1,13 +1,12 @@
|
|||||||
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Break case statements up and add Unknown assigns
|
// DESCRIPTION: Verilator: Break case statements up and add Unknown assigns
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.org/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
|
||||||
//
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2014 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
@@ -98,7 +97,8 @@ private:
|
|||||||
nodep->v3error("Use of x/? constant in generate case statement, (no such thing as 'generate casez')");
|
nodep->v3error("Use of x/? constant in generate case statement, (no such thing as 'generate casez')");
|
||||||
} else if (m_caseExprp->castCase() && m_caseExprp->castCase()->casex()) {
|
} else if (m_caseExprp->castCase() && m_caseExprp->castCase()->casex()) {
|
||||||
// Don't sweat it, we already complained about casex in general
|
// Don't sweat it, we already complained about casex in general
|
||||||
} else if (m_caseExprp->castCase() && m_caseExprp->castCase()->casez()) {
|
} else if (m_caseExprp->castCase() && (m_caseExprp->castCase()->casez()
|
||||||
|
|| m_caseExprp->castCase()->caseInside())) {
|
||||||
if (nodep->num().isUnknown()) {
|
if (nodep->num().isUnknown()) {
|
||||||
nodep->v3warn(CASEWITHX, "Use of x constant in casez statement, (perhaps intended ?/z in constant)");
|
nodep->v3warn(CASEWITHX, "Use of x constant in casez statement, (perhaps intended ?/z in constant)");
|
||||||
}
|
}
|
||||||
@@ -148,17 +148,19 @@ private:
|
|||||||
|
|
||||||
bool isCaseTreeFast(AstCase* nodep) {
|
bool isCaseTreeFast(AstCase* nodep) {
|
||||||
int width = 0;
|
int width = 0;
|
||||||
|
bool opaque = false;
|
||||||
m_caseItems = 0;
|
m_caseItems = 0;
|
||||||
m_caseNoOverlapsAllCovered = true;
|
m_caseNoOverlapsAllCovered = true;
|
||||||
for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) {
|
for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) {
|
||||||
for (AstNode* icondp = itemp->condsp(); icondp!=NULL; icondp=icondp->nextp()) {
|
for (AstNode* icondp = itemp->condsp(); icondp!=NULL; icondp=icondp->nextp()) {
|
||||||
if (icondp->width() > width) width = icondp->width();
|
if (icondp->width() > width) width = icondp->width();
|
||||||
|
if (icondp->isDouble()) opaque = true;
|
||||||
if (!icondp->castConst()) width = CASE_BARF; // Can't parse; not a constant
|
if (!icondp->castConst()) width = CASE_BARF; // Can't parse; not a constant
|
||||||
m_caseItems++;
|
m_caseItems++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_caseWidth = width;
|
m_caseWidth = width;
|
||||||
if (width==0 || width > CASE_OVERLAP_WIDTH) {
|
if (width==0 || width > CASE_OVERLAP_WIDTH || opaque) {
|
||||||
m_caseNoOverlapsAllCovered = false;
|
m_caseNoOverlapsAllCovered = false;
|
||||||
return false; // Too wide for analysis
|
return false; // Too wide for analysis
|
||||||
}
|
}
|
||||||
@@ -195,7 +197,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
|
if (itemp->isDefault()) { // Case statement's default... Fill the table
|
||||||
for (uint32_t i=0; i<(1UL<<m_caseWidth); i++) {
|
for (uint32_t i=0; i<(1UL<<m_caseWidth); i++) {
|
||||||
if (!m_valueItem[i]) m_valueItem[i] = itemp;
|
if (!m_valueItem[i]) m_valueItem[i] = itemp;
|
||||||
@@ -321,34 +323,42 @@ private:
|
|||||||
icondNextp = icondp->nextp();
|
icondNextp = icondp->nextp();
|
||||||
icondp->unlinkFrBack();
|
icondp->unlinkFrBack();
|
||||||
|
|
||||||
AstNode* and1p;
|
AstNode* condp = NULL; // Default is to use and1p/and2p
|
||||||
AstNode* and2p;
|
|
||||||
AstConst* iconstp = icondp->castConst();
|
AstConst* iconstp = icondp->castConst();
|
||||||
if (iconstp && neverItem(nodep, iconstp)) {
|
if (iconstp && neverItem(nodep, iconstp)) {
|
||||||
// X in casez can't ever be executed
|
// X in casez can't ever be executed
|
||||||
icondp->deleteTree(); icondp=NULL; iconstp=NULL;
|
icondp->deleteTree(); icondp=NULL; iconstp=NULL;
|
||||||
// For simplicity, make expression that is not equal, and let later
|
// For simplicity, make expression that is not equal, and let later
|
||||||
// optimizations remove it
|
// optimizations remove it
|
||||||
and1p = new AstConst(itemp->fileline(), AstConst::LogicFalse());
|
condp = new AstConst(itemp->fileline(), AstConst::LogicFalse());
|
||||||
and2p = new AstConst(itemp->fileline(), AstConst::LogicTrue());
|
} else if (AstInsideRange* irangep = icondp->castInsideRange()) {
|
||||||
|
// Similar logic in V3Width::visit(AstInside)
|
||||||
|
AstNode* ap = AstGte::newTyped(itemp->fileline(),
|
||||||
|
cexprp->cloneTree(false),
|
||||||
|
irangep->lhsp()->unlinkFrBack());
|
||||||
|
AstNode* bp = AstLte::newTyped(itemp->fileline(),
|
||||||
|
cexprp->cloneTree(false),
|
||||||
|
irangep->rhsp()->unlinkFrBack());
|
||||||
|
condp = new AstAnd(itemp->fileline(), ap, bp);
|
||||||
} else if (iconstp && iconstp->num().isFourState()
|
} else if (iconstp && iconstp->num().isFourState()
|
||||||
&& (nodep->casex() || nodep->casez())) {
|
&& (nodep->casex() || nodep->casez() || nodep->caseInside())) {
|
||||||
V3Number nummask (itemp->fileline(), iconstp->width());
|
V3Number nummask (itemp->fileline(), iconstp->width());
|
||||||
nummask.opBitsNonX(iconstp->num());
|
nummask.opBitsNonX(iconstp->num());
|
||||||
V3Number numval (itemp->fileline(), iconstp->width());
|
V3Number numval (itemp->fileline(), iconstp->width());
|
||||||
numval.opBitsOne(iconstp->num());
|
numval.opBitsOne(iconstp->num());
|
||||||
and1p = new AstAnd(itemp->fileline(), cexprp->cloneTree(false),
|
AstNode* and1p = new AstAnd(itemp->fileline(), cexprp->cloneTree(false),
|
||||||
new AstConst(itemp->fileline(), nummask));
|
new AstConst(itemp->fileline(), nummask));
|
||||||
and2p = new AstAnd(itemp->fileline(),
|
AstNode* and2p = new AstAnd(itemp->fileline(),
|
||||||
new AstConst(itemp->fileline(), numval),
|
new AstConst(itemp->fileline(), numval),
|
||||||
new AstConst(itemp->fileline(), nummask));
|
new AstConst(itemp->fileline(), nummask));
|
||||||
icondp->deleteTree(); icondp=NULL; iconstp=NULL;
|
icondp->deleteTree(); icondp=NULL; iconstp=NULL;
|
||||||
|
condp = AstEq::newTyped(itemp->fileline(), and1p, and2p);
|
||||||
} else {
|
} else {
|
||||||
// Not a caseX mask, we can simply build CASEEQ(cexpr icond)
|
// Not a caseX mask, we can simply build CASEEQ(cexpr icond)
|
||||||
and1p = cexprp->cloneTree(false);
|
AstNode* and1p = cexprp->cloneTree(false);
|
||||||
and2p = icondp;
|
AstNode* and2p = icondp;
|
||||||
|
condp = AstEq::newTyped(itemp->fileline(), and1p, and2p);
|
||||||
}
|
}
|
||||||
AstEq* condp = new AstEq(itemp->fileline(), and1p, and2p);
|
|
||||||
if (!ifexprp) {
|
if (!ifexprp) {
|
||||||
ifexprp = condp;
|
ifexprp = condp;
|
||||||
} else {
|
} else {
|
||||||
@@ -432,7 +442,7 @@ private:
|
|||||||
bool neverItem(AstCase* casep, AstConst* itemp) {
|
bool neverItem(AstCase* casep, AstConst* itemp) {
|
||||||
// Xs in case or casez are impossible due to two state simulations
|
// Xs in case or casez are impossible due to two state simulations
|
||||||
if (casep->casex()) {
|
if (casep->casex()) {
|
||||||
} else if (casep->casez()) {
|
} else if (casep->casez() || casep->caseInside()) {
|
||||||
if (itemp->num().isUnknown()) return true;
|
if (itemp->num().isUnknown()) return true;
|
||||||
} else {
|
} else {
|
||||||
if (itemp->num().isFourState()) return true;
|
if (itemp->num().isFourState()) return true;
|
||||||
@@ -448,10 +458,10 @@ private:
|
|||||||
if (isCaseTreeFast(nodep) && v3Global.opt.oCase()) {
|
if (isCaseTreeFast(nodep) && v3Global.opt.oCase()) {
|
||||||
// It's a simple priority encoder or complete statement
|
// It's a simple priority encoder or complete statement
|
||||||
// we can make a tree of statements to avoid extra comparisons
|
// we can make a tree of statements to avoid extra comparisons
|
||||||
m_statCaseFast++;
|
++m_statCaseFast;
|
||||||
replaceCaseFast(nodep); nodep=NULL;
|
replaceCaseFast(nodep); nodep=NULL;
|
||||||
} else {
|
} else {
|
||||||
m_statCaseSlow++;
|
++m_statCaseSlow;
|
||||||
replaceCaseComplicated(nodep); nodep=NULL;
|
replaceCaseComplicated(nodep); nodep=NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-4
@@ -1,14 +1,12 @@
|
|||||||
// -*- C++ -*-
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Break case statements up and add Unknown assigns
|
// DESCRIPTION: Verilator: Break case statements up and add Unknown assigns
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.org/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
|
||||||
//
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2014 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
|
|||||||
+8
-10
@@ -1,13 +1,12 @@
|
|||||||
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Add C++ casts across expression size changes
|
// DESCRIPTION: Verilator: Add C++ casts across expression size changes
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.org/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
|
||||||
//
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2004-2010 by Wilson Snyder. This program is free software; you can
|
// Copyright 2004-2014 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
@@ -77,8 +76,7 @@ private:
|
|||||||
AstNRelinker relinkHandle;
|
AstNRelinker relinkHandle;
|
||||||
nodep->unlinkFrBack(&relinkHandle);
|
nodep->unlinkFrBack(&relinkHandle);
|
||||||
//
|
//
|
||||||
AstCast* castp = new AstCast (nodep->fileline(), nodep, needsize);
|
AstCCast* castp = new AstCCast (nodep->fileline(), nodep, needsize, nodep->widthMin());
|
||||||
castp->width(needsize, nodep->widthMin());
|
|
||||||
relinkHandle.relink(castp);
|
relinkHandle.relink(castp);
|
||||||
//if (debug()>8) castp->dumpTree(cout,"-castins: ");
|
//if (debug()>8) castp->dumpTree(cout,"-castins: ");
|
||||||
//
|
//
|
||||||
@@ -97,13 +95,13 @@ private:
|
|||||||
insertCast(nodep, castSize(nodep->backp()));
|
insertCast(nodep, castSize(nodep->backp()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void insureLower32Cast(AstCast* nodep) {
|
void insureLower32Cast(AstCCast* nodep) {
|
||||||
// If we have uint64 = CAST(uint64(x)) then the upcasting
|
// If we have uint64 = CAST(uint64(x)) then the upcasting
|
||||||
// really needs to be CAST(uint64(CAST(uint32(x))).
|
// really needs to be CAST(uint64(CAST(uint32(x))).
|
||||||
// Otherwise a (uint64)(a>b) would return wrong value, as
|
// Otherwise a (uint64)(a>b) would return wrong value, as
|
||||||
// less than has undeterministic signedness.
|
// less than has undeterministic signedness.
|
||||||
if (nodep->isQuad() && !nodep->lhsp()->isQuad()
|
if (nodep->isQuad() && !nodep->lhsp()->isQuad()
|
||||||
&& !nodep->lhsp()->castCast()) {
|
&& !nodep->lhsp()->castCCast()) {
|
||||||
insertCast(nodep->lhsp(), VL_WORDSIZE);
|
insertCast(nodep->lhsp(), VL_WORDSIZE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -130,12 +128,12 @@ private:
|
|||||||
if (nodep->sizeMattersRhs()) insureCast(nodep->rhsp());
|
if (nodep->sizeMattersRhs()) insureCast(nodep->rhsp());
|
||||||
if (nodep->sizeMattersThs()) insureCast(nodep->thsp());
|
if (nodep->sizeMattersThs()) insureCast(nodep->thsp());
|
||||||
}
|
}
|
||||||
virtual void visit(AstCast* nodep, AstNUser*) {
|
virtual void visit(AstCCast* nodep, AstNUser*) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
insureLower32Cast(nodep);
|
insureLower32Cast(nodep);
|
||||||
nodep->user1(1);
|
nodep->user1(1);
|
||||||
}
|
}
|
||||||
virtual void visit(AstUnaryMin* nodep, AstNUser*) {
|
virtual void visit(AstNegate* nodep, AstNUser*) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
nodep->user1(nodep->lhsp()->user1());
|
nodep->user1(nodep->lhsp()->user1());
|
||||||
if (nodep->lhsp()->widthMin()==1) {
|
if (nodep->lhsp()->widthMin()==1) {
|
||||||
@@ -149,7 +147,7 @@ private:
|
|||||||
}
|
}
|
||||||
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
||||||
if (!nodep->lvalue()
|
if (!nodep->lvalue()
|
||||||
&& !nodep->backp()->castCast()
|
&& !nodep->backp()->castCCast()
|
||||||
&& nodep->backp()->castNodeMath()
|
&& nodep->backp()->castNodeMath()
|
||||||
&& nodep->backp()->width()
|
&& nodep->backp()->width()
|
||||||
&& castSize(nodep) != castSize(nodep->varp())) {
|
&& castSize(nodep) != castSize(nodep->varp())) {
|
||||||
|
|||||||
+2
-4
@@ -1,14 +1,12 @@
|
|||||||
// -*- C++ -*-
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Add C++ casts across expression size changes
|
// DESCRIPTION: Verilator: Add C++ casts across expression size changes
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.org/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
|
||||||
//
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2004-2010 by Wilson Snyder. This program is free software; you can
|
// Copyright 2004-2014 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
|
|||||||
+55
-23
@@ -1,13 +1,12 @@
|
|||||||
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Clock Domain Crossing Lint
|
// DESCRIPTION: Verilator: Clock Domain Crossing Lint
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.org/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
|
||||||
//
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2014 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
@@ -46,6 +45,8 @@
|
|||||||
#include "V3EmitV.h"
|
#include "V3EmitV.h"
|
||||||
#include "V3File.h"
|
#include "V3File.h"
|
||||||
|
|
||||||
|
#define CDC_WEIGHT_ASYNC 0x1000 // Weight for edges that feed async logic
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
|
|
||||||
class CdcBaseVisitor : public AstNVisitor {
|
class CdcBaseVisitor : public AstNVisitor {
|
||||||
@@ -65,9 +66,9 @@ class CdcEitherVertex : public V3GraphVertex {
|
|||||||
AstNode* m_nodep;
|
AstNode* m_nodep;
|
||||||
AstSenTree* m_srcDomainp;
|
AstSenTree* m_srcDomainp;
|
||||||
AstSenTree* m_dstDomainp;
|
AstSenTree* m_dstDomainp;
|
||||||
bool m_srcDomainSet;
|
bool m_srcDomainSet:1;
|
||||||
bool m_dstDomainSet;
|
bool m_dstDomainSet:1;
|
||||||
bool m_asyncPath;
|
bool m_asyncPath:1;
|
||||||
public:
|
public:
|
||||||
CdcEitherVertex(V3Graph* graphp, AstScope* scopep, AstNode* nodep)
|
CdcEitherVertex(V3Graph* graphp, AstScope* scopep, AstNode* nodep)
|
||||||
: V3GraphVertex(graphp), m_scopep(scopep), m_nodep(nodep)
|
: V3GraphVertex(graphp), m_scopep(scopep), m_nodep(nodep)
|
||||||
@@ -109,11 +110,12 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
class CdcLogicVertex : public CdcEitherVertex {
|
class CdcLogicVertex : public CdcEitherVertex {
|
||||||
bool m_hazard;
|
bool m_hazard:1;
|
||||||
bool m_isFlop;
|
bool m_isFlop:1;
|
||||||
public:
|
public:
|
||||||
CdcLogicVertex(V3Graph* graphp, AstScope* scopep, AstNode* nodep, AstSenTree* sensenodep)
|
CdcLogicVertex(V3Graph* graphp, AstScope* scopep, AstNode* nodep, AstSenTree* sensenodep)
|
||||||
: CdcEitherVertex(graphp,scopep,nodep), m_hazard(false), m_isFlop(false)
|
: CdcEitherVertex(graphp,scopep,nodep)
|
||||||
|
, m_hazard(false), m_isFlop(false)
|
||||||
{ srcDomainp(sensenodep); dstDomainp(sensenodep); }
|
{ srcDomainp(sensenodep); dstDomainp(sensenodep); }
|
||||||
virtual ~CdcLogicVertex() {}
|
virtual ~CdcLogicVertex() {}
|
||||||
// Accessors
|
// Accessors
|
||||||
@@ -132,7 +134,7 @@ class CdcDumpVisitor : public CdcBaseVisitor {
|
|||||||
private:
|
private:
|
||||||
// NODE STATE
|
// NODE STATE
|
||||||
//Entire netlist:
|
//Entire netlist:
|
||||||
// {statement}Node::user3p -> bool, indicating not hazard
|
// {statement}Node::user3 -> bool, indicating not hazard
|
||||||
ofstream* m_ofp; // Output file
|
ofstream* m_ofp; // Output file
|
||||||
string m_prefix;
|
string m_prefix;
|
||||||
|
|
||||||
@@ -290,9 +292,12 @@ private:
|
|||||||
void setNodeHazard(AstNode* nodep) {
|
void setNodeHazard(AstNode* nodep) {
|
||||||
// Need to not clear if warnings are off (rather than when report it)
|
// Need to not clear if warnings are off (rather than when report it)
|
||||||
// as bypassing this warning may turn up another path that isn't warning off'ed.
|
// as bypassing this warning may turn up another path that isn't warning off'ed.
|
||||||
|
// We can't modifyWarnOff here, as one instantiation might not be an issue until we find a hitting flop
|
||||||
|
// Furthermore, a module like a "Or" module would only get flagged once,
|
||||||
|
// even though the signals feeding it are radically different.
|
||||||
if (!m_domainp || m_domainp->hasCombo()) { // Source flop logic in a posedge block is OK for reset (not async though)
|
if (!m_domainp || m_domainp->hasCombo()) { // Source flop logic in a posedge block is OK for reset (not async though)
|
||||||
if (m_logicVertexp && !nodep->fileline()->warnIsOff(V3ErrorCode::CDCRSTLOGIC)) {
|
if (m_logicVertexp && !nodep->fileline()->warnIsOff(V3ErrorCode::CDCRSTLOGIC)) {
|
||||||
UINFO(9,"Set hazard "<<nodep<<endl);
|
UINFO(8,"Set hazard "<<nodep<<endl);
|
||||||
m_logicVertexp->setHazard(nodep);
|
m_logicVertexp->setHazard(nodep);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -310,7 +315,9 @@ private:
|
|||||||
UINFO(3,__FUNCTION__<<": "<<endl);
|
UINFO(3,__FUNCTION__<<": "<<endl);
|
||||||
//if (debug()>6) m_graph.dump();
|
//if (debug()>6) m_graph.dump();
|
||||||
if (debug()>6) m_graph.dumpDotFilePrefixed("cdc_pre");
|
if (debug()>6) m_graph.dumpDotFilePrefixed("cdc_pre");
|
||||||
m_graph.removeRedundantEdgesSum(&V3GraphEdge::followAlwaysTrue);
|
//
|
||||||
|
m_graph.removeRedundantEdges(&V3GraphEdge::followAlwaysTrue); // This will MAX across edge weights
|
||||||
|
//
|
||||||
m_graph.dumpDotFilePrefixed("cdc_simp");
|
m_graph.dumpDotFilePrefixed("cdc_simp");
|
||||||
//
|
//
|
||||||
analyzeReset();
|
analyzeReset();
|
||||||
@@ -335,7 +342,7 @@ private:
|
|||||||
if (CdcVarVertex* vvertexp = dynamic_cast<CdcVarVertex*>(itp)) {
|
if (CdcVarVertex* vvertexp = dynamic_cast<CdcVarVertex*>(itp)) {
|
||||||
if (vvertexp->cntAsyncRst()) {
|
if (vvertexp->cntAsyncRst()) {
|
||||||
m_userGeneration++; // Effectively a userClearVertices()
|
m_userGeneration++; // Effectively a userClearVertices()
|
||||||
UINFO(9, " Trace One async: "<<vvertexp<<endl);
|
UINFO(8, " Trace One async: "<<vvertexp<<endl);
|
||||||
// Twice, as we need to detect, then propagate
|
// Twice, as we need to detect, then propagate
|
||||||
CdcEitherVertex* markp = traceAsyncRecurse(vvertexp, false);
|
CdcEitherVertex* markp = traceAsyncRecurse(vvertexp, false);
|
||||||
if (markp) { // Mark is non-NULL if something bad on this path
|
if (markp) { // Mark is non-NULL if something bad on this path
|
||||||
@@ -351,8 +358,9 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
CdcEitherVertex* traceAsyncRecurse(CdcEitherVertex* vertexp, bool mark) {
|
CdcEitherVertex* traceAsyncRecurse(CdcEitherVertex* vertexp, bool mark) {
|
||||||
// Return vertex of any hazardous stuff attached, or NULL if OK
|
// First pass: Return vertex of any hazardous stuff attached, or NULL if OK
|
||||||
if (vertexp->user()>=m_userGeneration) return false; // Processed - prevent loop
|
// If first pass returns true, second pass calls asyncPath() on appropriate nodes
|
||||||
|
if (vertexp->user()>=m_userGeneration) return NULL; // Processed - prevent loop
|
||||||
vertexp->user(m_userGeneration);
|
vertexp->user(m_userGeneration);
|
||||||
|
|
||||||
CdcEitherVertex* mark_outp = NULL;
|
CdcEitherVertex* mark_outp = NULL;
|
||||||
@@ -375,7 +383,7 @@ private:
|
|||||||
CdcEitherVertex* eFromVertexp = (CdcEitherVertex*)edgep->fromp();
|
CdcEitherVertex* eFromVertexp = (CdcEitherVertex*)edgep->fromp();
|
||||||
eFromVertexp->asyncPath(true);
|
eFromVertexp->asyncPath(true);
|
||||||
}
|
}
|
||||||
return false;
|
return NULL;
|
||||||
}
|
}
|
||||||
// Also ok if from flop, but partially trace the flop so more obvious to users
|
// Also ok if from flop, but partially trace the flop so more obvious to users
|
||||||
if (vvertexp->fromFlop()) {
|
if (vvertexp->fromFlop()) {
|
||||||
@@ -383,7 +391,7 @@ private:
|
|||||||
CdcEitherVertex* eFromVertexp = (CdcEitherVertex*)edgep->fromp();
|
CdcEitherVertex* eFromVertexp = (CdcEitherVertex*)edgep->fromp();
|
||||||
eFromVertexp->asyncPath(true);
|
eFromVertexp->asyncPath(true);
|
||||||
}
|
}
|
||||||
return false;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -406,12 +414,15 @@ private:
|
|||||||
CdcEitherVertex* eToVertexp = (CdcEitherVertex*)edgep->top();
|
CdcEitherVertex* eToVertexp = (CdcEitherVertex*)edgep->top();
|
||||||
if (!eToVertexp) targetp = eToVertexp;
|
if (!eToVertexp) targetp = eToVertexp;
|
||||||
if (CdcLogicVertex* vvertexp = dynamic_cast<CdcLogicVertex*>(eToVertexp)) {
|
if (CdcLogicVertex* vvertexp = dynamic_cast<CdcLogicVertex*>(eToVertexp)) {
|
||||||
if (vvertexp->isFlop()) {
|
if (vvertexp->isFlop() // IE the target flop that is upsetting us
|
||||||
|
&& edgep->weight() >= CDC_WEIGHT_ASYNC) { // And this signal feeds an async reset line
|
||||||
targetp = eToVertexp;
|
targetp = eToVertexp;
|
||||||
|
//UINFO(9," targetasync "<<targetp->name()<<" "<<" from "<<vertexp->name()<<endl);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} // else it might be random logic that's not relevant
|
} // else it might be random logic that's not relevant
|
||||||
}
|
}
|
||||||
|
//UINFO(9," finalflop "<<targetp->name()<<" "<<targetp->nodep()->fileline()<<endl);
|
||||||
warnAndFile(markp->nodep(),V3ErrorCode::CDCRSTLOGIC,"Logic in path that feeds async reset, via signal: "+nodep->prettyName());
|
warnAndFile(markp->nodep(),V3ErrorCode::CDCRSTLOGIC,"Logic in path that feeds async reset, via signal: "+nodep->prettyName());
|
||||||
dumpAsyncRecurse(targetp, "", " ",0);
|
dumpAsyncRecurse(targetp, "", " ",0);
|
||||||
}
|
}
|
||||||
@@ -464,6 +475,12 @@ private:
|
|||||||
|
|
||||||
void edgeReport() {
|
void edgeReport() {
|
||||||
// Make report of all signal names and what clock edges they have
|
// Make report of all signal names and what clock edges they have
|
||||||
|
//
|
||||||
|
// Due to flattening, many interesting direct-connect signals are
|
||||||
|
// lost, so we can't make a report showing I/Os for a low level
|
||||||
|
// module. Disabling flattening though makes us consider each
|
||||||
|
// signal in it's own unique clock domain.
|
||||||
|
|
||||||
UINFO(3,__FUNCTION__<<": "<<endl);
|
UINFO(3,__FUNCTION__<<": "<<endl);
|
||||||
|
|
||||||
// Trace all sources and sinks
|
// Trace all sources and sinks
|
||||||
@@ -493,6 +510,10 @@ private:
|
|||||||
|
|
||||||
ostringstream os;
|
ostringstream os;
|
||||||
os.setf(ios::left);
|
os.setf(ios::left);
|
||||||
|
// Module name - doesn't work due to flattening having lost the original
|
||||||
|
// so we assume the modulename matches the filebasename
|
||||||
|
string fname = vvertexp->varScp()->fileline()->filebasename() + ":";
|
||||||
|
os<<" "<<setw(20)<<fname;
|
||||||
os<<" "<<setw(8)<<whatp;
|
os<<" "<<setw(8)<<whatp;
|
||||||
os<<" "<<setw(40)<<vvertexp->varScp()->prettyName();
|
os<<" "<<setw(40)<<vvertexp->varScp()->prettyName();
|
||||||
os<<" SRC=";
|
os<<" SRC=";
|
||||||
@@ -505,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) {
|
for (deque<string>::iterator it = report.begin(); it!=report.end(); ++it) {
|
||||||
*ofp << *it;
|
*ofp << *it;
|
||||||
}
|
}
|
||||||
@@ -613,8 +634,9 @@ private:
|
|||||||
if (!varscp) nodep->v3fatalSrc("Var didn't get varscoped in V3Scope.cpp\n");
|
if (!varscp) nodep->v3fatalSrc("Var didn't get varscoped in V3Scope.cpp\n");
|
||||||
CdcVarVertex* varvertexp = makeVarVertex(varscp);
|
CdcVarVertex* varvertexp = makeVarVertex(varscp);
|
||||||
UINFO(5," VARREF to "<<varscp<<endl);
|
UINFO(5," VARREF to "<<varscp<<endl);
|
||||||
// We use weight of one; if we ref the var more than once, when we simplify,
|
// We use weight of one for normal edges,
|
||||||
// the weight will increase
|
// Weight of CDC_WEIGHT_ASYNC to indicate feeds async (for reporting)
|
||||||
|
// When simplify we'll take the MAX weight
|
||||||
if (nodep->lvalue()) {
|
if (nodep->lvalue()) {
|
||||||
new V3GraphEdge(&m_graph, m_logicVertexp, varvertexp, 1);
|
new V3GraphEdge(&m_graph, m_logicVertexp, varvertexp, 1);
|
||||||
if (m_inDly) {
|
if (m_inDly) {
|
||||||
@@ -623,7 +645,13 @@ private:
|
|||||||
varvertexp->srcDomainSet(true);
|
varvertexp->srcDomainSet(true);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
new V3GraphEdge(&m_graph, varvertexp, m_logicVertexp, 1);
|
if (varvertexp->cntAsyncRst()) {
|
||||||
|
//UINFO(9," edgeasync "<<varvertexp->name()<<" to "<<m_logicVertexp<<endl);
|
||||||
|
new V3GraphEdge(&m_graph, varvertexp, m_logicVertexp, CDC_WEIGHT_ASYNC);
|
||||||
|
} else {
|
||||||
|
//UINFO(9," edgena "<<varvertexp->name()<<" to "<<m_logicVertexp<<endl);
|
||||||
|
new V3GraphEdge(&m_graph, varvertexp, m_logicVertexp, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -642,6 +670,9 @@ private:
|
|||||||
virtual void visit(AstAlways* nodep, AstNUser*) {
|
virtual void visit(AstAlways* nodep, AstNUser*) {
|
||||||
iterateNewStmt(nodep);
|
iterateNewStmt(nodep);
|
||||||
}
|
}
|
||||||
|
virtual void visit(AstAlwaysPublic* nodep, AstNUser*) {
|
||||||
|
// CDC doesn't care about public variables
|
||||||
|
}
|
||||||
virtual void visit(AstCFunc* nodep, AstNUser*) {
|
virtual void visit(AstCFunc* nodep, AstNUser*) {
|
||||||
iterateNewStmt(nodep);
|
iterateNewStmt(nodep);
|
||||||
}
|
}
|
||||||
@@ -681,6 +712,7 @@ private:
|
|||||||
virtual void visit(AstInitial* nodep, AstNUser*) { }
|
virtual void visit(AstInitial* nodep, AstNUser*) { }
|
||||||
virtual void visit(AstTraceInc* nodep, AstNUser*) { }
|
virtual void visit(AstTraceInc* nodep, AstNUser*) { }
|
||||||
virtual void visit(AstCoverToggle* nodep, AstNUser*) { }
|
virtual void visit(AstCoverToggle* nodep, AstNUser*) { }
|
||||||
|
virtual void visit(AstNodeDType* nodep, AstNUser*) { }
|
||||||
|
|
||||||
//--------------------
|
//--------------------
|
||||||
// Default
|
// Default
|
||||||
@@ -717,7 +749,7 @@ public:
|
|||||||
|
|
||||||
nodep->accept(*this);
|
nodep->accept(*this);
|
||||||
analyze();
|
analyze();
|
||||||
//edgeReport(); // Not useful at the moment
|
if (debug()>=1) edgeReport(); // Not useful to users at the moment
|
||||||
|
|
||||||
if (0) { *m_ofp<<"\nDBG-test-dumper\n"; V3EmitV::verilogPrefixedTree(nodep, *m_ofp, "DBG ",40,NULL,true); *m_ofp<<endl; }
|
if (0) { *m_ofp<<"\nDBG-test-dumper\n"; V3EmitV::verilogPrefixedTree(nodep, *m_ofp, "DBG ",40,NULL,true); *m_ofp<<endl; }
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-4
@@ -1,14 +1,12 @@
|
|||||||
// -*- C++ -*-
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Break always into sensitivity block domains
|
// DESCRIPTION: Verilator: Break always into sensitivity block domains
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.org/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
|
||||||
//
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2014 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
|
|||||||
+52
-22
@@ -1,13 +1,12 @@
|
|||||||
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Add temporaries, such as for changed nodes
|
// DESCRIPTION: Verilator: Add temporaries, such as for changed nodes
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.org/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
|
||||||
//
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2014 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
@@ -59,6 +58,12 @@ private:
|
|||||||
AstScope* m_scopetopp; // Scope under TOPSCOPE
|
AstScope* m_scopetopp; // Scope under TOPSCOPE
|
||||||
AstCFunc* m_chgFuncp; // Change function we're building
|
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
|
// METHODS
|
||||||
static int debug() {
|
static int debug() {
|
||||||
static int level = -1;
|
static int level = -1;
|
||||||
@@ -66,14 +71,34 @@ private:
|
|||||||
return level;
|
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) {
|
void genChangeDet(AstVarScope* vscp) {
|
||||||
#ifdef NEW_ORDERING
|
|
||||||
vscp->v3fatalSrc("Not applicable\n");
|
|
||||||
#endif
|
|
||||||
AstVar* varp = vscp->varp();
|
AstVar* varp = vscp->varp();
|
||||||
vscp->v3warn(IMPERFECTSCH,"Imperfect scheduling of variable: "<<vscp);
|
vscp->v3warn(IMPERFECTSCH,"Imperfect scheduling of variable: "<<vscp);
|
||||||
if (!varp->dtypeSkipRefp()->castBasicDType()) {
|
AstUnpackArrayDType* uarrayp = varp->dtypeSkipRefp()->castUnpackArrayDType();
|
||||||
vscp->v3error("Unsupported: Can't detect changes on arrayed variable (probably with UNOPTFLAT warning suppressed): "<<varp->prettyName());
|
AstPackArrayDType* parrayp = varp->dtypeSkipRefp()->castPackArrayDType();
|
||||||
|
AstNodeClassDType *classp = varp->dtypeSkipRefp()->castNodeClassDType();
|
||||||
|
bool isUnpackArray = uarrayp;
|
||||||
|
bool isPackArray = parrayp;
|
||||||
|
bool isClass = classp && classp->packedUnsup();
|
||||||
|
int elements = isUnpackArray ? uarrayp->elementsConst() : 1;
|
||||||
|
if (isUnpackArray && (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 (!isUnpackArray && !isClass && !isPackArray
|
||||||
|
&& !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 {
|
} else {
|
||||||
string newvarname = "__Vchglast__"+vscp->scopep()->nameDotless()+"__"+varp->shortName();
|
string newvarname = "__Vchglast__"+vscp->scopep()->nameDotless()+"__"+varp->shortName();
|
||||||
// Create: VARREF(_last)
|
// Create: VARREF(_last)
|
||||||
@@ -84,17 +109,23 @@ private:
|
|||||||
m_topModp->addStmtp(newvarp);
|
m_topModp->addStmtp(newvarp);
|
||||||
AstVarScope* newvscp = new AstVarScope(vscp->fileline(), m_scopetopp, newvarp);
|
AstVarScope* newvscp = new AstVarScope(vscp->fileline(), m_scopetopp, newvarp);
|
||||||
m_scopetopp->addVarp(newvscp);
|
m_scopetopp->addVarp(newvscp);
|
||||||
AstChangeDet* changep
|
for (int index=0; index<elements; ++index) {
|
||||||
= new AstChangeDet (vscp->fileline(),
|
AstChangeDet* changep
|
||||||
new AstVarRef(vscp->fileline(), vscp, false),
|
= new AstChangeDet (vscp->fileline(),
|
||||||
new AstVarRef(vscp->fileline(), newvscp, false),
|
aselIfNeeded(isUnpackArray, index,
|
||||||
false);
|
new AstVarRef(vscp->fileline(), vscp, false)),
|
||||||
m_chgFuncp->addStmtsp(changep);
|
aselIfNeeded(isUnpackArray, index,
|
||||||
AstAssign* initp
|
new AstVarRef(vscp->fileline(), newvscp, false)),
|
||||||
= new AstAssign (vscp->fileline(),
|
false);
|
||||||
new AstVarRef(vscp->fileline(), newvscp, true),
|
m_chgFuncp->addStmtsp(changep);
|
||||||
new AstVarRef(vscp->fileline(), vscp, false));
|
AstAssign* initp
|
||||||
m_chgFuncp->addFinalsp(initp);
|
= new AstAssign (vscp->fileline(),
|
||||||
|
aselIfNeeded(isUnpackArray, index,
|
||||||
|
new AstVarRef(vscp->fileline(), newvscp, true)),
|
||||||
|
aselIfNeeded(isUnpackArray, index,
|
||||||
|
new AstVarRef(vscp->fileline(), vscp, false)));
|
||||||
|
m_chgFuncp->addFinalsp(initp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,7 +146,7 @@ private:
|
|||||||
if (!scopep) nodep->v3fatalSrc("No scope found on top level, perhaps you have no statements?\n");
|
if (!scopep) nodep->v3fatalSrc("No scope found on top level, perhaps you have no statements?\n");
|
||||||
m_scopetopp = scopep;
|
m_scopetopp = scopep;
|
||||||
// Create change detection function
|
// Create change detection function
|
||||||
m_chgFuncp = new AstCFunc(nodep->fileline(), "_change_request", scopep, "IData");
|
m_chgFuncp = new AstCFunc(nodep->fileline(), "_change_request", scopep, "QData");
|
||||||
m_chgFuncp->argTypes(EmitCBaseVisitor::symClassVar());
|
m_chgFuncp->argTypes(EmitCBaseVisitor::symClassVar());
|
||||||
m_chgFuncp->symProlog(true);
|
m_chgFuncp->symProlog(true);
|
||||||
m_chgFuncp->declPrivate(true);
|
m_chgFuncp->declPrivate(true);
|
||||||
@@ -128,8 +159,7 @@ private:
|
|||||||
virtual void visit(AstVarScope* nodep, AstNUser*) {
|
virtual void visit(AstVarScope* nodep, AstNUser*) {
|
||||||
if (nodep->isCircular()) {
|
if (nodep->isCircular()) {
|
||||||
UINFO(8," CIRC "<<nodep<<endl);
|
UINFO(8," CIRC "<<nodep<<endl);
|
||||||
if (!nodep->user1()) {
|
if (!nodep->user1SetOnce()) {
|
||||||
nodep->user1(true);
|
|
||||||
genChangeDet(nodep);
|
genChangeDet(nodep);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-4
@@ -1,14 +1,12 @@
|
|||||||
// -*- C++ -*-
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Pre C-Emit stage changes
|
// DESCRIPTION: Verilator: Pre C-Emit stage changes
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.org/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
|
||||||
//
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2014 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
|
|||||||
+28
-11
@@ -1,13 +1,12 @@
|
|||||||
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Add temporaries, such as for clean nodes
|
// DESCRIPTION: Verilator: Add temporaries, such as for clean nodes
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.org/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
|
||||||
//
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2014 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
@@ -24,7 +23,7 @@
|
|||||||
// For each math operator, if it requires a clean operand,
|
// For each math operator, if it requires a clean operand,
|
||||||
// and the operand is dirty, insert a CLEAN node.
|
// and the operand is dirty, insert a CLEAN node.
|
||||||
// Resize operands to C++ 32/64/wide types.
|
// 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
|
// NODE STATE
|
||||||
// Entire netlist:
|
// Entire netlist:
|
||||||
// AstNode::user() -> CleanState. For this node, 0==UNKNOWN
|
// 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;
|
AstUser1InUse m_inuser1;
|
||||||
AstUser2InUse m_inuser2;
|
AstUser2InUse m_inuser2;
|
||||||
|
AstUser3InUse m_inuser3;
|
||||||
|
|
||||||
// TYPES
|
// TYPES
|
||||||
enum CleanState { CS_UNKNOWN, CS_CLEAN, CS_DIRTY };
|
enum CleanState { CS_UNKNOWN, CS_CLEAN, CS_DIRTY };
|
||||||
@@ -70,16 +71,28 @@ private:
|
|||||||
else if (nodep->width()<=VL_QUADSIZE) return VL_QUADSIZE;
|
else if (nodep->width()<=VL_QUADSIZE) return VL_QUADSIZE;
|
||||||
else return nodep->widthWords()*VL_WORDSIZE;
|
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->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) {
|
void computeCppWidth (AstNode* nodep) {
|
||||||
if (!nodep->user2()) {
|
if (!nodep->user2() && nodep->hasDType()) {
|
||||||
if (nodep->castVar() || nodep->castNodeDType()) { // Don't want to change variable widths!
|
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 {
|
} else {
|
||||||
setCppWidth(nodep, cppWidth(nodep), nodep->widthMin());
|
setCppWidth(nodep);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -116,7 +129,7 @@ private:
|
|||||||
AstNode* cleanp = new AstAnd (nodep->fileline(),
|
AstNode* cleanp = new AstAnd (nodep->fileline(),
|
||||||
new AstConst (nodep->fileline(), mask),
|
new AstConst (nodep->fileline(), mask),
|
||||||
nodep);
|
nodep);
|
||||||
setCppWidth (cleanp, cppWidth(nodep), nodep->widthMin());
|
cleanp->dtypeFrom(nodep); // Otherwise the AND normally picks LHS
|
||||||
relinkHandle.relink(cleanp);
|
relinkHandle.relink(cleanp);
|
||||||
}
|
}
|
||||||
void insureClean(AstNode* nodep) {
|
void insureClean(AstNode* nodep) {
|
||||||
@@ -225,6 +238,10 @@ private:
|
|||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
insureCleanAndNext (nodep->valuep());
|
insureCleanAndNext (nodep->valuep());
|
||||||
}
|
}
|
||||||
|
virtual void visit(AstTypedef* nodep, AstNUser*) {
|
||||||
|
// No cleaning, or would loose pointer to enum
|
||||||
|
nodep->iterateChildren(*this);
|
||||||
|
}
|
||||||
|
|
||||||
// Control flow operators
|
// Control flow operators
|
||||||
virtual void visit(AstNodeCond* nodep, AstNUser*) {
|
virtual void visit(AstNodeCond* nodep, AstNUser*) {
|
||||||
|
|||||||
+2
-4
@@ -1,14 +1,12 @@
|
|||||||
// -*- C++ -*-
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Pre C-Emit stage changes
|
// DESCRIPTION: Verilator: Pre C-Emit stage changes
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.org/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
|
||||||
//
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2014 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
|
|||||||
+8
-9
@@ -1,14 +1,12 @@
|
|||||||
// -*- C++ -*-
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Break always into sensitivity active domains
|
// DESCRIPTION: Verilator: Break always into sensitivity active domains
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.org/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
|
||||||
//
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2008-2010 by Wilson Snyder. This program is free software; you can
|
// Copyright 2008-2014 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
@@ -315,6 +313,7 @@ public:
|
|||||||
m_exprp = exprp;
|
m_exprp = exprp;
|
||||||
m_original = original;
|
m_original = original;
|
||||||
m_state = STATE_UNKNOWN;
|
m_state = STATE_UNKNOWN;
|
||||||
|
m_cloning = false;
|
||||||
if (debug()>=9) nodep->dumpTree(cout," GateBodyIn: ");
|
if (debug()>=9) nodep->dumpTree(cout," GateBodyIn: ");
|
||||||
nodep->bodysp()->iterateAndNext(*this);
|
nodep->bodysp()->iterateAndNext(*this);
|
||||||
if (debug()>=9) nodep->dumpTree(cout," GateBodyOut: ");
|
if (debug()>=9) nodep->dumpTree(cout," GateBodyOut: ");
|
||||||
@@ -685,6 +684,7 @@ class GaterVisitor : public GaterBaseVisitor {
|
|||||||
AstNode* bodyp = nodep->bodysp()->cloneTree(true);
|
AstNode* bodyp = nodep->bodysp()->cloneTree(true);
|
||||||
|
|
||||||
AstAlways* alwp = new AstAlways(nodep->fileline(),
|
AstAlways* alwp = new AstAlways(nodep->fileline(),
|
||||||
|
nodep->keyword(),
|
||||||
sensesp,
|
sensesp,
|
||||||
bodyp);
|
bodyp);
|
||||||
|
|
||||||
@@ -696,7 +696,7 @@ class GaterVisitor : public GaterBaseVisitor {
|
|||||||
// Blow old statements from new body
|
// Blow old statements from new body
|
||||||
GaterBodyVisitor(alwp,exprp,false);
|
GaterBodyVisitor(alwp,exprp,false);
|
||||||
|
|
||||||
m_statGaters++;
|
++m_statGaters;
|
||||||
if (debug()>=9) alwp->dumpTree(cout," new: ");
|
if (debug()>=9) alwp->dumpTree(cout," new: ");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -704,8 +704,7 @@ class GaterVisitor : public GaterBaseVisitor {
|
|||||||
virtual void visit(AstAlways* nodep, AstNUser*) {
|
virtual void visit(AstAlways* nodep, AstNUser*) {
|
||||||
if (debug()>=9) cout<<endl<<endl<<endl;
|
if (debug()>=9) cout<<endl<<endl<<endl;
|
||||||
UINFO(5, "Gater: ALWAYS: "<<nodep<<endl);
|
UINFO(5, "Gater: ALWAYS: "<<nodep<<endl);
|
||||||
if (nodep->user4()) return;
|
if (nodep->user4SetOnce()) return;
|
||||||
nodep->user4(1);
|
|
||||||
|
|
||||||
clear();
|
clear();
|
||||||
|
|
||||||
@@ -862,9 +861,9 @@ class GaterVisitor : public GaterBaseVisitor {
|
|||||||
m_stmtVscp = NULL;
|
m_stmtVscp = NULL;
|
||||||
m_stmtInPli = false;
|
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
|
// 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);
|
scoreboardPli(nodep);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
|
|||||||
+2
-4
@@ -1,14 +1,12 @@
|
|||||||
// -*- C++ -*-
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Break always into clock gated blocks
|
// DESCRIPTION: Verilator: Break always into clock gated blocks
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.org/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
|
||||||
//
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2014 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
|
|||||||
+20
-151
@@ -1,13 +1,12 @@
|
|||||||
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Clocking POS/NEGEDGE insertion
|
// DESCRIPTION: Verilator: Clocking POS/NEGEDGE insertion
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.org/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
|
||||||
//
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2014 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
@@ -83,10 +82,9 @@ private:
|
|||||||
AstVarScope* getCreateLastClk(AstVarScope* vscp) {
|
AstVarScope* getCreateLastClk(AstVarScope* vscp) {
|
||||||
if (vscp->user1p()) return ((AstVarScope*)vscp->user1p());
|
if (vscp->user1p()) return ((AstVarScope*)vscp->user1p());
|
||||||
AstVar* varp = vscp->varp();
|
AstVar* varp = vscp->varp();
|
||||||
if (varp->width()!=1) varp->v3error("Unsupported: Clock edge on non-single bit signal: "<<varp->prettyName());
|
if (!varp->width1()) varp->v3error("Unsupported: Clock edge on non-single bit signal: "<<varp->prettyName());
|
||||||
string newvarname = ((string)"__Vclklast__"+vscp->scopep()->nameDotless()+"__"+varp->shortName());
|
string newvarname = ((string)"__Vclklast__"+vscp->scopep()->nameDotless()+"__"+varp->name());
|
||||||
AstVar* newvarp = new AstVar (vscp->fileline(), AstVarType::MODULETEMP, newvarname, AstLogicPacked(), 1);
|
AstVar* newvarp = new AstVar (vscp->fileline(), AstVarType::MODULETEMP, newvarname, VFlagLogicPacked(), 1);
|
||||||
newvarp->width(1,1);
|
|
||||||
m_modp->addStmtp(newvarp);
|
m_modp->addStmtp(newvarp);
|
||||||
AstVarScope* newvscp = new AstVarScope(vscp->fileline(), m_scopep, newvarp);
|
AstVarScope* newvscp = new AstVarScope(vscp->fileline(), m_scopep, newvarp);
|
||||||
vscp->user1p(newvscp);
|
vscp->user1p(newvscp);
|
||||||
@@ -104,7 +102,7 @@ private:
|
|||||||
AstVarScope* getCreateLocalVar(FileLine* fl, const string& name, AstVar* examplep, int width) {
|
AstVarScope* getCreateLocalVar(FileLine* fl, const string& name, AstVar* examplep, int width) {
|
||||||
AstVar* newvarp;
|
AstVar* newvarp;
|
||||||
if (width) {
|
if (width) {
|
||||||
newvarp = new AstVar (fl, AstVarType::BLOCKTEMP, name, AstLogicPacked(), width);
|
newvarp = new AstVar (fl, AstVarType::BLOCKTEMP, name, VFlagLogicPacked(), width);
|
||||||
} else {
|
} else {
|
||||||
newvarp = new AstVar (fl, AstVarType::BLOCKTEMP, name, examplep); // No range; 1 bit.
|
newvarp = new AstVar (fl, AstVarType::BLOCKTEMP, name, examplep); // No range; 1 bit.
|
||||||
}
|
}
|
||||||
@@ -322,40 +320,14 @@ private:
|
|||||||
}
|
}
|
||||||
nodep->deleteTree(); nodep = NULL;
|
nodep->deleteTree(); nodep = NULL;
|
||||||
}
|
}
|
||||||
void moveInitial(AstActive* nodep) {
|
|
||||||
// Change to CFunc
|
|
||||||
AstNode* stmtsp = nodep->stmtsp();
|
|
||||||
if (stmtsp) {
|
|
||||||
if (!m_scopep) nodep->v3fatalSrc("Initial Active not under scope\n");
|
|
||||||
AstCFunc* funcp = new AstCFunc(nodep->fileline(), "_initial__"+m_scopep->nameDotless(),
|
|
||||||
m_scopep);
|
|
||||||
funcp->argTypes(EmitCBaseVisitor::symClassVar());
|
|
||||||
funcp->symProlog(true);
|
|
||||||
funcp->slow(true);
|
|
||||||
stmtsp->unlinkFrBackWithNext();
|
|
||||||
funcp->addStmtsp(stmtsp);
|
|
||||||
nodep->replaceWith(funcp);
|
|
||||||
// Add top level call to it
|
|
||||||
AstCCall* callp = new AstCCall(nodep->fileline(), funcp);
|
|
||||||
callp->argTypes("vlSymsp");
|
|
||||||
m_initFuncp->addStmtsp(callp);
|
|
||||||
} else {
|
|
||||||
nodep->unlinkFrBack();
|
|
||||||
}
|
|
||||||
nodep->deleteTree(); nodep=NULL;
|
|
||||||
}
|
|
||||||
virtual void visit(AstCFunc* nodep, AstNUser*) {
|
virtual void visit(AstCFunc* nodep, AstNUser*) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
// Link to global function
|
// Link to global function
|
||||||
if (nodep->formCallTree()) {
|
if (nodep->formCallTree()) {
|
||||||
if (nodep->name() == "_final") {
|
UINFO(4, " formCallTree "<<nodep<<endl);
|
||||||
UINFO(4, " formCallTree "<<nodep<<endl);
|
AstCCall* callp = new AstCCall(nodep->fileline(), nodep);
|
||||||
AstCCall* callp = new AstCCall(nodep->fileline(), nodep);
|
callp->argTypes("vlSymsp");
|
||||||
callp->argTypes("vlSymsp");
|
m_finalFuncp->addStmtsp(callp);
|
||||||
m_finalFuncp->addStmtsp(callp);
|
|
||||||
} else {
|
|
||||||
nodep->v3fatalSrc("Unknown CFunc name. Make code more generic, with a map of func names");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
virtual void visit(AstSenTree* nodep, AstNUser*) {
|
virtual void visit(AstSenTree* nodep, AstNUser*) {
|
||||||
@@ -371,13 +343,14 @@ private:
|
|||||||
if (m_untilp) m_untilp->addBodysp(stmtsp); // In a until loop, add to body
|
if (m_untilp) m_untilp->addBodysp(stmtsp); // In a until loop, add to body
|
||||||
else m_settleFuncp->addStmtsp(stmtsp); // else add to top level function
|
else m_settleFuncp->addStmtsp(stmtsp); // else add to top level function
|
||||||
}
|
}
|
||||||
|
void addToInitial(AstNode* stmtsp) {
|
||||||
|
if (m_untilp) m_untilp->addBodysp(stmtsp); // In a until loop, add to body
|
||||||
|
else m_initFuncp->addStmtsp(stmtsp); // else add to top level function
|
||||||
|
}
|
||||||
virtual void visit(AstActive* nodep, AstNUser*) {
|
virtual void visit(AstActive* nodep, AstNUser*) {
|
||||||
// Careful if adding variables here, ACTIVES can be under other ACTIVES
|
// Careful if adding variables here, ACTIVES can be under other ACTIVES
|
||||||
// Need to save and restore any member state in AstUntilStable block
|
// Need to save and restore any member state in AstUntilStable block
|
||||||
if (nodep->hasInitial()) {
|
if (!m_topScopep || !nodep->stmtsp()) {
|
||||||
moveInitial(nodep);
|
|
||||||
}
|
|
||||||
else if (!m_topScopep || !nodep->stmtsp()) {
|
|
||||||
// Not at the top or empty block...
|
// Not at the top or empty block...
|
||||||
// Only empty blocks should be leftover on the non-top. Killem.
|
// Only empty blocks should be leftover on the non-top. Killem.
|
||||||
if (nodep->stmtsp()) nodep->v3fatalSrc("Non-empty lower active");
|
if (nodep->stmtsp()) nodep->v3fatalSrc("Non-empty lower active");
|
||||||
@@ -387,6 +360,7 @@ private:
|
|||||||
AstNode* stmtsp = nodep->stmtsp()->unlinkFrBackWithNext();
|
AstNode* stmtsp = nodep->stmtsp()->unlinkFrBackWithNext();
|
||||||
if (nodep->hasClocked()) {
|
if (nodep->hasClocked()) {
|
||||||
// Remember the latest sensitivity so we can compare it next time
|
// Remember the latest sensitivity so we can compare it next time
|
||||||
|
if (nodep->hasInitial()) nodep->v3fatalSrc("Initial block should not have clock sensitivity");
|
||||||
if (m_lastSenp && nodep->sensesp()->sameTree(m_lastSenp)) {
|
if (m_lastSenp && nodep->sensesp()->sameTree(m_lastSenp)) {
|
||||||
UINFO(4," sameSenseTree\n");
|
UINFO(4," sameSenseTree\n");
|
||||||
} else {
|
} else {
|
||||||
@@ -398,6 +372,10 @@ private:
|
|||||||
}
|
}
|
||||||
// Move statements to if
|
// Move statements to if
|
||||||
m_lastIfp->addIfsp(stmtsp);
|
m_lastIfp->addIfsp(stmtsp);
|
||||||
|
} else if (nodep->hasInitial()) {
|
||||||
|
// Don't need to: clearLastSen();, as we're adding it to different cfunc
|
||||||
|
// Move statements to function
|
||||||
|
addToInitial(stmtsp);
|
||||||
} else if (nodep->hasSettle()) {
|
} else if (nodep->hasSettle()) {
|
||||||
// Don't need to: clearLastSen();, as we're adding it to different cfunc
|
// Don't need to: clearLastSen();, as we're adding it to different cfunc
|
||||||
// Move statements to function
|
// Move statements to function
|
||||||
@@ -412,115 +390,6 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef NEW_ORDERING
|
|
||||||
virtual void visit(AstUntilStable* nodep, AstNUser*) {
|
|
||||||
// Process any sub ACTIVE statements first
|
|
||||||
UINFO(4," UNTILSTABLE "<<nodep<<endl);
|
|
||||||
{
|
|
||||||
// Keep vars if in middle of other stable
|
|
||||||
AstUntilStable* lastUntilp = m_untilp;
|
|
||||||
AstSenTree* lastSenp = m_lastSenp;
|
|
||||||
AstIf* lastIfp = m_lastIfp;
|
|
||||||
m_untilp = nodep;
|
|
||||||
m_lastSenp = NULL;
|
|
||||||
m_lastIfp = NULL;
|
|
||||||
nodep->iterateChildren(*this);
|
|
||||||
m_untilp = lastUntilp;
|
|
||||||
m_lastSenp = lastSenp;
|
|
||||||
m_lastIfp = lastIfp;
|
|
||||||
}
|
|
||||||
// Set "unstable" to 100. (non-stabilization count)
|
|
||||||
// int __VclockLoop = 0
|
|
||||||
// IData __Vchange = 1
|
|
||||||
// while (__Vchange) {
|
|
||||||
// Save old values of each until stable variable
|
|
||||||
// Evaluate the body
|
|
||||||
// __Vchange = {change_detect} contribution
|
|
||||||
// if (++__VclockLoop > 100) converge_error
|
|
||||||
if (debug()>4) nodep->dumpTree(cout, " UntilSt-old: ");
|
|
||||||
FileLine* fl = nodep->fileline();
|
|
||||||
if (nodep->bodysp()) fl = nodep->bodysp()->fileline(); // Point to applicable code...
|
|
||||||
m_stableNum++;
|
|
||||||
AstNode* origBodysp = nodep->bodysp(); if (origBodysp) origBodysp->unlinkFrBackWithNext();
|
|
||||||
AstVarScope* changeVarp = getCreateLocalVar(fl, "__Vchange"+cvtToStr(m_stableNum), NULL, 32);
|
|
||||||
AstVarScope* countVarp = getCreateLocalVar(fl, "__VloopCount"+cvtToStr(m_stableNum), NULL, 32);
|
|
||||||
AstWhile* untilp = new AstWhile(fl, new AstVarRef(fl, changeVarp, false), NULL);
|
|
||||||
AstNode* preUntilp = new AstComment(fl, "Change loop "+cvtToStr(m_stableNum));
|
|
||||||
preUntilp->addNext(new AstAssign(fl, new AstVarRef(fl, changeVarp, true),
|
|
||||||
new AstConst(fl, 1)));
|
|
||||||
preUntilp->addNext(new AstAssign(fl, new AstVarRef(fl, countVarp, true),
|
|
||||||
new AstConst(fl, 0)));
|
|
||||||
|
|
||||||
// Add stable variables & preinits
|
|
||||||
AstNode* setChglastp = NULL;
|
|
||||||
for (AstVarRef* varrefp = nodep->stablesp(); varrefp; varrefp=varrefp->nextp()->castVarRef()) {
|
|
||||||
AstVarScope* cmpvscp = getCreateLocalVar(varrefp->varp()->fileline(),
|
|
||||||
"__Vchglast"+cvtToStr(m_stableNum)+"__"+varrefp->name(),
|
|
||||||
varrefp->varp(), 0);
|
|
||||||
varrefp->varScopep()->user2p(cmpvscp);
|
|
||||||
setChglastp = setChglastp->addNext(
|
|
||||||
new AstAssign(fl, new AstVarRef(fl, cmpvscp, true),
|
|
||||||
new AstVarRef(fl, varrefp->varScopep(), false)));
|
|
||||||
}
|
|
||||||
if (!setChglastp) nodep->v3fatalSrc("UntilStable without any variables");
|
|
||||||
untilp->addBodysp(setChglastp);
|
|
||||||
untilp->addBodysp(new AstComment(fl, "Change Loop body begin"));
|
|
||||||
if (origBodysp) untilp->addBodysp(origBodysp);
|
|
||||||
untilp->addBodysp(new AstComment(fl, "Change Loop body end"));
|
|
||||||
// Add stable checks
|
|
||||||
// The order of the variables doesn't matter, but it's more expensive to test
|
|
||||||
// wide variables, and more so 64 bit wide ones. Someday it might be faster to
|
|
||||||
// set the changed variable in a "distributed" fashion over the code, IE,
|
|
||||||
// logic... logic.... a=....; Changed |= (a ^ old_a); more logic... Changed |=...
|
|
||||||
// But then, one hopes users don't have much unoptimized logic
|
|
||||||
AstNode* changeExprp = NULL;
|
|
||||||
int doublecount = 0;
|
|
||||||
for (int wide=0; wide<3; wide++) { // Adding backwards; wide, quad, then normal
|
|
||||||
for (AstVarRef* varrefp = nodep->stablesp(); varrefp; varrefp=varrefp->nextp()->castVarRef()) {
|
|
||||||
if (wide== ( varrefp->isQuad()?0:(varrefp->isWide() ? 1:2))) {
|
|
||||||
AstVarScope* cmpvscp = (AstVarScope*)(varrefp->varScopep()->user2p());
|
|
||||||
if (!cmpvscp) varrefp->v3fatalSrc("should have created above");
|
|
||||||
AstChangeXor* changep
|
|
||||||
= new AstChangeXor (fl,
|
|
||||||
new AstVarRef(fl, varrefp->varScopep(), false),
|
|
||||||
new AstVarRef(fl, cmpvscp, false));
|
|
||||||
if (!changeExprp) changeExprp = changep;
|
|
||||||
else if (doublecount++ > DOUBLE_OR_RATE) {
|
|
||||||
doublecount = 0;
|
|
||||||
changeExprp = new AstLogOr (fl, changep, changeExprp);
|
|
||||||
} else {
|
|
||||||
changeExprp = new AstOr (fl, changep, changeExprp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!changeExprp) nodep->v3fatalSrc("UntilStable without any variables");
|
|
||||||
changeExprp = new AstAssign(fl, new AstVarRef(fl, changeVarp, true),
|
|
||||||
changeExprp);
|
|
||||||
untilp->addBodysp(changeExprp);
|
|
||||||
//
|
|
||||||
// Final body
|
|
||||||
AstNode* ifstmtp = new AstAssign(fl, new AstVarRef(fl, countVarp, true),
|
|
||||||
new AstAdd(fl, new AstConst(fl, 1),
|
|
||||||
new AstVarRef(fl, countVarp, false)));
|
|
||||||
ifstmtp->addNext(new AstIf(fl,
|
|
||||||
new AstLt (fl, new AstConst(fl, 100),
|
|
||||||
new AstVarRef(fl, countVarp, false)),
|
|
||||||
(new AstDisplay (fl, AstDisplayType::DT_DISPLAY,
|
|
||||||
"%%Error: Verilated model didn't converge", NULL, NULL))
|
|
||||||
->addNext(new AstStop (fl)),
|
|
||||||
NULL));
|
|
||||||
untilp->addBodysp(new AstIf(fl, new AstNeq(fl, new AstConst(fl, 0),
|
|
||||||
new AstVarRef(fl, changeVarp, false)),
|
|
||||||
ifstmtp, NULL));
|
|
||||||
//
|
|
||||||
// Replace it
|
|
||||||
preUntilp->addNext(untilp);
|
|
||||||
if (debug()>4) preUntilp->dumpTreeAndNext(cout, " UntilSt-new: ");
|
|
||||||
nodep->replaceWith(preUntilp); nodep->deleteTree(); nodep=NULL;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//--------------------
|
//--------------------
|
||||||
// Default: Just iterate
|
// Default: Just iterate
|
||||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||||
|
|||||||
+2
-4
@@ -1,14 +1,12 @@
|
|||||||
// -*- C++ -*-
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Clocking POS/NEGEDGE insertion
|
// DESCRIPTION: Verilator: Clocking POS/NEGEDGE insertion
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.org/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
|
||||||
//
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2014 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
|
|||||||
+8
-7
@@ -1,13 +1,12 @@
|
|||||||
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Combine common code into functions
|
// DESCRIPTION: Verilator: Combine common code into functions
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.org/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
|
||||||
//
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2014 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
@@ -70,8 +69,8 @@ protected:
|
|||||||
virtual ~CombBaseVisitor() {}
|
virtual ~CombBaseVisitor() {}
|
||||||
|
|
||||||
//***** optimization levels
|
//***** optimization levels
|
||||||
bool emptyFunctionDeletion() { return true; }
|
static bool emptyFunctionDeletion() { return true; }
|
||||||
bool duplicateFunctionCombine() { return true; }
|
static bool duplicateFunctionCombine() { return true; }
|
||||||
// Note this is disabled, it still needed work
|
// Note this is disabled, it still needed work
|
||||||
// Also repair it for DPI functions; when make __common need to insure proper
|
// Also repair it for DPI functions; when make __common need to insure proper
|
||||||
// flags get inherited from the old to new AstCFunc, and that AstText doesn't
|
// flags get inherited from the old to new AstCFunc, and that AstText doesn't
|
||||||
@@ -146,7 +145,9 @@ private:
|
|||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
// CONSTRUCTORS
|
// CONSTRUCTORS
|
||||||
CombCallVisitor() {}
|
CombCallVisitor() {
|
||||||
|
m_find = false;
|
||||||
|
}
|
||||||
virtual ~CombCallVisitor() {}
|
virtual ~CombCallVisitor() {}
|
||||||
void main(AstNetlist* nodep) {
|
void main(AstNetlist* nodep) {
|
||||||
nodep->accept(*this);
|
nodep->accept(*this);
|
||||||
@@ -257,7 +258,7 @@ private:
|
|||||||
UINFO(5," DupFunc "<<hex<<V3Hash(newfuncp->user4p())<<" "<<newfuncp<<endl);
|
UINFO(5," DupFunc "<<hex<<V3Hash(newfuncp->user4p())<<" "<<newfuncp<<endl);
|
||||||
UINFO(5," and "<<hex<<V3Hash(oldfuncp->user4p())<<" "<<oldfuncp<<endl);
|
UINFO(5," and "<<hex<<V3Hash(oldfuncp->user4p())<<" "<<oldfuncp<<endl);
|
||||||
// Mark user3p on entire old tree, so we don't process it more
|
// Mark user3p on entire old tree, so we don't process it more
|
||||||
m_statCombs++;
|
++m_statCombs;
|
||||||
CombMarkVisitor visitor(oldfuncp);
|
CombMarkVisitor visitor(oldfuncp);
|
||||||
m_call.replaceFunc(oldfuncp, newfuncp);
|
m_call.replaceFunc(oldfuncp, newfuncp);
|
||||||
oldfuncp->unlinkFrBack();
|
oldfuncp->unlinkFrBack();
|
||||||
|
|||||||
+2
-4
@@ -1,14 +1,12 @@
|
|||||||
// -*- C++ -*-
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Combine common code into functions
|
// DESCRIPTION: Verilator: Combine common code into functions
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.org/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
|
||||||
//
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2014 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
|
|||||||
+33
-20
@@ -1,13 +1,12 @@
|
|||||||
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Configuration Files
|
// DESCRIPTION: Verilator: Configuration Files
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.org/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
|
||||||
//
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2010-2010 by Wilson Snyder. This program is free software; you can
|
// Copyright 2010-2014 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
@@ -26,6 +25,7 @@
|
|||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
#include "V3Global.h"
|
#include "V3Global.h"
|
||||||
|
#include "V3String.h"
|
||||||
#include "V3Config.h"
|
#include "V3Config.h"
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
@@ -60,21 +60,22 @@ class V3ConfigIgnores {
|
|||||||
IgnLines::const_iterator m_lastIt; // Point with next linenumber > current line number
|
IgnLines::const_iterator m_lastIt; // Point with next linenumber > current line number
|
||||||
IgnLines::const_iterator m_lastEnd; // Point with end()
|
IgnLines::const_iterator m_lastEnd; // Point with end()
|
||||||
|
|
||||||
IgnFiles m_ignFiles; // Ignores for each filename
|
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)
|
static V3ConfigIgnores s_singleton; // Singleton (not via local static, as that's slow)
|
||||||
|
|
||||||
V3ConfigIgnores() { m_lastLineno = -1; }
|
V3ConfigIgnores() { m_lastLineno = -1; }
|
||||||
~V3ConfigIgnores() {}
|
~V3ConfigIgnores() {}
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
inline IgnLines* findLines(const string& filename) {
|
inline IgnLines* findWilds(const string& wildname) {
|
||||||
IgnFiles::iterator it = m_ignFiles.find(filename);
|
IgnFiles::iterator it = m_ignWilds.find(wildname);
|
||||||
if (it != m_ignFiles.end()) {
|
if (it != m_ignWilds.end()) {
|
||||||
return &(it->second);
|
return &(it->second);
|
||||||
} else {
|
} else {
|
||||||
m_ignFiles.insert(make_pair(filename, IgnLines()));
|
m_ignWilds.insert(make_pair(wildname, IgnLines()));
|
||||||
it = m_ignFiles.find(filename);
|
it = m_ignWilds.find(wildname);
|
||||||
return &(it->second);
|
return &(it->second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -82,23 +83,35 @@ class V3ConfigIgnores {
|
|||||||
// Given a filename, find all wildcard matches against it and build
|
// Given a filename, find all wildcard matches against it and build
|
||||||
// hash with the specific filename. This avoids having to wildmatch
|
// hash with the specific filename. This avoids having to wildmatch
|
||||||
// more than once against any filename.
|
// more than once against any filename.
|
||||||
IgnLines* linesp = findLines(filename);
|
IgnFiles::iterator it = m_ignFiles.find(filename);
|
||||||
m_lastIt = linesp->begin();
|
if (it == m_ignFiles.end()) {
|
||||||
m_lastEnd = linesp->end();
|
// Haven't seen this filename before
|
||||||
|
m_ignFiles.insert(make_pair(filename, IgnLines()));
|
||||||
|
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 (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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_lastIt = it->second.begin();
|
||||||
|
m_lastEnd = it->second.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
inline static V3ConfigIgnores& singleton() { return s_singleton; }
|
inline static V3ConfigIgnores& singleton() { return s_singleton; }
|
||||||
|
|
||||||
void addIgnore(V3ErrorCode code, string filename, int lineno, bool on) {
|
void addIgnore(V3ErrorCode code, string wildname, int lineno, bool on) {
|
||||||
// Insert
|
// Insert
|
||||||
IgnLines* linesp = findLines(filename);
|
IgnLines* linesp = findWilds(wildname);
|
||||||
UINFO(9,"config addIgnore "<<filename<<":"<<lineno<<", "<<code<<", "<<on<<endl);
|
UINFO(9,"config addIgnore "<<wildname<<":"<<lineno<<", "<<code<<", "<<on<<endl);
|
||||||
linesp->insert(V3ConfigLine(code, lineno, on));
|
linesp->insert(V3ConfigLine(code, lineno, on));
|
||||||
if (m_lastFilename == filename) {
|
// Flush the match cache, due to a change in the rules.
|
||||||
// Flush the match cache, due to a change in the rules.
|
m_ignFiles.clear();
|
||||||
m_lastFilename = " ";
|
m_lastFilename = " ";
|
||||||
}
|
|
||||||
}
|
}
|
||||||
inline void applyIgnores(FileLine* filelinep) {
|
inline void applyIgnores(FileLine* filelinep) {
|
||||||
// HOT routine, called each parsed token line
|
// HOT routine, called each parsed token line
|
||||||
|
|||||||
+2
-4
@@ -1,14 +1,12 @@
|
|||||||
// -*- C++ -*-
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Configuration Files
|
// DESCRIPTION: Verilator: Configuration Files
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.org/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
|
||||||
//
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2010-2010 by Wilson Snyder. This program is free software; you can
|
// Copyright 2010-2014 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
|
|||||||
+907
-322
File diff suppressed because it is too large
Load Diff
+5
-6
@@ -1,14 +1,12 @@
|
|||||||
// -*- C++ -*-
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Propagate constants across AST
|
// DESCRIPTION: Verilator: Propagate constants across AST
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.org/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
|
||||||
//
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2014 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
@@ -31,9 +29,10 @@
|
|||||||
|
|
||||||
class V3Const {
|
class V3Const {
|
||||||
public:
|
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* 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
|
// Everything that's possible
|
||||||
static void constifyAll(AstNetlist* nodep);
|
static void constifyAll(AstNetlist* nodep);
|
||||||
// Also, warn
|
// Also, warn
|
||||||
|
|||||||
+82
-24
@@ -1,13 +1,12 @@
|
|||||||
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Netlist (top level) functions
|
// DESCRIPTION: Verilator: Netlist (top level) functions
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.org/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
|
||||||
//
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2014 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
@@ -61,10 +60,16 @@ private:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// NODE STATE
|
||||||
|
// Entire netlist:
|
||||||
|
// AstIf::user1() -> bool. True indicates ifelse processed
|
||||||
|
AstUser1InUse m_inuser1;
|
||||||
|
|
||||||
// STATE
|
// STATE
|
||||||
bool m_checkBlock; // Should this block get covered?
|
bool m_checkBlock; // Should this block get covered?
|
||||||
AstNodeModule* m_modp; // Current module to add statement to
|
AstNodeModule* m_modp; // Current module to add statement to
|
||||||
bool m_inToggleOff; // In function/task etc
|
bool m_inToggleOff; // In function/task etc
|
||||||
|
bool m_inModOff; // In module with no coverage
|
||||||
FileMap m_fileps; // Column counts for each fileline
|
FileMap m_fileps; // Column counts for each fileline
|
||||||
string m_beginHier; // AstBegin hier name for user coverage points
|
string m_beginHier; // AstBegin hier name for user coverage points
|
||||||
|
|
||||||
@@ -81,11 +86,13 @@ private:
|
|||||||
string prettyName = nodep->prettyName();
|
string prettyName = nodep->prettyName();
|
||||||
if (!nodep->isToggleCoverable())
|
if (!nodep->isToggleCoverable())
|
||||||
return "Not relevant signal type";
|
return "Not relevant signal type";
|
||||||
if (prettyName.c_str()[0] == '_')
|
if (!v3Global.opt.coverageUnderscore()) {
|
||||||
return "Leading underscore";
|
if (prettyName.c_str()[0] == '_')
|
||||||
if (prettyName.find("._") != string::npos)
|
return "Leading underscore";
|
||||||
return "Inlined leading underscore";
|
if (prettyName.find("._") != string::npos)
|
||||||
if ((nodep->width()*nodep->arrayElements()) > 256) return "Wide bus/array > 256 bits";
|
return "Inlined leading underscore";
|
||||||
|
}
|
||||||
|
if ((nodep->width()*nodep->dtypep()->arrayUnpackedElements()) > 256) return "Wide bus/array > 256 bits";
|
||||||
// We allow this, though tracing doesn't
|
// We allow this, though tracing doesn't
|
||||||
// if (nodep->arrayp(1)) return "Unsupported: Multi-dimensional array";
|
// if (nodep->arrayp(1)) return "Unsupported: Multi-dimensional array";
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -123,9 +130,11 @@ private:
|
|||||||
// VISITORS - BOTH
|
// VISITORS - BOTH
|
||||||
virtual void visit(AstNodeModule* nodep, AstNUser*) {
|
virtual void visit(AstNodeModule* nodep, AstNUser*) {
|
||||||
m_modp = nodep;
|
m_modp = nodep;
|
||||||
|
m_inModOff = nodep->isTop(); // Ignore coverage on top module; it's a shell we created
|
||||||
m_fileps.clear();
|
m_fileps.clear();
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
m_modp = NULL;
|
m_modp = NULL;
|
||||||
|
m_inModOff = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// VISITORS - TOGGLE COVERAGE
|
// VISITORS - TOGGLE COVERAGE
|
||||||
@@ -139,7 +148,7 @@ private:
|
|||||||
}
|
}
|
||||||
virtual void visit(AstVar* nodep, AstNUser*) {
|
virtual void visit(AstVar* nodep, AstNUser*) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
if (m_modp && !m_inToggleOff
|
if (m_modp && !m_inModOff && !m_inToggleOff
|
||||||
&& nodep->fileline()->coverageOn() && v3Global.opt.coverageToggle()) {
|
&& nodep->fileline()->coverageOn() && v3Global.opt.coverageToggle()) {
|
||||||
const char* disablep = varIgnoreToggle(nodep);
|
const char* disablep = varIgnoreToggle(nodep);
|
||||||
if (disablep) {
|
if (disablep) {
|
||||||
@@ -191,7 +200,7 @@ private:
|
|||||||
const ToggleEnt& above,
|
const ToggleEnt& above,
|
||||||
AstVar* varp, AstVar* chgVarp) { // Constant
|
AstVar* varp, AstVar* chgVarp) { // Constant
|
||||||
if (AstBasicDType* bdtypep = dtypep->castBasicDType()) {
|
if (AstBasicDType* bdtypep = dtypep->castBasicDType()) {
|
||||||
if (bdtypep->rangep()) {
|
if (bdtypep->isRanged()) {
|
||||||
for (int index_docs=bdtypep->lsb(); index_docs<bdtypep->msb()+1; index_docs++) {
|
for (int index_docs=bdtypep->lsb(); index_docs<bdtypep->msb()+1; index_docs++) {
|
||||||
int index_code = index_docs - bdtypep->lsb();
|
int index_code = index_docs - bdtypep->lsb();
|
||||||
ToggleEnt newent (above.m_comment+string("[")+cvtToStr(index_docs)+"]",
|
ToggleEnt newent (above.m_comment+string("[")+cvtToStr(index_docs)+"]",
|
||||||
@@ -208,13 +217,57 @@ private:
|
|||||||
varp, chgVarp);
|
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) {
|
for (int index_docs=adtypep->lsb(); index_docs<=adtypep->msb(); ++index_docs) {
|
||||||
int index_code = index_docs - adtypep->lsb();
|
int index_code = index_docs - adtypep->lsb();
|
||||||
ToggleEnt newent (above.m_comment+string("[")+cvtToStr(index_docs)+"]",
|
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_varRefp->cloneTree(true), index_code),
|
||||||
new AstArraySel(varp->fileline(), above.m_chgRefp->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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (AstPackArrayDType* adtypep = dtypep->castPackArrayDType()) {
|
||||||
|
for (int index_docs=adtypep->lsb(); index_docs<=adtypep->msb(); ++index_docs) {
|
||||||
|
AstNodeDType* subtypep = adtypep->subDTypep()->skipRefp();
|
||||||
|
int index_code = index_docs - adtypep->lsb();
|
||||||
|
ToggleEnt newent (above.m_comment+string("[")+cvtToStr(index_docs)+"]",
|
||||||
|
new AstSel(varp->fileline(), above.m_varRefp->cloneTree(true),
|
||||||
|
index_code*subtypep->width(), subtypep->width()),
|
||||||
|
new AstSel(varp->fileline(), above.m_chgRefp->cloneTree(true),
|
||||||
|
index_code*subtypep->width(), subtypep->width()));
|
||||||
|
toggleVarRecurse(adtypep->subDTypep()->skipRefp(), depth+1,
|
||||||
|
newent,
|
||||||
|
varp, chgVarp);
|
||||||
|
newent.cleanup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (AstStructDType* adtypep = dtypep->castStructDType()) {
|
||||||
|
// For now it's packed, so similar to array
|
||||||
|
for (AstMemberDType* itemp = adtypep->membersp(); itemp; itemp=itemp->nextp()->castMemberDType()) {
|
||||||
|
AstNodeDType* subtypep = itemp->subDTypep()->skipRefp();
|
||||||
|
int index_code = itemp->lsb();
|
||||||
|
ToggleEnt newent (above.m_comment+string(".")+itemp->name(),
|
||||||
|
new AstSel(varp->fileline(), above.m_varRefp->cloneTree(true),
|
||||||
|
index_code, subtypep->width()),
|
||||||
|
new AstSel(varp->fileline(), above.m_chgRefp->cloneTree(true),
|
||||||
|
index_code, subtypep->width()));
|
||||||
|
toggleVarRecurse(subtypep, depth+1,
|
||||||
|
newent,
|
||||||
|
varp, chgVarp);
|
||||||
|
newent.cleanup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (AstUnionDType* adtypep = dtypep->castUnionDType()) {
|
||||||
|
// Arbitrarially handle only the first member of the union
|
||||||
|
if (AstMemberDType* itemp = adtypep->membersp()) {
|
||||||
|
AstNodeDType* subtypep = itemp->subDTypep()->skipRefp();
|
||||||
|
ToggleEnt newent (above.m_comment+string(".")+itemp->name(),
|
||||||
|
above.m_varRefp->cloneTree(true),
|
||||||
|
above.m_chgRefp->cloneTree(true));
|
||||||
|
toggleVarRecurse(subtypep, depth+1,
|
||||||
newent,
|
newent,
|
||||||
varp, chgVarp);
|
varp, chgVarp);
|
||||||
newent.cleanup();
|
newent.cleanup();
|
||||||
@@ -229,12 +282,18 @@ private:
|
|||||||
virtual void visit(AstIf* nodep, AstNUser*) { // Note not AstNodeIf; other types don't get covered
|
virtual void visit(AstIf* nodep, AstNUser*) { // Note not AstNodeIf; other types don't get covered
|
||||||
UINFO(4," IF: "<<nodep<<endl);
|
UINFO(4," IF: "<<nodep<<endl);
|
||||||
if (m_checkBlock) {
|
if (m_checkBlock) {
|
||||||
|
// An else-if. When we iterate the if, use "elsif" marking
|
||||||
|
bool elsif = (nodep->elsesp()->castIf()
|
||||||
|
&& !nodep->elsesp()->castIf()->nextp());
|
||||||
|
if (elsif) nodep->elsesp()->castIf()->user1(true);
|
||||||
|
//
|
||||||
nodep->ifsp()->iterateAndNext(*this);
|
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
|
&& nodep->fileline()->coverageOn() && v3Global.opt.coverageLine()) { // if a "if" branch didn't disable it
|
||||||
if (!nodep->backp()->castIf()
|
UINFO(4," COVER: "<<nodep<<endl);
|
||||||
|| nodep->backp()->castIf()->elsesp()!=nodep) { // Ignore if else; did earlier
|
if (nodep->user1()) {
|
||||||
UINFO(4," COVER: "<<nodep<<endl);
|
nodep->addIfsp(newCoverInc(nodep->fileline(), "", "v_line", "elsif"));
|
||||||
|
} else {
|
||||||
nodep->addIfsp(newCoverInc(nodep->fileline(), "", "v_line", "if"));
|
nodep->addIfsp(newCoverInc(nodep->fileline(), "", "v_line", "if"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -242,12 +301,10 @@ private:
|
|||||||
if (nodep->elsesp()) {
|
if (nodep->elsesp()) {
|
||||||
m_checkBlock = true;
|
m_checkBlock = true;
|
||||||
nodep->elsesp()->iterateAndNext(*this);
|
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
|
&& nodep->fileline()->coverageOn() && v3Global.opt.coverageLine()) { // if a "else" branch didn't disable it
|
||||||
UINFO(4," COVER: "<<nodep<<endl);
|
UINFO(4," COVER: "<<nodep<<endl);
|
||||||
if (nodep->elsesp()->castIf()) {
|
if (!elsif) { // elsif done inside if()
|
||||||
nodep->addElsesp(newCoverInc(nodep->elsesp()->fileline(), "", "v_line", "elsif"));
|
|
||||||
} else {
|
|
||||||
nodep->addElsesp(newCoverInc(nodep->elsesp()->fileline(), "", "v_line", "else"));
|
nodep->addElsesp(newCoverInc(nodep->elsesp()->fileline(), "", "v_line", "else"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -257,7 +314,7 @@ private:
|
|||||||
}
|
}
|
||||||
virtual void visit(AstCaseItem* nodep, AstNUser*) {
|
virtual void visit(AstCaseItem* nodep, AstNUser*) {
|
||||||
UINFO(4," CASEI: "<<nodep<<endl);
|
UINFO(4," CASEI: "<<nodep<<endl);
|
||||||
if (m_checkBlock
|
if (m_checkBlock && !m_inModOff
|
||||||
&& nodep->fileline()->coverageOn() && v3Global.opt.coverageLine()) {
|
&& nodep->fileline()->coverageOn() && v3Global.opt.coverageLine()) {
|
||||||
nodep->bodysp()->iterateAndNext(*this);
|
nodep->bodysp()->iterateAndNext(*this);
|
||||||
if (m_checkBlock) { // if the case body didn't disable it
|
if (m_checkBlock) { // if the case body didn't disable it
|
||||||
@@ -326,6 +383,7 @@ public:
|
|||||||
m_checkBlock = true;
|
m_checkBlock = true;
|
||||||
m_beginHier = "";
|
m_beginHier = "";
|
||||||
m_inToggleOff = false;
|
m_inToggleOff = false;
|
||||||
|
m_inModOff = true;
|
||||||
rootp->iterateChildren(*this);
|
rootp->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
virtual ~CoverageVisitor() {}
|
virtual ~CoverageVisitor() {}
|
||||||
|
|||||||
+2
-4
@@ -1,14 +1,12 @@
|
|||||||
// -*- C++ -*-
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Coverage modules/signals together
|
// DESCRIPTION: Verilator: Coverage modules/signals together
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.org/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
|
||||||
//
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2014 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Netlist (top level) functions
|
// DESCRIPTION: Verilator: Netlist (top level) functions
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.org/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
|
||||||
//
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2014 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
@@ -97,7 +96,7 @@ private:
|
|||||||
removep->unlinkFrBack(); pushDeletep(removep); removep=NULL;
|
removep->unlinkFrBack(); pushDeletep(removep); removep=NULL;
|
||||||
// Remove node from comparison so don't hit it again
|
// Remove node from comparison so don't hit it again
|
||||||
hashed.erase(dupit);
|
hashed.erase(dupit);
|
||||||
m_statToggleJoins++;
|
++m_statToggleJoins;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,12 @@
|
|||||||
// -*- C++ -*-
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Coverage modules/signals together
|
// DESCRIPTION: Verilator: Coverage modules/signals together
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.org/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
|
||||||
//
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2014 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
|
|||||||
+103
-29
@@ -1,13 +1,12 @@
|
|||||||
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Dead code elimination
|
// DESCRIPTION: Verilator: Dead code elimination
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.org/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
|
||||||
//
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2014 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
@@ -22,6 +21,8 @@
|
|||||||
// Remove any unreferenced modules
|
// Remove any unreferenced modules
|
||||||
// Remove any unreferenced variables
|
// 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
|
// NOTE: If redo this, consider using maybePointedTo()/broken() ish scheme
|
||||||
// instead of needing as many visitors.
|
// instead of needing as many visitors.
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
@@ -70,19 +71,22 @@ class DeadVisitor : public AstNVisitor {
|
|||||||
private:
|
private:
|
||||||
// NODE STATE
|
// NODE STATE
|
||||||
// Entire Netlist:
|
// Entire Netlist:
|
||||||
// AstNodeModule::user() -> int. Count of number of cells referencing this module.
|
// AstNodeModule::user1() -> int. Count of number of cells referencing this module.
|
||||||
// AstVar::user() -> int. Count of number of references
|
// AstVar::user1() -> int. Count of number of references
|
||||||
// AstVarScope::user() -> 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;
|
AstUser1InUse m_inuser1;
|
||||||
|
|
||||||
// TYPES
|
// TYPES
|
||||||
typedef multimap<AstVarScope*,AstNodeAssign*> AssignMap;
|
typedef multimap<AstVarScope*,AstNodeAssign*> AssignMap;
|
||||||
|
|
||||||
// STATE
|
// STATE
|
||||||
vector<AstVar*> m_varsp; // List of all encountered to avoid another loop through tree
|
AstNodeModule* m_modp; // Current module
|
||||||
|
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
|
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
|
AssignMap m_assignMap; // List of all simple assignments for each variable
|
||||||
bool m_elimUserVars; // Allow removal of user's vars
|
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
|
bool m_sideEffect; // Side effects discovered in assign RHS
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
@@ -92,43 +96,96 @@ private:
|
|||||||
return level;
|
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
|
||||||
|
&& !nodep->castMemberDType() // Keep member names iff upper type exists
|
||||||
|
) {
|
||||||
|
m_varEtcsp.push_back(nodep);
|
||||||
|
}
|
||||||
|
if (AstNode* subnodep = nodep->virtRefDTypep()) subnodep->user1Inc();
|
||||||
|
}
|
||||||
|
|
||||||
// VISITORS
|
// VISITORS
|
||||||
|
virtual void visit(AstNodeModule* nodep, AstNUser*) {
|
||||||
|
m_modp = nodep;
|
||||||
|
nodep->iterateChildren(*this);
|
||||||
|
checkAll(nodep);
|
||||||
|
m_modp = NULL;
|
||||||
|
}
|
||||||
virtual void visit(AstCell* nodep, AstNUser*) {
|
virtual void visit(AstCell* nodep, AstNUser*) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
nodep->modp()->user1(nodep->modp()->user1() + 1);
|
checkAll(nodep);
|
||||||
|
nodep->modp()->user1Inc();
|
||||||
}
|
}
|
||||||
virtual void visit(AstNodeVarRef* nodep, AstNUser*) {
|
virtual void visit(AstNodeVarRef* nodep, AstNUser*) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
|
checkAll(nodep);
|
||||||
if (nodep->varScopep()) {
|
if (nodep->varScopep()) {
|
||||||
nodep->varScopep()->user1(nodep->varScopep()->user1() + 1);
|
nodep->varScopep()->user1Inc();
|
||||||
nodep->varScopep()->varp()->user1(nodep->varScopep()->varp()->user1() + 1);
|
nodep->varScopep()->varp()->user1Inc();
|
||||||
}
|
}
|
||||||
if (nodep->varp()) {
|
if (nodep->varp()) {
|
||||||
nodep->varp()->user1(nodep->varp()->user1() + 1);
|
nodep->varp()->user1Inc();
|
||||||
}
|
}
|
||||||
if (nodep->packagep()) {
|
if (nodep->packagep()) {
|
||||||
nodep->packagep()->user1(nodep->packagep()->user1() + 1);
|
nodep->packagep()->user1Inc();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
virtual void visit(AstNodeFTaskRef* nodep, AstNUser*) {
|
virtual void visit(AstNodeFTaskRef* nodep, AstNUser*) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
|
checkAll(nodep);
|
||||||
if (nodep->packagep()) {
|
if (nodep->packagep()) {
|
||||||
nodep->packagep()->user1(nodep->packagep()->user1() + 1);
|
nodep->packagep()->user1Inc();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
virtual void visit(AstRefDType* nodep, AstNUser*) {
|
virtual void visit(AstRefDType* nodep, AstNUser*) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
|
checkDType(nodep);
|
||||||
|
checkAll(nodep);
|
||||||
if (nodep->packagep()) {
|
if (nodep->packagep()) {
|
||||||
nodep->packagep()->user1(nodep->packagep()->user1() + 1);
|
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(AstTypedef* nodep, AstNUser*) {
|
||||||
|
nodep->iterateChildren(*this);
|
||||||
|
checkAll(nodep);
|
||||||
|
// Don't let packages with only public variables disappear
|
||||||
|
// Normal modules may disappear, e.g. if they are parameterized then removed
|
||||||
|
if (nodep->attrPublic() && m_modp && m_modp->castPackage()) m_modp->user1Inc();
|
||||||
|
}
|
||||||
virtual void visit(AstVarScope* nodep, AstNUser*) {
|
virtual void visit(AstVarScope* nodep, AstNUser*) {
|
||||||
nodep->iterateChildren(*this);
|
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*) {
|
virtual void visit(AstVar* nodep, AstNUser*) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
m_varsp.push_back(nodep);
|
checkAll(nodep);
|
||||||
|
if (nodep->isSigPublic() && m_modp && m_modp->castPackage()) m_modp->user1Inc();
|
||||||
|
if (mightElim(nodep)) {
|
||||||
|
m_varEtcsp.push_back(nodep);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void visit(AstNodeAssign* nodep, AstNUser*) {
|
virtual void visit(AstNodeAssign* nodep, AstNUser*) {
|
||||||
@@ -136,23 +193,24 @@ private:
|
|||||||
// Similar code in V3Life
|
// Similar code in V3Life
|
||||||
m_sideEffect = false;
|
m_sideEffect = false;
|
||||||
nodep->rhsp()->iterateAndNext(*this);
|
nodep->rhsp()->iterateAndNext(*this);
|
||||||
|
checkAll(nodep);
|
||||||
// Has to be direct assignment without any EXTRACTing.
|
// Has to be direct assignment without any EXTRACTing.
|
||||||
AstVarRef* varrefp = nodep->lhsp()->castVarRef();
|
AstVarRef* varrefp = nodep->lhsp()->castVarRef();
|
||||||
if (varrefp && !m_sideEffect
|
if (varrefp && !m_sideEffect
|
||||||
&& varrefp->varScopep()) { // For simplicity, we only remove post-scoping
|
&& varrefp->varScopep()) { // For simplicity, we only remove post-scoping
|
||||||
m_assignMap.insert(make_pair(varrefp->varScopep(), nodep));
|
m_assignMap.insert(make_pair(varrefp->varScopep(), nodep));
|
||||||
|
checkAll(varrefp); // Must track reference to dtype()
|
||||||
} else { // Track like any other statement
|
} else { // Track like any other statement
|
||||||
nodep->lhsp()->iterateAndNext(*this);
|
nodep->lhsp()->iterateAndNext(*this);
|
||||||
}
|
}
|
||||||
}
|
checkAll(nodep);
|
||||||
virtual void visit(AstUCFunc* nodep, AstNUser*) {
|
|
||||||
m_sideEffect = true; // If appears on assign RHS, don't ever delete the assignment
|
|
||||||
nodep->iterateChildren(*this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----
|
//-----
|
||||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||||
|
if (nodep->isOutputter()) m_sideEffect=true;
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
|
checkAll(nodep);
|
||||||
}
|
}
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
@@ -165,7 +223,7 @@ private:
|
|||||||
AstNodeModule* nextmodp;
|
AstNodeModule* nextmodp;
|
||||||
for (AstNodeModule* modp = v3Global.rootp()->modulesp(); modp; modp=nextmodp) {
|
for (AstNodeModule* modp = v3Global.rootp()->modulesp(); modp; modp=nextmodp) {
|
||||||
nextmodp = modp->nextp()->castNodeModule();
|
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
|
// > 2 because L1 is the wrapper, L2 is the top user module
|
||||||
UINFO(4," Dead module "<<modp<<endl);
|
UINFO(4," Dead module "<<modp<<endl);
|
||||||
// And its children may now be killable too; correct counts
|
// And its children may now be killable too; correct counts
|
||||||
@@ -177,16 +235,18 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool canElim(AstVar* nodep) {
|
bool mightElim(AstVar* nodep) {
|
||||||
return (!nodep->isSigPublic() // Can't elim publics!
|
return (!nodep->isSigPublic() // Can't elim publics!
|
||||||
&& !nodep->isIO()
|
&& !nodep->isIO()
|
||||||
&& (nodep->isTemp() || nodep->isParam() || m_elimUserVars));
|
&& (nodep->isTemp()
|
||||||
|
|| (nodep->isParam() && !nodep->isTrace())
|
||||||
|
|| m_elimUserVars)); // Post-Trace can kill most anything
|
||||||
}
|
}
|
||||||
void deadCheckVar() {
|
void deadCheckVar() {
|
||||||
// Delete any unused varscopes
|
// Delete any unused varscopes
|
||||||
for (vector<AstVarScope*>::iterator it = m_vscsp.begin(); it!=m_vscsp.end(); ++it) {
|
for (vector<AstVarScope*>::iterator it = m_vscsp.begin(); it!=m_vscsp.end(); ++it) {
|
||||||
AstVarScope* vscp = *it;
|
AstVarScope* vscp = *it;
|
||||||
if (vscp->user1() == 0 && canElim(vscp->varp())) {
|
if (vscp->user1() == 0) {
|
||||||
UINFO(4," Dead "<<vscp<<endl);
|
UINFO(4," Dead "<<vscp<<endl);
|
||||||
pair <AssignMap::iterator,AssignMap::iterator> eqrange = m_assignMap.equal_range(vscp);
|
pair <AssignMap::iterator,AssignMap::iterator> eqrange = m_assignMap.equal_range(vscp);
|
||||||
for (AssignMap::iterator it = eqrange.first; it != eqrange.second; ++it) {
|
for (AssignMap::iterator it = eqrange.first; it != eqrange.second; ++it) {
|
||||||
@@ -197,8 +257,8 @@ private:
|
|||||||
vscp->unlinkFrBack()->deleteTree(); vscp=NULL;
|
vscp->unlinkFrBack()->deleteTree(); vscp=NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (vector<AstVar*>::iterator it = m_varsp.begin(); it!=m_varsp.end(); ++it) {
|
for (vector<AstNode*>::iterator it = m_varEtcsp.begin(); it!=m_varEtcsp.end(); ++it) {
|
||||||
if ((*it)->user1() == 0 && canElim((*it))) {
|
if ((*it)->user1() == 0) {
|
||||||
UINFO(4," Dead "<<(*it)<<endl);
|
UINFO(4," Dead "<<(*it)<<endl);
|
||||||
(*it)->unlinkFrBack()->deleteTree(); (*it)=NULL;
|
(*it)->unlinkFrBack()->deleteTree(); (*it)=NULL;
|
||||||
}
|
}
|
||||||
@@ -207,14 +267,20 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
// CONSTRUCTORS
|
// CONSTRUCTORS
|
||||||
DeadVisitor(AstNetlist* nodep, bool elimUserVars) {
|
DeadVisitor(AstNetlist* nodep, bool elimUserVars, bool elimDTypes) {
|
||||||
|
m_modp = NULL;
|
||||||
m_elimUserVars = elimUserVars;
|
m_elimUserVars = elimUserVars;
|
||||||
|
m_elimDTypes = elimDTypes;
|
||||||
m_sideEffect = false;
|
m_sideEffect = false;
|
||||||
|
// Prepare to remove some datatypes
|
||||||
|
nodep->typeTablep()->clearCache();
|
||||||
// Operate on whole netlist
|
// Operate on whole netlist
|
||||||
nodep->accept(*this);
|
nodep->accept(*this);
|
||||||
deadCheckVar();
|
deadCheckVar();
|
||||||
// Modules after vars, because might be vars we delete inside a mod we delete
|
// Modules after vars, because might be vars we delete inside a mod we delete
|
||||||
deadCheckMod();
|
deadCheckMod();
|
||||||
|
// We may have removed some datatypes, cleanup
|
||||||
|
nodep->typeTablep()->repairCache();
|
||||||
}
|
}
|
||||||
virtual ~DeadVisitor() {}
|
virtual ~DeadVisitor() {}
|
||||||
};
|
};
|
||||||
@@ -222,7 +288,15 @@ public:
|
|||||||
//######################################################################
|
//######################################################################
|
||||||
// Dead class functions
|
// Dead class functions
|
||||||
|
|
||||||
void V3Dead::deadifyAll(AstNetlist* nodep, bool elimUserVars) {
|
void V3Dead::deadifyModules(AstNetlist* nodep) {
|
||||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
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
|
// DESCRIPTION: Verilator: Dead branch elimination
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.org/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
|
||||||
//
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2014 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
@@ -31,8 +29,12 @@
|
|||||||
|
|
||||||
class V3Dead {
|
class V3Dead {
|
||||||
public:
|
public:
|
||||||
|
// Modules, no vars/dtypes
|
||||||
|
static void deadifyModules(AstNetlist* nodep);
|
||||||
|
// Modules, Data types
|
||||||
|
static void deadifyDTypes(AstNetlist* nodep);
|
||||||
// Everything that's possible
|
// Everything that's possible
|
||||||
static void deadifyAll(AstNetlist* nodep, bool elimUserVars);
|
static void deadifyAll(AstNetlist* nodep);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // Guard
|
#endif // Guard
|
||||||
|
|||||||
+74
-60
@@ -1,13 +1,12 @@
|
|||||||
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Add temporaries, such as for delayed nodes
|
// DESCRIPTION: Verilator: Add temporaries, such as for delayed nodes
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.org/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
|
||||||
//
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2014 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
@@ -74,14 +73,15 @@ private:
|
|||||||
// NODE STATE
|
// NODE STATE
|
||||||
// Cleared each module:
|
// Cleared each module:
|
||||||
// AstVarScope::user1p() -> AstVarScope*. Points to temp var created.
|
// 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::user4p() -> AstAlwaysPost*. Post block for this variable
|
||||||
// AstVarScope::user5() -> VarUsage. Tracks delayed vs non-delayed usage
|
// AstVarScope::user5() -> VarUsage. Tracks delayed vs non-delayed usage
|
||||||
// AstVar::user2() -> bool. Set true if already made warning
|
// AstVar::user2() -> bool. Set true if already made warning
|
||||||
// AstVar::user4() -> int. Vector number, for assignment creation
|
// AstVar::user4() -> int. Vector number, for assignment creation
|
||||||
// AstVarRef::user2() -> bool. Set true if already processed
|
// 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
|
// 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
|
// AstAssignDly::user3() -> AstVarScope*. __Vdlyvset__ created for this assign
|
||||||
// AstAlwaysPost::user3() -> AstVarScope*. __Vdlyvset__ last referenced in IF
|
// AstAlwaysPost::user3() -> AstVarScope*. __Vdlyvset__ last referenced in IF
|
||||||
AstUser1InUse m_inuser1;
|
AstUser1InUse m_inuser1;
|
||||||
@@ -118,22 +118,24 @@ private:
|
|||||||
nodep->v3warn(BLKANDNBLK,"Unsupported: Blocked and non-blocking assignments to same variable: "<<nodep->varp()->prettyName());
|
nodep->v3warn(BLKANDNBLK,"Unsupported: Blocked and non-blocking assignments to same variable: "<<nodep->varp()->prettyName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AstVarScope* createVarSc(AstVarScope* oldvarscp, string name, int width/*0==fromoldvar*/) {
|
AstVarScope* createVarSc(AstVarScope* oldvarscp, string name, int width/*0==fromoldvar*/, AstNodeDType* newdtypep) {
|
||||||
// Because we've already scoped it, we may need to add both the AstVar and the AstVarScope
|
// Because we've already scoped it, we may need to add both the AstVar and the AstVarScope
|
||||||
if (!oldvarscp->scopep()) oldvarscp->v3fatalSrc("Var unscoped");
|
if (!oldvarscp->scopep()) oldvarscp->v3fatalSrc("Var unscoped");
|
||||||
AstVar* varp;
|
AstVar* varp;
|
||||||
AstNodeModule* addmodp = oldvarscp->scopep()->modp();
|
AstNodeModule* addmodp = oldvarscp->scopep()->modp();
|
||||||
// We need a new AstVar, but only one for all scopes, to match the new AstVarScope
|
// 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));
|
VarMap::iterator it = m_modVarMap.find(make_pair(addmodp,name));
|
||||||
if (iter != m_modVarMap.end()) {
|
if (it != m_modVarMap.end()) {
|
||||||
// Created module's AstVar earlier under some other scope
|
// Created module's AstVar earlier under some other scope
|
||||||
varp = iter->second;
|
varp = it->second;
|
||||||
} else {
|
} else {
|
||||||
if (width==0) {
|
if (newdtypep) {
|
||||||
|
varp = new AstVar (oldvarscp->fileline(), AstVarType::BLOCKTEMP, name, newdtypep);
|
||||||
|
} else if (width==0) {
|
||||||
varp = new AstVar (oldvarscp->fileline(), AstVarType::BLOCKTEMP, name, oldvarscp->varp());
|
varp = new AstVar (oldvarscp->fileline(), AstVarType::BLOCKTEMP, name, oldvarscp->varp());
|
||||||
varp->widthSignedFrom(oldvarscp);
|
varp->dtypeFrom(oldvarscp);
|
||||||
} else {
|
} else { // Used for vset and dimensions, so can zero init
|
||||||
varp = new AstVar (oldvarscp->fileline(), AstVarType::BLOCKTEMP, name, AstLogicPacked(), width);
|
varp = new AstVar (oldvarscp->fileline(), AstVarType::BLOCKTEMP, name, VFlagBitPacked(), width);
|
||||||
}
|
}
|
||||||
addmodp->addStmtp(varp);
|
addmodp->addStmtp(varp);
|
||||||
m_modVarMap.insert(make_pair(make_pair(addmodp, name), varp));
|
m_modVarMap.insert(make_pair(make_pair(addmodp, name), varp));
|
||||||
@@ -144,6 +146,40 @@ private:
|
|||||||
return varscp;
|
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) {
|
AstNode* createDlyArray(AstAssignDly* nodep, AstNode* lhsp) {
|
||||||
// Create delayed assignment
|
// Create delayed assignment
|
||||||
// See top of this file for transformation
|
// See top of this file for transformation
|
||||||
@@ -185,7 +221,7 @@ private:
|
|||||||
} else {
|
} else {
|
||||||
string bitvarname = (string("__Vdlyvdim")+cvtToStr(dimension)
|
string bitvarname = (string("__Vdlyvdim")+cvtToStr(dimension)
|
||||||
+"__"+oldvarp->shortName()+"__v"+cvtToStr(modVecNum));
|
+"__"+oldvarp->shortName()+"__v"+cvtToStr(modVecNum));
|
||||||
AstVarScope* bitvscp = createVarSc(varrefp->varScopep(), bitvarname, dimp->width());
|
AstVarScope* bitvscp = createVarSc(varrefp->varScopep(), bitvarname, dimp->width(), NULL);
|
||||||
AstAssign* bitassignp
|
AstAssign* bitassignp
|
||||||
= new AstAssign (nodep->fileline(),
|
= new AstAssign (nodep->fileline(),
|
||||||
new AstVarRef(nodep->fileline(), bitvscp, true),
|
new AstVarRef(nodep->fileline(), bitvscp, true),
|
||||||
@@ -203,7 +239,7 @@ private:
|
|||||||
bitreadp = lsbvaluep;
|
bitreadp = lsbvaluep;
|
||||||
} else {
|
} else {
|
||||||
string bitvarname = (string("__Vdlyvlsb__")+oldvarp->shortName()+"__v"+cvtToStr(modVecNum));
|
string bitvarname = (string("__Vdlyvlsb__")+oldvarp->shortName()+"__v"+cvtToStr(modVecNum));
|
||||||
AstVarScope* bitvscp = createVarSc(varrefp->varScopep(), bitvarname, lsbvaluep->width());
|
AstVarScope* bitvscp = createVarSc(varrefp->varScopep(), bitvarname, lsbvaluep->width(), NULL);
|
||||||
AstAssign* bitassignp = new AstAssign (nodep->fileline(),
|
AstAssign* bitassignp = new AstAssign (nodep->fileline(),
|
||||||
new AstVarRef(nodep->fileline(), bitvscp, true),
|
new AstVarRef(nodep->fileline(), bitvscp, true),
|
||||||
lsbvaluep);
|
lsbvaluep);
|
||||||
@@ -218,31 +254,28 @@ private:
|
|||||||
valreadp = nodep->rhsp()->unlinkFrBack();
|
valreadp = nodep->rhsp()->unlinkFrBack();
|
||||||
} else {
|
} else {
|
||||||
string valvarname = (string("__Vdlyvval__")+oldvarp->shortName()+"__v"+cvtToStr(modVecNum));
|
string valvarname = (string("__Vdlyvval__")+oldvarp->shortName()+"__v"+cvtToStr(modVecNum));
|
||||||
AstVarScope* valvscp = createVarSc(varrefp->varScopep(), valvarname, nodep->rhsp()->width());
|
AstVarScope* valvscp = createVarSc(varrefp->varScopep(), valvarname, 0, nodep->rhsp()->dtypep());
|
||||||
newlhsp = new AstVarRef(nodep->fileline(), valvscp, true);
|
newlhsp = new AstVarRef(nodep->fileline(), valvscp, true);
|
||||||
valreadp = new AstVarRef(nodep->fileline(), valvscp, false);
|
valreadp = new AstVarRef(nodep->fileline(), valvscp, false);
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
//=== Setting/not setting boolean: __Vdlyvset__
|
//=== Setting/not setting boolean: __Vdlyvset__
|
||||||
bool sharedVset = false;
|
|
||||||
AstVarScope* setvscp;
|
AstVarScope* setvscp;
|
||||||
|
AstAssignPre* setinitp = NULL;
|
||||||
|
|
||||||
if (nodep->user3p()) {
|
if (nodep->user3p()) {
|
||||||
// Simplistic optimization. If the previous statement in same scope was also a =>,
|
// Simplistic optimization. If the previous statement in same scope was also a =>,
|
||||||
// then we told this nodep->user3 we can use its Vdlyvset rather than making a new one.
|
// then we told this nodep->user3 we can use its Vdlyvset rather than making a new one.
|
||||||
// This is good for code like:
|
// This is good for code like:
|
||||||
// for (i=0; i<5; i++) vector[i] <= something;
|
// for (i=0; i<5; i++) vector[i] <= something;
|
||||||
sharedVset = true;
|
|
||||||
setvscp = nodep->user3p()->castNode()->castVarScope();
|
setvscp = nodep->user3p()->castNode()->castVarScope();
|
||||||
m_statSharedSet++;
|
++m_statSharedSet;
|
||||||
} else { // Create new one
|
} else { // Create new one
|
||||||
string setvarname = (string("__Vdlyvset__")+oldvarp->shortName()+"__v"+cvtToStr(modVecNum));
|
string setvarname = (string("__Vdlyvset__")+oldvarp->shortName()+"__v"+cvtToStr(modVecNum));
|
||||||
setvscp = createVarSc(varrefp->varScopep(), setvarname, 1);
|
setvscp = createVarSc(varrefp->varScopep(), setvarname, 1, NULL);
|
||||||
AstAssignPre* setinitp
|
setinitp = new AstAssignPre (nodep->fileline(),
|
||||||
= new AstAssignPre (nodep->fileline(),
|
new AstVarRef(nodep->fileline(), setvscp, true),
|
||||||
new AstVarRef(nodep->fileline(), setvscp, true),
|
new AstConst(nodep->fileline(), 0));
|
||||||
new AstConst(nodep->fileline(), 0));
|
|
||||||
m_activep->addStmtsp(setinitp);
|
|
||||||
AstAssign* setassignp
|
AstAssign* setassignp
|
||||||
= new AstAssign (nodep->fileline(),
|
= new AstAssign (nodep->fileline(),
|
||||||
new AstVarRef(nodep->fileline(), setvscp, true),
|
new AstVarRef(nodep->fileline(), setvscp, true),
|
||||||
@@ -271,11 +304,18 @@ private:
|
|||||||
UINFO(9," For "<<setvscp<<endl);
|
UINFO(9," For "<<setvscp<<endl);
|
||||||
UINFO(9," & "<<varrefp<<endl);
|
UINFO(9," & "<<varrefp<<endl);
|
||||||
AstAlwaysPost* finalp = varrefp->varScopep()->user4p()->castNode()->castAlwaysPost();
|
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*/);
|
finalp = new AstAlwaysPost(nodep->fileline(), NULL/*sens*/, NULL/*body*/);
|
||||||
UINFO(9," Created "<<finalp<<endl);
|
UINFO(9," Created "<<finalp<<endl);
|
||||||
m_activep->addStmtsp(finalp);
|
AstActive* newactp = createActivePost(varrefp);
|
||||||
|
newactp->addStmtsp(finalp);
|
||||||
varrefp->varScopep()->user4p(finalp);
|
varrefp->varScopep()->user4p(finalp);
|
||||||
|
finalp->user2p(newactp);
|
||||||
|
if (setinitp) newactp->addStmtsp(setinitp);
|
||||||
}
|
}
|
||||||
AstIf* postLogicp;
|
AstIf* postLogicp;
|
||||||
if (finalp->user3p()->castNode() == setvscp) {
|
if (finalp->user3p()->castNode() == setvscp) {
|
||||||
@@ -294,7 +334,6 @@ private:
|
|||||||
finalp->user4p(postLogicp); // and the associated IF, as we may be able to reuse it
|
finalp->user4p(postLogicp); // and the associated IF, as we may be able to reuse it
|
||||||
}
|
}
|
||||||
postLogicp->addIfsp(new AstAssign(nodep->fileline(), selectsp, valreadp));
|
postLogicp->addIfsp(new AstAssign(nodep->fileline(), selectsp, valreadp));
|
||||||
|
|
||||||
return newlhsp;
|
return newlhsp;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -318,6 +357,7 @@ private:
|
|||||||
m_activep = nodep;
|
m_activep = nodep;
|
||||||
bool oldinit = m_inInitial;
|
bool oldinit = m_inInitial;
|
||||||
m_inInitial = nodep->hasInitial();
|
m_inInitial = nodep->hasInitial();
|
||||||
|
AstNode::user3ClearTree(); // Two sets to same variable in different actives must use different vars.
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
m_inInitial = oldinit;
|
m_inInitial = oldinit;
|
||||||
}
|
}
|
||||||
@@ -344,10 +384,9 @@ private:
|
|||||||
m_inDly = false;
|
m_inDly = false;
|
||||||
m_nextDlyp = NULL;
|
m_nextDlyp = NULL;
|
||||||
}
|
}
|
||||||
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
|
||||||
if (!nodep->user2()) { // Not done yet
|
|
||||||
nodep->user2(true);
|
|
||||||
|
|
||||||
|
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
||||||
|
if (!nodep->user2Inc()) { // Not done yet
|
||||||
if (m_inDly && nodep->lvalue()) {
|
if (m_inDly && nodep->lvalue()) {
|
||||||
UINFO(4,"AssignDlyVar: "<<nodep<<endl);
|
UINFO(4,"AssignDlyVar: "<<nodep<<endl);
|
||||||
markVarUsage(nodep->varScopep(), VU_DLY);
|
markVarUsage(nodep->varScopep(), VU_DLY);
|
||||||
@@ -358,34 +397,11 @@ private:
|
|||||||
AstVarScope* dlyvscp = oldvscp->user1p()->castNode()->castVarScope();
|
AstVarScope* dlyvscp = oldvscp->user1p()->castNode()->castVarScope();
|
||||||
if (dlyvscp) { // Multiple use of delayed variable
|
if (dlyvscp) { // Multiple use of delayed variable
|
||||||
AstActive* oldactivep = dlyvscp->user2p()->castNode()->castActive();
|
AstActive* oldactivep = dlyvscp->user2p()->castNode()->castActive();
|
||||||
if (!oldactivep) nodep->v3fatalSrc("<= old dly assignment not put under sensitivity block");
|
checkActivePost(nodep, oldactivep);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (!dlyvscp) { // First use of this delayed variable
|
if (!dlyvscp) { // First use of this delayed variable
|
||||||
string newvarname = (string("__Vdly__")+nodep->varp()->shortName());
|
string newvarname = (string("__Vdly__")+nodep->varp()->shortName());
|
||||||
dlyvscp = createVarSc(oldvscp, newvarname, 0);
|
dlyvscp = createVarSc(oldvscp, newvarname, 0, NULL);
|
||||||
AstNodeAssign* prep
|
AstNodeAssign* prep
|
||||||
= new AstAssignPre (nodep->fileline(),
|
= new AstAssignPre (nodep->fileline(),
|
||||||
new AstVarRef(nodep->fileline(), dlyvscp, true),
|
new AstVarRef(nodep->fileline(), dlyvscp, true),
|
||||||
@@ -397,12 +413,10 @@ private:
|
|||||||
postp->lhsp()->user2(true); // Don't detect this assignment
|
postp->lhsp()->user2(true); // Don't detect this assignment
|
||||||
oldvscp->user1p(dlyvscp); // So we can find it later
|
oldvscp->user1p(dlyvscp); // So we can find it later
|
||||||
// Make new ACTIVE with identical sensitivity tree
|
// Make new ACTIVE with identical sensitivity tree
|
||||||
AstActive* newactp = new AstActive (nodep->fileline(), "sequentdly",
|
AstActive* newactp = createActivePost(nodep);
|
||||||
m_activep->sensesp());
|
dlyvscp->user2p(newactp);
|
||||||
newactp->addStmtsp(prep); // Add to FRONT of statements
|
newactp->addStmtsp(prep); // Add to FRONT of statements
|
||||||
newactp->addStmtsp(postp);
|
newactp->addStmtsp(postp);
|
||||||
m_activep->addNext(newactp);
|
|
||||||
dlyvscp->user2p(newactp);
|
|
||||||
}
|
}
|
||||||
AstVarRef* newrefp = new AstVarRef(nodep->fileline(), dlyvscp, true);
|
AstVarRef* newrefp = new AstVarRef(nodep->fileline(), dlyvscp, true);
|
||||||
newrefp->user2(true); // No reason to do it again
|
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
|
// DESCRIPTION: Verilator: Pre C-Emit stage changes
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.org/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
|
||||||
//
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2014 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user