mirror of
https://github.com/verilator/verilator.git
synced 2026-10-06 10:03:44 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
484b76e5b3 | ||
|
|
801d850724 | ||
|
|
769c0fa318 | ||
|
|
a11700271f | ||
|
|
6d80e8f856 | ||
|
|
f57c72e5db | ||
|
|
7eeb930c72 | ||
|
|
5b280c1911 | ||
|
|
1a073fbf5e | ||
|
|
83d978c2cd | ||
|
|
a17e2375b3 | ||
|
|
c0a6858c42 | ||
|
|
7a18adc716 | ||
|
|
bd602d0e2d | ||
|
|
72b2df30f8 | ||
|
|
d6c5d31dcd | ||
|
|
84c323188e | ||
|
|
cbd1bd5dad | ||
|
|
97255dc835 | ||
|
|
9f8b17230a | ||
|
|
93476a7372 | ||
|
|
b8b9170f9d | ||
|
|
575539996b | ||
|
|
922eab5f93 | ||
|
|
b7a533109d | ||
|
|
941e5c659a | ||
|
|
e37a93bffb | ||
|
|
6e3de7bfd1 | ||
|
|
1124829500 | ||
|
|
4096dee598 | ||
|
|
36f41e08a5 | ||
|
|
28ff71b1bf | ||
|
|
db276946b4 | ||
|
|
beb03be731 | ||
|
|
b93e409f0e | ||
|
|
788de3ad24 | ||
|
|
cb4ddd3213 | ||
|
|
7e94b3a4fa | ||
|
|
ca9bdc6e70 | ||
|
|
37ebc6e634 | ||
|
|
457e926168 | ||
|
|
ec4e408b2b | ||
|
|
a16ebaf79c | ||
|
|
1e34ae31d2 | ||
|
|
43811821d6 | ||
|
|
3797b5bca1 | ||
|
|
7deac509c6 | ||
|
|
c39a8b439a | ||
|
|
d0c4aee7b5 | ||
|
|
a88965a124 | ||
|
|
c18cbca813 | ||
|
|
e4eab56495 | ||
|
|
deb5531e54 | ||
|
|
9bb353c577 | ||
|
|
a816c2b75e | ||
|
|
ff702174d8 | ||
|
|
d5d6598d75 | ||
|
|
0abf18f618 | ||
|
|
6adda241c9 | ||
|
|
ce9293fcb3 | ||
|
|
d6168f654e | ||
|
|
738ee3d4eb | ||
|
|
b75901b3eb | ||
|
|
f98782c061 | ||
|
|
3039735648 | ||
|
|
c00c26c705 | ||
|
|
084ba6711b | ||
|
|
c54360485e | ||
|
|
d9ef4ac435 | ||
|
|
176cc5a196 | ||
|
|
7821da6ad5 | ||
|
|
5ee30e271e | ||
|
|
4ce48788c5 | ||
|
|
3590f7e206 | ||
|
|
882b310897 | ||
|
|
82fc142c1c | ||
|
|
5898c22b3b | ||
|
|
13e88106da | ||
|
|
457d1a66f2 | ||
|
|
b04a1caeac | ||
|
|
53c4c7d540 | ||
|
|
fb689bbb19 | ||
|
|
e2e3cc8463 | ||
|
|
6061744c4d | ||
|
|
8e25d2c61d | ||
|
|
18f8c8a14f | ||
|
|
44765e03a3 | ||
|
|
3f119f5647 | ||
|
|
517fdb7587 | ||
|
|
0ca72f8098 | ||
|
|
28d139149a | ||
|
|
81ce2cbc05 | ||
|
|
d7af6436a2 | ||
|
|
c80ca8d03e | ||
|
|
93304f3b82 | ||
|
|
30546afdab | ||
|
|
82d8fe0c27 | ||
|
|
4db673b2ff | ||
|
|
a5fa468343 | ||
|
|
2df1b72ce2 | ||
|
|
2998890647 | ||
|
|
8e178ca4a9 | ||
|
|
d94a8a28fa | ||
|
|
9a32158b5e | ||
|
|
b15dd3f898 | ||
|
|
af0e535015 | ||
|
|
5b2844e1be | ||
|
|
53ce708294 | ||
|
|
a1322635fd | ||
|
|
ab4ad9965c | ||
|
|
2273fa62d9 | ||
|
|
cca874dc83 | ||
|
|
274475aefd | ||
|
|
a91cf18d09 | ||
|
|
a7723ee9a5 | ||
|
|
28ee80c310 | ||
|
|
26da90ffce | ||
|
|
9eb211a8d4 | ||
|
|
75c2884fea | ||
|
|
f49f86c7ce | ||
|
|
a1989161d8 | ||
|
|
f11fa61ecf | ||
|
|
9a904b97b2 | ||
|
|
7d05be802d | ||
|
|
5e7b0d526d | ||
|
|
ff3d35ca61 | ||
|
|
c23de458ed | ||
|
|
90e0c9bdcd | ||
|
|
7892c5af13 | ||
|
|
0a0e4dce09 | ||
|
|
8e06b1e925 | ||
|
|
a15540dfdd | ||
|
|
3c680ddf22 | ||
|
|
47eeef485d | ||
|
|
251812638d | ||
|
|
cf7ea06b5d | ||
|
|
cd248f6bd7 | ||
|
|
b32d530000 | ||
|
|
570631380b | ||
|
|
d5f88cbf78 | ||
|
|
74ef35d3b3 | ||
|
|
8b8ebb0e43 | ||
|
|
301b4ff1ad | ||
|
|
5476ff93e2 | ||
|
|
375ea169b9 | ||
|
|
9c2785b49b | ||
|
|
8582aed66a | ||
|
|
9bd5cd4ef3 | ||
|
|
f858dd44ac | ||
|
|
e69736124f | ||
|
|
f0e691a1b8 | ||
|
|
5fb834e41e | ||
|
|
7f6d4ac359 | ||
|
|
666d0ab552 | ||
|
|
b9f2400d17 | ||
|
|
85b2c6b6c7 | ||
|
|
73a7595335 | ||
|
|
38c6085f54 | ||
|
|
b350b6a0ff | ||
|
|
80564a8f89 | ||
|
|
016611021d | ||
|
|
fa20614277 | ||
|
|
1e69167191 | ||
|
|
faa5edc068 | ||
|
|
e3c32adad4 | ||
|
|
b054d937cb | ||
|
|
212e8fb14b | ||
|
|
014e43f0ef | ||
|
|
d21b4e3fc7 | ||
|
|
0818d88113 | ||
|
|
77ec2dc875 | ||
|
|
665e8edaff | ||
|
|
67103d346b | ||
|
|
aebb54444e | ||
|
|
a54ac52a35 | ||
|
|
aa360052a8 | ||
|
|
e09f039a36 | ||
|
|
ff262fc4fb | ||
|
|
9a9931fb9d | ||
|
|
30686d8550 | ||
|
|
05f3fd7c6e | ||
|
|
e14319b401 | ||
|
|
1299b70945 | ||
|
|
cf2810db8b | ||
|
|
d77beecc6e | ||
|
|
0c6bd42da3 | ||
|
|
5091298fae | ||
|
|
cef7610b14 | ||
|
|
ed268805ce | ||
|
|
123d1af29d | ||
|
|
cc307626c0 | ||
|
|
963fd0664d | ||
|
|
4643d6e883 | ||
|
|
d89fc05da1 | ||
|
|
84d7380588 | ||
|
|
04febb1944 | ||
|
|
d56b923eaa | ||
|
|
a37866ee92 | ||
|
|
1a92a44c7d | ||
|
|
60a1d25a96 | ||
|
|
ad21f2e850 | ||
|
|
ffbae97a3d | ||
|
|
380137a402 | ||
|
|
ac2058c7ec | ||
|
|
de931d6a97 | ||
|
|
f2d8e45d72 | ||
|
|
085ef5fc05 | ||
|
|
6095efd84e | ||
|
|
114ab1378f | ||
|
|
8622c754b7 | ||
|
|
bf24fa9478 | ||
|
|
e1c45440fc | ||
|
|
b0cb43b2f2 | ||
|
|
dc1f44840d | ||
|
|
fd21a41acd | ||
|
|
cf09a9b6d2 | ||
|
|
dc306cf371 | ||
|
|
35374f09b4 | ||
|
|
e85a2e860e | ||
|
|
103ba1fb6d | ||
|
|
b684995292 | ||
|
|
c371a63d41 | ||
|
|
0102efd4ea | ||
|
|
abfee1270f | ||
|
|
5992d678be | ||
|
|
b6ded59c2b | ||
|
|
c0888c1b0f | ||
|
|
fa77141519 | ||
|
|
b3760911e7 | ||
|
|
b500e57991 | ||
|
|
19e4013ab5 | ||
|
|
82b2af3b83 | ||
|
|
e6f7510895 | ||
|
|
2f718b9ea0 | ||
|
|
899e7bacb2 | ||
|
|
5b3717b369 | ||
|
|
1e7c61b23e | ||
|
|
0e1e380a55 | ||
|
|
1b0a48ea02 | ||
|
|
70b3a599ce | ||
|
|
26c0e6ba00 | ||
|
|
efc6fb7fc3 | ||
|
|
b68038a73f | ||
|
|
f4ef4ad9f3 | ||
|
|
f6f7684ccd | ||
|
|
e74cc32f2d | ||
|
|
c64cc989f0 | ||
|
|
f94fcaa8e4 | ||
|
|
297b297bc7 | ||
|
|
02cb3d17a2 | ||
|
|
c3cfaf55ed | ||
|
|
3e7013af31 | ||
|
|
f7a5883205 | ||
|
|
5d3482734a | ||
|
|
e8c03650ae | ||
|
|
7eac788306 | ||
|
|
6a58e67699 | ||
|
|
b49be06a5a | ||
|
|
87b2adb6a1 | ||
|
|
5634a18f78 | ||
|
|
b84c9bb4c0 | ||
|
|
6dfce882a1 | ||
|
|
79d33bf1ee | ||
|
|
44eb362a18 | ||
|
|
8664aac225 | ||
|
|
6965e138aa | ||
|
|
fc52fb9093 | ||
|
|
cef7708f38 | ||
|
|
438fb01665 | ||
|
|
67d5b1a11a | ||
|
|
d78941885b | ||
|
|
6e7b07c794 | ||
|
|
9655e287ab | ||
|
|
917ca2bad7 | ||
|
|
c3f5dd7414 | ||
|
|
04c7fd1696 | ||
|
|
152689776d | ||
|
|
778f133118 | ||
|
|
ff5465308b | ||
|
|
602750b1ee | ||
|
|
2a24bb4759 | ||
|
|
7c4259bc0a | ||
|
|
1c2384cb3d | ||
|
|
75881754a9 | ||
|
|
0505816d31 | ||
|
|
48bcf66ac7 | ||
|
|
0145d9d514 | ||
|
|
2ce86eddfa | ||
|
|
b663d1a230 | ||
|
|
5821048df7 | ||
|
|
80284c437e | ||
|
|
2aedc91151 | ||
|
|
c1e8337fc1 | ||
|
|
1858cc8ff1 | ||
|
|
5e6aca59ab | ||
|
|
726e78fdda | ||
|
|
085e8454b8 | ||
|
|
85b05366bc | ||
|
|
e6b0479b80 | ||
|
|
3a53b32a32 | ||
|
|
cf7b5c091a | ||
|
|
51b0963e61 | ||
|
|
0c949ceba2 | ||
|
|
5c070558ae | ||
|
|
0c328b6eaf | ||
|
|
f670eccf8c | ||
|
|
23140aeff0 | ||
|
|
d44426b3f3 | ||
|
|
05ff96bea3 | ||
|
|
77ac9bfcc6 | ||
|
|
34b8ed4cf0 | ||
|
|
95d1272269 | ||
|
|
046c0a7aa1 | ||
|
|
835905bdae | ||
|
|
51d1235cda | ||
|
|
2f21b3385a | ||
|
|
9d0a7d5e70 | ||
|
|
4cec3ff2a0 | ||
|
|
25593c0ee2 | ||
|
|
5d3dd52f13 | ||
|
|
ec36d0d772 | ||
|
|
3d2503f9aa | ||
|
|
4576644591 | ||
|
|
d8df216a8d | ||
|
|
964dcd5b7c | ||
|
|
f62c070d06 | ||
|
|
a56e0a6e89 | ||
|
|
451e961e03 | ||
|
|
cb550e5357 | ||
|
|
829db3eefa | ||
|
|
44f938e507 | ||
|
|
4849c0530b | ||
|
|
f4ed367850 | ||
|
|
d4df94d866 | ||
|
|
5d8019f941 | ||
|
|
48597bebaf | ||
|
|
470859f929 | ||
|
|
77553d23fc | ||
|
|
3b9c8b64f7 | ||
|
|
7e5f562500 | ||
|
|
d4d3ae4dfc | ||
|
|
79b1b07fcd | ||
|
|
e3cf5c07e4 | ||
|
|
8750352495 | ||
|
|
3d8dc2774b | ||
|
|
0a9ae154be | ||
|
|
e25a6334cf | ||
|
|
070bead9f9 | ||
|
|
549921be2e | ||
|
|
7c05033b79 | ||
|
|
215d3614c0 | ||
|
|
1ebf937a6c | ||
|
|
7be343fd7c | ||
|
|
fb2d78520f | ||
|
|
c5da072ff6 | ||
|
|
efbcb094ca | ||
|
|
5033c906fd | ||
|
|
f8ab30d127 | ||
|
|
222ca4b009 | ||
|
|
e3a1954e20 | ||
|
|
4ba2637360 | ||
|
|
6430743b6f | ||
|
|
0c49cca527 | ||
|
|
7a9e79ea79 | ||
|
|
157948c552 | ||
|
|
1a127a479c | ||
|
|
87e4a86fbb | ||
|
|
1c1b95161b | ||
|
|
66d1754d19 | ||
|
|
57a53c014d | ||
|
|
e48a859b86 | ||
|
|
430238a6b4 | ||
|
|
9a4c5509fc | ||
|
|
0765443353 | ||
|
|
d07a6f81e4 | ||
|
|
fac04521db | ||
|
|
d0819f156f | ||
|
|
b77eab3f83 | ||
|
|
30f3774134 | ||
|
|
1899a875a4 | ||
|
|
cc134b38ee | ||
|
|
993115d30a | ||
|
|
c1d35c8622 | ||
|
|
16fba59480 | ||
|
|
4266c789ce | ||
|
|
627d83e807 | ||
|
|
80f5738544 | ||
|
|
600641b4a1 | ||
|
|
70eb99b050 | ||
|
|
dc1ad16b03 | ||
|
|
ba5779c69e | ||
|
|
069eb97eca | ||
|
|
96a959154a | ||
|
|
4f88ec3518 | ||
|
|
ef4f91ae5a | ||
|
|
45eccaecaf | ||
|
|
0397e19726 | ||
|
|
687edba969 | ||
|
|
02e83da2fa | ||
|
|
ef04ada12b | ||
|
|
bed3101dfc | ||
|
|
4265f9499d | ||
|
|
6acd5847e7 | ||
|
|
16547077a1 | ||
|
|
3ad3944f2c | ||
|
|
be8f1a25c6 | ||
|
|
f7f3d3fd43 | ||
|
|
4003e01283 | ||
|
|
917d3b0fb3 | ||
|
|
3d073c9534 | ||
|
|
20206b1e2e | ||
|
|
fefe731105 | ||
|
|
1dce6b2500 | ||
|
|
d2fac4aa2f | ||
|
|
132cc1d068 | ||
|
|
f4a72946eb | ||
|
|
e10156548d | ||
|
|
4e6d2cfe38 | ||
|
|
7f3a73e314 | ||
|
|
143050e034 | ||
|
|
8455ee7091 | ||
|
|
9702d11657 | ||
|
|
decbf79f39 | ||
|
|
2d7d2c5992 | ||
|
|
2abbd5c145 | ||
|
|
583605b218 | ||
|
|
67fab0b4fc | ||
|
|
43213fcdc2 | ||
|
|
f632ea500c | ||
|
|
dbb69412e5 | ||
|
|
d7bc0ff5e5 | ||
|
|
14604a24d6 | ||
|
|
816c5e0dc9 | ||
|
|
aa39d020d8 | ||
|
|
b67f1f0e94 | ||
|
|
f5546febe8 | ||
|
|
27181d534e | ||
|
|
698e0fbbd1 | ||
|
|
ea9b65fe6d | ||
|
|
3c1ed075e5 | ||
|
|
6013b54f7b | ||
|
|
d75a8624c1 | ||
|
|
ac04e85a1c | ||
|
|
78aee6f4e7 | ||
|
|
ee9d6dd63f | ||
|
|
034737d2a8 | ||
|
|
72d2cff0a1 | ||
|
|
033e7ac020 | ||
|
|
042d3eed23 | ||
|
|
ea4031cbd3 | ||
|
|
c0127599df | ||
|
|
7c54a451a9 | ||
|
|
2118038cb9 | ||
|
|
9927e8b3ee | ||
|
|
953a442827 | ||
|
|
f3b28c5c74 | ||
|
|
7a33fe2bf2 | ||
|
|
bdecf6c4e1 | ||
|
|
6fcf05e2b6 | ||
|
|
4a5e4b04f3 | ||
|
|
5d98035170 | ||
|
|
20c906261b | ||
|
|
74754d94c3 | ||
|
|
98cd925fda | ||
|
|
e029ba845e | ||
|
|
e53a522662 | ||
|
|
2bc813da4a | ||
|
|
555408b5d3 | ||
|
|
a07f2b3611 | ||
|
|
c85589371a | ||
|
|
1280070abb | ||
|
|
a52f975bd7 | ||
|
|
0c70f0c786 | ||
|
|
edf6a40f19 | ||
|
|
58739a0a99 | ||
|
|
1488f9130d | ||
|
|
a18d8cbe86 | ||
|
|
bfea4b7f99 | ||
|
|
84b8307938 | ||
|
|
ce340658d6 | ||
|
|
a02c420064 | ||
|
|
d55c233427 | ||
|
|
25bbbbd37b | ||
|
|
fdb4d3a145 | ||
|
|
ced1af8cb8 | ||
|
|
f0a6e4c2b2 | ||
|
|
9e5cd463e5 | ||
|
|
bb8899f307 | ||
|
|
1194dbf19c | ||
|
|
0cd4a57ad9 | ||
|
|
1bd1e21a69 | ||
|
|
7e7447812c | ||
|
|
af3ab13012 | ||
|
|
b35b5aacfa | ||
|
|
9c01665078 | ||
|
|
a500140f1d | ||
|
|
dced49a804 | ||
|
|
f8a67b2fe8 | ||
|
|
8cdecd5668 | ||
|
|
75d255a3bf | ||
|
|
0674267333 | ||
|
|
1632160fb1 | ||
|
|
e609328ebb | ||
|
|
8291ef6537 | ||
|
|
30600bf1a3 | ||
|
|
b968f57711 | ||
|
|
ee7b399bf5 | ||
|
|
50c28fa9d3 | ||
|
|
a17f51eac0 | ||
|
|
cc50126ad3 | ||
|
|
9d1a39a5e4 | ||
|
|
82cc1a319f | ||
|
|
2fd23458ce | ||
|
|
271fa5fe3c | ||
|
|
04c96694e6 | ||
|
|
e7bd44561c | ||
|
|
4d5e448664 | ||
|
|
236c2141e3 | ||
|
|
788fe3dc27 | ||
|
|
a2abd361db | ||
|
|
09806d7576 | ||
|
|
a2aa678278 | ||
|
|
0b09636c58 | ||
|
|
af197f2ceb | ||
|
|
748c818ccb | ||
|
|
ad55564905 | ||
|
|
ad2cb45a14 | ||
|
|
277fd9197f | ||
|
|
61ff7039b4 | ||
|
|
7342cf278a | ||
|
|
958654909f | ||
|
|
d9be86d69a | ||
|
|
378d947702 | ||
|
|
98b5417e04 | ||
|
|
0af971292e | ||
|
|
43a2fa080a | ||
|
|
0cdc2e038c | ||
|
|
d4a411db6c | ||
|
|
8d367dc8a3 | ||
|
|
5a4cc333fb | ||
|
|
f13fd4478c | ||
|
|
23e4a0f784 | ||
|
|
aa595d40de | ||
|
|
fa828ac9ba | ||
|
|
b1495f0742 | ||
|
|
8006b5479c | ||
|
|
19c2906a64 | ||
|
|
c367b671b6 | ||
|
|
35226d5e1a | ||
|
|
fac89c5d62 | ||
|
|
f40f0464e2 | ||
|
|
262ed9c03a | ||
|
|
a7edf13d62 | ||
|
|
6e57076726 | ||
|
|
cef56c6fca | ||
|
|
91f30af01f | ||
|
|
3c8953fec2 | ||
|
|
6de78d58fa | ||
|
|
d42f9c095b | ||
|
|
46e10173f8 | ||
|
|
d84c7df38f | ||
|
|
6e2d8df9e5 | ||
|
|
e2b40195b4 | ||
|
|
541f983dba | ||
|
|
5658cd3394 | ||
|
|
3963a50aef | ||
|
|
47f040a5fd | ||
|
|
7b7a2e99e3 | ||
|
|
25397e7612 | ||
|
|
4984d19ae9 | ||
|
|
305448ea86 | ||
|
|
4a1d18f0e9 | ||
|
|
30482f3eea | ||
|
|
b469feb44b | ||
|
|
466fd56d18 | ||
|
|
1aaf3f3424 | ||
|
|
b5e4917405 | ||
|
|
140671300c | ||
|
|
820a4dbbdd | ||
|
|
53d8ccd149 | ||
|
|
418b36ea71 | ||
|
|
05e51d0d18 | ||
|
|
575c565e77 | ||
|
|
01255082a6 | ||
|
|
0098e67e59 | ||
|
|
3798a472b5 | ||
|
|
0e322e2e85 | ||
|
|
5cd5c05c05 | ||
|
|
933e796cc2 | ||
|
|
ae701e014d | ||
|
|
3a0b8c8870 | ||
|
|
dea0e6793f | ||
|
|
4862916f39 | ||
|
|
870ec27b73 | ||
|
|
a21947d887 | ||
|
|
893dee3434 | ||
|
|
f083805ab5 | ||
|
|
7067afde5d | ||
|
|
1eaec2aa8a | ||
|
|
da01810d98 | ||
|
|
4c7d5a1dc0 | ||
|
|
d15e3d93c4 | ||
|
|
aae2bf872c | ||
|
|
04c0fc8aa7 | ||
|
|
1d8955fea5 | ||
|
|
48740a0dba | ||
|
|
4a404bd92e | ||
|
|
ff41701ddc | ||
|
|
2590c9c4a6 | ||
|
|
c5d61da5d2 | ||
|
|
5a622fd9db | ||
|
|
c83b1478e1 | ||
|
|
3243651c63 | ||
|
|
8d61cd9029 | ||
|
|
7fe49de420 | ||
|
|
a433096d5a | ||
|
|
b88e1e6970 | ||
|
|
79f228b04f | ||
|
|
d7cc1e6844 | ||
|
|
42312101b5 | ||
|
|
329f5b712a | ||
|
|
6ddd92c0a1 | ||
|
|
277dee109c | ||
|
|
ef71576825 | ||
|
|
c3271aa891 | ||
|
|
1cf17b5e78 | ||
|
|
2b6353b36e | ||
|
|
8b647f0977 | ||
|
|
4c31c5fab5 | ||
|
|
6ce878cb0d | ||
|
|
a67ba04c37 | ||
|
|
ae448e5ef9 | ||
|
|
a57826b125 | ||
|
|
656c460605 | ||
|
|
95534fa5c5 | ||
|
|
611e8b10c6 | ||
|
|
047852eb08 | ||
|
|
6318a08056 | ||
|
|
b60a92eed3 | ||
|
|
fe306a36b8 | ||
|
|
18870f8b62 | ||
|
|
9712ceedd7 | ||
|
|
2e32387e5c | ||
|
|
b66877c9df | ||
|
|
74a6f94e2b | ||
|
|
35fc8b7259 | ||
|
|
e591afd101 | ||
|
|
a41cdf4cfb | ||
|
|
ef72c42aa7 | ||
|
|
fbc814b54a | ||
|
|
4cfa3f879a | ||
|
|
4a8c7e869f | ||
|
|
a4a1c7a384 | ||
|
|
460315128b | ||
|
|
8ddafb4d9f | ||
|
|
ebda8f866c | ||
|
|
5ee4595aa8 | ||
|
|
5089ac6119 | ||
|
|
3f66f846cd | ||
|
|
279f21bb5b | ||
|
|
773ed97504 | ||
|
|
b6d4899d3f | ||
|
|
9d48ff7745 | ||
|
|
c4aab57c62 | ||
|
|
e8f27be200 | ||
|
|
15f0f967b3 | ||
|
|
cbafff8a71 | ||
|
|
41e362b580 | ||
|
|
622f59ad65 | ||
|
|
c5da38206e | ||
|
|
d737266f64 | ||
|
|
978c35995a | ||
|
|
2af7f2fa18 | ||
|
|
373c9090d3 | ||
|
|
723d407a87 | ||
|
|
dc90e6c3c3 | ||
|
|
68a2ed6776 | ||
|
|
7f32d4dc45 | ||
|
|
7b683fe258 | ||
|
|
72858175a2 | ||
|
|
9d7086067c | ||
|
|
5bb1da88ed | ||
|
|
9969a60b34 | ||
|
|
72402fa91e | ||
|
|
8255f3f9fe | ||
|
|
8957f77793 | ||
|
|
7187b82d1d | ||
|
|
1a92a58720 | ||
|
|
2351f9b9ad | ||
|
|
abc3c216f8 | ||
|
|
f1afa667d7 | ||
|
|
76d0671952 | ||
|
|
424769c32b | ||
|
|
f7249ad23a | ||
|
|
613d76c578 | ||
|
|
50662751fe | ||
|
|
c9e59e767a | ||
|
|
a7432bdea7 | ||
|
|
9ffad7f0db | ||
|
|
3097d5e093 | ||
|
|
cff4b5a5ee | ||
|
|
eda46e3949 | ||
|
|
71651718d4 | ||
|
|
da0cb44954 | ||
|
|
57621a93ad | ||
|
|
6a882f9dc6 | ||
|
|
c18b0eb122 | ||
|
|
3c28a66acf | ||
|
|
5c11de1663 | ||
|
|
72ea6bf414 | ||
|
|
101314a572 | ||
|
|
01f3e81a36 | ||
|
|
3cb3b6c400 | ||
|
|
8f58b58853 | ||
|
|
b66826169d | ||
|
|
d2a7376f14 | ||
|
|
c9e8a1cb4d | ||
|
|
8170f6f03f | ||
|
|
0abf88823f | ||
|
|
accf5a9a17 | ||
|
|
c64c81b7a3 | ||
|
|
7834028842 | ||
|
|
1e0d5eb238 | ||
|
|
b5460bd867 | ||
|
|
53cde90c8f | ||
|
|
d20a4db773 | ||
|
|
0f7677480f | ||
|
|
ba3930777a | ||
|
|
9c054a5774 | ||
|
|
cef0105dfc | ||
|
|
4773a1e77c | ||
|
|
ed4c7038b4 | ||
|
|
c4f31d3bb6 | ||
|
|
dc25e9b949 | ||
|
|
1f52b01b2c | ||
|
|
d5fc0fca41 | ||
|
|
212aa332dd | ||
|
|
17e7da77f0 | ||
|
|
201f0d3f5f | ||
|
|
7d0b3b300a | ||
|
|
0b55e205f7 | ||
|
|
9c0c6439cc | ||
|
|
d33d0301f8 | ||
|
|
6fd7f45cef | ||
|
|
57a937df03 | ||
|
|
ffd461dcf8 | ||
|
|
f77058774e | ||
|
|
1d0a726437 | ||
|
|
29bcbb0417 | ||
|
|
2d11c2cbb3 | ||
|
|
2edbcce032 | ||
|
|
35a53d9adb | ||
|
|
2885c2ce97 | ||
|
|
900c023bb5 | ||
|
|
12b95f6b93 | ||
|
|
85de3048a5 | ||
|
|
c1a9fe07e9 | ||
|
|
1a0da2e4ec | ||
|
|
38d11ecabe | ||
|
|
148762364b | ||
|
|
68d7596adf | ||
|
|
f005b7fd87 | ||
|
|
68ed683681 | ||
|
|
61e41595a2 | ||
|
|
484b574cef | ||
|
|
29695adf70 | ||
|
|
fac43811fd | ||
|
|
15f63d12d5 | ||
|
|
ba7b3fd60f | ||
|
|
897b9ccfe2 | ||
|
|
b97e1aa9fe | ||
|
|
d4a631446b | ||
|
|
a2cc053c6f | ||
|
|
8998ffc4e5 | ||
|
|
ca162716c6 | ||
|
|
629dd16714 | ||
|
|
12b903caf4 | ||
|
|
f9a0cf0cff | ||
|
|
070bcddf5a | ||
|
|
feb1e2bd48 | ||
|
|
6e7ee23644 | ||
|
|
c00cc18d37 | ||
|
|
a7e17a8855 | ||
|
|
60fa1db731 | ||
|
|
ac09ad3ffd | ||
|
|
27953e26b6 | ||
|
|
9375d9f603 | ||
|
|
72bd91c7f1 | ||
|
|
8850ca962e | ||
|
|
7fd590f855 | ||
|
|
5f7ae1fbce | ||
|
|
b56a25e89c | ||
|
|
4f32b093e6 | ||
|
|
6a54fb6f96 | ||
|
|
546ccd56c4 | ||
|
|
ca77a93214 | ||
|
|
ee1b20e1cd | ||
|
|
aa86e0bbc0 | ||
|
|
b6b3482010 | ||
|
|
05aecd2c0b | ||
|
|
6ab3d8f3ed | ||
|
|
0fcc7f2987 | ||
|
|
7d7e67b49b | ||
|
|
a41ea180fa | ||
|
|
98889b3f4e | ||
|
|
83fbfa8c71 | ||
|
|
a57262d6e7 | ||
|
|
fe708f045a | ||
|
|
8afcd67a1f | ||
|
|
16e258eb4c | ||
|
|
d6fbbddac9 |
+1
-1
@@ -104,7 +104,7 @@ SpacesInContainerLiterals: true
|
|||||||
SpacesInCStyleCastParentheses: false
|
SpacesInCStyleCastParentheses: false
|
||||||
SpacesInParentheses: false
|
SpacesInParentheses: false
|
||||||
SpacesInSquareBrackets: false
|
SpacesInSquareBrackets: false
|
||||||
Standard: Cpp03
|
Standard: Cpp11
|
||||||
TabWidth: 8
|
TabWidth: 8
|
||||||
UseTab: Never
|
UseTab: Never
|
||||||
...
|
...
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
Checks: 'clang-diagnostic-*,clang-analyzer-*,*,-modernize*,-hicpp*,-android-cloexec-fopen,-cert-dcl50-cpp,-cert-env33-c,-cert-err34-c,-cert-err58-cpp,-clang-analyzer-core.UndefinedBinaryOperatorResult,-clang-analyzer-security*,-cppcoreguidelines-no-malloc,-cppcoreguidelines-owning-memory,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-cppcoreguidelines-pro-bounds-constant-array-index,-cppcoreguidelines-pro-bounds-pointer-arithmetic,-cppcoreguidelines-pro-type-const-cast,-cppcoreguidelines-pro-type-reinterpret-cast,-cppcoreguidelines-pro-type-static-cast-downcast,-cppcoreguidelines-pro-type-union-access,-cppcoreguidelines-pro-type-vararg,-cppcoreguidelines-special-member-functions,-fuchsia-default-arguments,-fuchsia-overloaded-operator,-google-default-arguments,-google-readability-todo,-google-runtime-references,-llvm-header-guard,-llvm-include-order,-misc-string-integer-assignment,-misc-string-literal-with-embedded-nul,-readability-braces-around-statements,-readability-container-size-empty,-readability-delete-null-pointer,-readability-else-after-return,-readability-implicit-bool-conversion,-readability-named-parameter,-readability-static-accessed-through-instance'
|
Checks: '*,-hicpp*,-android-cloexec-fopen,-cert-dcl50-cpp,-cert-env33-c,-cert-err34-c,-cert-err58-cpp,-clang-analyzer-core.UndefinedBinaryOperatorResult,-clang-analyzer-security*,-cppcoreguidelines-avoid-magic-numbers,-cppcoreguidelines-no-malloc,-cppcoreguidelines-owning-memory,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-cppcoreguidelines-pro-bounds-constant-array-index,-cppcoreguidelines-pro-bounds-pointer-arithmetic,-cppcoreguidelines-pro-type-const-cast,-cppcoreguidelines-pro-type-reinterpret-cast,-cppcoreguidelines-pro-type-static-cast-downcast,-cppcoreguidelines-pro-type-union-access,-cppcoreguidelines-pro-type-vararg,-cppcoreguidelines-special-member-functions,-fuchsia-*,-google-default-arguments,-google-readability-todo,-google-runtime-references,-llvm-header-guard,-llvm-include-order,-misc-string-integer-assignment,-misc-string-literal-with-embedded-nul,-modernize-use-auto,-modernize-use-trailing-return-type,-readability-braces-around-statements,-readability-container-size-empty,-readability-delete-null-pointer,-readability-else-after-return,-readability-implicit-bool-conversion,-readability-named-parameter,-readability-static-accessed-through-instance'
|
||||||
WarningsAsErrors: ''
|
WarningsAsErrors: ''
|
||||||
HeaderFilterRegex: ''
|
HeaderFilterRegex: ''
|
||||||
FormatStyle: none
|
FormatStyle: none
|
||||||
|
|||||||
@@ -3,3 +3,4 @@ exclude_paths:
|
|||||||
- '.github/**'
|
- '.github/**'
|
||||||
- 'ci/build_verilator.sh'
|
- 'ci/build_verilator.sh'
|
||||||
- 'include/vltstd/**'
|
- 'include/vltstd/**'
|
||||||
|
- 'nodist/fastcov.py'
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
name: Bug report
|
name: Bug report
|
||||||
about: Something isn't working as expected, and it isn't "Unsupported." (Note our contributor agreement at https://github.com/verilator/verilator/.github/blob/master/CONTRIBUTING.adoc)
|
about: Something isn't working as expected, and it isn't "Unsupported." (Note our contributor agreement at https://github.com/verilator/verilator/blob/master/docs/CONTRIBUTING.adoc)
|
||||||
title: ''
|
title: ''
|
||||||
labels: new
|
labels: new
|
||||||
assignees: ''
|
assignees: ''
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
name: Feature Request
|
name: Feature Request
|
||||||
about: Request something should be supported, or a new feature added. (Note our contributor agreement at https://github.com/verilator/verilator/.github/blob/master/CONTRIBUTING.adoc)
|
about: Request something should be supported, or a new feature added. (Note our contributor agreement at https://github.com/verilator/verilator/blob/master/docs/CONTRIBUTING.adoc)
|
||||||
title: ''
|
title: ''
|
||||||
labels: new
|
labels: new
|
||||||
assignees: ''
|
assignees: ''
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
name: Q and A, or Other
|
name: Q and A, or Other
|
||||||
about: Ask a question, not related to a specific bug or feature request. (Note our contributor agreement at https://github.com/verilator/verilator/.github/blob/master/CONTRIBUTING.adoc)
|
about: Ask a question, not related to a specific bug or feature request. (Note our contributor agreement at https://github.com/verilator/verilator/blob/master/docs/CONTRIBUTING.adoc)
|
||||||
title: ''
|
title: ''
|
||||||
labels: new
|
labels: new
|
||||||
assignees: ''
|
assignees: ''
|
||||||
|
|||||||
@@ -0,0 +1,137 @@
|
|||||||
|
# DESCRIPTION: Github actions config
|
||||||
|
# This name is key to badges in README.adoc, so we use the name build
|
||||||
|
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||||
|
|
||||||
|
name: build
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
pull_request:
|
||||||
|
workflow_dispatch:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 0 * * 0' # weekly
|
||||||
|
|
||||||
|
env:
|
||||||
|
CI_OS_NAME: linux
|
||||||
|
CI_COMMIT: ${{ github.sha }}
|
||||||
|
CCACHE_COMPRESS: 1
|
||||||
|
CCACHE_DIR: ${{ github.workspace }}/.ccache
|
||||||
|
CCACHE_MAXSIZE: 2Gi # 2GiB for clang and gcc, 4GiB in total
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
|
||||||
|
Matrix:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
name: Generate Build matrix
|
||||||
|
outputs:
|
||||||
|
matrix: ${{ steps.generate.outputs.matrix }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- id: generate
|
||||||
|
name: Run 'generate_matrix.sh'
|
||||||
|
run: |
|
||||||
|
if [ '${{ github.event_name}}' = 'pull_request' ]; then
|
||||||
|
matrix='[ "ubuntu-20.04" ]'
|
||||||
|
else
|
||||||
|
matrix='[ "ubuntu-16.04", "ubuntu-18.04", "ubuntu-20.04" ]'
|
||||||
|
fi
|
||||||
|
echo "::set-output name=matrix::$matrix"
|
||||||
|
|
||||||
|
|
||||||
|
Build:
|
||||||
|
needs: Matrix
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
os: ${{ fromJson(needs.Matrix.outputs.matrix) }}
|
||||||
|
debug: [ opt, dbg ]
|
||||||
|
compiler:
|
||||||
|
- { cc: clang, cxx: clang++ }
|
||||||
|
- { cc: gcc, cxx: g++ }
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
name: Build | ${{ matrix.os }} | ${{ matrix.compiler.cc }} | ${{ matrix.debug }}
|
||||||
|
env:
|
||||||
|
CI_BUILD_STAGE_NAME: build
|
||||||
|
CI_RUNS_ON: ${{ matrix.os }}
|
||||||
|
CI_MAKE_SRC_TARGET: ${{ matrix.debug }}
|
||||||
|
CC: ${{ matrix.compiler.cc }}
|
||||||
|
CXX: ${{ matrix.compiler.cxx }}
|
||||||
|
CACHE_KEY: ${{ matrix.os }}-${{ matrix.compiler.cc }}
|
||||||
|
steps:
|
||||||
|
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Cache
|
||||||
|
uses: actions/cache@v2
|
||||||
|
env:
|
||||||
|
cache-name: ccache
|
||||||
|
with:
|
||||||
|
path: ${{ github.workspace }}/.ccache
|
||||||
|
key: ${{ env.CACHE_KEY }}-${{ env.cache-name }}-${{ github.sha }}
|
||||||
|
restore-keys: ${{ env.CACHE_KEY }}-${{ env.cache-name }}
|
||||||
|
|
||||||
|
- name: Install packages for build
|
||||||
|
run: ./ci/ci-install.bash
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: |
|
||||||
|
./ci/ci-script.bash
|
||||||
|
tar cvzf verilator-${{ matrix.os}}-${CI_COMMIT}-${{ matrix.compiler.cc }}-${{ matrix.debug }}.tgz ./bin
|
||||||
|
|
||||||
|
- uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
path: verilator-${{ matrix.os}}-${{ env.CI_COMMIT }}-${{ matrix.compiler.cc }}-${{ matrix.debug }}.tgz
|
||||||
|
|
||||||
|
|
||||||
|
Test:
|
||||||
|
needs: [ Matrix, Build ]
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
max-parallel: 8
|
||||||
|
matrix:
|
||||||
|
os: ${{ fromJson(needs.Matrix.outputs.matrix) }}
|
||||||
|
compiler:
|
||||||
|
- { cc: clang, cxx: clang++ }
|
||||||
|
- { cc: gcc, cxx: g++ }
|
||||||
|
suite:
|
||||||
|
- dist-vlt-0
|
||||||
|
- dist-vlt-1
|
||||||
|
- vltmt-0
|
||||||
|
- vltmt-1
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
name: Test | ${{ matrix.os }} | ${{ matrix.compiler.cc }} | ${{ matrix.suite }}
|
||||||
|
env:
|
||||||
|
CI_BUILD_STAGE_NAME: test
|
||||||
|
CI_RUNS_ON: ${{ matrix.os }}
|
||||||
|
CC: ${{ matrix.compiler.cc }}
|
||||||
|
CXX: ${{ matrix.compiler.cxx }}
|
||||||
|
CACHE_KEY: ${{ matrix.os }}-${{ matrix.compiler.cc }}
|
||||||
|
steps:
|
||||||
|
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Cache
|
||||||
|
uses: actions/cache@v2
|
||||||
|
env:
|
||||||
|
cache-name: ccache
|
||||||
|
with:
|
||||||
|
path: ${{ github.workspace }}/.ccache
|
||||||
|
key: ${{ env.CACHE_KEY }}-${{ env.cache-name }}-${{ github.sha }}
|
||||||
|
restore-keys: ${{ env.CACHE_KEY }}-${{ env.cache-name }}
|
||||||
|
|
||||||
|
- uses: actions/download-artifact@v2
|
||||||
|
|
||||||
|
- name: Install Verilator and test dependencies
|
||||||
|
run: |
|
||||||
|
tar xvzf artifact/verilator-${{ matrix.os}}-${CI_COMMIT}-${{ matrix.compiler.cc }}-opt.tgz
|
||||||
|
tar xvzf artifact/verilator-${{ matrix.os}}-${CI_COMMIT}-${{ matrix.compiler.cc }}-dbg.tgz
|
||||||
|
rm -rf artifact
|
||||||
|
./ci/ci-install.bash
|
||||||
|
|
||||||
|
- name: Test
|
||||||
|
env:
|
||||||
|
TESTS: ${{ matrix.suite }}
|
||||||
|
run: ./ci/ci-script.bash
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
# DESCRIPTION: Github actions config
|
||||||
|
# This name is key to badges in README.adoc, so we use the name build
|
||||||
|
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||||
|
|
||||||
|
name: clang-format
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
pull_request_target:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
format:
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
name: Ubuntu 20.04 | format
|
||||||
|
env:
|
||||||
|
CI_OS_NAME: linux
|
||||||
|
CI_RUNS_ON: ubuntu-20.04
|
||||||
|
CI_COMMIT: ${{ github.sha }}
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
- name: Install packages for build
|
||||||
|
env:
|
||||||
|
CI_BUILD_STAGE_NAME: build
|
||||||
|
run: |
|
||||||
|
bash ci/ci-install.bash &&
|
||||||
|
sudo apt-get install clang-10 yapf3 &&
|
||||||
|
git config --global user.email "[email protected]" &&
|
||||||
|
git config --global user.name "github action"
|
||||||
|
- name: Format code
|
||||||
|
run: |
|
||||||
|
autoconf &&
|
||||||
|
./configure &&
|
||||||
|
make -j 2 format CLANGFORMAT=clang-format-10 &&
|
||||||
|
git status
|
||||||
|
- name: Push
|
||||||
|
run: |
|
||||||
|
if [ -n "$(git status --porcelain)" ]; then
|
||||||
|
git commit . -m "Apply clang-format" &&
|
||||||
|
git push origin
|
||||||
|
fi
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
# DESCRIPTION: Github actions config
|
||||||
|
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||||
|
|
||||||
|
name: Contributor Agreement
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
pull_request:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
Test:
|
||||||
|
name: "'docs/CONTRIBUTORS' was signed"
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- run: test_regress/t/t_dist_contributors.pl
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
# DESCRIPTION: Github actions config
|
||||||
|
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||||
|
|
||||||
|
name: coverage
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 0 * * 0' # weekly
|
||||||
|
|
||||||
|
env:
|
||||||
|
CI_OS_NAME: linux
|
||||||
|
CI_COMMIT: ${{ github.sha }}
|
||||||
|
CCACHE_COMPRESS: 1
|
||||||
|
CCACHE_DIR: ${{ github.workspace }}/.ccache
|
||||||
|
CCACHE_MAXSIZE: 2Gi # 2GiB for clang and gcc, 4GiB in total
|
||||||
|
COVERAGE: 1
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
|
||||||
|
Build:
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
env:
|
||||||
|
CI_BUILD_STAGE_NAME: build
|
||||||
|
steps:
|
||||||
|
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- uses: actions/cache@v2
|
||||||
|
env:
|
||||||
|
cache-name: ccache
|
||||||
|
with:
|
||||||
|
path: ${{ github.workspace }}/.ccache
|
||||||
|
key: coverage-${{ env.cache-name }}-${{ github.sha }}
|
||||||
|
restore-keys: coverage-${{ env.cache-name }}
|
||||||
|
|
||||||
|
- name: Install dependencies for build
|
||||||
|
env:
|
||||||
|
CI_BUILD_STAGE_NAME: build
|
||||||
|
run: ./ci/ci-install.bash
|
||||||
|
|
||||||
|
- name: Build Verilator
|
||||||
|
run: |
|
||||||
|
./ci/ci-script.bash
|
||||||
|
|
||||||
|
mkdir tarball/
|
||||||
|
cp -vr bin tarball/
|
||||||
|
cp -vr src/obj*/*.gcno tarball/
|
||||||
|
tar cvzf verilator-${CI_COMMIT}.tgz -C ./tarball .
|
||||||
|
|
||||||
|
- uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
path: verilator-${{ env.CI_COMMIT }}.tgz
|
||||||
|
|
||||||
|
|
||||||
|
Test:
|
||||||
|
needs: Build
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
test:
|
||||||
|
- vlt-
|
||||||
|
- vltmt-
|
||||||
|
num:
|
||||||
|
- 0
|
||||||
|
- 1
|
||||||
|
- 2
|
||||||
|
- 3
|
||||||
|
include:
|
||||||
|
- { test: dist, num: '' }
|
||||||
|
name: test-${{ matrix.test }}${{ matrix.num }}
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
env:
|
||||||
|
CI_BUILD_STAGE_NAME: test
|
||||||
|
steps:
|
||||||
|
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- uses: actions/cache@v2
|
||||||
|
env:
|
||||||
|
cache-name: ccache
|
||||||
|
with:
|
||||||
|
path: ${{ github.workspace }}/.ccache
|
||||||
|
key: coverage-${{ env.cache-name }}-${{ github.sha }}
|
||||||
|
restore-keys: coverage-${{ env.cache-name }}
|
||||||
|
|
||||||
|
- uses: actions/download-artifact@v2
|
||||||
|
|
||||||
|
- name: Install Verilator and test dependencies
|
||||||
|
run: |
|
||||||
|
tar xvzf artifact/verilator-${CI_COMMIT}.tgz
|
||||||
|
./ci/ci-install.bash
|
||||||
|
|
||||||
|
- name: Test
|
||||||
|
env:
|
||||||
|
TESTS: coverage-${{ matrix.test }}${{ matrix.num }}
|
||||||
|
run: ./ci/ci-script.bash
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
\#*
|
\#*
|
||||||
.#*
|
.#*
|
||||||
|
.nfs*
|
||||||
*~
|
*~
|
||||||
*.tidy
|
*.tidy
|
||||||
*.old
|
*.old
|
||||||
@@ -14,6 +15,8 @@
|
|||||||
*.tex
|
*.tex
|
||||||
*.pdf
|
*.pdf
|
||||||
/Makefile
|
/Makefile
|
||||||
|
/.ccache
|
||||||
|
/artifact/
|
||||||
README
|
README
|
||||||
TAGS
|
TAGS
|
||||||
autom4te.cache
|
autom4te.cache
|
||||||
|
|||||||
-187
@@ -1,187 +0,0 @@
|
|||||||
# DESCRIPTION: Travis-CI config
|
|
||||||
#
|
|
||||||
# Copyright 2003-2020 by Wilson Snyder. This program is free software; you
|
|
||||||
# can redistribute it and/or modify it under the terms of either the GNU
|
|
||||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
|
||||||
# Version 2.0.
|
|
||||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
|
||||||
|
|
||||||
version: ~> 1.0
|
|
||||||
|
|
||||||
os: linux
|
|
||||||
language: cpp
|
|
||||||
cache: ccache
|
|
||||||
|
|
||||||
env:
|
|
||||||
global:
|
|
||||||
- VERILATOR_CACHE=$HOME/verilator_cache
|
|
||||||
- VERILATOR_ROOT=$PWD
|
|
||||||
- VERILATOR_NUM_JOBS=$(echo `nproc` + 1 | bc)
|
|
||||||
- VERILATOR_CONFIG_FLAGS="--enable-maintainer-mode --enable-longtests"
|
|
||||||
- VERILATOR_AUTHOR_SITE=1
|
|
||||||
|
|
||||||
cache:
|
|
||||||
directories:
|
|
||||||
- $VERILATOR_CACHE
|
|
||||||
|
|
||||||
before_install:
|
|
||||||
# Perl modules needed for testing
|
|
||||||
# Not listing Bit::Vector as slow to install, and only skips one test
|
|
||||||
- touch temp.cpp ; g++ -E -dM -c temp.cpp | sort ; rm -rf temp.cpp
|
|
||||||
- yes yes | sudo cpan -fi Unix::Processors Parallel::Forker
|
|
||||||
- sudo apt-get install gdb gtkwave
|
|
||||||
- sudo apt-get install libgoogle-perftools-dev
|
|
||||||
before_script:
|
|
||||||
- bash -x ci/build_vcddiff.sh
|
|
||||||
- bash -x ci/build_verilator.sh
|
|
||||||
after_script:
|
|
||||||
- ccache -s
|
|
||||||
|
|
||||||
stages:
|
|
||||||
- "Build Verilator"
|
|
||||||
- test
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
include:
|
|
||||||
- if: type != cron
|
|
||||||
stage: "Build Verilator"
|
|
||||||
name: Build Verilator
|
|
||||||
compiler: gcc
|
|
||||||
script: echo "Done building Verilator"
|
|
||||||
# Non-cron build will just run on whatever linux flavor we get
|
|
||||||
- if: type != cron
|
|
||||||
stage: test
|
|
||||||
name: Dist test
|
|
||||||
compiler: gcc
|
|
||||||
script: ci/test.sh dist
|
|
||||||
- if: type != cron
|
|
||||||
stage: test
|
|
||||||
name: Vlt test
|
|
||||||
compiler: gcc
|
|
||||||
script: ci/test.sh vlt
|
|
||||||
- if: type != cron
|
|
||||||
stage: test
|
|
||||||
name: Vltmt set 0 test
|
|
||||||
compiler: gcc
|
|
||||||
script: ci/test.sh vltmt0
|
|
||||||
- if: type != cron
|
|
||||||
stage: test
|
|
||||||
name: Vltmt set 1 test
|
|
||||||
compiler: gcc
|
|
||||||
script: ci/test.sh vltmt1
|
|
||||||
# Cron builds try different OS/compiler combinations
|
|
||||||
- if: type = cron
|
|
||||||
stage: "Build Verilator"
|
|
||||||
name: Build xenial gcc Verilator
|
|
||||||
os: linux
|
|
||||||
dist: xenial
|
|
||||||
compiler: gcc
|
|
||||||
script: echo "Done building Verilator"
|
|
||||||
- if: type = cron
|
|
||||||
stage: test
|
|
||||||
name: Xenial gcc dist test
|
|
||||||
os: linux
|
|
||||||
dist: xenial
|
|
||||||
compiler: gcc
|
|
||||||
script: ci/test.sh dist
|
|
||||||
- if: type = cron
|
|
||||||
stage: test
|
|
||||||
name: Xenial gcc vlt test
|
|
||||||
os: linux
|
|
||||||
dist: xenial
|
|
||||||
compiler: gcc
|
|
||||||
script: ci/test.sh vlt
|
|
||||||
- if: type = cron
|
|
||||||
stage: test
|
|
||||||
name: Xenial gcc vltmt test
|
|
||||||
os: linux
|
|
||||||
dist: xenial
|
|
||||||
compiler: gcc
|
|
||||||
script: ci/test.sh vltmt
|
|
||||||
- if: type = cron
|
|
||||||
stage: "Build Verilator"
|
|
||||||
name: Build xenial clang Verilator
|
|
||||||
os: linux
|
|
||||||
dist: xenial
|
|
||||||
compiler: clang
|
|
||||||
script: echo "Done building Verilator"
|
|
||||||
- if: type = cron
|
|
||||||
stage: test
|
|
||||||
name: Xenial clang dist test
|
|
||||||
os: linux
|
|
||||||
dist: xenial
|
|
||||||
compiler: clang
|
|
||||||
script: ci/test.sh dist
|
|
||||||
- if: type = cron
|
|
||||||
stage: test
|
|
||||||
name: Xenial clang vlt test
|
|
||||||
os: linux
|
|
||||||
dist: xenial
|
|
||||||
compiler: clang
|
|
||||||
script: ci/test.sh vlt
|
|
||||||
- if: type = cron
|
|
||||||
stage: test
|
|
||||||
name: Xenial clang vltmt test
|
|
||||||
os: linux
|
|
||||||
dist: xenial
|
|
||||||
compiler: clang
|
|
||||||
script: ci/test.sh vltmt
|
|
||||||
# - if: type = cron
|
|
||||||
# stage: "Build Verilator"
|
|
||||||
# name: Build OSX gcc Verilator
|
|
||||||
# os: osx
|
|
||||||
# compiler: gcc
|
|
||||||
# script: echo "Done building Verilator"
|
|
||||||
# - if: type = cron
|
|
||||||
# stage: test
|
|
||||||
# name: OSX gcc dist test
|
|
||||||
# os: osx
|
|
||||||
# compiler: gcc
|
|
||||||
# script: ci/test.sh dist
|
|
||||||
# - if: type = cron
|
|
||||||
# stage: test
|
|
||||||
# name: OSX gcc vlt test
|
|
||||||
# os: osx
|
|
||||||
# compiler: gcc
|
|
||||||
# script: ci/test.sh vlt
|
|
||||||
# - if: type = cron
|
|
||||||
# stage: test
|
|
||||||
# name: OSX gcc vltmt test
|
|
||||||
# os: osx
|
|
||||||
# compiler: gcc
|
|
||||||
# script: ci/test.sh vltmt
|
|
||||||
- if: type = cron
|
|
||||||
stage: "Build Verilator"
|
|
||||||
name: Build trusty gcc Verilator
|
|
||||||
os: linux
|
|
||||||
dist: trusty
|
|
||||||
compiler: gcc
|
|
||||||
script: echo "Done building Verilator"
|
|
||||||
- if: type = cron
|
|
||||||
stage: test
|
|
||||||
name: Trusty gcc dist test
|
|
||||||
os: linux
|
|
||||||
dist: trusty
|
|
||||||
compiler: gcc
|
|
||||||
script: ci/test.sh dist
|
|
||||||
- if: type = cron
|
|
||||||
stage: test
|
|
||||||
name: Trusty gcc vlt test
|
|
||||||
os: linux
|
|
||||||
dist: trusty
|
|
||||||
compiler: gcc
|
|
||||||
script: ci/test.sh vlt
|
|
||||||
- if: type = cron
|
|
||||||
stage: test
|
|
||||||
os: linux
|
|
||||||
dist: trusty
|
|
||||||
name: Trusty gcc vltmt test
|
|
||||||
compiler: gcc
|
|
||||||
script: ci/test.sh vltmt
|
|
||||||
|
|
||||||
notifications:
|
|
||||||
email:
|
|
||||||
if: repo = verilator/verilator
|
|
||||||
recipients:
|
|
||||||
- [email protected]
|
|
||||||
- [email protected]
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
\.ccache/
|
||||||
\.clang-format
|
\.clang-format
|
||||||
\.clang-tidy
|
\.clang-tidy
|
||||||
\.git/
|
\.git/
|
||||||
@@ -23,6 +24,7 @@
|
|||||||
/obj_dir/
|
/obj_dir/
|
||||||
/obj_dist/
|
/obj_dist/
|
||||||
/obj_iv/
|
/obj_iv/
|
||||||
|
/obj_ms/
|
||||||
/obj_nc/
|
/obj_nc/
|
||||||
/obj_opt/
|
/obj_opt/
|
||||||
/obj_vcs/
|
/obj_vcs/
|
||||||
@@ -45,6 +47,8 @@ src/Makefile$
|
|||||||
src/Makefile_obj$
|
src/Makefile_obj$
|
||||||
include/verilated.mk$
|
include/verilated.mk$
|
||||||
test_regress/.gdbinit$
|
test_regress/.gdbinit$
|
||||||
|
test_regress/transcript
|
||||||
|
codecov.yml
|
||||||
config.cache$
|
config.cache$
|
||||||
config.status$
|
config.status$
|
||||||
verilator\.log
|
verilator\.log
|
||||||
@@ -65,4 +69,5 @@ ci/
|
|||||||
/csrc/
|
/csrc/
|
||||||
obj_dir.*
|
obj_dir.*
|
||||||
TAGS
|
TAGS
|
||||||
|
gmon.out
|
||||||
.*~
|
.*~
|
||||||
|
|||||||
+39
-13
@@ -7,7 +7,7 @@
|
|||||||
#
|
#
|
||||||
#*****************************************************************************
|
#*****************************************************************************
|
||||||
#
|
#
|
||||||
# Copyright 2003-2020 by Wilson Snyder. This program is free software; you
|
# Copyright 2003-2021 by Wilson Snyder. This program is free software; you
|
||||||
# can redistribute it and/or modify it under the terms of either the GNU
|
# can 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.
|
||||||
@@ -89,7 +89,6 @@ datarootdir = @datarootdir@
|
|||||||
CFG_WITH_CCWARN = @CFG_WITH_CCWARN@
|
CFG_WITH_CCWARN = @CFG_WITH_CCWARN@
|
||||||
CFG_WITH_DEFENV = @CFG_WITH_DEFENV@
|
CFG_WITH_DEFENV = @CFG_WITH_DEFENV@
|
||||||
CFG_WITH_LONGTESTS = @CFG_WITH_LONGTESTS@
|
CFG_WITH_LONGTESTS = @CFG_WITH_LONGTESTS@
|
||||||
CFG_WITH_THREADED = @CFG_WITH_THREADED@
|
|
||||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||||
|
|
||||||
#### End of system configuration section. ####
|
#### End of system configuration section. ####
|
||||||
@@ -154,6 +153,7 @@ DISTFILES_INC = $(INFOS) .gitignore \
|
|||||||
.*attributes */.*attributes */*/.*attributes \
|
.*attributes */.*attributes */*/.*attributes \
|
||||||
src/.*ignore src/*.in src/*.cpp src/*.[chly] \
|
src/.*ignore src/*.in src/*.cpp src/*.[chly] \
|
||||||
src/astgen src/bisonpre src/*fix src/cppcheck_filtered \
|
src/astgen src/bisonpre src/*fix src/cppcheck_filtered \
|
||||||
|
src/config_rev \
|
||||||
src/vlcovgen src/mkinstalldirs \
|
src/vlcovgen src/mkinstalldirs \
|
||||||
src/.gdbinit \
|
src/.gdbinit \
|
||||||
src/*.pl src/*.pod \
|
src/*.pl src/*.pod \
|
||||||
@@ -171,6 +171,8 @@ DISTFILES_INC = $(INFOS) .gitignore \
|
|||||||
test_regress/t/t*/*.v* \
|
test_regress/t/t*/*.v* \
|
||||||
test_regress/t/t*/*/*.sv* \
|
test_regress/t/t*/*/*.sv* \
|
||||||
test_regress/t/t*/*/*.v* \
|
test_regress/t/t*/*/*.v* \
|
||||||
|
test_regress/t/t*/*.cpp \
|
||||||
|
test_regress/t/t*/CMakeLists.txt \
|
||||||
test_regress/t/*.cpp \
|
test_regress/t/*.cpp \
|
||||||
test_regress/t/*.h \
|
test_regress/t/*.h \
|
||||||
test_regress/t/*.dat \
|
test_regress/t/*.dat \
|
||||||
@@ -218,7 +220,7 @@ all_nomsg: verilator_exe $(VL_INST_MAN_FILES)
|
|||||||
verilator_exe verilator_bin verilator_bin_dbg verilator_coverage_bin_dbg:
|
verilator_exe verilator_bin verilator_bin_dbg verilator_coverage_bin_dbg:
|
||||||
@echo ------------------------------------------------------------
|
@echo ------------------------------------------------------------
|
||||||
@echo "making verilator in src"
|
@echo "making verilator in src"
|
||||||
$(MAKE) -C src $(OBJCACHE_JOBS)
|
$(MAKE) -C src $(OBJCACHE_JOBS) $(CI_MAKE_SRC_TARGET)
|
||||||
|
|
||||||
.PHONY:msg_test
|
.PHONY:msg_test
|
||||||
msg_test: all_nomsg
|
msg_test: all_nomsg
|
||||||
@@ -420,12 +422,16 @@ endif
|
|||||||
|
|
||||||
# Use --xml flag to see the cppcheck code to use for suppression
|
# Use --xml flag to see the cppcheck code to use for suppression
|
||||||
CPPCHECK_CPP = $(wildcard \
|
CPPCHECK_CPP = $(wildcard \
|
||||||
|
$(srcdir)/examples/*/*.cpp \
|
||||||
$(srcdir)/include/*.cpp \
|
$(srcdir)/include/*.cpp \
|
||||||
$(srcdir)/src/*.cpp )
|
$(srcdir)/src/*.cpp )
|
||||||
CPPCHECK_H = $(wildcard \
|
CPPCHECK_H = $(wildcard \
|
||||||
$(srcdir)/include/*.h \
|
$(srcdir)/include/*.h \
|
||||||
$(srcdir)/src/*.h )
|
$(srcdir)/src/*.h )
|
||||||
CPPCHECK = src/cppcheck_filtered
|
CPPCHECK_YL = $(wildcard \
|
||||||
|
$(srcdir)/src/*.y \
|
||||||
|
$(srcdir)/src/*.l )
|
||||||
|
CPPCHECK = src/cppcheck_filtered cppcheck
|
||||||
CPPCHECK_FLAGS = --enable=all --inline-suppr \
|
CPPCHECK_FLAGS = --enable=all --inline-suppr \
|
||||||
--suppress=unusedScopedObject --suppress=cstyleCast --suppress=useInitializationList \
|
--suppress=unusedScopedObject --suppress=cstyleCast --suppress=useInitializationList \
|
||||||
--suppress=nullPointerRedundantCheck
|
--suppress=nullPointerRedundantCheck
|
||||||
@@ -435,18 +441,19 @@ CPPCHECK_INC = -I$(srcdir)/include -I$(srcdir)/src/obj_dbg -I$(srcdir)/src
|
|||||||
|
|
||||||
cppcheck: $(CPPCHECK_DEP)
|
cppcheck: $(CPPCHECK_DEP)
|
||||||
%.cppcheck: %.cpp
|
%.cppcheck: %.cpp
|
||||||
$(CPPCHECK) $(CPPCHECK_FLAGS) -DVL_DEBUG=1 -DVL_CPPCHECK=1 $(CPPCHECK_INC) $<
|
$(CPPCHECK) $(CPPCHECK_FLAGS) -DVL_DEBUG=1 -DVL_CPPCHECK=1 -DVL_THREADED=1 $(CPPCHECK_INC) $<
|
||||||
|
|
||||||
CLANGTIDY = clang-tidy
|
CLANGTIDY = clang-tidy
|
||||||
CLANGTIDY_FLAGS = -config=''
|
CLANGTIDY_FLAGS = -config='' -checks='-fuchsia-*,-cppcoreguidelines-avoid-c-arrays,-cppcoreguidelines-init-variables'
|
||||||
CLANGTIDY_DEP = $(subst .h,.h.tidy,$(CPPCHECK_H)) \
|
CLANGTIDY_DEP = $(subst .h,.h.tidy,$(CPPCHECK_H)) \
|
||||||
$(subst .cpp,.cpp.tidy,$(CPPCHECK_CPP))
|
$(subst .cpp,.cpp.tidy,$(CPPCHECK_CPP))
|
||||||
|
CLANGTIDY_DEFS = -DVL_DEBUG=1 -DVL_THREADED=1 -DVL_CPPCHECK=1
|
||||||
|
|
||||||
clangtidy: $(CLANGTIDY_DEP)
|
clang-tidy: $(CLANGTIDY_DEP)
|
||||||
%.cpp.tidy: %.cpp
|
%.cpp.tidy: %.cpp
|
||||||
$(CLANGTIDY) $(CLANGTIDY_FLAGS) $< -- -DVL_DEBUG=1 -DVL_CPPCHECK=1 $(CPPCHECK_INC) | 2>&1 tee $@
|
$(CLANGTIDY) $(CLANGTIDY_FLAGS) $< -- $(CLANGTIDY_DEFS) $(CPPCHECK_INC) | 2>&1 tee $@
|
||||||
%.h.tidy: %.h
|
%.h.tidy: %.h
|
||||||
$(CLANGTIDY) $(CLANGTIDY_FLAGS) $< -- -DVL_DEBUG=1 -DVL_CPPCHECK=1 $(CPPCHECK_INC) | 2>&1 tee $@
|
$(CLANGTIDY) $(CLANGTIDY_FLAGS) $< -- $(CLANGTIDY_DEFS) $(CPPCHECK_INC) | 2>&1 tee $@
|
||||||
|
|
||||||
analyzer-src:
|
analyzer-src:
|
||||||
-rm -rf src/obj_dbg
|
-rm -rf src/obj_dbg
|
||||||
@@ -456,13 +463,35 @@ analyzer-include:
|
|||||||
-rm -rf examples/*/obj*
|
-rm -rf examples/*/obj*
|
||||||
scan-build $(MAKE) -k examples
|
scan-build $(MAKE) -k examples
|
||||||
|
|
||||||
|
format: clang-format yapf
|
||||||
|
|
||||||
CLANGFORMAT = clang-format
|
CLANGFORMAT = clang-format
|
||||||
CLANGFORMAT_FLAGS = -i
|
CLANGFORMAT_FLAGS = -i
|
||||||
|
CLANGFORMAT_FILES = $(CPPCHECK_CPP) $(CPPCHECK_H) $(CPPCHECK_YL) test_regress/t/*.c* test_regress/t/*.h
|
||||||
|
|
||||||
clang-format:
|
clang-format:
|
||||||
@$(CLANGFORMAT) --version | egrep 10.0 > /dev/null \
|
@$(CLANGFORMAT) --version | egrep 10.0 > /dev/null \
|
||||||
|| echo "*** You are not using clang-format 10.0, indents may differ from master's ***"
|
|| echo "*** You are not using clang-format 10.0, indents may differ from master's ***"
|
||||||
$(CLANGFORMAT) $(CLANGFORMAT_FLAGS) $(CPPCHECK_CPP) $(CPPCHECK_H)
|
$(CLANGFORMAT) $(CLANGFORMAT_FLAGS) $(CLANGFORMAT_FILES)
|
||||||
|
|
||||||
|
YAPF = yapf3
|
||||||
|
YAPF_FLAGS = -i
|
||||||
|
YAPF_FILES = \
|
||||||
|
examples/xml_py/vl_file_copy \
|
||||||
|
examples/xml_py/vl_hier_graph \
|
||||||
|
src/config_rev \
|
||||||
|
src/cppcheck_filtered \
|
||||||
|
src/flexfix \
|
||||||
|
src/vlcovgen \
|
||||||
|
nodist/code_coverage \
|
||||||
|
nodist/code_coverage.dat \
|
||||||
|
nodist/dot_importer \
|
||||||
|
nodist/fuzzer/actual_fail \
|
||||||
|
nodist/fuzzer/generate_dictionary \
|
||||||
|
nodist/install_test \
|
||||||
|
|
||||||
|
yapf:
|
||||||
|
$(YAPF) $(YAPF_FLAGS) $(YAPF_FILES)
|
||||||
|
|
||||||
ftp: info
|
ftp: info
|
||||||
|
|
||||||
@@ -543,9 +572,6 @@ dist-file-list:
|
|||||||
@echo $(wildcard $(DISTFILES))
|
@echo $(wildcard $(DISTFILES))
|
||||||
@echo "end-dist-file-list:"; # Scripts look for this
|
@echo "end-dist-file-list:"; # Scripts look for this
|
||||||
|
|
||||||
print-cfg-with-threaded:
|
|
||||||
@echo $(CFG_WITH_THREADED)
|
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
# Distributions
|
# Distributions
|
||||||
|
|
||||||
|
|||||||
+11
-8
@@ -5,7 +5,8 @@ ifdef::env-github[]
|
|||||||
image:https://img.shields.io/badge/License-LGPL%20v3-blue.svg[license LGPLv3,link=https://www.gnu.org/licenses/lgpl-3.0]
|
image:https://img.shields.io/badge/License-LGPL%20v3-blue.svg[license LGPLv3,link=https://www.gnu.org/licenses/lgpl-3.0]
|
||||||
image:https://img.shields.io/badge/License-Artistic%202.0-0298c3.svg[license Artistic-2.0,link=https://opensource.org/licenses/Artistic-2.0]
|
image:https://img.shields.io/badge/License-Artistic%202.0-0298c3.svg[license Artistic-2.0,link=https://opensource.org/licenses/Artistic-2.0]
|
||||||
image:https://api.codacy.com/project/badge/Grade/fa78caa433c84a4ab9049c43e9debc6f[Code Quality,link=https://www.codacy.com/gh/verilator/verilator]
|
image:https://api.codacy.com/project/badge/Grade/fa78caa433c84a4ab9049c43e9debc6f[Code Quality,link=https://www.codacy.com/gh/verilator/verilator]
|
||||||
image:https://travis-ci.com/verilator/verilator.svg?branch=master[Build Status (Travis CI),link=https://travis-ci.com/verilator/verilator]
|
image:https://codecov.io/gh/verilator/verilator/branch/master/graph/badge.svg[Coverage,link=https://codecov.io/gh/verilator/verilator]
|
||||||
|
image:https://github.com/verilator/verilator/workflows/build/badge.svg[Build Status (GitHub),link=https://github.com/verilator/verilator/actions?query=workflow%3Abuild]
|
||||||
endif::[]
|
endif::[]
|
||||||
|
|
||||||
ifdef::env-github[]
|
ifdef::env-github[]
|
||||||
@@ -20,9 +21,9 @@ endif::[]
|
|||||||
|
|
||||||
== Welcome to Verilator
|
== Welcome to Verilator
|
||||||
|
|
||||||
[cols="a,a",indent=0,frame="none"]
|
[cols="a,a",indent=0,frame="none",grid="rows"]
|
||||||
|===
|
|===
|
||||||
^.^| *Welcome to Verilator, the fastest Verilog HDL simulator.*
|
^.^| *Welcome to Verilator, the fastest Verilog/SystemVerilog simulator.*
|
||||||
+++ <br/> +++ • Accepts synthesizable Verilog or SystemVerilog
|
+++ <br/> +++ • Accepts synthesizable Verilog or SystemVerilog
|
||||||
+++ <br/> +++ • Performs lint code-quality checks
|
+++ <br/> +++ • Performs lint code-quality checks
|
||||||
+++ <br/> +++ • Compiles into multithreaded {cpp}, or SystemC
|
+++ <br/> +++ • Compiles into multithreaded {cpp}, or SystemC
|
||||||
@@ -73,15 +74,15 @@ replacement for NC-Verilog, VCS or another commercial Verilog simulator, or
|
|||||||
if you are looking for a behavioral Verilog simulator e.g. for a quick
|
if you are looking for a behavioral Verilog simulator e.g. for a quick
|
||||||
class project (we recommend http://iverilog.icarus.com[Icarus Verilog] for
|
class project (we recommend http://iverilog.icarus.com[Icarus Verilog] for
|
||||||
this.) However, if you are looking for a path to migrate SystemVerilog to
|
this.) However, if you are looking for a path to migrate SystemVerilog to
|
||||||
{cpp} or SystemC, and your team is comfortable writing just a
|
{cpp} or SystemC, or your team is comfortable writing just a touch of {cpp}
|
||||||
touch of {cpp} code, Verilator is the tool for you.
|
code, Verilator is the tool for you.
|
||||||
|
|
||||||
== Performance
|
== Performance
|
||||||
|
|
||||||
Verilator does not simply convert Verilog HDL to {cpp} or SystemC. Rather,
|
Verilator does not simply convert Verilog HDL to {cpp} or SystemC. Rather,
|
||||||
Verilator compiles your code into a much faster optimized and optionally
|
Verilator compiles your code into a much faster optimized and optionally
|
||||||
thread-partitioned model, which is in turn wrapped inside a
|
thread-partitioned model, which is in turn wrapped inside a
|
||||||
{cpp}/SystemC/{cpp}-under-Python module. The results are a compiled
|
{cpp}/SystemC module. The results are a compiled
|
||||||
Verilog model that executes even on a single-thread over 10x faster than
|
Verilog model that executes even on a single-thread over 10x faster than
|
||||||
standalone SystemC, and on a single thread is about 100 times faster than
|
standalone SystemC, and on a single thread is about 100 times faster than
|
||||||
interpreted Verilog simulators such as http://iverilog.icarus.com[Icarus
|
interpreted Verilog simulators such as http://iverilog.icarus.com[Icarus
|
||||||
@@ -112,9 +113,11 @@ For more information:
|
|||||||
* https://verilator.org/verilator_doc.html[Verilator manual (HTML)],
|
* https://verilator.org/verilator_doc.html[Verilator manual (HTML)],
|
||||||
or https://verilator.org/verilator_doc.pdf[Verilator manual (PDF)]
|
or https://verilator.org/verilator_doc.pdf[Verilator manual (PDF)]
|
||||||
|
|
||||||
|
* https://github.com/verilator/verilator-announce[Subscribe to verilator announcements]
|
||||||
|
|
||||||
* https://verilator.org/forum[Verilator forum]
|
* https://verilator.org/forum[Verilator forum]
|
||||||
|
|
||||||
* https://verilator.org/issues[Verilator Issues]
|
* https://verilator.org/issues[Verilator issues]
|
||||||
|
|
||||||
== Support
|
== Support
|
||||||
|
|
||||||
@@ -142,7 +145,7 @@ perhaps Icarus may.
|
|||||||
|
|
||||||
== Open License
|
== Open License
|
||||||
|
|
||||||
Verilator is Copyright 2003-2020 by Wilson Snyder. (Report bugs to
|
Verilator is Copyright 2003-2021 by Wilson Snyder. (Report bugs to
|
||||||
https://verilator.org/issues[Verilator Issues].)
|
https://verilator.org/issues[Verilator Issues].)
|
||||||
|
|
||||||
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
|
||||||
|
|||||||
+885
-676
File diff suppressed because it is too large
Load Diff
+19
-5
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env perl
|
#!/usr/bin/env perl
|
||||||
######################################################################
|
######################################################################
|
||||||
#
|
#
|
||||||
# Copyright 2003-2020 by Wilson Snyder. This program is free software; you
|
# Copyright 2003-2021 by Wilson Snyder. This program is free software; you
|
||||||
# can redistribute it and/or modify it under the terms of either the GNU
|
# can 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.
|
||||||
@@ -156,6 +156,8 @@ verilator_coverage - Verilator coverage analyzer
|
|||||||
|
|
||||||
verilator_coverage -write merged.dat -read <datafiles>...
|
verilator_coverage -write merged.dat -read <datafiles>...
|
||||||
|
|
||||||
|
verilator_coverage -write-info merged.info -read <datafiles>...
|
||||||
|
|
||||||
Verilator_coverage processes Verilator coverage reports.
|
Verilator_coverage processes Verilator coverage reports.
|
||||||
|
|
||||||
With --anotate, it reads the specified data file and generates annotated
|
With --anotate, it reads the specified data file and generates annotated
|
||||||
@@ -224,8 +226,20 @@ Displays program version and exits.
|
|||||||
=item --write I<filename>
|
=item --write I<filename>
|
||||||
|
|
||||||
Specifies the aggregate coverage results, summed across all the files,
|
Specifies the aggregate coverage results, summed across all the files,
|
||||||
should be written to the given filename. This is useful in scripts to
|
should be written to the given filename in verilator_coverage data format.
|
||||||
combine many sequential runs into one master coverage file.
|
This is useful in scripts to combine many sequential runs into one master
|
||||||
|
coverage file.
|
||||||
|
|
||||||
|
=item --write-info I<filename.info>
|
||||||
|
|
||||||
|
Specifies the aggregate coverage results, summed across all the files,
|
||||||
|
should be written to the given filename in C<lcov> .info format.
|
||||||
|
This may be used to use C<lcov> to aggregate or generate reports.
|
||||||
|
|
||||||
|
The info format loses data compared to the Verilator coverage data format;
|
||||||
|
the info will all forms of coverage converted to line style coverage, and
|
||||||
|
if there are multiple coverage points on a single line, the minimum
|
||||||
|
coverage across those points will be used to report coverage of the line.
|
||||||
|
|
||||||
=back
|
=back
|
||||||
|
|
||||||
@@ -264,7 +278,7 @@ Specifies a module search directory.
|
|||||||
|
|
||||||
The latest version is available from L<https://verilator.org>.
|
The latest version is available from L<https://verilator.org>.
|
||||||
|
|
||||||
Copyright 2003-2020 by Wilson Snyder. This program is free software; you
|
Copyright 2003-2021 by Wilson Snyder. This program is free software; you
|
||||||
can redistribute it and/or modify the Verilator internals under the terms
|
can redistribute it and/or modify the Verilator internals under the terms
|
||||||
of either the GNU Lesser General Public License Version 3 or the Perl
|
of either the GNU Lesser General Public License Version 3 or the Perl
|
||||||
Artistic License Version 2.0.
|
Artistic License Version 2.0.
|
||||||
@@ -277,7 +291,7 @@ Wilson Snyder <[email protected]>
|
|||||||
|
|
||||||
=head1 SEE ALSO
|
=head1 SEE ALSO
|
||||||
|
|
||||||
C<verilator>
|
C<verilator>, C<lcov>
|
||||||
|
|
||||||
L<verilator_coverage --help> which is the source for this document.
|
L<verilator_coverage --help> which is the source for this document.
|
||||||
|
|
||||||
|
|||||||
+1
-26
@@ -9,22 +9,6 @@ use Pod::Usage;
|
|||||||
use strict;
|
use strict;
|
||||||
use vars qw($Debug);
|
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
|
||||||
|
|
||||||
@@ -133,8 +117,6 @@ sub filter {
|
|||||||
$line =~ s/{[a-z]*\d+}/{}/g if !$Opt_Lineno;
|
$line =~ s/{[a-z]*\d+}/{}/g if !$Opt_Lineno;
|
||||||
if ($verCvt) {
|
if ($verCvt) {
|
||||||
next if $line =~ /^ NETLIST/;
|
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]+) /) {
|
if ($line =~ /: ([A-Z]+) /) {
|
||||||
my $type = $1;
|
my $type = $1;
|
||||||
next if $type =~ 'DTYPE';
|
next if $type =~ 'DTYPE';
|
||||||
@@ -147,14 +129,7 @@ sub filter {
|
|||||||
}
|
}
|
||||||
next;
|
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;
|
||||||
}
|
}
|
||||||
@@ -233,7 +208,7 @@ Do not show differences in line numbering.
|
|||||||
|
|
||||||
The latest version is available from L<https://verilator.org>.
|
The latest version is available from L<https://verilator.org>.
|
||||||
|
|
||||||
Copyright 2005-2020 by Wilson Snyder. This program is free software; you
|
Copyright 2005-2021 by Wilson Snyder. This program is free software; you
|
||||||
can redistribute it and/or modify it under the terms of either the GNU
|
can 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.
|
||||||
|
|||||||
+89
-10
@@ -60,6 +60,7 @@ sub process {
|
|||||||
my $filename = shift;
|
my $filename = shift;
|
||||||
|
|
||||||
read_data($filename);
|
read_data($filename);
|
||||||
|
read_cpuinfo();
|
||||||
report();
|
report();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,7 +71,7 @@ sub read_data {
|
|||||||
|
|
||||||
%Global = (rdtsc_cycle_time => 0);
|
%Global = (rdtsc_cycle_time => 0);
|
||||||
|
|
||||||
my $fh = IO::File->new ($filename) or die "%Error: $! $filename,";
|
my $fh = IO::File->new("<$filename") or die "%Error: $! $filename,";
|
||||||
while (my $line = $fh->getline) {
|
while (my $line = $fh->getline) {
|
||||||
if ($line =~ m/VLPROF mtask\s(\d+)\sstart\s(\d+)\send\s(\d+)\selapsed\s(\d+)\spredict_time\s(\d+)\scpu\s(\d+)\son thread (\d+)/) {
|
if ($line =~ m/VLPROF mtask\s(\d+)\sstart\s(\d+)\send\s(\d+)\selapsed\s(\d+)\spredict_time\s(\d+)\scpu\s(\d+)\son thread (\d+)/) {
|
||||||
my $mtask = $1;
|
my $mtask = $1;
|
||||||
@@ -113,6 +114,27 @@ sub read_data {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub read_cpuinfo {
|
||||||
|
my $filename = "/proc/cpuinfo";
|
||||||
|
my $fh = IO::File->new("<$filename") or return;
|
||||||
|
my $cpu;
|
||||||
|
while (my $line = $fh->getline) {
|
||||||
|
chomp $line;
|
||||||
|
if ($line =~ m/^processor\s*:\s*(\d+)\s*$/) {
|
||||||
|
$cpu = $1;
|
||||||
|
}
|
||||||
|
if ($cpu && $line =~ m/^([a-z_ ]+)\s*:\s*(.*)$/) {
|
||||||
|
my ($term, $value) = ($1, $2);
|
||||||
|
$term =~ s/\s+$//;
|
||||||
|
$term =~ s/\s+/_/;
|
||||||
|
$value =~ s/\s+$//;
|
||||||
|
$Global{cpuinfo}{$cpu}{$term} = $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#######################################################################
|
||||||
|
|
||||||
sub report {
|
sub report {
|
||||||
print "Verilator Gantt report\n";
|
print "Verilator Gantt report\n";
|
||||||
|
|
||||||
@@ -156,14 +178,15 @@ sub report {
|
|||||||
print "\nAnalysis:\n";
|
print "\nAnalysis:\n";
|
||||||
printf " Total threads = %d\n", $nthreads;
|
printf " Total threads = %d\n", $nthreads;
|
||||||
printf " Total mtasks = %d\n", scalar(keys %Mtasks);
|
printf " Total mtasks = %d\n", scalar(keys %Mtasks);
|
||||||
printf " Total cpus used = %d\n", scalar(keys %{$Global{cpus}});
|
my $ncpus = scalar(keys %{$Global{cpus}});
|
||||||
|
printf " Total cpus used = %d\n", $ncpus;
|
||||||
printf " Total yields = %d\n", $Global{stats}{yields};
|
printf " Total yields = %d\n", $Global{stats}{yields};
|
||||||
printf " Total eval time = %d rdtsc ticks\n", $Global{last_end};
|
printf " Total eval time = %d rdtsc ticks\n", $Global{last_end};
|
||||||
printf " Longest mtask time = %d rdtsc ticks\n", $long_mtask_time;
|
printf " Longest mtask time = %d rdtsc ticks\n", $long_mtask_time;
|
||||||
printf " All-thread mtask time = %d rdtsc ticks\n", $mt_mtask_time;
|
printf " All-thread mtask time = %d rdtsc ticks\n", $mt_mtask_time;
|
||||||
my $long_efficiency = $long_mtask_time/($Global{last_end});
|
my $long_efficiency = $long_mtask_time/($Global{last_end} || 1);
|
||||||
printf " Longest-thread efficiency = %0.1f%%\n", $long_efficiency*100;
|
printf " Longest-thread efficiency = %0.1f%%\n", $long_efficiency*100;
|
||||||
my $mt_efficiency = $mt_mtask_time/($Global{last_end}*$nthreads);
|
my $mt_efficiency = $mt_mtask_time/($Global{last_end}*$nthreads || 1);
|
||||||
printf " All-thread efficiency = %0.1f%%\n", $mt_efficiency*100;
|
printf " All-thread efficiency = %0.1f%%\n", $mt_efficiency*100;
|
||||||
printf " All-thread speedup = %0.1f\n", $mt_efficiency*$nthreads;
|
printf " All-thread speedup = %0.1f\n", $mt_efficiency*$nthreads;
|
||||||
if ($Global{rdtsc_cycle_time} > 0) {
|
if ($Global{rdtsc_cycle_time} > 0) {
|
||||||
@@ -197,17 +220,72 @@ sub report {
|
|||||||
}
|
}
|
||||||
|
|
||||||
print "\nStatistics:\n";
|
print "\nStatistics:\n";
|
||||||
print " min log(p2e) = $min_p2e from mtask $min_mtask (predict $Mtasks{$min_mtask}{predict}, elapsed $Mtasks{$min_mtask}{elapsed})\n";
|
printf " min log(p2e) = %0.3f", $min_p2e;
|
||||||
print " max log(p2e) = $max_p2e from mtask $max_mtask (predict $Mtasks{$max_mtask}{predict}, elapsed $Mtasks{$max_mtask}{elapsed})\n";
|
print " from mtask $min_mtask (predict $Mtasks{$min_mtask}{predict},";
|
||||||
|
print " elapsed $Mtasks{$min_mtask}{elapsed})\n";
|
||||||
|
printf " max log(p2e) = %0.3f", $max_p2e;
|
||||||
|
print " from mtask $max_mtask (predict $Mtasks{$max_mtask}{predict},";
|
||||||
|
print " elapsed $Mtasks{$max_mtask}{elapsed})\n";
|
||||||
|
|
||||||
my $stddev = stddev(\@p2e_ratios);
|
my $stddev = stddev(\@p2e_ratios);
|
||||||
my $mean = mean(\@p2e_ratios);
|
my $mean = mean(\@p2e_ratios);
|
||||||
print " mean = " . ($mean) . "\n";
|
printf " mean = %0.3f\n", $mean;
|
||||||
print " stddev = " . ($stddev) . "\n";
|
printf " stddev = %0.3f\n", $stddev;
|
||||||
print " e ^ stddev = " . exp($stddev). "\n";
|
printf " e ^ stddev = %0.3f\n", exp($stddev);
|
||||||
|
|
||||||
|
report_cpus();
|
||||||
|
|
||||||
|
if ($nthreads > $ncpus) {
|
||||||
|
print "\n";
|
||||||
|
print "%Warning: There were fewer CPUs ($ncpus) then threads ($nthreads).\n";
|
||||||
|
print " : See docs on use of numactl.\n";
|
||||||
|
} else {
|
||||||
|
if ($Global{cpu_socket_cores_warning}) {
|
||||||
|
print "\n";
|
||||||
|
print "%Warning: Multiple threads scheduled on same hyperthreaded core.\n";
|
||||||
|
print " : See docs on use of numactl.\n";
|
||||||
|
}
|
||||||
|
if ($Global{cpu_sockets_warning}) {
|
||||||
|
print "\n";
|
||||||
|
print "%Warning: Threads scheduled on multiple sockets.\n";
|
||||||
|
print " : See docs on use of numactl.\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
print "\n";
|
print "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub report_cpus {
|
||||||
|
print "\nCPUs:\n";
|
||||||
|
# Test - show all cores
|
||||||
|
# for (my $i=0; $i<73; ++$i) { $Global{cpus}{$i} ||= {cpu_time => 0}; }
|
||||||
|
|
||||||
|
$Global{cpu_sockets} ||= {};
|
||||||
|
$Global{cpu_socket_cores} ||= {};
|
||||||
|
|
||||||
|
foreach my $cpu (sort {$a <=> $b} keys %{$Global{cpus}}) {
|
||||||
|
printf " cpu %d: ", $cpu;
|
||||||
|
printf "cpu_time=%d", $Global{cpus}{$cpu}{cpu_time};
|
||||||
|
|
||||||
|
my $socket = $Global{cpuinfo}{$cpu}{physical_id};
|
||||||
|
$Global{cpu_sockets}{$socket}++ if defined $socket;
|
||||||
|
printf " socket=%d", $socket if defined $socket;
|
||||||
|
|
||||||
|
my $core = $Global{cpuinfo}{$cpu}{core_id};
|
||||||
|
$Global{cpu_socket_cores}{$socket."__".$core}++ if defined $socket && defined $core;
|
||||||
|
printf " core=%d", $core if defined $core;
|
||||||
|
|
||||||
|
my $model = $Global{cpuinfo}{$cpu}{model_name};
|
||||||
|
printf " %s", $model if defined $model;
|
||||||
|
print "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
$Global{cpu_sockets_warning} = 1
|
||||||
|
if (scalar keys %{$Global{cpu_sockets}} > 1);
|
||||||
|
foreach my $scn (values %{$Global{cpu_socket_cores}}) {
|
||||||
|
$Global{cpu_socket_cores_warning} = 1 if $scn > 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sub report_graph {
|
sub report_graph {
|
||||||
my $time_per = $Opt_Time_Per_Char;
|
my $time_per = $Opt_Time_Per_Char;
|
||||||
if ($time_per == 0) {
|
if ($time_per == 0) {
|
||||||
@@ -219,6 +297,7 @@ sub report_graph {
|
|||||||
}
|
}
|
||||||
# One more step so we can fit more labels
|
# One more step so we can fit more labels
|
||||||
$time_per = int($time_per/2);
|
$time_per = int($time_per/2);
|
||||||
|
$time_per ||= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
my ($graph, $conflicts) = _make_graph($time_per);
|
my ($graph, $conflicts) = _make_graph($time_per);
|
||||||
@@ -538,7 +617,7 @@ verilator_gantt.vcd.
|
|||||||
|
|
||||||
The latest version is available from L<https://verilator.org>.
|
The latest version is available from L<https://verilator.org>.
|
||||||
|
|
||||||
Copyright 2018-2020 by Wilson Snyder. This program is free software; you
|
Copyright 2018-2021 by Wilson Snyder. This program is free software; you
|
||||||
can redistribute it and/or modify it under the terms of either the GNU
|
can 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,7 +1,7 @@
|
|||||||
#!/usr/bin/env perl
|
#!/usr/bin/env perl
|
||||||
# DESCRIPTION: Print include statements for each ARGV
|
# DESCRIPTION: Print include statements for each ARGV
|
||||||
#
|
#
|
||||||
# Copyright 2003-2020 by Wilson Snyder. This program is free software; you
|
# Copyright 2003-2021 by Wilson Snyder. This program is free software; you
|
||||||
# can redistribute it and/or modify it under the terms of either the GNU
|
# can 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.
|
||||||
|
|||||||
@@ -228,7 +228,7 @@ Displays this message and program version and exits.
|
|||||||
|
|
||||||
The latest version is available from L<https://verilator.org>.
|
The latest version is available from L<https://verilator.org>.
|
||||||
|
|
||||||
Copyright 2007-2020 by Wilson Snyder. This program is free software; you
|
Copyright 2007-2021 by Wilson Snyder. This program is free software; you
|
||||||
can redistribute it and/or modify it under the terms of either the GNU
|
can 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,19 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
# DESCRIPTION: Verilator: Build script for vcddiff
|
|
||||||
#
|
|
||||||
# Copyright 2019 by Todd Strader. This program is free software; you
|
|
||||||
# can redistribute it and/or modify it under the terms of either the GNU
|
|
||||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
|
||||||
# Version 2.0.
|
|
||||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
|
||||||
set -e
|
|
||||||
|
|
||||||
# NB: it would be better to add this via a PPA
|
|
||||||
|
|
||||||
TMP_DIR=$(mktemp -d)
|
|
||||||
|
|
||||||
git -C "${TMP_DIR}" clone https://github.com/veripool/vcddiff
|
|
||||||
VCDDIFF_DIR=${TMP_DIR}/vcddiff
|
|
||||||
git -C "${VCDDIFF_DIR}" checkout 5112f88b7ba8818dce9dfb72619e64a1fc19542c
|
|
||||||
make -C "${VCDDIFF_DIR}"
|
|
||||||
sudo cp "${VCDDIFF_DIR}/vcddiff" /usr/local/bin
|
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
# DESCRIPTION: Verilator: Travis CI build script
|
|
||||||
#
|
|
||||||
# Copyright 2019 by Todd Strader. This program is free software; you
|
|
||||||
# can redistribute it and/or modify it under the terms of either the GNU
|
|
||||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
|
||||||
# Version 2.0.
|
|
||||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
|
||||||
#
|
|
||||||
# This script builds and caches the Verilator binaries for Travis CI
|
|
||||||
# (and possibly other CI platforms). The Verilator CI system uses this
|
|
||||||
# script, but other CI systems that depend on Verilator may also use
|
|
||||||
# the script.
|
|
||||||
# see: https://github.com/verilator/verilator_ext_tests/blob/master/.travis.yml
|
|
||||||
# To use this script, either checkout Verilator as part of the CI build
|
|
||||||
# process or add Verilator as a Git submodule. Verilator tarballs can
|
|
||||||
# not be used as the script relies on Git revisions for caching.
|
|
||||||
set -e
|
|
||||||
|
|
||||||
if [ -z "${VERILATOR_NUM_JOBS}" ]; then
|
|
||||||
VERILATOR_NUM_JOBS=$(nproc)
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Caching would be simpler if we installed without VERILATOR_ROOT, but
|
|
||||||
# it's needed for driver.pl outside of the repo
|
|
||||||
if [ -z "${VERILATOR_ROOT}" ]; then
|
|
||||||
echo "VERILATOR_ROOT not set"
|
|
||||||
exit -1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "${VERILATOR_CACHE}" ]; then
|
|
||||||
echo "VERILATOR_CACHE not set"
|
|
||||||
exit -1
|
|
||||||
fi
|
|
||||||
|
|
||||||
VERILATOR_REV=$(cd "${VERILATOR_ROOT}" && git rev-parse HEAD)
|
|
||||||
echo "Found Verilator rev ${VERILATOR_REV}"
|
|
||||||
|
|
||||||
CACHED_REV_FILE=${VERILATOR_CACHE}/.rev.txt
|
|
||||||
|
|
||||||
if [[ ! -f "${CACHED_REV_FILE}" || \
|
|
||||||
$(< "${CACHED_REV_FILE}") != "${VERILATOR_REV}" ]]; then
|
|
||||||
echo "Building Verilator"
|
|
||||||
|
|
||||||
# Unsure why Travis monkies with the capitalization of the stage name, but it does
|
|
||||||
if [[ -n ${TRAVIS_BUILD_STAGE_NAME} && \
|
|
||||||
${TRAVIS_BUILD_STAGE_NAME} != "Build verilator" ]]; then
|
|
||||||
echo "WARNING: Building Verilator in Travis build stage other than \"Build verilator\": ${TRAVIS_BUILD_STAGE_NAME}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
cd "${VERILATOR_ROOT}"
|
|
||||||
autoconf && ./configure ${VERILATOR_CONFIG_FLAGS} && make -j ${VERILATOR_NUM_JOBS}
|
|
||||||
# Copy the Verilator build artifacts
|
|
||||||
mkdir -p "${VERILATOR_CACHE}"
|
|
||||||
rm -rf ${VERILATOR_CACHE}/*
|
|
||||||
cp bin/*bin* "${VERILATOR_CACHE}"
|
|
||||||
# Remember the Git revision
|
|
||||||
echo "${VERILATOR_REV}" > "${CACHED_REV_FILE}"
|
|
||||||
else
|
|
||||||
echo "Using cached Verilator"
|
|
||||||
cd "${VERILATOR_ROOT}"
|
|
||||||
# Create include/verilated_config.h and maybe other things
|
|
||||||
autoconf && ./configure ${VERILATOR_CONFIG_FLAGS}
|
|
||||||
cp ${VERILATOR_CACHE}/* bin
|
|
||||||
fi
|
|
||||||
Executable
+29
@@ -0,0 +1,29 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# DESCRIPTION: Verilator: CI ccache maintenance
|
||||||
|
#
|
||||||
|
# Copyright 2020 by Geza Lore. This program is free software; you
|
||||||
|
# can redistribute it and/or modify it under the terms of either the GNU
|
||||||
|
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
|
# Version 2.0.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# This script is run in 'before_script', once ccache has been set up.
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
set -e
|
||||||
|
set -x
|
||||||
|
|
||||||
|
# Show version
|
||||||
|
ccache --version
|
||||||
|
|
||||||
|
# Flush ccache if requested in commit message
|
||||||
|
COMMIT="${CI_PULL_REQUEST_SHA:-$CI_COMMIT}"
|
||||||
|
if git log --format=%B -n 1 "$COMMIT" | grep -q -i '\[CI\s\+ccache\s\+clear\]'; then
|
||||||
|
echo "Flushing ccache due to commit message"
|
||||||
|
ccache -C
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Dump stats, then zero stats
|
||||||
|
ccache -s -z
|
||||||
Executable
+111
@@ -0,0 +1,111 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# DESCRIPTION: Verilator: CI dependency install script
|
||||||
|
#
|
||||||
|
# Copyright 2020 by Geza Lore. This program is free software; you
|
||||||
|
# can redistribute it and/or modify it under the terms of either the GNU
|
||||||
|
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
|
# Version 2.0.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# This script runs in the 'install' phase of all jobs, in all stages. We try to
|
||||||
|
# minimize the time spent in this by selectively installing only the components
|
||||||
|
# required by the particular build stage.
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
set -e
|
||||||
|
set -x
|
||||||
|
|
||||||
|
cd $(dirname "$0")/..
|
||||||
|
|
||||||
|
fatal() {
|
||||||
|
echo "ERROR: $(basename "$0"): $1" >&2; exit 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ "$CI_OS_NAME" = "linux" ]; then
|
||||||
|
MAKE=make
|
||||||
|
elif [ "$CI_OS_NAME" = "osx" ]; then
|
||||||
|
MAKE=make
|
||||||
|
elif [ "$CI_OS_NAME" = "freebsd" ]; then
|
||||||
|
MAKE=gmake
|
||||||
|
else
|
||||||
|
fatal "Unknown os: '$CI_OS_NAME'"
|
||||||
|
fi
|
||||||
|
|
||||||
|
install-vcddiff() {
|
||||||
|
TMP_DIR="$(mktemp -d)"
|
||||||
|
git clone https://github.com/veripool/vcddiff "$TMP_DIR"
|
||||||
|
git -C "${TMP_DIR}" checkout 5112f88b7ba8818dce9dfb72619e64a1fc19542c
|
||||||
|
"$MAKE" -C "${TMP_DIR}"
|
||||||
|
sudo cp "${TMP_DIR}/vcddiff" /usr/local/bin
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ "$CI_BUILD_STAGE_NAME" = "build" ]; then
|
||||||
|
##############################################################################
|
||||||
|
# Dependencies of jobs in the 'build' stage, i.e.: packages required to
|
||||||
|
# build Verilator
|
||||||
|
|
||||||
|
if [ "$CI_OS_NAME" = "linux" ]; then
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install libfl-dev libgoogle-perftools-dev ccache
|
||||||
|
if [ "$CI_RUNS_ON" = "ubuntu-20.04" ]; then
|
||||||
|
sudo apt-get install libsystemc libsystemc-dev
|
||||||
|
fi
|
||||||
|
if [ "$COVERAGE" = 1 ]; then
|
||||||
|
yes yes | sudo cpan -fi Parallel::Forker
|
||||||
|
fi
|
||||||
|
if [ "$M32" = 1 ]; then
|
||||||
|
sudo apt-get install gcc-multilib g++-multilib
|
||||||
|
fi
|
||||||
|
elif [ "$CI_OS_NAME" = "osx" ]; then
|
||||||
|
brew update
|
||||||
|
brew install ccache perl gperftools
|
||||||
|
elif [ "$CI_OS_NAME" = "freebsd" ]; then
|
||||||
|
sudo pkg install -y autoconf bison ccache gmake perl5
|
||||||
|
else
|
||||||
|
fatal "Unknown os: '$CI_OS_NAME'"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$CCACHE_DIR" ]; then
|
||||||
|
mkdir -p "$CCACHE_DIR" && ./ci/ci-ccache-maint.bash
|
||||||
|
fi
|
||||||
|
elif [ "$CI_BUILD_STAGE_NAME" = "test" ]; then
|
||||||
|
##############################################################################
|
||||||
|
# Dependencies of jobs in the 'test' stage, i.e.: packages required to
|
||||||
|
# run the tests
|
||||||
|
|
||||||
|
if [ "$CI_OS_NAME" = "linux" ]; then
|
||||||
|
sudo apt-get update
|
||||||
|
# libfl-dev needed for internal coverage's test runs
|
||||||
|
sudo apt-get install gdb gtkwave lcov libfl-dev ccache
|
||||||
|
if [ "$CI_RUNS_ON" = "ubuntu-20.04" ]; then
|
||||||
|
sudo apt-get install libsystemc-dev
|
||||||
|
fi
|
||||||
|
if [ "$M32" = 1 ]; then
|
||||||
|
sudo apt-get install lib32z1-dev gcc-multilib g++-multilib
|
||||||
|
fi
|
||||||
|
elif [ "$CI_OS_NAME" = "osx" ]; then
|
||||||
|
brew update
|
||||||
|
# brew cask install gtkwave # fst2vcd hangs at launch, so don't bother
|
||||||
|
brew install ccache perl
|
||||||
|
elif [ "$CI_OS_NAME" = "freebsd" ]; then
|
||||||
|
# fst2vcd fails with "Could not open '<input file>', exiting."
|
||||||
|
sudo pkg install -y ccache gmake perl5 python3
|
||||||
|
else
|
||||||
|
fatal "Unknown os: '$CI_OS_NAME'"
|
||||||
|
fi
|
||||||
|
# Common installs
|
||||||
|
if [ "$CI_RUNS_ON" != "ubuntu-14.04" ]; then
|
||||||
|
CI_CPAN_REPO=https://cpan.org
|
||||||
|
fi
|
||||||
|
yes yes | sudo cpan -M $CI_CPAN_REPO -fi Parallel::Forker
|
||||||
|
install-vcddiff
|
||||||
|
|
||||||
|
autoconf
|
||||||
|
./configure --enable-longtests --enable-ccwarn
|
||||||
|
else
|
||||||
|
##############################################################################
|
||||||
|
# Unknown build stage
|
||||||
|
fatal "Unknown build stage: '$CI_BUILD_STAGE_NAME'"
|
||||||
|
fi
|
||||||
Executable
+141
@@ -0,0 +1,141 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# DESCRIPTION: Verilator: CI main job script
|
||||||
|
#
|
||||||
|
# Copyright 2020 by Geza Lore. This program is free software; you
|
||||||
|
# can redistribute it and/or modify it under the terms of either the GNU
|
||||||
|
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
|
# Version 2.0.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# This is the main script executed in the 'script' phase by all jobs. We use a
|
||||||
|
# single script to keep the CI setting simple. We pass job parameters via
|
||||||
|
# environment variables using 'env' keys.
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
set -e
|
||||||
|
set -x
|
||||||
|
|
||||||
|
fatal() {
|
||||||
|
echo "ERROR: $(basename "$0"): $1" >&2; exit 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ "$CI_OS_NAME" = "linux" ]; then
|
||||||
|
export MAKE=make
|
||||||
|
NPROC=$(nproc)
|
||||||
|
elif [ "$CI_OS_NAME" = "osx" ]; then
|
||||||
|
export MAKE=make
|
||||||
|
NPROC=$(sysctl -n hw.logicalcpu)
|
||||||
|
elif [ "$CI_OS_NAME" = "freebsd" ]; then
|
||||||
|
export MAKE=gmake
|
||||||
|
NPROC=$(sysctl -n hw.ncpu)
|
||||||
|
else
|
||||||
|
fatal "Unknown os: '$CI_OS_NAME'"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$CI_BUILD_STAGE_NAME" = "build" ]; then
|
||||||
|
##############################################################################
|
||||||
|
# Build verilator
|
||||||
|
|
||||||
|
if [ "$COVERAGE" != 1 ]; then
|
||||||
|
autoconf
|
||||||
|
./configure --enable-longtests --enable-ccwarn
|
||||||
|
"$MAKE" -j "$NPROC" -k
|
||||||
|
if [ "$CI_OS_NAME" = "osx" ]; then
|
||||||
|
file bin/verilator_bin
|
||||||
|
file bin/verilator_bin_dbg
|
||||||
|
md5 bin/verilator_bin
|
||||||
|
md5 bin/verilator_bin_dbg
|
||||||
|
stat bin/verilator_bin
|
||||||
|
stat bin/verilator_bin_dbg
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
nodist/code_coverage --stages 1-2
|
||||||
|
fi
|
||||||
|
elif [ "$CI_BUILD_STAGE_NAME" = "test" ]; then
|
||||||
|
##############################################################################
|
||||||
|
# Run tests
|
||||||
|
|
||||||
|
export VERILATOR_TEST_NO_CONTRIBUTORS=1 # Separate workflow check
|
||||||
|
|
||||||
|
if [ "$CI_OS_NAME" = "osx" ]; then
|
||||||
|
export VERILATOR_TEST_NO_GDB=1 # Pain to get GDB to work on OS X
|
||||||
|
export VERILATOR_TEST_NO_GPROF=1 # Apple Clang has no -pg
|
||||||
|
# export PATH="/Applications/gtkwave.app/Contents/Resources/bin:$PATH" # fst2vcd
|
||||||
|
file bin/verilator_bin
|
||||||
|
file bin/verilator_bin_dbg
|
||||||
|
md5 bin/verilator_bin
|
||||||
|
md5 bin/verilator_bin_dbg
|
||||||
|
stat bin/verilator_bin
|
||||||
|
stat bin/verilator_bin_dbg
|
||||||
|
# For some reason, the dbg exe is corrupted by this point ('file' reports
|
||||||
|
# it as data rather than a Mach-O). Unclear if this is an OS X issue or
|
||||||
|
# CI's. Remove the file and re-link...
|
||||||
|
rm bin/verilator_bin_dbg
|
||||||
|
"$MAKE" -j "$NPROC" -k
|
||||||
|
elif [ "$CI_OS_NAME" = "freebsd" ]; then
|
||||||
|
export VERILATOR_TEST_NO_GDB=1 # Disable for now, ideally should run
|
||||||
|
export VERILATOR_TEST_NO_GPROF=1 # gprof is a bit different on FreeBSD, disable
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Run sanitize on Ubuntu 20.04 only
|
||||||
|
[ "$CI_RUNS_ON" = 'ubuntu-20.04' ] && sanitize='--sanitize' || sanitize=''
|
||||||
|
|
||||||
|
# Run the specified test
|
||||||
|
case $TESTS in
|
||||||
|
dist-vlt-0)
|
||||||
|
"$MAKE" -C test_regress SCENARIOS="--dist --vlt $sanitize" DRIVER_HASHSET=--hashset=0/2
|
||||||
|
;;
|
||||||
|
dist-vlt-1)
|
||||||
|
"$MAKE" -C test_regress SCENARIOS="--dist --vlt $sanitize" DRIVER_HASHSET=--hashset=1/2
|
||||||
|
;;
|
||||||
|
vltmt-0)
|
||||||
|
"$MAKE" -C test_regress SCENARIOS=--vltmt DRIVER_HASHSET=--hashset=0/2
|
||||||
|
;;
|
||||||
|
vltmt-1)
|
||||||
|
"$MAKE" -C test_regress SCENARIOS=--vltmt DRIVER_HASHSET=--hashset=1/2
|
||||||
|
;;
|
||||||
|
coverage-all)
|
||||||
|
nodist/code_coverage --stages 3-
|
||||||
|
;;
|
||||||
|
coverage-dist)
|
||||||
|
nodist/code_coverage --stages 3- --scenarios=--dist
|
||||||
|
;;
|
||||||
|
coverage-vlt-0)
|
||||||
|
nodist/code_coverage --stages 3- --scenarios=--vlt --hashset=0/4
|
||||||
|
;;
|
||||||
|
coverage-vlt-1)
|
||||||
|
nodist/code_coverage --stages 3- --scenarios=--vlt --hashset=1/4
|
||||||
|
;;
|
||||||
|
coverage-vlt-2)
|
||||||
|
nodist/code_coverage --stages 3- --scenarios=--vlt --hashset=2/4
|
||||||
|
;;
|
||||||
|
coverage-vlt-3)
|
||||||
|
nodist/code_coverage --stages 3- --scenarios=--vlt --hashset=3/4
|
||||||
|
;;
|
||||||
|
coverage-vltmt-0)
|
||||||
|
nodist/code_coverage --stages 3- --scenarios=--vltmt --hashset=0/4
|
||||||
|
;;
|
||||||
|
coverage-vltmt-1)
|
||||||
|
nodist/code_coverage --stages 3- --scenarios=--vltmt --hashset=1/4
|
||||||
|
;;
|
||||||
|
coverage-vltmt-2)
|
||||||
|
nodist/code_coverage --stages 3- --scenarios=--vltmt --hashset=2/4
|
||||||
|
;;
|
||||||
|
coverage-vltmt-3)
|
||||||
|
nodist/code_coverage --stages 3- --scenarios=--vltmt --hashset=3/4
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
fatal "Unknown test: $TESTS"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
# Upload coverage data to codecov.io
|
||||||
|
if [[ $TESTS == coverage-* ]]; then
|
||||||
|
bash <(curl -s https://codecov.io/bash) -f nodist/obj_dir/coverage/app_total.info
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
##############################################################################
|
||||||
|
# Unknown build stage
|
||||||
|
fatal "Unknown build stage: '$CI_BUILD_STAGE_NAME'"
|
||||||
|
fi
|
||||||
@@ -6,45 +6,41 @@
|
|||||||
# Version 2.0.
|
# Version 2.0.
|
||||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||||
|
|
||||||
FROM ubuntu:18.04
|
FROM ubuntu:20.04
|
||||||
|
|
||||||
RUN apt-get update \
|
RUN apt-get update \
|
||||||
&& DEBIAN_FRONTEND=noninteractive \
|
&& DEBIAN_FRONTEND=noninteractive \
|
||||||
apt-get install --no-install-recommends -y \
|
apt-get install --no-install-recommends -y \
|
||||||
autoconf=2.69-11 \
|
autoconf \
|
||||||
bc=1.07.1-2 \
|
bc \
|
||||||
bison=2:3.0.4.dfsg-1build1 \
|
bison \
|
||||||
build-essential=12.4ubuntu1 \
|
build-essential \
|
||||||
ca-certificates=20180409 \
|
ca-certificates \
|
||||||
cmake=3.10.2-1ubuntu2.18.04.1 \
|
ccache \
|
||||||
flex=2.6.4-6 \
|
clang \
|
||||||
gdb=8.1-0ubuntu3.2 \
|
cmake \
|
||||||
gcc-6=6.5.0-2ubuntu1~18.04 \
|
flex \
|
||||||
gcc-5=5.5.0-12ubuntu1 \
|
gdb \
|
||||||
gcc-4.8=4.8.5-4ubuntu8 \
|
git \
|
||||||
git=1:2.17.1-1ubuntu0.5 \
|
gtkwave \
|
||||||
gtkwave=3.3.86-1 \
|
libfl2 \
|
||||||
g++-6=6.5.0-2ubuntu1~18.04 \
|
libfl-dev \
|
||||||
g++-5=5.5.0-12ubuntu1 \
|
libgoogle-perftools-dev \
|
||||||
g++-4.8=4.8.5-4ubuntu8 \
|
libsystemc \
|
||||||
libfl2=2.6.4-6 \
|
libsystemc-dev \
|
||||||
libfl-dev=2.6.4-6 \
|
numactl \
|
||||||
numactl=2.0.11-2.1ubuntu0.1 \
|
perl \
|
||||||
perl=5.26.1-6ubuntu0.3 \
|
python3 \
|
||||||
python3=3.6.7-1~18.04 \
|
wget \
|
||||||
wget=1.19.4-1ubuntu2.2 \
|
zlibc \
|
||||||
zlibc=0.9k-4.3 \
|
zlib1g \
|
||||||
zlib1g=1:1.2.11.dfsg-0ubuntu2 \
|
zlib1g-dev \
|
||||||
zlib1g-dev=1:1.2.11.dfsg-0ubuntu2 \
|
|
||||||
&& apt-get clean \
|
&& apt-get clean \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
WORKDIR /tmp
|
WORKDIR /tmp
|
||||||
|
|
||||||
COPY build-systemc.sh /tmp/
|
RUN cpan install -fi Parallel::Forker
|
||||||
RUN ./build-systemc.sh
|
|
||||||
|
|
||||||
RUN cpan install -fi Unix::Processors Parallel::Forker Bit::Vector
|
|
||||||
|
|
||||||
RUN git clone https://github.com/veripool/vcddiff.git && \
|
RUN git clone https://github.com/veripool/vcddiff.git && \
|
||||||
make -C vcddiff && \
|
make -C vcddiff && \
|
||||||
@@ -55,4 +51,6 @@ COPY build.sh /tmp/build.sh
|
|||||||
|
|
||||||
ENV VERILATOR_AUTHOR_SITE=1
|
ENV VERILATOR_AUTHOR_SITE=1
|
||||||
|
|
||||||
|
WORKDIR /work
|
||||||
|
|
||||||
ENTRYPOINT [ "/tmp/build.sh" ]
|
ENTRYPOINT [ "/tmp/build.sh" ]
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ build. It uses the following parameters:
|
|||||||
|
|
||||||
* Source repository (default: https://github.com/verilator/verilator)
|
* Source repository (default: https://github.com/verilator/verilator)
|
||||||
* Source revision (default: master)
|
* Source revision (default: master)
|
||||||
* GCC version (4.8.5, 5.5.0, 6.5.0, 7.4.0, default: 7.4.0)
|
* Compiler (GCC 9.3.0, clang 10.0.0, default: 9.3.0)
|
||||||
|
|
||||||
The container is published as `verilator/verilator-buildenv` on
|
The container is published as `verilator/verilator-buildenv` on
|
||||||
https://hub.docker.com/repository/docker/verilator/verilator-buildenv[docker hub].
|
https://hub.docker.com/repository/docker/verilator/verilator-buildenv[docker hub].
|
||||||
@@ -20,13 +20,13 @@ To also run tests:
|
|||||||
|
|
||||||
To change the compiler:
|
To change the compiler:
|
||||||
|
|
||||||
docker run -ti -e CC=gcc-4.8 -e CXX=g++-4.8 verilator/verilator-buildenv test
|
docker run -ti -e CC=clang-10 -e CXX=clang++-10 verilator/verilator-buildenv test
|
||||||
|
|
||||||
The tests that involve gdb are not working due to security restrictions.
|
The tests that involve gdb are not working due to security restrictions.
|
||||||
To run those too:
|
To run those too:
|
||||||
|
|
||||||
....
|
....
|
||||||
docker run -ti -v ${PWD}:/tmp/repo -e REPO=/tmp/repo -e REV=`git rev-parse --short HEAD` -e CC=gcc-4.8 -e CXX=g++-4.8 --cap-add=SYS_PTRACE --security-opt seccomp=unconfined verilator/verilator-buildenv test
|
docker run -ti -e CC=clang-10 -e CXX=clang++-10 --cap-add=SYS_PTRACE --security-opt seccomp=unconfined verilator/verilator-buildenv test
|
||||||
....
|
....
|
||||||
|
|
||||||
Rather then building using a remote git repository you may prefer to use a
|
Rather then building using a remote git repository you may prefer to use a
|
||||||
|
|||||||
@@ -1,30 +0,0 @@
|
|||||||
#!/bin/bash -e
|
|
||||||
# DESCRIPTION: Build SystemC in Ubuntu 18.04 with different g++/gcc
|
|
||||||
#
|
|
||||||
# Copyright 2020 by Stefan Wallentowitz. This program is free software; you
|
|
||||||
# can redistribute it and/or modify it under the terms of either the GNU
|
|
||||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
|
||||||
# Version 2.0.
|
|
||||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
|
||||||
|
|
||||||
build_variant () {
|
|
||||||
version=$($1 --version | grep gcc | awk '{print $4}')
|
|
||||||
mkdir "/usr/local/systemc-2.3.3-gcc$version"
|
|
||||||
mkdir build
|
|
||||||
cd build
|
|
||||||
../configure --prefix="/usr/local/systemc-2.3.3-gcc$version" CC="$1" CXX="$2" LD="$2"
|
|
||||||
make -j
|
|
||||||
make install
|
|
||||||
cd ..
|
|
||||||
rm -r build
|
|
||||||
}
|
|
||||||
|
|
||||||
wget https://www.accellera.org/images/downloads/standards/systemc/systemc-2.3.3.tar.gz
|
|
||||||
tar -xzf systemc-2.3.3.tar.gz
|
|
||||||
cd systemc-2.3.3
|
|
||||||
build_variant gcc g++
|
|
||||||
build_variant gcc-6 g++-6
|
|
||||||
build_variant gcc-5 g++-5
|
|
||||||
build_variant gcc-4.8 g++-4.8
|
|
||||||
cd ..
|
|
||||||
rm -r systemc-2.3.3*
|
|
||||||
@@ -12,12 +12,6 @@
|
|||||||
: "${CC:=gcc}"
|
: "${CC:=gcc}"
|
||||||
: "${CXX:=g++}"
|
: "${CXX:=g++}"
|
||||||
|
|
||||||
GCCVERSION=$(${CC} --version | grep gcc | awk '{print $4}')
|
|
||||||
|
|
||||||
export SYSTEMC_INCLUDE="/usr/local/systemc-2.3.3-gcc${GCCVERSION}/include"
|
|
||||||
export SYSTEMC_LIBDIR="/usr/local/systemc-2.3.3-gcc${GCCVERSION}/lib-linux64"
|
|
||||||
export LD_LIBRARY_PATH=${SYSTEMC_LIBDIR}
|
|
||||||
|
|
||||||
SRCS=$PWD/verilator
|
SRCS=$PWD/verilator
|
||||||
|
|
||||||
git clone "$REPO" "$SRCS"
|
git clone "$REPO" "$SRCS"
|
||||||
|
|||||||
@@ -6,19 +6,20 @@
|
|||||||
# Version 2.0.
|
# Version 2.0.
|
||||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||||
|
|
||||||
FROM ubuntu:18.04
|
FROM ubuntu:20.04
|
||||||
|
|
||||||
RUN apt-get update \
|
RUN apt-get update \
|
||||||
|
&& DEBIAN_FRONTEND=noninteractive \
|
||||||
&& apt-get install --no-install-recommends -y \
|
&& apt-get install --no-install-recommends -y \
|
||||||
autoconf=2.69-11 \
|
autoconf \
|
||||||
bc=1.07.1-2 \
|
bc \
|
||||||
bison=2:3.0.4.dfsg-1build1 \
|
bison \
|
||||||
build-essential=12.4ubuntu1 \
|
build-essential \
|
||||||
ca-certificates=20180409 \
|
ca-certificates \
|
||||||
ccache \
|
ccache \
|
||||||
flex=2.6.4-6 \
|
flex \
|
||||||
git \
|
git \
|
||||||
libfl-dev=2.6.4-6 \
|
libfl-dev \
|
||||||
libgoogle-perftools-dev \
|
libgoogle-perftools-dev \
|
||||||
perl \
|
perl \
|
||||||
python3 \
|
python3 \
|
||||||
|
|||||||
@@ -27,5 +27,5 @@ if [ -e ${obj_dir} ]; then
|
|||||||
cp -r /usr/local/share/verilator/bin ${obj_dir}/vlt
|
cp -r /usr/local/share/verilator/bin ${obj_dir}/vlt
|
||||||
cp -r /usr/local/share/verilator/include ${obj_dir}/vlt
|
cp -r /usr/local/share/verilator/include ${obj_dir}/vlt
|
||||||
# Point Makefile to that folder
|
# Point Makefile to that folder
|
||||||
perl -i -pe 's/VERILATOR_ROOT = \/usr\/local\/share\/verilator/VERILATOR_ROOT = vlt/g' ${obj_dir}/*.mk
|
sed -i 's/VERILATOR_ROOT = \/usr\/local\/share\/verilator/VERILATOR_ROOT = vlt/g' ${obj_dir}/*.mk
|
||||||
fi
|
fi
|
||||||
|
|||||||
-34
@@ -1,34 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
# DESCRIPTION: Verilator: Travis CI test script
|
|
||||||
#
|
|
||||||
# Copyright 2019 by Todd Strader. This program is free software; you
|
|
||||||
# can redistribute it and/or modify it under the terms of either the GNU
|
|
||||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
|
||||||
# Version 2.0.
|
|
||||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
export DRIVER_FLAGS='-j 0 --quiet --rerun'
|
|
||||||
|
|
||||||
case $1 in
|
|
||||||
dist)
|
|
||||||
make -C test_regress SCENARIOS=--dist
|
|
||||||
;;
|
|
||||||
vlt)
|
|
||||||
make -C test_regress SCENARIOS=--vlt
|
|
||||||
;;
|
|
||||||
vltmt)
|
|
||||||
make -C test_regress SCENARIOS=--vltmt
|
|
||||||
;;
|
|
||||||
vltmt0)
|
|
||||||
make -C test_regress SCENARIOS=--vltmt DRIVER_HASHSET=--hashset=0/2
|
|
||||||
;;
|
|
||||||
vltmt1)
|
|
||||||
make -C test_regress SCENARIOS=--vltmt DRIVER_HASHSET=--hashset=1/2
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "Usage: test.sh (dist|vlt|vltmt)"
|
|
||||||
exit -1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
+38
@@ -0,0 +1,38 @@
|
|||||||
|
# DESCRIPTION: codecov.io config
|
||||||
|
#
|
||||||
|
# Copyright 2020-2021 by Wilson Snyder. This program is free software; you
|
||||||
|
# can redistribute it and/or modify it under the terms of either the GNU
|
||||||
|
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
|
# Version 2.0.
|
||||||
|
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||||
|
####################
|
||||||
|
# Validate:
|
||||||
|
# curl --data-binary @codecov.yml https://codecov.io/validate
|
||||||
|
|
||||||
|
codecov:
|
||||||
|
require_ci_to_pass: no
|
||||||
|
|
||||||
|
coverage:
|
||||||
|
precision: 2
|
||||||
|
round: down
|
||||||
|
range: "50...100"
|
||||||
|
ignore:
|
||||||
|
- "ci"
|
||||||
|
- "docs"
|
||||||
|
- "examples"
|
||||||
|
- "include/gtkwave"
|
||||||
|
- "include/vltstd"
|
||||||
|
- "test_regress"
|
||||||
|
|
||||||
|
parsers:
|
||||||
|
gcov:
|
||||||
|
branch_detection:
|
||||||
|
conditional: yes
|
||||||
|
loop: yes
|
||||||
|
method: no
|
||||||
|
macro: no
|
||||||
|
|
||||||
|
comment:
|
||||||
|
layout: "reach,diff,flags,tree"
|
||||||
|
behavior: default
|
||||||
|
require_changes: yes
|
||||||
+66
-44
@@ -1,22 +1,26 @@
|
|||||||
# DESCRIPTION: Process this file with autoconf to produce a configure script.
|
# DESCRIPTION: Process this file with autoconf to produce a configure script.
|
||||||
#
|
#
|
||||||
# Copyright 2003-2020 by Wilson Snyder. Verilator is free software; you
|
# Copyright 2003-2021 by Wilson Snyder. Verilator is free software; you
|
||||||
# can redistribute it and/or modify it under the terms of either the GNU Lesser
|
# can redistribute it and/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.
|
||||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||||
|
|
||||||
#AC_INIT([Verilator],[#.### YYYY-MM-DD])
|
#AC_INIT([Verilator],[#.### YYYY-MM-DD])
|
||||||
#AC_INIT([Verilator],[#.### devel])
|
#AC_INIT([Verilator],[#.### devel])
|
||||||
AC_INIT([Verilator],[4.034 2020-05-03],
|
AC_INIT([Verilator],[4.108 2021-01-10],
|
||||||
[https://verilator.org],
|
[https://verilator.org],
|
||||||
[verilator],[https://verilator.org])
|
[verilator],[https://verilator.org])
|
||||||
# When releasing, also update header of Changes file
|
# When releasing, also update header of Changes file
|
||||||
# and commit using "devel release" or "Version bump" message
|
# and commit using "devel release" or "Version bump" message
|
||||||
|
# Then 'make maintainer-dist'
|
||||||
|
|
||||||
AC_CONFIG_HEADER(src/config_build.h)
|
AC_CONFIG_HEADER(src/config_build.h)
|
||||||
AC_CONFIG_FILES(Makefile docs/Makefile src/Makefile src/Makefile_obj include/verilated.mk include/verilated_config.h verilator.pc verilator-config.cmake verilator-config-version.cmake)
|
AC_CONFIG_FILES(Makefile docs/Makefile src/Makefile src/Makefile_obj include/verilated.mk include/verilated_config.h verilator.pc verilator-config.cmake verilator-config-version.cmake)
|
||||||
|
|
||||||
|
# Version
|
||||||
AC_MSG_RESULT([configuring for $PACKAGE_STRING])
|
AC_MSG_RESULT([configuring for $PACKAGE_STRING])
|
||||||
|
PACKAGE_VERSION_NUMBER=`AS_ECHO("$PACKAGE_VERSION") | sed 's/ .*//g'`
|
||||||
|
AC_SUBST(PACKAGE_VERSION_NUMBER)
|
||||||
|
|
||||||
# Ignore automake flags passed by Ubuntu builds
|
# Ignore automake flags passed by Ubuntu builds
|
||||||
AC_ARG_ENABLE([dependency-tracking],
|
AC_ARG_ENABLE([dependency-tracking],
|
||||||
@@ -109,27 +113,11 @@ AC_ARG_ENABLE([longtests],
|
|||||||
AC_SUBST(CFG_WITH_LONGTESTS)
|
AC_SUBST(CFG_WITH_LONGTESTS)
|
||||||
AC_MSG_RESULT($CFG_WITH_LONGTESTS)
|
AC_MSG_RESULT($CFG_WITH_LONGTESTS)
|
||||||
|
|
||||||
# CFG_WITH_PREC11
|
# Compiler flags (ensure they are not empty to avoid configure defaults)
|
||||||
AC_MSG_CHECKING(whether allow pre-C++11)
|
CFLAGS+=" "
|
||||||
AC_ARG_ENABLE([prec11],
|
CPPFLAGS+=" "
|
||||||
[AS_HELP_STRING([--enable-prec11],
|
CXXFLAGS+=" "
|
||||||
[enable pre-C++11 compilers for Verilator binary
|
LDFLAGS+=" "
|
||||||
and Verilated makefiles])],
|
|
||||||
[case "${enableval}" in
|
|
||||||
yes) CFG_WITH_PREC11=yes ;;
|
|
||||||
no) CFG_WITH_PREC11=no ;;
|
|
||||||
*) AC_MSG_ERROR([bad value ${enableval} for --enable-prec11]) ;;
|
|
||||||
esac],
|
|
||||||
[CFG_WITH_PREC11=no;]
|
|
||||||
)
|
|
||||||
AC_SUBST(CFG_WITH_PREC11)
|
|
||||||
AC_MSG_RESULT($CFG_WITH_PREC11)
|
|
||||||
|
|
||||||
# Compiler flags
|
|
||||||
CFLAGS+=" -I${includedir}"
|
|
||||||
CPPFLAGS+=" -I${includedir}"
|
|
||||||
CXXFLAGS+=" -I${includedir}"
|
|
||||||
LDFLAGS+=" -L${libdir}"
|
|
||||||
|
|
||||||
# Checks for programs.
|
# Checks for programs.
|
||||||
AC_PROG_CC
|
AC_PROG_CC
|
||||||
@@ -150,14 +138,25 @@ AC_PATH_PROG(PERL,perl)
|
|||||||
if test "x$PERL" = "x" ; then
|
if test "x$PERL" = "x" ; then
|
||||||
AC_MSG_ERROR([Cannot find "perl" in your PATH, please install it])
|
AC_MSG_ERROR([Cannot find "perl" in your PATH, please install it])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
AC_PATH_PROG(PYTHON3,python3)
|
||||||
|
if test "x$PYTHON3" = "x" ; then
|
||||||
|
AC_MSG_ERROR([Cannot find "python3" in your PATH, please install it])
|
||||||
|
fi
|
||||||
|
|
||||||
AC_PATH_PROG(LEX,flex)
|
AC_PATH_PROG(LEX,flex)
|
||||||
if test "x$LEX" = "x" ; then
|
if test "x$LEX" = "x" ; then
|
||||||
AC_MSG_ERROR([Cannot find "flex" in your PATH, please install it])
|
AC_MSG_ERROR([Cannot find "flex" in your PATH, please install it])
|
||||||
fi
|
fi
|
||||||
|
flex_version=$($LEX --version | head -1)
|
||||||
|
AC_MSG_RESULT([$LEX --version = $flex_version])
|
||||||
|
|
||||||
AC_PATH_PROG(YACC,bison)
|
AC_PATH_PROG(YACC,bison)
|
||||||
if test "x$YACC" = "x" ; then
|
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
|
||||||
|
bison_version=$($YACC --version | head -1)
|
||||||
|
AC_MSG_RESULT([$YACC --version = $bison_version])
|
||||||
|
|
||||||
AC_CHECK_PROG(OBJCACHE,ccache,ccache)
|
AC_CHECK_PROG(OBJCACHE,ccache,ccache)
|
||||||
if test "x$OBJCACHE" != "x" ; then
|
if test "x$OBJCACHE" != "x" ; then
|
||||||
@@ -400,12 +399,17 @@ _MY_LDLIBS_CHECK_IFELSE(
|
|||||||
fi])
|
fi])
|
||||||
AC_SUBST(CFG_LIBS)
|
AC_SUBST(CFG_LIBS)
|
||||||
|
|
||||||
# Set CFG_WITH_THREADED if can support threading
|
# Need C++11 at least
|
||||||
AC_MSG_CHECKING(whether $CXX supports Verilated threads)
|
#Alternative: AX_CXX_COMPILE_STDCXX([11])
|
||||||
ACO_SAVE_CXXFLAGS="$CXXFLAGS"
|
AC_DEFUN([_MY_CXX_CHECK_CXX_VER],
|
||||||
CXXFLAGS="$CXXFLAGS $CFG_CXXFLAGS_STD_NEWEST $CFG_CXXFLAGS_NO_UNUSED"
|
[# _MY_CXX_CHECK_CXX_VER(flag) -- Check if compiler runs C++11
|
||||||
AC_LINK_IFELSE(
|
# Set $_my_result
|
||||||
[AC_LANG_PROGRAM([#include <thread>], [[ ]])],
|
AC_LINK_IFELSE(
|
||||||
|
[AC_LANG_PROGRAM([#include <thread>
|
||||||
|
#if (__cplusplus < 201103L)
|
||||||
|
# error "Too old"
|
||||||
|
#endif
|
||||||
|
], [[ ]])],
|
||||||
[_my_result=yes
|
[_my_result=yes
|
||||||
if test -s conftest.err; then
|
if test -s conftest.err; then
|
||||||
if grep -e "$1" conftest.err >/dev/null; then
|
if grep -e "$1" conftest.err >/dev/null; then
|
||||||
@@ -413,24 +417,24 @@ AC_LINK_IFELSE(
|
|||||||
fi
|
fi
|
||||||
fi],
|
fi],
|
||||||
[_my_result=no])
|
[_my_result=no])
|
||||||
CFG_WITH_THREADED=$_my_result
|
])
|
||||||
AC_SUBST(CFG_WITH_THREADED)
|
|
||||||
AC_MSG_RESULT($CFG_WITH_THREADED)
|
|
||||||
|
|
||||||
# Check compiler flag
|
AC_MSG_CHECKING(whether $CXX supports C++11)
|
||||||
if test "$CFG_WITH_THREADED" = "no" ; then
|
_MY_CXX_CHECK_CXX_VER()
|
||||||
if test "$CFG_WITH_PREC11" = "no" ; then
|
AC_MSG_RESULT($_my_result)
|
||||||
AC_MSG_NOTICE([[]])
|
if test "$_my_result" = "no" ; then
|
||||||
AC_MSG_ERROR([[the $CXX compiler appears to not support C++11.
|
CXXFLAGS="$CXXFLAGS $CFG_CXXFLAGS_STD_NEWEST"
|
||||||
|
CFG_CXX_FLAGS_CMAKE="$CFG_CXX_FLAGS_CMAKE $CFG_CXXFLAGS_STD_NEWEST"
|
||||||
|
AC_MSG_CHECKING(whether $CXX supports C++11 with $CFG_CXXFLAGS_STD_NEWEST)
|
||||||
|
_MY_CXX_CHECK_CXX_VER()
|
||||||
|
AC_MSG_RESULT($_my_result)
|
||||||
|
fi
|
||||||
|
if test "$_my_result" = "no" ; then
|
||||||
|
AC_MSG_NOTICE([[]])
|
||||||
|
AC_MSG_ERROR([[the $CXX compiler appears to not support C++11.
|
||||||
|
|
||||||
Verilator plans to require a C++11 or newer compiler in a future release,
|
Verilator requires a C++11 or newer compiler.]])
|
||||||
unless sufficient people report problems. Therefore, if you do not have a
|
|
||||||
C++11 compiler, please post a message to
|
|
||||||
https://www.veripool.org/boards/3/topics/2580-Verilator-Requiring-C-11-compiler
|
|
||||||
indicating your OS and when you think C++11 might be ok, and then rerun
|
|
||||||
configure with the --enable-prec11 argument. Thanks.]])
|
|
||||||
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Checks for library functions.
|
# Checks for library functions.
|
||||||
@@ -438,6 +442,24 @@ AC_CHECK_MEMBER([struct stat.st_mtim.tv_nsec],
|
|||||||
[AC_DEFINE([HAVE_STAT_NSEC],[1],[Defined if struct stat has st_mtim.tv_nsec])],
|
[AC_DEFINE([HAVE_STAT_NSEC],[1],[Defined if struct stat has st_mtim.tv_nsec])],
|
||||||
[], [#include <sys/stat.h>])
|
[], [#include <sys/stat.h>])
|
||||||
|
|
||||||
|
# HAVE_SYSTEMC
|
||||||
|
# - If found the default search path has it, so support is always enabled.
|
||||||
|
# - If not found or not system-wide, user can set SYSTEMC_INCLUDE.
|
||||||
|
# AC_CHECK_HEADERS seems to not locate on Travis-CI but include does work.
|
||||||
|
AC_MSG_CHECKING([whether SystemC is found (in system path)])
|
||||||
|
ACO_SAVE_LIBS="$LIBS"
|
||||||
|
LIBS="$LIBS -lsystemc"
|
||||||
|
AC_LINK_IFELSE(
|
||||||
|
[AC_LANG_PROGRAM([[#include <systemc.h>
|
||||||
|
extern "C" int sc_main(int argc, char* argv[]) {}
|
||||||
|
]],[[sc_version()]])],
|
||||||
|
[_my_result=yes
|
||||||
|
AC_DEFINE([HAVE_SYSTEMC],[1],[Defined if have SystemC library])],
|
||||||
|
[_my_result=no])
|
||||||
|
AC_MSG_RESULT($_my_result)
|
||||||
|
LIBS="$ACO_SAVE_LIBS"
|
||||||
|
AC_SUBST(HAVE_SYSTEMC)
|
||||||
|
|
||||||
# Checks for system services
|
# Checks for system services
|
||||||
|
|
||||||
# Other install directories
|
# Other install directories
|
||||||
|
|||||||
@@ -27,8 +27,8 @@ contributions flow more efficiently.
|
|||||||
* You may attach a patch to the issue, or (preferred) may request a GitHub
|
* You may attach a patch to the issue, or (preferred) may request a GitHub
|
||||||
pull request.
|
pull request.
|
||||||
|
|
||||||
** Verilator uses Travis CI to provide continuous integration. You may
|
** Verilator uses GitHub Actions to provide continuous integration. You may
|
||||||
want to setup Travis CI on your GitHub branch to ensure your changes
|
want to enable Actions on your GitHub branch to ensure your changes
|
||||||
keep the tests passing. See link:internals.adoc[docs/internals].
|
keep the tests passing. See link:internals.adoc[docs/internals].
|
||||||
|
|
||||||
* Your source-code contributions must be certified as open source, under
|
* Your source-code contributions must be certified as open source, under
|
||||||
|
|||||||
@@ -6,44 +6,81 @@ Please see the Verilator manual for 200+ additional contributors. Thanks to all.
|
|||||||
Ahmed El-Mahmoudy
|
Ahmed El-Mahmoudy
|
||||||
Alex Chadwick
|
Alex Chadwick
|
||||||
Chris Randall
|
Chris Randall
|
||||||
|
Conor McCullough
|
||||||
|
Dan Petrisko
|
||||||
|
David Horton
|
||||||
David Stanford
|
David Stanford
|
||||||
Driss Hafdi
|
Driss Hafdi
|
||||||
|
Edgar E. Iglesias
|
||||||
Eric Rippey
|
Eric Rippey
|
||||||
|
Fan Shupei
|
||||||
Garrett Smith
|
Garrett Smith
|
||||||
Geza Lore
|
Geza Lore
|
||||||
Gianfranco Costamagna
|
Gianfranco Costamagna
|
||||||
|
Glen Gibb
|
||||||
|
Harald Heckmann
|
||||||
Howard Su
|
Howard Su
|
||||||
|
Huang Rui
|
||||||
Iztok Jeras
|
Iztok Jeras
|
||||||
James Hanlon
|
James Hanlon
|
||||||
|
James Hutchinson
|
||||||
|
Jamey Hicks
|
||||||
|
James Pallister
|
||||||
|
Jan Van Winkel
|
||||||
|
Jean Berniolles
|
||||||
Jeremy Bennett
|
Jeremy Bennett
|
||||||
John Coiner
|
John Coiner
|
||||||
John Demme
|
John Demme
|
||||||
|
Josh Redford
|
||||||
Julien Margetts
|
Julien Margetts
|
||||||
|
Kaleb Barrett
|
||||||
Kanad Kanhere
|
Kanad Kanhere
|
||||||
Kevin Kiningham
|
Kevin Kiningham
|
||||||
|
Krzysztof Bieganski
|
||||||
Kuba Ober
|
Kuba Ober
|
||||||
|
Ludwig Rogiers
|
||||||
Lukasz Dalek
|
Lukasz Dalek
|
||||||
Maarten De Braekeleer
|
Maarten De Braekeleer
|
||||||
Maciej Sobkowski
|
Maciej Sobkowski
|
||||||
Marco Widmer
|
Marco Widmer
|
||||||
|
Markus Krause
|
||||||
|
Marlon James
|
||||||
|
Marshal Qiao
|
||||||
Matthew Ballance
|
Matthew Ballance
|
||||||
|
Michael Killough
|
||||||
Mike Popoloski
|
Mike Popoloski
|
||||||
|
Nandu Raj
|
||||||
Nathan Kohagen
|
Nathan Kohagen
|
||||||
Nathan Myers
|
Nathan Myers
|
||||||
Patrick Stewart
|
Patrick Stewart
|
||||||
|
Paul Wright
|
||||||
Peter Horvath
|
Peter Horvath
|
||||||
Peter Monsson
|
Peter Monsson
|
||||||
Philipp Wagner
|
Philipp Wagner
|
||||||
Pieter Kapsenberg
|
Pieter Kapsenberg
|
||||||
|
Piotr Binkowski
|
||||||
Qingyao Sun
|
Qingyao Sun
|
||||||
|
Rafal Kapuscik
|
||||||
Richard Myers
|
Richard Myers
|
||||||
|
Rupert Swarbrick
|
||||||
Sean Cross
|
Sean Cross
|
||||||
Sebastien Van Cauwenberghe
|
Sebastien Van Cauwenberghe
|
||||||
|
Sergi Granell
|
||||||
Stefan Wallentowitz
|
Stefan Wallentowitz
|
||||||
|
Stephen Henry
|
||||||
|
Tim Snyder
|
||||||
Tobias Rosenkranz
|
Tobias Rosenkranz
|
||||||
Tobias Wölfel
|
Tobias Wölfel
|
||||||
Todd Strader
|
Todd Strader
|
||||||
|
Tomasz Gorochowik
|
||||||
|
Tymoteusz Blazejczyk
|
||||||
|
Unai Martinez-Corral
|
||||||
|
Victor Besyakov
|
||||||
|
Vassilis Papaefstathiou
|
||||||
Veripool API Bot
|
Veripool API Bot
|
||||||
Wilson Snyder
|
Wilson Snyder
|
||||||
|
Yossi Nivin
|
||||||
|
Yuri Victorovich
|
||||||
Yutetsu TAKATSUKASA
|
Yutetsu TAKATSUKASA
|
||||||
Yves Mathieu
|
Yves Mathieu
|
||||||
|
HyungKi Jeong
|
||||||
|
|||||||
+1
-1
@@ -7,7 +7,7 @@
|
|||||||
#
|
#
|
||||||
#*****************************************************************************
|
#*****************************************************************************
|
||||||
#
|
#
|
||||||
# Copyright 2003-2020 by Wilson Snyder. This program is free software; you
|
# Copyright 2003-2021 by Wilson Snyder. This program is free software; you
|
||||||
# can redistribute it and/or modify it under the terms of either the GNU
|
# can 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,6 +1,6 @@
|
|||||||
// DESCRIPTION: Verilator: List of To Do issues.
|
// DESCRIPTION: Verilator: List of To Do issues.
|
||||||
//
|
//
|
||||||
// Copyright 2004-2020 by Wilson Snyder. This program is free software; you can
|
// Copyright 2004-2021 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// 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.
|
||||||
@@ -84,7 +84,7 @@
|
|||||||
"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/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
|
||||||
|
|||||||
+16
-21
@@ -39,7 +39,7 @@ brief:
|
|||||||
#sudo apt-get install libfl2 # Ubuntu only (ignore if gives error)
|
#sudo apt-get install libfl2 # Ubuntu only (ignore if gives error)
|
||||||
#sudo apt-get install libfl-dev # Ubuntu only (ignore if gives error)
|
#sudo apt-get install libfl-dev # Ubuntu only (ignore if gives error)
|
||||||
|
|
||||||
git clone https://git.veripool.org/git/verilator # Only first time
|
git clone https://github.com/verilator/verilator # Only first time
|
||||||
## Note the URL above is not a page you can see with a browser, it's for git only
|
## Note the URL above is not a page you can see with a browser, it's for git only
|
||||||
|
|
||||||
# Every time you need to build:
|
# Every time you need to build:
|
||||||
@@ -69,19 +69,18 @@ Linux distribution, see instead <<Install From a Package Manager>>.
|
|||||||
|
|
||||||
=== OS Requirements
|
=== OS Requirements
|
||||||
|
|
||||||
Verilator is developed and has primary testing on Ubuntu. Versions have
|
Verilator is developed and has primary testing on Ubuntu, with additional
|
||||||
also built on Redhat Linux, Apple OS-X, HPUX and Solaris. It should run
|
testing on FreeBSD and Apple OS-X. Versions have also built on Redhat
|
||||||
with minor porting on any GNU/Linux-ish platform. Verilator also works on
|
Linux, HPUX and Solaris. It should run with minor porting on any
|
||||||
Windows under Cygwin, and Windows under MinGW (gcc -mno-cygwin). Verilated
|
GNU/Linux-ish platform. Verilator also works on Windows under Cygwin, and
|
||||||
output (not Verilator itself) compiles under all the options above, plus
|
Windows under MinGW (gcc -mno-cygwin). Verilated output (not Verilator
|
||||||
MSVC++.
|
itself) compiles under all the options above, plus MSVC++.
|
||||||
|
|
||||||
=== Install Prerequisites
|
=== Install Prerequisites
|
||||||
|
|
||||||
To build or run Verilator you need these standard packages:
|
To build or run Verilator you need these standard packages:
|
||||||
|
|
||||||
sudo apt-get install perl python3
|
sudo apt-get install perl python3 make
|
||||||
sudo apt-get install make
|
|
||||||
sudo apt-get install g++ # Alternatively, clang
|
sudo apt-get install g++ # Alternatively, clang
|
||||||
sudo apt-get install libgz # Non-Ubuntu (ignore if gives error)
|
sudo apt-get install libgz # Non-Ubuntu (ignore if gives error)
|
||||||
sudo apt-get install libfl2 libfl-dev zlibc zlib1g zlib1g-dev # Ubuntu only (ignore if gives error)
|
sudo apt-get install libfl2 libfl-dev zlibc zlib1g zlib1g-dev # Ubuntu only (ignore if gives error)
|
||||||
@@ -90,21 +89,18 @@ To build or run the following are optional but should be installed for
|
|||||||
good performance:
|
good performance:
|
||||||
|
|
||||||
sudo apt-get install ccache # If present at build, needed for run
|
sudo apt-get install ccache # If present at build, needed for run
|
||||||
sudo apt-get install libgoogle-perftools-dev numactl
|
sudo apt-get install libgoogle-perftools-dev numactl perl-doc
|
||||||
|
|
||||||
To build Verilator you will need to install these packages; these do not
|
To build Verilator you will need to install these packages; these do not
|
||||||
need to be present to run Verilator:
|
need to be present to run Verilator:
|
||||||
|
|
||||||
sudo apt-get install git
|
sudo apt-get install git autoconf flex bison
|
||||||
sudo apt-get install autoconf flex bison
|
|
||||||
|
|
||||||
Those developing Verilator itself may also want these (see internals.adoc):
|
Those developing Verilator itself may also want these (see internals.adoc):
|
||||||
|
|
||||||
sudo apt-get install gdb asciidoctor graphviz cmake clang-format
|
sudo apt-get install gdb asciidoctor graphviz cmake clang clang-format gprof lcov
|
||||||
cpan install Pod::Perldoc
|
cpan install Pod::Perldoc
|
||||||
cpan install Unix::Processors
|
|
||||||
cpan install Parallel::Forker
|
cpan install Parallel::Forker
|
||||||
cpan install Bit::Vector
|
|
||||||
|
|
||||||
==== Install SystemC
|
==== Install SystemC
|
||||||
|
|
||||||
@@ -130,7 +126,7 @@ Downloads]; we presume you know how to use it, and is not described here.)
|
|||||||
|
|
||||||
Get the sources from the repository: (You need do this only once, ever.)
|
Get the sources from the repository: (You need do this only once, ever.)
|
||||||
|
|
||||||
git clone https://git.veripool.org/git/verilator # Only first time
|
git clone https://github.com/verilator/verilator # Only first time
|
||||||
## Note the URL above is not a page you can see with a browser, it's for git only
|
## Note the URL above is not a page you can see with a browser, it's for git only
|
||||||
|
|
||||||
Enter the checkout and determine what version/branch to use:
|
Enter the checkout and determine what version/branch to use:
|
||||||
@@ -266,10 +262,9 @@ set in your environment; it is built into the executable.
|
|||||||
|
|
||||||
== Announcements
|
== Announcements
|
||||||
|
|
||||||
To get notified of new releases, login to
|
To get notified of new releases, go to
|
||||||
https://www.veripool.org[Veripool], and click the "watch" button near the
|
https://github.com/verilator/verilator-announce[Verilator announcement
|
||||||
top right under https://www.veripool.org/projects/verilator/news[Verilator
|
repository] and follow the instructions there.
|
||||||
News].
|
|
||||||
|
|
||||||
== Directory Structure
|
== Directory Structure
|
||||||
|
|
||||||
@@ -302,7 +297,7 @@ or https://verilator.org/verilator_doc.pdf[Verilator manual (PDF)].
|
|||||||
|
|
||||||
== License
|
== License
|
||||||
|
|
||||||
Copyright 2008-2020 by Wilson Snyder. Verilator is free software; you can
|
Copyright 2008-2021 by Wilson Snyder. Verilator is free software; you can
|
||||||
redistribute it and/or modify it under the terms of either the GNU Lesser
|
redistribute it and/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.
|
||||||
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||||
|
|||||||
+61
-35
@@ -387,10 +387,8 @@ changed; if clear, checking those signals for changes may be skipped.
|
|||||||
|
|
||||||
=== Compiler Version and C++11
|
=== Compiler Version and C++11
|
||||||
|
|
||||||
Verilator supports GCC 4.4.7 and newer. GCC 4.4.7 does not support C++11,
|
Verilator requires C++11. Verilator does not require any newer versions,
|
||||||
therefore C++11 is generally not required. Exceptions may be made to
|
but is maintained to build successfully with C++14/C++17/C++20.
|
||||||
require C++11 for features that are only practical with C++11,
|
|
||||||
e.g. threads.
|
|
||||||
|
|
||||||
=== Indentation and Naming Style
|
=== Indentation and Naming Style
|
||||||
|
|
||||||
@@ -411,8 +409,9 @@ style indentation; the `c-set-style` undoes that.)
|
|||||||
|
|
||||||
* Comment every member variable.
|
* Comment every member variable.
|
||||||
|
|
||||||
Indentation is automatically maintained with "make clang-format" (using
|
Indentation is automatically maintained with "make format" using
|
||||||
clang-format version 10.0.0). For those manually formatting:
|
clang-format version 10.0.0, and yapf for python, and is automatically
|
||||||
|
corrected in the CI actions. For those manually formatting C++ code:
|
||||||
|
|
||||||
* Use 4 spaces per level, and no tabs.
|
* Use 4 spaces per level, and no tabs.
|
||||||
|
|
||||||
@@ -588,7 +587,7 @@ dealing with. For example a visitor might not implement separate `visit`
|
|||||||
methods for `AstIf` and `AstGenIf`, but just a single method for the base
|
methods for `AstIf` and `AstGenIf`, but just a single method for the base
|
||||||
class:
|
class:
|
||||||
|
|
||||||
void visit (AstNodeIf* nodep)
|
void visit(AstNodeIf* nodep)
|
||||||
|
|
||||||
However that method might want to specify additional code if it is called
|
However that method might want to specify additional code if it is called
|
||||||
for `AstGenIf`. Verilator does this by providing a `VN_IS` method for each
|
for `AstGenIf`. Verilator does this by providing a `VN_IS` method for each
|
||||||
@@ -630,8 +629,6 @@ https://github.com/veripool/vcddiff
|
|||||||
|
|
||||||
* Cmake for build paths that use it.
|
* Cmake for build paths that use it.
|
||||||
|
|
||||||
* Bit::Vector to test vgen.pl
|
|
||||||
|
|
||||||
=== Controlling the Test Driver
|
=== Controlling the Test Driver
|
||||||
|
|
||||||
Test drivers are written in PERL. All invoke the main test driver script,
|
Test drivers are written in PERL. All invoke the main test driver script,
|
||||||
@@ -674,7 +671,7 @@ Set to 1 to indicate that the compilation or execution is intended to fail.
|
|||||||
For example the following would specify that compilation requires two
|
For example the following would specify that compilation requires two
|
||||||
defines and is expected to fail.
|
defines and is expected to fail.
|
||||||
|
|
||||||
compile (
|
compile(
|
||||||
verilator_flags2 => ["-DSMALL_CLOCK -DGATED_COMMENT"],
|
verilator_flags2 => ["-DSMALL_CLOCK -DGATED_COMMENT"],
|
||||||
fails => 1,
|
fails => 1,
|
||||||
);
|
);
|
||||||
@@ -700,7 +697,7 @@ Verilator problem.
|
|||||||
When enabling the long tests, some additional PERL modules are needed,
|
When enabling the long tests, some additional PERL modules are needed,
|
||||||
which you can install using cpan.
|
which you can install using cpan.
|
||||||
|
|
||||||
cpan install Unix::Processors
|
cpan install Parallel::Forker
|
||||||
|
|
||||||
There are some traps to avoid when running regression tests
|
There are some traps to avoid when running regression tests
|
||||||
|
|
||||||
@@ -732,20 +729,17 @@ test, run the following command.
|
|||||||
|
|
||||||
=== Continuous Integration
|
=== Continuous Integration
|
||||||
|
|
||||||
Verilator has a https://travis-ci.com/verilator/verilator[Travis CI environment]
|
Verilator uses GitHub Actions which automatically tests the master branch
|
||||||
which automatically tests the master branch for test failures on new commits. It
|
for test failures on new commits. It also runs a daily cron job to validate
|
||||||
also runs a daily cron job to validate all of the tests against different OS and
|
all of the tests against different OS and compiler versions.
|
||||||
compiler versions.
|
|
||||||
|
|
||||||
Developers can connect Travis CI to their GitHub account so that the CI
|
Developers can enable Actions on their GitHub repository so that the CI
|
||||||
environment can check their branches too by doing the following:
|
environment can check their branches too by enabling the build workflow:
|
||||||
|
|
||||||
* Go to https://github.com/marketplace/travis-ci and follow the prompts
|
* On GitHub, navigate to the main page of the repository.
|
||||||
|
* Under your repository name, click Actions.
|
||||||
* Only the Open Source (FREE) version of Travis CI is required
|
* In the left sidebar, click the workflow you want to enable ("build").
|
||||||
|
* Click Enable workflow.
|
||||||
* Under a Travis CI project click More options > Settings in order to set up a
|
|
||||||
cron job on a particular branch
|
|
||||||
|
|
||||||
=== Fuzzing
|
=== Fuzzing
|
||||||
|
|
||||||
@@ -760,6 +754,15 @@ may be required to setup the system for fuzzing.
|
|||||||
|
|
||||||
== Debugging
|
== Debugging
|
||||||
|
|
||||||
|
=== Debug Levels
|
||||||
|
|
||||||
|
The "UINFO" calls in the source indicate a debug level. Messages level 3
|
||||||
|
and below are globally enabled with `--debug`. Higher levels may be
|
||||||
|
controlled with `--debugi <level>`. An individual source file levels may
|
||||||
|
be controlled with `-debugi-<srcfile> <level>`. For example `--debug
|
||||||
|
--debugi 5 --debugi-V3Width 9` will use the debug binary at default debug
|
||||||
|
level 5, with the V3Width.cpp file at level 9.
|
||||||
|
|
||||||
=== --debug
|
=== --debug
|
||||||
|
|
||||||
When you run with `--debug` there are two primary output file types placed
|
When you run with `--debug` there are two primary output file types placed
|
||||||
@@ -777,19 +780,20 @@ output, for example:
|
|||||||
You can then print a.ps. You may prefer gif format, which doesn't get
|
You can then print a.ps. You may prefer gif format, which doesn't get
|
||||||
scaled so can be more useful with large graphs.
|
scaled so can be more useful with large graphs.
|
||||||
|
|
||||||
For dynamic graph viewing consider
|
For interactive graph viewing consider
|
||||||
|
https://github.com/jrfonseca/xdot.py[xdot] or
|
||||||
http://zvtm.sourceforge.net/zgrviewer.html[ZGRViewer]. If you know of
|
http://zvtm.sourceforge.net/zgrviewer.html[ZGRViewer]. If you know of
|
||||||
better viewers let us know; ZGRViewer isn't great for large graphs.
|
better viewers (especially for large graphs) please let us know.
|
||||||
|
|
||||||
=== .tree Output
|
=== .tree Output
|
||||||
|
|
||||||
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> {a0}
|
NETLIST 0x90fb00 <e1> {a0ah}
|
||||||
1: MODULE 0x912b20 <e8822> {a8} top L2 [P]
|
1: MODULE 0x912b20 <e8822> {a8ah} top L2 [P]
|
||||||
*1:2: VAR 0x91a780 <e74#> {a22} @dt=0xa2e640(w32) out_wide [O] WIRE
|
*1:2: VAR 0x91a780 <e74#> {a22ah} @dt=0xa2e640(w32) out_wide [O] WIRE
|
||||||
1:2:1: BASICDTYPE 0xa2e640 <e2149> {e24} @dt=this(sw32) integer kwd=integer range=[31:0]
|
1:2:1: BASICDTYPE 0xa2e640 <e2149> {e24ah} @dt=this(sw32) integer kwd=integer range=[31:0]
|
||||||
|
|
||||||
The following summarizes the above example dump, with more detail on each
|
The following summarizes the above example dump, with more detail on each
|
||||||
field in the section below.
|
field in the section below.
|
||||||
@@ -807,8 +811,9 @@ the `MODULE`, which in turn is the `op1p` pointer under the `NETLIST`
|
|||||||
| `<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.
|
this node.
|
||||||
|
|
||||||
| `{a22}` | indicates this node is related to line 22 in the source filename
|
| `{a22ah}` | indicates this node is related to the source filename "a",
|
||||||
"a", where "a" is the first file read, "z" the 26th, and "aa" the 27th.
|
where "a" is the first file read, "z" the 26th, and "aa" the 27th. Then
|
||||||
|
line 22 in that file, then column 8 (aa=0, az=25, ba=26, ...).
|
||||||
|
|
||||||
| `@dt=0x...` | indicates the address of the data type this node contains.
|
| `@dt=0x...` | indicates the address of the data type this node contains.
|
||||||
|
|
||||||
@@ -849,7 +854,10 @@ correspond directly to Verilog entities (for example `MODULE` and
|
|||||||
Address of the node::
|
Address of the node::
|
||||||
|
|
||||||
A hexadecimal address of the node in memory. Useful for examining with the
|
A hexadecimal address of the node in memory. Useful for examining with the
|
||||||
debugger.
|
debugger. If the actual address values are not important, then using the
|
||||||
|
`--dump-tree-addrids` option will convert address values to short identifiers
|
||||||
|
of the form `([A-Z]*)`, which is hopefully easier for the reader to cross
|
||||||
|
reference throughout the dump.
|
||||||
|
|
||||||
Last edit number::
|
Last edit number::
|
||||||
|
|
||||||
@@ -947,9 +955,9 @@ Then, when the watch fires, to break at every following change to that node:
|
|||||||
To print a node:
|
To print a node:
|
||||||
|
|
||||||
pn nodep
|
pn nodep
|
||||||
# or: call nodep->dumpGdb() # aliased to "pn" in src/.gdbinit
|
# or: call dumpGdb(nodep) # aliased to "pn" in src/.gdbinit
|
||||||
pnt nodep
|
pnt nodep
|
||||||
# or: call nodep->dumpTreeGdb() # aliased to "pnt" in src/.gdbinit
|
# or: call dumpTreeGdb(nodep) # aliased to "pnt" in src/.gdbinit
|
||||||
|
|
||||||
When GDB halts, it is useful to understand that the backtrace will commonly
|
When GDB halts, it is useful to understand that the backtrace will commonly
|
||||||
show the iterator functions between each invocation of `visit` in the
|
show the iterator functions between each invocation of `visit` in the
|
||||||
@@ -996,9 +1004,27 @@ function in `src/verilator.cpp`.
|
|||||||
To get your pass to build you'll need to add its binary filename to the
|
To get your pass to build you'll need to add its binary filename to the
|
||||||
list in `src/Makefile_obj.in` and reconfigure.
|
list in `src/Makefile_obj.in` and reconfigure.
|
||||||
|
|
||||||
|
=== "Never" features
|
||||||
|
|
||||||
|
Verilator ideally would support all of IEEE, and has the goal to get close
|
||||||
|
to full support. However the following IEEE sections and features are not
|
||||||
|
anticipated to be ever implemented for the reasons indicated.
|
||||||
|
|
||||||
|
[horizontal]
|
||||||
|
IEEE 1800-2017 3.3 recursive modules:: Little/no tool support, and arguably not a good practice.
|
||||||
|
IEEE 1800-2017 6.12 "shortreal":: Little/no tool support, and easily simply promoted to real.
|
||||||
|
IEEE 1800-2017 11.11 Min, typ, max:: No SDF support so will always use typical.
|
||||||
|
IEEE 1800-2017 11.12 "let":: Little/no tool support, makes difficult to implement parsers.
|
||||||
|
IEEE 1800-2017 20.15 Probabilistic functions:: Little industry use.
|
||||||
|
IEEE 1800-2017 20.16 Stochastic analysis:: Little industry use.
|
||||||
|
IEEE 1800-2017 20.17 PLA modeling:: Little industry use and outdated technology.
|
||||||
|
IEEE 1800-2017 31 Timing checks:: No longer relevant with static timing analysis tools.
|
||||||
|
IEEE 1800-2017 32 SDF annotation:: No longer relevant with static timing analysis tools.
|
||||||
|
IEEE 1800-2017 33 Config:: Little/no tool support or industry use.
|
||||||
|
|
||||||
== Distribution
|
== Distribution
|
||||||
|
|
||||||
Copyright 2008-2020 by Wilson Snyder. Verilator is free software; you can
|
Copyright 2008-2021 by Wilson Snyder. Verilator is free software; you can
|
||||||
redistribute it and/or modify it under the terms of either the GNU Lesser
|
redistribute it and/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.
|
||||||
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||||
|
|||||||
+1
-1
@@ -66,7 +66,7 @@ elements in the `<module>` elements using the `dtype_id` attribute.
|
|||||||
|
|
||||||
== Distribution
|
== Distribution
|
||||||
|
|
||||||
Copyright 2020-2020 by Wilson Snyder. Verilator is free software; you can
|
Copyright 2020-2021 by Wilson Snyder. Verilator is free software; you can
|
||||||
redistribute it and/or modify it under the terms of either the GNU Lesser
|
redistribute it and/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.
|
||||||
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||||
|
|||||||
@@ -5,11 +5,9 @@
|
|||||||
# This is an example cmake script to build a verilog to systemc project
|
# This is an example cmake script to build a verilog to systemc project
|
||||||
# using cmake and verilator.
|
# using cmake and verilator.
|
||||||
#
|
#
|
||||||
# Copyright 2003-2020 by Wilson Snyder. This program is free software; you
|
# This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
# can redistribute it and/or modify it under the terms of either the GNU
|
# any use, without warranty, 2020 by Wilson Snyder.
|
||||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
# SPDX-License-Identifier: CC0-1.0
|
||||||
# Version 2.0.
|
|
||||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
|
||||||
#
|
#
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
|
|||||||
@@ -6,11 +6,9 @@
|
|||||||
# This makefile is here for testing the examples and should
|
# This makefile is here for testing the examples and should
|
||||||
# generally not be added to a CMake project.
|
# generally not be added to a CMake project.
|
||||||
#
|
#
|
||||||
# Copyright 2003-2020 by Wilson Snyder. This program is free software; you
|
# This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
# can redistribute it and/or modify it under the terms of either the GNU
|
# any use, without warranty, 2020 by Wilson Snyder.
|
||||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
# SPDX-License-Identifier: CC0-1.0
|
||||||
# Version 2.0.
|
|
||||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
|
||||||
#
|
#
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
|
|||||||
@@ -5,11 +5,9 @@
|
|||||||
# This is an example cmake script to build a verilog to SystemC project
|
# This is an example cmake script to build a verilog to SystemC project
|
||||||
# using CMake and Verilator.
|
# using CMake and Verilator.
|
||||||
#
|
#
|
||||||
# Copyright 2003-2020 by Wilson Snyder. This program is free software; you
|
# This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
# can redistribute it and/or modify it under the terms of either the GNU
|
# any use, without warranty, 2020 by Wilson Snyder.
|
||||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
# SPDX-License-Identifier: CC0-1.0
|
||||||
# Version 2.0.
|
|
||||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
|
||||||
#
|
#
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
|
|||||||
@@ -6,11 +6,9 @@
|
|||||||
# This makefile is here for testing the examples and should
|
# This makefile is here for testing the examples and should
|
||||||
# generally not be added to a CMake project.
|
# generally not be added to a CMake project.
|
||||||
#
|
#
|
||||||
# Copyright 2003-2020 by Wilson Snyder. This program is free software; you
|
# This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
# can redistribute it and/or modify it under the terms of either the GNU
|
# any use, without warranty, 2020 by Wilson Snyder.
|
||||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
# SPDX-License-Identifier: CC0-1.0
|
||||||
# Version 2.0.
|
|
||||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
|
||||||
#
|
#
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
|
|||||||
@@ -5,11 +5,9 @@
|
|||||||
# This is an example cmake script to build a verilog to systemc project
|
# This is an example cmake script to build a verilog to systemc project
|
||||||
# using cmake and verilator.
|
# using cmake and verilator.
|
||||||
#
|
#
|
||||||
# Copyright 2003-2020 by Wilson Snyder. This program is free software; you
|
# This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
# can redistribute it and/or modify it under the terms of either the GNU
|
# any use, without warranty, 2020 by Wilson Snyder.
|
||||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
# SPDX-License-Identifier: CC0-1.0
|
||||||
# Version 2.0.
|
|
||||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
|
||||||
#
|
#
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
|
|||||||
@@ -6,11 +6,9 @@
|
|||||||
# This makefile is here for testing the examples and should
|
# This makefile is here for testing the examples and should
|
||||||
# generally not be added to a CMake project.
|
# generally not be added to a CMake project.
|
||||||
#
|
#
|
||||||
# Copyright 2003-2020 by Wilson Snyder. This program is free software; you
|
# This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
# can redistribute it and/or modify it under the terms of either the GNU
|
# any use, without warranty, 2020 by Wilson Snyder.
|
||||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
# SPDX-License-Identifier: CC0-1.0
|
||||||
# Version 2.0.
|
|
||||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
|
||||||
#
|
#
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
|
|||||||
@@ -5,11 +5,9 @@
|
|||||||
# This is an example cmake script to build a verilog to systemc project
|
# This is an example cmake script to build a verilog to systemc project
|
||||||
# using cmake and verilator.
|
# using cmake and verilator.
|
||||||
#
|
#
|
||||||
# Copyright 2003-2020 by Wilson Snyder. This program is free software; you
|
# This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
# can redistribute it and/or modify it under the terms of either the GNU
|
# any use, without warranty, 2020 by Wilson Snyder.
|
||||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
# SPDX-License-Identifier: CC0-1.0
|
||||||
# Version 2.0.
|
|
||||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
|
||||||
#
|
#
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
|
|||||||
@@ -6,11 +6,9 @@
|
|||||||
# This makefile is here for testing the examples and should
|
# This makefile is here for testing the examples and should
|
||||||
# generally not be added to a CMake project.
|
# generally not be added to a CMake project.
|
||||||
#
|
#
|
||||||
# Copyright 2003-2020 by Wilson Snyder. This program is free software; you
|
# This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
# can redistribute it and/or modify it under the terms of either the GNU
|
# any use, without warranty, 2020 by Wilson Snyder.
|
||||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
# SPDX-License-Identifier: CC0-1.0
|
||||||
# Version 2.0.
|
|
||||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
|
||||||
#
|
#
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
|
|||||||
@@ -5,11 +5,9 @@
|
|||||||
# This is an example cmake script to build a verilog to SystemC project
|
# This is an example cmake script to build a verilog to SystemC project
|
||||||
# using CMake and Verilator.
|
# using CMake and Verilator.
|
||||||
#
|
#
|
||||||
# Copyright 2003-2020 by Wilson Snyder. This program is free software; you
|
# This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
# can redistribute it and/or modify it under the terms of either the GNU
|
# any use, without warranty, 2020 by Wilson Snyder.
|
||||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
# SPDX-License-Identifier: CC0-1.0
|
||||||
# Version 2.0.
|
|
||||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
|
||||||
#
|
#
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
|
|||||||
@@ -6,11 +6,9 @@
|
|||||||
# This makefile is here for testing the examples and should
|
# This makefile is here for testing the examples and should
|
||||||
# generally not be added to a CMake project.
|
# generally not be added to a CMake project.
|
||||||
#
|
#
|
||||||
# Copyright 2003-2020 by Wilson Snyder. This program is free software; you
|
# This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
# can redistribute it and/or modify it under the terms of either the GNU
|
# any use, without warranty, 2020 by Wilson Snyder.
|
||||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
# SPDX-License-Identifier: CC0-1.0
|
||||||
# Version 2.0.
|
|
||||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
|
||||||
#
|
#
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
|
|||||||
@@ -5,11 +5,9 @@
|
|||||||
# This calls the object directory makefile. That allows the objects to
|
# This calls the object directory makefile. That allows the objects to
|
||||||
# be placed in the "current directory" which simplifies the Makefile.
|
# be placed in the "current directory" which simplifies the Makefile.
|
||||||
#
|
#
|
||||||
# Copyright 2003-2020 by Wilson Snyder. This program is free software; you
|
# This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
# can redistribute it and/or modify it under the terms of either the GNU
|
# any use, without warranty, 2020 by Wilson Snyder.
|
||||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
# SPDX-License-Identifier: CC0-1.0
|
||||||
# Version 2.0.
|
|
||||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
|
||||||
#
|
#
|
||||||
######################################################################
|
######################################################################
|
||||||
# Check for sanity to avoid later confusion
|
# Check for sanity to avoid later confusion
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ int main(int argc, char** argv, char** env) {
|
|||||||
// e.g. examples/c_tracing.
|
// e.g. examples/c_tracing.
|
||||||
|
|
||||||
// Prevent unused variable warnings
|
// Prevent unused variable warnings
|
||||||
if (0 && argc && argv && env) {}
|
if (false && argc && argv && env) {}
|
||||||
|
|
||||||
// Construct the Verilated model, from Vtop.h generated from Verilating "top.v"
|
// Construct the Verilated model, from Vtop.h generated from Verilating "top.v"
|
||||||
Vtop* top = new Vtop;
|
Vtop* top = new Vtop;
|
||||||
@@ -37,6 +37,6 @@ int main(int argc, char** argv, char** env) {
|
|||||||
// Destroy model
|
// Destroy model
|
||||||
delete top;
|
delete top;
|
||||||
|
|
||||||
// Fin
|
// Return good completion status
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,11 +5,9 @@
|
|||||||
# This calls the object directory makefile. That allows the objects to
|
# This calls the object directory makefile. That allows the objects to
|
||||||
# be placed in the "current directory" which simplifies the Makefile.
|
# be placed in the "current directory" which simplifies the Makefile.
|
||||||
#
|
#
|
||||||
# Copyright 2003-2020 by Wilson Snyder. This program is free software; you
|
# This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
# can redistribute it and/or modify it under the terms of either the GNU
|
# any use, without warranty, 2020 by Wilson Snyder.
|
||||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
# SPDX-License-Identifier: CC0-1.0
|
||||||
# Version 2.0.
|
|
||||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
|
||||||
#
|
#
|
||||||
######################################################################
|
######################################################################
|
||||||
# Check for sanity to avoid later confusion
|
# Check for sanity to avoid later confusion
|
||||||
|
|||||||
@@ -23,30 +23,23 @@ int sc_main(int argc, char* argv[]) {
|
|||||||
// e.g. examples/c_tracing.
|
// e.g. examples/c_tracing.
|
||||||
|
|
||||||
// Prevent unused variable warnings
|
// Prevent unused variable warnings
|
||||||
if (0 && argc && argv) {}
|
if (false && argc && argv) {}
|
||||||
|
|
||||||
// Construct the Verilated model, from Vtop.h generated from Verilating "top.v"
|
// Construct the Verilated model, from Vtop.h generated from Verilating "top.v"
|
||||||
Vtop* top = new Vtop("top");
|
Vtop* top = new Vtop("top");
|
||||||
|
|
||||||
// Initialize SC model
|
// Initialize SC model
|
||||||
#if (SYSTEMC_VERSION >= 20070314)
|
|
||||||
sc_start(1, SC_NS);
|
sc_start(1, SC_NS);
|
||||||
#else
|
|
||||||
sc_start(1);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Simulate until $finish
|
// Simulate until $finish
|
||||||
while (!Verilated::gotFinish()) {
|
while (!Verilated::gotFinish()) {
|
||||||
#if (SYSTEMC_VERSION >= 20070314)
|
// Simulate 1ns
|
||||||
sc_start(1, SC_NS);
|
sc_start(1, SC_NS);
|
||||||
#else
|
|
||||||
sc_start(1);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Final model cleanup
|
// Final model cleanup
|
||||||
top->final();
|
top->final();
|
||||||
|
|
||||||
// Fin
|
// Return good completion status
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,11 +5,9 @@
|
|||||||
# This calls the object directory makefiles. That allows the objects to
|
# This calls the object directory makefiles. That allows the objects to
|
||||||
# be placed in the "current directory" which simplifies the Makefile.
|
# be placed in the "current directory" which simplifies the Makefile.
|
||||||
#
|
#
|
||||||
# Copyright 2019 by Wilson Snyder. This program is free software; you
|
# This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
# can redistribute it and/or modify it under the terms of either the GNU
|
# any use, without warranty, 2020 by Wilson Snyder.
|
||||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
# SPDX-License-Identifier: CC0-1.0
|
||||||
# Version 2.0.
|
|
||||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
|
||||||
#
|
#
|
||||||
######################################################################
|
######################################################################
|
||||||
# Check for sanity to avoid later confusion
|
# Check for sanity to avoid later confusion
|
||||||
@@ -70,7 +68,7 @@ run:
|
|||||||
@echo " library (libverilated_secret.a) generated from the previous"
|
@echo " library (libverilated_secret.a) generated from the previous"
|
||||||
@echo " step"
|
@echo " step"
|
||||||
@echo "---------------------------------------------------------------"
|
@echo "---------------------------------------------------------------"
|
||||||
$(VERILATOR) $(TOP_VERILATOR_FLAGS) --exe -LDFLAGS '-L../obj_dir_secret -lverilated_secret -static' top.v obj_dir_secret/verilated_secret.sv sim_main.cpp
|
$(VERILATOR) $(TOP_VERILATOR_FLAGS) --exe -LDFLAGS '../obj_dir_secret/libverilated_secret.a' top.v obj_dir_secret/verilated_secret.sv sim_main.cpp
|
||||||
|
|
||||||
@echo
|
@echo
|
||||||
@echo "-- COMPILE entire design --------------------------------------"
|
@echo "-- COMPILE entire design --------------------------------------"
|
||||||
|
|||||||
@@ -13,14 +13,14 @@
|
|||||||
#include "Vtop.h"
|
#include "Vtop.h"
|
||||||
|
|
||||||
#if VM_TRACE
|
#if VM_TRACE
|
||||||
# include <verilated_vcd_c.h>
|
#include <verilated_vcd_c.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
vluint64_t main_time = 0;
|
vluint64_t main_time = 0;
|
||||||
double sc_time_stamp() { return main_time; }
|
double sc_time_stamp() { return main_time; }
|
||||||
|
|
||||||
int main(int argc, char** argv, char** env) {
|
int main(int argc, char** argv, char** env) {
|
||||||
if (0 && argc && argv && env) {}
|
if (false && argc && argv && env) {}
|
||||||
|
|
||||||
Verilated::debug(0);
|
Verilated::debug(0);
|
||||||
Verilated::randReset(2);
|
Verilated::randReset(2);
|
||||||
@@ -31,7 +31,7 @@ int main(int argc, char** argv, char** env) {
|
|||||||
|
|
||||||
#if VM_TRACE
|
#if VM_TRACE
|
||||||
// When tracing, the contents of the secret module will not be seen
|
// When tracing, the contents of the secret module will not be seen
|
||||||
VerilatedVcdC* tfp = NULL;
|
VerilatedVcdC* tfp = nullptr;
|
||||||
const char* flag = Verilated::commandArgsPlusMatch("trace");
|
const char* flag = Verilated::commandArgsPlusMatch("trace");
|
||||||
if (flag && 0 == strcmp(flag, "+trace")) {
|
if (flag && 0 == strcmp(flag, "+trace")) {
|
||||||
Verilated::traceEverOn(true);
|
Verilated::traceEverOn(true);
|
||||||
@@ -62,14 +62,14 @@ int main(int argc, char** argv, char** env) {
|
|||||||
#if VM_TRACE
|
#if VM_TRACE
|
||||||
if (tfp) {
|
if (tfp) {
|
||||||
tfp->close();
|
tfp->close();
|
||||||
tfp = NULL;
|
tfp = nullptr;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Destroy model
|
// Destroy model
|
||||||
delete top;
|
delete top;
|
||||||
top = NULL;
|
top = nullptr;
|
||||||
|
|
||||||
// Fin
|
// Return good completion status
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,11 +5,9 @@
|
|||||||
# This calls the object directory makefile. That allows the objects to
|
# This calls the object directory makefile. That allows the objects to
|
||||||
# be placed in the "current directory" which simplifies the Makefile.
|
# be placed in the "current directory" which simplifies the Makefile.
|
||||||
#
|
#
|
||||||
# Copyright 2003-2020 by Wilson Snyder. This program is free software; you
|
# This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
# can redistribute it and/or modify it under the terms of either the GNU
|
# any use, without warranty, 2020 by Wilson Snyder.
|
||||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
# SPDX-License-Identifier: CC0-1.0
|
||||||
# Version 2.0.
|
|
||||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
|
||||||
#
|
#
|
||||||
######################################################################
|
######################################################################
|
||||||
# Check for sanity to avoid later confusion
|
# Check for sanity to avoid later confusion
|
||||||
|
|||||||
@@ -5,11 +5,9 @@
|
|||||||
#
|
#
|
||||||
# This is executed in the object directory, and called by ../Makefile
|
# This is executed in the object directory, and called by ../Makefile
|
||||||
#
|
#
|
||||||
# Copyright 2003-2020 by Wilson Snyder. This program is free software; you
|
# This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
# can redistribute it and/or modify it under the terms of either the GNU
|
# any use, without warranty, 2020 by Wilson Snyder.
|
||||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
# SPDX-License-Identifier: CC0-1.0
|
||||||
# Version 2.0.
|
|
||||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
|
||||||
#
|
#
|
||||||
#######################################################################
|
#######################################################################
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,9 @@
|
|||||||
// SPDX-License-Identifier: CC0-1.0
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
//======================================================================
|
//======================================================================
|
||||||
|
|
||||||
|
// For std::unique_ptr
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
// Include common routines
|
// Include common routines
|
||||||
#include <verilated.h>
|
#include <verilated.h>
|
||||||
|
|
||||||
@@ -22,7 +25,7 @@ int main(int argc, char** argv, char** env) {
|
|||||||
// This is a more complicated example, please also see the simpler examples/make_hello_c.
|
// This is a more complicated example, please also see the simpler examples/make_hello_c.
|
||||||
|
|
||||||
// Prevent unused variable warnings
|
// Prevent unused variable warnings
|
||||||
if (0 && argc && argv && env) {}
|
if (false && argc && argv && env) {}
|
||||||
|
|
||||||
// Set debug level, 0 is off, 9 is highest presently used
|
// Set debug level, 0 is off, 9 is highest presently used
|
||||||
// May be overridden by commandArgs
|
// May be overridden by commandArgs
|
||||||
@@ -43,7 +46,8 @@ int main(int argc, char** argv, char** env) {
|
|||||||
Verilated::mkdir("logs");
|
Verilated::mkdir("logs");
|
||||||
|
|
||||||
// Construct the Verilated model, from Vtop.h generated from Verilating "top.v"
|
// Construct the Verilated model, from Vtop.h generated from Verilating "top.v"
|
||||||
Vtop* top = new Vtop; // Or use a const unique_ptr, or the VL_UNIQUE_PTR wrapper
|
// Using unique_ptr is similar to "Vtop* top = new Vtop" then deleting at end
|
||||||
|
const std::unique_ptr<Vtop> top{new Vtop};
|
||||||
|
|
||||||
// Set some inputs
|
// Set some inputs
|
||||||
top->reset_l = !0;
|
top->reset_l = !0;
|
||||||
@@ -97,10 +101,6 @@ int main(int argc, char** argv, char** env) {
|
|||||||
VerilatedCov::write("logs/coverage.dat");
|
VerilatedCov::write("logs/coverage.dat");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Destroy model
|
// Return good completion status
|
||||||
delete top;
|
|
||||||
top = NULL;
|
|
||||||
|
|
||||||
// Fin
|
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,11 +5,9 @@
|
|||||||
# This calls the object directory makefile. That allows the objects to
|
# This calls the object directory makefile. That allows the objects to
|
||||||
# be placed in the "current directory" which simplifies the Makefile.
|
# be placed in the "current directory" which simplifies the Makefile.
|
||||||
#
|
#
|
||||||
# Copyright 2003-2020 by Wilson Snyder. This program is free software; you
|
# This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
# can redistribute it and/or modify it under the terms of either the GNU
|
# any use, without warranty, 2020 by Wilson Snyder.
|
||||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
# SPDX-License-Identifier: CC0-1.0
|
||||||
# Version 2.0.
|
|
||||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
|
||||||
#
|
#
|
||||||
######################################################################
|
######################################################################
|
||||||
# Check for sanity to avoid later confusion
|
# Check for sanity to avoid later confusion
|
||||||
|
|||||||
@@ -5,11 +5,9 @@
|
|||||||
#
|
#
|
||||||
# This is executed in the object directory, and called by ../Makefile
|
# This is executed in the object directory, and called by ../Makefile
|
||||||
#
|
#
|
||||||
# Copyright 2003-2020 by Wilson Snyder. This program is free software; you
|
# This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
# can redistribute it and/or modify it under the terms of either the GNU
|
# any use, without warranty, 2020 by Wilson Snyder.
|
||||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
# SPDX-License-Identifier: CC0-1.0
|
||||||
# Version 2.0.
|
|
||||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
|
||||||
#
|
#
|
||||||
#######################################################################
|
#######################################################################
|
||||||
|
|
||||||
@@ -39,8 +37,8 @@ endif
|
|||||||
# If you build your own rules from scratch, note you need to include
|
# If you build your own rules from scratch, note you need to include
|
||||||
# SystemC as follows (Vtop.mk file includes verilated.mk with these
|
# SystemC as follows (Vtop.mk file includes verilated.mk with these
|
||||||
# already).
|
# already).
|
||||||
# CPPFLAGS += $(SYSTEMC_CXX_FLAGS) -I$(SYSTEMC_INCLUDE)
|
# CPPFLAGS += $(SYSTEMC_CXX_FLAGS) $(addprefix -I, $(SYSTEMC_INCLUDE))
|
||||||
# LDFLAGS += $(SYSTEMC_CXX_FLAGS) -L$(SYSTEMC_LIBDIR)
|
# LDFLAGS += $(SYSTEMC_CXX_FLAGS) $(addprefix -L, $(SYSTEMC_LIBDIR))
|
||||||
|
|
||||||
# See the benchmarking section of bin/verilator.
|
# See the benchmarking section of bin/verilator.
|
||||||
# Support class optimizations. This includes the tracing and symbol table.
|
# Support class optimizations. This includes the tracing and symbol table.
|
||||||
|
|||||||
@@ -6,6 +6,9 @@
|
|||||||
// SPDX-License-Identifier: CC0-1.0
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
//======================================================================
|
//======================================================================
|
||||||
|
|
||||||
|
// For std::unique_ptr
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
// SystemC global header
|
// SystemC global header
|
||||||
#include <systemc.h>
|
#include <systemc.h>
|
||||||
|
|
||||||
@@ -24,7 +27,7 @@ int sc_main(int argc, char* argv[]) {
|
|||||||
// This is a more complicated example, please also see the simpler examples/make_hello_c.
|
// This is a more complicated example, please also see the simpler examples/make_hello_c.
|
||||||
|
|
||||||
// Prevent unused variable warnings
|
// Prevent unused variable warnings
|
||||||
if (0 && argc && argv) {}
|
if (false && argc && argv) {}
|
||||||
|
|
||||||
// Set debug level, 0 is off, 9 is highest presently used
|
// Set debug level, 0 is off, 9 is highest presently used
|
||||||
// May be overridden by commandArgs
|
// May be overridden by commandArgs
|
||||||
@@ -44,33 +47,23 @@ int sc_main(int argc, char* argv[]) {
|
|||||||
// General logfile
|
// General logfile
|
||||||
ios::sync_with_stdio();
|
ios::sync_with_stdio();
|
||||||
|
|
||||||
// Defaults time
|
|
||||||
#if (SYSTEMC_VERSION > 20011000)
|
|
||||||
#else
|
|
||||||
sc_time dut(1.0, sc_ns);
|
|
||||||
sc_set_default_time_unit(dut);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Define clocks
|
// Define clocks
|
||||||
#if (SYSTEMC_VERSION >= 20070314)
|
sc_clock clk{"clk", 10, SC_NS, 0.5, 3, SC_NS, true};
|
||||||
sc_clock clk("clk", 10, SC_NS, 0.5, 3, SC_NS, true);
|
sc_clock fastclk{"fastclk", 2, SC_NS, 0.5, 2, SC_NS, true};
|
||||||
sc_clock fastclk("fastclk", 2, SC_NS, 0.5, 2, SC_NS, true);
|
|
||||||
#else
|
|
||||||
sc_clock clk("clk", 10, 0.5, 3, true);
|
|
||||||
sc_clock fastclk("fastclk", 2, 0.5, 2, true);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Define interconnect
|
// Define interconnect
|
||||||
sc_signal<bool> reset_l;
|
sc_signal<bool> reset_l;
|
||||||
sc_signal<vluint32_t> in_small;
|
sc_signal<vluint32_t> in_small;
|
||||||
sc_signal<vluint64_t> in_quad;
|
sc_signal<vluint64_t> in_quad;
|
||||||
sc_signal<sc_bv<70> > in_wide;
|
sc_signal<sc_bv<70>> in_wide;
|
||||||
sc_signal<vluint32_t> out_small;
|
sc_signal<vluint32_t> out_small;
|
||||||
sc_signal<vluint64_t> out_quad;
|
sc_signal<vluint64_t> out_quad;
|
||||||
sc_signal<sc_bv<70> > out_wide;
|
sc_signal<sc_bv<70>> out_wide;
|
||||||
|
|
||||||
// Construct the Verilated model, from inside Vtop.h
|
// Construct the Verilated model, from inside Vtop.h
|
||||||
Vtop* top = new Vtop("top");
|
// Using unique_ptr is similar to "Vtop* top = new Vtop" then deleting at end
|
||||||
|
const std::unique_ptr<Vtop> top{new Vtop{"top"}};
|
||||||
|
|
||||||
// Attach signals to the model
|
// Attach signals to the model
|
||||||
top->clk(clk);
|
top->clk(clk);
|
||||||
top->fastclk(fastclk);
|
top->fastclk(fastclk);
|
||||||
@@ -89,16 +82,12 @@ int sc_main(int argc, char* argv[]) {
|
|||||||
|
|
||||||
// You must do one evaluation before enabling waves, in order to allow
|
// You must do one evaluation before enabling waves, in order to allow
|
||||||
// SystemC to interconnect everything for testing.
|
// SystemC to interconnect everything for testing.
|
||||||
#if (SYSTEMC_VERSION >= 20070314)
|
|
||||||
sc_start(1, SC_NS);
|
sc_start(1, SC_NS);
|
||||||
#else
|
|
||||||
sc_start(1);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if VM_TRACE
|
#if VM_TRACE
|
||||||
// If verilator was invoked with --trace argument,
|
// If verilator was invoked with --trace argument,
|
||||||
// and if at run time passed the +trace argument, turn on tracing
|
// and if at run time passed the +trace argument, turn on tracing
|
||||||
VerilatedVcdSc* tfp = NULL;
|
VerilatedVcdSc* tfp = nullptr;
|
||||||
const char* flag = Verilated::commandArgsPlusMatch("trace");
|
const char* flag = Verilated::commandArgsPlusMatch("trace");
|
||||||
if (flag && 0 == strcmp(flag, "+trace")) {
|
if (flag && 0 == strcmp(flag, "+trace")) {
|
||||||
cout << "Enabling waves into logs/vlt_dump.vcd...\n";
|
cout << "Enabling waves into logs/vlt_dump.vcd...\n";
|
||||||
@@ -125,11 +114,7 @@ int sc_main(int argc, char* argv[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Simulate 1ns
|
// Simulate 1ns
|
||||||
#if (SYSTEMC_VERSION >= 20070314)
|
|
||||||
sc_start(1, SC_NS);
|
sc_start(1, SC_NS);
|
||||||
#else
|
|
||||||
sc_start(1);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Final model cleanup
|
// Final model cleanup
|
||||||
@@ -139,7 +124,7 @@ int sc_main(int argc, char* argv[]) {
|
|||||||
#if VM_TRACE
|
#if VM_TRACE
|
||||||
if (tfp) {
|
if (tfp) {
|
||||||
tfp->close();
|
tfp->close();
|
||||||
tfp = NULL;
|
tfp = nullptr;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -149,10 +134,6 @@ int sc_main(int argc, char* argv[]) {
|
|||||||
VerilatedCov::write("logs/coverage.dat");
|
VerilatedCov::write("logs/coverage.dat");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Destroy model
|
// Return good completion status
|
||||||
delete top;
|
|
||||||
top = NULL;
|
|
||||||
|
|
||||||
// Fin
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,11 +2,9 @@
|
|||||||
#
|
#
|
||||||
# DESCRIPTION: Verilator Example: XML tests
|
# DESCRIPTION: Verilator Example: XML tests
|
||||||
#
|
#
|
||||||
# Copyright 2003-2020 by Wilson Snyder. This program is free software; you
|
# This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
# can redistribute it and/or modify it under the terms of either the GNU
|
# any use, without warranty, 2020 by Wilson Snyder.
|
||||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
# SPDX-License-Identifier: CC0-1.0
|
||||||
# Version 2.0.
|
|
||||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
|
||||||
#
|
#
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
@@ -24,9 +22,9 @@ VERILATOR = $(VERILATOR_ROOT)/bin/verilator
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
DOT = dot
|
DOT = dot
|
||||||
PYTHON = python3
|
PYTHON3 = python3
|
||||||
|
|
||||||
PYTHON_VERSION := $(shell ${PYTHON} --version 2>&1)
|
PYTHON_VERSION := $(shell ${PYTHON3} --version 2>&1)
|
||||||
PYTHON_VERSION_FULL := $(wordlist 2,4,$(subst ., ,${PYTHON_VERSION}))
|
PYTHON_VERSION_FULL := $(wordlist 2,4,$(subst ., ,${PYTHON_VERSION}))
|
||||||
PYTHON_VERSION_MAJOR := $(word 1,${PYTHON_VERSION_FULL})
|
PYTHON_VERSION_MAJOR := $(word 1,${PYTHON_VERSION_FULL})
|
||||||
PYTHON_VERSION_MINOR := $(word 2,${PYTHON_VERSION_FULL})
|
PYTHON_VERSION_MINOR := $(word 2,${PYTHON_VERSION_FULL})
|
||||||
@@ -47,13 +45,13 @@ test: \
|
|||||||
|
|
||||||
test-vl_file_copy:
|
test-vl_file_copy:
|
||||||
@echo "-- vl_file_copy example"
|
@echo "-- vl_file_copy example"
|
||||||
$(PYTHON) vl_file_copy -odir copied top.v
|
$(PYTHON3) vl_file_copy -odir copied top.v
|
||||||
@cmp copied/top.v top.v
|
@cmp copied/top.v top.v
|
||||||
@cmp copied/sub.v sub.v
|
@cmp copied/sub.v sub.v
|
||||||
|
|
||||||
test-vl_hier_graph:
|
test-vl_hier_graph:
|
||||||
@echo "-- vl_hier_graph example"
|
@echo "-- vl_hier_graph example"
|
||||||
$(PYTHON) vl_hier_graph -o graph.dot top.v
|
$(PYTHON3) vl_hier_graph -o graph.dot top.v
|
||||||
@echo "Manually run: " $(DOT) -Tpdf -o graph.pdf graph.dot
|
@echo "Manually run: " $(DOT) -Tpdf -o graph.pdf graph.dot
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|||||||
@@ -10,24 +10,29 @@ import sys
|
|||||||
import tempfile
|
import tempfile
|
||||||
import xml.etree.ElementTree as ET
|
import xml.etree.ElementTree as ET
|
||||||
from shutil import copy2
|
from shutil import copy2
|
||||||
from pprint import pprint,pformat
|
from pprint import pprint, pformat
|
||||||
|
|
||||||
#######################################################################
|
#######################################################################
|
||||||
|
|
||||||
|
|
||||||
class VlFileCopy:
|
class VlFileCopy:
|
||||||
def __init__(self,
|
def __init__(
|
||||||
verilator_args, # presently all verilator options are passed-thru
|
self,
|
||||||
# ideally this script would check against options mentioned in help
|
verilator_args, # presently all verilator options are passed-thru
|
||||||
debug=0,
|
# ideally this script would check against options mentioned in help
|
||||||
output_dir='copied'): # directory name we output file uses
|
debug=0,
|
||||||
|
output_dir='copied'): # directory name we output file uses
|
||||||
self.debug = debug
|
self.debug = debug
|
||||||
|
|
||||||
xml_temp = tempfile.NamedTemporaryFile()
|
xml_temp = tempfile.NamedTemporaryFile()
|
||||||
|
|
||||||
args = ['--xml-output', xml_temp.name,
|
args = [
|
||||||
'--bbox-sys', # Parse some stuff can't translate
|
'--xml-output',
|
||||||
'--bbox-unsup',
|
xml_temp.name,
|
||||||
'--prefix vlxml'] # So we know name of .xml output
|
'--bbox-sys', # Parse some stuff can't translate
|
||||||
|
'--bbox-unsup',
|
||||||
|
'--prefix vlxml'
|
||||||
|
] # So we know name of .xml output
|
||||||
args += verilator_args
|
args += verilator_args
|
||||||
self.run_verilator(args)
|
self.run_verilator(args)
|
||||||
self.tree = ET.parse(xml_temp.name)
|
self.tree = ET.parse(xml_temp.name)
|
||||||
@@ -55,16 +60,18 @@ class VlFileCopy:
|
|||||||
print("\t%s " % command)
|
print("\t%s " % command)
|
||||||
status = subprocess.call(command, shell=True)
|
status = subprocess.call(command, shell=True)
|
||||||
if status != 0:
|
if status != 0:
|
||||||
raise Exception("Command failed running Verilator with '"+command+"', stopped")
|
raise Exception("Command failed running Verilator with '" +
|
||||||
|
command + "', stopped")
|
||||||
|
|
||||||
|
|
||||||
#######################################################################
|
#######################################################################
|
||||||
|
|
||||||
if __name__=='__main__':
|
if __name__ == '__main__':
|
||||||
parser = argparse.ArgumentParser(
|
parser = argparse.ArgumentParser(
|
||||||
allow_abbrev=False,
|
allow_abbrev=False,
|
||||||
formatter_class=argparse.RawTextHelpFormatter,
|
formatter_class=argparse.RawTextHelpFormatter,
|
||||||
description=
|
description=
|
||||||
"""Example of using Verilator XML output to copy a list of files to an
|
"""Example of using Verilator XML output to copy a list of files to an
|
||||||
output directory (-odir, defaults to 'copied'), e.g. to easily create a
|
output directory (-odir, defaults to 'copied'), e.g. to easily create a
|
||||||
tarball of the design to pass to others.
|
tarball of the design to pass to others.
|
||||||
|
|
||||||
@@ -72,8 +79,7 @@ Example usage:
|
|||||||
vl_file_copy -f input.vc top.v -odir mycopy
|
vl_file_copy -f input.vc top.v -odir mycopy
|
||||||
# This will make at least mycopy/top.v
|
# This will make at least mycopy/top.v
|
||||||
""",
|
""",
|
||||||
epilog=
|
epilog="""All other arguments are pass-thru to Verilator: e.g.:
|
||||||
"""All other arguments are pass-thru to Verilator: e.g.:
|
|
||||||
|
|
||||||
+define+<var>=<value> Set preprocessor define
|
+define+<var>=<value> Set preprocessor define
|
||||||
-F <file> Parse options from a file, relatively
|
-F <file> Parse options from a file, relatively
|
||||||
@@ -87,26 +93,30 @@ Example usage:
|
|||||||
This file ONLY is placed under the Creative Commons Public Domain, for
|
This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
any use, without warranty, 2019 by Wilson Snyder.
|
any use, without warranty, 2019 by Wilson Snyder.
|
||||||
SPDX-License-Identifier: CC0-1.0
|
SPDX-License-Identifier: CC0-1.0
|
||||||
"""
|
""")
|
||||||
)
|
parser.add_argument('-debug',
|
||||||
parser.add_argument('-debug', '--debug',
|
'--debug',
|
||||||
action='store_const', const=9,
|
action='store_const',
|
||||||
|
const=9,
|
||||||
help='enable debug')
|
help='enable debug')
|
||||||
parser.add_argument('-odir', '--odir',
|
parser.add_argument('-odir',
|
||||||
action='store', metavar='directory', required=True,
|
'--odir',
|
||||||
|
action='store',
|
||||||
|
metavar='directory',
|
||||||
|
required=True,
|
||||||
help='target output directory')
|
help='target output directory')
|
||||||
(args, rem) = parser.parse_known_args()
|
(args, rem) = parser.parse_known_args()
|
||||||
|
|
||||||
print("NOTE: vl_file_copy is only an example starting point for writing your own tool.")
|
print(
|
||||||
|
"NOTE: vl_file_copy is only an example starting point for writing your own tool."
|
||||||
|
)
|
||||||
# That is:
|
# That is:
|
||||||
# 1. We will accept basic patches
|
# 1. We will accept basic patches
|
||||||
# 2. We are not expecting to make this globally useful. (e.g. we don't cleanup obj_dir)
|
# 2. We are not expecting to make this globally useful. (e.g. we don't cleanup obj_dir)
|
||||||
# 3. "make install" will not install this.
|
# 3. "make install" will not install this.
|
||||||
# 4. This has not had production-worthy validation.
|
# 4. This has not had production-worthy validation.
|
||||||
|
|
||||||
fc = VlFileCopy(output_dir = args.odir,
|
fc = VlFileCopy(output_dir=args.odir, debug=args.debug, verilator_args=rem)
|
||||||
debug = args.debug,
|
|
||||||
verilator_args = rem)
|
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
### Local Variables:
|
### Local Variables:
|
||||||
|
|||||||
@@ -10,26 +10,31 @@ import sys
|
|||||||
import tempfile
|
import tempfile
|
||||||
import xml.etree.ElementTree as ET
|
import xml.etree.ElementTree as ET
|
||||||
from shutil import copy2
|
from shutil import copy2
|
||||||
from pprint import pprint,pformat
|
from pprint import pprint, pformat
|
||||||
|
|
||||||
#######################################################################
|
#######################################################################
|
||||||
|
|
||||||
|
|
||||||
class VlHierGraph:
|
class VlHierGraph:
|
||||||
def __init__(self,
|
def __init__(
|
||||||
verilator_args, # presently all verilator options are passed-thru
|
self,
|
||||||
# ideally this script would check against options mentioned in help
|
verilator_args, # presently all verilator options are passed-thru
|
||||||
debug=0,
|
# ideally this script would check against options mentioned in help
|
||||||
output_filename='graph.dot'): # output filename
|
debug=0,
|
||||||
|
output_filename='graph.dot'): # output filename
|
||||||
self.debug = debug
|
self.debug = debug
|
||||||
self.next_vertex_number = 0
|
self.next_vertex_number = 0
|
||||||
self.name_to_number = {}
|
self.name_to_number = {}
|
||||||
|
|
||||||
xml_temp = tempfile.NamedTemporaryFile()
|
xml_temp = tempfile.NamedTemporaryFile()
|
||||||
|
|
||||||
args = ['--xml-output', xml_temp.name,
|
args = [
|
||||||
'--bbox-sys', # Parse some stuff can't translate
|
'--xml-output',
|
||||||
'--bbox-unsup',
|
xml_temp.name,
|
||||||
'--prefix vlxml'] # So we know name of .xml output
|
'--bbox-sys', # Parse some stuff can't translate
|
||||||
|
'--bbox-unsup',
|
||||||
|
'--prefix vlxml'
|
||||||
|
] # So we know name of .xml output
|
||||||
args += verilator_args
|
args += verilator_args
|
||||||
self.run_verilator(args)
|
self.run_verilator(args)
|
||||||
self.tree = ET.parse(xml_temp.name)
|
self.tree = ET.parse(xml_temp.name)
|
||||||
@@ -39,7 +44,9 @@ class VlHierGraph:
|
|||||||
fh.write("digraph {\n")
|
fh.write("digraph {\n")
|
||||||
fh.write(" dpi=300;\n")
|
fh.write(" dpi=300;\n")
|
||||||
fh.write(" order=LR;\n")
|
fh.write(" order=LR;\n")
|
||||||
fh.write(" node [fontsize=8 shape=\"box\" margin=0.01 width=0 height=0]")
|
fh.write(
|
||||||
|
" node [fontsize=8 shape=\"box\" margin=0.01 width=0 height=0]"
|
||||||
|
)
|
||||||
fh.write(" edge [fontsize=6]")
|
fh.write(" edge [fontsize=6]")
|
||||||
# Find cells
|
# Find cells
|
||||||
root = self.tree.getroot()
|
root = self.tree.getroot()
|
||||||
@@ -48,8 +55,7 @@ class VlHierGraph:
|
|||||||
# origNames are before parameterization, name if after
|
# origNames are before parameterization, name if after
|
||||||
mod_name = module.get('name')
|
mod_name = module.get('name')
|
||||||
mod_number = self.name_to_vertex_number(mod_name)
|
mod_number = self.name_to_vertex_number(mod_name)
|
||||||
fh.write(" n%d [label=\"%s\""
|
fh.write(" n%d [label=\"%s\"" % (mod_number, mod_name))
|
||||||
% (mod_number, mod_name))
|
|
||||||
if module.get('topModule'):
|
if module.get('topModule'):
|
||||||
fh.write(" color=\"red\" rank=1")
|
fh.write(" color=\"red\" rank=1")
|
||||||
fh.write("];\n")
|
fh.write("];\n")
|
||||||
@@ -58,8 +64,8 @@ class VlHierGraph:
|
|||||||
inst_name = instance.get('name')
|
inst_name = instance.get('name')
|
||||||
def_name = instance.get('defName')
|
def_name = instance.get('defName')
|
||||||
def_number = self.name_to_vertex_number(def_name)
|
def_number = self.name_to_vertex_number(def_name)
|
||||||
fh.write(" n%d->n%d [label=\"%s\"];\n"
|
fh.write(" n%d->n%d [label=\"%s\"];\n" %
|
||||||
% (mod_number, def_number, inst_name));
|
(mod_number, def_number, inst_name))
|
||||||
|
|
||||||
fh.write("}\n")
|
fh.write("}\n")
|
||||||
|
|
||||||
@@ -80,24 +86,25 @@ class VlHierGraph:
|
|||||||
print("\t%s " % command)
|
print("\t%s " % command)
|
||||||
status = subprocess.call(command, shell=True)
|
status = subprocess.call(command, shell=True)
|
||||||
if status != 0:
|
if status != 0:
|
||||||
raise Exception("Command failed running Verilator with '"+command+"', stopped")
|
raise Exception("Command failed running Verilator with '" +
|
||||||
|
command + "', stopped")
|
||||||
|
|
||||||
|
|
||||||
#######################################################################
|
#######################################################################
|
||||||
|
|
||||||
if __name__=='__main__':
|
if __name__ == '__main__':
|
||||||
parser = argparse.ArgumentParser(
|
parser = argparse.ArgumentParser(
|
||||||
allow_abbrev=False,
|
allow_abbrev=False,
|
||||||
formatter_class=argparse.RawTextHelpFormatter,
|
formatter_class=argparse.RawTextHelpFormatter,
|
||||||
description=
|
description=
|
||||||
"""Example of using Verilator XML output to create a .dot file showing the
|
"""Example of using Verilator XML output to create a .dot file showing the
|
||||||
design module hierarchy.
|
design module hierarchy.
|
||||||
|
|
||||||
Example usage:
|
Example usage:
|
||||||
vl_hier_graph -f input.vc top.v -o graph.dot
|
vl_hier_graph -f input.vc top.v -o graph.dot
|
||||||
dot -Tpdf -o graph.pdf graph.dot
|
dot -Tpdf -o graph.pdf graph.dot
|
||||||
""",
|
""",
|
||||||
epilog=
|
epilog="""All other arguments are pass-thru to Verilator: e.g.:
|
||||||
"""All other arguments are pass-thru to Verilator: e.g.:
|
|
||||||
|
|
||||||
+define+<var>=<value> Set preprocessor define
|
+define+<var>=<value> Set preprocessor define
|
||||||
-F <file> Parse options from a file, relatively
|
-F <file> Parse options from a file, relatively
|
||||||
@@ -111,26 +118,32 @@ Example usage:
|
|||||||
This file ONLY is placed under the Creative Commons Public Domain, for
|
This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
any use, without warranty, 2019 by Wilson Snyder.
|
any use, without warranty, 2019 by Wilson Snyder.
|
||||||
SPDX-License-Identifier: CC0-1.0
|
SPDX-License-Identifier: CC0-1.0
|
||||||
"""
|
""")
|
||||||
)
|
parser.add_argument('-debug',
|
||||||
parser.add_argument('-debug', '--debug',
|
'--debug',
|
||||||
action='store_const', const=9,
|
action='store_const',
|
||||||
|
const=9,
|
||||||
help='enable debug')
|
help='enable debug')
|
||||||
parser.add_argument('-o', '--o',
|
parser.add_argument('-o',
|
||||||
action='store', metavar='filename', required=True,
|
'--o',
|
||||||
|
action='store',
|
||||||
|
metavar='filename',
|
||||||
|
required=True,
|
||||||
help='output filename')
|
help='output filename')
|
||||||
(args, rem) = parser.parse_known_args()
|
(args, rem) = parser.parse_known_args()
|
||||||
|
|
||||||
print("NOTE: vl_hier_graph is only an example starting point for writing your own tool.")
|
print(
|
||||||
|
"NOTE: vl_hier_graph is only an example starting point for writing your own tool."
|
||||||
|
)
|
||||||
# That is:
|
# That is:
|
||||||
# 1. We will accept basic patches
|
# 1. We will accept basic patches
|
||||||
# 2. We are not expecting to make this globally useful. (e.g. we don't cleanup obj_dir)
|
# 2. We are not expecting to make this globally useful. (e.g. we don't cleanup obj_dir)
|
||||||
# 3. "make install" will not install this.
|
# 3. "make install" will not install this.
|
||||||
# 4. This has not had production-worthy validation.
|
# 4. This has not had production-worthy validation.
|
||||||
|
|
||||||
fc = VlHierGraph(output_filename = args.o,
|
fc = VlHierGraph(output_filename=args.o,
|
||||||
debug = args.debug,
|
debug=args.debug,
|
||||||
verilator_args = rem)
|
verilator_args=rem)
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
### Local Variables:
|
### Local Variables:
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
/* config.h.in. Generated from configure.ac by autoheader. */
|
/* config.h.in. Generated from configure.ac by autoheader. */
|
||||||
|
|
||||||
/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix). */
|
/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix). */
|
||||||
#if !defined(__MINGW32__)
|
#if !defined(__MINGW32__) && !defined(__FreeBSD__)
|
||||||
# define HAVE_ALLOCA_H 1
|
# define HAVE_ALLOCA_H 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -794,6 +794,7 @@ pthread_t thread;
|
|||||||
pthread_attr_t thread_attr;
|
pthread_attr_t thread_attr;
|
||||||
struct fstWriterContext *xc_parent;
|
struct fstWriterContext *xc_parent;
|
||||||
#endif
|
#endif
|
||||||
|
unsigned in_pthread : 1;
|
||||||
|
|
||||||
size_t fst_orig_break_size;
|
size_t fst_orig_break_size;
|
||||||
size_t fst_orig_break_add_size;
|
size_t fst_orig_break_add_size;
|
||||||
@@ -1805,19 +1806,23 @@ xc->already_in_flush = 0;
|
|||||||
static void *fstWriterFlushContextPrivate1(void *ctx)
|
static void *fstWriterFlushContextPrivate1(void *ctx)
|
||||||
{
|
{
|
||||||
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
|
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
|
||||||
|
struct fstWriterContext *xc_parent;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&(xc->xc_parent->mutex));
|
||||||
fstWriterFlushContextPrivate2(xc);
|
fstWriterFlushContextPrivate2(xc);
|
||||||
|
|
||||||
pthread_mutex_unlock(&(xc->xc_parent->mutex));
|
|
||||||
|
|
||||||
#ifdef FST_REMOVE_DUPLICATE_VC
|
#ifdef FST_REMOVE_DUPLICATE_VC
|
||||||
free(xc->curval_mem);
|
free(xc->curval_mem);
|
||||||
#endif
|
#endif
|
||||||
free(xc->valpos_mem);
|
free(xc->valpos_mem);
|
||||||
free(xc->vchg_mem);
|
free(xc->vchg_mem);
|
||||||
tmpfile_close(&xc->tchn_handle, &xc->tchn_handle_nam);
|
tmpfile_close(&xc->tchn_handle, &xc->tchn_handle_nam);
|
||||||
|
xc_parent = xc->xc_parent;
|
||||||
free(xc);
|
free(xc);
|
||||||
|
|
||||||
|
xc_parent->in_pthread = 0;
|
||||||
|
pthread_mutex_unlock(&(xc_parent->mutex));
|
||||||
|
|
||||||
return(NULL);
|
return(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1865,7 +1870,15 @@ if(xc->parallel_enabled)
|
|||||||
xc->section_header_only = 0;
|
xc->section_header_only = 0;
|
||||||
xc->secnum++;
|
xc->secnum++;
|
||||||
|
|
||||||
|
while (xc->in_pthread)
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&xc->mutex);
|
||||||
|
pthread_mutex_unlock(&xc->mutex);
|
||||||
|
};
|
||||||
|
|
||||||
pthread_mutex_lock(&xc->mutex);
|
pthread_mutex_lock(&xc->mutex);
|
||||||
|
xc->in_pthread = 1;
|
||||||
|
pthread_mutex_unlock(&xc->mutex);
|
||||||
|
|
||||||
pthread_create(&xc->thread, &xc->thread_attr, fstWriterFlushContextPrivate1, xc2);
|
pthread_create(&xc->thread, &xc->thread_attr, fstWriterFlushContextPrivate1, xc2);
|
||||||
}
|
}
|
||||||
@@ -1947,6 +1960,12 @@ if(xc && !xc->already_in_close && !xc->already_in_flush)
|
|||||||
#ifdef FST_WRITER_PARALLEL
|
#ifdef FST_WRITER_PARALLEL
|
||||||
pthread_mutex_lock(&xc->mutex);
|
pthread_mutex_lock(&xc->mutex);
|
||||||
pthread_mutex_unlock(&xc->mutex);
|
pthread_mutex_unlock(&xc->mutex);
|
||||||
|
|
||||||
|
while (xc->in_pthread)
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&xc->mutex);
|
||||||
|
pthread_mutex_unlock(&xc->mutex);
|
||||||
|
};
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+628
-437
File diff suppressed because it is too large
Load Diff
+205
-145
@@ -1,7 +1,7 @@
|
|||||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2020 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2021 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// 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,7 +61,7 @@
|
|||||||
|
|
||||||
// Version check
|
// Version check
|
||||||
#if defined(SYSTEMC_VERSION) && (SYSTEMC_VERSION < 20111121)
|
#if defined(SYSTEMC_VERSION) && (SYSTEMC_VERSION < 20111121)
|
||||||
# warning "Verilator soon requires SystemC 2.3.*; see manual for deprecated other versions."
|
# warning "Verilator requires SystemC 2.3.* or newer."
|
||||||
#endif
|
#endif
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
@@ -84,10 +84,6 @@ typedef EData 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 SpTraceVcdCFile;
|
|
||||||
class VerilatedEvalMsgQueue;
|
class VerilatedEvalMsgQueue;
|
||||||
class VerilatedScopeNameMap;
|
class VerilatedScopeNameMap;
|
||||||
class VerilatedVar;
|
class VerilatedVar;
|
||||||
@@ -98,7 +94,7 @@ class VerilatedVcdSc;
|
|||||||
class VerilatedFst;
|
class VerilatedFst;
|
||||||
class VerilatedFstC;
|
class VerilatedFstC;
|
||||||
|
|
||||||
enum VerilatedVarType {
|
enum VerilatedVarType : vluint8_t {
|
||||||
VLVT_UNKNOWN = 0,
|
VLVT_UNKNOWN = 0,
|
||||||
VLVT_PTR, // Pointer to something
|
VLVT_PTR, // Pointer to something
|
||||||
VLVT_UINT8, // AKA CData
|
VLVT_UINT8, // AKA CData
|
||||||
@@ -133,12 +129,12 @@ extern vluint32_t VL_THREAD_ID() VL_MT_SAFE;
|
|||||||
#define VL_LOCK_SPINS 50000 /// Number of times to spin for a mutex before relaxing
|
#define VL_LOCK_SPINS 50000 /// Number of times to spin for a mutex before relaxing
|
||||||
|
|
||||||
/// Mutex, wrapped to allow -fthread_safety checks
|
/// Mutex, wrapped to allow -fthread_safety checks
|
||||||
class VL_CAPABILITY("mutex") VerilatedMutex {
|
class VL_CAPABILITY("mutex") VerilatedMutex final {
|
||||||
private:
|
private:
|
||||||
std::mutex m_mutex; // Mutex
|
std::mutex m_mutex; // Mutex
|
||||||
public:
|
public:
|
||||||
VerilatedMutex() {}
|
VerilatedMutex() = default;
|
||||||
~VerilatedMutex() {}
|
~VerilatedMutex() = default;
|
||||||
const VerilatedMutex& operator!() const { return *this; } // For -fthread_safety
|
const VerilatedMutex& operator!() const { return *this; } // For -fthread_safety
|
||||||
/// Acquire/lock mutex
|
/// Acquire/lock mutex
|
||||||
void lock() VL_ACQUIRE() {
|
void lock() VL_ACQUIRE() {
|
||||||
@@ -159,7 +155,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// Lock guard for mutex (ala std::unique_lock), wrapped to allow -fthread_safety checks
|
/// Lock guard for mutex (ala std::unique_lock), wrapped to allow -fthread_safety checks
|
||||||
class VL_SCOPED_CAPABILITY VerilatedLockGuard {
|
class VL_SCOPED_CAPABILITY VerilatedLockGuard final {
|
||||||
VL_UNCOPYABLE(VerilatedLockGuard);
|
VL_UNCOPYABLE(VerilatedLockGuard);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -167,7 +163,7 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
explicit VerilatedLockGuard(VerilatedMutex& mutexr) VL_ACQUIRE(mutexr)
|
explicit VerilatedLockGuard(VerilatedMutex& mutexr) VL_ACQUIRE(mutexr)
|
||||||
: m_mutexr(mutexr) {
|
: m_mutexr(mutexr) { // Need () or GCC 4.8 false warning
|
||||||
m_mutexr.lock();
|
m_mutexr.lock();
|
||||||
}
|
}
|
||||||
~VerilatedLockGuard() VL_RELEASE() { m_mutexr.unlock(); }
|
~VerilatedLockGuard() VL_RELEASE() { m_mutexr.unlock(); }
|
||||||
@@ -178,19 +174,19 @@ public:
|
|||||||
#else // !VL_THREADED
|
#else // !VL_THREADED
|
||||||
|
|
||||||
/// Empty non-threaded mutex to avoid #ifdefs in consuming code
|
/// Empty non-threaded mutex to avoid #ifdefs in consuming code
|
||||||
class VerilatedMutex {
|
class VerilatedMutex final {
|
||||||
public:
|
public:
|
||||||
void lock() {}
|
void lock() {}
|
||||||
void unlock() {}
|
void unlock() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Empty non-threaded lock guard to avoid #ifdefs in consuming code
|
/// Empty non-threaded lock guard to avoid #ifdefs in consuming code
|
||||||
class VerilatedLockGuard {
|
class VerilatedLockGuard final {
|
||||||
VL_UNCOPYABLE(VerilatedLockGuard);
|
VL_UNCOPYABLE(VerilatedLockGuard);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit VerilatedLockGuard(VerilatedMutex&) {}
|
explicit VerilatedLockGuard(VerilatedMutex&) {}
|
||||||
~VerilatedLockGuard() {}
|
~VerilatedLockGuard() = default;
|
||||||
void lock() {}
|
void lock() {}
|
||||||
void unlock() {}
|
void unlock() {}
|
||||||
};
|
};
|
||||||
@@ -198,7 +194,7 @@ public:
|
|||||||
#endif // VL_THREADED
|
#endif // VL_THREADED
|
||||||
|
|
||||||
/// Remember the calling thread at construction time, and make sure later calls use same thread
|
/// Remember the calling thread at construction time, and make sure later calls use same thread
|
||||||
class VerilatedAssertOneThread {
|
class VerilatedAssertOneThread final {
|
||||||
// MEMBERS
|
// MEMBERS
|
||||||
#if defined(VL_THREADED) && defined(VL_DEBUG)
|
#if defined(VL_THREADED) && defined(VL_DEBUG)
|
||||||
vluint32_t m_threadid; /// Thread that is legal
|
vluint32_t m_threadid; /// Thread that is legal
|
||||||
@@ -207,7 +203,7 @@ public:
|
|||||||
/// The constructor establishes the thread id for all later calls.
|
/// The constructor establishes the thread id for all later calls.
|
||||||
/// If necessary, a different class could be made that inits it otherwise.
|
/// If necessary, a different class could be made that inits it otherwise.
|
||||||
VerilatedAssertOneThread()
|
VerilatedAssertOneThread()
|
||||||
: m_threadid(VL_THREAD_ID()) {}
|
: m_threadid{VL_THREAD_ID()} {}
|
||||||
~VerilatedAssertOneThread() { check(); }
|
~VerilatedAssertOneThread() { check(); }
|
||||||
// METHODS
|
// METHODS
|
||||||
/// Check that the current thread ID is the same as the construction thread ID
|
/// Check that the current thread ID is the same as the construction thread ID
|
||||||
@@ -234,7 +230,7 @@ public:
|
|||||||
|
|
||||||
class VerilatedScope;
|
class VerilatedScope;
|
||||||
|
|
||||||
class VerilatedModule {
|
class VerilatedModule VL_NOT_FINAL {
|
||||||
VL_UNCOPYABLE(VerilatedModule);
|
VL_UNCOPYABLE(VerilatedModule);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -273,7 +269,8 @@ 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) class modname : public VerilatedModule
|
#define VL_MODULE(modname) class modname VL_NOT_FINAL : public VerilatedModule
|
||||||
|
// Not class final in VL_MODULE, as users might be abstracting our models (--hierarchical)
|
||||||
|
|
||||||
/// Constructor, ala SC_CTOR
|
/// Constructor, ala SC_CTOR
|
||||||
#define VL_CTOR(modname) modname(const char* __VCname = "")
|
#define VL_CTOR(modname) modname(const char* __VCname = "")
|
||||||
@@ -302,7 +299,7 @@ public:
|
|||||||
//===========================================================================
|
//===========================================================================
|
||||||
/// Verilator symbol table base class
|
/// Verilator symbol table base class
|
||||||
|
|
||||||
class VerilatedSyms {
|
class VerilatedSyms VL_NOT_FINAL {
|
||||||
public: // But for internal use only
|
public: // But for internal use only
|
||||||
#ifdef VL_THREADED
|
#ifdef VL_THREADED
|
||||||
VerilatedEvalMsgQueue* __Vm_evalMsgQp;
|
VerilatedEvalMsgQueue* __Vm_evalMsgQp;
|
||||||
@@ -315,32 +312,32 @@ public: // But for internal use only
|
|||||||
/// Verilator global class information class
|
/// Verilator global class information class
|
||||||
/// This class is initialized by main thread only. Reading post-init is thread safe.
|
/// This class is initialized by main thread only. Reading post-init is thread safe.
|
||||||
|
|
||||||
class VerilatedScope {
|
class VerilatedScope final {
|
||||||
public:
|
public:
|
||||||
typedef enum {
|
typedef enum : vluint8_t {
|
||||||
SCOPE_MODULE,
|
SCOPE_MODULE,
|
||||||
SCOPE_OTHER
|
SCOPE_OTHER
|
||||||
} Type; // Type of a scope, currently module is only interesting
|
} Type; // Type of a scope, currently module is only interesting
|
||||||
private:
|
private:
|
||||||
// Fastpath:
|
// Fastpath:
|
||||||
VerilatedSyms* m_symsp; ///< Symbol table
|
VerilatedSyms* m_symsp = nullptr; ///< Symbol table
|
||||||
void** m_callbacksp; ///< Callback table pointer (Fastpath)
|
void** m_callbacksp = nullptr; ///< Callback table pointer (Fastpath)
|
||||||
int m_funcnumMax; ///< Maxium function number stored (Fastpath)
|
int m_funcnumMax = 0; ///< Maxium function number stored (Fastpath)
|
||||||
// 4 bytes padding (on -m64), for rent.
|
// 4 bytes padding (on -m64), for rent.
|
||||||
VerilatedVarNameMap* m_varsp; ///< Variable map
|
VerilatedVarNameMap* m_varsp = nullptr; ///< Variable map
|
||||||
const char* m_namep; ///< Scope name (Slowpath)
|
const char* m_namep = nullptr; ///< Scope name (Slowpath)
|
||||||
const char* m_identifierp; ///< Identifier of scope (with escapes removed)
|
const char* m_identifierp = nullptr; ///< Identifier of scope (with escapes removed)
|
||||||
vlsint8_t m_timeunit; ///< Timeunit in negative power-of-10
|
vlsint8_t m_timeunit = 0; ///< Timeunit in negative power-of-10
|
||||||
Type m_type; ///< Type of the scope
|
Type m_type = SCOPE_OTHER; ///< Type of the scope
|
||||||
|
|
||||||
public: // But internals only - called from VerilatedModule's
|
public: // But internals only - called from VerilatedModule's
|
||||||
VerilatedScope();
|
VerilatedScope() = default;
|
||||||
~VerilatedScope();
|
~VerilatedScope();
|
||||||
void configure(VerilatedSyms* symsp, const char* prefixp, const char* suffixp,
|
void configure(VerilatedSyms* symsp, const char* prefixp, const char* suffixp,
|
||||||
const char* identifier, vlsint8_t timeunit, const Type type) VL_MT_UNSAFE;
|
const char* identifier, vlsint8_t timeunit, const Type& type) VL_MT_UNSAFE;
|
||||||
void exportInsert(int finalize, const char* namep, void* cb) VL_MT_UNSAFE;
|
void exportInsert(int finalize, const char* namep, void* cb) VL_MT_UNSAFE;
|
||||||
void varInsert(int finalize, const char* namep, void* datap, VerilatedVarType vltype,
|
void varInsert(int finalize, const char* namep, void* datap, bool isParam,
|
||||||
int vlflags, int dims, ...) VL_MT_UNSAFE;
|
VerilatedVarType vltype, int vlflags, int dims, ...) VL_MT_UNSAFE;
|
||||||
// ACCESSORS
|
// ACCESSORS
|
||||||
const char* name() const { return m_namep; }
|
const char* name() const { return m_namep; }
|
||||||
const char* identifier() const { return m_identifierp; }
|
const char* identifier() const { return m_identifierp; }
|
||||||
@@ -363,20 +360,19 @@ public: // But internals only - called from VerilatedModule's
|
|||||||
Type type() const { return m_type; }
|
Type type() const { return m_type; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class VerilatedHierarchy {
|
class VerilatedHierarchy final {
|
||||||
public:
|
public:
|
||||||
void add(VerilatedScope* fromp, VerilatedScope* top);
|
static void add(VerilatedScope* fromp, VerilatedScope* top);
|
||||||
|
static void remove(VerilatedScope* fromp, VerilatedScope* top);
|
||||||
};
|
};
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
/// Verilator global static information class
|
/// Verilator global static information class
|
||||||
|
|
||||||
class Verilated {
|
class Verilated final {
|
||||||
// MEMBERS
|
// MEMBERS
|
||||||
// Slow path variables
|
// Slow path variables
|
||||||
static VerilatedMutex m_mutex; ///< Mutex for s_s/s_ns members, when VL_THREADED
|
static VerilatedMutex s_mutex; ///< Mutex for s_s/s_ns members, when VL_THREADED
|
||||||
|
|
||||||
static VerilatedVoidCb s_flushCb; ///< Flush callback function
|
|
||||||
|
|
||||||
static struct Serialized { // All these members serialized/deserialized
|
static struct Serialized { // All these members serialized/deserialized
|
||||||
// Fast path
|
// Fast path
|
||||||
@@ -386,54 +382,56 @@ class Verilated {
|
|||||||
bool s_assertOn; ///< Assertions are enabled
|
bool s_assertOn; ///< Assertions are enabled
|
||||||
bool s_fatalOnVpiError; ///< Stop on vpi error/unsupported
|
bool s_fatalOnVpiError; ///< Stop on vpi error/unsupported
|
||||||
// Slow path
|
// Slow path
|
||||||
unsigned s_timeunit : 4; ///< Time unit as 0..15
|
vlsint8_t s_timeunit; ///< Time unit as 0..15
|
||||||
unsigned s_timeprecision : 4; ///< Time precision as 0..15
|
vlsint8_t s_timeprecision; ///< Time precision as 0..15
|
||||||
int s_errorCount; ///< Number of errors
|
int s_errorCount; ///< Number of errors
|
||||||
int s_errorLimit; ///< Stop on error number
|
int s_errorLimit; ///< Stop on error number
|
||||||
int s_randReset; ///< Random reset: 0=all 0s, 1=all 1s, 2=random
|
int s_randReset; ///< Random reset: 0=all 0s, 1=all 1s, 2=random
|
||||||
int s_randSeed; ///< Random seed: 0=random
|
int s_randSeed; ///< Random seed: 0=random
|
||||||
|
int s_randSeedEpoch; ///< Number incrementing on each reseed, 0=illegal
|
||||||
Serialized();
|
Serialized();
|
||||||
~Serialized() {}
|
~Serialized() = default;
|
||||||
} s_s;
|
} s_s;
|
||||||
|
|
||||||
static struct NonSerialized { // Non-serialized information
|
static struct NonSerialized { // Non-serialized information
|
||||||
// These are reloaded from on command-line settings, so do not need to persist
|
// These are reloaded from on command-line settings, so do not need to persist
|
||||||
// Fast path
|
// Fast path
|
||||||
vluint64_t s_profThreadsStart; ///< +prof+threads starting time
|
vluint64_t s_profThreadsStart = 1; ///< +prof+threads starting time
|
||||||
vluint32_t s_profThreadsWindow; ///< +prof+threads window size
|
vluint32_t s_profThreadsWindow = 2; ///< +prof+threads window size
|
||||||
// Slow path
|
// Slow path
|
||||||
const char* s_profThreadsFilenamep; ///< +prof+threads filename
|
const char* s_profThreadsFilenamep; ///< +prof+threads filename
|
||||||
NonSerialized();
|
void setup();
|
||||||
~NonSerialized();
|
void teardown();
|
||||||
} s_ns;
|
} s_ns;
|
||||||
|
|
||||||
// no need to be save-restored (serialized) the
|
// no need to be save-restored (serialized) the
|
||||||
// assumption is that the restore is allowed to pass different arguments
|
// assumption is that the restore is allowed to pass different arguments
|
||||||
static struct CommandArgValues {
|
static struct CommandArgValues {
|
||||||
VerilatedMutex m_argMutex; ///< Mutex for s_args members, when VL_THREADED
|
VerilatedMutex m_argMutex; ///< Mutex for s_args members, when VL_THREADED
|
||||||
int argc;
|
int argc = 0;
|
||||||
const char** argv;
|
const char** argv = nullptr;
|
||||||
CommandArgValues()
|
CommandArgValues() = default;
|
||||||
: argc(0)
|
~CommandArgValues() = default;
|
||||||
, argv(NULL) {}
|
|
||||||
~CommandArgValues() {}
|
|
||||||
} s_args;
|
} s_args;
|
||||||
|
|
||||||
// Not covered by mutex, as per-thread
|
// Not covered by mutex, as per-thread
|
||||||
static VL_THREAD_LOCAL struct ThreadLocal {
|
static VL_THREAD_LOCAL struct ThreadLocal {
|
||||||
#ifdef VL_THREADED
|
#ifdef VL_THREADED
|
||||||
vluint32_t t_mtaskId; ///< Current mtask# executing on this thread
|
vluint32_t t_mtaskId = 0; ///< Current mtask# executing on this thread
|
||||||
vluint32_t t_endOfEvalReqd; ///< Messages may be pending, thread needs endOf-eval calls
|
vluint32_t t_endOfEvalReqd
|
||||||
|
= 0; ///< Messages may be pending, thread needs endOf-eval calls
|
||||||
#endif
|
#endif
|
||||||
const VerilatedScope* t_dpiScopep; ///< DPI context scope
|
const VerilatedScope* t_dpiScopep = nullptr; ///< DPI context scope
|
||||||
const char* t_dpiFilename; ///< DPI context filename
|
const char* t_dpiFilename = nullptr; ///< DPI context filename
|
||||||
int t_dpiLineno; ///< DPI context line number
|
int t_dpiLineno = 0; ///< DPI context line number
|
||||||
|
|
||||||
ThreadLocal();
|
ThreadLocal() = default;
|
||||||
~ThreadLocal();
|
~ThreadLocal() = default;
|
||||||
} t_s;
|
} t_s;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
friend struct VerilatedInitializer;
|
||||||
|
|
||||||
// CONSTRUCTORS
|
// CONSTRUCTORS
|
||||||
VL_UNCOPYABLE(Verilated);
|
VL_UNCOPYABLE(Verilated);
|
||||||
|
|
||||||
@@ -449,6 +447,9 @@ public:
|
|||||||
static int randReset() VL_MT_SAFE { return s_s.s_randReset; } ///< Return randReset value
|
static int randReset() VL_MT_SAFE { return s_s.s_randReset; } ///< Return randReset value
|
||||||
static void randSeed(int val) VL_MT_SAFE;
|
static void randSeed(int val) VL_MT_SAFE;
|
||||||
static int randSeed() VL_MT_SAFE { return s_s.s_randSeed; } ///< Return randSeed value
|
static int randSeed() VL_MT_SAFE { return s_s.s_randSeed; } ///< Return randSeed value
|
||||||
|
static vluint32_t randSeedEpoch() VL_MT_SAFE { return s_s.s_randSeedEpoch; }
|
||||||
|
/// Random seed extended to 64 bits, and defaulted if user seed==0
|
||||||
|
static vluint64_t randSeedDefault64() VL_MT_SAFE;
|
||||||
|
|
||||||
/// Enable debug of internal verilated code
|
/// Enable debug of internal verilated code
|
||||||
static void debug(int level) VL_MT_SAFE;
|
static void debug(int level) VL_MT_SAFE;
|
||||||
@@ -459,7 +460,7 @@ public:
|
|||||||
static inline int debug() VL_MT_SAFE { return s_s.s_debug; }
|
static inline int debug() VL_MT_SAFE { return s_s.s_debug; }
|
||||||
#else
|
#else
|
||||||
/// Return constant 0 debug level, so C++'s optimizer rips up
|
/// Return constant 0 debug level, so C++'s optimizer rips up
|
||||||
static inline int debug() VL_PURE { return 0; }
|
static constexpr int debug() VL_PURE { return 0; }
|
||||||
#endif
|
#endif
|
||||||
/// Enable calculation of unused signals
|
/// Enable calculation of unused signals
|
||||||
static void calcUnusedSigs(bool flag) VL_MT_SAFE;
|
static void calcUnusedSigs(bool flag) VL_MT_SAFE;
|
||||||
@@ -501,9 +502,16 @@ public:
|
|||||||
static void profThreadsFilenamep(const char* flagp) VL_MT_SAFE;
|
static void profThreadsFilenamep(const char* flagp) VL_MT_SAFE;
|
||||||
static const char* profThreadsFilenamep() VL_MT_SAFE { return s_ns.s_profThreadsFilenamep; }
|
static const char* profThreadsFilenamep() VL_MT_SAFE { return s_ns.s_profThreadsFilenamep; }
|
||||||
|
|
||||||
/// Flush callback for VCD waves
|
typedef void (*VoidPCb)(void*); // Callback type for below
|
||||||
static void flushCb(VerilatedVoidCb cb) VL_MT_SAFE;
|
/// Callbacks to run on global flush
|
||||||
static void flushCall() VL_MT_SAFE;
|
static void addFlushCb(VoidPCb cb, void* datap) VL_MT_SAFE;
|
||||||
|
static void removeFlushCb(VoidPCb cb, void* datap) VL_MT_SAFE;
|
||||||
|
static void runFlushCallbacks() VL_MT_SAFE;
|
||||||
|
static void flushCall() VL_MT_SAFE { runFlushCallbacks(); } // Deprecated
|
||||||
|
/// Callbacks to run prior to termination
|
||||||
|
static void addExitCb(VoidPCb cb, void* datap) VL_MT_SAFE;
|
||||||
|
static void removeExitCb(VoidPCb cb, void* datap) VL_MT_SAFE;
|
||||||
|
static void runExitCallbacks() VL_MT_SAFE;
|
||||||
|
|
||||||
/// Record command line arguments, for retrieval by $test$plusargs/$value$plusargs,
|
/// Record command line arguments, for retrieval by $test$plusargs/$value$plusargs,
|
||||||
/// and for parsing +verilator+ run-time arguments.
|
/// and for parsing +verilator+ run-time arguments.
|
||||||
@@ -561,14 +569,14 @@ public:
|
|||||||
t_s.t_dpiFilename = filenamep;
|
t_s.t_dpiFilename = filenamep;
|
||||||
t_s.t_dpiLineno = lineno;
|
t_s.t_dpiLineno = lineno;
|
||||||
}
|
}
|
||||||
static void dpiClearContext() VL_MT_SAFE { t_s.t_dpiScopep = NULL; }
|
static void dpiClearContext() VL_MT_SAFE { t_s.t_dpiScopep = nullptr; }
|
||||||
static bool dpiInContext() VL_MT_SAFE { return t_s.t_dpiScopep != NULL; }
|
static bool dpiInContext() VL_MT_SAFE { return t_s.t_dpiScopep != nullptr; }
|
||||||
static const char* dpiFilenamep() VL_MT_SAFE { return t_s.t_dpiFilename; }
|
static const char* dpiFilenamep() VL_MT_SAFE { return t_s.t_dpiFilename; }
|
||||||
static int dpiLineno() VL_MT_SAFE { return t_s.t_dpiLineno; }
|
static int dpiLineno() VL_MT_SAFE { return t_s.t_dpiLineno; }
|
||||||
static int exportFuncNum(const char* namep) VL_MT_SAFE;
|
static int exportFuncNum(const char* namep) VL_MT_SAFE;
|
||||||
|
|
||||||
static size_t serialized1Size() VL_PURE { return sizeof(s_s); }
|
static constexpr size_t serialized1Size() VL_PURE { return sizeof(s_s); }
|
||||||
static void* serialized1Ptr() VL_MT_UNSAFE { return &s_s; } // Unsafe, for Serialize only
|
static constexpr void* serialized1Ptr() VL_MT_UNSAFE { return &s_s; } // For Serialize only
|
||||||
static size_t serialized2Size() VL_PURE;
|
static size_t serialized2Size() VL_PURE;
|
||||||
static void* serialized2Ptr() VL_MT_UNSAFE;
|
static void* serialized2Ptr() VL_MT_UNSAFE;
|
||||||
#ifdef VL_THREADED
|
#ifdef VL_THREADED
|
||||||
@@ -644,9 +652,20 @@ extern void VL_PRINTF_MT(const char* formatp, ...) VL_ATTR_PRINTF(1) VL_MT_SAFE;
|
|||||||
/// Print a debug message from internals with standard prefix, with printf style format
|
/// Print a debug message from internals with standard prefix, with printf style format
|
||||||
extern void VL_DBG_MSGF(const char* formatp, ...) VL_ATTR_PRINTF(1) VL_MT_SAFE;
|
extern void VL_DBG_MSGF(const char* formatp, ...) VL_ATTR_PRINTF(1) VL_MT_SAFE;
|
||||||
|
|
||||||
extern IData VL_RANDOM_I(int obits); ///< Randomize a signal
|
extern vluint64_t vl_rand64() VL_MT_SAFE;
|
||||||
extern QData VL_RANDOM_Q(int obits); ///< Randomize a signal
|
inline IData VL_RANDOM_I(int obits) VL_MT_SAFE { return vl_rand64() & VL_MASK_I(obits); }
|
||||||
|
inline QData VL_RANDOM_Q(int obits) VL_MT_SAFE { return vl_rand64() & VL_MASK_Q(obits); }
|
||||||
extern WDataOutP VL_RANDOM_W(int obits, WDataOutP outwp); ///< Randomize a signal
|
extern WDataOutP VL_RANDOM_W(int obits, WDataOutP outwp); ///< Randomize a signal
|
||||||
|
extern IData VL_RANDOM_SEEDED_II(int obits, IData seed) VL_MT_SAFE;
|
||||||
|
inline IData VL_URANDOM_RANGE_I(IData hi, IData lo) {
|
||||||
|
vluint64_t rnd = vl_rand64();
|
||||||
|
if (VL_LIKELY(hi > lo)) {
|
||||||
|
// Modulus isn't very fast but it's common that hi-low is power-of-two
|
||||||
|
return (rnd % (hi - lo + 1)) + lo;
|
||||||
|
} else {
|
||||||
|
return (rnd % (lo - hi + 1)) + hi;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Init time only, so slow is fine
|
/// Init time only, so slow is fine
|
||||||
extern IData VL_RAND_RESET_I(int obits); ///< Random reset a signal
|
extern IData VL_RAND_RESET_I(int obits); ///< Random reset a signal
|
||||||
@@ -673,13 +692,9 @@ extern WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, WDataInP lwp, WDataInP r
|
|||||||
/// File I/O
|
/// File I/O
|
||||||
extern IData VL_FGETS_IXI(int obits, void* destp, IData fpi);
|
extern IData VL_FGETS_IXI(int obits, void* destp, IData fpi);
|
||||||
|
|
||||||
extern IData VL_FOPEN_S(const char* filenamep, const char* modep);
|
extern void VL_FFLUSH_I(IData fdi);
|
||||||
extern IData VL_FOPEN_WI(int fnwords, WDataInP filenamep, IData mode);
|
extern IData VL_FSEEK_I(IData fdi, IData offset, IData origin);
|
||||||
extern IData VL_FOPEN_QI(QData filename, IData mode);
|
extern IData VL_FTELL_I(IData fdi);
|
||||||
inline IData VL_FOPEN_II(IData filename, IData mode) VL_MT_SAFE {
|
|
||||||
return VL_FOPEN_QI(filename, mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern void VL_FCLOSE_I(IData fdi);
|
extern void VL_FCLOSE_I(IData fdi);
|
||||||
|
|
||||||
extern IData VL_FREAD_I(int width, int array_lsb, int array_size, void* memp, IData fpi,
|
extern IData VL_FREAD_I(int width, int array_lsb, int array_size, void* memp, IData fpi,
|
||||||
@@ -711,7 +726,7 @@ extern const char* vl_mc_scan_plusargs(const char* prefixp); // PLIish
|
|||||||
|
|
||||||
/// Return true if data[bit] set; not 0/1 return, but 0/non-zero return.
|
/// Return true if data[bit] set; not 0/1 return, but 0/non-zero return.
|
||||||
#define VL_BITISSET_I(data, bit) ((data) & (VL_UL(1) << VL_BITBIT_I(bit)))
|
#define VL_BITISSET_I(data, bit) ((data) & (VL_UL(1) << VL_BITBIT_I(bit)))
|
||||||
#define VL_BITISSET_Q(data, bit) ((data) & (VL_ULL(1) << VL_BITBIT_Q(bit)))
|
#define VL_BITISSET_Q(data, bit) ((data) & (1ULL << VL_BITBIT_Q(bit)))
|
||||||
#define VL_BITISSET_E(data, bit) ((data) & (VL_EUL(1) << VL_BITBIT_E(bit)))
|
#define VL_BITISSET_E(data, bit) ((data) & (VL_EUL(1) << VL_BITBIT_E(bit)))
|
||||||
#define VL_BITISSET_W(data, bit) ((data)[VL_BITWORD_E(bit)] & (VL_EUL(1) << VL_BITBIT_E(bit)))
|
#define VL_BITISSET_W(data, bit) ((data)[VL_BITWORD_E(bit)] & (VL_EUL(1) << VL_BITBIT_E(bit)))
|
||||||
#define VL_BITISSETLIMIT_W(data, width, bit) (((bit) < (width)) && VL_BITISSET_W(data, bit))
|
#define VL_BITISSETLIMIT_W(data, width, bit) (((bit) < (width)) && VL_BITISSET_W(data, bit))
|
||||||
@@ -722,22 +737,22 @@ extern const char* vl_mc_scan_plusargs(const char* prefixp); // PLIish
|
|||||||
/// Create two 32-bit words from quadword
|
/// Create two 32-bit words from quadword
|
||||||
/// WData is always at least 2 words; does not clean upper bits
|
/// WData is always at least 2 words; does not clean upper bits
|
||||||
#define VL_SET_WQ(owp, data) \
|
#define VL_SET_WQ(owp, data) \
|
||||||
{ \
|
do { \
|
||||||
(owp)[0] = static_cast<IData>(data); \
|
(owp)[0] = static_cast<IData>(data); \
|
||||||
(owp)[1] = static_cast<IData>((data) >> VL_EDATASIZE); \
|
(owp)[1] = static_cast<IData>((data) >> VL_EDATASIZE); \
|
||||||
}
|
} while (false)
|
||||||
#define VL_SET_WI(owp, data) \
|
#define VL_SET_WI(owp, data) \
|
||||||
{ \
|
do { \
|
||||||
(owp)[0] = static_cast<IData>(data); \
|
(owp)[0] = static_cast<IData>(data); \
|
||||||
(owp)[1] = 0; \
|
(owp)[1] = 0; \
|
||||||
}
|
} while (false)
|
||||||
#define VL_SET_QW(lwp) \
|
#define VL_SET_QW(lwp) \
|
||||||
((static_cast<QData>((lwp)[0])) \
|
((static_cast<QData>((lwp)[0])) \
|
||||||
| (static_cast<QData>((lwp)[1]) << (static_cast<QData>(VL_EDATASIZE))))
|
| (static_cast<QData>((lwp)[1]) << (static_cast<QData>(VL_EDATASIZE))))
|
||||||
#define _VL_SET_QII(ld, rd) ((static_cast<QData>(ld) << VL_ULL(32)) | static_cast<QData>(rd))
|
#define _VL_SET_QII(ld, rd) ((static_cast<QData>(ld) << 32ULL) | static_cast<QData>(rd))
|
||||||
|
|
||||||
/// Return FILE* from IData
|
/// Return FILE* from IData
|
||||||
extern FILE* VL_CVT_I_FP(IData lhs);
|
extern FILE* VL_CVT_I_FP(IData lhs) VL_MT_SAFE;
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
// Use a union to avoid cast-to-different-size warnings
|
// Use a union to avoid cast-to-different-size warnings
|
||||||
@@ -747,9 +762,9 @@ static inline void* VL_CVT_Q_VP(QData lhs) VL_PURE {
|
|||||||
u.q = lhs;
|
u.q = lhs;
|
||||||
return u.fp;
|
return u.fp;
|
||||||
}
|
}
|
||||||
/// Return QData from void*
|
/// Return QData from const void*
|
||||||
static inline QData VL_CVT_VP_Q(void* fp) VL_PURE {
|
static inline QData VL_CVT_VP_Q(const void* fp) VL_PURE {
|
||||||
union { void* fp; QData q; } u;
|
union { const void* fp; QData q; } u;
|
||||||
u.q = 0;
|
u.q = 0;
|
||||||
u.fp = fp;
|
u.fp = fp;
|
||||||
return u.q;
|
return u.q;
|
||||||
@@ -768,9 +783,27 @@ static inline QData VL_CVT_Q_D(double lhs) VL_PURE {
|
|||||||
}
|
}
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
/// Return double from QData (numeric)
|
/// Return double from lhs (numeric) unsigned
|
||||||
static inline double VL_ITOR_D_I(IData lhs) VL_PURE {
|
double VL_ITOR_D_W(int lbits, WDataInP lwp) VL_PURE;
|
||||||
return static_cast<double>(static_cast<vlsint32_t>(lhs));
|
static inline double VL_ITOR_D_I(int, IData lhs) VL_PURE {
|
||||||
|
return static_cast<double>(static_cast<vluint32_t>(lhs));
|
||||||
|
}
|
||||||
|
static inline double VL_ITOR_D_Q(int, QData lhs) VL_PURE {
|
||||||
|
return static_cast<double>(static_cast<vluint64_t>(lhs));
|
||||||
|
}
|
||||||
|
/// Return double from lhs (numeric) signed
|
||||||
|
double VL_ISTOR_D_W(int lbits, WDataInP lwp) VL_PURE;
|
||||||
|
static inline double VL_ISTOR_D_I(int lbits, IData lhs) VL_PURE {
|
||||||
|
if (lbits == 32) return static_cast<double>(static_cast<vlsint32_t>(lhs));
|
||||||
|
WData lwp[VL_WQ_WORDS_E];
|
||||||
|
VL_SET_WI(lwp, lhs);
|
||||||
|
return VL_ISTOR_D_W(lbits, lwp);
|
||||||
|
}
|
||||||
|
static inline double VL_ISTOR_D_Q(int lbits, QData lhs) VL_PURE {
|
||||||
|
if (lbits == 64) return static_cast<double>(static_cast<vlsint64_t>(lhs));
|
||||||
|
WData lwp[VL_WQ_WORDS_E];
|
||||||
|
VL_SET_WQ(lwp, lhs);
|
||||||
|
return VL_ISTOR_D_W(lbits, lwp);
|
||||||
}
|
}
|
||||||
/// Return QData from double (numeric)
|
/// Return QData from double (numeric)
|
||||||
static inline IData VL_RTOI_I_D(double lhs) VL_PURE {
|
static inline IData VL_RTOI_I_D(double lhs) VL_PURE {
|
||||||
@@ -780,7 +813,7 @@ static inline IData VL_RTOI_I_D(double lhs) VL_PURE {
|
|||||||
// 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)
|
||||||
#define VL_SIGN_I(nbits, lhs) ((lhs) >> VL_BITBIT_I((nbits)-VL_UL(1)))
|
#define VL_SIGN_I(nbits, lhs) ((lhs) >> VL_BITBIT_I((nbits)-VL_UL(1)))
|
||||||
#define VL_SIGN_Q(nbits, lhs) ((lhs) >> VL_BITBIT_Q((nbits)-VL_ULL(1)))
|
#define VL_SIGN_Q(nbits, lhs) ((lhs) >> VL_BITBIT_Q((nbits)-1ULL))
|
||||||
#define VL_SIGN_E(nbits, lhs) ((lhs) >> VL_BITBIT_E((nbits)-VL_EUL(1)))
|
#define VL_SIGN_E(nbits, lhs) ((lhs) >> VL_BITBIT_E((nbits)-VL_EUL(1)))
|
||||||
#define VL_SIGN_W(nbits, rwp) \
|
#define VL_SIGN_W(nbits, rwp) \
|
||||||
((rwp)[VL_BITWORD_E((nbits)-VL_EUL(1))] >> VL_BITBIT_E((nbits)-VL_EUL(1)))
|
((rwp)[VL_BITWORD_E((nbits)-VL_EUL(1))] >> VL_BITBIT_E((nbits)-VL_EUL(1)))
|
||||||
@@ -792,7 +825,7 @@ static inline IData VL_EXTENDSIGN_I(int lbits, IData lhs) VL_PURE {
|
|||||||
return (-((lhs) & (VL_UL(1) << (lbits - 1))));
|
return (-((lhs) & (VL_UL(1) << (lbits - 1))));
|
||||||
}
|
}
|
||||||
static inline QData VL_EXTENDSIGN_Q(int lbits, QData lhs) VL_PURE {
|
static inline QData VL_EXTENDSIGN_Q(int lbits, QData lhs) VL_PURE {
|
||||||
return (-((lhs) & (VL_ULL(1) << (lbits - 1))));
|
return (-((lhs) & (1ULL << (lbits - 1))));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Debugging prints
|
// Debugging prints
|
||||||
@@ -823,13 +856,8 @@ extern int VL_TIME_STR_CONVERT(const char* strp) VL_PURE;
|
|||||||
|
|
||||||
/// Return current simulation time
|
/// Return current simulation time
|
||||||
#if defined(SYSTEMC_VERSION)
|
#if defined(SYSTEMC_VERSION)
|
||||||
# if SYSTEMC_VERSION > 20011000
|
|
||||||
// Already defined: extern sc_time sc_time_stamp();
|
// Already defined: extern sc_time sc_time_stamp();
|
||||||
inline vluint64_t vl_time_stamp64() { return sc_time_stamp().value(); }
|
inline vluint64_t vl_time_stamp64() { return sc_time_stamp().value(); }
|
||||||
# else // Before SystemC changed to integral time representation
|
|
||||||
// Already defined: extern double sc_time_stamp();
|
|
||||||
inline vluint64_t vl_time_stamp64() { return static_cast<vluint64_t>(sc_time_stamp()); }
|
|
||||||
# endif
|
|
||||||
#else // Non-SystemC
|
#else // Non-SystemC
|
||||||
# ifdef VL_TIME_STAMP64
|
# ifdef VL_TIME_STAMP64
|
||||||
extern vluint64_t vl_time_stamp64();
|
extern vluint64_t vl_time_stamp64();
|
||||||
@@ -847,7 +875,7 @@ inline vluint64_t vl_time_stamp64() { return static_cast<vluint64_t>(sc_time_sta
|
|||||||
// Optimized assuming scale is always constant.
|
// Optimized assuming scale is always constant.
|
||||||
// Can't use multiply in Q flavor, as might lose precision
|
// Can't use multiply in Q flavor, as might lose precision
|
||||||
#define VL_TIME_UNITED_Q(scale) (VL_TIME_Q() / static_cast<QData>(scale))
|
#define VL_TIME_UNITED_Q(scale) (VL_TIME_Q() / static_cast<QData>(scale))
|
||||||
#define VL_TIME_UNITED_D(scale) (VL_TIME_D() * (1.0 / (scale)))
|
#define VL_TIME_UNITED_D(scale) (VL_TIME_D() / static_cast<double>(scale))
|
||||||
/// Time imported from units to time precision
|
/// Time imported from units to time precision
|
||||||
double vl_time_multiplier(int scale);
|
double vl_time_multiplier(int scale);
|
||||||
|
|
||||||
@@ -930,8 +958,7 @@ static inline void VL_ASSIGNBIT_II(int, int bit, IData& lhsr, IData rhs) VL_PURE
|
|||||||
lhsr = ((lhsr & ~(VL_UL(1) << VL_BITBIT_I(bit))) | (rhs << VL_BITBIT_I(bit)));
|
lhsr = ((lhsr & ~(VL_UL(1) << VL_BITBIT_I(bit))) | (rhs << VL_BITBIT_I(bit)));
|
||||||
}
|
}
|
||||||
static inline void VL_ASSIGNBIT_QI(int, int bit, QData& lhsr, QData rhs) VL_PURE {
|
static inline void VL_ASSIGNBIT_QI(int, int bit, QData& lhsr, QData rhs) VL_PURE {
|
||||||
lhsr = ((lhsr & ~(VL_ULL(1) << VL_BITBIT_Q(bit)))
|
lhsr = ((lhsr & ~(1ULL << VL_BITBIT_Q(bit))) | (static_cast<QData>(rhs) << VL_BITBIT_Q(bit)));
|
||||||
| (static_cast<QData>(rhs) << VL_BITBIT_Q(bit)));
|
|
||||||
}
|
}
|
||||||
static inline void VL_ASSIGNBIT_WI(int, int bit, WDataOutP owp, IData rhs) VL_MT_SAFE {
|
static inline void VL_ASSIGNBIT_WI(int, int bit, WDataOutP owp, IData rhs) VL_MT_SAFE {
|
||||||
EData orig = owp[VL_BITWORD_E(bit)];
|
EData orig = owp[VL_BITWORD_E(bit)];
|
||||||
@@ -949,7 +976,7 @@ static inline void VL_ASSIGNBIT_IO(int, int bit, IData& lhsr, IData) VL_PURE {
|
|||||||
lhsr = (lhsr | (VL_UL(1) << VL_BITBIT_I(bit)));
|
lhsr = (lhsr | (VL_UL(1) << VL_BITBIT_I(bit)));
|
||||||
}
|
}
|
||||||
static inline void VL_ASSIGNBIT_QO(int, int bit, QData& lhsr, IData) VL_PURE {
|
static inline void VL_ASSIGNBIT_QO(int, int bit, QData& lhsr, IData) VL_PURE {
|
||||||
lhsr = (lhsr | (VL_ULL(1) << VL_BITBIT_Q(bit)));
|
lhsr = (lhsr | (1ULL << VL_BITBIT_Q(bit)));
|
||||||
}
|
}
|
||||||
static inline void VL_ASSIGNBIT_WO(int, int bit, WDataOutP owp, IData) VL_MT_SAFE {
|
static inline void VL_ASSIGNBIT_WO(int, int bit, WDataOutP owp, IData) VL_MT_SAFE {
|
||||||
EData orig = owp[VL_BITWORD_E(bit)];
|
EData orig = owp[VL_BITWORD_E(bit)];
|
||||||
@@ -1217,6 +1244,36 @@ static inline IData VL_COUNTONES_W(int words, WDataInP lwp) VL_MT_SAFE {
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EMIT_RULE: VL_COUNTBITS_II: oclean = false; lhs clean
|
||||||
|
static inline IData VL_COUNTBITS_I(int lbits, IData lhs, IData ctrl0, IData ctrl1,
|
||||||
|
IData ctrl2) VL_PURE {
|
||||||
|
int ctrlSum = (ctrl0 & 0x1) + (ctrl1 & 0x1) + (ctrl2 & 0x1);
|
||||||
|
if (ctrlSum == 3) {
|
||||||
|
return VL_COUNTONES_I(lhs);
|
||||||
|
} else if (ctrlSum == 0) {
|
||||||
|
IData mask = (lbits == 32) ? -1 : ((1 << lbits) - 1);
|
||||||
|
return VL_COUNTONES_I(~lhs & mask);
|
||||||
|
} else {
|
||||||
|
return (lbits == 32) ? 32 : lbits;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static inline IData VL_COUNTBITS_Q(int lbits, QData lhs, IData ctrl0, IData ctrl1,
|
||||||
|
IData ctrl2) VL_PURE {
|
||||||
|
return VL_COUNTBITS_I(32, static_cast<IData>(lhs), ctrl0, ctrl1, ctrl2)
|
||||||
|
+ VL_COUNTBITS_I(lbits - 32, static_cast<IData>(lhs >> 32), ctrl0, ctrl1, ctrl2);
|
||||||
|
}
|
||||||
|
#define VL_COUNTBITS_E VL_COUNTBITS_I
|
||||||
|
static inline IData VL_COUNTBITS_W(int lbits, int words, WDataInP lwp, IData ctrl0, IData ctrl1,
|
||||||
|
IData ctrl2) VL_MT_SAFE {
|
||||||
|
EData r = 0;
|
||||||
|
IData wordLbits = 32;
|
||||||
|
for (int i = 0; i < words; ++i) {
|
||||||
|
if (i == words - 1) { wordLbits = lbits % 32; }
|
||||||
|
r += VL_COUNTBITS_E(wordLbits, lwp[i], ctrl0, ctrl1, ctrl2);
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
static inline IData VL_ONEHOT_I(IData lhs) VL_PURE {
|
static inline IData VL_ONEHOT_I(IData lhs) VL_PURE {
|
||||||
return (((lhs & (lhs - 1)) == 0) & (lhs != 0));
|
return (((lhs & (lhs - 1)) == 0) & (lhs != 0));
|
||||||
}
|
}
|
||||||
@@ -1261,7 +1318,7 @@ static inline IData VL_CLOG2_Q(QData lhs) VL_PURE {
|
|||||||
if (VL_UNLIKELY(!lhs)) return 0;
|
if (VL_UNLIKELY(!lhs)) return 0;
|
||||||
lhs--;
|
lhs--;
|
||||||
int shifts = 0;
|
int shifts = 0;
|
||||||
for (; lhs != 0; ++shifts) lhs = lhs >> VL_ULL(1);
|
for (; lhs != 0; ++shifts) lhs = lhs >> 1ULL;
|
||||||
return shifts;
|
return shifts;
|
||||||
}
|
}
|
||||||
static inline IData VL_CLOG2_W(int words, WDataInP lwp) VL_MT_SAFE {
|
static inline IData VL_CLOG2_W(int words, WDataInP lwp) VL_MT_SAFE {
|
||||||
@@ -1316,12 +1373,6 @@ static inline WDataOutP VL_XOR_W(int words, WDataOutP owp, WDataInP lwp, WDataIn
|
|||||||
for (int i = 0; (i < words); ++i) owp[i] = (lwp[i] ^ rwp[i]);
|
for (int i = 0; (i < words); ++i) owp[i] = (lwp[i] ^ rwp[i]);
|
||||||
return owp;
|
return owp;
|
||||||
}
|
}
|
||||||
// EMIT_RULE: VL_XNOR: oclean=dirty; obits=lbits; lbits==rbits;
|
|
||||||
static inline WDataOutP VL_XNOR_W(int words, WDataOutP owp, WDataInP lwp,
|
|
||||||
WDataInP rwp) VL_MT_SAFE {
|
|
||||||
for (int i = 0; (i < words); ++i) owp[i] = (lwp[i] ^ ~rwp[i]);
|
|
||||||
return owp;
|
|
||||||
}
|
|
||||||
// EMIT_RULE: VL_NOT: oclean=dirty; obits=lbits;
|
// EMIT_RULE: VL_NOT: oclean=dirty; obits=lbits;
|
||||||
static inline WDataOutP VL_NOT_W(int words, WDataOutP owp, WDataInP lwp) VL_MT_SAFE {
|
static inline WDataOutP VL_NOT_W(int words, WDataOutP owp, WDataInP lwp) VL_MT_SAFE {
|
||||||
for (int i = 0; i < words; ++i) owp[i] = ~(lwp[i]);
|
for (int i = 0; i < words; ++i) owp[i] = ~(lwp[i]);
|
||||||
@@ -1428,6 +1479,7 @@ static inline int _VL_CMPS_W(int lbits, WDataInP lwp, WDataInP rwp) VL_MT_SAFE {
|
|||||||
//=========================================================================
|
//=========================================================================
|
||||||
// Math
|
// Math
|
||||||
|
|
||||||
|
// Output NOT clean
|
||||||
static inline WDataOutP VL_NEGATE_W(int words, WDataOutP owp, WDataInP lwp) VL_MT_SAFE {
|
static inline WDataOutP VL_NEGATE_W(int words, WDataOutP owp, WDataInP lwp) VL_MT_SAFE {
|
||||||
EData carry = 1;
|
EData carry = 1;
|
||||||
for (int i = 0; i < words; ++i) {
|
for (int i = 0; i < words; ++i) {
|
||||||
@@ -1459,8 +1511,8 @@ static inline WDataOutP VL_ADD_W(int words, WDataOutP owp, WDataInP lwp, WDataIn
|
|||||||
QData carry = 0;
|
QData carry = 0;
|
||||||
for (int i = 0; i < words; ++i) {
|
for (int i = 0; i < words; ++i) {
|
||||||
carry = carry + static_cast<QData>(lwp[i]) + static_cast<QData>(rwp[i]);
|
carry = carry + static_cast<QData>(lwp[i]) + static_cast<QData>(rwp[i]);
|
||||||
owp[i] = (carry & VL_ULL(0xffffffff));
|
owp[i] = (carry & 0xffffffffULL);
|
||||||
carry = (carry >> VL_ULL(32)) & VL_ULL(0xffffffff);
|
carry = (carry >> 32ULL) & 0xffffffffULL;
|
||||||
}
|
}
|
||||||
// Last output word is dirty
|
// Last output word is dirty
|
||||||
return owp;
|
return owp;
|
||||||
@@ -1472,8 +1524,8 @@ static inline WDataOutP VL_SUB_W(int words, WDataOutP owp, WDataInP lwp, WDataIn
|
|||||||
carry = (carry + static_cast<QData>(lwp[i])
|
carry = (carry + static_cast<QData>(lwp[i])
|
||||||
+ static_cast<QData>(static_cast<IData>(~rwp[i])));
|
+ static_cast<QData>(static_cast<IData>(~rwp[i])));
|
||||||
if (i == 0) ++carry; // Negation of rwp
|
if (i == 0) ++carry; // Negation of rwp
|
||||||
owp[i] = (carry & VL_ULL(0xffffffff));
|
owp[i] = (carry & 0xffffffffULL);
|
||||||
carry = (carry >> VL_ULL(32)) & VL_ULL(0xffffffff);
|
carry = (carry >> 32ULL) & 0xffffffffULL;
|
||||||
}
|
}
|
||||||
// Last output word is dirty
|
// Last output word is dirty
|
||||||
return owp;
|
return owp;
|
||||||
@@ -1486,8 +1538,8 @@ static inline WDataOutP VL_MUL_W(int words, WDataOutP owp, WDataInP lwp, WDataIn
|
|||||||
QData mul = static_cast<QData>(lwp[lword]) * static_cast<QData>(rwp[rword]);
|
QData mul = static_cast<QData>(lwp[lword]) * static_cast<QData>(rwp[rword]);
|
||||||
for (int qword = lword + rword; qword < words; ++qword) {
|
for (int qword = lword + rword; qword < words; ++qword) {
|
||||||
mul += static_cast<QData>(owp[qword]);
|
mul += static_cast<QData>(owp[qword]);
|
||||||
owp[qword] = (mul & VL_ULL(0xffffffff));
|
owp[qword] = (mul & 0xffffffffULL);
|
||||||
mul = (mul >> VL_ULL(32)) & VL_ULL(0xffffffff);
|
mul = (mul >> 32ULL) & 0xffffffffULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1535,8 +1587,8 @@ static inline WDataOutP VL_MULS_WWW(int, int lbits, int, WDataOutP owp, WDataInP
|
|||||||
for (int i = 0; i < words; ++i) {
|
for (int i = 0; i < words; ++i) {
|
||||||
carry = carry + static_cast<QData>(static_cast<IData>(~owp[i]));
|
carry = carry + static_cast<QData>(static_cast<IData>(~owp[i]));
|
||||||
if (i == 0) ++carry; // Negation of temp2
|
if (i == 0) ++carry; // Negation of temp2
|
||||||
owp[i] = (carry & VL_ULL(0xffffffff));
|
owp[i] = (carry & 0xffffffffULL);
|
||||||
carry = (carry >> VL_ULL(32)) & VL_ULL(0xffffffff);
|
carry = (carry >> 32ULL) & 0xffffffffULL;
|
||||||
}
|
}
|
||||||
// Not needed: owp[words-1] |= 1<<VL_BITBIT_E(lbits-1); // Set sign bit
|
// Not needed: owp[words-1] |= 1<<VL_BITBIT_E(lbits-1); // Set sign bit
|
||||||
}
|
}
|
||||||
@@ -1546,24 +1598,30 @@ static inline WDataOutP VL_MULS_WWW(int, int lbits, int, WDataOutP owp, WDataInP
|
|||||||
|
|
||||||
static inline IData VL_DIVS_III(int lbits, IData lhs, IData rhs) VL_PURE {
|
static inline IData VL_DIVS_III(int lbits, IData lhs, IData rhs) VL_PURE {
|
||||||
if (VL_UNLIKELY(rhs == 0)) return 0;
|
if (VL_UNLIKELY(rhs == 0)) return 0;
|
||||||
|
// -MAX / -1 cannot be represented in twos complement, and will cause SIGFPE
|
||||||
|
if (VL_UNLIKELY(lhs == 0x80000000 && rhs == 0xffffffff)) return 0;
|
||||||
vlsint32_t lhs_signed = VL_EXTENDS_II(VL_IDATASIZE, lbits, lhs);
|
vlsint32_t lhs_signed = VL_EXTENDS_II(VL_IDATASIZE, lbits, lhs);
|
||||||
vlsint32_t rhs_signed = VL_EXTENDS_II(VL_IDATASIZE, lbits, rhs);
|
vlsint32_t rhs_signed = VL_EXTENDS_II(VL_IDATASIZE, lbits, rhs);
|
||||||
return lhs_signed / rhs_signed;
|
return lhs_signed / rhs_signed;
|
||||||
}
|
}
|
||||||
static inline QData VL_DIVS_QQQ(int lbits, QData lhs, QData rhs) VL_PURE {
|
static inline QData VL_DIVS_QQQ(int lbits, QData lhs, QData rhs) VL_PURE {
|
||||||
if (VL_UNLIKELY(rhs == 0)) return 0;
|
if (VL_UNLIKELY(rhs == 0)) return 0;
|
||||||
|
// -MAX / -1 cannot be represented in twos complement, and will cause SIGFPE
|
||||||
|
if (VL_UNLIKELY(lhs == 0x8000000000000000ULL && rhs == 0xffffffffffffffffULL)) return 0;
|
||||||
vlsint64_t lhs_signed = VL_EXTENDS_QQ(VL_QUADSIZE, lbits, lhs);
|
vlsint64_t lhs_signed = VL_EXTENDS_QQ(VL_QUADSIZE, lbits, lhs);
|
||||||
vlsint64_t rhs_signed = VL_EXTENDS_QQ(VL_QUADSIZE, lbits, rhs);
|
vlsint64_t rhs_signed = VL_EXTENDS_QQ(VL_QUADSIZE, lbits, rhs);
|
||||||
return lhs_signed / rhs_signed;
|
return lhs_signed / rhs_signed;
|
||||||
}
|
}
|
||||||
static inline IData VL_MODDIVS_III(int lbits, IData lhs, IData rhs) VL_PURE {
|
static inline IData VL_MODDIVS_III(int lbits, IData lhs, IData rhs) VL_PURE {
|
||||||
if (VL_UNLIKELY(rhs == 0)) return 0;
|
if (VL_UNLIKELY(rhs == 0)) return 0;
|
||||||
|
if (VL_UNLIKELY(lhs == 0x80000000 && rhs == 0xffffffff)) return 0;
|
||||||
vlsint32_t lhs_signed = VL_EXTENDS_II(VL_IDATASIZE, lbits, lhs);
|
vlsint32_t lhs_signed = VL_EXTENDS_II(VL_IDATASIZE, lbits, lhs);
|
||||||
vlsint32_t rhs_signed = VL_EXTENDS_II(VL_IDATASIZE, lbits, rhs);
|
vlsint32_t rhs_signed = VL_EXTENDS_II(VL_IDATASIZE, lbits, rhs);
|
||||||
return lhs_signed % rhs_signed;
|
return lhs_signed % rhs_signed;
|
||||||
}
|
}
|
||||||
static inline QData VL_MODDIVS_QQQ(int lbits, QData lhs, QData rhs) VL_PURE {
|
static inline QData VL_MODDIVS_QQQ(int lbits, QData lhs, QData rhs) VL_PURE {
|
||||||
if (VL_UNLIKELY(rhs == 0)) return 0;
|
if (VL_UNLIKELY(rhs == 0)) return 0;
|
||||||
|
if (VL_UNLIKELY(lhs == 0x8000000000000000ULL && rhs == 0xffffffffffffffffULL)) return 0;
|
||||||
vlsint64_t lhs_signed = VL_EXTENDS_QQ(VL_QUADSIZE, lbits, lhs);
|
vlsint64_t lhs_signed = VL_EXTENDS_QQ(VL_QUADSIZE, lbits, lhs);
|
||||||
vlsint64_t rhs_signed = VL_EXTENDS_QQ(VL_QUADSIZE, lbits, rhs);
|
vlsint64_t rhs_signed = VL_EXTENDS_QQ(VL_QUADSIZE, lbits, rhs);
|
||||||
return lhs_signed % rhs_signed;
|
return lhs_signed % rhs_signed;
|
||||||
@@ -1627,7 +1685,7 @@ static inline IData VL_POW_III(int, int, int rbits, IData lhs, IData rhs) VL_PUR
|
|||||||
IData out = 1;
|
IData out = 1;
|
||||||
for (int i = 0; i < rbits; ++i) {
|
for (int i = 0; i < rbits; ++i) {
|
||||||
if (i > 0) power = power * power;
|
if (i > 0) power = power * power;
|
||||||
if (rhs & (VL_ULL(1) << i)) out *= power;
|
if (rhs & (1ULL << i)) out *= power;
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
@@ -1635,10 +1693,10 @@ static inline QData VL_POW_QQQ(int, int, int rbits, QData lhs, QData rhs) VL_PUR
|
|||||||
if (VL_UNLIKELY(rhs == 0)) return 1;
|
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 = 1ULL;
|
||||||
for (int i = 0; i < rbits; ++i) {
|
for (int i = 0; i < rbits; ++i) {
|
||||||
if (i > 0) power = power * power;
|
if (i > 0) power = power * power;
|
||||||
if (rhs & (VL_ULL(1) << i)) out *= power;
|
if (rhs & (1ULL << i)) out *= power;
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
@@ -1884,7 +1942,8 @@ static inline IData VL_STREAML_FAST_III(int, int lbits, int, IData ld, IData rd_
|
|||||||
case 1: ret = ((ret >> 2) & VL_UL(0x33333333)) | ((ret & VL_UL(0x33333333)) << 2); // 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 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 3: ret = ((ret >> 8) & VL_UL(0x00ff00ff)) | ((ret & VL_UL(0x00ff00ff)) << 8); // FALLTHRU
|
||||||
case 4: ret = ((ret >> 16) | (ret << 16));
|
case 4: ret = ((ret >> 16) | (ret << 16)); // FALLTHRU
|
||||||
|
default:;
|
||||||
}
|
}
|
||||||
return ret >> (VL_IDATASIZE - lbits);
|
return ret >> (VL_IDATASIZE - lbits);
|
||||||
}
|
}
|
||||||
@@ -1896,25 +1955,26 @@ static inline QData VL_STREAML_FAST_QQI(int, int lbits, int, QData ld, IData rd_
|
|||||||
vluint32_t lbitsFloor = lbits & ~VL_MASK_I(rd_log2);
|
vluint32_t lbitsFloor = lbits & ~VL_MASK_I(rd_log2);
|
||||||
vluint32_t lbitsRem = lbits - lbitsFloor;
|
vluint32_t lbitsRem = lbits - lbitsFloor;
|
||||||
QData msbMask = VL_MASK_Q(lbitsRem) << lbitsFloor;
|
QData msbMask = VL_MASK_Q(lbitsRem) << lbitsFloor;
|
||||||
ret = (ret & ~msbMask) | ((ret & msbMask) << ((VL_ULL(1) << rd_log2) - lbitsRem));
|
ret = (ret & ~msbMask) | ((ret & msbMask) << ((1ULL << rd_log2) - lbitsRem));
|
||||||
}
|
}
|
||||||
switch (rd_log2) {
|
switch (rd_log2) {
|
||||||
case 0:
|
case 0:
|
||||||
ret = (((ret >> 1) & VL_ULL(0x5555555555555555))
|
ret = (((ret >> 1) & 0x5555555555555555ULL)
|
||||||
| ((ret & VL_ULL(0x5555555555555555)) << 1)); // FALLTHRU
|
| ((ret & 0x5555555555555555ULL) << 1)); // FALLTHRU
|
||||||
case 1:
|
case 1:
|
||||||
ret = (((ret >> 2) & VL_ULL(0x3333333333333333))
|
ret = (((ret >> 2) & 0x3333333333333333ULL)
|
||||||
| ((ret & VL_ULL(0x3333333333333333)) << 2)); // FALLTHRU
|
| ((ret & 0x3333333333333333ULL) << 2)); // FALLTHRU
|
||||||
case 2:
|
case 2:
|
||||||
ret = (((ret >> 4) & VL_ULL(0x0f0f0f0f0f0f0f0f))
|
ret = (((ret >> 4) & 0x0f0f0f0f0f0f0f0fULL)
|
||||||
| ((ret & VL_ULL(0x0f0f0f0f0f0f0f0f)) << 4)); // FALLTHRU
|
| ((ret & 0x0f0f0f0f0f0f0f0fULL) << 4)); // FALLTHRU
|
||||||
case 3:
|
case 3:
|
||||||
ret = (((ret >> 8) & VL_ULL(0x00ff00ff00ff00ff))
|
ret = (((ret >> 8) & 0x00ff00ff00ff00ffULL)
|
||||||
| ((ret & VL_ULL(0x00ff00ff00ff00ff)) << 8)); // FALLTHRU
|
| ((ret & 0x00ff00ff00ff00ffULL) << 8)); // FALLTHRU
|
||||||
case 4:
|
case 4:
|
||||||
ret = (((ret >> 16) & VL_ULL(0x0000ffff0000ffff))
|
ret = (((ret >> 16) & 0x0000ffff0000ffffULL)
|
||||||
| ((ret & VL_ULL(0x0000ffff0000ffff)) << 16)); // FALLTHRU
|
| ((ret & 0x0000ffff0000ffffULL) << 16)); // FALLTHRU
|
||||||
case 5: ret = ((ret >> 32) | (ret << 32));
|
case 5: ret = ((ret >> 32) | (ret << 32)); // FALLTHRU
|
||||||
|
default:;
|
||||||
}
|
}
|
||||||
return ret >> (VL_QUADSIZE - lbits);
|
return ret >> (VL_QUADSIZE - lbits);
|
||||||
}
|
}
|
||||||
@@ -2358,14 +2418,14 @@ static inline WDataOutP VL_SEL_WWII(int obits, int lbits, int, int, WDataOutP ow
|
|||||||
|
|
||||||
/// Return QData from double (numeric)
|
/// Return QData from double (numeric)
|
||||||
// EMIT_RULE: VL_RTOIROUND_Q_D: oclean=dirty; lclean==clean/real
|
// EMIT_RULE: VL_RTOIROUND_Q_D: oclean=dirty; lclean==clean/real
|
||||||
static inline QData VL_RTOIROUND_Q_D(int bits, double lhs) VL_PURE {
|
static inline QData VL_RTOIROUND_Q_D(int, double lhs) VL_PURE {
|
||||||
// IEEE format: [63]=sign [62:52]=exp+1023 [51:0]=mantissa
|
// IEEE format: [63]=sign [62:52]=exp+1023 [51:0]=mantissa
|
||||||
// This does not need to support subnormals as they are sub-integral
|
// This does not need to support subnormals as they are sub-integral
|
||||||
lhs = VL_ROUND(lhs);
|
lhs = VL_ROUND(lhs);
|
||||||
if (lhs == 0.0) return 0;
|
if (lhs == 0.0) return 0;
|
||||||
QData q = VL_CVT_Q_D(lhs);
|
QData q = VL_CVT_Q_D(lhs);
|
||||||
int lsb = static_cast<int>((q >> VL_ULL(52)) & VL_MASK_Q(11)) - 1023 - 52;
|
int lsb = static_cast<int>((q >> 52ULL) & VL_MASK_Q(11)) - 1023 - 52;
|
||||||
vluint64_t mantissa = (q & VL_MASK_Q(52)) | (VL_ULL(1) << 52);
|
vluint64_t mantissa = (q & VL_MASK_Q(52)) | (1ULL << 52);
|
||||||
vluint64_t out = 0;
|
vluint64_t out = 0;
|
||||||
if (lsb < 0) {
|
if (lsb < 0) {
|
||||||
out = mantissa >> -lsb;
|
out = mantissa >> -lsb;
|
||||||
@@ -2385,8 +2445,8 @@ static inline WDataOutP VL_RTOIROUND_W_D(int obits, WDataOutP owp, double lhs) V
|
|||||||
VL_ZERO_W(obits, owp);
|
VL_ZERO_W(obits, owp);
|
||||||
if (lhs == 0.0) return owp;
|
if (lhs == 0.0) return owp;
|
||||||
QData q = VL_CVT_Q_D(lhs);
|
QData q = VL_CVT_Q_D(lhs);
|
||||||
int lsb = static_cast<int>((q >> VL_ULL(52)) & VL_MASK_Q(11)) - 1023 - 52;
|
int lsb = static_cast<int>((q >> 52ULL) & VL_MASK_Q(11)) - 1023 - 52;
|
||||||
vluint64_t mantissa = (q & VL_MASK_Q(52)) | (VL_ULL(1) << 52);
|
vluint64_t mantissa = (q & VL_MASK_Q(52)) | (1ULL << 52);
|
||||||
if (lsb < 0) {
|
if (lsb < 0) {
|
||||||
VL_SET_WQ(owp, mantissa >> -lsb);
|
VL_SET_WQ(owp, mantissa >> -lsb);
|
||||||
} else if (lsb < obits) {
|
} else if (lsb < obits) {
|
||||||
@@ -2505,25 +2565,25 @@ static inline WDataOutP VL_CONSTHI_W_1X(int obits, int lsb, WDataOutP obase,
|
|||||||
EData d0) VL_MT_SAFE {
|
EData d0) VL_MT_SAFE {
|
||||||
WDataOutP o = obase + VL_WORDS_I(lsb);
|
WDataOutP o = obase + VL_WORDS_I(lsb);
|
||||||
o[0] = d0;
|
o[0] = d0;
|
||||||
_END(obits,1);
|
_END(obits, VL_WORDS_I(lsb) + 1);
|
||||||
}
|
}
|
||||||
static inline WDataOutP VL_CONSTHI_W_2X(int obits, int lsb, WDataOutP obase,
|
static inline WDataOutP VL_CONSTHI_W_2X(int obits, int lsb, WDataOutP obase,
|
||||||
EData d1, EData d0) VL_MT_SAFE {
|
EData d1, EData d0) VL_MT_SAFE {
|
||||||
WDataOutP o = obase + VL_WORDS_I(lsb);
|
WDataOutP o = obase + VL_WORDS_I(lsb);
|
||||||
o[0] = d0; o[1] = d1;
|
o[0] = d0; o[1] = d1;
|
||||||
_END(obits,2);
|
_END(obits, VL_WORDS_I(lsb) + 2);
|
||||||
}
|
}
|
||||||
static inline WDataOutP VL_CONSTHI_W_3X(int obits, int lsb, WDataOutP obase,
|
static inline WDataOutP VL_CONSTHI_W_3X(int obits, int lsb, WDataOutP obase,
|
||||||
EData d2, EData d1, EData d0) VL_MT_SAFE {
|
EData d2, EData d1, EData d0) VL_MT_SAFE {
|
||||||
WDataOutP o = obase + VL_WORDS_I(lsb);
|
WDataOutP o = obase + VL_WORDS_I(lsb);
|
||||||
o[0] = d0; o[1] = d1; o[2] = d2;
|
o[0] = d0; o[1] = d1; o[2] = d2;
|
||||||
_END(obits,3);
|
_END(obits, VL_WORDS_I(lsb) + 3);
|
||||||
}
|
}
|
||||||
static inline WDataOutP VL_CONSTHI_W_4X(int obits, int lsb, WDataOutP obase,
|
static inline WDataOutP VL_CONSTHI_W_4X(int obits, int lsb, WDataOutP obase,
|
||||||
EData d3, EData d2, EData d1, EData d0) VL_MT_SAFE {
|
EData d3, EData d2, EData d1, EData d0) VL_MT_SAFE {
|
||||||
WDataOutP o = obase + VL_WORDS_I(lsb);
|
WDataOutP o = obase + VL_WORDS_I(lsb);
|
||||||
o[0] = d0; o[1] = d1; o[2] = d2; o[3] = d3;
|
o[0] = d0; o[1] = d1; o[2] = d2; o[3] = d3;
|
||||||
_END(obits,4);
|
_END(obits, VL_WORDS_I(lsb) + 4);
|
||||||
}
|
}
|
||||||
static inline WDataOutP VL_CONSTHI_W_5X(int obits, int lsb, WDataOutP obase,
|
static inline WDataOutP VL_CONSTHI_W_5X(int obits, int lsb, WDataOutP obase,
|
||||||
EData d4,
|
EData d4,
|
||||||
@@ -2531,7 +2591,7 @@ static inline WDataOutP VL_CONSTHI_W_5X(int obits, int lsb, WDataOutP obase,
|
|||||||
WDataOutP o = obase + VL_WORDS_I(lsb);
|
WDataOutP o = obase + VL_WORDS_I(lsb);
|
||||||
o[0] = d0; o[1] = d1; o[2] = d2; o[3] = d3;
|
o[0] = d0; o[1] = d1; o[2] = d2; o[3] = d3;
|
||||||
o[4] = d4;
|
o[4] = d4;
|
||||||
_END(obits,5);
|
_END(obits, VL_WORDS_I(lsb) + 5);
|
||||||
}
|
}
|
||||||
static inline WDataOutP VL_CONSTHI_W_6X(int obits, int lsb, WDataOutP obase,
|
static inline WDataOutP VL_CONSTHI_W_6X(int obits, int lsb, WDataOutP obase,
|
||||||
EData d5, EData d4,
|
EData d5, EData d4,
|
||||||
@@ -2539,7 +2599,7 @@ static inline WDataOutP VL_CONSTHI_W_6X(int obits, int lsb, WDataOutP obase,
|
|||||||
WDataOutP o = obase + VL_WORDS_I(lsb);
|
WDataOutP o = obase + VL_WORDS_I(lsb);
|
||||||
o[0] = d0; o[1] = d1; o[2] = d2; o[3] = d3;
|
o[0] = d0; o[1] = d1; o[2] = d2; o[3] = d3;
|
||||||
o[4] = d4; o[5] = d5;
|
o[4] = d4; o[5] = d5;
|
||||||
_END(obits,6);
|
_END(obits, VL_WORDS_I(lsb) + 6);
|
||||||
}
|
}
|
||||||
static inline WDataOutP VL_CONSTHI_W_7X(int obits, int lsb, WDataOutP obase,
|
static inline WDataOutP VL_CONSTHI_W_7X(int obits, int lsb, WDataOutP obase,
|
||||||
EData d6, EData d5, EData d4,
|
EData d6, EData d5, EData d4,
|
||||||
@@ -2547,7 +2607,7 @@ static inline WDataOutP VL_CONSTHI_W_7X(int obits, int lsb, WDataOutP obase,
|
|||||||
WDataOutP o = obase + VL_WORDS_I(lsb);
|
WDataOutP o = obase + VL_WORDS_I(lsb);
|
||||||
o[0] = d0; o[1] = d1; o[2] = d2; o[3] = d3;
|
o[0] = d0; o[1] = d1; o[2] = d2; o[3] = d3;
|
||||||
o[4] = d4; o[5] = d5; o[6] = d6;
|
o[4] = d4; o[5] = d5; o[6] = d6;
|
||||||
_END(obits,7);
|
_END(obits, VL_WORDS_I(lsb) + 7);
|
||||||
}
|
}
|
||||||
static inline WDataOutP VL_CONSTHI_W_8X(int obits, int lsb, WDataOutP obase,
|
static inline WDataOutP VL_CONSTHI_W_8X(int obits, int lsb, WDataOutP obase,
|
||||||
EData d7, EData d6, EData d5, EData d4,
|
EData d7, EData d6, EData d5, EData d4,
|
||||||
@@ -2555,7 +2615,7 @@ static inline WDataOutP VL_CONSTHI_W_8X(int obits, int lsb, WDataOutP obase,
|
|||||||
WDataOutP o = obase + VL_WORDS_I(lsb);
|
WDataOutP o = obase + VL_WORDS_I(lsb);
|
||||||
o[0] = d0; o[1] = d1; o[2] = d2; o[3] = d3;
|
o[0] = d0; o[1] = d1; o[2] = d2; o[3] = d3;
|
||||||
o[4] = d4; o[5] = d5; o[6] = d6; o[7] = d7;
|
o[4] = d4; o[5] = d5; o[6] = d6; o[7] = d7;
|
||||||
_END(obits,8);
|
_END(obits, VL_WORDS_I(lsb) + 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef _END
|
#undef _END
|
||||||
|
|||||||
+67
-43
@@ -2,7 +2,7 @@
|
|||||||
######################################################################
|
######################################################################
|
||||||
# DESCRIPTION: Makefile commands for all verilated target files
|
# DESCRIPTION: Makefile commands for all verilated target files
|
||||||
#
|
#
|
||||||
# Copyright 2003-2020 by Wilson Snyder. This program is free software; you
|
# Copyright 2003-2021 by Wilson Snyder. This program is free software; you
|
||||||
# can redistribute it and/or modify it under the terms of either the GNU
|
# can 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,6 +54,7 @@ VK_CPPFLAGS_ALWAYS += \
|
|||||||
-DVM_COVERAGE=$(VM_COVERAGE) \
|
-DVM_COVERAGE=$(VM_COVERAGE) \
|
||||||
-DVM_SC=$(VM_SC) \
|
-DVM_SC=$(VM_SC) \
|
||||||
-DVM_TRACE=$(VM_TRACE) \
|
-DVM_TRACE=$(VM_TRACE) \
|
||||||
|
-DVM_TRACE_FST=$(VM_TRACE_FST) \
|
||||||
$(CFG_CXXFLAGS_NO_UNUSED) \
|
$(CFG_CXXFLAGS_NO_UNUSED) \
|
||||||
|
|
||||||
ifeq ($(CFG_WITH_CCWARN),yes) # Local... Else don't burden users
|
ifeq ($(CFG_WITH_CCWARN),yes) # Local... Else don't burden users
|
||||||
@@ -84,27 +85,29 @@ CPPFLAGS += $(VM_USER_CFLAGS)
|
|||||||
LDFLAGS += $(VM_USER_LDFLAGS)
|
LDFLAGS += $(VM_USER_LDFLAGS)
|
||||||
LDLIBS += $(VM_USER_LDLIBS)
|
LDLIBS += $(VM_USER_LDLIBS)
|
||||||
|
|
||||||
# See the benchmarking section of bin/verilator.
|
######################################################################
|
||||||
# Support class optimizations. This includes the tracing and symbol table.
|
# Optimization control.
|
||||||
# SystemC takes minutes to optimize, thus it is off by default.
|
|
||||||
#OPT_SLOW =
|
|
||||||
# Fast path optimizations. Most time is spent in these classes.
|
|
||||||
#OPT_FAST = -Os -fstrict-aliasing
|
|
||||||
#OPT_FAST = -O
|
|
||||||
#OPT_FAST =
|
|
||||||
|
|
||||||
#######################################################################
|
# See also the BENCHMARKING & OPTIMIZATION section of the manual.
|
||||||
##### Aggregates
|
|
||||||
|
|
||||||
VM_CLASSES += $(VM_CLASSES_FAST) $(VM_CLASSES_SLOW)
|
# Optimization flags for non performance-critical/rarely executed code.
|
||||||
VM_SUPPORT += $(VM_SUPPORT_FAST) $(VM_SUPPORT_SLOW)
|
# No optimization by default, which improves compilation speed.
|
||||||
|
OPT_SLOW =
|
||||||
|
# Optimization for performance critical/hot code. Most time is spent in these
|
||||||
|
# routines. Optimizing by default for improved execution speed.
|
||||||
|
OPT_FAST = -Os
|
||||||
|
# Optimization applied to the common run-time library used by verilated models.
|
||||||
|
# For compatibility this is called OPT_GLOBAL even though it only applies to
|
||||||
|
# files in the run-time library. Normally there should be no need for the user
|
||||||
|
# to change this as the library is small, but can have significant speed impact.
|
||||||
|
OPT_GLOBAL = -Os
|
||||||
|
|
||||||
#######################################################################
|
#######################################################################
|
||||||
##### SystemC builds
|
##### SystemC builds
|
||||||
|
|
||||||
ifeq ($(VM_SC),1)
|
ifeq ($(VM_SC),1)
|
||||||
CPPFLAGS += $(SYSTEMC_CXX_FLAGS) -I$(SYSTEMC_INCLUDE)
|
CPPFLAGS += $(SYSTEMC_CXX_FLAGS) $(addprefix -I, $(SYSTEMC_INCLUDE))
|
||||||
LDFLAGS += $(SYSTEMC_CXX_FLAGS) -L$(SYSTEMC_LIBDIR)
|
LDFLAGS += $(SYSTEMC_CXX_FLAGS) $(addprefix -L, $(SYSTEMC_LIBDIR))
|
||||||
SC_LIBS = -lsystemc
|
SC_LIBS = -lsystemc
|
||||||
ifneq ($(wildcard $(SYSTEMC_LIBDIR)/*numeric_bit*),)
|
ifneq ($(wildcard $(SYSTEMC_LIBDIR)/*numeric_bit*),)
|
||||||
# Systemc 1.2.1beta
|
# Systemc 1.2.1beta
|
||||||
@@ -163,58 +166,79 @@ ifneq ($(VK_LIBS_THREADED),0)
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
#######################################################################
|
#######################################################################
|
||||||
##### Stub
|
### Aggregates
|
||||||
|
|
||||||
preproc:
|
VM_FAST += $(VM_CLASSES_FAST) $(VM_SUPPORT_FAST)
|
||||||
|
VM_SLOW += $(VM_CLASSES_SLOW) $(VM_SUPPORT_SLOW)
|
||||||
|
|
||||||
#######################################################################
|
#######################################################################
|
||||||
# Overall Objects Linking
|
### Overall Objects Linking
|
||||||
|
|
||||||
VK_CLASSES_FAST_CPP = $(addsuffix .cpp, $(VM_CLASSES_FAST))
|
VK_FAST_OBJS = $(addsuffix .o, $(VM_FAST))
|
||||||
VK_CLASSES_SLOW_CPP = $(addsuffix .cpp, $(VM_CLASSES_SLOW))
|
VK_SLOW_OBJS = $(addsuffix .o, $(VM_SLOW))
|
||||||
|
|
||||||
VK_SUPPORT_FAST_CPP = $(addsuffix .cpp, $(VM_SUPPORT_FAST))
|
|
||||||
VK_SUPPORT_SLOW_CPP = $(addsuffix .cpp, $(VM_SUPPORT_SLOW))
|
|
||||||
|
|
||||||
VK_USER_OBJS = $(addsuffix .o, $(VM_USER_CLASSES))
|
VK_USER_OBJS = $(addsuffix .o, $(VM_USER_CLASSES))
|
||||||
|
|
||||||
|
# Note VM_GLOBAL_FAST and VM_GLOBAL_SLOW holds the files required from the
|
||||||
|
# run-time library. In practice everything is actually in VM_GLOBAL_FAST,
|
||||||
|
# but keeping the distinction for compatibility for now.
|
||||||
VK_GLOBAL_OBJS = $(addsuffix .o, $(VM_GLOBAL_FAST) $(VM_GLOBAL_SLOW))
|
VK_GLOBAL_OBJS = $(addsuffix .o, $(VM_GLOBAL_FAST) $(VM_GLOBAL_SLOW))
|
||||||
|
|
||||||
ifneq ($(VM_PARALLEL_BUILDS),1)
|
ifneq ($(VM_PARALLEL_BUILDS),1)
|
||||||
# Fast building, all .cpp's in one fell swoop
|
# Fast build for small designs: All .cpp files in one fell swoop. This
|
||||||
# This saves about 5 sec per module, but can be slower if only a little changes
|
# saves total compute, but can be slower if only a little changes. It is
|
||||||
VK_OBJS += $(VM_PREFIX)__ALLfast.o $(VM_PREFIX)__ALLslow.o
|
# also a lot slower for medium to large designs when the speed of the C
|
||||||
all_cpp: $(VM_PREFIX)__ALLfast.cpp $(VM_PREFIX)__ALLslow.cpp
|
# compiler dominates, which in this mode is not parallelizable.
|
||||||
$(VM_PREFIX)__ALLfast.cpp: $(VK_CLASSES_FAST_CPP) $(VK_SUPPORT_FAST_CPP)
|
|
||||||
$(VERILATOR_INCLUDER) -DVL_INCLUDE_OPT=include $^ > $@
|
VK_OBJS += $(VM_PREFIX)__ALL.o
|
||||||
$(VM_PREFIX)__ALLslow.cpp: $(VK_CLASSES_SLOW_CPP) $(VK_SUPPORT_SLOW_CPP)
|
$(VM_PREFIX)__ALL.cpp: $(addsuffix .cpp, $(VM_FAST) $(VM_SLOW))
|
||||||
$(VERILATOR_INCLUDER) -DVL_INCLUDE_OPT=include $^ > $@
|
$(VERILATOR_INCLUDER) -DVL_INCLUDE_OPT=include $^ > $@
|
||||||
|
all_cpp: $(VM_PREFIX)__ALL.cpp
|
||||||
else
|
else
|
||||||
#Slow way of building... Each .cpp file by itself
|
# Parallel build: Each .cpp file by itself. This can be somewhat slower for
|
||||||
VK_OBJS += $(addsuffix .o, $(VM_CLASSES) $(VM_SUPPORT))
|
# very small designs and examples, but is a lot faster for large designs.
|
||||||
|
|
||||||
|
VK_OBJS += $(VK_FAST_OBJS) $(VK_SLOW_OBJS)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
$(VM_PREFIX)__ALL.a: $(VK_OBJS)
|
# When archiving just objects (.o), single $(AR) run is enough.
|
||||||
$(AR) -cr $@ $^
|
# When merging objects (.o) and archives (.a), the following steps are taken.
|
||||||
$(RANLIB) $@
|
# 1. Extract object files from .a
|
||||||
|
# 2. Create a new archive from extracted .o and given .o
|
||||||
|
%.a:
|
||||||
|
@echo "Archive $(AR) -cr $@ $^"
|
||||||
|
@if test $(words $(filter %.a,$^)) -eq 0; then \
|
||||||
|
$(AR) -cr $@ $^; \
|
||||||
|
$(RANLIB) $@; \
|
||||||
|
else \
|
||||||
|
$(RM) -rf $*__tmpdir; \
|
||||||
|
for archive in $(filter %.a,$^); do \
|
||||||
|
mkdir -p $*__tmpdir/$$(basename $${archive}); \
|
||||||
|
cd $*__tmpdir/$$(basename $${archive}); \
|
||||||
|
$(AR) -x ../../$${archive}; \
|
||||||
|
cd ../..; \
|
||||||
|
done; \
|
||||||
|
$(AR) -cr $@ $(filter %.o,$^) $*__tmpdir/*/*.o; \
|
||||||
|
$(RM) -rf $*__tmpdir; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
$(VM_PREFIX)__ALL.a: $(VK_OBJS) $(VM_HIER_LIBS)
|
||||||
|
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
### Compile rules
|
### Compile rules
|
||||||
|
|
||||||
ifneq ($(VM_DEFAULT_RULES),0)
|
ifneq ($(VM_DEFAULT_RULES),0)
|
||||||
$(VM_PREFIX)__ALLfast.o: $(VM_PREFIX)__ALLfast.cpp
|
# Anything not in $(VK_SLOW_OBJS) or $(VK_GLOBAL_OBJS), including verilated.o
|
||||||
$(OBJCACHE) $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(OPT_FAST) -c -o $@ $<
|
# and user files passed on the Verilator command line use this rule.
|
||||||
|
|
||||||
$(VM_PREFIX)__ALLslow.o: $(VM_PREFIX)__ALLslow.cpp
|
|
||||||
$(OBJCACHE) $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(OPT_SLOW) -c -o $@ $<
|
|
||||||
|
|
||||||
# VM_GLOBAL_FAST files including verilated.o use this rule
|
|
||||||
%.o: %.cpp
|
%.o: %.cpp
|
||||||
$(OBJCACHE) $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(OPT_FAST) -c -o $@ $<
|
$(OBJCACHE) $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(OPT_FAST) -c -o $@ $<
|
||||||
|
|
||||||
%__Slow.o: %__Slow.cpp
|
$(VK_SLOW_OBJS): %.o: %.cpp
|
||||||
$(OBJCACHE) $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(OPT_SLOW) -c -o $@ $<
|
$(OBJCACHE) $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(OPT_SLOW) -c -o $@ $<
|
||||||
|
|
||||||
|
$(VK_GLOBAL_OBJS): %.o: %.cpp
|
||||||
|
$(OBJCACHE) $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(OPT_GLOBAL) -c -o $@ $<
|
||||||
endif
|
endif
|
||||||
|
|
||||||
#Default rule embedded in make:
|
#Default rule embedded in make:
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2020 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2021 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// 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,7 +1,7 @@
|
|||||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2020 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2021 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// 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.
|
||||||
|
|||||||
+65
-77
@@ -3,7 +3,7 @@
|
|||||||
//
|
//
|
||||||
// THIS MODULE IS PUBLICLY LICENSED
|
// THIS MODULE IS PUBLICLY LICENSED
|
||||||
//
|
//
|
||||||
// Copyright 2001-2020 by Wilson Snyder. This program is free software; you
|
// Copyright 2001-2021 by Wilson Snyder. This program is free software; you
|
||||||
// can redistribute it and/or modify it under the terms of either the GNU
|
// can 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.
|
||||||
@@ -29,7 +29,7 @@
|
|||||||
// VerilatedCovImpBase
|
// VerilatedCovImpBase
|
||||||
/// Implementation base class for constants
|
/// Implementation base class for constants
|
||||||
|
|
||||||
struct VerilatedCovImpBase {
|
struct VerilatedCovImpBase VL_NOT_FINAL {
|
||||||
// TYPES
|
// TYPES
|
||||||
enum { MAX_KEYS = 33 }; /// Maximum user arguments + filename+lineno
|
enum { MAX_KEYS = 33 }; /// Maximum user arguments + filename+lineno
|
||||||
enum { KEY_UNDEF = 0 }; /// Magic key # for unspecified values
|
enum { KEY_UNDEF = 0 }; /// Magic key # for unspecified values
|
||||||
@@ -39,7 +39,7 @@ struct VerilatedCovImpBase {
|
|||||||
// VerilatedCovImpItem
|
// VerilatedCovImpItem
|
||||||
/// Implementation class for a VerilatedCov item
|
/// Implementation class for a VerilatedCov item
|
||||||
|
|
||||||
class VerilatedCovImpItem : VerilatedCovImpBase {
|
class VerilatedCovImpItem VL_NOT_FINAL : VerilatedCovImpBase {
|
||||||
public: // But only local to this file
|
public: // But only local to this file
|
||||||
// MEMBERS
|
// MEMBERS
|
||||||
int m_keys[MAX_KEYS]; ///< Key
|
int m_keys[MAX_KEYS]; ///< Key
|
||||||
@@ -52,7 +52,7 @@ public: // But only local to this file
|
|||||||
m_vals[i] = 0;
|
m_vals[i] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
virtual ~VerilatedCovImpItem() {}
|
virtual ~VerilatedCovImpItem() = default;
|
||||||
virtual vluint64_t count() const = 0;
|
virtual vluint64_t count() const = 0;
|
||||||
virtual void zero() const = 0;
|
virtual void zero() const = 0;
|
||||||
};
|
};
|
||||||
@@ -63,22 +63,22 @@ public: // But only local to this file
|
|||||||
/// This isn't in the header file for auto-magic conversion because it
|
/// This isn't in the header file for auto-magic conversion because it
|
||||||
/// inlines to too much code and makes compilation too slow.
|
/// inlines to too much code and makes compilation too slow.
|
||||||
|
|
||||||
template <class T> class VerilatedCoverItemSpec : public VerilatedCovImpItem {
|
template <class T> class VerilatedCoverItemSpec final : public VerilatedCovImpItem {
|
||||||
private:
|
private:
|
||||||
// MEMBERS
|
// MEMBERS
|
||||||
T* m_countp; ///< Count value
|
T* m_countp; ///< Count value
|
||||||
public:
|
public:
|
||||||
// METHODS
|
// METHODS
|
||||||
// cppcheck-suppress truncLongCastReturn
|
// cppcheck-suppress truncLongCastReturn
|
||||||
virtual vluint64_t count() const VL_OVERRIDE { return *m_countp; }
|
virtual vluint64_t count() const override { return *m_countp; }
|
||||||
virtual void zero() const VL_OVERRIDE { *m_countp = 0; }
|
virtual void zero() const override { *m_countp = 0; }
|
||||||
// CONSTRUCTORS
|
// CONSTRUCTORS
|
||||||
// cppcheck-suppress noExplicitConstructor
|
// cppcheck-suppress noExplicitConstructor
|
||||||
explicit VerilatedCoverItemSpec(T* countp)
|
explicit VerilatedCoverItemSpec(T* countp)
|
||||||
: m_countp(countp) {
|
: m_countp{countp} {
|
||||||
*m_countp = 0;
|
*m_countp = 0;
|
||||||
}
|
}
|
||||||
virtual ~VerilatedCoverItemSpec() VL_OVERRIDE {}
|
virtual ~VerilatedCoverItemSpec() override = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
@@ -87,30 +87,26 @@ public:
|
|||||||
/// All value and keys are indexed into a unique number. Thus we can greatly reduce
|
/// All value and keys are indexed into a unique number. Thus we can greatly reduce
|
||||||
/// the storage requirements for otherwise identical keys.
|
/// the storage requirements for otherwise identical keys.
|
||||||
|
|
||||||
class VerilatedCovImp : VerilatedCovImpBase {
|
class VerilatedCovImp final : VerilatedCovImpBase {
|
||||||
private:
|
private:
|
||||||
// TYPES
|
// TYPES
|
||||||
typedef std::map<std::string, int> ValueIndexMap;
|
typedef std::map<const std::string, int> ValueIndexMap;
|
||||||
typedef std::map<int, std::string> IndexValueMap;
|
typedef std::map<int, std::string> IndexValueMap;
|
||||||
typedef std::deque<VerilatedCovImpItem*> ItemList;
|
typedef std::deque<VerilatedCovImpItem*> ItemList;
|
||||||
|
|
||||||
private:
|
|
||||||
// MEMBERS
|
// MEMBERS
|
||||||
VerilatedMutex m_mutex; ///< Protects all members
|
VerilatedMutex m_mutex; ///< Protects all members
|
||||||
ValueIndexMap m_valueIndexes VL_GUARDED_BY(m_mutex); ///< Unique arbitrary value for values
|
ValueIndexMap m_valueIndexes VL_GUARDED_BY(m_mutex); ///< Unique arbitrary value for values
|
||||||
IndexValueMap m_indexValues VL_GUARDED_BY(m_mutex); ///< Unique arbitrary value for keys
|
IndexValueMap m_indexValues VL_GUARDED_BY(m_mutex); ///< Unique arbitrary value for keys
|
||||||
ItemList m_items VL_GUARDED_BY(m_mutex); ///< List of all items
|
ItemList m_items VL_GUARDED_BY(m_mutex); ///< List of all items
|
||||||
|
int m_nextIndex VL_GUARDED_BY(m_mutex) = (KEY_UNDEF + 1); ///< Next insert value
|
||||||
|
|
||||||
VerilatedCovImpItem* m_insertp VL_GUARDED_BY(m_mutex); ///< Item about to insert
|
VerilatedCovImpItem* m_insertp VL_GUARDED_BY(m_mutex) = nullptr; ///< Item about to insert
|
||||||
const char* m_insertFilenamep VL_GUARDED_BY(m_mutex); ///< Filename about to insert
|
const char* m_insertFilenamep VL_GUARDED_BY(m_mutex) = nullptr; ///< Filename about to insert
|
||||||
int m_insertLineno VL_GUARDED_BY(m_mutex); ///< Line number about to insert
|
int m_insertLineno VL_GUARDED_BY(m_mutex) = 0; ///< Line number about to insert
|
||||||
|
|
||||||
// CONSTRUCTORS
|
// CONSTRUCTORS
|
||||||
VerilatedCovImp() {
|
VerilatedCovImp() = default;
|
||||||
m_insertp = NULL;
|
|
||||||
m_insertFilenamep = NULL;
|
|
||||||
m_insertLineno = 0;
|
|
||||||
}
|
|
||||||
VL_UNCOPYABLE(VerilatedCovImp);
|
VL_UNCOPYABLE(VerilatedCovImp);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -123,14 +119,13 @@ public:
|
|||||||
private:
|
private:
|
||||||
// PRIVATE METHODS
|
// PRIVATE METHODS
|
||||||
int valueIndex(const std::string& value) VL_REQUIRES(m_mutex) {
|
int valueIndex(const std::string& value) VL_REQUIRES(m_mutex) {
|
||||||
static int nextIndex = KEY_UNDEF + 1;
|
const auto iter = m_valueIndexes.find(value);
|
||||||
ValueIndexMap::iterator iter = m_valueIndexes.find(value);
|
|
||||||
if (iter != m_valueIndexes.end()) return iter->second;
|
if (iter != m_valueIndexes.end()) return iter->second;
|
||||||
nextIndex++;
|
m_nextIndex++;
|
||||||
assert(nextIndex > 0); // Didn't rollover
|
assert(m_nextIndex > 0); // Didn't rollover
|
||||||
m_valueIndexes.insert(std::make_pair(value, nextIndex));
|
m_valueIndexes.emplace(value, m_nextIndex);
|
||||||
m_indexValues.insert(std::make_pair(nextIndex, value));
|
m_indexValues.emplace(m_nextIndex, value);
|
||||||
return nextIndex;
|
return m_nextIndex;
|
||||||
}
|
}
|
||||||
static std::string dequote(const std::string& text) VL_PURE {
|
static std::string dequote(const std::string& text) VL_PURE {
|
||||||
// Quote any special characters
|
// Quote any special characters
|
||||||
@@ -221,45 +216,41 @@ private:
|
|||||||
}
|
}
|
||||||
static void selftest() VL_MT_SAFE {
|
static void selftest() VL_MT_SAFE {
|
||||||
// Little selftest
|
// Little selftest
|
||||||
#define VL_CST_CHECK(got, exp) \
|
#define SELF_CHECK(got, exp) \
|
||||||
do { \
|
do { \
|
||||||
if ((got) != (exp)) VL_FATAL_MT(__FILE__, __LINE__, "", "%Error: selftest\n"); \
|
if ((got) != (exp)) VL_FATAL_MT(__FILE__, __LINE__, "", "%Error: selftest\n"); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
SELF_CHECK(combineHier("a.b.c", "a.b.c"), "a.b.c");
|
||||||
VL_CST_CHECK(combineHier("a.b.c", "a.b.c"), "a.b.c");
|
SELF_CHECK(combineHier("a.b.c", "a.b"), "a.b*");
|
||||||
VL_CST_CHECK(combineHier("a.b.c", "a.b"), "a.b*");
|
SELF_CHECK(combineHier("a.x.c", "a.y.c"), "a.*.c");
|
||||||
VL_CST_CHECK(combineHier("a.x.c", "a.y.c"), "a.*.c");
|
SELF_CHECK(combineHier("a.z.z.z.c", "a.b.c"), "a.*.c");
|
||||||
VL_CST_CHECK(combineHier("a.z.z.z.c", "a.b.c"), "a.*.c");
|
SELF_CHECK(combineHier("z", "a"), "*");
|
||||||
VL_CST_CHECK(combineHier("z", "a"), "*");
|
SELF_CHECK(combineHier("q.a", "q.b"), "q.*");
|
||||||
VL_CST_CHECK(combineHier("q.a", "q.b"), "q.*");
|
SELF_CHECK(combineHier("q.za", "q.zb"), "q.z*");
|
||||||
VL_CST_CHECK(combineHier("q.za", "q.zb"), "q.z*");
|
SELF_CHECK(combineHier("1.2.3.a", "9.8.7.a"), "*.a");
|
||||||
VL_CST_CHECK(combineHier("1.2.3.a", "9.8.7.a"), "*.a");
|
#undef SELF_CHECK
|
||||||
#undef VL_CST_CHECK
|
|
||||||
}
|
}
|
||||||
void clearGuts() VL_REQUIRES(m_mutex) {
|
void clearGuts() VL_REQUIRES(m_mutex) {
|
||||||
for (ItemList::const_iterator it = m_items.begin(); it != m_items.end(); ++it) {
|
for (const auto& itemp : m_items) VL_DO_DANGLING(delete itemp, itemp);
|
||||||
VerilatedCovImpItem* itemp = *(it);
|
|
||||||
VL_DO_DANGLING(delete itemp, itemp);
|
|
||||||
}
|
|
||||||
m_items.clear();
|
m_items.clear();
|
||||||
m_indexValues.clear();
|
m_indexValues.clear();
|
||||||
m_valueIndexes.clear();
|
m_valueIndexes.clear();
|
||||||
|
m_nextIndex = KEY_UNDEF + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// PUBLIC METHODS
|
// PUBLIC METHODS
|
||||||
void clear() VL_EXCLUDES(m_mutex) {
|
void clear() VL_EXCLUDES(m_mutex) {
|
||||||
Verilated::quiesce();
|
Verilated::quiesce();
|
||||||
VerilatedLockGuard lock(m_mutex);
|
const VerilatedLockGuard lock(m_mutex);
|
||||||
clearGuts();
|
clearGuts();
|
||||||
}
|
}
|
||||||
void clearNonMatch(const char* matchp) VL_EXCLUDES(m_mutex) {
|
void clearNonMatch(const char* matchp) VL_EXCLUDES(m_mutex) {
|
||||||
Verilated::quiesce();
|
Verilated::quiesce();
|
||||||
VerilatedLockGuard lock(m_mutex);
|
const VerilatedLockGuard lock(m_mutex);
|
||||||
if (matchp && matchp[0]) {
|
if (matchp && matchp[0]) {
|
||||||
ItemList newlist;
|
ItemList newlist;
|
||||||
for (ItemList::iterator it = m_items.begin(); it != m_items.end(); ++it) {
|
for (const auto& itemp : m_items) {
|
||||||
VerilatedCovImpItem* itemp = *(it);
|
|
||||||
if (!itemMatchesString(itemp, matchp)) {
|
if (!itemMatchesString(itemp, matchp)) {
|
||||||
VL_DO_DANGLING(delete itemp, itemp);
|
VL_DO_DANGLING(delete itemp, itemp);
|
||||||
} else {
|
} else {
|
||||||
@@ -271,25 +262,23 @@ public:
|
|||||||
}
|
}
|
||||||
void zero() VL_EXCLUDES(m_mutex) {
|
void zero() VL_EXCLUDES(m_mutex) {
|
||||||
Verilated::quiesce();
|
Verilated::quiesce();
|
||||||
VerilatedLockGuard lock(m_mutex);
|
const VerilatedLockGuard lock(m_mutex);
|
||||||
for (ItemList::const_iterator it = m_items.begin(); it != m_items.end(); ++it) {
|
for (const auto& itemp : m_items) itemp->zero();
|
||||||
(*it)->zero();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// We assume there's always call to i/f/p in that order
|
// We assume there's always call to i/f/p in that order
|
||||||
void inserti(VerilatedCovImpItem* itemp) VL_EXCLUDES(m_mutex) {
|
void inserti(VerilatedCovImpItem* itemp) VL_EXCLUDES(m_mutex) {
|
||||||
VerilatedLockGuard lock(m_mutex);
|
const VerilatedLockGuard lock(m_mutex);
|
||||||
assert(!m_insertp);
|
assert(!m_insertp);
|
||||||
m_insertp = itemp;
|
m_insertp = itemp;
|
||||||
}
|
}
|
||||||
void insertf(const char* filenamep, int lineno) VL_EXCLUDES(m_mutex) {
|
void insertf(const char* filenamep, int lineno) VL_EXCLUDES(m_mutex) {
|
||||||
VerilatedLockGuard lock(m_mutex);
|
const VerilatedLockGuard lock(m_mutex);
|
||||||
m_insertFilenamep = filenamep;
|
m_insertFilenamep = filenamep;
|
||||||
m_insertLineno = lineno;
|
m_insertLineno = lineno;
|
||||||
}
|
}
|
||||||
void insertp(const char* ckeyps[MAX_KEYS], const char* valps[MAX_KEYS]) VL_EXCLUDES(m_mutex) {
|
void insertp(const char* ckeyps[MAX_KEYS], const char* valps[MAX_KEYS]) VL_EXCLUDES(m_mutex) {
|
||||||
VerilatedLockGuard lock(m_mutex);
|
const VerilatedLockGuard lock(m_mutex);
|
||||||
assert(m_insertp);
|
assert(m_insertp);
|
||||||
// First two key/vals are filename
|
// First two key/vals are filename
|
||||||
ckeyps[0] = "filename";
|
ckeyps[0] = "filename";
|
||||||
@@ -332,22 +321,22 @@ public:
|
|||||||
m_insertp->m_keys[addKeynum] = valueIndex(key);
|
m_insertp->m_keys[addKeynum] = valueIndex(key);
|
||||||
m_insertp->m_vals[addKeynum] = valueIndex(val);
|
m_insertp->m_vals[addKeynum] = valueIndex(val);
|
||||||
addKeynum++;
|
addKeynum++;
|
||||||
if (!legalKey(key)) {
|
if (VL_UNCOVERABLE(!legalKey(key))) {
|
||||||
std::string msg
|
std::string msg
|
||||||
= ("%Error: Coverage keys of one character, or letter+digit are illegal: "
|
= ("%Error: Coverage keys of one character, or letter+digit are illegal: "
|
||||||
+ key);
|
+ key); // LCOV_EXCL_LINE
|
||||||
VL_FATAL_MT("", 0, "", msg.c_str());
|
VL_FATAL_MT("", 0, "", msg.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_items.push_back(m_insertp);
|
m_items.push_back(m_insertp);
|
||||||
// Prepare for next
|
// Prepare for next
|
||||||
m_insertp = NULL;
|
m_insertp = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void write(const char* filename) VL_EXCLUDES(m_mutex) {
|
void write(const char* filename) VL_EXCLUDES(m_mutex) {
|
||||||
Verilated::quiesce();
|
Verilated::quiesce();
|
||||||
VerilatedLockGuard lock(m_mutex);
|
const VerilatedLockGuard lock(m_mutex);
|
||||||
#ifndef VM_COVERAGE
|
#ifndef VM_COVERAGE
|
||||||
VL_FATAL_MT("", 0, "", "%Error: Called VerilatedCov::write when VM_COVERAGE disabled\n");
|
VL_FATAL_MT("", 0, "", "%Error: Called VerilatedCov::write when VM_COVERAGE disabled\n");
|
||||||
#endif
|
#endif
|
||||||
@@ -362,10 +351,9 @@ public:
|
|||||||
os << "# SystemC::Coverage-3\n";
|
os << "# SystemC::Coverage-3\n";
|
||||||
|
|
||||||
// Build list of events; totalize if collapsing hierarchy
|
// Build list of events; totalize if collapsing hierarchy
|
||||||
typedef std::map<std::string, std::pair<std::string, vluint64_t> > EventMap;
|
typedef std::map<const std::string, std::pair<std::string, vluint64_t>> EventMap;
|
||||||
EventMap eventCounts;
|
EventMap eventCounts;
|
||||||
for (ItemList::iterator it = m_items.begin(); it != m_items.end(); ++it) {
|
for (const auto& itemp : m_items) {
|
||||||
VerilatedCovImpItem* itemp = *(it);
|
|
||||||
std::string name;
|
std::string name;
|
||||||
std::string hier;
|
std::string hier;
|
||||||
bool per_instance = false;
|
bool per_instance = false;
|
||||||
@@ -396,23 +384,23 @@ public:
|
|||||||
// inefficient)
|
// inefficient)
|
||||||
|
|
||||||
// Find or insert the named event
|
// Find or insert the named event
|
||||||
EventMap::iterator cit = eventCounts.find(name);
|
const auto cit = eventCounts.find(name);
|
||||||
if (cit != eventCounts.end()) {
|
if (cit != eventCounts.end()) {
|
||||||
const std::string& oldhier = cit->second.first;
|
const std::string& oldhier = cit->second.first;
|
||||||
cit->second.second += itemp->count();
|
cit->second.second += itemp->count();
|
||||||
cit->second.first = combineHier(oldhier, hier);
|
cit->second.first = combineHier(oldhier, hier);
|
||||||
} else {
|
} else {
|
||||||
eventCounts.insert(std::make_pair(name, make_pair(hier, itemp->count())));
|
eventCounts.emplace(name, make_pair(hier, itemp->count()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Output body
|
// Output body
|
||||||
for (EventMap::const_iterator it = eventCounts.begin(); it != eventCounts.end(); ++it) {
|
for (const auto& i : eventCounts) {
|
||||||
os << "C '" << std::dec;
|
os << "C '" << std::dec;
|
||||||
os << it->first;
|
os << i.first;
|
||||||
if (!it->second.first.empty()) os << keyValueFormatter(VL_CIK_HIER, it->second.first);
|
if (!i.second.first.empty()) os << keyValueFormatter(VL_CIK_HIER, i.second.first);
|
||||||
os << "' " << it->second.second;
|
os << "' " << i.second.second;
|
||||||
os << std::endl;
|
os << '\n';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -447,15 +435,15 @@ void VerilatedCov::_insertp(A(0), A(1), A(2), A(3), A(4), A(5), A(6), A(7), A(8)
|
|||||||
A(21), A(22), A(23), A(24), A(25), A(26), A(27), A(28),
|
A(21), A(22), A(23), A(24), A(25), A(26), A(27), A(28),
|
||||||
A(29)) VL_MT_SAFE {
|
A(29)) VL_MT_SAFE {
|
||||||
const char* keyps[VerilatedCovImpBase::MAX_KEYS]
|
const char* keyps[VerilatedCovImpBase::MAX_KEYS]
|
||||||
= {NULL, NULL, NULL, // filename,lineno,page
|
= {nullptr, nullptr, nullptr, // filename,lineno,page
|
||||||
key0, key1, key2, key3, key4, key5, key6, key7, key8, key9,
|
key0, key1, key2, key3, key4, key5, key6, key7, key8, key9,
|
||||||
key10, key11, key12, key13, key14, key15, key16, key17, key18, key19,
|
key10, key11, key12, key13, key14, key15, key16, key17, key18, key19,
|
||||||
key20, key21, key22, key23, key24, key25, key26, key27, key28, key29};
|
key20, key21, key22, key23, key24, key25, key26, key27, key28, key29};
|
||||||
const char* valps[VerilatedCovImpBase::MAX_KEYS]
|
const char* valps[VerilatedCovImpBase::MAX_KEYS]
|
||||||
= {NULL, NULL, NULL, // filename,lineno,page
|
= {nullptr, nullptr, nullptr, // filename,lineno,page
|
||||||
valp0, valp1, valp2, valp3, valp4, valp5, valp6, valp7, valp8, valp9,
|
valp0, valp1, valp2, valp3, valp4, valp5, valp6, valp7, valp8, valp9,
|
||||||
valp10, valp11, valp12, valp13, valp14, valp15, valp16, valp17, valp18, valp19,
|
valp10, valp11, valp12, valp13, valp14, valp15, valp16, valp17, valp18, valp19,
|
||||||
valp20, valp21, valp22, valp23, valp24, valp25, valp26, valp27, valp28, valp29};
|
valp20, valp21, valp22, valp23, valp24, valp25, valp26, valp27, valp28, valp29};
|
||||||
VerilatedCovImp::imp().insertp(keyps, valps);
|
VerilatedCovImp::imp().insertp(keyps, valps);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -475,11 +463,11 @@ void VerilatedCov::_insertp(A(0), A(1), A(2), A(3), A(4), A(5), A(6), A(7), A(8)
|
|||||||
}
|
}
|
||||||
// Backward compatibility for Verilator
|
// Backward compatibility for Verilator
|
||||||
void VerilatedCov::_insertp(A(0), A(1), K(2), int val2, K(3), int val3, K(4),
|
void VerilatedCov::_insertp(A(0), A(1), K(2), int val2, K(3), int val3, K(4),
|
||||||
const std::string& val4, A(5), A(6)) VL_MT_SAFE {
|
const std::string& val4, A(5), A(6), A(7)) VL_MT_SAFE {
|
||||||
std::string val2str = vlCovCvtToStr(val2);
|
std::string val2str = vlCovCvtToStr(val2);
|
||||||
std::string val3str = vlCovCvtToStr(val3);
|
std::string val3str = vlCovCvtToStr(val3);
|
||||||
_insertp(C(0), C(1), key2, val2str.c_str(), key3, val3str.c_str(), key4, val4.c_str(), C(5),
|
_insertp(C(0), C(1), key2, val2str.c_str(), key3, val3str.c_str(), key4, val4.c_str(), C(5),
|
||||||
C(6), N(7), N(8), N(9), N(10), N(11), N(12), N(13), N(14), N(15), N(16), N(17), N(18),
|
C(6), C(7), N(8), N(9), N(10), N(11), N(12), N(13), N(14), N(15), N(16), N(17), N(18),
|
||||||
N(19), N(20), N(21), N(22), N(23), N(24), N(25), N(26), N(27), N(28), N(29));
|
N(19), N(20), N(21), N(22), N(23), N(24), N(25), N(26), N(27), N(28), N(29));
|
||||||
}
|
}
|
||||||
#undef A
|
#undef A
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
//
|
//
|
||||||
// THIS MODULE IS PUBLICLY LICENSED
|
// THIS MODULE IS PUBLICLY LICENSED
|
||||||
//
|
//
|
||||||
// Copyright 2001-2020 by Wilson Snyder. This program is free software; you
|
// Copyright 2001-2021 by Wilson Snyder. This program is free software; you
|
||||||
// can redistribute it and/or modify it under the terms of either the GNU
|
// can 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.
|
||||||
@@ -88,7 +88,7 @@ template <class T> std::string vlCovCvtToStr(const T& t) VL_PURE {
|
|||||||
/// Global class with methods affecting all coverage data.
|
/// Global class with methods affecting all coverage data.
|
||||||
/// All public methods in this class are thread safe.
|
/// All public methods in this class are thread safe.
|
||||||
|
|
||||||
class VerilatedCov {
|
class VerilatedCov final {
|
||||||
VL_UNCOPYABLE(VerilatedCov);
|
VL_UNCOPYABLE(VerilatedCov);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -112,7 +112,7 @@ public:
|
|||||||
// there's not much more gain in having a version for each number of args.
|
// there's not much more gain in having a version for each number of args.
|
||||||
#define K(n) const char* key##n
|
#define K(n) const char* key##n
|
||||||
#define A(n) const char *key##n, const char *valp##n // Argument list
|
#define A(n) const char *key##n, const char *valp##n // Argument list
|
||||||
#define D(n) const char *key##n = NULL, const char *valp##n = NULL // Argument list
|
#define D(n) const char *key##n = nullptr, const char *valp##n = nullptr // Argument list
|
||||||
static void _insertp(D(0), D(1), D(2), D(3), D(4), D(5), D(6), D(7), D(8), D(9));
|
static void _insertp(D(0), D(1), D(2), D(3), D(4), D(5), D(6), D(7), D(8), D(9));
|
||||||
static void _insertp(A(0), A(1), A(2), A(3), A(4), A(5), A(6), A(7), A(8), A(9), A(10), D(11),
|
static void _insertp(A(0), A(1), A(2), A(3), A(4), A(5), A(6), A(7), A(8), A(9), A(10), D(11),
|
||||||
D(12), D(13), D(14), D(15), D(16), D(17), D(18), D(19));
|
D(12), D(13), D(14), D(15), D(16), D(17), D(18), D(19));
|
||||||
@@ -121,7 +121,7 @@ public:
|
|||||||
D(22), D(23), D(24), D(25), D(26), D(27), D(28), D(29));
|
D(22), D(23), D(24), D(25), D(26), D(27), D(28), D(29));
|
||||||
// Backward compatibility for Verilator
|
// Backward compatibility for Verilator
|
||||||
static void _insertp(A(0), A(1), K(2), int val2, K(3), int val3, K(4), const std::string& val4,
|
static void _insertp(A(0), A(1), K(2), int val2, K(3), int val3, K(4), const std::string& val4,
|
||||||
A(5), A(6));
|
A(5), A(6), A(7));
|
||||||
|
|
||||||
#undef K
|
#undef K
|
||||||
#undef A
|
#undef A
|
||||||
|
|||||||
+14
-74
@@ -3,7 +3,7 @@
|
|||||||
//
|
//
|
||||||
// THIS MODULE IS PUBLICLY LICENSED
|
// THIS MODULE IS PUBLICLY LICENSED
|
||||||
//
|
//
|
||||||
// Copyright 2001-2020 by Wilson Snyder. This program is free software; you
|
// Copyright 2001-2021 by Wilson Snyder. This program is free software; you
|
||||||
// can redistribute it and/or modify it under the terms of either the GNU
|
// can 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.
|
||||||
@@ -29,67 +29,27 @@
|
|||||||
#define VLCOVGEN_ITEM(string_parsed_by_vlcovgen)
|
#define VLCOVGEN_ITEM(string_parsed_by_vlcovgen)
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
VLCOVGEN_ITEM("name=>'col0_name', short=>'C0', group=>1, default=>undef, descr=>'The column title for the header line of this column'")
|
VLCOVGEN_ITEM("'name':'column', 'short':'n', 'group':1, 'default':0, 'descr':'Column number for the item. Used to disambiguate multiple coverage points on the same line number'")
|
||||||
VLCOVGEN_ITEM("name=>'col1_name', short=>'C1', group=>1, default=>undef, ")
|
VLCOVGEN_ITEM("'name':'filename', 'short':'f', 'group':1, 'default':None, 'descr':'Filename of the item'")
|
||||||
VLCOVGEN_ITEM("name=>'col2_name', short=>'C2', group=>1, default=>undef, ")
|
VLCOVGEN_ITEM("'name':'linescov', 'short':'S', 'group':1, 'default':'', 'descr':'List of comma-separated lines covered'")
|
||||||
VLCOVGEN_ITEM("name=>'col3_name', short=>'C3', group=>1, default=>undef, ")
|
VLCOVGEN_ITEM("'name':'per_instance','short':'P', 'group':1, 'default':0, 'descr':'True if every hierarchy is independently counted; otherwise all hierarchies will be combined into a single count'")
|
||||||
VLCOVGEN_ITEM("name=>'column', short=>'n', group=>1, default=>0, descr=>'Column number for the item. Used to disambiguate multiple coverage points on the same line number'")
|
VLCOVGEN_ITEM("'name':'thresh', 'short':'s', 'group':1, 'default':None, 'descr':'Number of hits to consider covered (aka at_least)'")
|
||||||
VLCOVGEN_ITEM("name=>'filename', short=>'f', group=>1, default=>undef, descr=>'Filename of the item'")
|
VLCOVGEN_ITEM("'name':'type', 'short':'t', 'group':1, 'default':'', 'descr':'Type of coverage (block, line, fsm, etc)'")
|
||||||
VLCOVGEN_ITEM("name=>'groupdesc', short=>'d', group=>1, default=>'', descr=>'Description of the covergroup this item belongs to'")
|
|
||||||
VLCOVGEN_ITEM("name=>'groupname', short=>'g', group=>1, default=>'', descr=>'Group name of the covergroup this item belongs to'")
|
|
||||||
VLCOVGEN_ITEM("name=>'groupcmt', short=>'O', group=>1, default=>'', ")
|
|
||||||
VLCOVGEN_ITEM("name=>'per_instance',short=>'P', group=>1, default=>0, descr=>'True if every hierarchy is independently counted; otherwise all hierarchies will be combined into a single count'")
|
|
||||||
VLCOVGEN_ITEM("name=>'row0_name', short=>'R0', group=>1, default=>undef, descr=>'The row title for the header line of this row'")
|
|
||||||
VLCOVGEN_ITEM("name=>'row1_name', short=>'R1', group=>1, default=>undef, ")
|
|
||||||
VLCOVGEN_ITEM("name=>'row2_name', short=>'R2', group=>1, default=>undef, ")
|
|
||||||
VLCOVGEN_ITEM("name=>'row3_name', short=>'R3', group=>1, default=>undef, ")
|
|
||||||
VLCOVGEN_ITEM("name=>'table', short=>'T', group=>1, default=>undef, descr=>'The name of the table for automatically generated tables'")
|
|
||||||
VLCOVGEN_ITEM("name=>'thresh', short=>'s', group=>1, default=>undef, ")
|
|
||||||
VLCOVGEN_ITEM("name=>'type', short=>'t', group=>1, default=>'', descr=>'Type of coverage (block, line, fsm, etc)'")
|
|
||||||
// Bin attributes
|
// Bin attributes
|
||||||
VLCOVGEN_ITEM("name=>'col0', short=>'c0', group=>0, default=>undef, descr=>'The (enumeration) value name for this column in a table cross' ")
|
VLCOVGEN_ITEM("'name':'comment', 'short':'o', 'group':0, 'default':'', 'descr':'Textual description for the item'")
|
||||||
VLCOVGEN_ITEM("name=>'col1', short=>'c1', group=>0, default=>undef, ")
|
VLCOVGEN_ITEM("'name':'hier', 'short':'h', 'group':0, 'default':'', 'descr':'Hierarchy path name for the item'")
|
||||||
VLCOVGEN_ITEM("name=>'col2', short=>'c2', group=>0, default=>undef, ")
|
VLCOVGEN_ITEM("'name':'lineno', 'short':'l', 'group':0, 'default':0, 'descr':'Line number for the item'")
|
||||||
VLCOVGEN_ITEM("name=>'col3', short=>'c3', group=>0, default=>undef, ")
|
VLCOVGEN_ITEM("'name':'weight', 'short':'w', 'group':0, 'default':None, 'descr':'For totaling items, weight of this item'")
|
||||||
VLCOVGEN_ITEM("name=>'comment', short=>'o', group=>0, default=>'', descr=>'Textual description for the item'")
|
|
||||||
VLCOVGEN_ITEM("name=>'hier', short=>'h', group=>0, default=>'', descr=>'Hierarchy path name for the item'")
|
|
||||||
VLCOVGEN_ITEM("name=>'limit', short=>'L', group=>0, default=>undef, ")
|
|
||||||
VLCOVGEN_ITEM("name=>'lineno', short=>'l', group=>0, default=>0, descr=>'Line number for the item'")
|
|
||||||
VLCOVGEN_ITEM("name=>'row0', short=>'r0', group=>0, default=>undef, descr=>'The (enumeration) value name for this row in a table cross'")
|
|
||||||
VLCOVGEN_ITEM("name=>'row1', short=>'r1', group=>0, default=>undef, ")
|
|
||||||
VLCOVGEN_ITEM("name=>'row2', short=>'r2', group=>0, default=>undef, ")
|
|
||||||
VLCOVGEN_ITEM("name=>'row3', short=>'r3', group=>0, default=>undef, ")
|
|
||||||
VLCOVGEN_ITEM("name=>'weight', short=>'w', group=>0, default=>undef, descr=>'For totaling items, weight of this item'")
|
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
// VLCOVGEN_CIK_AUTO_EDIT_BEGIN
|
// VLCOVGEN_CIK_AUTO_EDIT_BEGIN
|
||||||
#define VL_CIK_COL0 "c0"
|
|
||||||
#define VL_CIK_COL0_NAME "C0"
|
|
||||||
#define VL_CIK_COL1 "c1"
|
|
||||||
#define VL_CIK_COL1_NAME "C1"
|
|
||||||
#define VL_CIK_COL2 "c2"
|
|
||||||
#define VL_CIK_COL2_NAME "C2"
|
|
||||||
#define VL_CIK_COL3 "c3"
|
|
||||||
#define VL_CIK_COL3_NAME "C3"
|
|
||||||
#define VL_CIK_COLUMN "n"
|
#define VL_CIK_COLUMN "n"
|
||||||
#define VL_CIK_COMMENT "o"
|
#define VL_CIK_COMMENT "o"
|
||||||
#define VL_CIK_FILENAME "f"
|
#define VL_CIK_FILENAME "f"
|
||||||
#define VL_CIK_GROUPCMT "O"
|
|
||||||
#define VL_CIK_GROUPDESC "d"
|
|
||||||
#define VL_CIK_GROUPNAME "g"
|
|
||||||
#define VL_CIK_HIER "h"
|
#define VL_CIK_HIER "h"
|
||||||
#define VL_CIK_LIMIT "L"
|
|
||||||
#define VL_CIK_LINENO "l"
|
#define VL_CIK_LINENO "l"
|
||||||
|
#define VL_CIK_LINESCOV "S"
|
||||||
#define VL_CIK_PER_INSTANCE "P"
|
#define VL_CIK_PER_INSTANCE "P"
|
||||||
#define VL_CIK_ROW0 "r0"
|
|
||||||
#define VL_CIK_ROW0_NAME "R0"
|
|
||||||
#define VL_CIK_ROW1 "r1"
|
|
||||||
#define VL_CIK_ROW1_NAME "R1"
|
|
||||||
#define VL_CIK_ROW2 "r2"
|
|
||||||
#define VL_CIK_ROW2_NAME "R2"
|
|
||||||
#define VL_CIK_ROW3 "r3"
|
|
||||||
#define VL_CIK_ROW3_NAME "R3"
|
|
||||||
#define VL_CIK_TABLE "T"
|
|
||||||
#define VL_CIK_THRESH "s"
|
#define VL_CIK_THRESH "s"
|
||||||
#define VL_CIK_TYPE "t"
|
#define VL_CIK_TYPE "t"
|
||||||
#define VL_CIK_WEIGHT "w"
|
#define VL_CIK_WEIGHT "w"
|
||||||
@@ -100,37 +60,17 @@ VLCOVGEN_ITEM("name=>'weight', short=>'w', group=>0, default=>undef, descr
|
|||||||
/// Verilator coverage global class.
|
/// Verilator coverage global class.
|
||||||
/// This class is thread safe.
|
/// This class is thread safe.
|
||||||
|
|
||||||
class VerilatedCovKey {
|
class VerilatedCovKey final {
|
||||||
public:
|
public:
|
||||||
static std::string shortKey(const std::string& key) VL_PURE {
|
static std::string shortKey(const std::string& key) VL_PURE {
|
||||||
// VLCOVGEN_SHORT_AUTO_EDIT_BEGIN
|
// VLCOVGEN_SHORT_AUTO_EDIT_BEGIN
|
||||||
if (key == "col0") return VL_CIK_COL0;
|
|
||||||
if (key == "col0_name") return VL_CIK_COL0_NAME;
|
|
||||||
if (key == "col1") return VL_CIK_COL1;
|
|
||||||
if (key == "col1_name") return VL_CIK_COL1_NAME;
|
|
||||||
if (key == "col2") return VL_CIK_COL2;
|
|
||||||
if (key == "col2_name") return VL_CIK_COL2_NAME;
|
|
||||||
if (key == "col3") return VL_CIK_COL3;
|
|
||||||
if (key == "col3_name") return VL_CIK_COL3_NAME;
|
|
||||||
if (key == "column") return VL_CIK_COLUMN;
|
if (key == "column") return VL_CIK_COLUMN;
|
||||||
if (key == "comment") return VL_CIK_COMMENT;
|
if (key == "comment") return VL_CIK_COMMENT;
|
||||||
if (key == "filename") return VL_CIK_FILENAME;
|
if (key == "filename") return VL_CIK_FILENAME;
|
||||||
if (key == "groupcmt") return VL_CIK_GROUPCMT;
|
|
||||||
if (key == "groupdesc") return VL_CIK_GROUPDESC;
|
|
||||||
if (key == "groupname") return VL_CIK_GROUPNAME;
|
|
||||||
if (key == "hier") return VL_CIK_HIER;
|
if (key == "hier") return VL_CIK_HIER;
|
||||||
if (key == "limit") return VL_CIK_LIMIT;
|
|
||||||
if (key == "lineno") return VL_CIK_LINENO;
|
if (key == "lineno") return VL_CIK_LINENO;
|
||||||
|
if (key == "linescov") return VL_CIK_LINESCOV;
|
||||||
if (key == "per_instance") return VL_CIK_PER_INSTANCE;
|
if (key == "per_instance") return VL_CIK_PER_INSTANCE;
|
||||||
if (key == "row0") return VL_CIK_ROW0;
|
|
||||||
if (key == "row0_name") return VL_CIK_ROW0_NAME;
|
|
||||||
if (key == "row1") return VL_CIK_ROW1;
|
|
||||||
if (key == "row1_name") return VL_CIK_ROW1_NAME;
|
|
||||||
if (key == "row2") return VL_CIK_ROW2;
|
|
||||||
if (key == "row2_name") return VL_CIK_ROW2_NAME;
|
|
||||||
if (key == "row3") return VL_CIK_ROW3;
|
|
||||||
if (key == "row3_name") return VL_CIK_ROW3_NAME;
|
|
||||||
if (key == "table") return VL_CIK_TABLE;
|
|
||||||
if (key == "thresh") return VL_CIK_THRESH;
|
if (key == "thresh") return VL_CIK_THRESH;
|
||||||
if (key == "type") return VL_CIK_TYPE;
|
if (key == "type") return VL_CIK_TYPE;
|
||||||
if (key == "weight") return VL_CIK_WEIGHT;
|
if (key == "weight") return VL_CIK_WEIGHT;
|
||||||
|
|||||||
+35
-108
@@ -1,7 +1,7 @@
|
|||||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2009-2020 by Wilson Snyder. This program is free software; you can
|
// Copyright 2009-2021 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// 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.
|
||||||
@@ -37,17 +37,12 @@
|
|||||||
//======================================================================
|
//======================================================================
|
||||||
// Internal macros
|
// Internal macros
|
||||||
|
|
||||||
// Not supported yet
|
|
||||||
#define _VL_SVDPI_UNIMP() \
|
|
||||||
VL_FATAL_MT(__FILE__, __LINE__, "", \
|
|
||||||
(std::string("%%Error: Unsupported DPI function: ") + VL_FUNC).c_str())
|
|
||||||
|
|
||||||
#define _VL_SVDPI_WARN(...) VL_PRINTF_MT(__VA_ARGS__)
|
#define _VL_SVDPI_WARN(...) VL_PRINTF_MT(__VA_ARGS__)
|
||||||
|
|
||||||
// Function requires a "context" in the import declaration
|
// Function requires a "context" in the import declaration
|
||||||
#define _VL_SVDPI_CONTEXT_WARN() \
|
#define _VL_SVDPI_CONTEXT_WARN() \
|
||||||
_VL_SVDPI_WARN("%%Warning: DPI C Function called by Verilog DPI import with missing " \
|
_VL_SVDPI_WARN("%%Warning: DPI C Function called by Verilog DPI import with missing " \
|
||||||
"'context' keyword.\n");
|
"'context' keyword.\n")
|
||||||
|
|
||||||
//======================================================================
|
//======================================================================
|
||||||
//======================================================================
|
//======================================================================
|
||||||
@@ -181,7 +176,7 @@ void svPutPartselLogic(svLogicVecVal* dp, const svLogicVecVal s, int lbit, int w
|
|||||||
static inline const VerilatedDpiOpenVar* _vl_openhandle_varp(const svOpenArrayHandle h) {
|
static inline const VerilatedDpiOpenVar* _vl_openhandle_varp(const svOpenArrayHandle h) {
|
||||||
if (VL_UNLIKELY(!h)) {
|
if (VL_UNLIKELY(!h)) {
|
||||||
VL_FATAL_MT(__FILE__, __LINE__, "",
|
VL_FATAL_MT(__FILE__, __LINE__, "",
|
||||||
"%%Error: DPI svOpenArrayHandle function called with NULL handle");
|
"%%Error: DPI svOpenArrayHandle function called with nullptr handle");
|
||||||
}
|
}
|
||||||
const VerilatedDpiOpenVar* varp = reinterpret_cast<const VerilatedDpiOpenVar*>(h);
|
const VerilatedDpiOpenVar* varp = reinterpret_cast<const VerilatedDpiOpenVar*>(h);
|
||||||
if (VL_UNLIKELY(!varp->magicOk())) {
|
if (VL_UNLIKELY(!varp->magicOk())) {
|
||||||
@@ -202,10 +197,10 @@ int svIncrement(const svOpenArrayHandle h, int d) { return _vl_openhandle_varp(h
|
|||||||
int svSize(const svOpenArrayHandle h, int d) { return _vl_openhandle_varp(h)->elements(d); }
|
int svSize(const svOpenArrayHandle h, int d) { return _vl_openhandle_varp(h)->elements(d); }
|
||||||
int svDimensions(const svOpenArrayHandle h) { return _vl_openhandle_varp(h)->udims(); }
|
int svDimensions(const svOpenArrayHandle h) { return _vl_openhandle_varp(h)->udims(); }
|
||||||
|
|
||||||
/// Return pointer to open array data, or NULL if not in IEEE standard C layout
|
/// Return pointer to open array data, or nullptr if not in IEEE standard C layout
|
||||||
void* svGetArrayPtr(const svOpenArrayHandle h) {
|
void* svGetArrayPtr(const svOpenArrayHandle h) {
|
||||||
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(h);
|
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(h);
|
||||||
if (VL_UNLIKELY(!varp->isDpiStdLayout())) return NULL;
|
if (VL_UNLIKELY(!varp->isDpiStdLayout())) return nullptr;
|
||||||
return varp->datap();
|
return varp->datap();
|
||||||
}
|
}
|
||||||
/// Return size of open array, or 0 if not in IEEE standard C layout
|
/// Return size of open array, or 0 if not in IEEE standard C layout
|
||||||
@@ -226,7 +221,7 @@ static void* _vl_sv_adjusted_datap(const VerilatedDpiOpenVar* varp, int nargs, i
|
|||||||
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function called on"
|
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function called on"
|
||||||
" %d dimensional array using %d dimensional function.\n",
|
" %d dimensional array using %d dimensional function.\n",
|
||||||
varp->udims(), nargs);
|
varp->udims(), nargs);
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
if (nargs >= 1) {
|
if (nargs >= 1) {
|
||||||
datap = varp->datapAdjustIndex(datap, 1, indx1);
|
datap = varp->datapAdjustIndex(datap, 1, indx1);
|
||||||
@@ -234,7 +229,7 @@ static void* _vl_sv_adjusted_datap(const VerilatedDpiOpenVar* varp, int nargs, i
|
|||||||
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function index 1 "
|
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function index 1 "
|
||||||
"out of bounds; %d outside [%d:%d].\n",
|
"out of bounds; %d outside [%d:%d].\n",
|
||||||
indx1, varp->left(1), varp->right(1));
|
indx1, varp->left(1), varp->right(1));
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (nargs >= 2) {
|
if (nargs >= 2) {
|
||||||
@@ -243,7 +238,7 @@ static void* _vl_sv_adjusted_datap(const VerilatedDpiOpenVar* varp, int nargs, i
|
|||||||
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function index 2 "
|
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function index 2 "
|
||||||
"out of bounds; %d outside [%d:%d].\n",
|
"out of bounds; %d outside [%d:%d].\n",
|
||||||
indx2, varp->left(2), varp->right(2));
|
indx2, varp->left(2), varp->right(2));
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (nargs >= 3) {
|
if (nargs >= 3) {
|
||||||
@@ -252,27 +247,17 @@ static void* _vl_sv_adjusted_datap(const VerilatedDpiOpenVar* varp, int nargs, i
|
|||||||
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function index 3 "
|
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function index 3 "
|
||||||
"out of bounds; %d outside [%d:%d].\n",
|
"out of bounds; %d outside [%d:%d].\n",
|
||||||
indx1, varp->left(3), varp->right(3));
|
indx1, varp->left(3), varp->right(3));
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return datap;
|
return datap;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _vl_sv_adjusted_bit(const VerilatedDpiOpenVar* varp, int indx) {
|
/// Return pointer to simulator open array element, or nullptr if outside range
|
||||||
if (VL_UNLIKELY(indx < varp->low(0) || indx > varp->high(0))) {
|
|
||||||
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function packed index out of bounds; %d "
|
|
||||||
"outside [%d:%d].\n",
|
|
||||||
indx, varp->left(0), varp->right(0));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return indx - varp->low(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return pointer to simulator open array element, or NULL if outside range
|
|
||||||
static void* _vl_svGetArrElemPtr(const svOpenArrayHandle h, int nargs, int indx1, int indx2,
|
static void* _vl_svGetArrElemPtr(const svOpenArrayHandle h, int nargs, int indx1, int indx2,
|
||||||
int indx3) VL_MT_SAFE {
|
int indx3) VL_MT_SAFE {
|
||||||
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(h);
|
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(h);
|
||||||
if (VL_UNLIKELY(!varp->isDpiStdLayout())) return NULL;
|
if (VL_UNLIKELY(!varp->isDpiStdLayout())) return nullptr;
|
||||||
void* datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3);
|
void* datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3);
|
||||||
return datap;
|
return datap;
|
||||||
}
|
}
|
||||||
@@ -283,7 +268,7 @@ static void _vl_svGetBitArrElemVecVal(svBitVecVal* d, const svOpenArrayHandle s,
|
|||||||
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(s);
|
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(s);
|
||||||
void* datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3);
|
void* datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3);
|
||||||
if (VL_UNLIKELY(!datap)) return;
|
if (VL_UNLIKELY(!datap)) return;
|
||||||
switch (varp->vltype()) {
|
switch (varp->vltype()) { // LCOV_EXCL_BR_LINE
|
||||||
case VLVT_UINT8: d[0] = *(reinterpret_cast<CData*>(datap)); return;
|
case VLVT_UINT8: d[0] = *(reinterpret_cast<CData*>(datap)); return;
|
||||||
case VLVT_UINT16: d[0] = *(reinterpret_cast<SData*>(datap)); return;
|
case VLVT_UINT16: d[0] = *(reinterpret_cast<SData*>(datap)); return;
|
||||||
case VLVT_UINT32: d[0] = *(reinterpret_cast<IData*>(datap)); return;
|
case VLVT_UINT32: d[0] = *(reinterpret_cast<IData*>(datap)); return;
|
||||||
@@ -299,10 +284,10 @@ static void _vl_svGetBitArrElemVecVal(svBitVecVal* d, const svOpenArrayHandle s,
|
|||||||
for (int i = 0; i < VL_WORDS_I(varp->packed().elements()); ++i) d[i] = wdatap[i];
|
for (int i = 0; i < VL_WORDS_I(varp->packed().elements()); ++i) d[i] = wdatap[i];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
default:
|
default: // LCOV_EXCL_START // Errored earlier
|
||||||
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n",
|
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n",
|
||||||
varp->vltype());
|
varp->vltype());
|
||||||
return;
|
return; // LCOV_EXCL_STOP
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Copy to user logic array from simulator open array
|
/// Copy to user logic array from simulator open array
|
||||||
@@ -311,7 +296,7 @@ static void _vl_svGetLogicArrElemVecVal(svLogicVecVal* d, const svOpenArrayHandl
|
|||||||
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(s);
|
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(s);
|
||||||
void* datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3);
|
void* datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3);
|
||||||
if (VL_UNLIKELY(!datap)) return;
|
if (VL_UNLIKELY(!datap)) return;
|
||||||
switch (varp->vltype()) {
|
switch (varp->vltype()) { // LCOV_EXCL_BR_LINE
|
||||||
case VLVT_UINT8:
|
case VLVT_UINT8:
|
||||||
d[0].aval = *(reinterpret_cast<CData*>(datap));
|
d[0].aval = *(reinterpret_cast<CData*>(datap));
|
||||||
d[0].bval = 0;
|
d[0].bval = 0;
|
||||||
@@ -330,7 +315,7 @@ static void _vl_svGetLogicArrElemVecVal(svLogicVecVal* d, const svOpenArrayHandl
|
|||||||
d[0].aval = lwp[0];
|
d[0].aval = lwp[0];
|
||||||
d[0].bval = 0;
|
d[0].bval = 0;
|
||||||
d[1].aval = lwp[1];
|
d[1].aval = lwp[1];
|
||||||
d[0].bval = 0;
|
d[1].bval = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case VLVT_WDATA: {
|
case VLVT_WDATA: {
|
||||||
@@ -341,10 +326,10 @@ static void _vl_svGetLogicArrElemVecVal(svLogicVecVal* d, const svOpenArrayHandl
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
default:
|
default: // LCOV_EXCL_START // Errored earlier
|
||||||
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n",
|
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n",
|
||||||
varp->vltype());
|
varp->vltype());
|
||||||
return;
|
return; // LCOV_EXCL_STOP
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -354,7 +339,7 @@ static void _vl_svPutBitArrElemVecVal(const svOpenArrayHandle d, const svBitVecV
|
|||||||
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(d);
|
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(d);
|
||||||
void* datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3);
|
void* datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3);
|
||||||
if (VL_UNLIKELY(!datap)) return;
|
if (VL_UNLIKELY(!datap)) return;
|
||||||
switch (varp->vltype()) {
|
switch (varp->vltype()) { // LCOV_EXCL_BR_LINE
|
||||||
case VLVT_UINT8: *(reinterpret_cast<CData*>(datap)) = s[0]; return;
|
case VLVT_UINT8: *(reinterpret_cast<CData*>(datap)) = s[0]; return;
|
||||||
case VLVT_UINT16: *(reinterpret_cast<SData*>(datap)) = s[0]; return;
|
case VLVT_UINT16: *(reinterpret_cast<SData*>(datap)) = s[0]; return;
|
||||||
case VLVT_UINT32: *(reinterpret_cast<IData*>(datap)) = s[0]; return;
|
case VLVT_UINT32: *(reinterpret_cast<IData*>(datap)) = s[0]; return;
|
||||||
@@ -364,10 +349,10 @@ static void _vl_svPutBitArrElemVecVal(const svOpenArrayHandle d, const svBitVecV
|
|||||||
for (int i = 0; i < VL_WORDS_I(varp->packed().elements()); ++i) wdatap[i] = s[i];
|
for (int i = 0; i < VL_WORDS_I(varp->packed().elements()); ++i) wdatap[i] = s[i];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
default:
|
default: // LCOV_EXCL_START // Errored earlier
|
||||||
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n",
|
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n",
|
||||||
varp->vltype());
|
varp->vltype());
|
||||||
return;
|
return; // LCOV_EXCL_STOP
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Copy to simulator open array from from user logic array
|
/// Copy to simulator open array from from user logic array
|
||||||
@@ -376,7 +361,7 @@ static void _vl_svPutLogicArrElemVecVal(const svOpenArrayHandle d, const svLogic
|
|||||||
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(d);
|
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(d);
|
||||||
void* datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3);
|
void* datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3);
|
||||||
if (VL_UNLIKELY(!datap)) return;
|
if (VL_UNLIKELY(!datap)) return;
|
||||||
switch (varp->vltype()) {
|
switch (varp->vltype()) { // LCOV_EXCL_BR_LINE
|
||||||
case VLVT_UINT8: *(reinterpret_cast<CData*>(datap)) = s[0].aval; return;
|
case VLVT_UINT8: *(reinterpret_cast<CData*>(datap)) = s[0].aval; return;
|
||||||
case VLVT_UINT16: *(reinterpret_cast<SData*>(datap)) = s[0].aval; return;
|
case VLVT_UINT16: *(reinterpret_cast<SData*>(datap)) = s[0].aval; return;
|
||||||
case VLVT_UINT32: *(reinterpret_cast<IData*>(datap)) = s[0].aval; return;
|
case VLVT_UINT32: *(reinterpret_cast<IData*>(datap)) = s[0].aval; return;
|
||||||
@@ -388,10 +373,10 @@ static void _vl_svPutLogicArrElemVecVal(const svOpenArrayHandle d, const svLogic
|
|||||||
for (int i = 0; i < VL_WORDS_I(varp->packed().elements()); ++i) wdatap[i] = s[i].aval;
|
for (int i = 0; i < VL_WORDS_I(varp->packed().elements()); ++i) wdatap[i] = s[i].aval;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
default:
|
default: // LCOV_EXCL_START // Errored earlier
|
||||||
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n",
|
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n",
|
||||||
varp->vltype());
|
varp->vltype());
|
||||||
return;
|
return; // LCOV_EXCL_STOP
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -400,31 +385,14 @@ static svBit _vl_svGetBitArrElem(const svOpenArrayHandle s, int nargs, int indx1
|
|||||||
int indx3, int indx4) VL_MT_SAFE {
|
int indx3, int indx4) VL_MT_SAFE {
|
||||||
// One extra index supported, as need bit number
|
// One extra index supported, as need bit number
|
||||||
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(s);
|
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(s);
|
||||||
void* datap;
|
void* datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3);
|
||||||
int lsb;
|
|
||||||
if (varp->packed().elements()) {
|
|
||||||
datap = _vl_sv_adjusted_datap(varp, nargs - 1, indx1, indx2, indx3);
|
|
||||||
lsb = _vl_sv_adjusted_bit(
|
|
||||||
varp, ((nargs == 1) ? indx1 : (nargs == 2) ? indx2 : (nargs == 3) ? indx3 : indx4));
|
|
||||||
} else {
|
|
||||||
datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3);
|
|
||||||
lsb = 0;
|
|
||||||
}
|
|
||||||
if (VL_UNLIKELY(!datap)) return 0;
|
if (VL_UNLIKELY(!datap)) return 0;
|
||||||
switch (varp->vltype()) {
|
switch (varp->vltype()) { // LCOV_EXCL_BR_LINE
|
||||||
case VLVT_UINT8: return (*(reinterpret_cast<CData*>(datap)) >> lsb) & 1;
|
case VLVT_UINT8: return (*(reinterpret_cast<CData*>(datap))) & 1;
|
||||||
case VLVT_UINT16: return (*(reinterpret_cast<SData*>(datap)) >> lsb) & 1;
|
default: // LCOV_EXCL_START // Errored earlier
|
||||||
case VLVT_UINT32: return (*(reinterpret_cast<IData*>(datap)) >> lsb) & 1;
|
|
||||||
case VLVT_UINT64:
|
|
||||||
return (*(reinterpret_cast<QData*>(datap)) >> static_cast<QData>(lsb)) & VL_ULL(1);
|
|
||||||
case VLVT_WDATA: {
|
|
||||||
WDataOutP wdatap = (reinterpret_cast<WDataOutP>(datap));
|
|
||||||
return VL_BITRSHIFT_W(wdatap, lsb) & 1;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n",
|
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n",
|
||||||
varp->vltype());
|
varp->vltype());
|
||||||
return 0;
|
return 0; // LCOV_EXCL_STOP
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Update simulator open array from bit
|
/// Update simulator open array from bit
|
||||||
@@ -433,27 +401,14 @@ static void _vl_svPutBitArrElem(const svOpenArrayHandle d, svBit value, int narg
|
|||||||
// One extra index supported, as need bit number
|
// One extra index supported, as need bit number
|
||||||
value &= 1; // Make sure clean
|
value &= 1; // Make sure clean
|
||||||
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(d);
|
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(d);
|
||||||
void* datap;
|
void* datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3);
|
||||||
int lsb;
|
|
||||||
if (varp->packed().elements()) {
|
|
||||||
datap = _vl_sv_adjusted_datap(varp, nargs - 1, indx1, indx2, indx3);
|
|
||||||
lsb = _vl_sv_adjusted_bit(
|
|
||||||
varp, ((nargs == 1) ? indx1 : (nargs == 2) ? indx2 : (nargs == 3) ? indx3 : indx4));
|
|
||||||
} else {
|
|
||||||
datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3);
|
|
||||||
lsb = 0;
|
|
||||||
}
|
|
||||||
if (VL_UNLIKELY(!datap)) return;
|
if (VL_UNLIKELY(!datap)) return;
|
||||||
switch (varp->vltype()) {
|
switch (varp->vltype()) { // LCOV_EXCL_BR_LINE
|
||||||
case VLVT_UINT8: VL_ASSIGNBIT_II(-1, lsb, *(reinterpret_cast<CData*>(datap)), value); return;
|
case VLVT_UINT8: *(reinterpret_cast<CData*>(datap)) = value; return;
|
||||||
case VLVT_UINT16: VL_ASSIGNBIT_II(-1, lsb, *(reinterpret_cast<SData*>(datap)), value); return;
|
default: // LCOV_EXCL_START // Errored earlier
|
||||||
case VLVT_UINT32: VL_ASSIGNBIT_II(-1, lsb, *(reinterpret_cast<IData*>(datap)), value); return;
|
|
||||||
case VLVT_UINT64: VL_ASSIGNBIT_QI(-1, lsb, *(reinterpret_cast<QData*>(datap)), value); return;
|
|
||||||
case VLVT_WDATA: VL_ASSIGNBIT_WI(-1, lsb, (reinterpret_cast<WDataOutP>(datap)), value); return;
|
|
||||||
default:
|
|
||||||
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n",
|
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n",
|
||||||
varp->vltype());
|
varp->vltype());
|
||||||
return;
|
return; // LCOV_EXCL_STOP
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -643,13 +598,6 @@ svBit svGetBitArrElem(const svOpenArrayHandle s, int indx1, ...) {
|
|||||||
out = _vl_svGetBitArrElem(s, 3, indx1, indx2, indx3, 0);
|
out = _vl_svGetBitArrElem(s, 3, indx1, indx2, indx3, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 4: {
|
|
||||||
int indx2 = va_arg(ap, int);
|
|
||||||
int indx3 = va_arg(ap, int);
|
|
||||||
int indx4 = va_arg(ap, int);
|
|
||||||
out = _vl_svGetBitArrElem(s, 4, indx1, indx2, indx3, indx4);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: out = _vl_svGetBitArrElem(s, -1, 0, 0, 0, 0); break; // Will error
|
default: out = _vl_svGetBitArrElem(s, -1, 0, 0, 0, 0); break; // Will error
|
||||||
}
|
}
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
@@ -683,13 +631,6 @@ svLogic svGetLogicArrElem(const svOpenArrayHandle s, int indx1, ...) {
|
|||||||
out = _vl_svGetBitArrElem(s, 3, indx1, indx2, indx3, 0);
|
out = _vl_svGetBitArrElem(s, 3, indx1, indx2, indx3, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 4: {
|
|
||||||
int indx2 = va_arg(ap, int);
|
|
||||||
int indx3 = va_arg(ap, int);
|
|
||||||
int indx4 = va_arg(ap, int);
|
|
||||||
out = _vl_svGetBitArrElem(s, 4, indx1, indx2, indx3, indx4);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: out = _vl_svGetBitArrElem(s, -1, 0, 0, 0, 0); break; // Will error
|
default: out = _vl_svGetBitArrElem(s, -1, 0, 0, 0, 0); break; // Will error
|
||||||
}
|
}
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
@@ -725,13 +666,6 @@ void svPutBitArrElem(const svOpenArrayHandle d, svBit value, int indx1, ...) {
|
|||||||
_vl_svPutBitArrElem(d, value, 3, indx1, indx2, indx3, 0);
|
_vl_svPutBitArrElem(d, value, 3, indx1, indx2, indx3, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 4: {
|
|
||||||
int indx2 = va_arg(ap, int);
|
|
||||||
int indx3 = va_arg(ap, int);
|
|
||||||
int indx4 = va_arg(ap, int);
|
|
||||||
_vl_svPutBitArrElem(d, value, 4, indx1, indx2, indx3, indx4);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: _vl_svPutBitArrElem(d, value, -1, 0, 0, 0, 0); break; // Will error
|
default: _vl_svPutBitArrElem(d, value, -1, 0, 0, 0, 0); break; // Will error
|
||||||
}
|
}
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
@@ -763,13 +697,6 @@ void svPutLogicArrElem(const svOpenArrayHandle d, svLogic value, int indx1, ...)
|
|||||||
_vl_svPutBitArrElem(d, value, 3, indx1, indx2, indx3, 0);
|
_vl_svPutBitArrElem(d, value, 3, indx1, indx2, indx3, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 4: {
|
|
||||||
int indx2 = va_arg(ap, int);
|
|
||||||
int indx3 = va_arg(ap, int);
|
|
||||||
int indx4 = va_arg(ap, int);
|
|
||||||
_vl_svPutBitArrElem(d, value, 4, indx1, indx2, indx3, indx4);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: _vl_svPutBitArrElem(d, value, -1, 0, 0, 0, 0); break; // Will error
|
default: _vl_svPutBitArrElem(d, value, -1, 0, 0, 0, 0); break; // Will error
|
||||||
}
|
}
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
@@ -794,7 +721,7 @@ void svPutLogicArrElem3(const svOpenArrayHandle d, svLogic value, int indx1, int
|
|||||||
svScope svGetScope() {
|
svScope svGetScope() {
|
||||||
if (VL_UNLIKELY(!Verilated::dpiInContext())) {
|
if (VL_UNLIKELY(!Verilated::dpiInContext())) {
|
||||||
_VL_SVDPI_CONTEXT_WARN();
|
_VL_SVDPI_CONTEXT_WARN();
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
// NOLINTNEXTLINE(google-readability-casting)
|
// NOLINTNEXTLINE(google-readability-casting)
|
||||||
return (svScope)(Verilated::dpiScope());
|
return (svScope)(Verilated::dpiScope());
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2020 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2021 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// 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
-47
@@ -3,7 +3,7 @@
|
|||||||
//
|
//
|
||||||
// THIS MODULE IS PUBLICLY LICENSED
|
// THIS MODULE IS PUBLICLY LICENSED
|
||||||
//
|
//
|
||||||
// Copyright 2001-2020 by Wilson Snyder. This program is free software; you
|
// Copyright 2001-2021 by Wilson Snyder. This program is free software; you
|
||||||
// can redistribute it and/or modify it under the terms of either the GNU
|
// can 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,17 +36,12 @@
|
|||||||
#include "gtkwave/lz4.c"
|
#include "gtkwave/lz4.c"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cerrno>
|
|
||||||
#include <ctime>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <sys/stat.h>
|
|
||||||
|
|
||||||
#if defined(_WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__)
|
#if defined(_WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__)
|
||||||
# include <io.h>
|
# include <io.h>
|
||||||
#else
|
#else
|
||||||
# include <stdint.h>
|
|
||||||
# include <unistd.h>
|
# include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -63,14 +58,12 @@
|
|||||||
// VerilatedFst
|
// VerilatedFst
|
||||||
|
|
||||||
VerilatedFst::VerilatedFst(void* fst)
|
VerilatedFst::VerilatedFst(void* fst)
|
||||||
: m_fst(fst)
|
: m_fst{fst} {}
|
||||||
, m_symbolp(NULL)
|
|
||||||
, m_strbuf(NULL) {}
|
|
||||||
|
|
||||||
VerilatedFst::~VerilatedFst() {
|
VerilatedFst::~VerilatedFst() {
|
||||||
if (m_fst) fstWriterClose(m_fst);
|
if (m_fst) fstWriterClose(m_fst);
|
||||||
if (m_symbolp) VL_DO_CLEAR(delete[] m_symbolp, m_symbolp = NULL);
|
if (m_symbolp) VL_DO_CLEAR(delete[] m_symbolp, m_symbolp = nullptr);
|
||||||
if (m_strbuf) VL_DO_CLEAR(delete[] m_strbuf, m_strbuf = NULL);
|
if (m_strbuf) VL_DO_CLEAR(delete[] m_strbuf, m_strbuf = nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VerilatedFst::open(const char* filename) VL_MT_UNSAFE {
|
void VerilatedFst::open(const char* filename) VL_MT_UNSAFE {
|
||||||
@@ -87,7 +80,7 @@ void VerilatedFst::open(const char* filename) VL_MT_UNSAFE {
|
|||||||
VerilatedTrace<VerilatedFst>::traceInit();
|
VerilatedTrace<VerilatedFst>::traceInit();
|
||||||
|
|
||||||
// Clear the scope stack
|
// Clear the scope stack
|
||||||
std::list<std::string>::iterator it = m_curScope.begin();
|
auto it = m_curScope.begin();
|
||||||
while (it != m_curScope.end()) {
|
while (it != m_curScope.end()) {
|
||||||
fstWriterSetUpscope(m_fst);
|
fstWriterSetUpscope(m_fst);
|
||||||
it = m_curScope.erase(it);
|
it = m_curScope.erase(it);
|
||||||
@@ -96,10 +89,7 @@ void VerilatedFst::open(const char* filename) VL_MT_UNSAFE {
|
|||||||
// convert m_code2symbol into an array for fast lookup
|
// convert m_code2symbol into an array for fast lookup
|
||||||
if (!m_symbolp) {
|
if (!m_symbolp) {
|
||||||
m_symbolp = new fstHandle[nextCode()];
|
m_symbolp = new fstHandle[nextCode()];
|
||||||
for (Code2SymbolType::iterator it = m_code2symbol.begin(); it != m_code2symbol.end();
|
for (const auto& i : m_code2symbol) m_symbolp[i.first] = i.second;
|
||||||
++it) {
|
|
||||||
m_symbolp[it->first] = it->second;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
m_code2symbol.clear();
|
m_code2symbol.clear();
|
||||||
|
|
||||||
@@ -111,7 +101,7 @@ void VerilatedFst::close() {
|
|||||||
m_assertOne.check();
|
m_assertOne.check();
|
||||||
VerilatedTrace<VerilatedFst>::close();
|
VerilatedTrace<VerilatedFst>::close();
|
||||||
fstWriterClose(m_fst);
|
fstWriterClose(m_fst);
|
||||||
m_fst = NULL;
|
m_fst = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VerilatedFst::flush() {
|
void VerilatedFst::flush() {
|
||||||
@@ -132,23 +122,23 @@ void VerilatedFst::declDTypeEnum(int dtypenum, const char* name, vluint32_t elem
|
|||||||
m_local2fstdtype[dtypenum] = enumNum;
|
m_local2fstdtype[dtypenum] = enumNum;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VerilatedFst::declSymbol(vluint32_t code, const char* name, int dtypenum, fstVarDir vardir,
|
void VerilatedFst::declare(vluint32_t code, const char* name, int dtypenum, fstVarDir vardir,
|
||||||
fstVarType vartype, bool array, int arraynum, vluint32_t len,
|
fstVarType vartype, bool array, int arraynum, int msb, int lsb) {
|
||||||
vluint32_t bits) {
|
const int bits = ((msb > lsb) ? (msb - lsb) : (lsb - msb)) + 1;
|
||||||
|
|
||||||
VerilatedTrace<VerilatedFst>::declCode(code, bits, false);
|
VerilatedTrace<VerilatedFst>::declCode(code, bits, false);
|
||||||
|
|
||||||
std::pair<Code2SymbolType::iterator, bool> p
|
|
||||||
= m_code2symbol.insert(std::make_pair(code, static_cast<fstHandle>(NULL)));
|
|
||||||
std::istringstream nameiss(name);
|
std::istringstream nameiss(name);
|
||||||
std::istream_iterator<std::string> beg(nameiss), end;
|
std::istream_iterator<std::string> beg(nameiss);
|
||||||
|
std::istream_iterator<std::string> end;
|
||||||
std::list<std::string> tokens(beg, end); // Split name
|
std::list<std::string> tokens(beg, end); // Split name
|
||||||
std::string symbol_name(tokens.back());
|
std::string symbol_name(tokens.back());
|
||||||
tokens.pop_back(); // Remove symbol name from hierarchy
|
tokens.pop_back(); // Remove symbol name from hierarchy
|
||||||
tokens.insert(tokens.begin(), moduleName()); // Add current module to the hierarchy
|
tokens.insert(tokens.begin(), moduleName()); // Add current module to the hierarchy
|
||||||
|
|
||||||
// Find point where current and new scope diverge
|
// Find point where current and new scope diverge
|
||||||
std::list<std::string>::iterator cur_it = m_curScope.begin();
|
auto cur_it = m_curScope.begin();
|
||||||
std::list<std::string>::iterator new_it = tokens.begin();
|
auto new_it = tokens.begin();
|
||||||
while (cur_it != m_curScope.end() && new_it != tokens.end()) {
|
while (cur_it != m_curScope.end() && new_it != tokens.end()) {
|
||||||
if (*cur_it != *new_it) break;
|
if (*cur_it != *new_it) break;
|
||||||
++cur_it;
|
++cur_it;
|
||||||
@@ -163,7 +153,7 @@ void VerilatedFst::declSymbol(vluint32_t code, const char* name, int dtypenum, f
|
|||||||
|
|
||||||
// Follow the hierarchy of the new variable from the common scope point
|
// Follow the hierarchy of the new variable from the common scope point
|
||||||
while (new_it != tokens.end()) {
|
while (new_it != tokens.end()) {
|
||||||
fstWriterSetScope(m_fst, FST_ST_VCD_SCOPE, new_it->c_str(), NULL);
|
fstWriterSetScope(m_fst, FST_ST_VCD_SCOPE, new_it->c_str(), nullptr);
|
||||||
m_curScope.push_back(*new_it);
|
m_curScope.push_back(*new_it);
|
||||||
new_it = tokens.erase(new_it);
|
new_it = tokens.erase(new_it);
|
||||||
}
|
}
|
||||||
@@ -177,40 +167,35 @@ void VerilatedFst::declSymbol(vluint32_t code, const char* name, int dtypenum, f
|
|||||||
fstEnumHandle enumNum = m_local2fstdtype[dtypenum];
|
fstEnumHandle enumNum = m_local2fstdtype[dtypenum];
|
||||||
fstWriterEmitEnumTableRef(m_fst, enumNum);
|
fstWriterEmitEnumTableRef(m_fst, enumNum);
|
||||||
}
|
}
|
||||||
if (p.second) { // New
|
|
||||||
p.first->second = fstWriterCreateVar(m_fst, vartype, vardir, len, name_str.c_str(), 0);
|
const auto it = vlstd::as_const(m_code2symbol).find(code);
|
||||||
assert(p.first->second);
|
if (it == m_code2symbol.end()) { // New
|
||||||
|
m_code2symbol[code]
|
||||||
|
= fstWriterCreateVar(m_fst, vartype, vardir, bits, name_str.c_str(), 0);
|
||||||
} else { // Alias
|
} else { // Alias
|
||||||
fstWriterCreateVar(m_fst, vartype, vardir, len, name_str.c_str(), p.first->second);
|
fstWriterCreateVar(m_fst, vartype, vardir, bits, name_str.c_str(), it->second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VerilatedFst::declBit(vluint32_t code, const char* name, int dtypenum, fstVarDir vardir,
|
void VerilatedFst::declBit(vluint32_t code, const char* name, int dtypenum, fstVarDir vardir,
|
||||||
fstVarType vartype, bool array, int arraynum) {
|
fstVarType vartype, bool array, int arraynum) {
|
||||||
declSymbol(code, name, dtypenum, vardir, vartype, array, arraynum, 1, 1);
|
declare(code, name, dtypenum, vardir, vartype, array, arraynum, 0, 0);
|
||||||
}
|
}
|
||||||
void VerilatedFst::declBus(vluint32_t code, const char* name, int dtypenum, fstVarDir vardir,
|
void VerilatedFst::declBus(vluint32_t code, const char* name, int dtypenum, fstVarDir vardir,
|
||||||
fstVarType vartype, bool array, int arraynum, int msb, int lsb) {
|
fstVarType vartype, bool array, int arraynum, int msb, int lsb) {
|
||||||
declSymbol(code, name, dtypenum, vardir, vartype, array, arraynum, msb - lsb + 1,
|
declare(code, name, dtypenum, vardir, vartype, array, arraynum, msb, lsb);
|
||||||
msb - lsb + 1);
|
|
||||||
}
|
}
|
||||||
void VerilatedFst::declQuad(vluint32_t code, const char* name, int dtypenum, fstVarDir vardir,
|
void VerilatedFst::declQuad(vluint32_t code, const char* name, int dtypenum, fstVarDir vardir,
|
||||||
fstVarType vartype, bool array, int arraynum, int msb, int lsb) {
|
fstVarType vartype, bool array, int arraynum, int msb, int lsb) {
|
||||||
declSymbol(code, name, dtypenum, vardir, vartype, array, arraynum, msb - lsb + 1,
|
declare(code, name, dtypenum, vardir, vartype, array, arraynum, msb, lsb);
|
||||||
msb - lsb + 1);
|
|
||||||
}
|
}
|
||||||
void VerilatedFst::declArray(vluint32_t code, const char* name, int dtypenum, fstVarDir vardir,
|
void VerilatedFst::declArray(vluint32_t code, const char* name, int dtypenum, fstVarDir vardir,
|
||||||
fstVarType vartype, bool array, int arraynum, int msb, int lsb) {
|
fstVarType vartype, bool array, int arraynum, int msb, int lsb) {
|
||||||
declSymbol(code, name, dtypenum, vardir, vartype, array, arraynum, msb - lsb + 1,
|
declare(code, name, dtypenum, vardir, vartype, array, arraynum, msb, lsb);
|
||||||
msb - lsb + 1);
|
|
||||||
}
|
|
||||||
void VerilatedFst::declFloat(vluint32_t code, const char* name, int dtypenum, fstVarDir vardir,
|
|
||||||
fstVarType vartype, bool array, int arraynum) {
|
|
||||||
declSymbol(code, name, dtypenum, vardir, vartype, array, arraynum, 1, 32);
|
|
||||||
}
|
}
|
||||||
void VerilatedFst::declDouble(vluint32_t code, const char* name, int dtypenum, fstVarDir vardir,
|
void VerilatedFst::declDouble(vluint32_t code, const char* name, int dtypenum, fstVarDir vardir,
|
||||||
fstVarType vartype, bool array, int arraynum) {
|
fstVarType vartype, bool array, int arraynum) {
|
||||||
declSymbol(code, name, dtypenum, vardir, vartype, array, arraynum, 2, 64);
|
declare(code, name, dtypenum, vardir, vartype, array, arraynum, 63, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: emit* are only ever called from one place (full* in
|
// Note: emit* are only ever called from one place (full* in
|
||||||
@@ -266,11 +251,6 @@ void VerilatedFst::emitWData(vluint32_t code, const WData* newvalp, int bits) {
|
|||||||
fstWriterEmitValueChange(m_fst, m_symbolp[code], m_strbuf);
|
fstWriterEmitValueChange(m_fst, m_symbolp[code], m_strbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
VL_ATTR_ALWINLINE
|
|
||||||
void VerilatedFst::emitFloat(vluint32_t code, float newval) {
|
|
||||||
fstWriterEmitValueChange(m_fst, m_symbolp[code], &newval);
|
|
||||||
}
|
|
||||||
|
|
||||||
VL_ATTR_ALWINLINE
|
VL_ATTR_ALWINLINE
|
||||||
void VerilatedFst::emitDouble(vluint32_t code, double newval) {
|
void VerilatedFst::emitDouble(vluint32_t code, double newval) {
|
||||||
fstWriterEmitValueChange(m_fst, m_symbolp[code], &newval);
|
fstWriterEmitValueChange(m_fst, m_symbolp[code], &newval);
|
||||||
|
|||||||
+14
-17
@@ -3,7 +3,7 @@
|
|||||||
//
|
//
|
||||||
// THIS MODULE IS PUBLICLY LICENSED
|
// THIS MODULE IS PUBLICLY LICENSED
|
||||||
//
|
//
|
||||||
// Copyright 2001-2020 by Wilson Snyder. This program is free software; you
|
// Copyright 2001-2021 by Wilson Snyder. This program is free software; you
|
||||||
// can redistribute it and/or modify it under the terms of either the GNU
|
// can 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.
|
||||||
@@ -35,7 +35,7 @@
|
|||||||
/// Base class to create a Verilator FST dump
|
/// Base class to create a Verilator FST dump
|
||||||
/// This is an internally used class - see VerilatedFstC for what to call from applications
|
/// This is an internally used class - see VerilatedFstC for what to call from applications
|
||||||
|
|
||||||
class VerilatedFst : public VerilatedTrace<VerilatedFst> {
|
class VerilatedFst final : public VerilatedTrace<VerilatedFst> {
|
||||||
private:
|
private:
|
||||||
// Give the superclass access to private bits (to avoid virtual functions)
|
// Give the superclass access to private bits (to avoid virtual functions)
|
||||||
friend class VerilatedTrace<VerilatedFst>;
|
friend class VerilatedTrace<VerilatedFst>;
|
||||||
@@ -50,24 +50,24 @@ private:
|
|||||||
Code2SymbolType m_code2symbol;
|
Code2SymbolType m_code2symbol;
|
||||||
Local2FstDtype m_local2fstdtype;
|
Local2FstDtype m_local2fstdtype;
|
||||||
std::list<std::string> m_curScope;
|
std::list<std::string> m_curScope;
|
||||||
fstHandle* m_symbolp; ///< same as m_code2symbol, but as an array
|
fstHandle* m_symbolp = nullptr; ///< same as m_code2symbol, but as an array
|
||||||
char* m_strbuf; ///< String buffer long enough to hold maxBits() chars
|
char* m_strbuf = nullptr; ///< String buffer long enough to hold maxBits() chars
|
||||||
|
|
||||||
// CONSTRUCTORS
|
// CONSTRUCTORS
|
||||||
VL_UNCOPYABLE(VerilatedFst);
|
VL_UNCOPYABLE(VerilatedFst);
|
||||||
void declSymbol(vluint32_t code, const char* name, int dtypenum, fstVarDir vardir,
|
void declare(vluint32_t code, const char* name, int dtypenum, fstVarDir vardir,
|
||||||
fstVarType vartype, bool array, int arraynum, vluint32_t len, vluint32_t bits);
|
fstVarType vartype, bool array, int arraynum, int msb, int lsb);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
//=========================================================================
|
//=========================================================================
|
||||||
// Implementation of VerilatedTrace interface
|
// Implementation of VerilatedTrace interface
|
||||||
|
|
||||||
// Implementations of protected virtual methods for VerilatedTrace
|
// Implementations of protected virtual methods for VerilatedTrace
|
||||||
void emitTimeChange(vluint64_t timeui) VL_OVERRIDE;
|
virtual void emitTimeChange(vluint64_t timeui) override;
|
||||||
|
|
||||||
// Hooks called from VerilatedTrace
|
// Hooks called from VerilatedTrace
|
||||||
bool preFullDump() VL_OVERRIDE { return isOpen(); }
|
virtual bool preFullDump() override { return isOpen(); }
|
||||||
bool preChangeDump() VL_OVERRIDE { return isOpen(); }
|
virtual bool preChangeDump() override { return isOpen(); }
|
||||||
|
|
||||||
// Implementations of duck-typed methods for VerilatedTrace. These are
|
// Implementations of duck-typed methods for VerilatedTrace. These are
|
||||||
// called from only one place (namely full*) so always inline them.
|
// called from only one place (namely full*) so always inline them.
|
||||||
@@ -77,14 +77,13 @@ protected:
|
|||||||
inline void emitIData(vluint32_t code, IData newval, int bits);
|
inline void emitIData(vluint32_t code, IData newval, int bits);
|
||||||
inline void emitQData(vluint32_t code, QData newval, int bits);
|
inline void emitQData(vluint32_t code, QData newval, int bits);
|
||||||
inline void emitWData(vluint32_t code, const WData* newvalp, int bits);
|
inline void emitWData(vluint32_t code, const WData* newvalp, int bits);
|
||||||
inline void emitFloat(vluint32_t code, float newval);
|
|
||||||
inline void emitDouble(vluint32_t code, double newval);
|
inline void emitDouble(vluint32_t code, double newval);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
//=========================================================================
|
//=========================================================================
|
||||||
// External interface to client code
|
// External interface to client code
|
||||||
|
|
||||||
explicit VerilatedFst(void* fst = NULL);
|
explicit VerilatedFst(void* fst = nullptr);
|
||||||
~VerilatedFst();
|
~VerilatedFst();
|
||||||
|
|
||||||
/// Open the file; call isOpen() to see if errors
|
/// Open the file; call isOpen() to see if errors
|
||||||
@@ -94,7 +93,7 @@ public:
|
|||||||
/// Flush any remaining data to this file
|
/// Flush any remaining data to this file
|
||||||
void flush() VL_MT_UNSAFE;
|
void flush() VL_MT_UNSAFE;
|
||||||
/// Is file open?
|
/// Is file open?
|
||||||
bool isOpen() const { return m_fst != NULL; }
|
bool isOpen() const { return m_fst != nullptr; }
|
||||||
|
|
||||||
//=========================================================================
|
//=========================================================================
|
||||||
// Internal interface to Verilator generated code
|
// Internal interface to Verilator generated code
|
||||||
@@ -112,8 +111,6 @@ public:
|
|||||||
fstVarType vartype, bool array, int arraynum, int msb, int lsb);
|
fstVarType vartype, bool array, int arraynum, int msb, int lsb);
|
||||||
void declArray(vluint32_t code, const char* name, int dtypenum, fstVarDir vardir,
|
void declArray(vluint32_t code, const char* name, int dtypenum, fstVarDir vardir,
|
||||||
fstVarType vartype, bool array, int arraynum, int msb, int lsb);
|
fstVarType vartype, bool array, int arraynum, int msb, int lsb);
|
||||||
void declFloat(vluint32_t code, const char* name, int dtypenum, fstVarDir vardir,
|
|
||||||
fstVarType vartype, bool array, int arraynum);
|
|
||||||
void declDouble(vluint32_t code, const char* name, int dtypenum, fstVarDir vardir,
|
void declDouble(vluint32_t code, const char* name, int dtypenum, fstVarDir vardir,
|
||||||
fstVarType vartype, bool array, int arraynum);
|
fstVarType vartype, bool array, int arraynum);
|
||||||
};
|
};
|
||||||
@@ -131,15 +128,15 @@ template <> void VerilatedTrace<VerilatedFst>::set_time_resolution(const std::st
|
|||||||
/// Also derived for use in SystemC simulations.
|
/// Also derived for use in SystemC simulations.
|
||||||
/// Thread safety: Unless otherwise indicated, every function is VL_MT_UNSAFE_ONE
|
/// Thread safety: Unless otherwise indicated, every function is VL_MT_UNSAFE_ONE
|
||||||
|
|
||||||
class VerilatedFstC {
|
class VerilatedFstC final {
|
||||||
VerilatedFst m_sptrace; ///< Trace file being created
|
VerilatedFst m_sptrace; ///< Trace file being created
|
||||||
|
|
||||||
// CONSTRUCTORS
|
// CONSTRUCTORS
|
||||||
VL_UNCOPYABLE(VerilatedFstC);
|
VL_UNCOPYABLE(VerilatedFstC);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit VerilatedFstC(void* filep = NULL)
|
explicit VerilatedFstC(void* filep = nullptr)
|
||||||
: m_sptrace(filep) {}
|
: m_sptrace{filep} {}
|
||||||
~VerilatedFstC() { close(); }
|
~VerilatedFstC() { close(); }
|
||||||
/// Routines can only be called from one thread; allow next call from different thread
|
/// Routines can only be called from one thread; allow next call from different thread
|
||||||
void changeThread() { spTrace()->changeThread(); }
|
void changeThread() { spTrace()->changeThread(); }
|
||||||
|
|||||||
+644
-182
@@ -1,7 +1,7 @@
|
|||||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2010-2020 by Wilson Snyder. This program is free software; you can
|
// Copyright 2010-2021 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// 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,10 +26,13 @@
|
|||||||
|
|
||||||
#include "verilated.h"
|
#include "verilated.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <set>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
//===================================================================
|
//===================================================================
|
||||||
// String formatters (required by below containers)
|
// String formatters (required by below containers)
|
||||||
@@ -41,10 +44,21 @@ extern std::string VL_TO_STRING(QData lhs);
|
|||||||
inline std::string VL_TO_STRING(const std::string& obj) { return "\"" + obj + "\""; }
|
inline std::string VL_TO_STRING(const std::string& obj) { return "\"" + obj + "\""; }
|
||||||
extern std::string VL_TO_STRING_W(int words, WDataInP obj);
|
extern std::string VL_TO_STRING_W(int words, WDataInP obj);
|
||||||
|
|
||||||
|
//===================================================================
|
||||||
|
// Shuffle RNG
|
||||||
|
|
||||||
|
class VlURNG final {
|
||||||
|
public:
|
||||||
|
typedef size_t result_type;
|
||||||
|
static constexpr size_t min() { return 0; }
|
||||||
|
static constexpr size_t max() { return 1ULL << 31; }
|
||||||
|
size_t operator()() { return VL_MASK_I(31) & VL_RANDOM_I(32); }
|
||||||
|
};
|
||||||
|
|
||||||
//===================================================================
|
//===================================================================
|
||||||
// Readmem/Writemem operation classes
|
// Readmem/Writemem operation classes
|
||||||
|
|
||||||
class VlReadMem {
|
class VlReadMem final {
|
||||||
bool m_hex; // Hex format
|
bool m_hex; // Hex format
|
||||||
int m_bits; // Bit width of values
|
int m_bits; // Bit width of values
|
||||||
const std::string& m_filename; // Filename
|
const std::string& m_filename; // Filename
|
||||||
@@ -55,41 +69,52 @@ class VlReadMem {
|
|||||||
public:
|
public:
|
||||||
VlReadMem(bool hex, int bits, const std::string& filename, QData start, QData end);
|
VlReadMem(bool hex, int bits, const std::string& filename, QData start, QData end);
|
||||||
~VlReadMem();
|
~VlReadMem();
|
||||||
bool isOpen() const { return m_fp != NULL; }
|
bool isOpen() const { return m_fp != nullptr; }
|
||||||
int linenum() const { return m_linenum; }
|
int linenum() const { return m_linenum; }
|
||||||
bool get(QData& addrr, std::string& valuer);
|
bool get(QData& addrr, std::string& valuer);
|
||||||
void setData(void* valuep, const std::string& rhs);
|
void setData(void* valuep, const std::string& rhs);
|
||||||
};
|
};
|
||||||
|
|
||||||
class VlWriteMem {
|
class VlWriteMem final {
|
||||||
|
bool m_hex; // Hex format
|
||||||
int m_bits; // Bit width of values
|
int m_bits; // Bit width of values
|
||||||
FILE* m_fp; // File handle for filename
|
FILE* m_fp; // File handle for filename
|
||||||
QData m_addr; // Next address to write
|
QData m_addr; // Next address to write
|
||||||
public:
|
public:
|
||||||
VlWriteMem(bool hex, int bits, const std::string& filename, QData start, QData end);
|
VlWriteMem(bool hex, int bits, const std::string& filename, QData start, QData end);
|
||||||
~VlWriteMem();
|
~VlWriteMem();
|
||||||
bool isOpen() const { return m_fp != NULL; }
|
bool isOpen() const { return m_fp != nullptr; }
|
||||||
void print(QData addr, bool addrstamp, const void* valuep);
|
void print(QData addr, bool addrstamp, const void* valuep);
|
||||||
};
|
};
|
||||||
|
|
||||||
//===================================================================
|
//===================================================================
|
||||||
// Verilog array container
|
// Verilog wide-number-in-array container
|
||||||
// Similar to std::array<WData, N>, but:
|
// Similar to std::array<WData, N>, but lighter weight, only methods needed
|
||||||
// 1. Doesn't require C++11
|
// by Verilator, to help compile time.
|
||||||
// 2. Lighter weight, only methods needed by Verilator, to help compile time.
|
|
||||||
//
|
//
|
||||||
// This is only used when we need an upper-level container and so can't
|
// This is only used when we need an upper-level container and so can't
|
||||||
// simply use a C style array (which is just a pointer).
|
// simply use a C style array (which is just a pointer).
|
||||||
|
|
||||||
template <std::size_t T_Words> class VlWide {
|
template <std::size_t T_Words> class VlWide final {
|
||||||
WData m_storage[T_Words];
|
EData m_storage[T_Words];
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// cppcheck-suppress uninitVar
|
// cppcheck-suppress uninitVar
|
||||||
VlWide() {}
|
VlWide() = default;
|
||||||
~VlWide() {}
|
~VlWide() = default;
|
||||||
const WData& at(size_t index) const { return m_storage[index]; }
|
VlWide(const VlWide&) = default;
|
||||||
WData& at(size_t index) { return m_storage[index]; }
|
VlWide(VlWide&&) = default;
|
||||||
|
|
||||||
|
// OPERATOR METHODS
|
||||||
|
VlWide& operator=(const VlWide&) = default;
|
||||||
|
VlWide& operator=(VlWide&&) = default;
|
||||||
|
const EData& operator[](size_t index) const { return m_storage[index]; };
|
||||||
|
EData& operator[](size_t index) { return m_storage[index]; };
|
||||||
|
operator WDataOutP() { return &m_storage[0]; }
|
||||||
|
|
||||||
|
// METHODS
|
||||||
|
const EData& at(size_t index) const { return m_storage[index]; }
|
||||||
|
EData& at(size_t index) { return m_storage[index]; }
|
||||||
WData* data() { return &m_storage[0]; }
|
WData* data() { return &m_storage[0]; }
|
||||||
const WData* data() const { return &m_storage[0]; }
|
const WData* data() const { return &m_storage[0]; }
|
||||||
bool operator<(const VlWide<T_Words>& rhs) const {
|
bool operator<(const VlWide<T_Words>& rhs) const {
|
||||||
@@ -107,145 +132,6 @@ template <std::size_t T_Words> std::string VL_TO_STRING(const VlWide<T_Words>& o
|
|||||||
return VL_TO_STRING_W(T_Words, obj.data());
|
return VL_TO_STRING_W(T_Words, obj.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
//===================================================================
|
|
||||||
// Verilog associative array container
|
|
||||||
// There are no multithreaded locks on this; the base variable must
|
|
||||||
// be protected by other means
|
|
||||||
//
|
|
||||||
template <class T_Key, class T_Value> class VlAssocArray {
|
|
||||||
private:
|
|
||||||
// TYPES
|
|
||||||
typedef std::map<T_Key, T_Value> Map;
|
|
||||||
|
|
||||||
public:
|
|
||||||
typedef typename Map::const_iterator const_iterator;
|
|
||||||
|
|
||||||
private:
|
|
||||||
// MEMBERS
|
|
||||||
Map m_map; // State of the assoc array
|
|
||||||
T_Value m_defaultValue; // Default value
|
|
||||||
|
|
||||||
public:
|
|
||||||
// CONSTRUCTORS
|
|
||||||
VlAssocArray() {
|
|
||||||
// m_defaultValue isn't defaulted. Caller's constructor must do it.
|
|
||||||
}
|
|
||||||
~VlAssocArray() {}
|
|
||||||
// Standard copy constructor works. Verilog: assoca = assocb
|
|
||||||
|
|
||||||
// METHODS
|
|
||||||
T_Value& atDefault() { return m_defaultValue; }
|
|
||||||
|
|
||||||
// Size of array. Verilog: function int size(), or int num()
|
|
||||||
int size() const { return m_map.size(); }
|
|
||||||
// Clear array. Verilog: function void delete([input index])
|
|
||||||
void clear() { m_map.clear(); }
|
|
||||||
void erase(const T_Key& index) { m_map.erase(index); }
|
|
||||||
// Return 0/1 if element exists. Verilog: function int exists(input index)
|
|
||||||
int exists(const T_Key& index) const { return m_map.find(index) != m_map.end(); }
|
|
||||||
// Return first element. Verilog: function int first(ref index);
|
|
||||||
int first(T_Key& indexr) const {
|
|
||||||
typename Map::const_iterator it = m_map.begin();
|
|
||||||
if (it == m_map.end()) return 0;
|
|
||||||
indexr = it->first;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
// Return last element. Verilog: function int last(ref index)
|
|
||||||
int last(T_Key& indexr) const {
|
|
||||||
typename Map::const_reverse_iterator it = m_map.rbegin();
|
|
||||||
if (it == m_map.rend()) return 0;
|
|
||||||
indexr = it->first;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
// Return next element. Verilog: function int next(ref index)
|
|
||||||
int next(T_Key& indexr) const {
|
|
||||||
typename Map::const_iterator it = m_map.find(indexr);
|
|
||||||
if (VL_UNLIKELY(it == m_map.end())) return 0;
|
|
||||||
++it;
|
|
||||||
if (VL_UNLIKELY(it == m_map.end())) return 0;
|
|
||||||
indexr = it->first;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
// Return prev element. Verilog: function int prev(ref index)
|
|
||||||
int prev(T_Key& indexr) const {
|
|
||||||
typename Map::const_iterator it = m_map.find(indexr);
|
|
||||||
if (VL_UNLIKELY(it == m_map.end())) return 0;
|
|
||||||
if (VL_UNLIKELY(it == m_map.begin())) return 0;
|
|
||||||
--it;
|
|
||||||
indexr = it->first;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
// Setting. Verilog: assoc[index] = v
|
|
||||||
// Can't just overload operator[] or provide a "at" reference to set,
|
|
||||||
// because we need to be able to insert only when the value is set
|
|
||||||
T_Value& at(const T_Key& index) {
|
|
||||||
typename Map::iterator it = m_map.find(index);
|
|
||||||
if (it == m_map.end()) {
|
|
||||||
std::pair<typename Map::iterator, bool> pit
|
|
||||||
= m_map.insert(std::make_pair(index, m_defaultValue));
|
|
||||||
return pit.first->second;
|
|
||||||
}
|
|
||||||
return it->second;
|
|
||||||
}
|
|
||||||
// Accessing. Verilog: v = assoc[index]
|
|
||||||
const T_Value& at(const T_Key& index) const {
|
|
||||||
typename Map::iterator it = m_map.find(index);
|
|
||||||
if (it == m_map.end()) {
|
|
||||||
return m_defaultValue;
|
|
||||||
} else {
|
|
||||||
return it->second;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// For save/restore
|
|
||||||
const_iterator begin() const { return m_map.begin(); }
|
|
||||||
const_iterator end() const { return m_map.end(); }
|
|
||||||
|
|
||||||
// Dumping. Verilog: str = $sformatf("%p", assoc)
|
|
||||||
std::string to_string() const {
|
|
||||||
std::string out = "'{";
|
|
||||||
std::string comma;
|
|
||||||
for (typename Map::const_iterator it = m_map.begin(); it != m_map.end(); ++it) {
|
|
||||||
out += comma + VL_TO_STRING(it->first) + ":" + VL_TO_STRING(it->second);
|
|
||||||
comma = ", ";
|
|
||||||
}
|
|
||||||
// Default not printed - maybe random init data
|
|
||||||
return out + "} ";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class T_Key, class T_Value>
|
|
||||||
std::string VL_TO_STRING(const VlAssocArray<T_Key, T_Value>& obj) {
|
|
||||||
return obj.to_string();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T_Key, class T_Value>
|
|
||||||
void VL_READMEM_N(bool hex, int bits, const std::string& filename,
|
|
||||||
VlAssocArray<T_Key, T_Value>& obj, QData start, QData end) VL_MT_SAFE {
|
|
||||||
VlReadMem rmem(hex, bits, filename, start, end);
|
|
||||||
if (VL_UNLIKELY(!rmem.isOpen())) return;
|
|
||||||
while (true) {
|
|
||||||
QData addr;
|
|
||||||
std::string data;
|
|
||||||
if (rmem.get(addr /*ref*/, data /*ref*/)) {
|
|
||||||
rmem.setData(&(obj.at(addr)), data);
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T_Key, class T_Value>
|
|
||||||
void VL_WRITEMEM_N(bool hex, int bits, const std::string& filename,
|
|
||||||
const VlAssocArray<T_Key, T_Value>& obj, QData start, QData end) VL_MT_SAFE {
|
|
||||||
VlWriteMem wmem(hex, bits, filename, start, end);
|
|
||||||
if (VL_UNLIKELY(!wmem.isOpen())) return;
|
|
||||||
for (typename VlAssocArray<T_Key, T_Value>::const_iterator it = obj.begin(); it != obj.end();
|
|
||||||
++it) {
|
|
||||||
QData addr = it->first;
|
|
||||||
if (addr >= start && addr <= end) wmem.print(addr, true, &(it->second));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//===================================================================
|
//===================================================================
|
||||||
// Verilog queue and dynamic array container
|
// Verilog queue and dynamic array container
|
||||||
// There are no multithreaded locks on this; the base variable must
|
// There are no multithreaded locks on this; the base variable must
|
||||||
@@ -253,7 +139,7 @@ void VL_WRITEMEM_N(bool hex, int bits, const std::string& filename,
|
|||||||
//
|
//
|
||||||
// Bound here is the maximum size() allowed, e.g. 1 + SystemVerilog bound
|
// Bound here is the maximum size() allowed, e.g. 1 + SystemVerilog bound
|
||||||
// For dynamic arrays it is always zero
|
// For dynamic arrays it is always zero
|
||||||
template <class T_Value, size_t T_MaxSize = 0> class VlQueue {
|
template <class T_Value, size_t T_MaxSize = 0> class VlQueue final {
|
||||||
private:
|
private:
|
||||||
// TYPES
|
// TYPES
|
||||||
typedef std::deque<T_Value> Deque;
|
typedef std::deque<T_Value> Deque;
|
||||||
@@ -268,21 +154,61 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
// CONSTRUCTORS
|
// CONSTRUCTORS
|
||||||
VlQueue() {
|
// m_defaultValue isn't defaulted. Caller's constructor must do it.
|
||||||
// m_defaultValue isn't defaulted. Caller's constructor must do it.
|
VlQueue() = default;
|
||||||
}
|
~VlQueue() = default;
|
||||||
~VlQueue() {}
|
VlQueue(const VlQueue&) = default;
|
||||||
|
VlQueue(VlQueue&&) = default;
|
||||||
|
VlQueue& operator=(const VlQueue&) = default;
|
||||||
|
VlQueue& operator=(VlQueue&&) = default;
|
||||||
|
|
||||||
// Standard copy constructor works. Verilog: assoca = assocb
|
// Standard copy constructor works. Verilog: assoca = assocb
|
||||||
|
// Also must allow conversion from a different T_MaxSize queue
|
||||||
|
template <size_t U_MaxSize = 0> VlQueue operator=(const VlQueue<T_Value, U_MaxSize>& rhs) {
|
||||||
|
m_deque = rhs.privateDeque();
|
||||||
|
if (VL_UNLIKELY(T_MaxSize && T_MaxSize < m_deque.size())) m_deque.resize(T_MaxSize - 1);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VlQueue cons(const T_Value& lhs) {
|
||||||
|
VlQueue out;
|
||||||
|
out.push_back(lhs);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
static VlQueue cons(const T_Value& lhs, const T_Value& rhs) {
|
||||||
|
VlQueue out;
|
||||||
|
out.push_back(rhs);
|
||||||
|
out.push_back(lhs);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
static VlQueue cons(const VlQueue& lhs, const T_Value& rhs) {
|
||||||
|
VlQueue out = lhs;
|
||||||
|
out.push_front(rhs);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
static VlQueue cons(const T_Value& lhs, const VlQueue& rhs) {
|
||||||
|
VlQueue out = rhs;
|
||||||
|
out.push_back(lhs);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
static VlQueue cons(const VlQueue& lhs, const VlQueue& rhs) {
|
||||||
|
VlQueue out = rhs;
|
||||||
|
for (const auto& i : lhs.m_deque) out.push_back(i);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
T_Value& atDefault() { return m_defaultValue; }
|
T_Value& atDefault() { return m_defaultValue; }
|
||||||
|
const T_Value& atDefault() const { return m_defaultValue; }
|
||||||
|
const Deque& privateDeque() const { return m_deque; }
|
||||||
|
|
||||||
// Size. Verilog: function int size(), or int num()
|
// Size. Verilog: function int size(), or int num()
|
||||||
int size() const { return m_deque.size(); }
|
int size() const { return m_deque.size(); }
|
||||||
// Clear array. Verilog: function void delete([input index])
|
// Clear array. Verilog: function void delete([input index])
|
||||||
void clear() { m_deque.clear(); }
|
void clear() { m_deque.clear(); }
|
||||||
void erase(size_t index) {
|
void erase(vlsint32_t index) {
|
||||||
if (VL_LIKELY(index < m_deque.size())) m_deque.erase(index);
|
if (VL_LIKELY(index >= 0 && index < m_deque.size()))
|
||||||
|
m_deque.erase(m_deque.begin() + index);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dynamic array new[] becomes a renew()
|
// Dynamic array new[] becomes a renew()
|
||||||
@@ -327,10 +253,10 @@ public:
|
|||||||
// Setting. Verilog: assoc[index] = v
|
// Setting. Verilog: assoc[index] = v
|
||||||
// Can't just overload operator[] or provide a "at" reference to set,
|
// Can't just overload operator[] or provide a "at" reference to set,
|
||||||
// because we need to be able to insert only when the value is set
|
// because we need to be able to insert only when the value is set
|
||||||
T_Value& at(size_t index) {
|
T_Value& at(vlsint32_t index) {
|
||||||
static T_Value s_throwAway;
|
static T_Value s_throwAway;
|
||||||
// Needs to work for dynamic arrays, so does not use T_MaxSize
|
// Needs to work for dynamic arrays, so does not use T_MaxSize
|
||||||
if (VL_UNLIKELY(index >= m_deque.size())) {
|
if (VL_UNLIKELY(index < 0 || index >= m_deque.size())) {
|
||||||
s_throwAway = atDefault();
|
s_throwAway = atDefault();
|
||||||
return s_throwAway;
|
return s_throwAway;
|
||||||
} else {
|
} else {
|
||||||
@@ -338,31 +264,221 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Accessing. Verilog: v = assoc[index]
|
// Accessing. Verilog: v = assoc[index]
|
||||||
const T_Value& at(size_t index) const {
|
const T_Value& at(vlsint32_t index) const {
|
||||||
static T_Value s_throwAway;
|
static T_Value s_throwAway;
|
||||||
// Needs to work for dynamic arrays, so does not use T_MaxSize
|
// Needs to work for dynamic arrays, so does not use T_MaxSize
|
||||||
if (VL_UNLIKELY(index >= m_deque.size())) {
|
if (VL_UNLIKELY(index < 0 || index >= m_deque.size())) {
|
||||||
return atDefault();
|
return atDefault();
|
||||||
} else {
|
} else {
|
||||||
return m_deque[index];
|
return m_deque[index];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// function void q.insert(index, value);
|
// function void q.insert(index, value);
|
||||||
void insert(size_t index, const T_Value& value) {
|
void insert(vlsint32_t index, const T_Value& value) {
|
||||||
if (VL_UNLIKELY(index >= m_deque.size())) return;
|
if (VL_UNLIKELY(index < 0 || index >= m_deque.size())) return;
|
||||||
m_deque[index] = value;
|
m_deque.insert(m_deque.begin() + index, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return slice q[lsb:msb]
|
||||||
|
VlQueue slice(vlsint32_t lsb, vlsint32_t msb) const {
|
||||||
|
VlQueue out;
|
||||||
|
if (VL_UNLIKELY(lsb < 0)) lsb = 0;
|
||||||
|
if (VL_UNLIKELY(lsb >= m_deque.size())) lsb = m_deque.size() - 1;
|
||||||
|
if (VL_UNLIKELY(msb >= m_deque.size())) msb = m_deque.size() - 1;
|
||||||
|
for (vlsint32_t i = lsb; i <= msb; ++i) out.push_back(m_deque[i]);
|
||||||
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
// For save/restore
|
// For save/restore
|
||||||
const_iterator begin() const { return m_deque.begin(); }
|
const_iterator begin() const { return m_deque.begin(); }
|
||||||
const_iterator end() const { return m_deque.end(); }
|
const_iterator end() const { return m_deque.end(); }
|
||||||
|
|
||||||
|
// Methods
|
||||||
|
void sort() { std::sort(m_deque.begin(), m_deque.end()); }
|
||||||
|
template <typename Func> void sort(Func with_func) {
|
||||||
|
// with_func returns arbitrary type to use for the sort comparison
|
||||||
|
std::sort(m_deque.begin(), m_deque.end(), [=](const T_Value& a, const T_Value& b) {
|
||||||
|
// index number is meaninless with sort, as it changes
|
||||||
|
return with_func(0, a) < with_func(0, b);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
void rsort() { std::sort(m_deque.rbegin(), m_deque.rend()); }
|
||||||
|
template <typename Func> void rsort(Func with_func) {
|
||||||
|
// with_func returns arbitrary type to use for the sort comparison
|
||||||
|
std::sort(m_deque.rbegin(), m_deque.rend(), [=](const T_Value& a, const T_Value& b) {
|
||||||
|
// index number is meaninless with sort, as it changes
|
||||||
|
return with_func(0, a) < with_func(0, b);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
void reverse() { std::reverse(m_deque.begin(), m_deque.end()); }
|
||||||
|
void shuffle() { std::shuffle(m_deque.begin(), m_deque.end(), VlURNG()); }
|
||||||
|
VlQueue unique() const {
|
||||||
|
VlQueue out;
|
||||||
|
std::unordered_set<T_Value> saw;
|
||||||
|
for (const auto& i : m_deque) {
|
||||||
|
auto it = saw.find(i);
|
||||||
|
if (it == saw.end()) {
|
||||||
|
saw.insert(it, i);
|
||||||
|
out.push_back(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
VlQueue<IData> unique_index() const {
|
||||||
|
VlQueue<IData> out;
|
||||||
|
IData index = 0;
|
||||||
|
std::unordered_set<T_Value> saw;
|
||||||
|
for (const auto& i : m_deque) {
|
||||||
|
auto it = saw.find(i);
|
||||||
|
if (it == saw.end()) {
|
||||||
|
saw.insert(it, i);
|
||||||
|
out.push_back(index);
|
||||||
|
}
|
||||||
|
++index;
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
template <typename Func> VlQueue find(Func with_func) const {
|
||||||
|
VlQueue out;
|
||||||
|
IData index = 0;
|
||||||
|
for (const auto& i : m_deque) {
|
||||||
|
if (with_func(index, i)) out.push_back(i);
|
||||||
|
++index;
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
template <typename Func> VlQueue<IData> find_index(Func with_func) const {
|
||||||
|
VlQueue<IData> out;
|
||||||
|
IData index = 0;
|
||||||
|
for (const auto& i : m_deque) {
|
||||||
|
if (with_func(index, i)) out.push_back(index);
|
||||||
|
++index;
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
template <typename Func> VlQueue find_first(Func with_func) const {
|
||||||
|
// Can't use std::find_if as need index number
|
||||||
|
IData index = 0;
|
||||||
|
for (const auto& i : m_deque) {
|
||||||
|
if (with_func(index, i)) return VlQueue::cons(i);
|
||||||
|
++index;
|
||||||
|
}
|
||||||
|
return VlQueue{};
|
||||||
|
}
|
||||||
|
template <typename Func> VlQueue<IData> find_first_index(Func with_func) const {
|
||||||
|
IData index = 0;
|
||||||
|
for (const auto& i : m_deque) {
|
||||||
|
if (with_func(index, i)) return VlQueue<IData>::cons(index);
|
||||||
|
++index;
|
||||||
|
}
|
||||||
|
return VlQueue<IData>{};
|
||||||
|
}
|
||||||
|
template <typename Func> VlQueue find_last(Func with_func) const {
|
||||||
|
IData index = m_deque.size() - 1;
|
||||||
|
for (auto it = m_deque.rbegin(); it != m_deque.rend(); ++it) {
|
||||||
|
if (with_func(index, *it)) return VlQueue::cons(*it);
|
||||||
|
--index;
|
||||||
|
}
|
||||||
|
return VlQueue{};
|
||||||
|
}
|
||||||
|
template <typename Func> VlQueue<IData> find_last_index(Func with_func) const {
|
||||||
|
IData index = m_deque.size() - 1;
|
||||||
|
for (auto it = m_deque.rbegin(); it != m_deque.rend(); ++it) {
|
||||||
|
if (with_func(index, *it)) return VlQueue<IData>::cons(index);
|
||||||
|
--index;
|
||||||
|
}
|
||||||
|
return VlQueue<IData>{};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reduction operators
|
||||||
|
VlQueue min() const {
|
||||||
|
if (m_deque.empty()) return VlQueue();
|
||||||
|
const auto it = std::min_element(m_deque.begin(), m_deque.end());
|
||||||
|
return VlQueue::cons(*it);
|
||||||
|
}
|
||||||
|
VlQueue max() const {
|
||||||
|
if (m_deque.empty()) return VlQueue();
|
||||||
|
const auto it = std::max_element(m_deque.begin(), m_deque.end());
|
||||||
|
return VlQueue::cons(*it);
|
||||||
|
}
|
||||||
|
|
||||||
|
T_Value r_sum() const {
|
||||||
|
T_Value out(0); // Type must have assignment operator
|
||||||
|
for (const auto& i : m_deque) out += i;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
template <typename Func> T_Value r_sum(Func with_func) const {
|
||||||
|
T_Value out(0); // Type must have assignment operator
|
||||||
|
IData index = 0;
|
||||||
|
for (const auto& i : m_deque) out += with_func(index++, i);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
T_Value r_product() const {
|
||||||
|
if (m_deque.empty()) return T_Value(0);
|
||||||
|
auto it = m_deque.begin();
|
||||||
|
T_Value out{*it};
|
||||||
|
++it;
|
||||||
|
for (; it != m_deque.end(); ++it) out *= *it;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
template <typename Func> T_Value r_product(Func with_func) const {
|
||||||
|
if (m_deque.empty()) return T_Value(0);
|
||||||
|
auto it = m_deque.begin();
|
||||||
|
IData index = 0;
|
||||||
|
T_Value out{with_func(index, *it)};
|
||||||
|
++it;
|
||||||
|
++index;
|
||||||
|
for (; it != m_deque.end(); ++it) out *= with_func(index++, *it);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
T_Value r_and() const {
|
||||||
|
if (m_deque.empty()) return T_Value(0);
|
||||||
|
auto it = m_deque.begin();
|
||||||
|
T_Value out{*it};
|
||||||
|
++it;
|
||||||
|
for (; it != m_deque.end(); ++it) out &= *it;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
template <typename Func> T_Value r_and(Func with_func) const {
|
||||||
|
if (m_deque.empty()) return T_Value(0);
|
||||||
|
auto it = m_deque.begin();
|
||||||
|
IData index = 0;
|
||||||
|
T_Value out{with_func(index, *it)};
|
||||||
|
++it;
|
||||||
|
++index;
|
||||||
|
for (; it != m_deque.end(); ++it) out &= with_func(index, *it);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
T_Value r_or() const {
|
||||||
|
T_Value out(0); // Type must have assignment operator
|
||||||
|
for (const auto& i : m_deque) out |= i;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
template <typename Func> T_Value r_or(Func with_func) const {
|
||||||
|
T_Value out(0); // Type must have assignment operator
|
||||||
|
IData index = 0;
|
||||||
|
for (const auto& i : m_deque) out |= with_func(index++, i);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
T_Value r_xor() const {
|
||||||
|
T_Value out(0); // Type must have assignment operator
|
||||||
|
for (const auto& i : m_deque) out ^= i;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
template <typename Func> T_Value r_xor(Func with_func) const {
|
||||||
|
T_Value out(0); // Type must have assignment operator
|
||||||
|
IData index = 0;
|
||||||
|
for (const auto& i : m_deque) out ^= with_func(index++, i);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
// Dumping. Verilog: str = $sformatf("%p", assoc)
|
// Dumping. Verilog: str = $sformatf("%p", assoc)
|
||||||
std::string to_string() const {
|
std::string to_string() const {
|
||||||
|
if (m_deque.empty()) return "'{}"; // No trailing space
|
||||||
std::string out = "'{";
|
std::string out = "'{";
|
||||||
std::string comma;
|
std::string comma;
|
||||||
for (typename Deque::const_iterator it = m_deque.begin(); it != m_deque.end(); ++it) {
|
for (const auto& i : m_deque) {
|
||||||
out += comma + VL_TO_STRING(*it);
|
out += comma + VL_TO_STRING(i);
|
||||||
comma = ", ";
|
comma = ", ";
|
||||||
}
|
}
|
||||||
return out + "} ";
|
return out + "} ";
|
||||||
@@ -373,19 +489,352 @@ template <class T_Value> std::string VL_TO_STRING(const VlQueue<T_Value>& obj) {
|
|||||||
return obj.to_string();
|
return obj.to_string();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//===================================================================
|
||||||
|
// Verilog associative array container
|
||||||
|
// There are no multithreaded locks on this; the base variable must
|
||||||
|
// be protected by other means
|
||||||
|
//
|
||||||
|
template <class T_Key, class T_Value> class VlAssocArray final {
|
||||||
|
private:
|
||||||
|
// TYPES
|
||||||
|
typedef std::map<T_Key, T_Value> Map;
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef typename Map::const_iterator const_iterator;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// MEMBERS
|
||||||
|
Map m_map; // State of the assoc array
|
||||||
|
T_Value m_defaultValue; // Default value
|
||||||
|
|
||||||
|
public:
|
||||||
|
// CONSTRUCTORS
|
||||||
|
// m_defaultValue isn't defaulted. Caller's constructor must do it.
|
||||||
|
VlAssocArray() = default;
|
||||||
|
~VlAssocArray() = default;
|
||||||
|
VlAssocArray(const VlAssocArray&) = default;
|
||||||
|
VlAssocArray(VlAssocArray&&) = default;
|
||||||
|
VlAssocArray& operator=(const VlAssocArray&) = default;
|
||||||
|
VlAssocArray& operator=(VlAssocArray&&) = default;
|
||||||
|
|
||||||
|
// METHODS
|
||||||
|
T_Value& atDefault() { return m_defaultValue; }
|
||||||
|
const T_Value& atDefault() const { return m_defaultValue; }
|
||||||
|
|
||||||
|
// Size of array. Verilog: function int size(), or int num()
|
||||||
|
int size() const { return m_map.size(); }
|
||||||
|
// Clear array. Verilog: function void delete([input index])
|
||||||
|
void clear() { m_map.clear(); }
|
||||||
|
void erase(const T_Key& index) { m_map.erase(index); }
|
||||||
|
// Return 0/1 if element exists. Verilog: function int exists(input index)
|
||||||
|
int exists(const T_Key& index) const { return m_map.find(index) != m_map.end(); }
|
||||||
|
// Return first element. Verilog: function int first(ref index);
|
||||||
|
int first(T_Key& indexr) const {
|
||||||
|
const auto it = m_map.cbegin();
|
||||||
|
if (it == m_map.end()) return 0;
|
||||||
|
indexr = it->first;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
// Return last element. Verilog: function int last(ref index)
|
||||||
|
int last(T_Key& indexr) const {
|
||||||
|
const auto it = m_map.crbegin();
|
||||||
|
if (it == m_map.rend()) return 0;
|
||||||
|
indexr = it->first;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
// Return next element. Verilog: function int next(ref index)
|
||||||
|
int next(T_Key& indexr) const {
|
||||||
|
auto it = m_map.find(indexr);
|
||||||
|
if (VL_UNLIKELY(it == m_map.end())) return 0;
|
||||||
|
++it;
|
||||||
|
if (VL_UNLIKELY(it == m_map.end())) return 0;
|
||||||
|
indexr = it->first;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
// Return prev element. Verilog: function int prev(ref index)
|
||||||
|
int prev(T_Key& indexr) const {
|
||||||
|
auto it = m_map.find(indexr);
|
||||||
|
if (VL_UNLIKELY(it == m_map.end())) return 0;
|
||||||
|
if (VL_UNLIKELY(it == m_map.begin())) return 0;
|
||||||
|
--it;
|
||||||
|
indexr = it->first;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
// Setting. Verilog: assoc[index] = v
|
||||||
|
// Can't just overload operator[] or provide a "at" reference to set,
|
||||||
|
// because we need to be able to insert only when the value is set
|
||||||
|
T_Value& at(const T_Key& index) {
|
||||||
|
const auto it = m_map.find(index);
|
||||||
|
if (it == m_map.end()) {
|
||||||
|
std::pair<typename Map::iterator, bool> pit = m_map.emplace(index, m_defaultValue);
|
||||||
|
return pit.first->second;
|
||||||
|
}
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
// Accessing. Verilog: v = assoc[index]
|
||||||
|
const T_Value& at(const T_Key& index) const {
|
||||||
|
const auto it = m_map.find(index);
|
||||||
|
if (it == m_map.end()) {
|
||||||
|
return m_defaultValue;
|
||||||
|
} else {
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Setting as a chained operation
|
||||||
|
VlAssocArray& set(const T_Key& index, const T_Value& value) {
|
||||||
|
at(index) = value;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
VlAssocArray& setDefault(const T_Value& value) {
|
||||||
|
atDefault() = value;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// For save/restore
|
||||||
|
const_iterator begin() const { return m_map.begin(); }
|
||||||
|
const_iterator end() const { return m_map.end(); }
|
||||||
|
|
||||||
|
// Methods
|
||||||
|
VlQueue<T_Value> unique() const {
|
||||||
|
VlQueue<T_Value> out;
|
||||||
|
std::set<T_Value> saw;
|
||||||
|
for (const auto& i : m_map) {
|
||||||
|
auto it = saw.find(i.second);
|
||||||
|
if (it == saw.end()) {
|
||||||
|
saw.insert(it, i.second);
|
||||||
|
out.push_back(i.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
VlQueue<T_Key> unique_index() const {
|
||||||
|
VlQueue<T_Key> out;
|
||||||
|
std::set<T_Key> saw;
|
||||||
|
for (const auto& i : m_map) {
|
||||||
|
auto it = saw.find(i.second);
|
||||||
|
if (it == saw.end()) {
|
||||||
|
saw.insert(it, i.second);
|
||||||
|
out.push_back(i.first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
template <typename Func> VlQueue<T_Value> find(Func with_func) const {
|
||||||
|
VlQueue<T_Value> out;
|
||||||
|
for (const auto& i : m_map)
|
||||||
|
if (with_func(i.first, i.second)) out.push_back(i.second);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
template <typename Func> VlQueue<T_Key> find_index(Func with_func) const {
|
||||||
|
VlQueue<T_Key> out;
|
||||||
|
for (const auto& i : m_map)
|
||||||
|
if (with_func(i.first, i.second)) out.push_back(i.first);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
template <typename Func> VlQueue<T_Value> find_first(Func with_func) const {
|
||||||
|
const auto it
|
||||||
|
= std::find_if(m_map.begin(), m_map.end(), [=](const std::pair<T_Key, T_Value>& i) {
|
||||||
|
return with_func(i.first, i.second);
|
||||||
|
});
|
||||||
|
if (it == m_map.end()) return VlQueue<T_Value>{};
|
||||||
|
return VlQueue<T_Value>::cons(it->second);
|
||||||
|
}
|
||||||
|
template <typename Func> VlQueue<T_Key> find_first_index(Func with_func) const {
|
||||||
|
const auto it
|
||||||
|
= std::find_if(m_map.begin(), m_map.end(), [=](const std::pair<T_Key, T_Value>& i) {
|
||||||
|
return with_func(i.first, i.second);
|
||||||
|
});
|
||||||
|
if (it == m_map.end()) return VlQueue<T_Value>{};
|
||||||
|
return VlQueue<T_Key>::cons(it->first);
|
||||||
|
}
|
||||||
|
template <typename Func> VlQueue<T_Value> find_last(Func with_func) const {
|
||||||
|
const auto it
|
||||||
|
= std::find_if(m_map.rbegin(), m_map.rend(), [=](const std::pair<T_Key, T_Value>& i) {
|
||||||
|
return with_func(i.first, i.second);
|
||||||
|
});
|
||||||
|
if (it == m_map.rend()) return VlQueue<T_Value>{};
|
||||||
|
return VlQueue<T_Value>::cons(it->second);
|
||||||
|
}
|
||||||
|
template <typename Func> VlQueue<T_Key> find_last_index(Func with_func) const {
|
||||||
|
const auto it
|
||||||
|
= std::find_if(m_map.rbegin(), m_map.rend(), [=](const std::pair<T_Key, T_Value>& i) {
|
||||||
|
return with_func(i.first, i.second);
|
||||||
|
});
|
||||||
|
if (it == m_map.rend()) return VlQueue<T_Value>{};
|
||||||
|
return VlQueue<T_Key>::cons(it->first);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reduction operators
|
||||||
|
VlQueue<T_Value> min() const {
|
||||||
|
if (m_map.empty()) return VlQueue<T_Value>();
|
||||||
|
const auto it = std::min_element(
|
||||||
|
m_map.begin(), m_map.end(),
|
||||||
|
[](const std::pair<T_Key, T_Value>& a, const std::pair<T_Key, T_Value>& b) {
|
||||||
|
return a.second < b.second;
|
||||||
|
});
|
||||||
|
return VlQueue<T_Value>::cons(it->second);
|
||||||
|
}
|
||||||
|
VlQueue<T_Value> max() const {
|
||||||
|
if (m_map.empty()) return VlQueue<T_Value>();
|
||||||
|
const auto it = std::max_element(
|
||||||
|
m_map.begin(), m_map.end(),
|
||||||
|
[](const std::pair<T_Key, T_Value>& a, const std::pair<T_Key, T_Value>& b) {
|
||||||
|
return a.second < b.second;
|
||||||
|
});
|
||||||
|
return VlQueue<T_Value>::cons(it->second);
|
||||||
|
}
|
||||||
|
|
||||||
|
T_Value r_sum() const {
|
||||||
|
T_Value out(0); // Type must have assignment operator
|
||||||
|
for (const auto& i : m_map) out += i.second;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
template <typename Func> T_Value r_sum(Func with_func) const {
|
||||||
|
T_Value out(0); // Type must have assignment operator
|
||||||
|
for (const auto& i : m_map) out += with_func(i.first, i.second);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
T_Value r_product() const {
|
||||||
|
if (m_map.empty()) return T_Value(0);
|
||||||
|
auto it = m_map.begin();
|
||||||
|
T_Value out{it->second};
|
||||||
|
++it;
|
||||||
|
for (; it != m_map.end(); ++it) out *= it->second;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
template <typename Func> T_Value r_product(Func with_func) const {
|
||||||
|
if (m_map.empty()) return T_Value(0);
|
||||||
|
auto it = m_map.begin();
|
||||||
|
T_Value out{with_func(it->first, it->second)};
|
||||||
|
++it;
|
||||||
|
for (; it != m_map.end(); ++it) out *= with_func(it->first, it->second);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
T_Value r_and() const {
|
||||||
|
if (m_map.empty()) return T_Value(0);
|
||||||
|
auto it = m_map.begin();
|
||||||
|
T_Value out{it->second};
|
||||||
|
++it;
|
||||||
|
for (; it != m_map.end(); ++it) out &= it->second;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
template <typename Func> T_Value r_and(Func with_func) const {
|
||||||
|
if (m_map.empty()) return T_Value(0);
|
||||||
|
auto it = m_map.begin();
|
||||||
|
T_Value out{with_func(it->first, it->second)};
|
||||||
|
++it;
|
||||||
|
for (; it != m_map.end(); ++it) out &= with_func(it->first, it->second);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
T_Value r_or() const {
|
||||||
|
T_Value out(0); // Type must have assignment operator
|
||||||
|
for (const auto& i : m_map) out |= i.second;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
template <typename Func> T_Value r_or(Func with_func) const {
|
||||||
|
T_Value out(0); // Type must have assignment operator
|
||||||
|
for (const auto& i : m_map) out |= with_func(i.first, i.second);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
T_Value r_xor() const {
|
||||||
|
T_Value out(0); // Type must have assignment operator
|
||||||
|
for (const auto& i : m_map) out ^= i.second;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
template <typename Func> T_Value r_xor(Func with_func) const {
|
||||||
|
T_Value out(0); // Type must have assignment operator
|
||||||
|
for (const auto& i : m_map) out ^= with_func(i.first, i.second);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dumping. Verilog: str = $sformatf("%p", assoc)
|
||||||
|
std::string to_string() const {
|
||||||
|
if (m_map.empty()) return "'{}"; // No trailing space
|
||||||
|
std::string out = "'{";
|
||||||
|
std::string comma;
|
||||||
|
for (const auto& i : m_map) {
|
||||||
|
out += comma + VL_TO_STRING(i.first) + ":" + VL_TO_STRING(i.second);
|
||||||
|
comma = ", ";
|
||||||
|
}
|
||||||
|
// Default not printed - maybe random init data
|
||||||
|
return out + "} ";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T_Key, class T_Value>
|
||||||
|
std::string VL_TO_STRING(const VlAssocArray<T_Key, T_Value>& obj) {
|
||||||
|
return obj.to_string();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T_Key, class T_Value>
|
||||||
|
void VL_READMEM_N(bool hex, int bits, const std::string& filename,
|
||||||
|
VlAssocArray<T_Key, T_Value>& obj, QData start, QData end) VL_MT_SAFE {
|
||||||
|
VlReadMem rmem(hex, bits, filename, start, end);
|
||||||
|
if (VL_UNLIKELY(!rmem.isOpen())) return;
|
||||||
|
while (true) {
|
||||||
|
QData addr;
|
||||||
|
std::string data;
|
||||||
|
if (rmem.get(addr /*ref*/, data /*ref*/)) {
|
||||||
|
rmem.setData(&(obj.at(addr)), data);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T_Key, class T_Value>
|
||||||
|
void VL_WRITEMEM_N(bool hex, int bits, const std::string& filename,
|
||||||
|
const VlAssocArray<T_Key, T_Value>& obj, QData start, QData end) VL_MT_SAFE {
|
||||||
|
VlWriteMem wmem(hex, bits, filename, start, end);
|
||||||
|
if (VL_UNLIKELY(!wmem.isOpen())) return;
|
||||||
|
for (const auto& i : obj) {
|
||||||
|
QData addr = i.first;
|
||||||
|
if (addr >= start && addr <= end) wmem.print(addr, true, &(i.second));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//===================================================================
|
||||||
|
// Verilog packed array container
|
||||||
|
// For when a standard C++[] array is not sufficient, e.g. an
|
||||||
|
// array under a queue, or methods operating on the array
|
||||||
|
|
||||||
|
template <class T_Value, std::size_t T_Depth> class VlUnpacked final {
|
||||||
|
private:
|
||||||
|
// TYPES
|
||||||
|
typedef std::array<T_Value, T_Depth> Array;
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef typename Array::const_iterator const_iterator;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// MEMBERS
|
||||||
|
Array m_array; // State of the assoc array
|
||||||
|
|
||||||
|
public:
|
||||||
|
// CONSTRUCTORS
|
||||||
|
VlUnpacked() = default;
|
||||||
|
~VlUnpacked() = default;
|
||||||
|
VlUnpacked(const VlUnpacked&) = default;
|
||||||
|
VlUnpacked(VlUnpacked&&) = default;
|
||||||
|
VlUnpacked& operator=(const VlUnpacked&) = default;
|
||||||
|
VlUnpacked& operator=(VlUnpacked&&) = default;
|
||||||
|
|
||||||
|
// METHODS
|
||||||
|
// Raw access
|
||||||
|
WData* data() { return &m_array[0]; }
|
||||||
|
const WData* data() const { return &m_array[0]; }
|
||||||
|
|
||||||
|
T_Value& operator[](size_t index) { return m_array[index]; };
|
||||||
|
const T_Value& operator[](size_t index) const { return m_array[index]; };
|
||||||
|
};
|
||||||
|
|
||||||
//===================================================================
|
//===================================================================
|
||||||
// Verilog class reference container
|
// Verilog class reference container
|
||||||
// There are no multithreaded locks on this; the base variable must
|
// There are no multithreaded locks on this; the base variable must
|
||||||
// be protected by other means
|
// be protected by other means
|
||||||
//
|
//
|
||||||
|
|
||||||
// clang-format off
|
#define VlClassRef std::shared_ptr
|
||||||
#if (defined(_MSC_VER) && _MSC_VER >= 1900) || (__cplusplus >= 201103L)
|
|
||||||
# define VlClassRef std::shared_ptr
|
|
||||||
#else
|
|
||||||
# define VlClassRef VlClassRef__SystemVerilog_class_support_requires_a_C11_or_newer_compiler
|
|
||||||
#endif
|
|
||||||
// clang-format on
|
|
||||||
|
|
||||||
template <class T> // T typically of type VlClassRef<x>
|
template <class T> // T typically of type VlClassRef<x>
|
||||||
inline T VL_NULL_CHECK(T t, const char* filename, int linenum) {
|
inline T VL_NULL_CHECK(T t, const char* filename, int linenum) {
|
||||||
@@ -393,6 +842,17 @@ inline T VL_NULL_CHECK(T t, const char* filename, int linenum) {
|
|||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T, typename U>
|
||||||
|
static inline bool VL_CAST_DYNAMIC(VlClassRef<T> in, VlClassRef<U>& outr) {
|
||||||
|
VlClassRef<U> casted = std::dynamic_pointer_cast<U>(in);
|
||||||
|
if (VL_LIKELY(casted)) {
|
||||||
|
outr = casted;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//======================================================================
|
//======================================================================
|
||||||
// Conversion functions
|
// Conversion functions
|
||||||
|
|
||||||
@@ -403,6 +863,7 @@ inline std::string VL_CVT_PACK_STR_NQ(QData lhs) VL_PURE {
|
|||||||
return VL_CVT_PACK_STR_NW(VL_WQ_WORDS_E, lw);
|
return VL_CVT_PACK_STR_NW(VL_WQ_WORDS_E, lw);
|
||||||
}
|
}
|
||||||
inline std::string VL_CVT_PACK_STR_NN(const std::string& lhs) VL_PURE { return lhs; }
|
inline std::string VL_CVT_PACK_STR_NN(const std::string& lhs) VL_PURE { return lhs; }
|
||||||
|
inline std::string& VL_CVT_PACK_STR_NN(std::string& lhs) VL_PURE { return lhs; }
|
||||||
inline std::string VL_CVT_PACK_STR_NI(IData lhs) VL_PURE {
|
inline std::string VL_CVT_PACK_STR_NI(IData lhs) VL_PURE {
|
||||||
WData lw[VL_WQ_WORDS_E];
|
WData lw[VL_WQ_WORDS_E];
|
||||||
VL_SET_WI(lw, lhs);
|
VL_SET_WI(lw, lhs);
|
||||||
@@ -427,7 +888,8 @@ extern std::string VL_TOLOWER_NN(const std::string& ld);
|
|||||||
extern std::string VL_TOUPPER_NN(const std::string& ld);
|
extern std::string VL_TOUPPER_NN(const std::string& ld);
|
||||||
|
|
||||||
extern IData VL_FERROR_IN(IData fpi, std::string& outputr) VL_MT_SAFE;
|
extern IData VL_FERROR_IN(IData fpi, std::string& outputr) VL_MT_SAFE;
|
||||||
extern IData VL_FOPEN_NI(const std::string& filename, IData mode) VL_MT_SAFE;
|
extern IData VL_FOPEN_NN(const std::string& filename, const std::string& mode) VL_MT_SAFE;
|
||||||
|
extern IData VL_FOPEN_MCD_N(const std::string& filename) VL_MT_SAFE;
|
||||||
extern void VL_READMEM_N(bool hex, int bits, QData depth, int array_lsb,
|
extern void VL_READMEM_N(bool hex, int bits, QData depth, int array_lsb,
|
||||||
const std::string& filename, void* memp, QData start,
|
const std::string& filename, void* memp, QData start,
|
||||||
QData end) VL_MT_SAFE;
|
QData end) VL_MT_SAFE;
|
||||||
@@ -483,17 +945,17 @@ extern std::string VL_SUBSTR_N(const std::string& lhs, IData rhs, IData ths) VL_
|
|||||||
inline IData VL_CMP_NN(const std::string& lhs, const std::string& rhs, bool ignoreCase) VL_PURE {
|
inline IData VL_CMP_NN(const std::string& lhs, const std::string& rhs, bool ignoreCase) VL_PURE {
|
||||||
// SystemVerilog does not allow a string variable to contain '\0'.
|
// SystemVerilog does not allow a string variable to contain '\0'.
|
||||||
// So C functions such as strcmp() can correctly compare strings.
|
// So C functions such as strcmp() can correctly compare strings.
|
||||||
int result;
|
|
||||||
if (ignoreCase) {
|
if (ignoreCase) {
|
||||||
result = VL_STRCASECMP(lhs.c_str(), rhs.c_str());
|
return VL_STRCASECMP(lhs.c_str(), rhs.c_str());
|
||||||
} else {
|
} else {
|
||||||
result = std::strcmp(lhs.c_str(), rhs.c_str());
|
return std::strcmp(lhs.c_str(), rhs.c_str());
|
||||||
}
|
}
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern IData VL_ATOI_N(const std::string& str, int base) VL_PURE;
|
extern IData VL_ATOI_N(const std::string& str, int base) VL_PURE;
|
||||||
|
|
||||||
|
extern IData VL_FGETS_NI(std::string& dest, IData fpi);
|
||||||
|
|
||||||
//======================================================================
|
//======================================================================
|
||||||
// Dumping
|
// Dumping
|
||||||
|
|
||||||
|
|||||||
+238
-116
@@ -1,7 +1,7 @@
|
|||||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2009-2020 by Wilson Snyder. This program is free software; you can
|
// Copyright 2009-2021 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// 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,6 +32,7 @@
|
|||||||
#include <deque>
|
#include <deque>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <numeric>
|
||||||
#ifdef VL_THREADED
|
#ifdef VL_THREADED
|
||||||
# include <functional>
|
# include <functional>
|
||||||
# include <queue>
|
# include <queue>
|
||||||
@@ -45,7 +46,7 @@ class VerilatedScope;
|
|||||||
|
|
||||||
#ifdef VL_THREADED
|
#ifdef VL_THREADED
|
||||||
/// Message, enqueued on an mtask, and consumed on the main eval thread
|
/// Message, enqueued on an mtask, and consumed on the main eval thread
|
||||||
class VerilatedMsg {
|
class VerilatedMsg final {
|
||||||
public:
|
public:
|
||||||
// TYPES
|
// TYPES
|
||||||
struct Cmp {
|
struct Cmp {
|
||||||
@@ -60,10 +61,14 @@ private:
|
|||||||
std::function<void()> m_cb; ///< Lambda to execute when message received
|
std::function<void()> m_cb; ///< Lambda to execute when message received
|
||||||
public:
|
public:
|
||||||
// CONSTRUCTORS
|
// CONSTRUCTORS
|
||||||
VerilatedMsg(const std::function<void()>& cb)
|
explicit VerilatedMsg(const std::function<void()>& cb)
|
||||||
: m_mtaskId(Verilated::mtaskId())
|
: m_mtaskId{Verilated::mtaskId()}
|
||||||
, m_cb(cb) {}
|
, m_cb{cb} {}
|
||||||
~VerilatedMsg() {}
|
~VerilatedMsg() = default;
|
||||||
|
VerilatedMsg(const VerilatedMsg&) = default;
|
||||||
|
VerilatedMsg(VerilatedMsg&&) = default;
|
||||||
|
VerilatedMsg& operator=(const VerilatedMsg&) = default;
|
||||||
|
VerilatedMsg& operator=(VerilatedMsg&&) = default;
|
||||||
// METHODS
|
// METHODS
|
||||||
vluint32_t mtaskId() const { return m_mtaskId; }
|
vluint32_t mtaskId() const { return m_mtaskId; }
|
||||||
/// Execute the lambda function
|
/// Execute the lambda function
|
||||||
@@ -73,7 +78,7 @@ public:
|
|||||||
/// Each thread has a queue it pushes to
|
/// Each thread has a queue it pushes to
|
||||||
/// This assumes no thread starts pushing the next tick until the previous has drained.
|
/// This assumes no thread starts pushing the next tick until the previous has drained.
|
||||||
/// If more aggressiveness is needed, a double-buffered scheme might work well.
|
/// If more aggressiveness is needed, a double-buffered scheme might work well.
|
||||||
class VerilatedEvalMsgQueue {
|
class VerilatedEvalMsgQueue final {
|
||||||
typedef std::multiset<VerilatedMsg, VerilatedMsg::Cmp> VerilatedThreadQueue;
|
typedef std::multiset<VerilatedMsg, VerilatedMsg::Cmp> VerilatedThreadQueue;
|
||||||
|
|
||||||
std::atomic<vluint64_t> m_depth; ///< Current depth of queue (see comments below)
|
std::atomic<vluint64_t> m_depth; ///< Current depth of queue (see comments below)
|
||||||
@@ -83,10 +88,10 @@ class VerilatedEvalMsgQueue {
|
|||||||
public:
|
public:
|
||||||
// CONSTRUCTORS
|
// CONSTRUCTORS
|
||||||
VerilatedEvalMsgQueue()
|
VerilatedEvalMsgQueue()
|
||||||
: m_depth(0) {
|
: m_depth{0} {
|
||||||
assert(atomic_is_lock_free(&m_depth));
|
assert(atomic_is_lock_free(&m_depth));
|
||||||
}
|
}
|
||||||
~VerilatedEvalMsgQueue() {}
|
~VerilatedEvalMsgQueue() = default;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
VL_UNCOPYABLE(VerilatedEvalMsgQueue);
|
VL_UNCOPYABLE(VerilatedEvalMsgQueue);
|
||||||
@@ -95,7 +100,7 @@ public:
|
|||||||
// METHODS
|
// METHODS
|
||||||
//// Add message to queue (called by producer)
|
//// Add message to queue (called by producer)
|
||||||
void post(const VerilatedMsg& msg) VL_EXCLUDES(m_mutex) {
|
void post(const VerilatedMsg& msg) VL_EXCLUDES(m_mutex) {
|
||||||
VerilatedLockGuard lock(m_mutex);
|
const VerilatedLockGuard lock(m_mutex);
|
||||||
m_queue.insert(msg); // Pass by value to copy the message into queue
|
m_queue.insert(msg); // Pass by value to copy the message into queue
|
||||||
++m_depth;
|
++m_depth;
|
||||||
}
|
}
|
||||||
@@ -111,7 +116,7 @@ public:
|
|||||||
// Unfortunately to release the lock we need to copy the message
|
// Unfortunately to release the lock we need to copy the message
|
||||||
// (Or have the message be a pointer, but then new/delete cost on each message)
|
// (Or have the message be a pointer, but then new/delete cost on each message)
|
||||||
// We assume messages are small, so copy
|
// We assume messages are small, so copy
|
||||||
auto it = m_queue.begin();
|
const auto it = m_queue.begin();
|
||||||
const VerilatedMsg msg = *(it);
|
const VerilatedMsg msg = *(it);
|
||||||
m_queue.erase(it);
|
m_queue.erase(it);
|
||||||
m_mutex.unlock();
|
m_mutex.unlock();
|
||||||
@@ -125,7 +130,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// Each thread has a local queue to build up messages until the end of the eval() call
|
/// Each thread has a local queue to build up messages until the end of the eval() call
|
||||||
class VerilatedThreadMsgQueue {
|
class VerilatedThreadMsgQueue final {
|
||||||
std::queue<VerilatedMsg> m_queue;
|
std::queue<VerilatedMsg> m_queue;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -168,13 +173,31 @@ public:
|
|||||||
};
|
};
|
||||||
#endif // VL_THREADED
|
#endif // VL_THREADED
|
||||||
|
|
||||||
|
// FILE* list constructed from a file-descriptor
|
||||||
|
class VerilatedFpList final {
|
||||||
|
FILE* m_fp[31];
|
||||||
|
std::size_t m_sz = 0;
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef FILE* const* const_iterator;
|
||||||
|
explicit VerilatedFpList() {}
|
||||||
|
const_iterator begin() const { return m_fp; }
|
||||||
|
const_iterator end() const { return m_fp + m_sz; }
|
||||||
|
std::size_t size() const { return m_sz; }
|
||||||
|
std::size_t capacity() const { return 31; }
|
||||||
|
void push_back(FILE* fd) {
|
||||||
|
if (VL_LIKELY(size() < capacity())) m_fp[m_sz++] = fd;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
//======================================================================
|
//======================================================================
|
||||||
// VerilatedImp
|
// VerilatedImp
|
||||||
|
|
||||||
class VerilatedImp {
|
class VerilatedImpData final {
|
||||||
// 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.
|
||||||
protected:
|
protected:
|
||||||
friend class Verilated;
|
friend class Verilated;
|
||||||
|
friend class VerilatedImp;
|
||||||
|
|
||||||
// TYPES
|
// TYPES
|
||||||
typedef std::vector<std::string> ArgVec;
|
typedef std::vector<std::string> ArgVec;
|
||||||
@@ -182,18 +205,14 @@ protected:
|
|||||||
typedef std::map<const char*, int, VerilatedCStrCmp> ExportNameMap;
|
typedef std::map<const char*, int, VerilatedCStrCmp> ExportNameMap;
|
||||||
|
|
||||||
// MEMBERS
|
// MEMBERS
|
||||||
static VerilatedImp s_s; ///< Static Singleton; One and only static this
|
|
||||||
|
|
||||||
struct Serialized { // All these members serialized/deserialized
|
struct Serialized { // All these members serialized/deserialized
|
||||||
int m_timeFormatUnits; // $timeformat units
|
int m_timeFormatUnits = UNITS_NONE; // $timeformat units
|
||||||
int m_timeFormatPrecision; // $timeformat number of decimal places
|
int m_timeFormatPrecision = 0; // $timeformat number of decimal places
|
||||||
int m_timeFormatWidth; // $timeformat character width
|
int m_timeFormatWidth = 20; // $timeformat character width
|
||||||
enum { UNITS_NONE = 99 }; // Default based on precision
|
enum { UNITS_NONE = 99 }; // Default based on precision
|
||||||
Serialized()
|
Serialized() = default;
|
||||||
: m_timeFormatUnits(UNITS_NONE)
|
~Serialized() = default;
|
||||||
, m_timeFormatPrecision(0)
|
|
||||||
, m_timeFormatWidth(20) {}
|
|
||||||
~Serialized() {}
|
|
||||||
} m_ser;
|
} m_ser;
|
||||||
|
|
||||||
VerilatedMutex m_sergMutex; ///< Protect m_ser
|
VerilatedMutex m_sergMutex; ///< Protect m_ser
|
||||||
@@ -229,19 +248,41 @@ protected:
|
|||||||
VerilatedMutex m_fdMutex; ///< Protect m_fdps, m_fdFree
|
VerilatedMutex m_fdMutex; ///< Protect m_fdps, m_fdFree
|
||||||
std::vector<FILE*> m_fdps VL_GUARDED_BY(m_fdMutex); ///< File descriptors
|
std::vector<FILE*> m_fdps VL_GUARDED_BY(m_fdMutex); ///< File descriptors
|
||||||
/// List of free descriptors (SLOW - FOPEN/CLOSE only)
|
/// List of free descriptors (SLOW - FOPEN/CLOSE only)
|
||||||
std::deque<IData> m_fdFree VL_GUARDED_BY(m_fdMutex);
|
std::vector<IData> m_fdFree VL_GUARDED_BY(m_fdMutex);
|
||||||
|
// List of free descriptors in the MCT region [4, 32)
|
||||||
|
std::vector<IData> m_fdFreeMct VL_GUARDED_BY(m_fdMutex);
|
||||||
|
|
||||||
|
// CONSTRUCTORS
|
||||||
|
VerilatedImpData()
|
||||||
|
: m_argVecLoaded{false}
|
||||||
|
, m_exportNext{0} {
|
||||||
|
|
||||||
|
m_fdps.resize(31);
|
||||||
|
std::fill(m_fdps.begin(), m_fdps.end(), (FILE*)0);
|
||||||
|
m_fdFreeMct.resize(30);
|
||||||
|
for (std::size_t i = 0, id = 1; i < m_fdFreeMct.size(); ++i, ++id) { m_fdFreeMct[i] = id; }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class VerilatedImp final {
|
||||||
|
// Whole class is internal use only - Global information shared between verilated*.cpp files.
|
||||||
|
protected:
|
||||||
|
friend class Verilated;
|
||||||
|
|
||||||
|
// MEMBERS
|
||||||
|
union VerilatedImpU { ///< Enclose in an union to call ctor/dtor manually
|
||||||
|
VerilatedImpData v;
|
||||||
|
VerilatedImpU() {} // Can't be = default;
|
||||||
|
~VerilatedImpU() {} // Can't be = default;
|
||||||
|
};
|
||||||
|
static VerilatedImpU s_s; ///< Static Singleton; One and only static this
|
||||||
|
|
||||||
public: // But only for verilated*.cpp
|
public: // But only for verilated*.cpp
|
||||||
// CONSTRUCTORS
|
// CONSTRUCTORS
|
||||||
VerilatedImp()
|
VerilatedImp() = default;
|
||||||
: m_argVecLoaded(false)
|
~VerilatedImp() = default;
|
||||||
, m_exportNext(0) {
|
static void setup();
|
||||||
m_fdps.resize(3);
|
static void teardown();
|
||||||
m_fdps[0] = stdin;
|
|
||||||
m_fdps[1] = stdout;
|
|
||||||
m_fdps[2] = stderr;
|
|
||||||
}
|
|
||||||
~VerilatedImp() {}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
VL_UNCOPYABLE(VerilatedImp);
|
VL_UNCOPYABLE(VerilatedImp);
|
||||||
@@ -253,28 +294,28 @@ public:
|
|||||||
|
|
||||||
// METHODS - arguments
|
// METHODS - arguments
|
||||||
public:
|
public:
|
||||||
static void commandArgs(int argc, const char** argv) VL_EXCLUDES(s_s.m_argMutex);
|
static void commandArgs(int argc, const char** argv) VL_EXCLUDES(s_s.v.m_argMutex);
|
||||||
static void commandArgsAdd(int argc, const char** argv) VL_EXCLUDES(s_s.m_argMutex);
|
static void commandArgsAdd(int argc, const char** argv) VL_EXCLUDES(s_s.v.m_argMutex);
|
||||||
static std::string argPlusMatch(const char* prefixp) VL_EXCLUDES(s_s.m_argMutex) {
|
static std::string argPlusMatch(const char* prefixp) VL_EXCLUDES(s_s.v.m_argMutex) {
|
||||||
VerilatedLockGuard lock(s_s.m_argMutex);
|
const VerilatedLockGuard lock(s_s.v.m_argMutex);
|
||||||
// Note prefixp does not include the leading "+"
|
// Note prefixp does not include the leading "+"
|
||||||
size_t len = strlen(prefixp);
|
size_t len = strlen(prefixp);
|
||||||
if (VL_UNLIKELY(!s_s.m_argVecLoaded)) {
|
if (VL_UNLIKELY(!s_s.v.m_argVecLoaded)) {
|
||||||
s_s.m_argVecLoaded = true; // Complain only once
|
s_s.v.m_argVecLoaded = true; // Complain only once
|
||||||
VL_FATAL_MT("unknown", 0, "",
|
VL_FATAL_MT("unknown", 0, "",
|
||||||
"%Error: Verilog called $test$plusargs or $value$plusargs without"
|
"%Error: Verilog called $test$plusargs or $value$plusargs without"
|
||||||
" testbench C first calling Verilated::commandArgs(argc,argv).");
|
" testbench C first calling Verilated::commandArgs(argc,argv).");
|
||||||
}
|
}
|
||||||
for (ArgVec::const_iterator it = s_s.m_argVec.begin(); it != s_s.m_argVec.end(); ++it) {
|
for (const auto& i : s_s.v.m_argVec) {
|
||||||
if ((*it)[0] == '+') {
|
if (i[0] == '+') {
|
||||||
if (0 == strncmp(prefixp, it->c_str() + 1, len)) return *it;
|
if (0 == strncmp(prefixp, i.c_str() + 1, len)) return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void commandArgsAddGuts(int argc, const char** argv) VL_REQUIRES(s_s.m_argMutex);
|
static void commandArgsAddGuts(int argc, const char** argv) VL_REQUIRES(s_s.v.m_argMutex);
|
||||||
static void commandArgVl(const std::string& arg);
|
static void commandArgVl(const std::string& arg);
|
||||||
static bool commandArgVlValue(const std::string& arg, const std::string& prefix,
|
static bool commandArgVlValue(const std::string& arg, const std::string& prefix,
|
||||||
std::string& valuer);
|
std::string& valuer);
|
||||||
@@ -285,18 +326,18 @@ public:
|
|||||||
// There's often many more scopes than userdata's and thus having a ~48byte
|
// There's often many more scopes than userdata's and thus having a ~48byte
|
||||||
// per map overhead * N scopes would take much more space and cache thrashing.
|
// per map overhead * N scopes would take much more space and cache thrashing.
|
||||||
static inline void userInsert(const void* scopep, void* userKey, void* userData) VL_MT_SAFE {
|
static inline void userInsert(const void* scopep, void* userKey, void* userData) VL_MT_SAFE {
|
||||||
VerilatedLockGuard lock(s_s.m_userMapMutex);
|
const VerilatedLockGuard lock(s_s.v.m_userMapMutex);
|
||||||
UserMap::iterator it = s_s.m_userMap.find(std::make_pair(scopep, userKey));
|
const auto it = s_s.v.m_userMap.find(std::make_pair(scopep, userKey));
|
||||||
if (it != s_s.m_userMap.end()) {
|
if (it != s_s.v.m_userMap.end()) {
|
||||||
it->second = userData;
|
it->second = userData;
|
||||||
} else {
|
} else {
|
||||||
s_s.m_userMap.insert(it, std::make_pair(std::make_pair(scopep, userKey), userData));
|
s_s.v.m_userMap.emplace(std::make_pair(scopep, userKey), userData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static inline void* userFind(const void* scopep, void* userKey) VL_MT_SAFE {
|
static inline void* userFind(const void* scopep, void* userKey) VL_MT_SAFE {
|
||||||
VerilatedLockGuard lock(s_s.m_userMapMutex);
|
const VerilatedLockGuard lock(s_s.v.m_userMapMutex);
|
||||||
UserMap::const_iterator it = s_s.m_userMap.find(std::make_pair(scopep, userKey));
|
const auto& it = vlstd::as_const(s_s.v.m_userMap).find(std::make_pair(scopep, userKey));
|
||||||
if (VL_UNLIKELY(it == s_s.m_userMap.end())) return NULL;
|
if (VL_UNLIKELY(it == s_s.v.m_userMap.end())) return nullptr;
|
||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -304,25 +345,26 @@ private:
|
|||||||
/// Symbol table destruction cleans up the entries for each scope.
|
/// Symbol table destruction cleans up the entries for each scope.
|
||||||
static void userEraseScope(const VerilatedScope* scopep) VL_MT_SAFE {
|
static void userEraseScope(const VerilatedScope* scopep) VL_MT_SAFE {
|
||||||
// Slow ok - called once/scope on destruction, so we simply iterate.
|
// Slow ok - called once/scope on destruction, so we simply iterate.
|
||||||
VerilatedLockGuard lock(s_s.m_userMapMutex);
|
const VerilatedLockGuard lock(s_s.v.m_userMapMutex);
|
||||||
for (UserMap::iterator it = s_s.m_userMap.begin(); it != s_s.m_userMap.end();) {
|
for (auto it = s_s.v.m_userMap.begin(); it != s_s.v.m_userMap.end();) {
|
||||||
if (it->first.first == scopep) {
|
if (it->first.first == scopep) {
|
||||||
s_s.m_userMap.erase(it++);
|
s_s.v.m_userMap.erase(it++);
|
||||||
} else {
|
} else {
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static void userDump() VL_MT_SAFE {
|
static void userDump() VL_MT_SAFE {
|
||||||
VerilatedLockGuard lock(s_s.m_userMapMutex); // Avoid it changing in middle of dump
|
const VerilatedLockGuard lock(
|
||||||
|
s_s.v.m_userMapMutex); // Avoid it changing in middle of dump
|
||||||
bool first = true;
|
bool first = true;
|
||||||
for (UserMap::const_iterator it = s_s.m_userMap.begin(); it != s_s.m_userMap.end(); ++it) {
|
for (const auto& i : s_s.v.m_userMap) {
|
||||||
if (first) {
|
if (first) {
|
||||||
VL_PRINTF_MT(" userDump:\n");
|
VL_PRINTF_MT(" userDump:\n");
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
VL_PRINTF_MT(" DPI_USER_DATA scope %p key %p: %p\n", it->first.first,
|
VL_PRINTF_MT(" DPI_USER_DATA scope %p key %p: %p\n", i.first.first, i.first.second,
|
||||||
it->first.second, it->second);
|
i.second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -330,51 +372,58 @@ public: // But only for verilated*.cpp
|
|||||||
// METHODS - scope name
|
// METHODS - scope name
|
||||||
static void scopeInsert(const VerilatedScope* scopep) VL_MT_SAFE {
|
static void scopeInsert(const VerilatedScope* scopep) VL_MT_SAFE {
|
||||||
// Slow ok - called once/scope at construction
|
// Slow ok - called once/scope at construction
|
||||||
VerilatedLockGuard lock(s_s.m_nameMutex);
|
const VerilatedLockGuard lock(s_s.v.m_nameMutex);
|
||||||
VerilatedScopeNameMap::iterator it = s_s.m_nameMap.find(scopep->name());
|
const auto it = s_s.v.m_nameMap.find(scopep->name());
|
||||||
if (it == s_s.m_nameMap.end()) {
|
if (it == s_s.v.m_nameMap.end()) s_s.v.m_nameMap.emplace(scopep->name(), scopep);
|
||||||
s_s.m_nameMap.insert(it, std::make_pair(scopep->name(), scopep));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
static inline const VerilatedScope* scopeFind(const char* namep) VL_MT_SAFE {
|
static inline const VerilatedScope* scopeFind(const char* namep) VL_MT_SAFE {
|
||||||
VerilatedLockGuard lock(s_s.m_nameMutex);
|
const VerilatedLockGuard lock(s_s.v.m_nameMutex);
|
||||||
// If too slow, can assume this is only VL_MT_SAFE_POSINIT
|
// If too slow, can assume this is only VL_MT_SAFE_POSINIT
|
||||||
VerilatedScopeNameMap::const_iterator it = s_s.m_nameMap.find(namep);
|
const auto& it = s_s.v.m_nameMap.find(namep);
|
||||||
if (VL_UNLIKELY(it == s_s.m_nameMap.end())) return NULL;
|
if (VL_UNLIKELY(it == s_s.v.m_nameMap.end())) return nullptr;
|
||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
static void scopeErase(const VerilatedScope* scopep) VL_MT_SAFE {
|
static void scopeErase(const VerilatedScope* scopep) VL_MT_SAFE {
|
||||||
// Slow ok - called once/scope at destruction
|
// Slow ok - called once/scope at destruction
|
||||||
VerilatedLockGuard lock(s_s.m_nameMutex);
|
const VerilatedLockGuard lock(s_s.v.m_nameMutex);
|
||||||
userEraseScope(scopep);
|
userEraseScope(scopep);
|
||||||
VerilatedScopeNameMap::iterator it = s_s.m_nameMap.find(scopep->name());
|
const auto it = s_s.v.m_nameMap.find(scopep->name());
|
||||||
if (it != s_s.m_nameMap.end()) s_s.m_nameMap.erase(it);
|
if (it != s_s.v.m_nameMap.end()) s_s.v.m_nameMap.erase(it);
|
||||||
}
|
}
|
||||||
static void scopesDump() VL_MT_SAFE {
|
static void scopesDump() VL_MT_SAFE {
|
||||||
VerilatedLockGuard lock(s_s.m_nameMutex);
|
const VerilatedLockGuard lock(s_s.v.m_nameMutex);
|
||||||
VL_PRINTF_MT(" scopesDump:\n");
|
VL_PRINTF_MT(" scopesDump:\n");
|
||||||
for (VerilatedScopeNameMap::const_iterator it = s_s.m_nameMap.begin();
|
for (const auto& i : s_s.v.m_nameMap) {
|
||||||
it != s_s.m_nameMap.end(); ++it) {
|
const VerilatedScope* scopep = i.second;
|
||||||
const VerilatedScope* scopep = it->second;
|
|
||||||
scopep->scopeDump();
|
scopep->scopeDump();
|
||||||
}
|
}
|
||||||
VL_PRINTF_MT("\n");
|
VL_PRINTF_MT("\n");
|
||||||
}
|
}
|
||||||
static const VerilatedScopeNameMap* scopeNameMap() VL_MT_SAFE_POSTINIT {
|
static const VerilatedScopeNameMap* scopeNameMap() VL_MT_SAFE_POSTINIT {
|
||||||
// Thread save only assuming this is called only after model construction completed
|
// Thread save only assuming this is called only after model construction completed
|
||||||
return &s_s.m_nameMap;
|
return &s_s.v.m_nameMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
public: // But only for verilated*.cpp
|
public: // But only for verilated*.cpp
|
||||||
// METHODS - hierarchy
|
// METHODS - hierarchy
|
||||||
static void hierarchyAdd(const VerilatedScope* fromp, const VerilatedScope* top) VL_MT_SAFE {
|
static void hierarchyAdd(const VerilatedScope* fromp, const VerilatedScope* top) VL_MT_SAFE {
|
||||||
// Slow ok - called at construction for VPI accessible elements
|
// Slow ok - called at construction for VPI accessible elements
|
||||||
VerilatedLockGuard lock(s_s.m_hierMapMutex);
|
const VerilatedLockGuard lock(s_s.v.m_hierMapMutex);
|
||||||
s_s.m_hierMap[fromp].push_back(top);
|
s_s.v.m_hierMap[fromp].push_back(top);
|
||||||
|
}
|
||||||
|
static void hierarchyRemove(const VerilatedScope* fromp,
|
||||||
|
const VerilatedScope* top) VL_MT_SAFE {
|
||||||
|
// Slow ok - called at destruction for VPI accessible elements
|
||||||
|
const VerilatedLockGuard lock(s_s.v.m_hierMapMutex);
|
||||||
|
VerilatedHierarchyMap& map = s_s.v.m_hierMap;
|
||||||
|
if (map.find(fromp) == map.end()) return;
|
||||||
|
VerilatedScopeVector& scopes = map[fromp];
|
||||||
|
const auto it = find(scopes.begin(), scopes.end(), top);
|
||||||
|
if (it != scopes.end()) scopes.erase(it);
|
||||||
}
|
}
|
||||||
static const VerilatedHierarchyMap* hierarchyMap() VL_MT_SAFE_POSTINIT {
|
static const VerilatedHierarchyMap* hierarchyMap() VL_MT_SAFE_POSTINIT {
|
||||||
// Thread save only assuming this is called only after model construction completed
|
// Thread save only assuming this is called only after model construction completed
|
||||||
return &s_s.m_hierMap;
|
return &s_s.v.m_hierMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
public: // But only for verilated*.cpp
|
public: // But only for verilated*.cpp
|
||||||
@@ -388,19 +437,19 @@ public: // But only for verilated*.cpp
|
|||||||
// miss at the cost of a multiply, and all lookups move to slowpath.
|
// miss at the cost of a multiply, and all lookups move to slowpath.
|
||||||
static int exportInsert(const char* namep) VL_MT_SAFE {
|
static int exportInsert(const char* namep) VL_MT_SAFE {
|
||||||
// Slow ok - called once/function at creation
|
// Slow ok - called once/function at creation
|
||||||
VerilatedLockGuard lock(s_s.m_exportMutex);
|
const VerilatedLockGuard lock(s_s.v.m_exportMutex);
|
||||||
ExportNameMap::iterator it = s_s.m_exportMap.find(namep);
|
const auto it = s_s.v.m_exportMap.find(namep);
|
||||||
if (it == s_s.m_exportMap.end()) {
|
if (it == s_s.v.m_exportMap.end()) {
|
||||||
s_s.m_exportMap.insert(it, std::make_pair(namep, s_s.m_exportNext++));
|
s_s.v.m_exportMap.emplace(namep, s_s.v.m_exportNext++);
|
||||||
return s_s.m_exportNext++;
|
return s_s.v.m_exportNext++;
|
||||||
} else {
|
} else {
|
||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static int exportFind(const char* namep) VL_MT_SAFE {
|
static int exportFind(const char* namep) VL_MT_SAFE {
|
||||||
VerilatedLockGuard lock(s_s.m_exportMutex);
|
const VerilatedLockGuard lock(s_s.v.m_exportMutex);
|
||||||
ExportNameMap::const_iterator it = s_s.m_exportMap.find(namep);
|
const auto& it = s_s.v.m_exportMap.find(namep);
|
||||||
if (VL_LIKELY(it != s_s.m_exportMap.end())) return it->second;
|
if (VL_LIKELY(it != s_s.v.m_exportMap.end())) return it->second;
|
||||||
std::string msg = (std::string("%Error: Testbench C called ") + namep
|
std::string msg = (std::string("%Error: Testbench C called ") + namep
|
||||||
+ " but no such DPI export function name exists in ANY model");
|
+ " but no such DPI export function name exists in ANY model");
|
||||||
VL_FATAL_MT("unknown", 0, "", msg.c_str());
|
VL_FATAL_MT("unknown", 0, "", msg.c_str());
|
||||||
@@ -408,23 +457,21 @@ public: // But only for verilated*.cpp
|
|||||||
}
|
}
|
||||||
static const char* exportName(int funcnum) VL_MT_SAFE {
|
static const char* exportName(int funcnum) VL_MT_SAFE {
|
||||||
// Slowpath; find name for given export; errors only so no map to reverse-map it
|
// Slowpath; find name for given export; errors only so no map to reverse-map it
|
||||||
VerilatedLockGuard lock(s_s.m_exportMutex);
|
const VerilatedLockGuard lock(s_s.v.m_exportMutex);
|
||||||
for (ExportNameMap::const_iterator it = s_s.m_exportMap.begin();
|
for (const auto& i : s_s.v.m_exportMap) {
|
||||||
it != s_s.m_exportMap.end(); ++it) {
|
if (i.second == funcnum) return i.first;
|
||||||
if (it->second == funcnum) return it->first;
|
|
||||||
}
|
}
|
||||||
return "*UNKNOWN*";
|
return "*UNKNOWN*";
|
||||||
}
|
}
|
||||||
static void exportsDump() VL_MT_SAFE {
|
static void exportsDump() VL_MT_SAFE {
|
||||||
VerilatedLockGuard lock(s_s.m_exportMutex);
|
const VerilatedLockGuard lock(s_s.v.m_exportMutex);
|
||||||
bool first = true;
|
bool first = true;
|
||||||
for (ExportNameMap::const_iterator it = s_s.m_exportMap.begin();
|
for (const auto& i : s_s.v.m_exportMap) {
|
||||||
it != s_s.m_exportMap.end(); ++it) {
|
|
||||||
if (first) {
|
if (first) {
|
||||||
VL_PRINTF_MT(" exportDump:\n");
|
VL_PRINTF_MT(" exportDump:\n");
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
VL_PRINTF_MT(" DPI_EXPORT_NAME %05d: %s\n", it->second, it->first);
|
VL_PRINTF_MT(" DPI_EXPORT_NAME %05d: %s\n", i.second, i.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
|
||||||
@@ -435,49 +482,124 @@ public: // But only for verilated*.cpp
|
|||||||
static std::string timeFormatSuffix() VL_MT_SAFE;
|
static std::string timeFormatSuffix() VL_MT_SAFE;
|
||||||
static void timeFormatSuffix(const std::string& value) VL_MT_SAFE;
|
static void timeFormatSuffix(const std::string& value) VL_MT_SAFE;
|
||||||
static int timeFormatUnits() VL_MT_SAFE {
|
static int timeFormatUnits() VL_MT_SAFE {
|
||||||
if (s_s.m_ser.m_timeFormatUnits == Serialized::UNITS_NONE) {
|
if (s_s.v.m_ser.m_timeFormatUnits == VerilatedImpData::Serialized::UNITS_NONE) {
|
||||||
return Verilated::timeprecision();
|
return Verilated::timeprecision();
|
||||||
}
|
}
|
||||||
return s_s.m_ser.m_timeFormatUnits;
|
return s_s.v.m_ser.m_timeFormatUnits;
|
||||||
}
|
}
|
||||||
static int timeFormatPrecision() VL_MT_SAFE { return s_s.m_ser.m_timeFormatPrecision; }
|
static int timeFormatPrecision() VL_MT_SAFE { return s_s.v.m_ser.m_timeFormatPrecision; }
|
||||||
static int timeFormatWidth() VL_MT_SAFE { return s_s.m_ser.m_timeFormatWidth; }
|
static int timeFormatWidth() VL_MT_SAFE { return s_s.v.m_ser.m_timeFormatWidth; }
|
||||||
static void timeFormatUnits(int value) VL_MT_SAFE;
|
static void timeFormatUnits(int value) VL_MT_SAFE;
|
||||||
static void timeFormatPrecision(int value) VL_MT_SAFE;
|
static void timeFormatPrecision(int value) VL_MT_SAFE;
|
||||||
static void timeFormatWidth(int value) VL_MT_SAFE;
|
static void timeFormatWidth(int value) VL_MT_SAFE;
|
||||||
|
|
||||||
public: // But only for verilated*.cpp
|
public: // But only for verilated*.cpp
|
||||||
// METHODS - file IO
|
// METHODS - file IO
|
||||||
static IData fdNew(FILE* fp) VL_MT_SAFE {
|
static IData fdNewMcd(const char* filenamep) VL_MT_SAFE {
|
||||||
|
const VerilatedLockGuard lock(s_s.v.m_fdMutex);
|
||||||
|
if (s_s.v.m_fdFreeMct.empty()) return 0;
|
||||||
|
IData idx = s_s.v.m_fdFreeMct.back();
|
||||||
|
s_s.v.m_fdFreeMct.pop_back();
|
||||||
|
s_s.v.m_fdps[idx] = fopen(filenamep, "w");
|
||||||
|
if (VL_UNLIKELY(!s_s.v.m_fdps[idx])) return 0;
|
||||||
|
return (1 << idx);
|
||||||
|
}
|
||||||
|
static IData fdNew(const char* filenamep, const char* modep) VL_MT_SAFE {
|
||||||
|
FILE* fp = fopen(filenamep, modep);
|
||||||
if (VL_UNLIKELY(!fp)) return 0;
|
if (VL_UNLIKELY(!fp)) return 0;
|
||||||
// Bit 31 indicates it's a descriptor not a MCD
|
// Bit 31 indicates it's a descriptor not a MCD
|
||||||
VerilatedLockGuard lock(s_s.m_fdMutex);
|
const VerilatedLockGuard lock(s_s.v.m_fdMutex);
|
||||||
if (s_s.m_fdFree.empty()) {
|
if (s_s.v.m_fdFree.empty()) {
|
||||||
// Need to create more space in m_fdps and m_fdFree
|
// Need to create more space in m_fdps and m_fdFree
|
||||||
size_t start = s_s.m_fdps.size();
|
const std::size_t start = std::max<std::size_t>(31UL + 1UL + 3UL, s_s.v.m_fdps.size());
|
||||||
s_s.m_fdps.resize(start * 2);
|
const std::size_t excess = 10;
|
||||||
for (size_t i = start; i < start * 2; ++i) {
|
s_s.v.m_fdps.resize(start + excess);
|
||||||
s_s.m_fdFree.push_back(static_cast<IData>(i));
|
std::fill(s_s.v.m_fdps.begin() + start, s_s.v.m_fdps.end(), (FILE*)0);
|
||||||
|
s_s.v.m_fdFree.resize(excess);
|
||||||
|
for (std::size_t i = 0, id = start; i < s_s.v.m_fdFree.size(); ++i, ++id) {
|
||||||
|
s_s.v.m_fdFree[i] = id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
IData idx = s_s.m_fdFree.back();
|
IData idx = s_s.v.m_fdFree.back();
|
||||||
s_s.m_fdFree.pop_back();
|
s_s.v.m_fdFree.pop_back();
|
||||||
s_s.m_fdps[idx] = fp;
|
s_s.v.m_fdps[idx] = fp;
|
||||||
return (idx | (1UL << 31)); // bit 31 indicates not MCD
|
return (idx | (1UL << 31)); // bit 31 indicates not MCD
|
||||||
}
|
}
|
||||||
static void fdDelete(IData fdi) VL_MT_SAFE {
|
static void fdFlush(IData fdi) VL_MT_SAFE {
|
||||||
IData idx = VL_MASK_I(31) & fdi;
|
const VerilatedLockGuard lock(s_s.v.m_fdMutex);
|
||||||
VerilatedLockGuard lock(s_s.m_fdMutex);
|
const VerilatedFpList fdlist = fdToFpList(fdi);
|
||||||
if (VL_UNLIKELY(!(fdi & (VL_ULL(1) << 31)) || idx >= s_s.m_fdps.size())) return;
|
for (const auto& i : fdlist) fflush(i);
|
||||||
if (VL_UNLIKELY(!s_s.m_fdps[idx])) return; // Already free
|
}
|
||||||
s_s.m_fdps[idx] = NULL;
|
static IData fdSeek(IData fdi, IData offset, IData origin) VL_MT_SAFE {
|
||||||
s_s.m_fdFree.push_back(idx);
|
const VerilatedLockGuard lock(s_s.v.m_fdMutex);
|
||||||
|
const VerilatedFpList fdlist = fdToFpList(fdi);
|
||||||
|
if (VL_UNLIKELY(fdlist.size() != 1)) return 0;
|
||||||
|
return static_cast<IData>(
|
||||||
|
fseek(*fdlist.begin(), static_cast<long>(offset), static_cast<int>(origin)));
|
||||||
|
}
|
||||||
|
static IData fdTell(IData fdi) VL_MT_SAFE {
|
||||||
|
const VerilatedLockGuard lock(s_s.v.m_fdMutex);
|
||||||
|
const VerilatedFpList fdlist = fdToFpList(fdi);
|
||||||
|
if (VL_UNLIKELY(fdlist.size() != 1)) return 0;
|
||||||
|
return static_cast<IData>(ftell(*fdlist.begin()));
|
||||||
|
}
|
||||||
|
static void fdWrite(IData fdi, const std::string& output) VL_MT_SAFE {
|
||||||
|
const VerilatedLockGuard lock(s_s.v.m_fdMutex);
|
||||||
|
const VerilatedFpList fdlist = fdToFpList(fdi);
|
||||||
|
for (const auto& i : fdlist) {
|
||||||
|
if (VL_UNLIKELY(!i)) continue;
|
||||||
|
(void)fwrite(output.c_str(), 1, output.size(), i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static void fdClose(IData fdi) VL_MT_SAFE {
|
||||||
|
const VerilatedLockGuard lock(s_s.v.m_fdMutex);
|
||||||
|
if ((fdi & (1 << 31)) != 0) {
|
||||||
|
// Non-MCD case
|
||||||
|
IData idx = VL_MASK_I(31) & fdi;
|
||||||
|
if (VL_UNLIKELY(idx >= s_s.v.m_fdps.size())) return;
|
||||||
|
if (VL_UNLIKELY(!s_s.v.m_fdps[idx])) return; // Already free
|
||||||
|
fclose(s_s.v.m_fdps[idx]);
|
||||||
|
s_s.v.m_fdps[idx] = (FILE*)0;
|
||||||
|
s_s.v.m_fdFree.push_back(idx);
|
||||||
|
} else {
|
||||||
|
// MCD case
|
||||||
|
for (int i = 0; (fdi != 0) && (i < 31); i++, fdi >>= 1) {
|
||||||
|
if (fdi & VL_MASK_I(1)) {
|
||||||
|
fclose(s_s.v.m_fdps[i]);
|
||||||
|
s_s.v.m_fdps[i] = nullptr;
|
||||||
|
s_s.v.m_fdFreeMct.push_back(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
static inline FILE* fdToFp(IData fdi) VL_MT_SAFE {
|
static inline FILE* fdToFp(IData fdi) VL_MT_SAFE {
|
||||||
IData idx = VL_MASK_I(31) & fdi;
|
const VerilatedLockGuard lock(s_s.v.m_fdMutex);
|
||||||
VerilatedLockGuard lock(s_s.m_fdMutex); // This might get slow, if it does we can cache it
|
const VerilatedFpList fdlist = fdToFpList(fdi);
|
||||||
if (VL_UNLIKELY(!(fdi & (VL_ULL(1) << 31)) || idx >= s_s.m_fdps.size())) return NULL;
|
if (VL_UNLIKELY(fdlist.size() != 1)) return nullptr;
|
||||||
return s_s.m_fdps[idx];
|
return *fdlist.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static inline VerilatedFpList fdToFpList(IData fdi) VL_REQUIRES(s_s.v.m_fdMutex) {
|
||||||
|
VerilatedFpList fp;
|
||||||
|
if ((fdi & (1 << 31)) != 0) {
|
||||||
|
// Non-MCD case
|
||||||
|
const IData idx = fdi & VL_MASK_I(31);
|
||||||
|
switch (idx) {
|
||||||
|
case 0: fp.push_back(stdin); break;
|
||||||
|
case 1: fp.push_back(stdout); break;
|
||||||
|
case 2: fp.push_back(stderr); break;
|
||||||
|
default:
|
||||||
|
if (VL_LIKELY(idx < s_s.v.m_fdps.size())) fp.push_back(s_s.v.m_fdps[idx]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// MCD Case
|
||||||
|
for (int i = 0; (fdi != 0) && (i < fp.capacity()); ++i, fdi >>= 1) {
|
||||||
|
if (fdi & VL_MASK_I(1)) fp.push_back(s_s.v.m_fdps[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fp;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2020 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2021 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// 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,8 +24,8 @@
|
|||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
|
|
||||||
// Use VL_DISABLE_INTRINSICS to disable all intrinsics based optimization
|
// Use VL_PORTABLE_ONLY to disable all intrinsics based optimization
|
||||||
#if !defined(VL_DISABLE_INTRINSICS) && !defined(VL_PORTABLE_ONLY)
|
#ifndef VL_PORTABLE_ONLY
|
||||||
# if defined(__SSE2__) && !defined(VL_DISABLE_SSE2)
|
# if defined(__SSE2__) && !defined(VL_DISABLE_SSE2)
|
||||||
# define VL_HAVE_SSE2 1
|
# define VL_HAVE_SSE2 1
|
||||||
# include <emmintrin.h>
|
# include <emmintrin.h>
|
||||||
|
|||||||
+27
-20
@@ -3,7 +3,7 @@
|
|||||||
//
|
//
|
||||||
// THIS MODULE IS PUBLICLY LICENSED
|
// THIS MODULE IS PUBLICLY LICENSED
|
||||||
//
|
//
|
||||||
// Copyright 2001-2020 by Wilson Snyder. This program is free software; you
|
// Copyright 2001-2021 by Wilson Snyder. This program is free software; you
|
||||||
// can redistribute it and/or modify it under the terms of either the GNU
|
// can 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.
|
||||||
@@ -42,9 +42,10 @@
|
|||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
// CONSTANTS
|
// CONSTANTS
|
||||||
static const char* const VLTSAVE_HEADER_STR
|
/// Value of first bytes of each file (must be multiple of 8 bytes)
|
||||||
= "verilatorsave01\n"; ///< Value of first bytes of each file
|
static const char* const VLTSAVE_HEADER_STR = "verilatorsave01\n";
|
||||||
static const char* const VLTSAVE_TRAILER_STR = "vltsaved"; ///< Value of last bytes of each file
|
/// Value of last bytes of each file (must be multiple of 8 bytes)
|
||||||
|
static const char* const VLTSAVE_TRAILER_STR = "vltsaved";
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
@@ -64,10 +65,10 @@ VerilatedDeserialize& VerilatedDeserialize::readAssert(const void* __restrict da
|
|||||||
size_t size) VL_MT_UNSAFE_ONE {
|
size_t size) VL_MT_UNSAFE_ONE {
|
||||||
if (VL_UNLIKELY(readDiffers(datap, size))) {
|
if (VL_UNLIKELY(readDiffers(datap, size))) {
|
||||||
std::string fn = filename();
|
std::string fn = filename();
|
||||||
std::string msg
|
std::string msg = "Can't deserialize save-restore file as was made from different model: "
|
||||||
= "Can't deserialize save-restore file as was made from different model:" + filename();
|
+ filename();
|
||||||
VL_FATAL_MT(fn.c_str(), 0, "", msg.c_str());
|
VL_FATAL_MT(fn.c_str(), 0, "", msg.c_str());
|
||||||
close();
|
// Die before we close() as close would infinite loop
|
||||||
}
|
}
|
||||||
return *this; // For function chaining
|
return *this; // For function chaining
|
||||||
}
|
}
|
||||||
@@ -88,9 +89,11 @@ void VerilatedDeserialize::header() VL_MT_UNSAFE_ONE {
|
|||||||
if (VL_UNLIKELY(os.readDiffers(VLTSAVE_HEADER_STR, strlen(VLTSAVE_HEADER_STR)))) {
|
if (VL_UNLIKELY(os.readDiffers(VLTSAVE_HEADER_STR, strlen(VLTSAVE_HEADER_STR)))) {
|
||||||
std::string fn = filename();
|
std::string fn = filename();
|
||||||
std::string msg
|
std::string msg
|
||||||
= std::string("Can't deserialize; file has wrong header signature: ") + filename();
|
= std::string(
|
||||||
|
"Can't deserialize; file has wrong header signature, or file not found: ")
|
||||||
|
+ filename();
|
||||||
VL_FATAL_MT(fn.c_str(), 0, "", msg.c_str());
|
VL_FATAL_MT(fn.c_str(), 0, "", msg.c_str());
|
||||||
close();
|
// Die before we close() as close would infinite loop
|
||||||
}
|
}
|
||||||
os.read(Verilated::serialized1Ptr(), Verilated::serialized1Size());
|
os.read(Verilated::serialized1Ptr(), Verilated::serialized1Size());
|
||||||
os.read(Verilated::serialized2Ptr(), Verilated::serialized2Size());
|
os.read(Verilated::serialized2Ptr(), Verilated::serialized2Size());
|
||||||
@@ -109,7 +112,7 @@ void VerilatedDeserialize::trailer() VL_MT_UNSAFE_ONE {
|
|||||||
std::string msg = std::string("Can't deserialize; file has wrong end-of-file signature: ")
|
std::string msg = std::string("Can't deserialize; file has wrong end-of-file signature: ")
|
||||||
+ filename();
|
+ filename();
|
||||||
VL_FATAL_MT(fn.c_str(), 0, "", msg.c_str());
|
VL_FATAL_MT(fn.c_str(), 0, "", msg.c_str());
|
||||||
close();
|
// Die before we close() as close would infinite loop
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,13 +126,13 @@ void VerilatedSave::open(const char* filenamep) VL_MT_UNSAFE_ONE {
|
|||||||
if (isOpen()) return;
|
if (isOpen()) return;
|
||||||
VL_DEBUG_IF(VL_DBG_MSGF("- save: opening save file %s\n", filenamep););
|
VL_DEBUG_IF(VL_DBG_MSGF("- save: opening save file %s\n", filenamep););
|
||||||
|
|
||||||
if (filenamep[0] == '|') {
|
if (VL_UNCOVERABLE(filenamep[0] == '|')) {
|
||||||
assert(0); // Not supported yet.
|
assert(0); // LCOV_EXCL_LINE // Not supported yet.
|
||||||
} else {
|
} else {
|
||||||
// cppcheck-suppress duplicateExpression
|
// cppcheck-suppress duplicateExpression
|
||||||
m_fd = ::open(filenamep,
|
m_fd = ::open(filenamep,
|
||||||
O_CREAT | O_WRONLY | O_TRUNC | O_LARGEFILE | O_NONBLOCK | O_CLOEXEC, 0666);
|
O_CREAT | O_WRONLY | O_TRUNC | O_LARGEFILE | O_NONBLOCK | O_CLOEXEC, 0666);
|
||||||
if (m_fd < 0) {
|
if (VL_UNLIKELY(m_fd < 0)) {
|
||||||
// User code can check isOpen()
|
// User code can check isOpen()
|
||||||
m_isOpen = false;
|
m_isOpen = false;
|
||||||
return;
|
return;
|
||||||
@@ -146,12 +149,12 @@ void VerilatedRestore::open(const char* filenamep) VL_MT_UNSAFE_ONE {
|
|||||||
if (isOpen()) return;
|
if (isOpen()) return;
|
||||||
VL_DEBUG_IF(VL_DBG_MSGF("- restore: opening restore file %s\n", filenamep););
|
VL_DEBUG_IF(VL_DBG_MSGF("- restore: opening restore file %s\n", filenamep););
|
||||||
|
|
||||||
if (filenamep[0] == '|') {
|
if (VL_UNCOVERABLE(filenamep[0] == '|')) {
|
||||||
assert(0); // Not supported yet.
|
assert(0); // LCOV_EXCL_LINE // Not supported yet.
|
||||||
} else {
|
} else {
|
||||||
// cppcheck-suppress duplicateExpression
|
// cppcheck-suppress duplicateExpression
|
||||||
m_fd = ::open(filenamep, O_CREAT | O_RDONLY | O_LARGEFILE | O_CLOEXEC, 0666);
|
m_fd = ::open(filenamep, O_CREAT | O_RDONLY | O_LARGEFILE | O_CLOEXEC, 0666);
|
||||||
if (m_fd < 0) {
|
if (VL_UNLIKELY(m_fd < 0)) {
|
||||||
// User code can check isOpen()
|
// User code can check isOpen()
|
||||||
m_isOpen = false;
|
m_isOpen = false;
|
||||||
return;
|
return;
|
||||||
@@ -194,13 +197,15 @@ void VerilatedSave::flush() VL_MT_UNSAFE_ONE {
|
|||||||
ssize_t got = ::write(m_fd, wp, remaining);
|
ssize_t got = ::write(m_fd, wp, remaining);
|
||||||
if (got > 0) {
|
if (got > 0) {
|
||||||
wp += got;
|
wp += got;
|
||||||
} else if (got < 0) {
|
} else if (VL_UNCOVERABLE(got < 0)) {
|
||||||
if (errno != EAGAIN && errno != EINTR) {
|
if (VL_UNCOVERABLE(errno != EAGAIN && errno != EINTR)) {
|
||||||
|
// LCOV_EXCL_START
|
||||||
// write failed, presume error (perhaps out of disk space)
|
// write failed, presume error (perhaps out of disk space)
|
||||||
std::string msg = std::string(__FUNCTION__) + ": " + strerror(errno);
|
std::string msg = std::string(__FUNCTION__) + ": " + strerror(errno);
|
||||||
VL_FATAL_MT("", 0, "", msg.c_str());
|
VL_FATAL_MT("", 0, "", msg.c_str());
|
||||||
close();
|
close();
|
||||||
break;
|
break;
|
||||||
|
// LCOV_EXCL_STOP
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -223,13 +228,15 @@ void VerilatedRestore::fill() VL_MT_UNSAFE_ONE {
|
|||||||
ssize_t got = ::read(m_fd, m_endp, remaining);
|
ssize_t got = ::read(m_fd, m_endp, remaining);
|
||||||
if (got > 0) {
|
if (got > 0) {
|
||||||
m_endp += got;
|
m_endp += got;
|
||||||
} else if (got < 0) {
|
} else if (VL_UNCOVERABLE(got < 0)) {
|
||||||
if (errno != EAGAIN && errno != EINTR) {
|
if (VL_UNCOVERABLE(errno != EAGAIN && errno != EINTR)) {
|
||||||
|
// LCOV_EXCL_START
|
||||||
// write failed, presume error (perhaps out of disk space)
|
// write failed, presume error (perhaps out of disk space)
|
||||||
std::string msg = std::string(__FUNCTION__) + ": " + strerror(errno);
|
std::string msg = std::string(__FUNCTION__) + ": " + strerror(errno);
|
||||||
VL_FATAL_MT("", 0, "", msg.c_str());
|
VL_FATAL_MT("", 0, "", msg.c_str());
|
||||||
close();
|
close();
|
||||||
break;
|
break;
|
||||||
|
// LCOV_EXCL_STOP
|
||||||
}
|
}
|
||||||
} else { // got==0, EOF
|
} else { // got==0, EOF
|
||||||
// Fill buffer from here to end with NULLs so reader's don't
|
// Fill buffer from here to end with NULLs so reader's don't
|
||||||
|
|||||||
+28
-34
@@ -3,7 +3,7 @@
|
|||||||
//
|
//
|
||||||
// THIS MODULE IS PUBLICLY LICENSED
|
// THIS MODULE IS PUBLICLY LICENSED
|
||||||
//
|
//
|
||||||
// Copyright 2000-2020 by Wilson Snyder. This program is free software; you
|
// Copyright 2000-2021 by Wilson Snyder. This program is free software; you
|
||||||
// can redistribute it and/or modify it under the terms of either the GNU
|
// can 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,18 +28,18 @@
|
|||||||
// VerilatedSerialize - convert structures to a stream representation
|
// VerilatedSerialize - convert structures to a stream representation
|
||||||
// This class is not thread safe, it must be called by a single thread
|
// This class is not thread safe, it must be called by a single thread
|
||||||
|
|
||||||
class VerilatedSerialize {
|
class VerilatedSerialize VL_NOT_FINAL {
|
||||||
protected:
|
protected:
|
||||||
// MEMBERS
|
// MEMBERS
|
||||||
// For speed, keep m_cp as the first member of this structure
|
// 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_cp; ///< Current pointer into m_bufp buffer
|
||||||
vluint8_t* m_bufp; ///< Output buffer
|
vluint8_t* m_bufp; ///< Output buffer
|
||||||
bool m_isOpen; ///< True indicates open file/stream
|
bool m_isOpen = false; ///< True indicates open file/stream
|
||||||
std::string m_filename; ///< Filename, for error messages
|
std::string m_filename; ///< Filename, for error messages
|
||||||
VerilatedAssertOneThread m_assertOne; ///< Assert only called from single thread
|
VerilatedAssertOneThread m_assertOne; ///< Assert only called from single thread
|
||||||
|
|
||||||
inline static size_t bufferSize() { return 256 * 1024; } // See below for slack calculation
|
static constexpr size_t bufferSize() { return 256 * 1024; } // See below for slack calculation
|
||||||
inline static size_t bufferInsertSize() { return 16 * 1024; }
|
static constexpr size_t bufferInsertSize() { return 16 * 1024; }
|
||||||
|
|
||||||
void header() VL_MT_UNSAFE_ONE;
|
void header() VL_MT_UNSAFE_ONE;
|
||||||
void trailer() VL_MT_UNSAFE_ONE;
|
void trailer() VL_MT_UNSAFE_ONE;
|
||||||
@@ -49,13 +49,12 @@ protected:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
VerilatedSerialize() {
|
VerilatedSerialize() {
|
||||||
m_isOpen = false;
|
|
||||||
m_bufp = new vluint8_t[bufferSize()];
|
m_bufp = new vluint8_t[bufferSize()];
|
||||||
m_cp = m_bufp;
|
m_cp = m_bufp;
|
||||||
}
|
}
|
||||||
virtual ~VerilatedSerialize() {
|
virtual ~VerilatedSerialize() {
|
||||||
close();
|
close();
|
||||||
if (m_bufp) VL_DO_CLEAR(delete m_bufp, m_bufp = NULL);
|
if (m_bufp) VL_DO_CLEAR(delete[] m_bufp, m_bufp = nullptr);
|
||||||
}
|
}
|
||||||
// METHODS
|
// METHODS
|
||||||
bool isOpen() const { return m_isOpen; }
|
bool isOpen() const { return m_isOpen; }
|
||||||
@@ -88,19 +87,19 @@ private:
|
|||||||
// VerilatedDeserial - load structures from a stream representation
|
// VerilatedDeserial - load structures from a stream representation
|
||||||
// This class is not thread safe, it must be called by a single thread
|
// This class is not thread safe, it must be called by a single thread
|
||||||
|
|
||||||
class VerilatedDeserialize {
|
class VerilatedDeserialize VL_NOT_FINAL {
|
||||||
protected:
|
protected:
|
||||||
// MEMBERS
|
// MEMBERS
|
||||||
// For speed, keep m_cp as the first member of this structure
|
// 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_cp; ///< Current pointer into m_bufp buffer
|
||||||
vluint8_t* m_bufp; ///< Output buffer
|
vluint8_t* m_bufp; ///< Output buffer
|
||||||
vluint8_t* m_endp; ///< Last valid byte in m_bufp buffer
|
vluint8_t* m_endp = nullptr; ///< Last valid byte in m_bufp buffer
|
||||||
bool m_isOpen; ///< True indicates open file/stream
|
bool m_isOpen = false; ///< True indicates open file/stream
|
||||||
std::string m_filename; ///< Filename, for error messages
|
std::string m_filename; ///< Filename, for error messages
|
||||||
VerilatedAssertOneThread m_assertOne; ///< Assert only called from single thread
|
VerilatedAssertOneThread m_assertOne; ///< Assert only called from single thread
|
||||||
|
|
||||||
inline static size_t bufferSize() { return 256 * 1024; } // See below for slack calculation
|
static constexpr size_t bufferSize() { return 256 * 1024; } // See below for slack calculation
|
||||||
inline static size_t bufferInsertSize() { return 16 * 1024; }
|
static constexpr size_t bufferInsertSize() { return 16 * 1024; }
|
||||||
|
|
||||||
virtual void fill() = 0;
|
virtual void fill() = 0;
|
||||||
void header() VL_MT_UNSAFE_ONE;
|
void header() VL_MT_UNSAFE_ONE;
|
||||||
@@ -111,14 +110,12 @@ protected:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
VerilatedDeserialize() {
|
VerilatedDeserialize() {
|
||||||
m_isOpen = false;
|
|
||||||
m_bufp = new vluint8_t[bufferSize()];
|
m_bufp = new vluint8_t[bufferSize()];
|
||||||
m_cp = m_bufp;
|
m_cp = m_bufp;
|
||||||
m_endp = NULL;
|
|
||||||
}
|
}
|
||||||
virtual ~VerilatedDeserialize() {
|
virtual ~VerilatedDeserialize() {
|
||||||
close();
|
close();
|
||||||
if (m_bufp) VL_DO_CLEAR(delete m_bufp, m_bufp = NULL);
|
if (m_bufp) VL_DO_CLEAR(delete[] m_bufp, m_bufp = nullptr);
|
||||||
}
|
}
|
||||||
// METHODS
|
// METHODS
|
||||||
bool isOpen() const { return m_isOpen; }
|
bool isOpen() const { return m_isOpen; }
|
||||||
@@ -157,44 +154,42 @@ private:
|
|||||||
// VerilatedSave - serialize to a file
|
// VerilatedSave - serialize to a file
|
||||||
// This class is not thread safe, it must be called by a single thread
|
// This class is not thread safe, it must be called by a single thread
|
||||||
|
|
||||||
class VerilatedSave : public VerilatedSerialize {
|
class VerilatedSave final : public VerilatedSerialize {
|
||||||
private:
|
private:
|
||||||
int m_fd; ///< File descriptor we're writing to
|
int m_fd = -1; ///< File descriptor we're writing to
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// CONSTRUCTORS
|
// CONSTRUCTORS
|
||||||
VerilatedSave()
|
VerilatedSave() = default;
|
||||||
: m_fd(-1) {}
|
virtual ~VerilatedSave() override { close(); }
|
||||||
virtual ~VerilatedSave() VL_OVERRIDE { close(); }
|
|
||||||
// METHODS
|
// METHODS
|
||||||
/// Open the file; call isOpen() to see if errors
|
/// Open the file; call isOpen() to see if errors
|
||||||
void open(const char* filenamep) VL_MT_UNSAFE_ONE;
|
void open(const char* filenamep) VL_MT_UNSAFE_ONE;
|
||||||
void open(const std::string& filename) VL_MT_UNSAFE_ONE { open(filename.c_str()); }
|
void open(const std::string& filename) VL_MT_UNSAFE_ONE { open(filename.c_str()); }
|
||||||
virtual void close() VL_OVERRIDE VL_MT_UNSAFE_ONE;
|
virtual void close() override VL_MT_UNSAFE_ONE;
|
||||||
virtual void flush() VL_OVERRIDE VL_MT_UNSAFE_ONE;
|
virtual void flush() override VL_MT_UNSAFE_ONE;
|
||||||
};
|
};
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
// VerilatedRestore - deserialize from a file
|
// VerilatedRestore - deserialize from a file
|
||||||
// This class is not thread safe, it must be called by a single thread
|
// This class is not thread safe, it must be called by a single thread
|
||||||
|
|
||||||
class VerilatedRestore : public VerilatedDeserialize {
|
class VerilatedRestore final : public VerilatedDeserialize {
|
||||||
private:
|
private:
|
||||||
int m_fd; ///< File descriptor we're writing to
|
int m_fd = -1; ///< File descriptor we're writing to
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// CONSTRUCTORS
|
// CONSTRUCTORS
|
||||||
VerilatedRestore()
|
VerilatedRestore() = default;
|
||||||
: m_fd(-1) {}
|
virtual ~VerilatedRestore() override { close(); }
|
||||||
virtual ~VerilatedRestore() VL_OVERRIDE { close(); }
|
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
/// Open the file; call isOpen() to see if errors
|
/// Open the file; call isOpen() to see if errors
|
||||||
void open(const char* filenamep) VL_MT_UNSAFE_ONE;
|
void open(const char* filenamep) VL_MT_UNSAFE_ONE;
|
||||||
void open(const std::string& filename) VL_MT_UNSAFE_ONE { open(filename.c_str()); }
|
void open(const std::string& filename) VL_MT_UNSAFE_ONE { open(filename.c_str()); }
|
||||||
virtual void close() VL_OVERRIDE VL_MT_UNSAFE_ONE;
|
virtual void close() override VL_MT_UNSAFE_ONE;
|
||||||
virtual void flush() VL_OVERRIDE VL_MT_UNSAFE_ONE {}
|
virtual void flush() override VL_MT_UNSAFE_ONE {}
|
||||||
virtual void fill() VL_OVERRIDE VL_MT_UNSAFE_ONE;
|
virtual void fill() override VL_MT_UNSAFE_ONE;
|
||||||
};
|
};
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
@@ -257,10 +252,9 @@ VerilatedSerialize& operator<<(VerilatedSerialize& os, VlAssocArray<T_Key, T_Val
|
|||||||
os << rhs.atDefault();
|
os << rhs.atDefault();
|
||||||
vluint32_t len = rhs.size();
|
vluint32_t len = rhs.size();
|
||||||
os << len;
|
os << len;
|
||||||
for (typename VlAssocArray<T_Key, T_Value>::const_iterator it = rhs.begin(); it != rhs.end();
|
for (const auto& i : rhs) {
|
||||||
++it) {
|
T_Key index = i.first; // Copy to get around const_iterator
|
||||||
T_Key index = it->first; // Copy to get around const_iterator
|
T_Value value = i.second;
|
||||||
T_Value value = it->second;
|
|
||||||
os << index << value;
|
os << index << value;
|
||||||
}
|
}
|
||||||
return os;
|
return os;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2009-2020 by Wilson Snyder. This program is free software; you can
|
// Copyright 2009-2021 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// 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.
|
||||||
@@ -34,7 +34,7 @@
|
|||||||
// This class is thread safe (though most of SystemC is not).
|
// This class is thread safe (though most of SystemC is not).
|
||||||
|
|
||||||
#define VL_SC_BV_DATAP(bv) (VlScBvExposer::sp_datap(bv))
|
#define VL_SC_BV_DATAP(bv) (VlScBvExposer::sp_datap(bv))
|
||||||
class VlScBvExposer : public sc_bv_base {
|
class VlScBvExposer final : public sc_bv_base {
|
||||||
public:
|
public:
|
||||||
static const vluint32_t* sp_datap(const sc_bv_base& base) VL_MT_SAFE {
|
static const vluint32_t* sp_datap(const sc_bv_base& base) VL_MT_SAFE {
|
||||||
return static_cast<const VlScBvExposer*>(&base)->sp_datatp();
|
return static_cast<const VlScBvExposer*>(&base)->sp_datatp();
|
||||||
|
|||||||
+81
-111
@@ -1,7 +1,7 @@
|
|||||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2020 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2021 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// 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.
|
||||||
@@ -29,31 +29,31 @@
|
|||||||
|
|
||||||
#include "verilatedos.h"
|
#include "verilatedos.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
/// Verilator range
|
/// Verilator range
|
||||||
/// Thread safety: Assume is constructed only with model, then any number of readers
|
/// Thread safety: Assume is constructed only with model, then any number of readers
|
||||||
|
|
||||||
// See also V3Ast::VNumRange
|
// See also V3Ast::VNumRange
|
||||||
class VerilatedRange {
|
class VerilatedRange final {
|
||||||
int m_left;
|
int m_left = 0;
|
||||||
int m_right;
|
int m_right = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class VerilatedVarProps;
|
friend class VerilatedVarProps;
|
||||||
friend class VerilatedScope;
|
friend class VerilatedScope;
|
||||||
VerilatedRange()
|
VerilatedRange() = default;
|
||||||
: m_left(0)
|
|
||||||
, m_right(0) {}
|
|
||||||
VerilatedRange(int left, int right)
|
|
||||||
: m_left(left)
|
|
||||||
, m_right(right) {}
|
|
||||||
void init(int left, int right) {
|
void init(int left, int right) {
|
||||||
m_left = left;
|
m_left = left;
|
||||||
m_right = right;
|
m_right = right;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
~VerilatedRange() {}
|
VerilatedRange(int left, int right)
|
||||||
|
: m_left{left}
|
||||||
|
, m_right{right} {}
|
||||||
|
~VerilatedRange() = default;
|
||||||
int left() const { return m_left; }
|
int left() const { return m_left; }
|
||||||
int right() const { return m_right; }
|
int right() const { return m_right; }
|
||||||
int low() const { return (m_left < m_right) ? m_left : m_right; }
|
int low() const { return (m_left < m_right) ? m_left : m_right; }
|
||||||
@@ -68,110 +68,75 @@ public:
|
|||||||
/// Verilator variable
|
/// Verilator variable
|
||||||
/// Thread safety: Assume is constructed only with model, then any number of readers
|
/// Thread safety: Assume is constructed only with model, then any number of readers
|
||||||
|
|
||||||
class VerilatedVarProps {
|
class VerilatedVarProps VL_NOT_FINAL {
|
||||||
// TYPES
|
// TYPES
|
||||||
enum { MAGIC = 0xddc4f829 };
|
enum { MAGIC = 0xddc4f829 };
|
||||||
// MEMBERS
|
// MEMBERS
|
||||||
const vluint32_t m_magic; // Magic number
|
const vluint32_t m_magic; // Magic number
|
||||||
const VerilatedVarType m_vltype; // Data type
|
const VerilatedVarType m_vltype; // Data type
|
||||||
const VerilatedVarFlags m_vlflags; // Direction
|
const VerilatedVarFlags m_vlflags; // Direction
|
||||||
const int m_pdims; // Packed dimensions
|
const int m_pdims; // Packed dimensions, 0 = none
|
||||||
const int m_udims; // Unpacked dimensions
|
const int m_udims; // Unpacked dimensions, 0 = none
|
||||||
VerilatedRange m_packed; // Packed array range
|
VerilatedRange m_packed; // Packed array range
|
||||||
VerilatedRange m_unpacked[3]; // Unpacked array range
|
std::vector<VerilatedRange> m_unpacked; // Unpacked array ranges
|
||||||
|
void initUnpacked(const int* ulims) {
|
||||||
|
for (int i = 0; i < m_udims; ++i) {
|
||||||
|
const int uleft = ulims ? ulims[2 * i + 0] : 0;
|
||||||
|
const int uright = ulims ? ulims[2 * i + 1] : 0;
|
||||||
|
m_unpacked.emplace_back(uleft, uright);
|
||||||
|
}
|
||||||
|
}
|
||||||
// CONSTRUCTORS
|
// CONSTRUCTORS
|
||||||
protected:
|
protected:
|
||||||
friend class VerilatedScope;
|
friend class VerilatedScope;
|
||||||
VerilatedVarProps(VerilatedVarType vltype, VerilatedVarFlags vlflags, int pdims, int udims)
|
VerilatedVarProps(VerilatedVarType vltype, VerilatedVarFlags vlflags, int pdims, int udims)
|
||||||
: m_magic(MAGIC)
|
: m_magic{MAGIC}
|
||||||
, m_vltype(vltype)
|
, m_vltype{vltype}
|
||||||
, m_vlflags(vlflags)
|
, m_vlflags{vlflags}
|
||||||
, m_pdims(pdims)
|
, m_pdims{pdims}
|
||||||
, m_udims(udims) {}
|
, m_udims{udims} {
|
||||||
|
initUnpacked(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
class Unpacked {};
|
class Unpacked {};
|
||||||
// Without packed
|
// Without packed
|
||||||
VerilatedVarProps(VerilatedVarType vltype, int vlflags)
|
VerilatedVarProps(VerilatedVarType vltype, int vlflags)
|
||||||
: m_magic(MAGIC)
|
: m_magic{MAGIC}
|
||||||
, m_vltype(vltype)
|
, m_vltype{vltype}
|
||||||
, m_vlflags(VerilatedVarFlags(vlflags))
|
, m_vlflags(VerilatedVarFlags(vlflags)) // Need () or GCC 4.8 false warning
|
||||||
, m_pdims(0)
|
, m_pdims{0}
|
||||||
, m_udims(0) {}
|
, m_udims{0} {}
|
||||||
VerilatedVarProps(VerilatedVarType vltype, int vlflags, Unpacked, int u0l, int u0r)
|
VerilatedVarProps(VerilatedVarType vltype, int vlflags, Unpacked, int udims, const int* ulims)
|
||||||
: m_magic(MAGIC)
|
: m_magic{MAGIC}
|
||||||
, m_vltype(vltype)
|
, m_vltype{vltype}
|
||||||
, m_vlflags(VerilatedVarFlags(vlflags))
|
, m_vlflags(VerilatedVarFlags(vlflags)) // Need () or GCC 4.8 false warning
|
||||||
, m_pdims(0)
|
, m_pdims{0}
|
||||||
, m_udims(1) {
|
, m_udims{udims} {
|
||||||
m_unpacked[0].init(u0l, u0r);
|
initUnpacked(ulims);
|
||||||
}
|
|
||||||
VerilatedVarProps(VerilatedVarType vltype, int vlflags, Unpacked, int u0l, int u0r, int u1l,
|
|
||||||
int u1r)
|
|
||||||
: m_magic(MAGIC)
|
|
||||||
, m_vltype(vltype)
|
|
||||||
, m_vlflags(VerilatedVarFlags(vlflags))
|
|
||||||
, m_pdims(0)
|
|
||||||
, m_udims(2) {
|
|
||||||
m_unpacked[0].init(u0l, u0r);
|
|
||||||
m_unpacked[1].init(u1l, u1r);
|
|
||||||
}
|
|
||||||
VerilatedVarProps(VerilatedVarType vltype, int vlflags, Unpacked, int u0l, int u0r, int u1l,
|
|
||||||
int u1r, int u2l, int u2r)
|
|
||||||
: m_magic(MAGIC)
|
|
||||||
, m_vltype(vltype)
|
|
||||||
, m_vlflags(VerilatedVarFlags(vlflags))
|
|
||||||
, m_pdims(0)
|
|
||||||
, m_udims(3) {
|
|
||||||
m_unpacked[0].init(u0l, u0r);
|
|
||||||
m_unpacked[1].init(u1l, u1r);
|
|
||||||
m_unpacked[2].init(u2l, u2r);
|
|
||||||
}
|
}
|
||||||
// With packed
|
// With packed
|
||||||
class Packed {};
|
class Packed {};
|
||||||
VerilatedVarProps(VerilatedVarType vltype, int vlflags, Packed, int pl, int pr)
|
VerilatedVarProps(VerilatedVarType vltype, int vlflags, Packed, int pl, int pr)
|
||||||
: m_magic(MAGIC)
|
: m_magic{MAGIC}
|
||||||
, m_vltype(vltype)
|
, m_vltype{vltype}
|
||||||
, m_vlflags(VerilatedVarFlags(vlflags))
|
, m_vlflags(VerilatedVarFlags(vlflags)) // Need () or GCC 4.8 false warning
|
||||||
, m_pdims(1)
|
, m_pdims{1}
|
||||||
, m_udims(0)
|
, m_udims{0}
|
||||||
, m_packed(pl, pr) {}
|
, m_packed{pl, pr} {}
|
||||||
VerilatedVarProps(VerilatedVarType vltype, int vlflags, Packed, int pl, int pr, Unpacked,
|
VerilatedVarProps(VerilatedVarType vltype, int vlflags, Packed, int pl, int pr, Unpacked,
|
||||||
int u0l, int u0r)
|
int udims, const int* ulims)
|
||||||
: m_magic(MAGIC)
|
: m_magic{MAGIC}
|
||||||
, m_vltype(vltype)
|
, m_vltype{vltype}
|
||||||
, m_vlflags(VerilatedVarFlags(vlflags))
|
, m_vlflags(VerilatedVarFlags(vlflags)) // Need () or GCC 4.8 false warning
|
||||||
, m_pdims(1)
|
, m_pdims{1}
|
||||||
, m_udims(1)
|
, m_udims{udims}
|
||||||
, m_packed(pl, pr) {
|
, m_packed{pl, pr} {
|
||||||
m_unpacked[0].init(u0l, u0r);
|
initUnpacked(ulims);
|
||||||
}
|
|
||||||
VerilatedVarProps(VerilatedVarType vltype, int vlflags, Packed, int pl, int pr, Unpacked,
|
|
||||||
int u0l, int u0r, int u1l, int u1r)
|
|
||||||
: m_magic(MAGIC)
|
|
||||||
, m_vltype(vltype)
|
|
||||||
, m_vlflags(VerilatedVarFlags(vlflags))
|
|
||||||
, m_pdims(1)
|
|
||||||
, m_udims(2)
|
|
||||||
, m_packed(pl, pr) {
|
|
||||||
m_unpacked[0].init(u0l, u0r);
|
|
||||||
m_unpacked[1].init(u1l, u1r);
|
|
||||||
}
|
|
||||||
VerilatedVarProps(VerilatedVarType vltype, int vlflags, Packed, int pl, int pr, Unpacked,
|
|
||||||
int u0l, int u0r, int u1l, int u1r, int u2l, int u2r)
|
|
||||||
: m_magic(MAGIC)
|
|
||||||
, m_vltype(vltype)
|
|
||||||
, m_vlflags(VerilatedVarFlags(vlflags))
|
|
||||||
, m_pdims(1)
|
|
||||||
, m_udims(3)
|
|
||||||
, m_packed(pl, pr) {
|
|
||||||
m_unpacked[0].init(u0l, u0r);
|
|
||||||
m_unpacked[1].init(u1l, u1r);
|
|
||||||
m_unpacked[2].init(u2l, u2r);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
~VerilatedVarProps() {}
|
~VerilatedVarProps() = default;
|
||||||
// METHODS
|
// METHODS
|
||||||
bool magicOk() const { return m_magic == MAGIC; }
|
bool magicOk() const { return m_magic == MAGIC; }
|
||||||
VerilatedVarType vltype() const { return m_vltype; }
|
VerilatedVarType vltype() const { return m_vltype; }
|
||||||
@@ -189,27 +154,29 @@ public:
|
|||||||
// DPI accessors
|
// DPI accessors
|
||||||
int left(int dim) const {
|
int left(int dim) const {
|
||||||
return dim == 0 ? m_packed.left()
|
return dim == 0 ? m_packed.left()
|
||||||
: VL_LIKELY(dim >= 1 && dim <= 3) ? m_unpacked[dim - 1].left() : 0;
|
: VL_LIKELY(dim >= 1 && dim <= udims()) ? m_unpacked[dim - 1].left() : 0;
|
||||||
}
|
}
|
||||||
int right(int dim) const {
|
int right(int dim) const {
|
||||||
return dim == 0 ? m_packed.right()
|
return dim == 0 ? m_packed.right()
|
||||||
: VL_LIKELY(dim >= 1 && dim <= 3) ? m_unpacked[dim - 1].right() : 0;
|
: VL_LIKELY(dim >= 1 && dim <= udims()) ? m_unpacked[dim - 1].right() : 0;
|
||||||
}
|
}
|
||||||
int low(int dim) const {
|
int low(int dim) const {
|
||||||
return dim == 0 ? m_packed.low()
|
return dim == 0 ? m_packed.low()
|
||||||
: VL_LIKELY(dim >= 1 && dim <= 3) ? m_unpacked[dim - 1].low() : 0;
|
: VL_LIKELY(dim >= 1 && dim <= udims()) ? m_unpacked[dim - 1].low() : 0;
|
||||||
}
|
}
|
||||||
int high(int dim) const {
|
int high(int dim) const {
|
||||||
return dim == 0 ? m_packed.high()
|
return dim == 0 ? m_packed.high()
|
||||||
: VL_LIKELY(dim >= 1 && dim <= 3) ? m_unpacked[dim - 1].high() : 0;
|
: VL_LIKELY(dim >= 1 && dim <= udims()) ? m_unpacked[dim - 1].high() : 0;
|
||||||
}
|
}
|
||||||
int increment(int dim) const {
|
int increment(int dim) const {
|
||||||
return dim == 0 ? m_packed.increment()
|
return dim == 0
|
||||||
: VL_LIKELY(dim >= 1 && dim <= 3) ? m_unpacked[dim - 1].increment() : 0;
|
? m_packed.increment()
|
||||||
|
: VL_LIKELY(dim >= 1 && dim <= udims()) ? m_unpacked[dim - 1].increment() : 0;
|
||||||
}
|
}
|
||||||
int elements(int dim) const {
|
int elements(int dim) const {
|
||||||
return dim == 0 ? m_packed.elements()
|
return dim == 0
|
||||||
: VL_LIKELY(dim >= 1 && dim <= 3) ? m_unpacked[dim - 1].elements() : 0;
|
? m_packed.elements()
|
||||||
|
: VL_LIKELY(dim >= 1 && dim <= udims()) ? m_unpacked[dim - 1].elements() : 0;
|
||||||
}
|
}
|
||||||
/// Total size in bytes (note DPI limited to 4GB)
|
/// Total size in bytes (note DPI limited to 4GB)
|
||||||
size_t totalSize() const;
|
size_t totalSize() const;
|
||||||
@@ -220,19 +187,19 @@ public:
|
|||||||
//===========================================================================
|
//===========================================================================
|
||||||
/// Verilator DPI open array variable
|
/// Verilator DPI open array variable
|
||||||
|
|
||||||
class VerilatedDpiOpenVar {
|
class VerilatedDpiOpenVar final {
|
||||||
// MEMBERS
|
// MEMBERS
|
||||||
const VerilatedVarProps* m_propsp; // Variable properties
|
const VerilatedVarProps* m_propsp; // Variable properties
|
||||||
void* m_datap; // Location of data (local to thread always, so safe)
|
void* m_datap; // Location of data (local to thread always, so safe)
|
||||||
public:
|
public:
|
||||||
// CONSTRUCTORS
|
// CONSTRUCTORS
|
||||||
VerilatedDpiOpenVar(const VerilatedVarProps* propsp, void* datap)
|
VerilatedDpiOpenVar(const VerilatedVarProps* propsp, void* datap)
|
||||||
: m_propsp(propsp)
|
: m_propsp{propsp}
|
||||||
, m_datap(datap) {}
|
, m_datap{datap} {}
|
||||||
VerilatedDpiOpenVar(const VerilatedVarProps* propsp, const void* datap)
|
VerilatedDpiOpenVar(const VerilatedVarProps* propsp, const void* datap)
|
||||||
: m_propsp(propsp)
|
: m_propsp{propsp}
|
||||||
, m_datap(const_cast<void*>(datap)) {}
|
, m_datap{const_cast<void*>(datap)} {}
|
||||||
~VerilatedDpiOpenVar() {}
|
~VerilatedDpiOpenVar() = default;
|
||||||
// METHODS
|
// METHODS
|
||||||
void* datap() const { return m_datap; }
|
void* datap() const { return m_datap; }
|
||||||
// METHODS - from VerilatedVarProps
|
// METHODS - from VerilatedVarProps
|
||||||
@@ -258,26 +225,29 @@ public:
|
|||||||
/// Verilator variable
|
/// Verilator variable
|
||||||
/// Thread safety: Assume is constructed only with model, then any number of readers
|
/// Thread safety: Assume is constructed only with model, then any number of readers
|
||||||
|
|
||||||
class VerilatedVar : public VerilatedVarProps {
|
class VerilatedVar final : public VerilatedVarProps {
|
||||||
// MEMBERS
|
// MEMBERS
|
||||||
void* m_datap; // Location of data
|
void* m_datap; // Location of data
|
||||||
const char* m_namep; // Name - slowpath
|
const char* m_namep; // Name - slowpath
|
||||||
protected:
|
protected:
|
||||||
|
bool m_isParam;
|
||||||
friend class VerilatedScope;
|
friend class VerilatedScope;
|
||||||
// CONSTRUCTORS
|
// CONSTRUCTORS
|
||||||
VerilatedVar(const char* namep, void* datap, VerilatedVarType vltype,
|
VerilatedVar(const char* namep, void* datap, VerilatedVarType vltype,
|
||||||
VerilatedVarFlags vlflags, int dims)
|
VerilatedVarFlags vlflags, int dims, bool isParam)
|
||||||
: VerilatedVarProps(vltype, vlflags, (dims > 0 ? 1 : 0), ((dims > 1) ? dims - 1 : 0))
|
: VerilatedVarProps{vltype, vlflags, (dims > 0 ? 1 : 0), ((dims > 1) ? dims - 1 : 0)}
|
||||||
, m_datap(datap)
|
, m_datap{datap}
|
||||||
, m_namep(namep) {}
|
, m_namep{namep}
|
||||||
|
, m_isParam{isParam} {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
~VerilatedVar() {}
|
~VerilatedVar() = default;
|
||||||
// ACCESSORS
|
// ACCESSORS
|
||||||
void* datap() const { return m_datap; }
|
void* datap() const { return m_datap; }
|
||||||
const VerilatedRange& range() const { return packed(); } // Deprecated
|
const VerilatedRange& range() const { return packed(); } // Deprecated
|
||||||
const VerilatedRange& array() const { return unpacked(); } // Deprecated
|
const VerilatedRange& array() const { return unpacked(); } // Deprecated
|
||||||
const char* name() const { return m_namep; }
|
const char* name() const { return m_namep; }
|
||||||
|
bool isParam() const { return m_isParam; }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // Guard
|
#endif // Guard
|
||||||
|
|||||||
+12
-10
@@ -1,7 +1,7 @@
|
|||||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2020 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2021 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// 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,6 +31,7 @@
|
|||||||
#include "verilated_sym_props.h"
|
#include "verilated_sym_props.h"
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
//======================================================================
|
//======================================================================
|
||||||
@@ -42,26 +43,27 @@ struct VerilatedCStrCmp {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// Map of sorted scope names to find associated scope class
|
/// Map of sorted scope names to find associated scope class
|
||||||
class VerilatedScopeNameMap
|
class VerilatedScopeNameMap final
|
||||||
: public std::map<const char*, const VerilatedScope*, VerilatedCStrCmp> {
|
: public std::map<const char*, const VerilatedScope*, VerilatedCStrCmp> {
|
||||||
public:
|
public:
|
||||||
VerilatedScopeNameMap() {}
|
VerilatedScopeNameMap() = default;
|
||||||
~VerilatedScopeNameMap() {}
|
~VerilatedScopeNameMap() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Map of sorted variable names to find associated variable class
|
/// Map of sorted variable names to find associated variable class
|
||||||
class VerilatedVarNameMap : public std::map<const char*, VerilatedVar, VerilatedCStrCmp> {
|
class VerilatedVarNameMap final : public std::map<const char*, VerilatedVar, VerilatedCStrCmp> {
|
||||||
public:
|
public:
|
||||||
VerilatedVarNameMap() {}
|
VerilatedVarNameMap() = default;
|
||||||
~VerilatedVarNameMap() {}
|
~VerilatedVarNameMap() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::vector<const VerilatedScope*> VerilatedScopeVector;
|
typedef std::vector<const VerilatedScope*> VerilatedScopeVector;
|
||||||
|
|
||||||
class VerilatedHierarchyMap : public std::map<const VerilatedScope*, VerilatedScopeVector> {
|
class VerilatedHierarchyMap final
|
||||||
|
: public std::unordered_map<const VerilatedScope*, VerilatedScopeVector> {
|
||||||
public:
|
public:
|
||||||
VerilatedHierarchyMap() {}
|
VerilatedHierarchyMap() = default;
|
||||||
~VerilatedHierarchyMap() {}
|
~VerilatedHierarchyMap() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // Guard
|
#endif // Guard
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
//
|
//
|
||||||
// Copyright 2012-2020 by Wilson Snyder. This program is free software; you can
|
// Copyright 2012-2021 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// 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.
|
||||||
@@ -21,14 +21,14 @@
|
|||||||
|
|
||||||
std::atomic<vluint64_t> VlMTaskVertex::s_yields;
|
std::atomic<vluint64_t> VlMTaskVertex::s_yields;
|
||||||
|
|
||||||
VL_THREAD_LOCAL VlThreadPool::ProfileTrace* VlThreadPool::t_profilep = NULL;
|
VL_THREAD_LOCAL VlThreadPool::ProfileTrace* VlThreadPool::t_profilep = nullptr;
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
// VlMTaskVertex
|
// VlMTaskVertex
|
||||||
|
|
||||||
VlMTaskVertex::VlMTaskVertex(vluint32_t upstreamDepCount)
|
VlMTaskVertex::VlMTaskVertex(vluint32_t upstreamDepCount)
|
||||||
: m_upstreamDepsDone(0)
|
: m_upstreamDepsDone{0}
|
||||||
, m_upstreamDepCount(upstreamDepCount) {
|
, m_upstreamDepCount{upstreamDepCount} {
|
||||||
assert(atomic_is_lock_free(&m_upstreamDepsDone));
|
assert(atomic_is_lock_free(&m_upstreamDepsDone));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,13 +36,11 @@ VlMTaskVertex::VlMTaskVertex(vluint32_t upstreamDepCount)
|
|||||||
// VlWorkerThread
|
// VlWorkerThread
|
||||||
|
|
||||||
VlWorkerThread::VlWorkerThread(VlThreadPool* poolp, bool profiling)
|
VlWorkerThread::VlWorkerThread(VlThreadPool* poolp, bool profiling)
|
||||||
: m_waiting(false)
|
: m_waiting{false}
|
||||||
, m_ready_size(0)
|
, m_poolp{poolp}
|
||||||
, m_poolp(poolp)
|
, m_profiling{profiling} // Must init this last -- after setting up fields that it might read:
|
||||||
, m_profiling(profiling)
|
, m_exiting{false}
|
||||||
, m_exiting(false)
|
, m_cthread{startWorker, this} {}
|
||||||
// Must init this last -- after setting up fields that it might read:
|
|
||||||
, m_cthread(startWorker, this) {}
|
|
||||||
|
|
||||||
VlWorkerThread::~VlWorkerThread() {
|
VlWorkerThread::~VlWorkerThread() {
|
||||||
m_exiting.store(true, std::memory_order_release);
|
m_exiting.store(true, std::memory_order_release);
|
||||||
@@ -55,7 +53,7 @@ void VlWorkerThread::workerLoop() {
|
|||||||
if (VL_UNLIKELY(m_profiling)) m_poolp->setupProfilingClientThread();
|
if (VL_UNLIKELY(m_profiling)) m_poolp->setupProfilingClientThread();
|
||||||
|
|
||||||
ExecRec work;
|
ExecRec work;
|
||||||
work.m_fnp = NULL;
|
work.m_fnp = nullptr;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
if (VL_LIKELY(!work.m_fnp)) dequeWork(&work);
|
if (VL_LIKELY(!work.m_fnp)) dequeWork(&work);
|
||||||
@@ -65,7 +63,7 @@ void VlWorkerThread::workerLoop() {
|
|||||||
|
|
||||||
if (VL_LIKELY(work.m_fnp)) {
|
if (VL_LIKELY(work.m_fnp)) {
|
||||||
work.m_fnp(work.m_evenCycle, work.m_sym);
|
work.m_fnp(work.m_evenCycle, work.m_sym);
|
||||||
work.m_fnp = NULL;
|
work.m_fnp = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,7 +76,7 @@ void VlWorkerThread::startWorker(VlWorkerThread* workerp) { workerp->workerLoop(
|
|||||||
// VlThreadPool
|
// VlThreadPool
|
||||||
|
|
||||||
VlThreadPool::VlThreadPool(int nThreads, bool profiling)
|
VlThreadPool::VlThreadPool(int nThreads, bool profiling)
|
||||||
: m_profiling(profiling) {
|
: m_profiling{profiling} {
|
||||||
// --threads N passes nThreads=N-1, as the "main" threads counts as 1
|
// --threads N passes nThreads=N-1, as the "main" threads counts as 1
|
||||||
unsigned cpus = std::thread::hardware_concurrency();
|
unsigned cpus = std::thread::hardware_concurrency();
|
||||||
if (cpus < nThreads + 1) {
|
if (cpus < nThreads + 1) {
|
||||||
@@ -100,17 +98,15 @@ VlThreadPool::VlThreadPool(int nThreads, bool profiling)
|
|||||||
}
|
}
|
||||||
|
|
||||||
VlThreadPool::~VlThreadPool() {
|
VlThreadPool::~VlThreadPool() {
|
||||||
for (int i = 0; i < m_workers.size(); ++i) {
|
// Each ~WorkerThread will wait for its thread to exit.
|
||||||
// Each ~WorkerThread will wait for its thread to exit.
|
for (auto& i : m_workers) delete i;
|
||||||
delete m_workers[i];
|
|
||||||
}
|
|
||||||
if (VL_UNLIKELY(m_profiling)) tearDownProfilingClientThread();
|
if (VL_UNLIKELY(m_profiling)) tearDownProfilingClientThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VlThreadPool::tearDownProfilingClientThread() {
|
void VlThreadPool::tearDownProfilingClientThread() {
|
||||||
assert(t_profilep);
|
assert(t_profilep);
|
||||||
delete t_profilep;
|
delete t_profilep;
|
||||||
t_profilep = NULL;
|
t_profilep = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VlThreadPool::setupProfilingClientThread() {
|
void VlThreadPool::setupProfilingClientThread() {
|
||||||
@@ -120,28 +116,28 @@ void VlThreadPool::setupProfilingClientThread() {
|
|||||||
// try not to malloc while collecting profiling.
|
// try not to malloc while collecting profiling.
|
||||||
t_profilep->reserve(4096);
|
t_profilep->reserve(4096);
|
||||||
{
|
{
|
||||||
VerilatedLockGuard lk(m_mutex);
|
const VerilatedLockGuard lk(m_mutex);
|
||||||
m_allProfiles.insert(t_profilep);
|
m_allProfiles.insert(t_profilep);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VlThreadPool::profileAppendAll(const VlProfileRec& rec) {
|
void VlThreadPool::profileAppendAll(const VlProfileRec& rec) {
|
||||||
VerilatedLockGuard lk(m_mutex);
|
const VerilatedLockGuard lk(m_mutex);
|
||||||
for (ProfileSet::iterator it = m_allProfiles.begin(); it != m_allProfiles.end(); ++it) {
|
for (const auto& profilep : m_allProfiles) {
|
||||||
// Every thread's profile trace gets a copy of rec.
|
// Every thread's profile trace gets a copy of rec.
|
||||||
(*it)->emplace_back(rec);
|
profilep->emplace_back(rec);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VlThreadPool::profileDump(const char* filenamep, vluint64_t ticksElapsed) {
|
void VlThreadPool::profileDump(const char* filenamep, vluint64_t ticksElapsed) {
|
||||||
VerilatedLockGuard lk(m_mutex);
|
const VerilatedLockGuard lk(m_mutex);
|
||||||
VL_DEBUG_IF(VL_DBG_MSGF("+prof+threads writing to '%s'\n", filenamep););
|
VL_DEBUG_IF(VL_DBG_MSGF("+prof+threads writing to '%s'\n", filenamep););
|
||||||
|
|
||||||
FILE* fp = fopen(filenamep, "w");
|
FILE* fp = fopen(filenamep, "w");
|
||||||
if (VL_UNLIKELY(!fp)) {
|
if (VL_UNLIKELY(!fp)) {
|
||||||
VL_FATAL_MT(filenamep, 0, "", "+prof+threads+file file not writable");
|
VL_FATAL_MT(filenamep, 0, "", "+prof+threads+file file not writable");
|
||||||
// cppcheck-suppress resourceLeak // bug, doesn't realize fp is nullptr
|
// cppcheck-suppress resourceLeak // bug, doesn't realize fp is nullptr
|
||||||
return;
|
return; // LCOV_EXCL_LINE
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Perhaps merge with verilated_coverage output format, so can
|
// TODO Perhaps merge with verilated_coverage output format, so can
|
||||||
@@ -154,13 +150,12 @@ void VlThreadPool::profileDump(const char* filenamep, vluint64_t ticksElapsed) {
|
|||||||
fprintf(fp, "VLPROF stat yields %" VL_PRI64 "u\n", VlMTaskVertex::yields());
|
fprintf(fp, "VLPROF stat yields %" VL_PRI64 "u\n", VlMTaskVertex::yields());
|
||||||
|
|
||||||
vluint32_t thread_id = 0;
|
vluint32_t thread_id = 0;
|
||||||
for (ProfileSet::const_iterator pit = m_allProfiles.begin(); pit != m_allProfiles.end();
|
for (const auto& pi : m_allProfiles) {
|
||||||
++pit) {
|
|
||||||
++thread_id;
|
++thread_id;
|
||||||
|
|
||||||
bool printing = false; // False while in warmup phase
|
bool printing = false; // False while in warmup phase
|
||||||
for (ProfileTrace::const_iterator eit = (*pit)->begin(); eit != (*pit)->end(); ++eit) {
|
for (const auto& ei : *pi) {
|
||||||
switch (eit->m_type) {
|
switch (ei.m_type) {
|
||||||
case VlProfileRec::TYPE_BARRIER: //
|
case VlProfileRec::TYPE_BARRIER: //
|
||||||
printing = true;
|
printing = true;
|
||||||
break;
|
break;
|
||||||
@@ -170,9 +165,8 @@ void VlThreadPool::profileDump(const char* filenamep, vluint64_t ticksElapsed) {
|
|||||||
"VLPROF mtask %d"
|
"VLPROF mtask %d"
|
||||||
" start %" VL_PRI64 "u end %" VL_PRI64 "u elapsed %" VL_PRI64 "u"
|
" start %" VL_PRI64 "u end %" VL_PRI64 "u elapsed %" VL_PRI64 "u"
|
||||||
" predict_time %u cpu %u on thread %u\n",
|
" predict_time %u cpu %u on thread %u\n",
|
||||||
eit->m_mtaskId, eit->m_startTime, eit->m_endTime,
|
ei.m_mtaskId, ei.m_startTime, ei.m_endTime,
|
||||||
(eit->m_endTime - eit->m_startTime), eit->m_predictTime, eit->m_cpu,
|
(ei.m_endTime - ei.m_startTime), ei.m_predictTime, ei.m_cpu, thread_id);
|
||||||
thread_id);
|
|
||||||
break;
|
break;
|
||||||
default: assert(false); break; // LCOV_EXCL_LINE
|
default: assert(false); break; // LCOV_EXCL_LINE
|
||||||
}
|
}
|
||||||
|
|||||||
+29
-27
@@ -3,7 +3,7 @@
|
|||||||
//
|
//
|
||||||
// THIS MODULE IS PUBLICLY LICENSED
|
// THIS MODULE IS PUBLICLY LICENSED
|
||||||
//
|
//
|
||||||
// Copyright 2012-2020 by Wilson Snyder. This program is free software; you
|
// Copyright 2012-2021 by Wilson Snyder. This program is free software; you
|
||||||
// can redistribute it and/or modify it under the terms of either the GNU
|
// can 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 +22,15 @@
|
|||||||
#include "verilatedos.h"
|
#include "verilatedos.h"
|
||||||
#include "verilated.h" // for VerilatedMutex and clang annotations
|
#include "verilated.h" // for VerilatedMutex and clang annotations
|
||||||
|
|
||||||
|
#ifndef VL_THREADED
|
||||||
|
// Hitting this likely means verilated_threads.cpp is being compiled when
|
||||||
|
// 'verilator --threads' was not used. 'verilator --threads' sets
|
||||||
|
// VL_THREADED.
|
||||||
|
// Alternatively it is always safe but may harm performance to always
|
||||||
|
// define VL_THREADED for all compiles.
|
||||||
|
#error "verilated_threads.h/cpp expected VL_THREADED (from verilator --threads)"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -43,7 +52,7 @@ typedef void* VlThrSymTab;
|
|||||||
typedef void (*VlExecFnp)(bool, VlThrSymTab);
|
typedef void (*VlExecFnp)(bool, VlThrSymTab);
|
||||||
|
|
||||||
/// Track dependencies for a single MTask.
|
/// Track dependencies for a single MTask.
|
||||||
class VlMTaskVertex {
|
class VlMTaskVertex final {
|
||||||
// MEMBERS
|
// MEMBERS
|
||||||
static std::atomic<vluint64_t> s_yields; // Statistics
|
static std::atomic<vluint64_t> s_yields; // Statistics
|
||||||
|
|
||||||
@@ -73,7 +82,7 @@ public:
|
|||||||
// that must notify this MTaskVertex before it will become ready
|
// that must notify this MTaskVertex before it will become ready
|
||||||
// to run.
|
// to run.
|
||||||
explicit VlMTaskVertex(vluint32_t upstreamDepCount);
|
explicit VlMTaskVertex(vluint32_t upstreamDepCount);
|
||||||
~VlMTaskVertex() {}
|
~VlMTaskVertex() = default;
|
||||||
|
|
||||||
static vluint64_t yields() { return s_yields; }
|
static vluint64_t yields() { return s_yields; }
|
||||||
static void yieldThread() {
|
static void yieldThread() {
|
||||||
@@ -115,27 +124,20 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Profiling support
|
// Profiling support
|
||||||
class VlProfileRec {
|
class VlProfileRec final {
|
||||||
protected:
|
protected:
|
||||||
friend class VlThreadPool;
|
friend class VlThreadPool;
|
||||||
enum VlProfileE { TYPE_MTASK_RUN, TYPE_BARRIER };
|
enum VlProfileE { TYPE_MTASK_RUN, TYPE_BARRIER };
|
||||||
VlProfileE m_type; // Record type
|
VlProfileE m_type = TYPE_BARRIER; // Record type
|
||||||
vluint32_t m_mtaskId; // Mtask we're logging
|
vluint32_t m_mtaskId = 0; // Mtask we're logging
|
||||||
vluint32_t m_predictTime; // How long scheduler predicted would take
|
vluint32_t m_predictTime = 0; // How long scheduler predicted would take
|
||||||
vluint64_t m_startTime; // Tick at start of execution
|
vluint64_t m_startTime = 0; // Tick at start of execution
|
||||||
vluint64_t m_endTime; // Tick at end of execution
|
vluint64_t m_endTime = 0; // Tick at end of execution
|
||||||
unsigned m_cpu; // Execution CPU number (at start anyways)
|
unsigned m_cpu; // Execution CPU number (at start anyways)
|
||||||
public:
|
public:
|
||||||
class Barrier {};
|
class Barrier {};
|
||||||
VlProfileRec() {}
|
VlProfileRec() = default;
|
||||||
explicit VlProfileRec(Barrier) {
|
explicit VlProfileRec(Barrier) { m_cpu = getcpu(); }
|
||||||
m_type = TYPE_BARRIER;
|
|
||||||
m_mtaskId = 0;
|
|
||||||
m_predictTime = 0;
|
|
||||||
m_startTime = 0;
|
|
||||||
m_endTime = 0;
|
|
||||||
m_cpu = getcpu();
|
|
||||||
}
|
|
||||||
void startRecord(vluint64_t time, uint32_t mtask, uint32_t predict) {
|
void startRecord(vluint64_t time, uint32_t mtask, uint32_t predict) {
|
||||||
m_type = VlProfileRec::TYPE_MTASK_RUN;
|
m_type = VlProfileRec::TYPE_MTASK_RUN;
|
||||||
m_mtaskId = mtask;
|
m_mtaskId = mtask;
|
||||||
@@ -166,7 +168,7 @@ public:
|
|||||||
|
|
||||||
class VlThreadPool;
|
class VlThreadPool;
|
||||||
|
|
||||||
class VlWorkerThread {
|
class VlWorkerThread final {
|
||||||
private:
|
private:
|
||||||
// TYPES
|
// TYPES
|
||||||
struct ExecRec {
|
struct ExecRec {
|
||||||
@@ -174,13 +176,13 @@ private:
|
|||||||
VlThrSymTab m_sym; // Symbol table to execute
|
VlThrSymTab m_sym; // Symbol table to execute
|
||||||
bool m_evenCycle; // Even/odd for flag alternation
|
bool m_evenCycle; // Even/odd for flag alternation
|
||||||
ExecRec()
|
ExecRec()
|
||||||
: m_fnp(NULL)
|
: m_fnp{nullptr}
|
||||||
, m_sym(NULL)
|
, m_sym{nullptr}
|
||||||
, m_evenCycle(false) {}
|
, m_evenCycle{false} {}
|
||||||
ExecRec(VlExecFnp fnp, bool evenCycle, VlThrSymTab sym)
|
ExecRec(VlExecFnp fnp, bool evenCycle, VlThrSymTab sym)
|
||||||
: m_fnp(fnp)
|
: m_fnp{fnp}
|
||||||
, m_sym(sym)
|
, m_sym{sym}
|
||||||
, m_evenCycle(evenCycle) {}
|
, m_evenCycle{evenCycle} {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// MEMBERS
|
// MEMBERS
|
||||||
@@ -234,7 +236,7 @@ public:
|
|||||||
inline void addTask(VlExecFnp fnp, bool evenCycle, VlThrSymTab sym) {
|
inline void addTask(VlExecFnp fnp, bool evenCycle, VlThrSymTab sym) {
|
||||||
bool notify;
|
bool notify;
|
||||||
{
|
{
|
||||||
VerilatedLockGuard lk(m_mutex);
|
const VerilatedLockGuard lk(m_mutex);
|
||||||
m_ready.emplace_back(fnp, evenCycle, sym);
|
m_ready.emplace_back(fnp, evenCycle, sym);
|
||||||
m_ready_size.fetch_add(1, std::memory_order_relaxed);
|
m_ready_size.fetch_add(1, std::memory_order_relaxed);
|
||||||
notify = m_waiting;
|
notify = m_waiting;
|
||||||
@@ -245,7 +247,7 @@ public:
|
|||||||
static void startWorker(VlWorkerThread* workerp);
|
static void startWorker(VlWorkerThread* workerp);
|
||||||
};
|
};
|
||||||
|
|
||||||
class VlThreadPool {
|
class VlThreadPool final {
|
||||||
// TYPES
|
// TYPES
|
||||||
typedef std::vector<VlProfileRec> ProfileTrace;
|
typedef std::vector<VlProfileRec> ProfileTrace;
|
||||||
typedef std::set<ProfileTrace*> ProfileSet;
|
typedef std::set<ProfileTrace*> ProfileSet;
|
||||||
|
|||||||
+46
-32
@@ -3,7 +3,7 @@
|
|||||||
//
|
//
|
||||||
// THIS MODULE IS PUBLICLY LICENSED
|
// THIS MODULE IS PUBLICLY LICENSED
|
||||||
//
|
//
|
||||||
// Copyright 2001-2020 by Wilson Snyder. This program is free software; you
|
// Copyright 2001-2021 by Wilson Snyder. This program is free software; you
|
||||||
// can redistribute it and/or modify it under the terms of either the GNU
|
// can 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.
|
||||||
@@ -40,7 +40,7 @@
|
|||||||
// Threaded tracing
|
// Threaded tracing
|
||||||
|
|
||||||
// A simple synchronized first in first out queue
|
// A simple synchronized first in first out queue
|
||||||
template <class T> class VerilatedThreadQueue {
|
template <class T> class VerilatedThreadQueue final { // LCOV_EXCL_LINE // lcov bug
|
||||||
private:
|
private:
|
||||||
VerilatedMutex m_mutex; // Protects m_queue
|
VerilatedMutex m_mutex; // Protects m_queue
|
||||||
std::condition_variable_any m_cv;
|
std::condition_variable_any m_cv;
|
||||||
@@ -73,7 +73,7 @@ public:
|
|||||||
|
|
||||||
// Non blocking get
|
// Non blocking get
|
||||||
bool tryGet(T& result) {
|
bool tryGet(T& result) {
|
||||||
VerilatedLockGuard lockGuard(m_mutex);
|
const VerilatedLockGuard lockGuard(m_mutex);
|
||||||
if (m_queue.empty()) { return false; }
|
if (m_queue.empty()) { return false; }
|
||||||
result = m_queue.front();
|
result = m_queue.front();
|
||||||
m_queue.pop_front();
|
m_queue.pop_front();
|
||||||
@@ -83,11 +83,11 @@ public:
|
|||||||
|
|
||||||
// Commands used by thread tracing. Anonymous enum in class, as we want
|
// Commands used by thread tracing. Anonymous enum in class, as we want
|
||||||
// it scoped, but we also want the automatic conversion to integer types.
|
// it scoped, but we also want the automatic conversion to integer types.
|
||||||
class VerilatedTraceCommand {
|
class VerilatedTraceCommand final {
|
||||||
public:
|
public:
|
||||||
// These must all fit in 4 bit at the moment, as the tracing routines
|
// These must all fit in 4 bit at the moment, as the tracing routines
|
||||||
// pack parameters in the top bits.
|
// pack parameters in the top bits.
|
||||||
enum {
|
enum : vluint8_t {
|
||||||
CHG_BIT_0 = 0x0,
|
CHG_BIT_0 = 0x0,
|
||||||
CHG_BIT_1 = 0x1,
|
CHG_BIT_1 = 0x1,
|
||||||
CHG_CDATA = 0x2,
|
CHG_CDATA = 0x2,
|
||||||
@@ -95,7 +95,6 @@ public:
|
|||||||
CHG_IDATA = 0x4,
|
CHG_IDATA = 0x4,
|
||||||
CHG_QDATA = 0x5,
|
CHG_QDATA = 0x5,
|
||||||
CHG_WDATA = 0x6,
|
CHG_WDATA = 0x6,
|
||||||
CHG_FLOAT = 0x7,
|
|
||||||
CHG_DOUBLE = 0x8,
|
CHG_DOUBLE = 0x8,
|
||||||
// TODO: full..
|
// TODO: full..
|
||||||
TIME_CHANGE = 0xd,
|
TIME_CHANGE = 0xd,
|
||||||
@@ -105,22 +104,45 @@ public:
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
class VerilatedTraceCallInfo;
|
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
// VerilatedTrace
|
// VerilatedTrace
|
||||||
|
|
||||||
// VerilatedTrace uses F-bounded polymorphism to access duck-typed
|
// VerilatedTrace uses F-bounded polymorphism to access duck-typed
|
||||||
// implementations in the format specific derived class, which must be passed
|
// implementations in the format specific derived class, which must be passed
|
||||||
// as the type parameter T_Derived
|
// as the type parameter T_Derived
|
||||||
template <class T_Derived> class VerilatedTrace {
|
template <class T_Derived> class VerilatedTrace VL_NOT_FINAL {
|
||||||
private:
|
public:
|
||||||
//=========================================================================
|
//=========================================================================
|
||||||
// Generic tracing internals
|
// Generic tracing internals
|
||||||
|
|
||||||
|
typedef void (*initCb_t)(void*, T_Derived*, uint32_t); // Type of init callbacks
|
||||||
|
typedef void (*dumpCb_t)(void*, T_Derived*); // Type of all but init callbacks
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct CallbackRecord {
|
||||||
|
// Note: would make these fields const, but some old STL implementations
|
||||||
|
// (the one in Ubuntu 14.04 with GCC 4.8.4 in particular) use the
|
||||||
|
// assignment operator on inserting into collections, so they don't work
|
||||||
|
// with const fields...
|
||||||
|
union {
|
||||||
|
initCb_t m_initCb; // The callback function
|
||||||
|
dumpCb_t m_dumpCb; // The callback function
|
||||||
|
};
|
||||||
|
void* m_userp; // The user pointer to pass to the callback (the symbol table)
|
||||||
|
CallbackRecord(initCb_t cb, void* userp)
|
||||||
|
: m_initCb{cb}
|
||||||
|
, m_userp{userp} {}
|
||||||
|
CallbackRecord(dumpCb_t cb, void* userp)
|
||||||
|
: m_dumpCb{cb}
|
||||||
|
, m_userp{userp} {}
|
||||||
|
};
|
||||||
|
|
||||||
vluint32_t* m_sigs_oldvalp; ///< Old value store
|
vluint32_t* m_sigs_oldvalp; ///< Old value store
|
||||||
vluint64_t m_timeLastDump; ///< Last time we did a dump
|
vluint64_t m_timeLastDump; ///< Last time we did a dump
|
||||||
std::vector<VerilatedTraceCallInfo*> m_callbacks; ///< Routines to perform dumping
|
std::vector<CallbackRecord> m_initCbs; ///< Routines to initialize traciong
|
||||||
|
std::vector<CallbackRecord> m_fullCbs; ///< Routines to perform full dump
|
||||||
|
std::vector<CallbackRecord> m_chgCbs; ///< Routines to perform incremental dump
|
||||||
|
std::vector<CallbackRecord> m_cleanupCbs; ///< Routines to call at the end of dump
|
||||||
bool m_fullDump; ///< Whether a full dump is required on the next call to 'dump'
|
bool m_fullDump; ///< Whether a full dump is required on the next call to 'dump'
|
||||||
vluint32_t m_nextCode; ///< Next code number to assign
|
vluint32_t m_nextCode; ///< Next code number to assign
|
||||||
vluint32_t m_numSignals; ///< Number of distinct signals
|
vluint32_t m_numSignals; ///< Number of distinct signals
|
||||||
@@ -130,10 +152,17 @@ private:
|
|||||||
double m_timeRes; ///< Time resolution (ns/ms etc)
|
double m_timeRes; ///< Time resolution (ns/ms etc)
|
||||||
double m_timeUnit; ///< Time units (ns/ms etc)
|
double m_timeUnit; ///< Time units (ns/ms etc)
|
||||||
|
|
||||||
|
void addCallbackRecord(std::vector<CallbackRecord>& cbVec, CallbackRecord& cbRec);
|
||||||
|
|
||||||
// Equivalent to 'this' but is of the sub-type 'T_Derived*'. Use 'self()->'
|
// Equivalent to 'this' but is of the sub-type 'T_Derived*'. Use 'self()->'
|
||||||
// to access duck-typed functions to avoid a virtual function call.
|
// to access duck-typed functions to avoid a virtual function call.
|
||||||
T_Derived* self() { return static_cast<T_Derived*>(this); }
|
T_Derived* self() { return static_cast<T_Derived*>(this); }
|
||||||
|
|
||||||
|
// Flush any remaining data for this file
|
||||||
|
static void onFlush(void* selfp) VL_MT_UNSAFE_ONE;
|
||||||
|
// Close the file on termination
|
||||||
|
static void onExit(void* selfp) VL_MT_UNSAFE_ONE;
|
||||||
|
|
||||||
#ifdef VL_TRACE_THREADED
|
#ifdef VL_TRACE_THREADED
|
||||||
// Number of total trace buffers that have been allocated
|
// Number of total trace buffers that have been allocated
|
||||||
vluint32_t m_numTraceBuffers;
|
vluint32_t m_numTraceBuffers;
|
||||||
@@ -187,7 +216,6 @@ protected:
|
|||||||
double timeRes() const { return m_timeRes; }
|
double timeRes() const { return m_timeRes; }
|
||||||
double timeUnit() const { return m_timeUnit; }
|
double timeUnit() const { return m_timeUnit; }
|
||||||
std::string timeResStr() const;
|
std::string timeResStr() const;
|
||||||
std::string timeUnitStr() const;
|
|
||||||
|
|
||||||
void traceInit() VL_MT_UNSAFE;
|
void traceInit() VL_MT_UNSAFE;
|
||||||
|
|
||||||
@@ -209,8 +237,8 @@ protected:
|
|||||||
|
|
||||||
// These hooks are called before a full or change based dump is produced.
|
// These hooks are called before a full or change based dump is produced.
|
||||||
// The return value indicates whether to proceed with the dump.
|
// The return value indicates whether to proceed with the dump.
|
||||||
virtual bool preFullDump() { return true; }
|
virtual bool preFullDump() = 0;
|
||||||
virtual bool preChangeDump() { return true; }
|
virtual bool preChangeDump() = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
//=========================================================================
|
//=========================================================================
|
||||||
@@ -232,13 +260,13 @@ public:
|
|||||||
//=========================================================================
|
//=========================================================================
|
||||||
// Non-hot path internal interface to Verilator generated code
|
// Non-hot path internal interface to Verilator generated code
|
||||||
|
|
||||||
typedef void (*callback_t)(T_Derived* tracep, void* userthis, vluint32_t code);
|
void addInitCb(initCb_t cb, void* userp) VL_MT_UNSAFE_ONE;
|
||||||
|
void addFullCb(dumpCb_t cb, void* userp) VL_MT_UNSAFE_ONE;
|
||||||
|
void addChgCb(dumpCb_t cb, void* userp) VL_MT_UNSAFE_ONE;
|
||||||
|
void addCleanupCb(dumpCb_t cb, void* userp) VL_MT_UNSAFE_ONE;
|
||||||
|
|
||||||
void changeThread() { m_assertOne.changeThread(); }
|
void changeThread() { m_assertOne.changeThread(); }
|
||||||
|
|
||||||
void addCallback(callback_t initcb, callback_t fullcb, callback_t changecb,
|
|
||||||
void* userthis) VL_MT_UNSAFE_ONE;
|
|
||||||
|
|
||||||
void module(const std::string& name) VL_MT_UNSAFE_ONE {
|
void module(const std::string& name) VL_MT_UNSAFE_ONE {
|
||||||
m_assertOne.check();
|
m_assertOne.check();
|
||||||
m_moduleName = name;
|
m_moduleName = name;
|
||||||
@@ -261,7 +289,6 @@ public:
|
|||||||
// duck-typed void emitIData(vluint32_t code, IData newval, int bits) = 0;
|
// duck-typed void emitIData(vluint32_t code, IData newval, int bits) = 0;
|
||||||
// duck-typed void emitQData(vluint32_t code, QData newval, int bits) = 0;
|
// duck-typed void emitQData(vluint32_t code, QData newval, int bits) = 0;
|
||||||
// duck-typed void emitWData(vluint32_t code, const WData* newvalp, int bits) = 0;
|
// duck-typed void emitWData(vluint32_t code, const WData* newvalp, int bits) = 0;
|
||||||
// duck-typed void emitFloat(vluint32_t code, float newval) = 0;
|
|
||||||
// duck-typed void emitDouble(vluint32_t code, double newval) = 0;
|
// duck-typed void emitDouble(vluint32_t code, double newval) = 0;
|
||||||
|
|
||||||
vluint32_t* oldp(vluint32_t code) { return m_sigs_oldvalp + code; }
|
vluint32_t* oldp(vluint32_t code) { return m_sigs_oldvalp + code; }
|
||||||
@@ -273,7 +300,6 @@ public:
|
|||||||
void fullIData(vluint32_t* oldp, IData newval, int bits);
|
void fullIData(vluint32_t* oldp, IData newval, int bits);
|
||||||
void fullQData(vluint32_t* oldp, QData newval, int bits);
|
void fullQData(vluint32_t* oldp, QData newval, int bits);
|
||||||
void fullWData(vluint32_t* oldp, const WData* newvalp, int bits);
|
void fullWData(vluint32_t* oldp, const WData* newvalp, int bits);
|
||||||
void fullFloat(vluint32_t* oldp, float newval);
|
|
||||||
void fullDouble(vluint32_t* oldp, double newval);
|
void fullDouble(vluint32_t* oldp, double newval);
|
||||||
|
|
||||||
#ifdef VL_TRACE_THREADED
|
#ifdef VL_TRACE_THREADED
|
||||||
@@ -319,14 +345,6 @@ public:
|
|||||||
for (int i = 0; i < (bits + 31) / 32; ++i) { *m_traceBufferWritep++ = newvalp[i]; }
|
for (int i = 0; i < (bits + 31) / 32; ++i) { *m_traceBufferWritep++ = newvalp[i]; }
|
||||||
VL_DEBUG_IF(assert(m_traceBufferWritep <= m_traceBufferEndp););
|
VL_DEBUG_IF(assert(m_traceBufferWritep <= m_traceBufferEndp););
|
||||||
}
|
}
|
||||||
inline void chgFloat(vluint32_t code, float newval) {
|
|
||||||
m_traceBufferWritep[0] = VerilatedTraceCommand::CHG_FLOAT;
|
|
||||||
m_traceBufferWritep[1] = code;
|
|
||||||
// cppcheck-suppress invalidPointerCast
|
|
||||||
*reinterpret_cast<float*>(m_traceBufferWritep + 2) = newval;
|
|
||||||
m_traceBufferWritep += 3;
|
|
||||||
VL_DEBUG_IF(assert(m_traceBufferWritep <= m_traceBufferEndp););
|
|
||||||
}
|
|
||||||
inline void chgDouble(vluint32_t code, double newval) {
|
inline void chgDouble(vluint32_t code, double newval) {
|
||||||
m_traceBufferWritep[0] = VerilatedTraceCommand::CHG_DOUBLE;
|
m_traceBufferWritep[0] = VerilatedTraceCommand::CHG_DOUBLE;
|
||||||
m_traceBufferWritep[1] = code;
|
m_traceBufferWritep[1] = code;
|
||||||
@@ -374,10 +392,6 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
inline void CHG(Float)(vluint32_t* oldp, float newval) {
|
|
||||||
// cppcheck-suppress invalidPointerCast
|
|
||||||
if (VL_UNLIKELY(*reinterpret_cast<float*>(oldp) != newval)) fullFloat(oldp, newval);
|
|
||||||
}
|
|
||||||
inline void CHG(Double)(vluint32_t* oldp, double newval) {
|
inline void CHG(Double)(vluint32_t* oldp, double newval) {
|
||||||
// cppcheck-suppress invalidPointerCast
|
// cppcheck-suppress invalidPointerCast
|
||||||
if (VL_UNLIKELY(*reinterpret_cast<double*>(oldp) != newval)) fullDouble(oldp, newval);
|
if (VL_UNLIKELY(*reinterpret_cast<double*>(oldp) != newval)) fullDouble(oldp, newval);
|
||||||
|
|||||||
+123
-86
@@ -3,7 +3,7 @@
|
|||||||
//
|
//
|
||||||
// THIS MODULE IS PUBLICLY LICENSED
|
// THIS MODULE IS PUBLICLY LICENSED
|
||||||
//
|
//
|
||||||
// Copyright 2001-2020 by Wilson Snyder. This program is free software; you
|
// Copyright 2001-2021 by Wilson Snyder. This program is free software; you
|
||||||
// can redistribute it and/or modify it under the terms of either the GNU
|
// can 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.
|
||||||
@@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
|
|
||||||
|
#ifndef VL_CPPCHECK
|
||||||
#ifndef VL_DERIVED_T
|
#ifndef VL_DERIVED_T
|
||||||
# error "This file should be included in trace format implementations"
|
# error "This file should be included in trace format implementations"
|
||||||
#endif
|
#endif
|
||||||
@@ -39,14 +40,14 @@
|
|||||||
// Static utility functions
|
// Static utility functions
|
||||||
|
|
||||||
static double timescaleToDouble(const char* unitp) {
|
static double timescaleToDouble(const char* unitp) {
|
||||||
char* endp;
|
char* endp = nullptr;
|
||||||
double value = strtod(unitp, &endp);
|
double value = strtod(unitp, &endp);
|
||||||
// On error so we allow just "ns" to return 1e-9.
|
// On error so we allow just "ns" to return 1e-9.
|
||||||
if (value == 0.0 && endp == unitp) value = 1;
|
if (value == 0.0 && endp == unitp) value = 1;
|
||||||
unitp = endp;
|
unitp = endp;
|
||||||
for (; *unitp && isspace(*unitp); unitp++) {}
|
for (; *unitp && isspace(*unitp); unitp++) {}
|
||||||
switch (*unitp) {
|
switch (*unitp) {
|
||||||
case 's': value *= 1e1; break;
|
case 's': value *= 1e0; break;
|
||||||
case 'm': value *= 1e-3; break;
|
case 'm': value *= 1e-3; break;
|
||||||
case 'u': value *= 1e-6; break;
|
case 'u': value *= 1e-6; break;
|
||||||
case 'n': value *= 1e-9; break;
|
case 'n': value *= 1e-9; break;
|
||||||
@@ -69,35 +70,10 @@ static std::string doubleToTimescale(double value) {
|
|||||||
else if (value >= 1e-18) { suffixp = "as"; value *= 1e18; }
|
else if (value >= 1e-18) { suffixp = "as"; value *= 1e18; }
|
||||||
// clang-format on
|
// clang-format on
|
||||||
char valuestr[100];
|
char valuestr[100];
|
||||||
sprintf(valuestr, "%3.0f%s", value, suffixp);
|
sprintf(valuestr, "%0.0f%s", value, suffixp);
|
||||||
return valuestr; // Gets converted to string, so no ref to stack
|
return valuestr; // Gets converted to string, so no ref to stack
|
||||||
}
|
}
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
// Internal callback routines for each module being traced.
|
|
||||||
|
|
||||||
// Each module that wishes to be traced registers a set of callbacks stored in
|
|
||||||
// this class. When the trace file is being constructed, this class provides
|
|
||||||
// the callback routines to be executed.
|
|
||||||
class VerilatedTraceCallInfo {
|
|
||||||
public: // This is in .cpp file so is not widely visible
|
|
||||||
typedef VerilatedTrace<VL_DERIVED_T>::callback_t callback_t;
|
|
||||||
|
|
||||||
callback_t m_initcb; ///< Initialization Callback function
|
|
||||||
callback_t m_fullcb; ///< Full Dumping Callback function
|
|
||||||
callback_t m_changecb; ///< Incremental Dumping Callback function
|
|
||||||
void* m_userthis; ///< User data pointer for callback
|
|
||||||
vluint32_t m_code; ///< Starting code number (set later by traceInit)
|
|
||||||
// CONSTRUCTORS
|
|
||||||
VerilatedTraceCallInfo(callback_t icb, callback_t fcb, callback_t changecb, void* ut)
|
|
||||||
: m_initcb(icb)
|
|
||||||
, m_fullcb(fcb)
|
|
||||||
, m_changecb(changecb)
|
|
||||||
, m_userthis(ut)
|
|
||||||
, m_code(1) {}
|
|
||||||
~VerilatedTraceCallInfo() {}
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef VL_TRACE_THREADED
|
#ifdef VL_TRACE_THREADED
|
||||||
//=========================================================================
|
//=========================================================================
|
||||||
// Buffer management
|
// Buffer management
|
||||||
@@ -196,11 +172,6 @@ template <> void VerilatedTrace<VL_DERIVED_T>::workerThreadMain() {
|
|||||||
chgWDataImpl(oldp, readp, top);
|
chgWDataImpl(oldp, readp, top);
|
||||||
readp += VL_WORDS_I(top);
|
readp += VL_WORDS_I(top);
|
||||||
continue;
|
continue;
|
||||||
case VerilatedTraceCommand::CHG_FLOAT:
|
|
||||||
VL_TRACE_THREAD_DEBUG("Command CHG_FLOAT " << top);
|
|
||||||
chgFloatImpl(oldp, *reinterpret_cast<const float*>(readp));
|
|
||||||
readp += 1;
|
|
||||||
continue;
|
|
||||||
case VerilatedTraceCommand::CHG_DOUBLE:
|
case VerilatedTraceCommand::CHG_DOUBLE:
|
||||||
VL_TRACE_THREAD_DEBUG("Command CHG_DOUBLE " << top);
|
VL_TRACE_THREAD_DEBUG("Command CHG_DOUBLE " << top);
|
||||||
chgDoubleImpl(oldp, *reinterpret_cast<const double*>(readp));
|
chgDoubleImpl(oldp, *reinterpret_cast<const double*>(readp));
|
||||||
@@ -224,13 +195,14 @@ template <> void VerilatedTrace<VL_DERIVED_T>::workerThreadMain() {
|
|||||||
shutdown = true;
|
shutdown = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
//===
|
//===
|
||||||
// Unknown command
|
// Unknown command
|
||||||
default:
|
default: { // LCOV_EXCL_START
|
||||||
VL_TRACE_THREAD_DEBUG("Command UNKNOWN");
|
VL_TRACE_THREAD_DEBUG("Command UNKNOWN");
|
||||||
VL_PRINTF_MT("Trace command: 0x%08x\n", cmd);
|
VL_PRINTF_MT("Trace command: 0x%08x\n", cmd);
|
||||||
VL_FATAL_MT(__FILE__, __LINE__, "", "Unknown trace command");
|
VL_FATAL_MT(__FILE__, __LINE__, "", "Unknown trace command");
|
||||||
break;
|
break;
|
||||||
|
} // LCOV_EXCL_STOP
|
||||||
}
|
}
|
||||||
|
|
||||||
// The above switch will execute 'continue' when necessary,
|
// The above switch will execute 'continue' when necessary,
|
||||||
@@ -287,22 +259,37 @@ template <> void VerilatedTrace<VL_DERIVED_T>::flush() {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
// Callbacks to run on global events
|
||||||
|
|
||||||
|
template <> void VerilatedTrace<VL_DERIVED_T>::onFlush(void* selfp) {
|
||||||
|
// Note this calls 'flush' on the derived class
|
||||||
|
reinterpret_cast<VL_DERIVED_T*>(selfp)->flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <> void VerilatedTrace<VL_DERIVED_T>::onExit(void* selfp) {
|
||||||
|
// Note this calls 'close' on the derived class
|
||||||
|
reinterpret_cast<VL_DERIVED_T*>(selfp)->close();
|
||||||
|
}
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
// VerilatedTrace
|
// VerilatedTrace
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
VerilatedTrace<VL_DERIVED_T>::VerilatedTrace()
|
VerilatedTrace<VL_DERIVED_T>::VerilatedTrace()
|
||||||
: m_sigs_oldvalp(NULL)
|
: m_sigs_oldvalp{nullptr}
|
||||||
, m_timeLastDump(0)
|
, m_timeLastDump{0}
|
||||||
, m_fullDump(true)
|
, m_fullDump{true}
|
||||||
, m_nextCode(0)
|
, m_nextCode{0}
|
||||||
, m_numSignals(0)
|
, m_numSignals{0}
|
||||||
, m_maxBits(0)
|
, m_maxBits{0}
|
||||||
, m_scopeEscape('.')
|
, m_scopeEscape{'.'}
|
||||||
, m_timeRes(1e-9)
|
, m_timeRes{1e-9}
|
||||||
, m_timeUnit(1e-9)
|
, m_timeUnit {
|
||||||
|
1e-9
|
||||||
|
}
|
||||||
#ifdef VL_TRACE_THREADED
|
#ifdef VL_TRACE_THREADED
|
||||||
, m_numTraceBuffers(0)
|
, m_numTraceBuffers { 0 }
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
set_time_unit(Verilated::timeunitString());
|
set_time_unit(Verilated::timeunitString());
|
||||||
@@ -310,11 +297,9 @@ VerilatedTrace<VL_DERIVED_T>::VerilatedTrace()
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <> VerilatedTrace<VL_DERIVED_T>::~VerilatedTrace() {
|
template <> VerilatedTrace<VL_DERIVED_T>::~VerilatedTrace() {
|
||||||
if (m_sigs_oldvalp) VL_DO_CLEAR(delete[] m_sigs_oldvalp, m_sigs_oldvalp = NULL);
|
if (m_sigs_oldvalp) VL_DO_CLEAR(delete[] m_sigs_oldvalp, m_sigs_oldvalp = nullptr);
|
||||||
while (!m_callbacks.empty()) {
|
Verilated::removeFlushCb(VerilatedTrace<VL_DERIVED_T>::onFlush, this);
|
||||||
delete m_callbacks.back();
|
Verilated::removeExitCb(VerilatedTrace<VL_DERIVED_T>::onExit, this);
|
||||||
m_callbacks.pop_back();
|
|
||||||
}
|
|
||||||
#ifdef VL_TRACE_THREADED
|
#ifdef VL_TRACE_THREADED
|
||||||
close();
|
close();
|
||||||
#endif
|
#endif
|
||||||
@@ -334,11 +319,12 @@ template <> void VerilatedTrace<VL_DERIVED_T>::traceInit() VL_MT_UNSAFE {
|
|||||||
m_numSignals = 0;
|
m_numSignals = 0;
|
||||||
m_maxBits = 0;
|
m_maxBits = 0;
|
||||||
|
|
||||||
// Call all initialize callbacks, which will call decl* for each signal.
|
// Call all initialize callbacks, which will:
|
||||||
for (vluint32_t ent = 0; ent < m_callbacks.size(); ++ent) {
|
// - Call decl* for each signal
|
||||||
VerilatedTraceCallInfo* cip = m_callbacks[ent];
|
// - Store the base code
|
||||||
cip->m_code = nextCode();
|
for (vluint32_t i = 0; i < m_initCbs.size(); ++i) {
|
||||||
(cip->m_initcb)(self(), cip->m_userthis, cip->m_code);
|
const CallbackRecord& cbr = m_initCbs[i];
|
||||||
|
cbr.m_initCb(cbr.m_userp, self(), nextCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (expectedCodes && nextCode() != expectedCodes) {
|
if (expectedCodes && nextCode() != expectedCodes) {
|
||||||
@@ -350,6 +336,10 @@ template <> void VerilatedTrace<VL_DERIVED_T>::traceInit() VL_MT_UNSAFE {
|
|||||||
// holding previous signal values.
|
// holding previous signal values.
|
||||||
if (!m_sigs_oldvalp) m_sigs_oldvalp = new vluint32_t[nextCode()];
|
if (!m_sigs_oldvalp) m_sigs_oldvalp = new vluint32_t[nextCode()];
|
||||||
|
|
||||||
|
// Set callback so flush/abort will flush this file
|
||||||
|
Verilated::addFlushCb(VerilatedTrace<VL_DERIVED_T>::onFlush, this);
|
||||||
|
Verilated::addExitCb(VerilatedTrace<VL_DERIVED_T>::onExit, this);
|
||||||
|
|
||||||
#ifdef VL_TRACE_THREADED
|
#ifdef VL_TRACE_THREADED
|
||||||
// Compute trace buffer size. we need to be able to store a new value for
|
// Compute trace buffer size. we need to be able to store a new value for
|
||||||
// each signal, which is 'nextCode()' entries after the init callbacks
|
// each signal, which is 'nextCode()' entries after the init callbacks
|
||||||
@@ -384,10 +374,6 @@ template <> std::string VerilatedTrace<VL_DERIVED_T>::timeResStr() const {
|
|||||||
return doubleToTimescale(m_timeRes);
|
return doubleToTimescale(m_timeRes);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <> std::string VerilatedTrace<VL_DERIVED_T>::timeUnitStr() const {
|
|
||||||
return doubleToTimescale(m_timeUnit);
|
|
||||||
}
|
|
||||||
|
|
||||||
//=========================================================================
|
//=========================================================================
|
||||||
// External interface to client code
|
// External interface to client code
|
||||||
|
|
||||||
@@ -409,12 +395,12 @@ template <> void VerilatedTrace<VL_DERIVED_T>::set_time_resolution(const std::st
|
|||||||
|
|
||||||
template <> void VerilatedTrace<VL_DERIVED_T>::dump(vluint64_t timeui) {
|
template <> void VerilatedTrace<VL_DERIVED_T>::dump(vluint64_t timeui) {
|
||||||
m_assertOne.check();
|
m_assertOne.check();
|
||||||
if (VL_UNLIKELY(m_timeLastDump && timeui <= m_timeLastDump)) {
|
if (VL_UNCOVERABLE(m_timeLastDump && timeui <= m_timeLastDump)) { // LCOV_EXCL_START
|
||||||
VL_PRINTF_MT("%%Warning: previous dump at t=%" VL_PRI64 "u, requesting t=%" VL_PRI64
|
VL_PRINTF_MT("%%Warning: previous dump at t=%" VL_PRI64 "u, requesting t=%" VL_PRI64
|
||||||
"u, dump call ignored\n",
|
"u, dump call ignored\n",
|
||||||
m_timeLastDump, timeui);
|
m_timeLastDump, timeui);
|
||||||
return;
|
return;
|
||||||
}
|
} // LCOV_EXCL_STOP
|
||||||
m_timeLastDump = timeui;
|
m_timeLastDump = timeui;
|
||||||
|
|
||||||
Verilated::quiesce();
|
Verilated::quiesce();
|
||||||
@@ -452,17 +438,22 @@ template <> void VerilatedTrace<VL_DERIVED_T>::dump(vluint64_t timeui) {
|
|||||||
// Run the callbacks
|
// Run the callbacks
|
||||||
if (VL_UNLIKELY(m_fullDump)) {
|
if (VL_UNLIKELY(m_fullDump)) {
|
||||||
m_fullDump = false; // No more need for next dump to be full
|
m_fullDump = false; // No more need for next dump to be full
|
||||||
for (vluint32_t ent = 0; ent < m_callbacks.size(); ++ent) {
|
for (vluint32_t i = 0; i < m_fullCbs.size(); ++i) {
|
||||||
VerilatedTraceCallInfo* cip = m_callbacks[ent];
|
const CallbackRecord& cbr = m_fullCbs[i];
|
||||||
(cip->m_fullcb)(self(), cip->m_userthis, cip->m_code);
|
cbr.m_dumpCb(cbr.m_userp, self());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (vluint32_t ent = 0; ent < m_callbacks.size(); ++ent) {
|
for (vluint32_t i = 0; i < m_chgCbs.size(); ++i) {
|
||||||
VerilatedTraceCallInfo* cip = m_callbacks[ent];
|
const CallbackRecord& cbr = m_chgCbs[i];
|
||||||
(cip->m_changecb)(self(), cip->m_userthis, cip->m_code);
|
cbr.m_dumpCb(cbr.m_userp, self());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (vluint32_t i = 0; i < m_cleanupCbs.size(); ++i) {
|
||||||
|
const CallbackRecord& cbr = m_cleanupCbs[i];
|
||||||
|
cbr.m_dumpCb(cbr.m_userp, self());
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef VL_TRACE_THREADED
|
#ifdef VL_TRACE_THREADED
|
||||||
if (VL_LIKELY(bufferp)) {
|
if (VL_LIKELY(bufferp)) {
|
||||||
// Mark end of the trace buffer we just filled
|
// Mark end of the trace buffer we just filled
|
||||||
@@ -481,17 +472,32 @@ template <> void VerilatedTrace<VL_DERIVED_T>::dump(vluint64_t timeui) {
|
|||||||
// Non-hot path internal interface to Verilator generated code
|
// Non-hot path internal interface to Verilator generated code
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
void VerilatedTrace<VL_DERIVED_T>::addCallback(callback_t initcb, callback_t fullcb,
|
void VerilatedTrace<VL_DERIVED_T>::addCallbackRecord(std::vector<CallbackRecord>& cbVec,
|
||||||
callback_t changecb,
|
CallbackRecord& cbRec) {
|
||||||
void* userthis) VL_MT_UNSAFE_ONE {
|
|
||||||
m_assertOne.check();
|
m_assertOne.check();
|
||||||
if (VL_UNLIKELY(timeLastDump() != 0)) {
|
if (VL_UNCOVERABLE(timeLastDump() != 0)) { // LCOV_EXCL_START
|
||||||
std::string msg = (std::string("Internal: ") + __FILE__ + "::" + __FUNCTION__
|
std::string msg = (std::string("Internal: ") + __FILE__ + "::" + __FUNCTION__
|
||||||
+ " called with already open file");
|
+ " called with already open file");
|
||||||
VL_FATAL_MT(__FILE__, __LINE__, "", msg.c_str());
|
VL_FATAL_MT(__FILE__, __LINE__, "", msg.c_str());
|
||||||
}
|
} // LCOV_EXCL_STOP
|
||||||
VerilatedTraceCallInfo* cip = new VerilatedTraceCallInfo(initcb, fullcb, changecb, userthis);
|
cbVec.push_back(cbRec);
|
||||||
m_callbacks.push_back(cip);
|
}
|
||||||
|
|
||||||
|
template <> void VerilatedTrace<VL_DERIVED_T>::addInitCb(initCb_t cb, void* userp) {
|
||||||
|
CallbackRecord cbr(cb, userp);
|
||||||
|
addCallbackRecord(m_initCbs, cbr);
|
||||||
|
}
|
||||||
|
template <> void VerilatedTrace<VL_DERIVED_T>::addFullCb(dumpCb_t cb, void* userp) {
|
||||||
|
CallbackRecord cbr(cb, userp);
|
||||||
|
addCallbackRecord(m_fullCbs, cbr);
|
||||||
|
}
|
||||||
|
template <> void VerilatedTrace<VL_DERIVED_T>::addChgCb(dumpCb_t cb, void* userp) {
|
||||||
|
CallbackRecord cbr(cb, userp);
|
||||||
|
addCallbackRecord(m_chgCbs, cbr);
|
||||||
|
}
|
||||||
|
template <> void VerilatedTrace<VL_DERIVED_T>::addCleanupCb(dumpCb_t cb, void* userp) {
|
||||||
|
CallbackRecord cbr(cb, userp);
|
||||||
|
addCallbackRecord(m_cleanupCbs, cbr);
|
||||||
}
|
}
|
||||||
|
|
||||||
//=========================================================================
|
//=========================================================================
|
||||||
@@ -537,12 +543,6 @@ void VerilatedTrace<VL_DERIVED_T>::fullWData(vluint32_t* oldp, const WData* newv
|
|||||||
self()->emitWData(oldp - m_sigs_oldvalp, newvalp, bits);
|
self()->emitWData(oldp - m_sigs_oldvalp, newvalp, bits);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <> void VerilatedTrace<VL_DERIVED_T>::fullFloat(vluint32_t* oldp, float newval) {
|
|
||||||
// cppcheck-suppress invalidPointerCast
|
|
||||||
*reinterpret_cast<float*>(oldp) = newval;
|
|
||||||
self()->emitFloat(oldp - m_sigs_oldvalp, newval);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <> void VerilatedTrace<VL_DERIVED_T>::fullDouble(vluint32_t* oldp, double newval) {
|
template <> void VerilatedTrace<VL_DERIVED_T>::fullDouble(vluint32_t* oldp, double newval) {
|
||||||
// cppcheck-suppress invalidPointerCast
|
// cppcheck-suppress invalidPointerCast
|
||||||
*reinterpret_cast<double*>(oldp) = newval;
|
*reinterpret_cast<double*>(oldp) = newval;
|
||||||
@@ -555,7 +555,7 @@ template <> void VerilatedTrace<VL_DERIVED_T>::fullDouble(vluint32_t* oldp, doub
|
|||||||
// All of these take a destination pointer where the string will be emitted,
|
// All of these take a destination pointer where the string will be emitted,
|
||||||
// and a value to convert. There are a couple of variants for efficiency.
|
// and a value to convert. There are a couple of variants for efficiency.
|
||||||
|
|
||||||
inline static void cvtCDataToStr(char* dstp, CData value) {
|
static inline void cvtCDataToStr(char* dstp, CData value) {
|
||||||
#ifdef VL_HAVE_SSE2
|
#ifdef VL_HAVE_SSE2
|
||||||
// Similar to cvtSDataToStr but only the bottom 8 byte lanes are used
|
// Similar to cvtSDataToStr but only the bottom 8 byte lanes are used
|
||||||
const __m128i a = _mm_cvtsi32_si128(value);
|
const __m128i a = _mm_cvtsi32_si128(value);
|
||||||
@@ -577,7 +577,7 @@ inline static void cvtCDataToStr(char* dstp, CData value) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static void cvtSDataToStr(char* dstp, SData value) {
|
static inline void cvtSDataToStr(char* dstp, SData value) {
|
||||||
#ifdef VL_HAVE_SSE2
|
#ifdef VL_HAVE_SSE2
|
||||||
// We want each bit in the 16-bit input value to end up in a byte lane
|
// We want each bit in the 16-bit input value to end up in a byte lane
|
||||||
// within the 128-bit XMM register. Note that x86 is little-endian and we
|
// within the 128-bit XMM register. Note that x86 is little-endian and we
|
||||||
@@ -613,7 +613,7 @@ inline static void cvtSDataToStr(char* dstp, SData value) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static void cvtIDataToStr(char* dstp, IData value) {
|
static inline void cvtIDataToStr(char* dstp, IData value) {
|
||||||
#ifdef VL_HAVE_AVX2
|
#ifdef VL_HAVE_AVX2
|
||||||
// Similar to cvtSDataToStr but the bottom 16-bits are processed in the
|
// Similar to cvtSDataToStr but the bottom 16-bits are processed in the
|
||||||
// top half of the YMM registerss
|
// top half of the YMM registerss
|
||||||
@@ -632,9 +632,46 @@ inline static void cvtIDataToStr(char* dstp, IData value) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static void cvtQDataToStr(char* dstp, QData value) {
|
static inline void cvtQDataToStr(char* dstp, QData value) {
|
||||||
cvtIDataToStr(dstp, value >> 32);
|
cvtIDataToStr(dstp, value >> 32);
|
||||||
cvtIDataToStr(dstp + 32, value);
|
cvtIDataToStr(dstp + 32, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define cvtEDataToStr cvtIDataToStr
|
#define cvtEDataToStr cvtIDataToStr
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
#ifdef VERILATED_VCD_TEST
|
||||||
|
|
||||||
|
void verilated_trace_imp_selftest() {
|
||||||
|
#define SELF_CHECK(got, exp) \
|
||||||
|
do { \
|
||||||
|
if ((got) != (exp)) VL_FATAL_MT(__FILE__, __LINE__, "", "%Error: selftest\n"); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define SELF_CHECK_TS(scale) \
|
||||||
|
SELF_CHECK(doubleToTimescale(timescaleToDouble(scale)), std::string{scale});
|
||||||
|
SELF_CHECK_TS("1s");
|
||||||
|
SELF_CHECK_TS("100ms");
|
||||||
|
SELF_CHECK_TS("10ms");
|
||||||
|
SELF_CHECK_TS("1ms");
|
||||||
|
SELF_CHECK_TS("100us");
|
||||||
|
SELF_CHECK_TS("10us");
|
||||||
|
SELF_CHECK_TS("1us");
|
||||||
|
SELF_CHECK_TS("100ns");
|
||||||
|
SELF_CHECK_TS("10ns");
|
||||||
|
SELF_CHECK_TS("1ns");
|
||||||
|
SELF_CHECK_TS("100ps");
|
||||||
|
SELF_CHECK_TS("10ps");
|
||||||
|
SELF_CHECK_TS("1ps");
|
||||||
|
SELF_CHECK_TS("100fs");
|
||||||
|
SELF_CHECK_TS("10fs");
|
||||||
|
SELF_CHECK_TS("1fs");
|
||||||
|
SELF_CHECK_TS("100as");
|
||||||
|
SELF_CHECK_TS("10as");
|
||||||
|
SELF_CHECK_TS("1as");
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // VL_CPPCHECK
|
||||||
|
|||||||
@@ -1,497 +0,0 @@
|
|||||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
|
||||||
//*************************************************************************
|
|
||||||
// DESCRIPTION: Verilator: pre-C++11 replacements for std::unordered_set
|
|
||||||
// and std::unordered_map.
|
|
||||||
//
|
|
||||||
// Code available from: https://verilator.org
|
|
||||||
//
|
|
||||||
//*************************************************************************
|
|
||||||
//
|
|
||||||
// Copyright 2003-2020 by Wilson Snyder. This program is free software; you
|
|
||||||
// can redistribute it and/or modify it under the terms of either the GNU
|
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
|
||||||
// Version 2.0.
|
|
||||||
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
|
||||||
//
|
|
||||||
//*************************************************************************
|
|
||||||
|
|
||||||
//*************************************************************************
|
|
||||||
// This file has clones of the std::unordered_set and std::unordered_map
|
|
||||||
// hash table types. They are here so that Verilator can use hash tables
|
|
||||||
// in pre-C++11 compilers, and the same client code can link against the
|
|
||||||
// std:: types when they are available.
|
|
||||||
//
|
|
||||||
// The implementations in this file do not implement the complete APIs
|
|
||||||
// of the std:: types. Nor are they correct in every detail,
|
|
||||||
// notably, the const_iterators do not enforce constness. We can extend
|
|
||||||
// these implementations to cover more of the std API as needed.
|
|
||||||
//
|
|
||||||
// TODO: In the future, when Verilator requires C++11 to compile,
|
|
||||||
// remove this entire file and switch to the std:: types.
|
|
||||||
//
|
|
||||||
//*************************************************************************
|
|
||||||
|
|
||||||
#ifndef _V3_UNORDERED_SET_MAP_H_
|
|
||||||
#define _V3_UNORDERED_SET_MAP_H_
|
|
||||||
|
|
||||||
#include "verilatedos.h"
|
|
||||||
|
|
||||||
#include <list>
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
// Abstract 'vl_hash' and 'vl_equal_to' templates.
|
|
||||||
template <typename T> struct vl_hash { size_t operator()(const T& k) const; };
|
|
||||||
|
|
||||||
template <typename T> struct vl_equal_to { bool operator()(const T& a, const T& b) const; };
|
|
||||||
|
|
||||||
// Specializations of 'vl_hash' and 'vl_equal_to'.
|
|
||||||
inline size_t vl_hash_bytes(const void* vbufp, size_t nbytes) {
|
|
||||||
const vluint8_t* bufp = static_cast<const vluint8_t*>(vbufp);
|
|
||||||
size_t hash = 0;
|
|
||||||
for (size_t i = 0; i < nbytes; i++) {
|
|
||||||
hash = bufp[i] + 31U * hash; // the K&R classic!
|
|
||||||
}
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <> inline size_t vl_hash<unsigned int>::operator()(const unsigned int& k) const {
|
|
||||||
return k;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
inline bool vl_equal_to<unsigned int>::operator()(const unsigned int& a,
|
|
||||||
const unsigned int& b) const {
|
|
||||||
return a == b;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <> inline size_t vl_hash<std::string>::operator()(const std::string& k) const {
|
|
||||||
return vl_hash_bytes(k.data(), k.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
inline bool vl_equal_to<std::string>::operator()(const std::string& a,
|
|
||||||
const std::string& b) const {
|
|
||||||
// Don't scan the strings if the sizes are different.
|
|
||||||
if (a.size() != b.size()) return false;
|
|
||||||
return (0 == a.compare(b)); // Must scan.
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T> struct vl_hash<T*> {
|
|
||||||
size_t operator()(T* kp) const {
|
|
||||||
return ((sizeof(size_t) == sizeof(kp)) ? reinterpret_cast<size_t>(kp)
|
|
||||||
: vl_hash_bytes(&kp, sizeof(kp)));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T> struct vl_equal_to<T*> {
|
|
||||||
bool operator()(T* ap, T* bp) const { return ap == bp; }
|
|
||||||
};
|
|
||||||
|
|
||||||
//===================================================================
|
|
||||||
//
|
|
||||||
/// Functional clone of the std::unordered_set hash table.
|
|
||||||
template <class T_Key, class T_Hash = vl_hash<T_Key>, class T_Equal = vl_equal_to<T_Key> >
|
|
||||||
class vl_unordered_set {
|
|
||||||
public:
|
|
||||||
// TYPES
|
|
||||||
typedef std::list<T_Key> Bucket;
|
|
||||||
enum RehashType { GROW, SHRINK };
|
|
||||||
|
|
||||||
template <class KK, class VV, class HH, class EQ> friend class vl_unordered_map;
|
|
||||||
|
|
||||||
class iterator {
|
|
||||||
protected:
|
|
||||||
// MEMBERS
|
|
||||||
size_t m_bucketIdx; // Bucket this iterator points into
|
|
||||||
typename Bucket::iterator m_bit; // Bucket-local iterator
|
|
||||||
const vl_unordered_set* m_setp; // The containing set
|
|
||||||
|
|
||||||
public:
|
|
||||||
// CONSTRUCTORS
|
|
||||||
iterator(size_t bucketIdx, typename Bucket::iterator bit, const vl_unordered_set* setp)
|
|
||||||
: m_bucketIdx(bucketIdx)
|
|
||||||
, m_bit(bit)
|
|
||||||
, m_setp(setp) {}
|
|
||||||
|
|
||||||
// METHODS
|
|
||||||
const T_Key& operator*() const { return *m_bit; }
|
|
||||||
// This should really be 'const T_Key*' type for unordered_set,
|
|
||||||
// however this iterator is shared with unordered_map whose
|
|
||||||
// operator-> returns a non-const ValueType*, so keep this
|
|
||||||
// non-const to avoid having to define a whole separate iterator
|
|
||||||
// for unordered_map.
|
|
||||||
T_Key* operator->() const { return &(*m_bit); }
|
|
||||||
bool operator==(const iterator& other) const {
|
|
||||||
return ((m_bucketIdx == other.m_bucketIdx) && (m_bit == other.m_bit));
|
|
||||||
}
|
|
||||||
bool operator!=(const iterator& other) const { return (!this->operator==(other)); }
|
|
||||||
void advanceUntilValid() {
|
|
||||||
while (true) {
|
|
||||||
if (m_bit != m_setp->m_bucketsp[m_bucketIdx].end()) {
|
|
||||||
// Valid iterator in this bucket; we're done.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try the next bucket?
|
|
||||||
m_bucketIdx++;
|
|
||||||
if (m_bucketIdx == m_setp->numBuckets()) {
|
|
||||||
// Ran past the end of buckets, set to end().
|
|
||||||
*this = m_setp->end();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
m_bit = m_setp->m_bucketsp[m_bucketIdx].begin();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void operator++() {
|
|
||||||
++m_bit;
|
|
||||||
advanceUntilValid();
|
|
||||||
}
|
|
||||||
|
|
||||||
typename Bucket::iterator bit() const { return m_bit; }
|
|
||||||
};
|
|
||||||
|
|
||||||
// TODO: there's no real const enforcement on the 'const_iterator'.
|
|
||||||
typedef iterator const_iterator;
|
|
||||||
|
|
||||||
private:
|
|
||||||
// MEMBERS
|
|
||||||
size_t m_numElements; // Number of entries present.
|
|
||||||
size_t m_log2Buckets; // Log-base-2 of the number of buckets.
|
|
||||||
mutable Bucket* m_bucketsp; // Hash table buckets. May be NULL;
|
|
||||||
// // we'll allocate it on the fly when
|
|
||||||
// // the first entries are created.
|
|
||||||
Bucket m_emptyBucket; // A fake bucket, used to construct end().
|
|
||||||
T_Hash m_hash; // Hash function provider.
|
|
||||||
T_Equal m_equal; // Equal-to function provider.
|
|
||||||
|
|
||||||
public:
|
|
||||||
// CONSTRUCTORS
|
|
||||||
vl_unordered_set()
|
|
||||||
: m_numElements(0)
|
|
||||||
, m_log2Buckets(initLog2Buckets())
|
|
||||||
, m_bucketsp(NULL)
|
|
||||||
, m_hash()
|
|
||||||
, m_equal() {}
|
|
||||||
|
|
||||||
vl_unordered_set(const vl_unordered_set& other)
|
|
||||||
: m_numElements(other.m_numElements)
|
|
||||||
, m_log2Buckets(other.m_log2Buckets)
|
|
||||||
, m_bucketsp(NULL)
|
|
||||||
, m_hash()
|
|
||||||
, m_equal() {
|
|
||||||
if (other.m_bucketsp) {
|
|
||||||
m_bucketsp = new Bucket[numBuckets()];
|
|
||||||
for (size_t i = 0; i < numBuckets(); i++) m_bucketsp[i] = other.m_bucketsp[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
~vl_unordered_set() { VL_DO_DANGLING(delete[] m_bucketsp, m_bucketsp); }
|
|
||||||
|
|
||||||
vl_unordered_set& operator=(const vl_unordered_set& other) {
|
|
||||||
if (this != &other) {
|
|
||||||
clear();
|
|
||||||
delete[] m_bucketsp;
|
|
||||||
m_numElements = other.m_numElements;
|
|
||||||
m_log2Buckets = other.m_log2Buckets;
|
|
||||||
if (other.m_bucketsp) {
|
|
||||||
m_bucketsp = new Bucket[numBuckets()];
|
|
||||||
for (size_t i = 0; i < numBuckets(); i++) m_bucketsp[i] = other.m_bucketsp[i];
|
|
||||||
} else {
|
|
||||||
m_bucketsp = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// METHODS
|
|
||||||
static size_t initLog2Buckets() { return 4; }
|
|
||||||
|
|
||||||
iterator begin() {
|
|
||||||
if (m_numElements) {
|
|
||||||
initBuckets();
|
|
||||||
iterator result = iterator(0, m_bucketsp[0].begin(), this);
|
|
||||||
result.advanceUntilValid();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
return end();
|
|
||||||
}
|
|
||||||
const_iterator begin() const {
|
|
||||||
if (m_numElements) {
|
|
||||||
initBuckets();
|
|
||||||
const_iterator result = iterator(0, m_bucketsp[0].begin(), this);
|
|
||||||
result.advanceUntilValid();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
return end();
|
|
||||||
}
|
|
||||||
const_iterator end() const {
|
|
||||||
return iterator(VL_ULL(0xFFFFFFFFFFFFFFFF), const_cast<Bucket&>(m_emptyBucket).begin(),
|
|
||||||
this);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool empty() const { return m_numElements == 0; }
|
|
||||||
|
|
||||||
size_t size() const { return m_numElements; }
|
|
||||||
|
|
||||||
size_t count(const T_Key& key) const { return (find(key) == end()) ? 0 : 1; }
|
|
||||||
|
|
||||||
size_t hashToBucket(size_t hashVal) const { return hashToBucket(hashVal, m_log2Buckets); }
|
|
||||||
static size_t hashToBucket(size_t hashVal, unsigned log2Buckets) {
|
|
||||||
// Fibonacci hashing, see
|
|
||||||
// https://probablydance.com/2018/06/16/fibonacci-hashing-the-optimization
|
|
||||||
// -that-the-world-forgot-or-a-better-alternative-to-integer-modulo/
|
|
||||||
//
|
|
||||||
// * The magic numbers below are UINT_MAX/phi where phi is the
|
|
||||||
// golden ratio number (1.618...) for either 64- or 32-bit
|
|
||||||
// values of UINT_MAX.
|
|
||||||
//
|
|
||||||
// * Fibonacci hashing mixes the result of the client's hash
|
|
||||||
// function further. This permits the use of very fast client
|
|
||||||
// hash funcs (like just returning the int or pointer value as
|
|
||||||
// is!) and tolerates crappy client hash functions pretty well.
|
|
||||||
size_t mult
|
|
||||||
= hashVal * ((sizeof(size_t) == 8) ? VL_ULL(11400714819323198485) : 2654435769lu);
|
|
||||||
size_t result = (mult >> (((sizeof(size_t) == 8) ? 64 : 32) - log2Buckets));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
iterator find_internal(const T_Key& key, size_t& bucketIdxOut) {
|
|
||||||
size_t hash = m_hash.operator()(key);
|
|
||||||
bucketIdxOut = hashToBucket(hash);
|
|
||||||
initBuckets();
|
|
||||||
Bucket* bucketp = &m_bucketsp[bucketIdxOut];
|
|
||||||
|
|
||||||
for (typename Bucket::iterator it = bucketp->begin(); it != bucketp->end(); ++it) {
|
|
||||||
if (m_equal.operator()(*it, key)) return iterator(bucketIdxOut, it, this);
|
|
||||||
}
|
|
||||||
return end();
|
|
||||||
}
|
|
||||||
|
|
||||||
const_iterator find(const T_Key& key) const {
|
|
||||||
size_t bucketIdx;
|
|
||||||
return const_cast<vl_unordered_set*>(this)->find_internal(key, bucketIdx);
|
|
||||||
}
|
|
||||||
|
|
||||||
iterator find(const T_Key& key) {
|
|
||||||
size_t bucketIdx;
|
|
||||||
return find_internal(key, bucketIdx);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::pair<iterator, bool> insert(const T_Key& val) {
|
|
||||||
size_t bucketIdx;
|
|
||||||
iterator existIt = find_internal(val, bucketIdx);
|
|
||||||
if (existIt != end()) {
|
|
||||||
// Collision with existing element.
|
|
||||||
//
|
|
||||||
// An element may be inserted only if it is not
|
|
||||||
// equal to an existing element. So fail.
|
|
||||||
return std::pair<iterator, bool>(end(), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// No collision, so insert it.
|
|
||||||
m_numElements++;
|
|
||||||
|
|
||||||
m_bucketsp[bucketIdx].push_front(val);
|
|
||||||
|
|
||||||
// Compute result iterator. This pointer will be valid
|
|
||||||
// if we don't rehash:
|
|
||||||
iterator result_it(bucketIdx, m_bucketsp[bucketIdx].begin(), this);
|
|
||||||
|
|
||||||
if (needToRehash(GROW)) {
|
|
||||||
rehash(GROW);
|
|
||||||
// ... since we rehashed, do a lookup to get the result iterator.
|
|
||||||
result_it = find(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::pair<iterator, bool>(result_it, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
iterator erase(iterator it) {
|
|
||||||
iterator next_it = it;
|
|
||||||
++next_it;
|
|
||||||
erase(*it);
|
|
||||||
return next_it;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t erase(const T_Key& key) {
|
|
||||||
size_t bucketIdx;
|
|
||||||
iterator it = find_internal(key, bucketIdx);
|
|
||||||
if (it != end()) {
|
|
||||||
m_bucketsp[bucketIdx].erase(it.bit());
|
|
||||||
m_numElements--;
|
|
||||||
// Rehashing to handle a shrinking data set is important
|
|
||||||
// for the Scoreboard in V3Partition, which begins tracking
|
|
||||||
// a huge number of vertices and then tracks a successively
|
|
||||||
// smaller number over time.
|
|
||||||
if (needToRehash(SHRINK)) rehash(SHRINK);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void clear() {
|
|
||||||
if (m_bucketsp) {
|
|
||||||
delete[] m_bucketsp;
|
|
||||||
m_bucketsp = NULL;
|
|
||||||
}
|
|
||||||
m_numElements = 0;
|
|
||||||
m_log2Buckets = initLog2Buckets();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
size_t numBuckets() const { return (VL_ULL(1) << m_log2Buckets); }
|
|
||||||
|
|
||||||
Bucket* getBucket(size_t idx) {
|
|
||||||
initBuckets();
|
|
||||||
return &m_bucketsp[idx];
|
|
||||||
}
|
|
||||||
|
|
||||||
void initBuckets() const {
|
|
||||||
if (!m_bucketsp) m_bucketsp = new Bucket[numBuckets()];
|
|
||||||
}
|
|
||||||
|
|
||||||
bool needToRehash(RehashType rt) const {
|
|
||||||
if (rt == GROW) {
|
|
||||||
return ((4 * numBuckets()) < m_numElements);
|
|
||||||
} else {
|
|
||||||
return (numBuckets() > (4 * m_numElements));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void rehash(RehashType rt) {
|
|
||||||
size_t new_log2Buckets;
|
|
||||||
if (rt == GROW) {
|
|
||||||
new_log2Buckets = m_log2Buckets + 2;
|
|
||||||
} else {
|
|
||||||
if (m_log2Buckets <= 4) {
|
|
||||||
// On shrink, saturate m_log2Buckets at its
|
|
||||||
// initial size of 2^4 == 16 buckets. Don't risk
|
|
||||||
// underflowing!
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
new_log2Buckets = m_log2Buckets - 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t new_num_buckets = VL_ULL(1) << new_log2Buckets;
|
|
||||||
Bucket* new_bucketsp = new Bucket[new_num_buckets];
|
|
||||||
|
|
||||||
for (size_t i = 0; i < numBuckets(); i++) {
|
|
||||||
while (!m_bucketsp[i].empty()) {
|
|
||||||
typename Bucket::iterator bit = m_bucketsp[i].begin();
|
|
||||||
size_t hash = m_hash.operator()(*bit);
|
|
||||||
size_t new_idx = hashToBucket(hash, new_log2Buckets);
|
|
||||||
// Avoid mallocing one list elem and freeing another;
|
|
||||||
// splice just moves it over.
|
|
||||||
new_bucketsp[new_idx].splice(new_bucketsp[new_idx].begin(), m_bucketsp[i], bit);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
delete[] m_bucketsp;
|
|
||||||
m_bucketsp = new_bucketsp;
|
|
||||||
m_log2Buckets = new_log2Buckets;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//===================================================================
|
|
||||||
//
|
|
||||||
/// Functional clone of the std::unordered_map hash table.
|
|
||||||
template <class T_Key, class T_Value, class T_Hash = vl_hash<T_Key>,
|
|
||||||
class T_Equal = vl_equal_to<T_Key> >
|
|
||||||
class vl_unordered_map {
|
|
||||||
private:
|
|
||||||
// TYPES
|
|
||||||
typedef std::pair<T_Key, T_Value> KeyValPair;
|
|
||||||
|
|
||||||
class KeyHash {
|
|
||||||
private:
|
|
||||||
T_Hash key_hash;
|
|
||||||
|
|
||||||
public:
|
|
||||||
KeyHash() {}
|
|
||||||
size_t operator()(const KeyValPair& kv_pair) const {
|
|
||||||
return key_hash.operator()(kv_pair.first);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class KeyEqual {
|
|
||||||
private:
|
|
||||||
T_Equal key_eq;
|
|
||||||
|
|
||||||
public:
|
|
||||||
KeyEqual() {}
|
|
||||||
bool operator()(const KeyValPair& kv_a, const KeyValPair& kv_b) const {
|
|
||||||
return key_eq.operator()(kv_a.first, kv_b.first);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// MEMBERS
|
|
||||||
typedef vl_unordered_set<KeyValPair, KeyHash, KeyEqual> MapSet;
|
|
||||||
MapSet m_set; // Wrap this vl_unordered_set which holds all state.
|
|
||||||
|
|
||||||
public:
|
|
||||||
// CONSTRUCTORS
|
|
||||||
vl_unordered_map() {}
|
|
||||||
~vl_unordered_map() {}
|
|
||||||
|
|
||||||
typedef typename MapSet::iterator iterator;
|
|
||||||
typedef typename MapSet::const_iterator const_iterator;
|
|
||||||
|
|
||||||
// METHODS
|
|
||||||
iterator begin() { return m_set.begin(); }
|
|
||||||
const_iterator begin() const { return m_set.begin(); }
|
|
||||||
const_iterator end() const { return m_set.end(); }
|
|
||||||
bool empty() const { return m_set.empty(); }
|
|
||||||
iterator find(const T_Key& k) {
|
|
||||||
// We can't assume that T_Value() is defined.
|
|
||||||
// ie, this does not work:
|
|
||||||
// return m_set.find(std::make_pair(k, T_Value()));
|
|
||||||
|
|
||||||
// So, do this instead:
|
|
||||||
T_Hash mapHash;
|
|
||||||
T_Equal mapEq;
|
|
||||||
size_t hash = mapHash.operator()(k);
|
|
||||||
size_t bucketIdxOut = m_set.hashToBucket(hash);
|
|
||||||
typename MapSet::Bucket* bucketp = m_set.getBucket(bucketIdxOut);
|
|
||||||
|
|
||||||
for (typename MapSet::Bucket::iterator it = bucketp->begin(); it != bucketp->end(); ++it) {
|
|
||||||
if (mapEq.operator()(it->first, k)) return iterator(bucketIdxOut, it, &m_set);
|
|
||||||
}
|
|
||||||
return end();
|
|
||||||
}
|
|
||||||
const_iterator find(const T_Key& k) const {
|
|
||||||
return const_cast<vl_unordered_map*>(this)->find(k);
|
|
||||||
}
|
|
||||||
std::pair<iterator, bool> insert(const KeyValPair& val) { return m_set.insert(val); }
|
|
||||||
iterator erase(iterator it) { return m_set.erase(it); }
|
|
||||||
size_t erase(const T_Key& k) {
|
|
||||||
iterator it = find(k);
|
|
||||||
if (it == end()) return 0;
|
|
||||||
m_set.erase(it);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
T_Value& operator[](const T_Key& k) {
|
|
||||||
// Here we can assume T_Value() is defined, as
|
|
||||||
// std::unordered_map::operator[] relies on it too.
|
|
||||||
KeyValPair dummy = std::make_pair(k, T_Value());
|
|
||||||
iterator it = m_set.find(dummy);
|
|
||||||
if (it == m_set.end()) it = m_set.insert(dummy).first;
|
|
||||||
// For the 'set', it's generally not safe to modify
|
|
||||||
// the value after deref. For the 'map' though, we know
|
|
||||||
// it's safe to modify the value field and we can allow it:
|
|
||||||
return it->second;
|
|
||||||
}
|
|
||||||
T_Value& at(const T_Key& k) {
|
|
||||||
iterator it = find(k);
|
|
||||||
if (it == end()) { throw std::out_of_range("sorry"); }
|
|
||||||
return it->second;
|
|
||||||
}
|
|
||||||
const T_Value& at(const T_Key& k) const {
|
|
||||||
iterator it = find(k);
|
|
||||||
if (it == end()) { throw std::out_of_range("sorry"); }
|
|
||||||
return it->second;
|
|
||||||
}
|
|
||||||
void clear() { m_set.clear(); }
|
|
||||||
size_t size() const { return m_set.size(); }
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
+87
-168
@@ -3,7 +3,7 @@
|
|||||||
//
|
//
|
||||||
// THIS MODULE IS PUBLICLY LICENSED
|
// THIS MODULE IS PUBLICLY LICENSED
|
||||||
//
|
//
|
||||||
// Copyright 2001-2020 by Wilson Snyder. This program is free software; you
|
// Copyright 2001-2021 by Wilson Snyder. This program is free software; you
|
||||||
// can redistribute it and/or modify it under the terms of either the GNU
|
// can 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,6 @@
|
|||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <sys/stat.h>
|
|
||||||
|
|
||||||
#if defined(_WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__)
|
#if defined(_WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__)
|
||||||
# include <io.h>
|
# include <io.h>
|
||||||
@@ -35,8 +34,6 @@
|
|||||||
# include <unistd.h>
|
# include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "verilated_intrinsics.h"
|
|
||||||
|
|
||||||
// SPDIFF_ON
|
// SPDIFF_ON
|
||||||
|
|
||||||
#ifndef O_LARGEFILE // For example on WIN32
|
#ifndef O_LARGEFILE // For example on WIN32
|
||||||
@@ -54,13 +51,14 @@
|
|||||||
// This size comes form VCD allowing use of printable ASCII characters between
|
// This size comes form VCD allowing use of printable ASCII characters between
|
||||||
// '!' and '~' inclusive, which are a total of 94 different values. Encoding a
|
// '!' and '~' inclusive, which are a total of 94 different values. Encoding a
|
||||||
// 32 bit code hence needs a maximum of ceil(log94(2**32-1)) == 5 bytes.
|
// 32 bit code hence needs a maximum of ceil(log94(2**32-1)) == 5 bytes.
|
||||||
#define VL_TRACE_MAX_VCD_CODE_SIZE 5 ///< Maximum length of a VCD string code
|
constexpr unsigned VL_TRACE_MAX_VCD_CODE_SIZE = 5; ///< Maximum length of a VCD string code
|
||||||
|
|
||||||
// We use 8 bytes per code in a suffix buffer array.
|
// We use 8 bytes per code in a suffix buffer array.
|
||||||
// 1 byte optional separator + VL_TRACE_MAX_VCD_CODE_SIZE bytes for code
|
// 1 byte optional separator + VL_TRACE_MAX_VCD_CODE_SIZE bytes for code
|
||||||
// + 1 byte '\n' + 1 byte suffix size. This luckily comes out to a power of 2,
|
// + 1 byte '\n' + 1 byte suffix size. This luckily comes out to a power of 2,
|
||||||
// meaning the array can be aligned such that entries never straddle multiple
|
// meaning the array can be aligned such that entries never straddle multiple
|
||||||
// cache-lines.
|
// cache-lines.
|
||||||
#define VL_TRACE_SUFFIX_ENTRY_SIZE 8 ///< Size of a suffix entry
|
constexpr unsigned VL_TRACE_SUFFIX_ENTRY_SIZE = 8; ///< Size of a suffix entry
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
// Specialization of the generics for this trace format
|
// Specialization of the generics for this trace format
|
||||||
@@ -69,47 +67,6 @@
|
|||||||
#include "verilated_trace_imp.cpp"
|
#include "verilated_trace_imp.cpp"
|
||||||
#undef VL_DERIVED_T
|
#undef VL_DERIVED_T
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
// VerilatedVcdImp
|
|
||||||
/// Base class to hold some static state
|
|
||||||
/// This is an internally used class
|
|
||||||
|
|
||||||
class VerilatedVcdSingleton {
|
|
||||||
private:
|
|
||||||
typedef std::vector<VerilatedVcd*> VcdVec;
|
|
||||||
struct Singleton {
|
|
||||||
VerilatedMutex s_vcdMutex; ///< Protect the singleton
|
|
||||||
VcdVec s_vcdVecp VL_GUARDED_BY(s_vcdMutex); ///< List of all created traces
|
|
||||||
};
|
|
||||||
static Singleton& singleton() {
|
|
||||||
static Singleton s;
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
static void pushVcd(VerilatedVcd* vcdp) VL_EXCLUDES(singleton().s_vcdMutex) {
|
|
||||||
VerilatedLockGuard lock(singleton().s_vcdMutex);
|
|
||||||
singleton().s_vcdVecp.push_back(vcdp);
|
|
||||||
}
|
|
||||||
static void removeVcd(const VerilatedVcd* vcdp) VL_EXCLUDES(singleton().s_vcdMutex) {
|
|
||||||
VerilatedLockGuard lock(singleton().s_vcdMutex);
|
|
||||||
VcdVec::iterator pos
|
|
||||||
= find(singleton().s_vcdVecp.begin(), singleton().s_vcdVecp.end(), vcdp);
|
|
||||||
if (pos != singleton().s_vcdVecp.end()) { singleton().s_vcdVecp.erase(pos); }
|
|
||||||
}
|
|
||||||
static void flush_all() VL_EXCLUDES(singleton().s_vcdMutex) VL_MT_UNSAFE_ONE {
|
|
||||||
// Thread safety: Although this function is protected by a mutex so
|
|
||||||
// perhaps in the future we can allow tracing in separate threads,
|
|
||||||
// vcdp->flush() assumes call from single thread
|
|
||||||
VerilatedLockGuard lock(singleton().s_vcdMutex);
|
|
||||||
for (VcdVec::const_iterator it = singleton().s_vcdVecp.begin();
|
|
||||||
it != singleton().s_vcdVecp.end(); ++it) {
|
|
||||||
VerilatedVcd* vcdp = *it;
|
|
||||||
vcdp->flush();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
@@ -132,21 +89,15 @@ ssize_t VerilatedVcdFile::write(const char* bufp, ssize_t len) VL_MT_UNSAFE {
|
|||||||
//=============================================================================
|
//=============================================================================
|
||||||
// Opening/Closing
|
// Opening/Closing
|
||||||
|
|
||||||
VerilatedVcd::VerilatedVcd(VerilatedVcdFile* filep)
|
VerilatedVcd::VerilatedVcd(VerilatedVcdFile* filep) {
|
||||||
: m_isOpen(false)
|
|
||||||
, m_rolloverMB(0)
|
|
||||||
, m_modDepth(0) {
|
|
||||||
// Not in header to avoid link issue if header is included without this .cpp file
|
// Not in header to avoid link issue if header is included without this .cpp file
|
||||||
m_fileNewed = (filep == NULL);
|
m_fileNewed = (filep == nullptr);
|
||||||
m_filep = m_fileNewed ? new VerilatedVcdFile : filep;
|
m_filep = m_fileNewed ? new VerilatedVcdFile : filep;
|
||||||
m_namemapp = NULL;
|
|
||||||
m_evcd = false;
|
|
||||||
m_wrChunkSize = 8 * 1024;
|
m_wrChunkSize = 8 * 1024;
|
||||||
m_wrBufp = new char[m_wrChunkSize * 8];
|
m_wrBufp = new char[m_wrChunkSize * 8];
|
||||||
m_wrFlushp = m_wrBufp + m_wrChunkSize * 6;
|
m_wrFlushp = m_wrBufp + m_wrChunkSize * 6;
|
||||||
m_writep = m_wrBufp;
|
m_writep = m_wrBufp;
|
||||||
m_wroteBytes = 0;
|
m_suffixesp = nullptr;
|
||||||
m_suffixesp = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VerilatedVcd::open(const char* filename) {
|
void VerilatedVcd::open(const char* filename) {
|
||||||
@@ -155,13 +106,7 @@ void VerilatedVcd::open(const char* filename) {
|
|||||||
|
|
||||||
// Set member variables
|
// Set member variables
|
||||||
m_filename = filename; // "" is ok, as someone may overload open
|
m_filename = filename; // "" is ok, as someone may overload open
|
||||||
VerilatedVcdSingleton::pushVcd(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;
|
||||||
|
|
||||||
@@ -203,8 +148,8 @@ void VerilatedVcd::openNext(bool incFilename) {
|
|||||||
}
|
}
|
||||||
m_filename = name;
|
m_filename = name;
|
||||||
}
|
}
|
||||||
if (m_filename[0] == '|') {
|
if (VL_UNCOVERABLE(m_filename[0] == '|')) {
|
||||||
assert(0); // Not supported yet.
|
assert(0); // LCOV_EXCL_LINE // Not supported yet.
|
||||||
} else {
|
} else {
|
||||||
// cppcheck-suppress duplicateExpression
|
// cppcheck-suppress duplicateExpression
|
||||||
if (!m_filep->open(m_filename)) {
|
if (!m_filep->open(m_filename)) {
|
||||||
@@ -241,19 +186,19 @@ void VerilatedVcd::makeNameMap() {
|
|||||||
// If no scope was specified, prefix everything with a "top"
|
// If no scope was specified, prefix everything with a "top"
|
||||||
// This comes from user instantiations with no name - IE Vtop("").
|
// This comes from user instantiations with no name - IE Vtop("").
|
||||||
bool nullScope = false;
|
bool nullScope = false;
|
||||||
for (NameMap::const_iterator it = m_namemapp->begin(); it != m_namemapp->end(); ++it) {
|
for (const auto& i : *m_namemapp) {
|
||||||
const std::string& hiername = it->first;
|
const std::string& hiername = i.first;
|
||||||
if (!hiername.empty() && hiername[0] == '\t') nullScope = true;
|
if (!hiername.empty() && hiername[0] == '\t') nullScope = true;
|
||||||
}
|
}
|
||||||
if (nullScope) {
|
if (nullScope) {
|
||||||
NameMap* newmapp = new NameMap;
|
NameMap* newmapp = new NameMap;
|
||||||
for (NameMap::const_iterator it = m_namemapp->begin(); it != m_namemapp->end(); ++it) {
|
for (const auto& i : *m_namemapp) {
|
||||||
const std::string& hiername = it->first;
|
const std::string& hiername = i.first;
|
||||||
const std::string& decl = it->second;
|
const std::string& decl = i.second;
|
||||||
std::string newname = std::string("top");
|
std::string newname = std::string("top");
|
||||||
if (hiername[0] != '\t') newname += ' ';
|
if (hiername[0] != '\t') newname += ' ';
|
||||||
newname += hiername;
|
newname += hiername;
|
||||||
newmapp->insert(std::make_pair(newname, decl));
|
newmapp->emplace(newname, decl);
|
||||||
}
|
}
|
||||||
deleteNameMap();
|
deleteNameMap();
|
||||||
m_namemapp = newmapp;
|
m_namemapp = newmapp;
|
||||||
@@ -261,15 +206,14 @@ void VerilatedVcd::makeNameMap() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void VerilatedVcd::deleteNameMap() {
|
void VerilatedVcd::deleteNameMap() {
|
||||||
if (m_namemapp) VL_DO_CLEAR(delete m_namemapp, m_namemapp = NULL);
|
if (m_namemapp) VL_DO_CLEAR(delete m_namemapp, m_namemapp = nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
VerilatedVcd::~VerilatedVcd() {
|
VerilatedVcd::~VerilatedVcd() {
|
||||||
close();
|
close();
|
||||||
if (m_wrBufp) VL_DO_CLEAR(delete[] m_wrBufp, m_wrBufp = NULL);
|
if (m_wrBufp) VL_DO_CLEAR(delete[] m_wrBufp, m_wrBufp = nullptr);
|
||||||
deleteNameMap();
|
deleteNameMap();
|
||||||
if (m_filep && m_fileNewed) VL_DO_CLEAR(delete m_filep, m_filep = NULL);
|
if (m_filep && m_fileNewed) VL_DO_CLEAR(delete m_filep, m_filep = nullptr);
|
||||||
VerilatedVcdSingleton::removeVcd(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VerilatedVcd::closePrev() {
|
void VerilatedVcd::closePrev() {
|
||||||
@@ -337,7 +281,7 @@ void VerilatedVcd::bufferResize(vluint64_t minsize) {
|
|||||||
memcpy(m_wrBufp, oldbufp, m_writep - oldbufp);
|
memcpy(m_wrBufp, oldbufp, m_writep - oldbufp);
|
||||||
m_writep = m_wrBufp + (m_writep - oldbufp);
|
m_writep = m_wrBufp + (m_writep - oldbufp);
|
||||||
m_wrFlushp = m_wrBufp + m_wrChunkSize * 6;
|
m_wrFlushp = m_wrBufp + m_wrChunkSize * 6;
|
||||||
VL_DO_CLEAR(delete[] oldbufp, oldbufp = NULL);
|
VL_DO_CLEAR(delete[] oldbufp, oldbufp = nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -358,13 +302,15 @@ void VerilatedVcd::bufferFlush() VL_MT_UNSAFE_ONE {
|
|||||||
if (got > 0) {
|
if (got > 0) {
|
||||||
wp += got;
|
wp += got;
|
||||||
m_wroteBytes += got;
|
m_wroteBytes += got;
|
||||||
} else if (got < 0) {
|
} else if (VL_UNCOVERABLE(got < 0)) {
|
||||||
if (errno != EAGAIN && errno != EINTR) {
|
if (VL_UNCOVERABLE(errno != EAGAIN && errno != EINTR)) {
|
||||||
|
// LCOV_EXCL_START
|
||||||
// write failed, presume error (perhaps out of disk space)
|
// write failed, presume error (perhaps out of disk space)
|
||||||
std::string msg = std::string("VerilatedVcd::bufferFlush: ") + strerror(errno);
|
std::string msg = std::string("VerilatedVcd::bufferFlush: ") + strerror(errno);
|
||||||
VL_FATAL_MT("", 0, "", msg.c_str());
|
VL_FATAL_MT("", 0, "", msg.c_str());
|
||||||
closeErr();
|
closeErr();
|
||||||
break;
|
break;
|
||||||
|
// LCOV_EXCL_STOP
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -399,7 +345,7 @@ void VerilatedVcd::printIndent(int level_change) {
|
|||||||
|
|
||||||
void VerilatedVcd::dumpHeader() {
|
void VerilatedVcd::dumpHeader() {
|
||||||
printStr("$version Generated by VerilatedVcd $end\n");
|
printStr("$version Generated by VerilatedVcd $end\n");
|
||||||
time_t time_str = time(NULL);
|
time_t time_str = time(nullptr);
|
||||||
printStr("$date ");
|
printStr("$date ");
|
||||||
printStr(ctime(&time_str));
|
printStr(ctime(&time_str));
|
||||||
printStr(" $end\n");
|
printStr(" $end\n");
|
||||||
@@ -422,9 +368,9 @@ void VerilatedVcd::dumpHeader() {
|
|||||||
|
|
||||||
// Print the signal names
|
// Print the signal names
|
||||||
const char* lastName = "";
|
const char* lastName = "";
|
||||||
for (NameMap::const_iterator it = m_namemapp->begin(); it != m_namemapp->end(); ++it) {
|
for (const auto& i : *m_namemapp) {
|
||||||
const std::string& hiernamestr = it->first;
|
const std::string& hiernamestr = i.first;
|
||||||
const std::string& decl = it->second;
|
const std::string& decl = i.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* hiername = hiernamestr.c_str();
|
||||||
@@ -565,7 +511,7 @@ void VerilatedVcd::declare(vluint32_t code, const char* name, const char* wirep,
|
|||||||
decl += buf;
|
decl += buf;
|
||||||
}
|
}
|
||||||
decl += " $end\n";
|
decl += " $end\n";
|
||||||
m_namemapp->insert(std::make_pair(hiername, decl));
|
m_namemapp->emplace(hiername, decl);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VerilatedVcd::declBit(vluint32_t code, const char* name, bool array, int arraynum) {
|
void VerilatedVcd::declBit(vluint32_t code, const char* name, bool array, int arraynum) {
|
||||||
@@ -583,9 +529,6 @@ void VerilatedVcd::declArray(vluint32_t code, const char* name, bool array, int
|
|||||||
int lsb) {
|
int lsb) {
|
||||||
declare(code, name, "wire", array, arraynum, false, true, msb, lsb);
|
declare(code, name, "wire", array, arraynum, false, true, msb, lsb);
|
||||||
}
|
}
|
||||||
void VerilatedVcd::declFloat(vluint32_t code, const char* name, bool array, int arraynum) {
|
|
||||||
declare(code, name, "real", array, arraynum, false, false, 31, 0);
|
|
||||||
}
|
|
||||||
void VerilatedVcd::declDouble(vluint32_t code, const char* name, bool array, int arraynum) {
|
void VerilatedVcd::declDouble(vluint32_t code, const char* name, bool array, int arraynum) {
|
||||||
declare(code, name, "real", array, arraynum, false, false, 63, 0);
|
declare(code, name, "real", array, arraynum, false, false, 63, 0);
|
||||||
}
|
}
|
||||||
@@ -699,15 +642,6 @@ void VerilatedVcd::emitWData(vluint32_t code, const WData* newvalp, int bits) {
|
|||||||
finishLine(code, wp);
|
finishLine(code, wp);
|
||||||
}
|
}
|
||||||
|
|
||||||
VL_ATTR_ALWINLINE
|
|
||||||
void VerilatedVcd::emitFloat(vluint32_t code, float newval) {
|
|
||||||
char* wp = m_writep;
|
|
||||||
// Buffer can't overflow before sprintf; we sized during declaration
|
|
||||||
sprintf(wp, "r%.16g", static_cast<double>(newval));
|
|
||||||
wp += strlen(wp);
|
|
||||||
finishLine(code, wp);
|
|
||||||
}
|
|
||||||
|
|
||||||
VL_ATTR_ALWINLINE
|
VL_ATTR_ALWINLINE
|
||||||
void VerilatedVcd::emitDouble(vluint32_t code, double newval) {
|
void VerilatedVcd::emitDouble(vluint32_t code, double newval) {
|
||||||
char* wp = m_writep;
|
char* wp = m_writep;
|
||||||
@@ -742,7 +676,7 @@ void VerilatedVcd::fullQuad(vluint32_t code, const vluint64_t newval, int bits)
|
|||||||
(*(reinterpret_cast<vluint64_t*>(oldp(code)))) = newval;
|
(*(reinterpret_cast<vluint64_t*>(oldp(code)))) = newval;
|
||||||
*m_writep++ = 'b';
|
*m_writep++ = 'b';
|
||||||
for (int bit = bits - 1; bit >= 0; --bit) {
|
for (int bit = bits - 1; bit >= 0; --bit) {
|
||||||
*m_writep++ = ((newval & (VL_ULL(1) << bit)) ? '1' : '0');
|
*m_writep++ = ((newval & (1ULL << bit)) ? '1' : '0');
|
||||||
}
|
}
|
||||||
*m_writep++ = ' ';
|
*m_writep++ = ' ';
|
||||||
m_writep = writeCode(m_writep, code);
|
m_writep = writeCode(m_writep, code);
|
||||||
@@ -764,7 +698,7 @@ void VerilatedVcd::fullArray(vluint32_t code, const vluint64_t* newval, int bits
|
|||||||
for (int word = 0; word < (((bits - 1) / 64) + 1); ++word) { oldp(code)[word] = newval[word]; }
|
for (int word = 0; word < (((bits - 1) / 64) + 1); ++word) { oldp(code)[word] = newval[word]; }
|
||||||
*m_writep++ = 'b';
|
*m_writep++ = 'b';
|
||||||
for (int bit = bits - 1; bit >= 0; --bit) {
|
for (int bit = bits - 1; bit >= 0; --bit) {
|
||||||
*m_writep++ = ((newval[(bit / 64)] & (VL_ULL(1) << (bit & 0x3f))) ? '1' : '0');
|
*m_writep++ = ((newval[(bit / 64)] & (1ULL << (bit & 0x3f))) ? '1' : '0');
|
||||||
}
|
}
|
||||||
*m_writep++ = ' ';
|
*m_writep++ = ' ';
|
||||||
m_writep = writeCode(m_writep, code);
|
m_writep = writeCode(m_writep, code);
|
||||||
@@ -792,14 +726,13 @@ void VerilatedVcd::fullTriBus(vluint32_t code, const vluint32_t newval, const vl
|
|||||||
*m_writep++ = '\n';
|
*m_writep++ = '\n';
|
||||||
bufferCheck();
|
bufferCheck();
|
||||||
}
|
}
|
||||||
void VerilatedVcd::fullTriQuad(vluint32_t code, const vluint64_t newval, const vluint32_t newtri,
|
void VerilatedVcd::fullTriQuad(vluint32_t code, const vluint64_t newval, const vluint64_t newtri,
|
||||||
int bits) {
|
int bits) {
|
||||||
(*(reinterpret_cast<vluint64_t*>(oldp(code)))) = newval;
|
(*(reinterpret_cast<vluint64_t*>(oldp(code)))) = newval;
|
||||||
(*(reinterpret_cast<vluint64_t*>(oldp(code + 1)))) = newtri;
|
(*(reinterpret_cast<vluint64_t*>(oldp(code + 1)))) = newtri;
|
||||||
*m_writep++ = 'b';
|
*m_writep++ = 'b';
|
||||||
for (int bit = bits - 1; bit >= 0; --bit) {
|
for (int bit = bits - 1; bit >= 0; --bit) {
|
||||||
*m_writep++
|
*m_writep++ = "01zz"[((newval >> bit) & 1ULL) | (((newtri >> bit) & 1ULL) << 1ULL)];
|
||||||
= "01zz"[((newval >> bit) & VL_ULL(1)) | (((newtri >> bit) & VL_ULL(1)) << VL_ULL(1))];
|
|
||||||
}
|
}
|
||||||
*m_writep++ = ' ';
|
*m_writep++ = ' ';
|
||||||
m_writep = writeCode(m_writep, code);
|
m_writep = writeCode(m_writep, code);
|
||||||
@@ -834,82 +767,55 @@ void VerilatedVcd::fullDouble(vluint32_t code, const double newval) {
|
|||||||
*m_writep++ = '\n';
|
*m_writep++ = '\n';
|
||||||
bufferCheck();
|
bufferCheck();
|
||||||
}
|
}
|
||||||
void VerilatedVcd::fullFloat(vluint32_t code, const float newval) {
|
|
||||||
// cppcheck-suppress invalidPointerCast
|
|
||||||
(*(reinterpret_cast<float*>(oldp(code)))) = newval;
|
|
||||||
// Buffer can't overflow before sprintf; we sized during declaration
|
|
||||||
sprintf(m_writep, "r%.16g", static_cast<double>(newval));
|
|
||||||
m_writep += strlen(m_writep);
|
|
||||||
*m_writep++ = ' ';
|
|
||||||
m_writep = writeCode(m_writep, code);
|
|
||||||
*m_writep++ = '\n';
|
|
||||||
bufferCheck();
|
|
||||||
}
|
|
||||||
void VerilatedVcd::fullBitX(vluint32_t code) {
|
|
||||||
*m_writep++ = 'x';
|
|
||||||
m_writep = writeCode(m_writep, code);
|
|
||||||
*m_writep++ = '\n';
|
|
||||||
bufferCheck();
|
|
||||||
}
|
|
||||||
void VerilatedVcd::fullBusX(vluint32_t code, int bits) {
|
|
||||||
*m_writep++ = 'b';
|
|
||||||
for (int bit = bits - 1; bit >= 0; --bit) *m_writep++ = 'x';
|
|
||||||
*m_writep++ = ' ';
|
|
||||||
m_writep = writeCode(m_writep, code);
|
|
||||||
*m_writep++ = '\n';
|
|
||||||
bufferCheck();
|
|
||||||
}
|
|
||||||
void VerilatedVcd::fullQuadX(vluint32_t code, int bits) { fullBusX(code, bits); }
|
|
||||||
void VerilatedVcd::fullArrayX(vluint32_t code, int bits) { fullBusX(code, bits); }
|
|
||||||
|
|
||||||
#endif // VL_TRACE_VCD_OLD_API
|
#endif // VL_TRACE_VCD_OLD_API
|
||||||
|
|
||||||
//======================================================================
|
//======================================================================
|
||||||
// Static members
|
|
||||||
|
|
||||||
void VerilatedVcd::flush_all() VL_MT_UNSAFE_ONE { VerilatedVcdSingleton::flush_all(); }
|
|
||||||
|
|
||||||
//======================================================================
|
//======================================================================
|
||||||
//======================================================================
|
//======================================================================
|
||||||
//======================================================================
|
|
||||||
|
|
||||||
// clang-format off
|
|
||||||
|
|
||||||
#ifdef VERILATED_VCD_TEST
|
#ifdef VERILATED_VCD_TEST
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
extern void verilated_trace_imp_selftest();
|
||||||
|
|
||||||
vluint32_t v1, v2, s1, s2[3];
|
vluint32_t v1, v2, s1, s2[3];
|
||||||
vluint32_t tri96[3];
|
vluint32_t tri96[3];
|
||||||
vluint32_t tri96__tri[3];
|
vluint32_t tri96__tri[3];
|
||||||
vluint64_t quad96[2];
|
vluint64_t quad96[2];
|
||||||
|
vluint64_t tquad;
|
||||||
|
vluint64_t tquad__tri;
|
||||||
vluint8_t ch;
|
vluint8_t ch;
|
||||||
vluint64_t timestamp = 1;
|
vluint64_t timestamp = 1;
|
||||||
double doub = 0;
|
double doub = 0.0;
|
||||||
|
float flo = 0.0f;
|
||||||
|
|
||||||
void vcdInit(VerilatedVcd* vcdp, void* userthis, vluint32_t code) {
|
void vcdInit(void*, VerilatedVcd* vcdp, vluint32_t) {
|
||||||
vcdp->scopeEscape('.');
|
vcdp->scopeEscape('.');
|
||||||
vcdp->module("top");
|
vcdp->module("top");
|
||||||
vcdp->declBus(0x2, "v1",-1,5,1);
|
/**/ vcdp->declBus(0x2, "v1", -1, 0, 5, 1);
|
||||||
vcdp->declBus(0x3, "v2",-1,6,0);
|
/**/ vcdp->declBus(0x3, "v2", -1, 0, 6, 1);
|
||||||
vcdp->module("top.sub1");
|
/**/ vcdp->module("top.sub1");
|
||||||
vcdp->declBit(0x4, "s1",-1);
|
/***/ vcdp->declBit(0x4, "s1", -1, 0);
|
||||||
vcdp->declBit(0x5, "ch",-1);
|
/***/ vcdp->declBit(0x5, "ch", -1, 0);
|
||||||
vcdp->module("top.sub2");
|
/**/ vcdp->module("top.sub2");
|
||||||
vcdp->declArray(0x6, "s2",-1, 40,3);
|
/***/ vcdp->declArray(0x6, "s2", -1, 0, 40, 3);
|
||||||
// Note need to add 3 for next code.
|
// Note need to add 3 for next code.
|
||||||
vcdp->module("top2");
|
vcdp->module("top2");
|
||||||
vcdp->declBus(0x2, "t2v1",-1,4,1);
|
/**/ vcdp->declBus(0x2, "t2v1", -1, 0, 4, 1);
|
||||||
vcdp->declTriBit(0x10, "io1",-1);
|
/**/ vcdp->declTriBit(0x10, "io1", -1, 0);
|
||||||
vcdp->declTriBus(0x12, "io5",-1,4,0);
|
/**/ vcdp->declTriBus(0x12, "io5", -1, 0, 4, 0);
|
||||||
vcdp->declTriArray(0x16, "io96",-1,95,0);
|
/**/ vcdp->declTriArray(0x16, "io96", -1, 0, 95, 0);
|
||||||
// Note need to add 6 for next code.
|
/**/ // Note need to add 6 for next code.
|
||||||
vcdp->declDouble(0x1c, "doub",-1);
|
/**/ vcdp->declDouble(0x1c, "doub", -1, 0);
|
||||||
// Note need to add 2 for next code.
|
/**/ // Note need to add 2 for next code.
|
||||||
vcdp->declArray(0x1e, "q2",-1,95,0);
|
/**/ vcdp->declArray(0x20, "q2", -1, 0, 95, 0);
|
||||||
// Note need to add 4 for next code.
|
/**/ // Note need to add 4 for next code.
|
||||||
|
/**/ vcdp->declTriQuad(0x24, "tq", -1, 0, 63, 0);
|
||||||
|
/**/ // Note need to add 4 for next code.
|
||||||
}
|
}
|
||||||
|
|
||||||
void vcdFull(VerilatedVcd* vcdp, void* userthis, vluint32_t code) {
|
void vcdFull(void*, VerilatedVcd* vcdp) {
|
||||||
vcdp->fullBus(0x2, v1, 5);
|
vcdp->fullBus(0x2, v1, 5);
|
||||||
vcdp->fullBus(0x3, v2, 7);
|
vcdp->fullBus(0x3, v2, 7);
|
||||||
vcdp->fullBit(0x4, s1);
|
vcdp->fullBit(0x4, s1);
|
||||||
@@ -919,10 +825,11 @@ void vcdFull(VerilatedVcd* vcdp, void* userthis, vluint32_t code) {
|
|||||||
vcdp->fullTriBus(0x12, tri96[0] & 0x1f, tri96__tri[0] & 0x1f, 5);
|
vcdp->fullTriBus(0x12, tri96[0] & 0x1f, tri96__tri[0] & 0x1f, 5);
|
||||||
vcdp->fullTriArray(0x16, tri96, tri96__tri, 96);
|
vcdp->fullTriArray(0x16, tri96, tri96__tri, 96);
|
||||||
vcdp->fullDouble(0x1c, doub);
|
vcdp->fullDouble(0x1c, doub);
|
||||||
vcdp->fullArray(0x1e, &quad96[0], 96);
|
vcdp->fullArray(0x20, &quad96[0], 96);
|
||||||
|
vcdp->fullTriQuad(0x24, tquad, tquad__tri, 64);
|
||||||
}
|
}
|
||||||
|
|
||||||
void vcdChange(VerilatedVcd* vcdp, void* userthis, vluint32_t code) {
|
void vcdChange(void*, VerilatedVcd* vcdp) {
|
||||||
vcdp->chgBus(0x2, v1, 5);
|
vcdp->chgBus(0x2, v1, 5);
|
||||||
vcdp->chgBus(0x3, v2, 7);
|
vcdp->chgBus(0x3, v2, 7);
|
||||||
vcdp->chgBit(0x4, s1);
|
vcdp->chgBit(0x4, s1);
|
||||||
@@ -932,11 +839,13 @@ void vcdChange(VerilatedVcd* vcdp, void* userthis, vluint32_t code) {
|
|||||||
vcdp->chgTriBus(0x12, tri96[0] & 0x1f, tri96__tri[0] & 0x1f, 5);
|
vcdp->chgTriBus(0x12, tri96[0] & 0x1f, tri96__tri[0] & 0x1f, 5);
|
||||||
vcdp->chgTriArray(0x16, tri96, tri96__tri, 96);
|
vcdp->chgTriArray(0x16, tri96, tri96__tri, 96);
|
||||||
vcdp->chgDouble(0x1c, doub);
|
vcdp->chgDouble(0x1c, doub);
|
||||||
vcdp->chgArray(0x1e, &quad96[0], 96);
|
vcdp->chgArray(0x20, &quad96[0], 96);
|
||||||
|
vcdp->chgTriQuad(0x24, tquad, tquad__tri, 64);
|
||||||
}
|
}
|
||||||
|
|
||||||
main() {
|
// clang-format off
|
||||||
std::cout << "test: O_LARGEFILE=" << O_LARGEFILE << std::endl;
|
void vcdTestMain(const char* filenamep) {
|
||||||
|
verilated_trace_imp_selftest();
|
||||||
|
|
||||||
v1 = v2 = s1 = 0;
|
v1 = v2 = s1 = 0;
|
||||||
s2[0] = s2[1] = s2[2] = 0;
|
s2[0] = s2[1] = s2[2] = 0;
|
||||||
@@ -945,43 +854,53 @@ main() {
|
|||||||
quad96[1] = quad96[0] = 0;
|
quad96[1] = quad96[0] = 0;
|
||||||
ch = 0;
|
ch = 0;
|
||||||
doub = 0;
|
doub = 0;
|
||||||
|
tquad = tquad__tri = 0;
|
||||||
{
|
{
|
||||||
VerilatedVcdC* vcdp = new VerilatedVcdC;
|
VerilatedVcdC* vcdp = new VerilatedVcdC;
|
||||||
vcdp->spTrace()->addCallback(&vcdInit, &vcdFull, &vcdChange, 0);
|
vcdp->evcd(true);
|
||||||
vcdp->open("test.vcd");
|
vcdp->spTrace()->addInitCb(&vcdInit, 0);
|
||||||
|
vcdp->spTrace()->addFullCb(&vcdFull, 0);
|
||||||
|
vcdp->spTrace()->addChgCb(&vcdChange, 0);
|
||||||
|
vcdp->open(filenamep);
|
||||||
// Dumping
|
// Dumping
|
||||||
vcdp->dump(timestamp++);
|
vcdp->dump(++timestamp);
|
||||||
v1 = 0xfff;
|
v1 = 0xfff;
|
||||||
tri96[2] = 4; tri96[1] = 2; tri96[0] = 1;
|
tri96[2] = 4; tri96[1] = 2; tri96[0] = 1;
|
||||||
tri96__tri[2] = tri96__tri[1] = tri96__tri[0] = ~0; // Still tri
|
tri96__tri[2] = tri96__tri[1] = tri96__tri[0] = ~0; // Still tri
|
||||||
quad96[1] = 0xffffffff; quad96[0] = 0;
|
quad96[1] = 0xffffffff; quad96[0] = 0;
|
||||||
doub = 1.5;
|
doub = 1.5;
|
||||||
vcdp->dump(timestamp++);
|
flo = 1.4f;
|
||||||
|
vcdp->dump(++timestamp);
|
||||||
v2 = 0x1;
|
v2 = 0x1;
|
||||||
s2[1] = 2;
|
s2[1] = 2;
|
||||||
tri96__tri[2] = tri96__tri[1] = tri96__tri[0] = 0; // enable w/o data change
|
tri96__tri[2] = tri96__tri[1] = tri96__tri[0] = 0; // enable w/o data change
|
||||||
quad96[1] = 0; quad96[0] = ~0;
|
quad96[1] = 0; quad96[0] = ~0;
|
||||||
doub = -1.66e13;
|
doub = -1.66e13;
|
||||||
vcdp->dump(timestamp++);
|
flo = 0.123f;
|
||||||
|
tquad = 0x00ff00ff00ff00ffULL;
|
||||||
|
tquad__tri = 0x0000fffff0000ffffULL;
|
||||||
|
vcdp->dump(++timestamp);
|
||||||
ch = 2;
|
ch = 2;
|
||||||
tri96[2] = ~4; tri96[1] = ~2; tri96[0] = ~1;
|
tri96[2] = ~4; tri96[1] = ~2; tri96[0] = ~1;
|
||||||
doub = -3.33e-13;
|
doub = -3.33e-13;
|
||||||
vcdp->dump(timestamp++);
|
vcdp->dump(++timestamp);
|
||||||
vcdp->dump(timestamp++);
|
vcdp->dump(++timestamp);
|
||||||
# ifdef VERILATED_VCD_TEST_64BIT
|
# ifdef VERILATED_VCD_TEST_64BIT
|
||||||
vluint64_t bytesPerDump = VL_ULL(15);
|
vluint64_t bytesPerDump = 15ULL;
|
||||||
for (vluint64_t i = 0; i < ((VL_ULL(1) << 32) / bytesPerDump); i++) {
|
for (vluint64_t i = 0; i < ((1ULL << 32) / bytesPerDump); i++) {
|
||||||
v1 = i;
|
v1 = i;
|
||||||
vcdp->dump(timestamp++);
|
vcdp->dump(++timestamp);
|
||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
vcdp->close();
|
vcdp->close();
|
||||||
|
VL_DO_CLEAR(delete vcdp, vcdp = nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
//********************************************************************
|
//********************************************************************
|
||||||
// ;compile-command: "mkdir -p ../test_dir && cd ../test_dir && c++ -DVERILATED_VCD_TEST ../include/verilated_vcd_c.cpp -o verilated_vcd_c && ./verilated_vcd_c && cat test.vcd"
|
// ;compile-command: "v4make test_regress/t/t_trace_c_api.pl"
|
||||||
//
|
//
|
||||||
// Local Variables:
|
// Local Variables:
|
||||||
// End:
|
// End:
|
||||||
|
|||||||
+35
-52
@@ -3,7 +3,7 @@
|
|||||||
//
|
//
|
||||||
// THIS MODULE IS PUBLICLY LICENSED
|
// THIS MODULE IS PUBLICLY LICENSED
|
||||||
//
|
//
|
||||||
// Copyright 2001-2020 by Wilson Snyder. This program is free software; you
|
// Copyright 2001-2021 by Wilson Snyder. This program is free software; you
|
||||||
// can redistribute it and/or modify it under the terms of either the GNU
|
// can 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.
|
||||||
@@ -34,14 +34,13 @@ class VerilatedVcd;
|
|||||||
// VerilatedFile
|
// VerilatedFile
|
||||||
/// File handling routines, which can be overrode for e.g. socket I/O
|
/// File handling routines, which can be overrode for e.g. socket I/O
|
||||||
|
|
||||||
class VerilatedVcdFile {
|
class VerilatedVcdFile VL_NOT_FINAL {
|
||||||
private:
|
private:
|
||||||
int m_fd; ///< File descriptor we're writing to
|
int m_fd = 0; ///< File descriptor we're writing to
|
||||||
public:
|
public:
|
||||||
// METHODS
|
// METHODS
|
||||||
VerilatedVcdFile()
|
VerilatedVcdFile() = default;
|
||||||
: m_fd(0) {}
|
virtual ~VerilatedVcdFile() = default;
|
||||||
virtual ~VerilatedVcdFile() {}
|
|
||||||
virtual bool open(const std::string& name) VL_MT_UNSAFE;
|
virtual bool open(const std::string& name) VL_MT_UNSAFE;
|
||||||
virtual void close() VL_MT_UNSAFE;
|
virtual void close() VL_MT_UNSAFE;
|
||||||
virtual ssize_t write(const char* bufp, ssize_t len) VL_MT_UNSAFE;
|
virtual ssize_t write(const char* bufp, ssize_t len) VL_MT_UNSAFE;
|
||||||
@@ -52,7 +51,7 @@ public:
|
|||||||
/// Base class to create a Verilator VCD dump
|
/// Base class to create a Verilator VCD dump
|
||||||
/// This is an internally used class - see VerilatedVcdC for what to call from applications
|
/// This is an internally used class - see VerilatedVcdC for what to call from applications
|
||||||
|
|
||||||
class VerilatedVcd : public VerilatedTrace<VerilatedVcd> {
|
class VerilatedVcd VL_NOT_FINAL : public VerilatedTrace<VerilatedVcd> {
|
||||||
private:
|
private:
|
||||||
// Give the superclass access to private bits (to avoid virtual functions)
|
// Give the superclass access to private bits (to avoid virtual functions)
|
||||||
friend class VerilatedTrace<VerilatedVcd>;
|
friend class VerilatedTrace<VerilatedVcd>;
|
||||||
@@ -62,23 +61,23 @@ private:
|
|||||||
|
|
||||||
VerilatedVcdFile* m_filep; ///< File we're writing to
|
VerilatedVcdFile* m_filep; ///< File we're writing to
|
||||||
bool m_fileNewed; ///< m_filep needs destruction
|
bool m_fileNewed; ///< m_filep needs destruction
|
||||||
bool m_isOpen; ///< True indicates open file
|
bool m_isOpen = false; ///< True indicates open file
|
||||||
bool m_evcd; ///< True for evcd format
|
bool m_evcd = false; ///< True for evcd format
|
||||||
std::string m_filename; ///< Filename we're writing to (if open)
|
std::string m_filename; ///< Filename we're writing to (if open)
|
||||||
vluint64_t m_rolloverMB; ///< MB of file size to rollover at
|
vluint64_t m_rolloverMB = 0; ///< MB of file size to rollover at
|
||||||
int m_modDepth; ///< Depth of module hierarchy
|
int m_modDepth = 0; ///< Depth of module hierarchy
|
||||||
|
|
||||||
char* m_wrBufp; ///< Output buffer
|
char* m_wrBufp; ///< Output buffer
|
||||||
char* m_wrFlushp; ///< Output buffer flush trigger location
|
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_wrChunkSize; ///< Output buffer size
|
||||||
vluint64_t m_wroteBytes; ///< Number of bytes written to this file
|
vluint64_t m_wroteBytes = 0; ///< Number of bytes written to this file
|
||||||
|
|
||||||
std::vector<char> m_suffixes; ///< VCD line end string codes + metadata
|
std::vector<char> m_suffixes; ///< VCD line end string codes + metadata
|
||||||
const char* m_suffixesp; ///< Pointer to first element of above
|
const char* m_suffixesp; ///< Pointer to first element of above
|
||||||
|
|
||||||
typedef std::map<std::string, std::string> NameMap;
|
typedef std::map<const std::string, const std::string> NameMap;
|
||||||
NameMap* m_namemapp; ///< List of names for the header
|
NameMap* m_namemapp = nullptr; ///< List of names for the header
|
||||||
|
|
||||||
void bufferResize(vluint64_t minsize);
|
void bufferResize(vluint64_t minsize);
|
||||||
void bufferFlush() VL_MT_UNSAFE_ONE;
|
void bufferFlush() VL_MT_UNSAFE_ONE;
|
||||||
@@ -101,13 +100,10 @@ private:
|
|||||||
|
|
||||||
void dumpHeader();
|
void dumpHeader();
|
||||||
|
|
||||||
char* writeCode(char* writep, vluint32_t code);
|
static char* writeCode(char* writep, vluint32_t code);
|
||||||
|
|
||||||
void finishLine(vluint32_t code, char* writep);
|
void finishLine(vluint32_t code, char* writep);
|
||||||
|
|
||||||
/// Flush any remaining data from all files
|
|
||||||
static void flush_all() VL_MT_UNSAFE_ONE;
|
|
||||||
|
|
||||||
// CONSTRUCTORS
|
// CONSTRUCTORS
|
||||||
VL_UNCOPYABLE(VerilatedVcd);
|
VL_UNCOPYABLE(VerilatedVcd);
|
||||||
|
|
||||||
@@ -116,11 +112,11 @@ protected:
|
|||||||
// Implementation of VerilatedTrace interface
|
// Implementation of VerilatedTrace interface
|
||||||
|
|
||||||
// Implementations of protected virtual methods for VerilatedTrace
|
// Implementations of protected virtual methods for VerilatedTrace
|
||||||
void emitTimeChange(vluint64_t timeui) VL_OVERRIDE;
|
virtual void emitTimeChange(vluint64_t timeui) override;
|
||||||
|
|
||||||
// Hooks called from VerilatedTrace
|
// Hooks called from VerilatedTrace
|
||||||
bool preFullDump() VL_OVERRIDE { return isOpen(); }
|
virtual bool preFullDump() override { return isOpen(); }
|
||||||
bool preChangeDump() VL_OVERRIDE;
|
virtual bool preChangeDump() override;
|
||||||
|
|
||||||
// Implementations of duck-typed methods for VerilatedTrace. These are
|
// Implementations of duck-typed methods for VerilatedTrace. These are
|
||||||
// called from only one place (namely full*) so always inline them.
|
// called from only one place (namely full*) so always inline them.
|
||||||
@@ -130,14 +126,13 @@ protected:
|
|||||||
inline void emitIData(vluint32_t code, IData newval, int bits);
|
inline void emitIData(vluint32_t code, IData newval, int bits);
|
||||||
inline void emitQData(vluint32_t code, QData newval, int bits);
|
inline void emitQData(vluint32_t code, QData newval, int bits);
|
||||||
inline void emitWData(vluint32_t code, const WData* newvalp, int bits);
|
inline void emitWData(vluint32_t code, const WData* newvalp, int bits);
|
||||||
inline void emitFloat(vluint32_t code, float newval);
|
|
||||||
inline void emitDouble(vluint32_t code, double newval);
|
inline void emitDouble(vluint32_t code, double newval);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
//=========================================================================
|
//=========================================================================
|
||||||
// External interface to client code
|
// External interface to client code
|
||||||
|
|
||||||
explicit VerilatedVcd(VerilatedVcdFile* filep = NULL);
|
explicit VerilatedVcd(VerilatedVcdFile* filep = nullptr);
|
||||||
~VerilatedVcd();
|
~VerilatedVcd();
|
||||||
|
|
||||||
// ACCESSORS
|
// ACCESSORS
|
||||||
@@ -163,7 +158,6 @@ public:
|
|||||||
void declBus(vluint32_t code, const char* name, bool array, int arraynum, int msb, int lsb);
|
void declBus(vluint32_t code, const char* name, bool array, int arraynum, int msb, int lsb);
|
||||||
void declQuad(vluint32_t code, const char* name, bool array, int arraynum, int msb, int lsb);
|
void declQuad(vluint32_t code, const char* name, bool array, int arraynum, int msb, int lsb);
|
||||||
void declArray(vluint32_t code, const char* name, bool array, int arraynum, int msb, int lsb);
|
void declArray(vluint32_t code, const char* name, bool array, int arraynum, int msb, int lsb);
|
||||||
void declFloat(vluint32_t code, const char* name, bool array, int arraynum);
|
|
||||||
void declDouble(vluint32_t code, const char* name, bool array, int arraynum);
|
void declDouble(vluint32_t code, const char* name, bool array, int arraynum);
|
||||||
|
|
||||||
#ifdef VL_TRACE_VCD_OLD_API
|
#ifdef VL_TRACE_VCD_OLD_API
|
||||||
@@ -195,7 +189,6 @@ public:
|
|||||||
void fullWData(vluint32_t* oldp, const WData* newvalp, int bits) {
|
void fullWData(vluint32_t* oldp, const WData* newvalp, int bits) {
|
||||||
fullArray(oldp - this->oldp(0), newvalp, bits);
|
fullArray(oldp - this->oldp(0), newvalp, bits);
|
||||||
}
|
}
|
||||||
void fullFloat(vluint32_t* oldp, float newval) { fullFloat(oldp - this->oldp(0), newval); }
|
|
||||||
void fullDouble(vluint32_t* oldp, double newval) { fullDouble(oldp - this->oldp(0), newval); }
|
void fullDouble(vluint32_t* oldp, double newval) { fullDouble(oldp - this->oldp(0), newval); }
|
||||||
|
|
||||||
inline void chgBit(vluint32_t* oldp, CData newval) { chgBit(oldp - this->oldp(0), newval); }
|
inline void chgBit(vluint32_t* oldp, CData newval) { chgBit(oldp - this->oldp(0), newval); }
|
||||||
@@ -214,9 +207,6 @@ public:
|
|||||||
inline void chgWData(vluint32_t* oldp, const WData* newvalp, int bits) {
|
inline void chgWData(vluint32_t* oldp, const WData* newvalp, int bits) {
|
||||||
chgArray(oldp - this->oldp(0), newvalp, bits);
|
chgArray(oldp - this->oldp(0), newvalp, bits);
|
||||||
}
|
}
|
||||||
inline void chgFloat(vluint32_t* oldp, float newval) {
|
|
||||||
chgFloat(oldp - this->oldp(0), newval);
|
|
||||||
}
|
|
||||||
inline void chgDouble(vluint32_t* oldp, double newval) {
|
inline void chgDouble(vluint32_t* oldp, double newval) {
|
||||||
chgDouble(oldp - this->oldp(0), newval);
|
chgDouble(oldp - this->oldp(0), newval);
|
||||||
}
|
}
|
||||||
@@ -230,20 +220,10 @@ public:
|
|||||||
void fullArray(vluint32_t code, const vluint64_t* newvalp, int bits);
|
void fullArray(vluint32_t code, const vluint64_t* newvalp, int bits);
|
||||||
void fullTriBit(vluint32_t code, const vluint32_t newval, const vluint32_t newtri);
|
void fullTriBit(vluint32_t code, const vluint32_t newval, const vluint32_t newtri);
|
||||||
void fullTriBus(vluint32_t code, const vluint32_t newval, const vluint32_t newtri, int bits);
|
void fullTriBus(vluint32_t code, const vluint32_t newval, const vluint32_t newtri, int bits);
|
||||||
void fullTriQuad(vluint32_t code, const vluint64_t newval, const vluint32_t newtri, int bits);
|
void fullTriQuad(vluint32_t code, const vluint64_t newval, const vluint64_t newtri, int bits);
|
||||||
void fullTriArray(vluint32_t code, const vluint32_t* newvalp, const vluint32_t* newtrip,
|
void fullTriArray(vluint32_t code, const vluint32_t* newvalp, const vluint32_t* newtrip,
|
||||||
int bits);
|
int bits);
|
||||||
void fullDouble(vluint32_t code, const double newval);
|
void fullDouble(vluint32_t code, const double newval);
|
||||||
void fullFloat(vluint32_t code, const float newval);
|
|
||||||
|
|
||||||
/// Inside dumping routines, dump one signal as unknowns
|
|
||||||
/// Presently this code doesn't change the oldval vector.
|
|
||||||
/// Thus this is for special standalone applications that after calling
|
|
||||||
/// fullBitX, must when then value goes non-X call fullBit.
|
|
||||||
void fullBitX(vluint32_t code);
|
|
||||||
void fullBusX(vluint32_t code, int bits);
|
|
||||||
void fullQuadX(vluint32_t code, int bits);
|
|
||||||
void fullArrayX(vluint32_t code, int bits);
|
|
||||||
|
|
||||||
/// Inside dumping routines, dump one signal if it has changed.
|
/// Inside dumping routines, dump one signal if it has changed.
|
||||||
/// We do want to inline these to avoid calls when the value did not change.
|
/// We do want to inline these to avoid calls when the value did not change.
|
||||||
@@ -262,7 +242,7 @@ public:
|
|||||||
inline void chgQuad(vluint32_t code, const vluint64_t newval, int bits) {
|
inline void chgQuad(vluint32_t code, const vluint64_t newval, int bits) {
|
||||||
vluint64_t diff = (*(reinterpret_cast<vluint64_t*>(oldp(code)))) ^ newval;
|
vluint64_t diff = (*(reinterpret_cast<vluint64_t*>(oldp(code)))) ^ newval;
|
||||||
if (VL_UNLIKELY(diff)) {
|
if (VL_UNLIKELY(diff)) {
|
||||||
if (VL_UNLIKELY(bits == 64 || (diff & ((VL_ULL(1) << bits) - 1)))) {
|
if (VL_UNLIKELY(bits == 64 || (diff & ((1ULL << bits) - 1)))) {
|
||||||
fullQuad(code, newval, bits);
|
fullQuad(code, newval, bits);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -303,12 +283,12 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
inline void chgTriQuad(vluint32_t code, const vluint64_t newval, const vluint32_t newtri,
|
inline void chgTriQuad(vluint32_t code, const vluint64_t newval, const vluint64_t newtri,
|
||||||
int bits) {
|
int bits) {
|
||||||
vluint64_t diff = (((*(reinterpret_cast<vluint64_t*>(oldp(code)))) ^ newval)
|
vluint64_t diff = (((*(reinterpret_cast<vluint64_t*>(oldp(code)))) ^ newval)
|
||||||
| ((*(reinterpret_cast<vluint64_t*>(oldp(code + 1)))) ^ newtri));
|
| ((*(reinterpret_cast<vluint64_t*>(oldp(code + 1)))) ^ newtri));
|
||||||
if (VL_UNLIKELY(diff)) {
|
if (VL_UNLIKELY(diff)) {
|
||||||
if (VL_UNLIKELY(bits == 64 || (diff & ((VL_ULL(1) << bits) - 1)))) {
|
if (VL_UNLIKELY(bits == 64 || (diff & ((1ULL << bits) - 1)))) {
|
||||||
fullTriQuad(code, newval, newtri, bits);
|
fullTriQuad(code, newval, newtri, bits);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -329,15 +309,9 @@ public:
|
|||||||
fullDouble(code, newval);
|
fullDouble(code, newval);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
inline void chgFloat(vluint32_t code, const float newval) {
|
|
||||||
// cppcheck-suppress invalidPointerCast
|
|
||||||
if (VL_UNLIKELY((*(reinterpret_cast<float*>(oldp(code)))) != newval)) {
|
|
||||||
fullFloat(code, newval);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
// METHODS
|
// METHODS
|
||||||
|
// Old/standalone API only
|
||||||
void evcd(bool flag) { m_evcd = flag; }
|
void evcd(bool flag) { m_evcd = flag; }
|
||||||
#endif // VL_TRACE_VCD_OLD_API
|
#endif // VL_TRACE_VCD_OLD_API
|
||||||
};
|
};
|
||||||
@@ -355,15 +329,15 @@ template <> void VerilatedTrace<VerilatedVcd>::set_time_resolution(const std::st
|
|||||||
/// Also derived for use in SystemC simulations.
|
/// Also derived for use in SystemC simulations.
|
||||||
/// Thread safety: Unless otherwise indicated, every function is VL_MT_UNSAFE_ONE
|
/// Thread safety: Unless otherwise indicated, every function is VL_MT_UNSAFE_ONE
|
||||||
|
|
||||||
class VerilatedVcdC {
|
class VerilatedVcdC VL_NOT_FINAL {
|
||||||
VerilatedVcd m_sptrace; ///< Trace file being created
|
VerilatedVcd m_sptrace; ///< Trace file being created
|
||||||
|
|
||||||
// CONSTRUCTORS
|
// CONSTRUCTORS
|
||||||
VL_UNCOPYABLE(VerilatedVcdC);
|
VL_UNCOPYABLE(VerilatedVcdC);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit VerilatedVcdC(VerilatedVcdFile* filep = NULL)
|
explicit VerilatedVcdC(VerilatedVcdFile* filep = nullptr)
|
||||||
: m_sptrace(filep) {}
|
: m_sptrace{filep} {}
|
||||||
~VerilatedVcdC() { close(); }
|
~VerilatedVcdC() { close(); }
|
||||||
/// Routines can only be called from one thread; allow next call from different thread
|
/// Routines can only be called from one thread; allow next call from different thread
|
||||||
void changeThread() { spTrace()->changeThread(); }
|
void changeThread() { spTrace()->changeThread(); }
|
||||||
@@ -405,6 +379,15 @@ public:
|
|||||||
|
|
||||||
/// Internal class access
|
/// Internal class access
|
||||||
inline VerilatedVcd* spTrace() { return &m_sptrace; }
|
inline VerilatedVcd* spTrace() { return &m_sptrace; }
|
||||||
|
|
||||||
|
#ifdef VL_TRACE_VCD_OLD_API
|
||||||
|
//=========================================================================
|
||||||
|
// Note: These are only for testing for backward compatibility with foreign
|
||||||
|
// code and is not used by Verilator. Do not use these as there is no
|
||||||
|
// guarantee of functionality.
|
||||||
|
/// Use evcd format
|
||||||
|
void evcd(bool flag) VL_MT_UNSAFE_ONE { m_sptrace.evcd(flag); }
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // guard
|
#endif // guard
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
//
|
//
|
||||||
// THIS MODULE IS PUBLICLY LICENSED
|
// THIS MODULE IS PUBLICLY LICENSED
|
||||||
//
|
//
|
||||||
// Copyright 2001-2020 by Wilson Snyder. This program is free software; you
|
// Copyright 2001-2021 by Wilson Snyder. This program is free software; you
|
||||||
// can redistribute it and/or modify it under the terms of either the GNU
|
// can 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,22 +25,21 @@
|
|||||||
//======================================================================
|
//======================================================================
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
#if (SYSTEMC_VERSION >= 20050714)
|
|
||||||
// SystemC 2.1.v1
|
// SystemC 2.1.v1
|
||||||
// cppcheck-suppress unusedFunction
|
// cppcheck-suppress unusedFunction
|
||||||
void VerilatedVcdSc::write_comment(const std::string&) {}
|
void VerilatedVcdSc::write_comment(const std::string&) {}
|
||||||
void VerilatedVcdSc::trace(const unsigned int&, const std::string&, const char**) {}
|
void VerilatedVcdSc::trace(const unsigned int&, const std::string&, const char**) {}
|
||||||
|
|
||||||
// clang-format off
|
#define DECL_TRACE_METHOD_A(tp) \
|
||||||
# define DECL_TRACE_METHOD_A(tp) \
|
|
||||||
void VerilatedVcdSc::trace(const tp& object, const std::string& name) {}
|
void VerilatedVcdSc::trace(const tp& object, const std::string& name) {}
|
||||||
# define DECL_TRACE_METHOD_B(tp) \
|
#define DECL_TRACE_METHOD_B(tp) \
|
||||||
void VerilatedVcdSc::trace(const tp& object, const std::string& name, int width) {}
|
void VerilatedVcdSc::trace(const tp& object, const std::string& name, int width) {}
|
||||||
|
|
||||||
# if (SYSTEMC_VERSION >= 20171012)
|
// clang-format off
|
||||||
|
#if (SYSTEMC_VERSION >= 20171012)
|
||||||
DECL_TRACE_METHOD_A( sc_event )
|
DECL_TRACE_METHOD_A( sc_event )
|
||||||
DECL_TRACE_METHOD_A( sc_time )
|
DECL_TRACE_METHOD_A( sc_time )
|
||||||
# endif
|
#endif
|
||||||
|
|
||||||
DECL_TRACE_METHOD_A( bool )
|
DECL_TRACE_METHOD_A( bool )
|
||||||
DECL_TRACE_METHOD_A( sc_dt::sc_bit )
|
DECL_TRACE_METHOD_A( sc_dt::sc_bit )
|
||||||
@@ -50,9 +49,9 @@ void VerilatedVcdSc::trace(const unsigned int&, const std::string&, const char**
|
|||||||
DECL_TRACE_METHOD_B( unsigned short )
|
DECL_TRACE_METHOD_B( unsigned short )
|
||||||
DECL_TRACE_METHOD_B( unsigned int )
|
DECL_TRACE_METHOD_B( unsigned int )
|
||||||
DECL_TRACE_METHOD_B( unsigned long )
|
DECL_TRACE_METHOD_B( unsigned long )
|
||||||
# ifdef SYSTEMC_64BIT_PATCHES
|
#ifdef SYSTEMC_64BIT_PATCHES
|
||||||
DECL_TRACE_METHOD_B( unsigned long long)
|
DECL_TRACE_METHOD_B( unsigned long long)
|
||||||
# endif
|
#endif
|
||||||
DECL_TRACE_METHOD_B( char )
|
DECL_TRACE_METHOD_B( char )
|
||||||
DECL_TRACE_METHOD_B( short )
|
DECL_TRACE_METHOD_B( short )
|
||||||
DECL_TRACE_METHOD_B( int )
|
DECL_TRACE_METHOD_B( int )
|
||||||
@@ -76,92 +75,6 @@ void VerilatedVcdSc::trace(const unsigned int&, const std::string&, const char**
|
|||||||
DECL_TRACE_METHOD_A( sc_dt::sc_lv_base )
|
DECL_TRACE_METHOD_A( sc_dt::sc_lv_base )
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
//--------------------------------------------------
|
|
||||||
#elif (SYSTEMC_VERSION > 20011000)
|
|
||||||
// SystemC 2.0.1
|
|
||||||
// cppcheck-suppress unusedFunction
|
|
||||||
void VerilatedVcdSc::write_comment(const sc_string&) {}
|
|
||||||
void VerilatedVcdSc::trace(const unsigned int&, const sc_string&, const char**) {}
|
|
||||||
|
|
||||||
#define DECL_TRACE_METHOD_A(tp) \
|
|
||||||
void VerilatedVcdSc::trace(const tp& object, const sc_string& name) {}
|
|
||||||
#define DECL_TRACE_METHOD_B(tp) \
|
|
||||||
void VerilatedVcdSc::trace(const tp& object, const sc_string& name, int width) {}
|
|
||||||
|
|
||||||
// clang-format off
|
|
||||||
DECL_TRACE_METHOD_A( bool )
|
|
||||||
DECL_TRACE_METHOD_A( sc_bit )
|
|
||||||
DECL_TRACE_METHOD_A( sc_logic )
|
|
||||||
DECL_TRACE_METHOD_B( unsigned char )
|
|
||||||
DECL_TRACE_METHOD_B( unsigned short )
|
|
||||||
DECL_TRACE_METHOD_B( unsigned int )
|
|
||||||
DECL_TRACE_METHOD_B( unsigned long )
|
|
||||||
#ifdef SYSTEMC_64BIT_PATCHES
|
|
||||||
DECL_TRACE_METHOD_B( unsigned long long)
|
|
||||||
#endif
|
|
||||||
#if (SYSTEMC_VERSION > 20041000)
|
|
||||||
DECL_TRACE_METHOD_B( unsigned long long)
|
|
||||||
DECL_TRACE_METHOD_B( long long)
|
|
||||||
#endif
|
|
||||||
DECL_TRACE_METHOD_B( char )
|
|
||||||
DECL_TRACE_METHOD_B( short )
|
|
||||||
DECL_TRACE_METHOD_B( int )
|
|
||||||
DECL_TRACE_METHOD_B( long )
|
|
||||||
DECL_TRACE_METHOD_A( float )
|
|
||||||
DECL_TRACE_METHOD_A( double )
|
|
||||||
DECL_TRACE_METHOD_A( sc_int_base )
|
|
||||||
DECL_TRACE_METHOD_A( sc_uint_base )
|
|
||||||
DECL_TRACE_METHOD_A( sc_signed )
|
|
||||||
DECL_TRACE_METHOD_A( sc_unsigned )
|
|
||||||
DECL_TRACE_METHOD_A( sc_fxval )
|
|
||||||
DECL_TRACE_METHOD_A( sc_fxval_fast )
|
|
||||||
DECL_TRACE_METHOD_A( sc_fxnum )
|
|
||||||
DECL_TRACE_METHOD_A( sc_fxnum_fast )
|
|
||||||
DECL_TRACE_METHOD_A( sc_bv_base )
|
|
||||||
DECL_TRACE_METHOD_A( sc_lv_base )
|
|
||||||
// clang-format on
|
|
||||||
|
|
||||||
//--------------------------------------------------
|
|
||||||
#else
|
|
||||||
// SystemC 1.2.1beta
|
|
||||||
// cppcheck-suppress unusedFunction
|
|
||||||
void VerilatedVcdSc::write_comment(const sc_string&) {}
|
|
||||||
void VerilatedVcdSc::trace(const unsigned int&, const sc_string&, const char**) {}
|
|
||||||
|
|
||||||
#define DECL_TRACE_METHOD_A(tp) \
|
|
||||||
void VerilatedVcdSc::trace(const tp& object, const sc_string& name) {}
|
|
||||||
#define DECL_TRACE_METHOD_B(tp) \
|
|
||||||
void VerilatedVcdSc::trace(const tp& object, const sc_string& name, int width) {}
|
|
||||||
|
|
||||||
// clang-format off
|
|
||||||
DECL_TRACE_METHOD_A( bool )
|
|
||||||
DECL_TRACE_METHOD_B( unsigned char )
|
|
||||||
DECL_TRACE_METHOD_B( short unsigned int )
|
|
||||||
DECL_TRACE_METHOD_B( unsigned int )
|
|
||||||
DECL_TRACE_METHOD_B( long unsigned int )
|
|
||||||
DECL_TRACE_METHOD_B( char )
|
|
||||||
DECL_TRACE_METHOD_B( short int )
|
|
||||||
DECL_TRACE_METHOD_B( int )
|
|
||||||
DECL_TRACE_METHOD_B( long int )
|
|
||||||
DECL_TRACE_METHOD_A( float )
|
|
||||||
DECL_TRACE_METHOD_A( double )
|
|
||||||
DECL_TRACE_METHOD_A( sc_bit )
|
|
||||||
DECL_TRACE_METHOD_A( sc_logic )
|
|
||||||
DECL_TRACE_METHOD_A( sc_bool_vector )
|
|
||||||
DECL_TRACE_METHOD_A( sc_logic_vector )
|
|
||||||
DECL_TRACE_METHOD_A( sc_signal_bool_vector )
|
|
||||||
DECL_TRACE_METHOD_A( sc_signal_logic_vector )
|
|
||||||
DECL_TRACE_METHOD_A( sc_uint_base )
|
|
||||||
DECL_TRACE_METHOD_A( sc_int_base )
|
|
||||||
DECL_TRACE_METHOD_A( sc_unsigned )
|
|
||||||
DECL_TRACE_METHOD_A( sc_signed )
|
|
||||||
DECL_TRACE_METHOD_A( sc_signal_resolved )
|
|
||||||
DECL_TRACE_METHOD_A( sc_signal_resolved_vector )
|
|
||||||
DECL_TRACE_METHOD_A( sc_bv_ns::sc_bv_base )
|
|
||||||
DECL_TRACE_METHOD_A( sc_bv_ns::sc_lv_base )
|
|
||||||
// clang-format on
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#undef DECL_TRACE_METHOD_A
|
#undef DECL_TRACE_METHOD_A
|
||||||
#undef DECL_TRACE_METHOD_B
|
#undef DECL_TRACE_METHOD_B
|
||||||
|
|
||||||
|
|||||||
+11
-111
@@ -1,7 +1,7 @@
|
|||||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
//
|
//
|
||||||
// Copyright 2001-2020 by Wilson Snyder. This program is free software; you can
|
// Copyright 2001-2021 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// 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,14 +31,13 @@
|
|||||||
/// This class is passed to the SystemC simulation kernel, just like a
|
/// This class is passed to the SystemC simulation kernel, just like a
|
||||||
/// documented SystemC trace format.
|
/// documented SystemC trace format.
|
||||||
|
|
||||||
class VerilatedVcdSc : sc_trace_file, public VerilatedVcdC {
|
class VerilatedVcdSc final : sc_trace_file, public VerilatedVcdC {
|
||||||
// CONSTRUCTORS
|
// CONSTRUCTORS
|
||||||
VL_UNCOPYABLE(VerilatedVcdSc);
|
VL_UNCOPYABLE(VerilatedVcdSc);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
VerilatedVcdSc() {
|
VerilatedVcdSc() {
|
||||||
sc_get_curr_simcontext()->add_trace_file(this);
|
sc_get_curr_simcontext()->add_trace_file(this);
|
||||||
#if (SYSTEMC_VERSION >= 20060505)
|
|
||||||
// We want to avoid a depreciated warning, but still be back compatible.
|
// We want to avoid a depreciated warning, but still be back compatible.
|
||||||
// Turning off the message just for this still results in an
|
// Turning off the message just for this still results in an
|
||||||
// annoying "to turn off" message.
|
// annoying "to turn off" message.
|
||||||
@@ -48,25 +47,13 @@ public:
|
|||||||
spTrace()->set_time_unit(tunits.to_string());
|
spTrace()->set_time_unit(tunits.to_string());
|
||||||
}
|
}
|
||||||
spTrace()->set_time_resolution(sc_get_time_resolution().to_string());
|
spTrace()->set_time_resolution(sc_get_time_resolution().to_string());
|
||||||
#elif (SYSTEMC_VERSION > 20011000)
|
|
||||||
// To confuse matters 2.1.beta returns a char* here, while 2.1.v1 returns a std::string
|
|
||||||
// we allow both flavors with overloaded set_time_* functions.
|
|
||||||
spTrace()->set_time_unit(sc_get_default_time_unit().to_string());
|
|
||||||
spTrace()->set_time_resolution(sc_get_time_resolution().to_string());
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
virtual ~VerilatedVcdSc() { close(); }
|
virtual ~VerilatedVcdSc() { close(); }
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
/// Called by SystemC simulate()
|
/// Called by SystemC simulate()
|
||||||
virtual void cycle(bool delta_cycle) {
|
virtual void cycle(bool delta_cycle) {
|
||||||
#if (SYSTEMC_VERSION > 20011000)
|
|
||||||
if (!delta_cycle) { this->dump(sc_time_stamp().to_double()); }
|
if (!delta_cycle) { this->dump(sc_time_stamp().to_double()); }
|
||||||
#else
|
|
||||||
// VCD files must have integer timestamps, so we write all times in
|
|
||||||
// increments of time_resolution
|
|
||||||
if (!delta_cycle) { this->dump(sc_time_stamp().to_double()); }
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -76,26 +63,23 @@ private:
|
|||||||
// 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
|
#endif
|
||||||
#if defined(NC_SYSTEMC) || (SYSTEMC_VERSION >= 20111100)
|
virtual void set_time_unit(double v, sc_time_unit tu) {} // LCOV_EXCL_LINE
|
||||||
virtual void set_time_unit(double v, sc_time_unit tu) {}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
#if (SYSTEMC_VERSION >= 20050714)
|
// SystemC 2.1.v1
|
||||||
// SystemC 2.1.v1
|
#define DECL_TRACE_METHOD_A(tp) virtual void trace(const tp& object, const std::string& name);
|
||||||
// clang-format off
|
#define DECL_TRACE_METHOD_B(tp) \
|
||||||
# define DECL_TRACE_METHOD_A(tp) virtual void trace(const tp& object, const std::string& name);
|
|
||||||
# define DECL_TRACE_METHOD_B(tp) \
|
|
||||||
virtual void trace(const tp& object, const std::string& name, int width);
|
virtual void trace(const tp& object, const std::string& name, int width);
|
||||||
|
|
||||||
virtual void write_comment(const std::string&);
|
virtual void write_comment(const std::string&);
|
||||||
virtual void trace(const unsigned int&, const std::string&, const char**);
|
virtual void trace(const unsigned int&, const std::string&, const char**);
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
// Formatting matches that of sc_trace.h
|
// Formatting matches that of sc_trace.h
|
||||||
# if (SYSTEMC_VERSION >= 20171012)
|
#if (SYSTEMC_VERSION >= 20171012)
|
||||||
DECL_TRACE_METHOD_A( sc_event )
|
DECL_TRACE_METHOD_A( sc_event )
|
||||||
DECL_TRACE_METHOD_A( sc_time )
|
DECL_TRACE_METHOD_A( sc_time )
|
||||||
# endif
|
#endif
|
||||||
|
|
||||||
DECL_TRACE_METHOD_A( bool )
|
DECL_TRACE_METHOD_A( bool )
|
||||||
DECL_TRACE_METHOD_A( sc_dt::sc_bit )
|
DECL_TRACE_METHOD_A( sc_dt::sc_bit )
|
||||||
@@ -105,9 +89,9 @@ private:
|
|||||||
DECL_TRACE_METHOD_B( unsigned short )
|
DECL_TRACE_METHOD_B( unsigned short )
|
||||||
DECL_TRACE_METHOD_B( unsigned int )
|
DECL_TRACE_METHOD_B( unsigned int )
|
||||||
DECL_TRACE_METHOD_B( unsigned long )
|
DECL_TRACE_METHOD_B( unsigned long )
|
||||||
# ifdef SYSTEMC_64BIT_PATCHES
|
#ifdef SYSTEMC_64BIT_PATCHES
|
||||||
DECL_TRACE_METHOD_B( unsigned long long)
|
DECL_TRACE_METHOD_B( unsigned long long)
|
||||||
# endif
|
#endif
|
||||||
DECL_TRACE_METHOD_B( char )
|
DECL_TRACE_METHOD_B( char )
|
||||||
DECL_TRACE_METHOD_B( short )
|
DECL_TRACE_METHOD_B( short )
|
||||||
DECL_TRACE_METHOD_B( int )
|
DECL_TRACE_METHOD_B( int )
|
||||||
@@ -131,90 +115,6 @@ private:
|
|||||||
DECL_TRACE_METHOD_A( sc_dt::sc_lv_base )
|
DECL_TRACE_METHOD_A( sc_dt::sc_lv_base )
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
//--------------------------------------------------
|
|
||||||
#elif (SYSTEMC_VERSION > 20011000)
|
|
||||||
// SystemC 2.0.1
|
|
||||||
// clang-format off
|
|
||||||
# define DECL_TRACE_METHOD_A(tp) virtual void trace(const tp& object, const sc_string& name);
|
|
||||||
# define DECL_TRACE_METHOD_B(tp) \
|
|
||||||
virtual void trace(const tp& object, const sc_string& name, int width);
|
|
||||||
|
|
||||||
virtual void write_comment(const sc_string&);
|
|
||||||
virtual void trace(const unsigned int&, const sc_string&, const char**);
|
|
||||||
virtual void delta_cycles(bool) {}
|
|
||||||
virtual void space(int n) {}
|
|
||||||
|
|
||||||
DECL_TRACE_METHOD_A( bool )
|
|
||||||
DECL_TRACE_METHOD_A( sc_bit )
|
|
||||||
DECL_TRACE_METHOD_A( sc_logic )
|
|
||||||
DECL_TRACE_METHOD_B( unsigned char )
|
|
||||||
DECL_TRACE_METHOD_B( unsigned short )
|
|
||||||
DECL_TRACE_METHOD_B( unsigned int )
|
|
||||||
DECL_TRACE_METHOD_B( unsigned long )
|
|
||||||
# ifdef SYSTEMC_64BIT_PATCHES
|
|
||||||
DECL_TRACE_METHOD_B( unsigned long long)
|
|
||||||
# endif
|
|
||||||
# if (SYSTEMC_VERSION > 20041000)
|
|
||||||
DECL_TRACE_METHOD_B( unsigned long long)
|
|
||||||
DECL_TRACE_METHOD_B( long long)
|
|
||||||
# endif
|
|
||||||
DECL_TRACE_METHOD_B( char )
|
|
||||||
DECL_TRACE_METHOD_B( short )
|
|
||||||
DECL_TRACE_METHOD_B( int )
|
|
||||||
DECL_TRACE_METHOD_B( long )
|
|
||||||
DECL_TRACE_METHOD_A( float )
|
|
||||||
DECL_TRACE_METHOD_A( double )
|
|
||||||
DECL_TRACE_METHOD_A( sc_int_base )
|
|
||||||
DECL_TRACE_METHOD_A( sc_uint_base )
|
|
||||||
DECL_TRACE_METHOD_A( sc_signed )
|
|
||||||
DECL_TRACE_METHOD_A( sc_unsigned )
|
|
||||||
DECL_TRACE_METHOD_A( sc_fxval )
|
|
||||||
DECL_TRACE_METHOD_A( sc_fxval_fast )
|
|
||||||
DECL_TRACE_METHOD_A( sc_fxnum )
|
|
||||||
DECL_TRACE_METHOD_A( sc_fxnum_fast )
|
|
||||||
DECL_TRACE_METHOD_A( sc_bv_base )
|
|
||||||
DECL_TRACE_METHOD_A( sc_lv_base )
|
|
||||||
// clang-format on
|
|
||||||
|
|
||||||
//--------------------------------------------------
|
|
||||||
#else
|
|
||||||
// SystemC 1.2.1beta
|
|
||||||
// clang-format off
|
|
||||||
# define DECL_TRACE_METHOD_A(tp) virtual void trace(const tp& object, const sc_string& name);
|
|
||||||
# define DECL_TRACE_METHOD_B(tp) \
|
|
||||||
virtual void trace(const tp& object, const sc_string& name, int width);
|
|
||||||
|
|
||||||
virtual void write_comment(const sc_string&);
|
|
||||||
virtual void trace(const unsigned int&, const sc_string&, const char**);
|
|
||||||
|
|
||||||
DECL_TRACE_METHOD_A( bool )
|
|
||||||
DECL_TRACE_METHOD_B( unsigned char )
|
|
||||||
DECL_TRACE_METHOD_B( short unsigned int )
|
|
||||||
DECL_TRACE_METHOD_B( unsigned int )
|
|
||||||
DECL_TRACE_METHOD_B( long unsigned int )
|
|
||||||
DECL_TRACE_METHOD_B( char )
|
|
||||||
DECL_TRACE_METHOD_B( short int )
|
|
||||||
DECL_TRACE_METHOD_B( int )
|
|
||||||
DECL_TRACE_METHOD_B( long int )
|
|
||||||
DECL_TRACE_METHOD_A( float )
|
|
||||||
DECL_TRACE_METHOD_A( double )
|
|
||||||
DECL_TRACE_METHOD_A( sc_bit )
|
|
||||||
DECL_TRACE_METHOD_A( sc_logic )
|
|
||||||
DECL_TRACE_METHOD_A( sc_bool_vector )
|
|
||||||
DECL_TRACE_METHOD_A( sc_logic_vector )
|
|
||||||
DECL_TRACE_METHOD_A( sc_signal_bool_vector )
|
|
||||||
DECL_TRACE_METHOD_A( sc_signal_logic_vector )
|
|
||||||
DECL_TRACE_METHOD_A( sc_uint_base )
|
|
||||||
DECL_TRACE_METHOD_A( sc_int_base )
|
|
||||||
DECL_TRACE_METHOD_A( sc_unsigned )
|
|
||||||
DECL_TRACE_METHOD_A( sc_signed )
|
|
||||||
DECL_TRACE_METHOD_A( sc_signal_resolved )
|
|
||||||
DECL_TRACE_METHOD_A( sc_signal_resolved_vector )
|
|
||||||
DECL_TRACE_METHOD_A( sc_bv_ns::sc_bv_base )
|
|
||||||
DECL_TRACE_METHOD_A( sc_bv_ns::sc_lv_base )
|
|
||||||
# endif
|
|
||||||
// clang-format on
|
|
||||||
|
|
||||||
#undef DECL_TRACE_METHOD_A
|
#undef DECL_TRACE_METHOD_A
|
||||||
#undef DECL_TRACE_METHOD_B
|
#undef DECL_TRACE_METHOD_B
|
||||||
};
|
};
|
||||||
|
|||||||
+924
-832
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user