mirror of
https://github.com/steveicarus/iverilog.git
synced 2026-08-23 22:36:54 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4fd5291632 | ||
|
|
ba370285f3 | ||
|
|
8ecb1ab15c | ||
|
|
ce20e9f769 | ||
|
|
5347ba19cf | ||
|
|
295b65da2c | ||
|
|
15fa24a664 | ||
|
|
c0adbd0deb | ||
|
|
7188f7b210 | ||
|
|
862b118098 | ||
|
|
cc2ba4f8cb | ||
|
|
7b1fad78c3 | ||
|
|
507d8cc8ab | ||
|
|
0271602260 | ||
|
|
6b04d9795a | ||
|
|
82aedbc36c | ||
|
|
bb867480fc | ||
|
|
3335138d16 | ||
|
|
2e27b4393d | ||
|
|
a56ccabf7f | ||
|
|
6334839406 | ||
|
|
df82410a37 | ||
|
|
748d6d8de2 | ||
|
|
da4ac3607a | ||
|
|
3302ced608 | ||
|
|
54a4e7ff0b | ||
|
|
580d79eae3 | ||
|
|
01378fbdb0 | ||
|
|
32f66511e0 | ||
|
|
7914f8ad9d | ||
|
|
968f0d943e | ||
|
|
cd0b360575 | ||
|
|
79a3d08d69 | ||
|
|
52f269649a | ||
|
|
0dc64b99f3 | ||
|
|
59d70cad45 | ||
|
|
46e1a21d7b | ||
|
|
9d2244abb4 | ||
|
|
deb4ff4ca8 | ||
|
|
03f912dc55 | ||
|
|
c8a85877c2 | ||
|
|
4ef5b02bcd | ||
|
|
5ec72f4cc8 | ||
|
|
4cfba91d65 | ||
|
|
9b68c5776b | ||
|
|
269e1ca88d | ||
|
|
0e62ff153d | ||
|
|
54956f0f29 | ||
|
|
2d6243ea6c | ||
|
|
dd7bea1d5e | ||
|
|
70e2ff0bd5 | ||
|
|
a8dbb38af2 | ||
|
|
3c4d1bbe4e | ||
|
|
fa4c67ccf7 | ||
|
|
d426e80c73 | ||
|
|
abc26eeaeb | ||
|
|
569ba887b3 | ||
|
|
e0ec2ed386 | ||
|
|
2a15489e9d | ||
|
|
673193d508 | ||
|
|
c4397e66f9 | ||
|
|
c9e7aecf1d | ||
|
|
79771b17b2 | ||
|
|
4e69fe1355 | ||
|
|
2bb1489f92 | ||
|
|
15b4a8a046 | ||
|
|
4ead552203 | ||
|
|
0acb938f79 | ||
|
|
5b9ceee062 | ||
|
|
bb779112c7 | ||
|
|
afe2cd63ef | ||
|
|
78f37f7156 | ||
|
|
1e84e78cd6 | ||
|
|
fbfb6016c1 | ||
|
|
68d89bbe05 | ||
|
|
b4b591adba | ||
|
|
0e86e99358 | ||
|
|
e141aef828 | ||
|
|
f8401095aa | ||
|
|
eaea5e7939 | ||
|
|
aec1ee5a42 | ||
|
|
5ef847ea87 | ||
|
|
3509cc86f8 | ||
|
|
1434936aaa | ||
|
|
e97b7c4c56 | ||
|
|
bdafdb1e65 | ||
|
|
06c819849f | ||
|
|
10e35d1573 | ||
|
|
3787eca248 | ||
|
|
cdc9629ce7 | ||
|
|
699ceb15a5 | ||
|
|
8ee9d6b5ea | ||
|
|
2e0d6d5af1 | ||
|
|
3bea115c51 | ||
|
|
fdc7b0e1bd | ||
|
|
9553a872da | ||
|
|
410c8207ef | ||
|
|
3438078c90 | ||
|
|
a5a078ae08 | ||
|
|
fc2d9372ef | ||
|
|
9e37f4382e | ||
|
|
d97c1bc6db | ||
|
|
1e3994e1fa | ||
|
|
74c52d6fa1 | ||
|
|
b18d90a2d9 | ||
|
|
c2dbf4e483 | ||
|
|
0c8c642022 | ||
|
|
5a98e50db7 | ||
|
|
01a11cce56 | ||
|
|
b9bc06951a | ||
|
|
998d0c655d | ||
|
|
54afdc1e6b | ||
|
|
b7fce4a66e | ||
|
|
20d82bbdcb | ||
|
|
0a2cbcb4b7 | ||
|
|
4522709c06 | ||
|
|
9107e298a3 | ||
|
|
85edd8bb18 | ||
|
|
10a39e59a1 | ||
|
|
b0c262de80 | ||
|
|
8bbddfb69f | ||
|
|
90538e4193 | ||
|
|
31eab5b528 | ||
|
|
6c975eb89c | ||
|
|
7896349380 | ||
|
|
e897e3ab5f | ||
|
|
5fa1aecd4f | ||
|
|
d4765e3354 | ||
|
|
f831d7d76f | ||
|
|
070fc2aedc | ||
|
|
e7d3e7440d | ||
|
|
0aef9326ca | ||
|
|
46951c778e | ||
|
|
159345ca96 | ||
|
|
8d7e7b6283 | ||
|
|
3b711ed785 | ||
|
|
4f1dbee4ee | ||
|
|
b83fc0ac59 | ||
|
|
463f18a03f | ||
|
|
7c52d239db | ||
|
|
4c0b06329f | ||
|
|
b19a6a7518 | ||
|
|
bcc0730b6b | ||
|
|
69b108f661 | ||
|
|
6fe3e52085 | ||
|
|
fb8681a376 | ||
|
|
f9aadc13b5 | ||
|
|
2385b32cb3 | ||
|
|
72e59fc626 | ||
|
|
567df9c29a | ||
|
|
d4c662c6a1 | ||
|
|
1fd968773e | ||
|
|
fd69d4e09c | ||
|
|
6ea7763c31 | ||
|
|
a2aa659717 | ||
|
|
b0b0b84815 | ||
|
|
0d180ae465 | ||
|
|
8abb59022b | ||
|
|
d6912fb504 | ||
|
|
cff24f77b4 | ||
|
|
832917008c | ||
|
|
e799a09605 | ||
|
|
d6337a5bc5 | ||
|
|
8f78590bd2 | ||
|
|
b307da0831 | ||
|
|
c5ebe35953 | ||
|
|
d3be19081f | ||
|
|
62b1f44104 | ||
|
|
b5699d1260 | ||
|
|
c8daebef48 | ||
|
|
2acf7aded5 | ||
|
|
b0d328d594 | ||
|
|
521a7bea61 | ||
|
|
6204b78610 | ||
|
|
7fbfd82d51 | ||
|
|
20f4f31c1a | ||
|
|
b1bafe5e02 | ||
|
|
fa0217af87 | ||
|
|
5a774a9cab | ||
|
|
55a5ba3d5a | ||
|
|
6a1bf00490 | ||
|
|
f1e50e927b | ||
|
|
b69eff2ab1 | ||
|
|
dba6798d12 | ||
|
|
16fc3102b3 | ||
|
|
ea0588a7fd | ||
|
|
76047fd83a | ||
|
|
6e4a1ac15e | ||
|
|
a19a07254b | ||
|
|
a9bd522fd3 | ||
|
|
dd4ae93942 | ||
|
|
8315b82f40 | ||
|
|
a73ee3e3e7 | ||
|
|
f881baeef1 | ||
|
|
9ffe627b32 | ||
|
|
d753e6a5d0 | ||
|
|
134e7d6f08 | ||
|
|
8b0346d7b5 | ||
|
|
246a0d3ce8 | ||
|
|
0f7703e9c6 | ||
|
|
f253655e25 | ||
|
|
899d459233 | ||
|
|
310e239637 | ||
|
|
c7cdc6c230 | ||
|
|
2ceb90b95e | ||
|
|
542da11669 | ||
|
|
05a0622154 | ||
|
|
e3a9591960 | ||
|
|
e80746c50f | ||
|
|
e818a2f331 | ||
|
|
5a90b7857a | ||
|
|
c7cb13d302 | ||
|
|
5e8eb5e67d | ||
|
|
608c18699e | ||
|
|
1603df47d0 | ||
|
|
c286d1c418 | ||
|
|
93397e7234 | ||
|
|
dbd92bd3cd | ||
|
|
2346cc8b69 | ||
|
|
9a50956f5e | ||
|
|
ce9f3d5e59 | ||
|
|
eab37efb56 | ||
|
|
2693dd32b0 | ||
|
|
2bc1385a59 | ||
|
|
c3c7f6d9ee | ||
|
|
e5abd4bf82 | ||
|
|
68f75dce61 | ||
|
|
ebd574474c | ||
|
|
34876c8854 | ||
|
|
ec75c1aa74 | ||
|
|
ab95d1d903 | ||
|
|
5fb2d9158d | ||
|
|
07378fd300 | ||
|
|
86cc6e6159 | ||
|
|
781089662c | ||
|
|
e8cc9f3721 | ||
|
|
bf4bee319d | ||
|
|
e4d2b05976 | ||
|
|
2032e14f5a | ||
|
|
5ae7425fdb | ||
|
|
a4eeea75ce | ||
|
|
61549165cf | ||
|
|
d3573334d6 | ||
|
|
8fb38d7046 | ||
|
|
12188f8d83 | ||
|
|
d651aefd92 | ||
|
|
d746c592b2 | ||
|
|
e8bc3bf8dd | ||
|
|
6564f55219 | ||
|
|
6176f8eec3 | ||
|
|
5d97405724 | ||
|
|
73f40f73b0 | ||
|
|
c2c758369d | ||
|
|
e263d5b268 | ||
|
|
2abfef68ff | ||
|
|
b83ebf3c8e | ||
|
|
4c8903f117 | ||
|
|
e4372c8eda | ||
|
|
a1485906ca | ||
|
|
b83daa3ae3 | ||
|
|
abc3ad95e6 | ||
|
|
e15b125da8 | ||
|
|
278e071b35 | ||
|
|
e67a796a77 | ||
|
|
e076400449 | ||
|
|
508564b79f | ||
|
|
5a616bcaf4 | ||
|
|
37392383b5 | ||
|
|
37f9cde49f | ||
|
|
ef009e7200 | ||
|
|
1eb22b7e14 | ||
|
|
0a86773c5e | ||
|
|
64cc04f6d8 | ||
|
|
58ac6ed1f8 | ||
|
|
eeed05d9cd | ||
|
|
dddc41891e | ||
|
|
e7b700f48e | ||
|
|
7e67b8b11b | ||
|
|
dc203a20ba | ||
|
|
4679c722e3 | ||
|
|
3a3f7fc623 | ||
|
|
5d316c1fd9 | ||
|
|
da21c62f29 | ||
|
|
227cf20684 | ||
|
|
9d37878aa7 | ||
|
|
854422a3eb | ||
|
|
bd94c72472 | ||
|
|
5da2951c12 | ||
|
|
bdf581edd0 | ||
|
|
d4e862dc4e | ||
|
|
254e9dc094 | ||
|
|
135c664adf | ||
|
|
e815d37c25 | ||
|
|
818dfa55f3 | ||
|
|
f42ab248a4 | ||
|
|
724d7d4282 | ||
|
|
66a5cfe660 | ||
|
|
bd9f1b406e | ||
|
|
bf521c7eec | ||
|
|
fe4891a77d | ||
|
|
a3c329ae84 | ||
|
|
5b8fb089bf | ||
|
|
f19ba64614 | ||
|
|
ff8a44b025 | ||
|
|
52da910313 | ||
|
|
7aee124cfe | ||
|
|
393c7a3b49 | ||
|
|
27f3fcc5f1 | ||
|
|
c853025305 | ||
|
|
bcae0304a3 | ||
|
|
dda960dce4 | ||
|
|
b11da7e16f | ||
|
|
72b0498af4 | ||
|
|
e7d4fd6fee | ||
|
|
3166973f59 | ||
|
|
b2516ead66 | ||
|
|
0dc8596a89 | ||
|
|
031fbac5be | ||
|
|
0c123b8498 | ||
|
|
3a26bbb59a | ||
|
|
22cba1073c | ||
|
|
2f38adaeff | ||
|
|
156f08a1c5 | ||
|
|
8de2e60d26 | ||
|
|
752a28598b | ||
|
|
760ecfc44f | ||
|
|
083671cc4b | ||
|
|
d53e4dff2f | ||
|
|
48f486ef83 | ||
|
|
a4a60ec07b | ||
|
|
27b09f5d72 | ||
|
|
2781aa05e1 | ||
|
|
4ae2eec275 | ||
|
|
1bf568d808 | ||
|
|
4d0f005a10 | ||
|
|
6f0d3ae332 | ||
|
|
6b5d7a3695 | ||
|
|
313f376394 | ||
|
|
ea55421a07 | ||
|
|
f95f9955c8 | ||
|
|
f3c4967085 | ||
|
|
53fd42f3da | ||
|
|
5f2e4bf581 | ||
|
|
338516bc55 | ||
|
|
5b6d8e968d | ||
|
|
84c3c72563 | ||
|
|
ca919b3ce0 | ||
|
|
2f091c8f45 | ||
|
|
7c5694e516 | ||
|
|
3da5b4cf65 | ||
|
|
070b8af63c | ||
|
|
99eaf007a1 | ||
|
|
50ae8cf552 | ||
|
|
82caccd4eb | ||
|
|
35c69366a5 | ||
|
|
8f6a9c5d3c | ||
|
|
42de9e646a | ||
|
|
94e09ec473 | ||
|
|
4c9af1c47a | ||
|
|
f6042033d0 | ||
|
|
de9e3b791b | ||
|
|
571f222a73 | ||
|
|
51eae02e78 | ||
|
|
da5b9a4e5f | ||
|
|
e3bc99dbf3 | ||
|
|
967e3455fe | ||
|
|
9810ce6e60 | ||
|
|
ad9f5a3aa6 | ||
|
|
1a95dafc8d | ||
|
|
c96a6bfa09 | ||
|
|
d480c4d7d0 | ||
|
|
658d4f5eee | ||
|
|
4f971ea4f9 | ||
|
|
7dcde37475 | ||
|
|
8a19380a5d | ||
|
|
673b0d3066 | ||
|
|
315bc1908a | ||
|
|
4bf0d62cd1 | ||
|
|
4c36b2a8a7 | ||
|
|
3c58ca908d | ||
|
|
2bf753fd8f | ||
|
|
252174d15a | ||
|
|
b30d3fc8d7 | ||
|
|
23e1143ad6 | ||
|
|
86a7707482 | ||
|
|
af7c3043d8 | ||
|
|
abe5e692ce | ||
|
|
eed38bd14a | ||
|
|
583a7ddc35 | ||
|
|
b3f7ce6020 | ||
|
|
2c505f0040 | ||
|
|
fc80465b87 | ||
|
|
f73af99ce7 | ||
|
|
1de38dde12 | ||
|
|
af09d86113 | ||
|
|
83da384df3 | ||
|
|
fabff5ef5f | ||
|
|
b7f948193a | ||
|
|
c5e160f1dd | ||
|
|
aaffceff42 | ||
|
|
e53b2e774b | ||
|
|
59b3e220ad | ||
|
|
a4eb971655 | ||
|
|
aa7e253026 | ||
|
|
962c0af1b6 | ||
|
|
db33dbfbcc | ||
|
|
ee81ac2f85 | ||
|
|
53284b95af | ||
|
|
831db5a0d7 | ||
|
|
7f4013ac66 | ||
|
|
15e1a7a3f2 | ||
|
|
5bc1c08c67 | ||
|
|
d7e4d209b8 | ||
|
|
6c4a676bc1 | ||
|
|
77afa1774c | ||
|
|
a9c0469b2b | ||
|
|
026d552be1 | ||
|
|
0328fc5a6f | ||
|
|
56f36a96d3 | ||
|
|
3906d043b9 | ||
|
|
1a10abeae7 | ||
|
|
babfacee9a | ||
|
|
5cc825f45d | ||
|
|
61a088fa78 | ||
|
|
32d1f385f8 | ||
|
|
9fd91a8df8 | ||
|
|
3939126625 | ||
|
|
51d7cecce1 | ||
|
|
ede341410f | ||
|
|
88bddb6308 | ||
|
|
d2ac403415 | ||
|
|
679a6567e9 | ||
|
|
41b4ce5f8c | ||
|
|
b207ebd51a | ||
|
|
167005f849 | ||
|
|
98a87b49c8 | ||
|
|
8e25be99f9 | ||
|
|
8a2d4e4fa4 | ||
|
|
2921e66105 | ||
|
|
f67cdddecf | ||
|
|
472598dd74 | ||
|
|
73f4f4aef7 | ||
|
|
027c4828ea | ||
|
|
fbc91ec7cf | ||
|
|
e6bab92274 | ||
|
|
f30801e782 | ||
|
|
24b64365a6 | ||
|
|
fa864156e4 | ||
|
|
5b65a583a1 | ||
|
|
e0eed7146f | ||
|
|
035325e9df | ||
|
|
807fb2e5d1 | ||
|
|
f53a95840a | ||
|
|
046893d97f | ||
|
|
bbe44deec2 | ||
|
|
28bbebf98c | ||
|
|
70637db4d3 | ||
|
|
47b4621da1 | ||
|
|
85a4869ac3 | ||
|
|
de579f2650 | ||
|
|
978717f914 | ||
|
|
83f1ea60b7 | ||
|
|
cf5fb30c21 | ||
|
|
5f71307ab4 | ||
|
|
372e3eae25 | ||
|
|
b0c386182a | ||
|
|
c631ff2483 | ||
|
|
2e845821a8 | ||
|
|
d104e28dbf | ||
|
|
427091d3d3 | ||
|
|
ad23b08a10 | ||
|
|
892622bf64 | ||
|
|
aa905a27cf | ||
|
|
cc0a8c8dd2 | ||
|
|
afaaaed0a4 | ||
|
|
21c769e1e1 | ||
|
|
ce8ee42619 | ||
|
|
f6394c5fe6 | ||
|
|
9da057ceb1 | ||
|
|
6708c0f6df | ||
|
|
a5e9358d42 | ||
|
|
47b6ee714d | ||
|
|
b37636e4fc | ||
|
|
6730ead119 | ||
|
|
bb74c6412d | ||
|
|
673b40b78c | ||
|
|
96a1cbf7b2 | ||
|
|
a4d7c3f94e | ||
|
|
560129f0c6 | ||
|
|
6c04749a68 | ||
|
|
27d81bc610 | ||
|
|
3f048f266a | ||
|
|
91579c7c79 | ||
|
|
4a87bee3c0 | ||
|
|
b1fb4a6117 | ||
|
|
13aa782be2 | ||
|
|
310fe6c4de | ||
|
|
ef42df6fef | ||
|
|
c4feb89957 | ||
|
|
c76db2867c | ||
|
|
481f461e59 | ||
|
|
497c98bf9b | ||
|
|
30ff2aa5d1 | ||
|
|
7f40e120c8 | ||
|
|
89e935c210 | ||
|
|
618959d147 | ||
|
|
771d02bee1 | ||
|
|
bb36a16704 | ||
|
|
a7a154047a | ||
|
|
47e6c71113 | ||
|
|
9a94e6b43b | ||
|
|
9f5ad34e35 | ||
|
|
1207e908b1 | ||
|
|
42dd8a0703 | ||
|
|
6a61144937 | ||
|
|
4bebcad6fd | ||
|
|
305a1a9262 | ||
|
|
e950e2d0d3 | ||
|
|
7e18eba848 | ||
|
|
bc0fc4ab89 | ||
|
|
4a9200f5f2 | ||
|
|
f2c1e21ad3 | ||
|
|
922a2e0e13 | ||
|
|
8b4abd3228 | ||
|
|
04bff70a17 | ||
|
|
687abbd030 | ||
|
|
6db40d9f14 | ||
|
|
dd0a4c9a5e | ||
|
|
880f4927bf | ||
|
|
0ab1ed916f | ||
|
|
f25d7a74bc | ||
|
|
1549fd4332 | ||
|
|
0b30894f81 | ||
|
|
ac040dae42 | ||
|
|
30c169026e | ||
|
|
1c0955178d | ||
|
|
662e82c013 | ||
|
|
2477f79f52 | ||
|
|
fa643cbfe1 | ||
|
|
057cd700fe | ||
|
|
ac815a6118 | ||
|
|
32f01f87a6 | ||
|
|
8502f3bd85 | ||
|
|
67b29ab5d4 | ||
|
|
30b70923b5 | ||
|
|
ad6131b1c4 | ||
|
|
e75ad281fc | ||
|
|
9898bffd41 | ||
|
|
5fc1976496 | ||
|
|
1858c6a313 | ||
|
|
053453c645 | ||
|
|
9b7c99b8a8 | ||
|
|
25dae60bb6 | ||
|
|
be06e293f6 | ||
|
|
7c73ef8fb6 | ||
|
|
d0b9c11d35 | ||
|
|
f5f07d52b0 | ||
|
|
e176ce0776 | ||
|
|
09ac7c207e | ||
|
|
f1c543194c | ||
|
|
38c4c20cbc | ||
|
|
c670170ac0 | ||
|
|
3ca1c129ce | ||
|
|
ae954e5df7 | ||
|
|
6222a84d67 | ||
|
|
d856a35e4d | ||
|
|
9e6f651e09 | ||
|
|
74b433c083 | ||
|
|
bedc68707e | ||
|
|
3e5f9fd044 | ||
|
|
5bfc8a42eb | ||
|
|
8b1240f7cf | ||
|
|
cea237b407 | ||
|
|
279b2665af | ||
|
|
db72a1d769 | ||
|
|
d0223e6ed9 | ||
|
|
9ec42b1b8c | ||
|
|
3176611771 | ||
|
|
90edf48ac6 | ||
|
|
ea1bf7577a | ||
|
|
adf64f3cc8 | ||
|
|
52925ce9ff | ||
|
|
f705e7b61c | ||
|
|
f98e7d1a70 | ||
|
|
57cfbc0cea | ||
|
|
b86d7c8284 | ||
|
|
3481d48d18 | ||
|
|
18cc3b91a1 | ||
|
|
957e3d482f | ||
|
|
d4334139d3 | ||
|
|
a6e71f30d6 | ||
|
|
9bcee6c2c8 | ||
|
|
2fa7260a4c | ||
|
|
6c60851558 | ||
|
|
668f9850bc | ||
|
|
e1d6fd78f4 | ||
|
|
67b9374c69 | ||
|
|
71c36d1289 | ||
|
|
61aed6882c | ||
|
|
3c23180af3 | ||
|
|
c6ef2ba809 | ||
|
|
dcc9b59f6d | ||
|
|
dbf55da0f5 | ||
|
|
0e3682a127 | ||
|
|
9cc09b8513 | ||
|
|
23390c1ba3 | ||
|
|
ecbbb60fb6 | ||
|
|
19e44d79ec | ||
|
|
4c4b09947f | ||
|
|
829d361b17 | ||
|
|
3dda39bce3 | ||
|
|
e3c2234893 | ||
|
|
ef01dd1e81 | ||
|
|
7ee7a48310 | ||
|
|
cefcffecda | ||
|
|
a17557575d | ||
|
|
7445b424f1 | ||
|
|
ceb2581368 | ||
|
|
c34167b2c0 | ||
|
|
389e2a3a94 | ||
|
|
83d9b5deda | ||
|
|
e547a8355d | ||
|
|
b9863b4fde | ||
|
|
3b1b611a18 | ||
|
|
061121203b | ||
|
|
6b127432da | ||
|
|
c07a6ec8fd | ||
|
|
eb5b04626d | ||
|
|
31e3155426 | ||
|
|
bb2c51a174 | ||
|
|
1f8876be1c | ||
|
|
711623f682 | ||
|
|
a040ddc070 | ||
|
|
1341dee0e6 | ||
|
|
cf0bf4d9aa | ||
|
|
a7cb93842e | ||
|
|
d2521878d7 | ||
|
|
7d7aa0604c | ||
|
|
4af830187e | ||
|
|
7c024d6cab | ||
|
|
3167b2ed24 | ||
|
|
d8cb29f6e0 | ||
|
|
9a2c43ec34 | ||
|
|
45db0db8b3 | ||
|
|
c7eaa06a2b | ||
|
|
60a77b08d2 | ||
|
|
753bf516d6 | ||
|
|
18e7406dd0 | ||
|
|
2cc41a4639 | ||
|
|
7bb8a4463f | ||
|
|
5530fbac9f | ||
|
|
18392a464d | ||
|
|
8484ff71ac | ||
|
|
a73357ec72 | ||
|
|
a446c34d10 | ||
|
|
0c12344b27 | ||
|
|
31a68fcd8a | ||
|
|
9e3d6cc996 | ||
|
|
348bc13a21 | ||
|
|
56d2d798ec | ||
|
|
0cfbb8afeb | ||
|
|
f8e82448be | ||
|
|
7e40f5ac52 | ||
|
|
956f6ccf4c | ||
|
|
21c5fbe759 | ||
|
|
d1eb4befcc | ||
|
|
a19caf4fe6 | ||
|
|
9b432ba172 | ||
|
|
287ba56ab4 | ||
|
|
38b3c8efb2 | ||
|
|
e02410d519 | ||
|
|
7dc65af362 | ||
|
|
308c744e98 | ||
|
|
9eb77116b9 | ||
|
|
5f281d5f21 | ||
|
|
85e8cc6c5f | ||
|
|
c978d28c09 | ||
|
|
dbd63450d9 | ||
|
|
555a2e703a | ||
|
|
501586431b | ||
|
|
1bffc649cb | ||
|
|
9d3de84cd1 | ||
|
|
5442f3fee7 | ||
|
|
89eabdfa35 | ||
|
|
32787bb973 | ||
|
|
8f908a213d | ||
|
|
4efbfa3e8f | ||
|
|
57e87149e8 | ||
|
|
ba25b55f53 | ||
|
|
9fa9a9d95a | ||
|
|
aae3a570c2 | ||
|
|
da7484eea1 | ||
|
|
7299625ab5 | ||
|
|
e0313cecbd | ||
|
|
a56747b747 | ||
|
|
fbe42f13e2 | ||
|
|
1d318c4393 | ||
|
|
51a171a399 | ||
|
|
2e4bf05e21 | ||
|
|
4b3e1099e5 | ||
|
|
66c5d8cc20 | ||
|
|
053777f16d | ||
|
|
82a6e93c56 | ||
|
|
540555fca3 | ||
|
|
248aeeef66 | ||
|
|
99cb22fce0 | ||
|
|
407627f4e6 | ||
|
|
c335c68973 | ||
|
|
c943484b39 | ||
|
|
852d627de4 | ||
|
|
752401b88c | ||
|
|
2799db3912 | ||
|
|
eaa3a10e8c | ||
|
|
b7306001ab | ||
|
|
e633fcc199 | ||
|
|
6b53df9d1f | ||
|
|
1ce86a97ac | ||
|
|
34d7be092e | ||
|
|
f4c79f5629 | ||
|
|
04bd450acb | ||
|
|
a286764c1d | ||
|
|
16646c547c | ||
|
|
51025149a9 | ||
|
|
5edecab41f | ||
|
|
cf53584733 | ||
|
|
5ca947ea8a | ||
|
|
a019994513 | ||
|
|
71843a66f8 | ||
|
|
6c3abb44c6 | ||
|
|
fe79f130b5 | ||
|
|
0a429dba99 | ||
|
|
7f2ee99ebd | ||
|
|
a1dd6bb056 | ||
|
|
b7b7280794 | ||
|
|
05a4e72b1a | ||
|
|
16a45e06fb | ||
|
|
bfd22c373f | ||
|
|
e589d6f59a | ||
|
|
e5f68d7c89 | ||
|
|
f4d22af4bd | ||
|
|
f8c49469fa | ||
|
|
fbd87b4fee | ||
|
|
393236a9a8 | ||
|
|
94b503fc64 | ||
|
|
1bb355a95e | ||
|
|
96df23c5f9 | ||
|
|
0d6a2f95a8 | ||
|
|
48db632a03 | ||
|
|
af9f02472f | ||
|
|
dbe15b6a46 | ||
|
|
ae5be2b61f | ||
|
|
360d1ca447 | ||
|
|
3f9a49ae01 | ||
|
|
df72e1d362 | ||
|
|
cd7c3fdc4c | ||
|
|
17ef6d65e1 | ||
|
|
5e1dbb1624 | ||
|
|
efdf4a8a8a | ||
|
|
e30cbee332 | ||
|
|
0fdffe624d | ||
|
|
ed27dbf608 | ||
|
|
eca41e411e | ||
|
|
59e117ddcc | ||
|
|
2f86923c71 | ||
|
|
7419875e2f | ||
|
|
08ec099091 | ||
|
|
7a729f3ff8 | ||
|
|
bbd09ce87c | ||
|
|
5c76ce3923 | ||
|
|
8da8261fc3 | ||
|
|
8f736c7df7 | ||
|
|
b1484a97e2 | ||
|
|
11f4e71dd0 | ||
|
|
c37f1c9309 | ||
|
|
b7dec18088 | ||
|
|
8bb856f29d | ||
|
|
65b4c17451 | ||
|
|
f4aff860e7 | ||
|
|
0d20bf2123 | ||
|
|
de4e19ceea | ||
|
|
b8ea1e5cfe | ||
|
|
bda74bcd56 | ||
|
|
b2cca8fbec | ||
|
|
d18e280b1b | ||
|
|
9b7afd2146 | ||
|
|
a79b55ae28 | ||
|
|
a7ce4ec110 | ||
|
|
1b4244474c | ||
|
|
038f52b924 | ||
|
|
22bfa7b584 | ||
|
|
99bb0d15b2 | ||
|
|
2dcbfca5d9 | ||
|
|
dee68faf80 | ||
|
|
3c2fb6a601 | ||
|
|
159af4d4ba | ||
|
|
b0b44fdd8a | ||
|
|
55e06db693 | ||
|
|
7277f4e807 | ||
|
|
919fd22a79 | ||
|
|
156644d91e | ||
|
|
292d174cad | ||
|
|
b14a623eef | ||
|
|
1b3f0dd689 | ||
|
|
0fada92389 | ||
|
|
ad862020bb | ||
|
|
d209e7533a | ||
|
|
d6e01d0c55 | ||
|
|
359b2b65c2 | ||
|
|
6566072741 | ||
|
|
8f8737198c | ||
|
|
4e79c1c861 | ||
|
|
6880b39770 | ||
|
|
c4883da334 |
Executable
+14
@@ -0,0 +1,14 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
echo "Using the bundled ivtest to run regression tests."
|
||||
echo " pwd = $(pwd)"
|
||||
|
||||
cd ivtest
|
||||
|
||||
status=0
|
||||
|
||||
perl vvp_reg.pl || status=1
|
||||
|
||||
perl vpi_reg.pl || status=1
|
||||
|
||||
exit $status
|
||||
@@ -0,0 +1,36 @@
|
||||
|
||||
name: Deploy documentation
|
||||
|
||||
on:
|
||||
# Every push onto the main branch regerenates the documentation
|
||||
push:
|
||||
branches:
|
||||
- 'master'
|
||||
|
||||
jobs:
|
||||
|
||||
do-deploy:
|
||||
runs-on: ubuntu-latest
|
||||
name: 'Build documentation on Linux'
|
||||
steps:
|
||||
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt update -qq
|
||||
sudo apt install -y make autoconf python3-sphinx
|
||||
|
||||
- name: Make Documentation
|
||||
run: |
|
||||
cd Documentation
|
||||
make html
|
||||
|
||||
- name: Deploy to GitHub Pages
|
||||
uses: crazy-max/ghaction-github-pages@v2
|
||||
with:
|
||||
target_branch: gh-pages
|
||||
build_dir: Documentation/_build/html
|
||||
jekyll: false
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -0,0 +1,119 @@
|
||||
name: test
|
||||
|
||||
on:
|
||||
# Every push onto the main branch and releases triggers a retest.
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- v12-branch
|
||||
# All pull_requests trigger a retest.
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
|
||||
mac:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
runs-on: macos-latest
|
||||
name: '🍏 macOS'
|
||||
steps:
|
||||
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
brew install bison
|
||||
|
||||
- name: Build, check and install
|
||||
run: |
|
||||
export PATH="/usr/local/opt/bison/bin:$PATH"
|
||||
autoconf
|
||||
./configure
|
||||
make check
|
||||
sudo make install
|
||||
|
||||
- name: Test
|
||||
run: ./.github/test.sh
|
||||
|
||||
|
||||
lin:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [
|
||||
'20.04',
|
||||
'22.04'
|
||||
]
|
||||
runs-on: ubuntu-${{ matrix.os }}
|
||||
name: '🐧 Ubuntu ${{ matrix.os }}'
|
||||
steps:
|
||||
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt update -qq
|
||||
sudo apt install -y make g++ git bison flex gperf libreadline-dev autoconf python3-sphinx
|
||||
|
||||
- name: Build, check and install
|
||||
run: |
|
||||
autoconf
|
||||
./configure
|
||||
make check
|
||||
sudo make install
|
||||
|
||||
- name: Test
|
||||
run: ./.github/test.sh
|
||||
|
||||
- name: Documentation
|
||||
run: |
|
||||
cd Documentation
|
||||
make html
|
||||
|
||||
win:
|
||||
runs-on: windows-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include: [
|
||||
{ msystem: MINGW64, arch: x86_64 },
|
||||
{ msystem: MINGW32, arch: i686 }
|
||||
]
|
||||
name: 🟪 ${{ matrix.msystem}} · ${{ matrix.arch }}
|
||||
defaults:
|
||||
run:
|
||||
shell: msys2 {0}
|
||||
env:
|
||||
MINGW_ARCH: ${{ matrix.msystem }}
|
||||
steps:
|
||||
|
||||
- run: git config --global core.autocrlf input
|
||||
shell: bash
|
||||
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
msystem: ${{ matrix.msystem }}
|
||||
update: true
|
||||
install: >
|
||||
git
|
||||
base-devel
|
||||
gperf
|
||||
mingw-w64-${{ matrix.arch }}-toolchain
|
||||
|
||||
- name: Build and check
|
||||
run: |
|
||||
cd msys2
|
||||
makepkg-mingw --noconfirm --noprogressbar -sCLf
|
||||
|
||||
- name: Install
|
||||
run: pacman -U --noconfirm msys2/*.zst
|
||||
|
||||
- name: Test
|
||||
run: ./.github/test.sh
|
||||
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: ${{ matrix.msystem }}-${{ matrix.arch }}
|
||||
path: msys2/*.zst
|
||||
-71
@@ -1,71 +0,0 @@
|
||||
language: cpp
|
||||
sudo: required
|
||||
dist: xenial
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- gperf
|
||||
|
||||
sudo: false
|
||||
|
||||
notifications:
|
||||
email: false
|
||||
|
||||
jobs:
|
||||
include:
|
||||
|
||||
- stage: Test
|
||||
os: linux
|
||||
dist: xenial
|
||||
before_install:
|
||||
- git clone https://github.com/steveicarus/ivtest.git
|
||||
- export PATH=$HOME/bin:$PATH
|
||||
script:
|
||||
- autoconf
|
||||
- ./configure --prefix=$HOME
|
||||
- make install
|
||||
- make check
|
||||
- cd ivtest
|
||||
- perl vvp_reg.pl
|
||||
- diff regression_report-devel.txt regression_report.txt
|
||||
- perl vpi_reg.pl
|
||||
|
||||
- stage: Test
|
||||
os: linux
|
||||
dist: bionic
|
||||
before_install:
|
||||
- git clone https://github.com/steveicarus/ivtest.git
|
||||
- export PATH=$HOME/bin:$PATH
|
||||
script:
|
||||
- autoconf
|
||||
- ./configure --prefix=$HOME
|
||||
- make install
|
||||
- make check
|
||||
- cd ivtest
|
||||
- perl vvp_reg.pl
|
||||
- diff regression_report-devel.txt regression_report.txt
|
||||
- perl vpi_reg.pl
|
||||
|
||||
- stage: Test
|
||||
os: windows
|
||||
before_install:
|
||||
- git clone https://github.com/steveicarus/ivtest.git
|
||||
- choco uninstall -y mingw
|
||||
- choco upgrade --no-progress -y msys2
|
||||
- export msys2='cmd //C RefreshEnv.cmd '
|
||||
- export msys2+='& set MSYS=winsymlinks:nativestrict '
|
||||
- export msys2+='& C:\\tools\\msys64\\msys2_shell.cmd -defterm -no-start'
|
||||
- export mingw64="$msys2 -mingw64 -full-path -here -c "\"\$@"\" --"
|
||||
- export msys2+=" -msys2 -c "\"\$@"\" --"
|
||||
- $msys2 pacman --sync --noconfirm --needed base-devel mingw-w64-x86_64-toolchain
|
||||
script:
|
||||
- $mingw64 ./autoconf.sh
|
||||
- $mingw64 ./configure
|
||||
- $mingw64 make install
|
||||
- $mingw64 make check
|
||||
- cd ivtest
|
||||
- $mingw64 perl update_msys2_report.pl
|
||||
- $mingw64 perl vvp_reg.pl
|
||||
- diff --strip-trailing-cr regression_report-msys2.txt regression_report.txt
|
||||
- $mingw64 perl vpi_reg.pl
|
||||
+4
-4
@@ -1,7 +1,7 @@
|
||||
#ifndef IVL_AStatement_H
|
||||
#define IVL_AStatement_H
|
||||
/*
|
||||
* Copyright (c) 2008-2014 Stephen Williams ([email protected])
|
||||
* Copyright (c) 2008-2021 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -42,7 +42,7 @@ class AContrib : public Statement {
|
||||
AContrib(PExpr*lval, PExpr*rval);
|
||||
~AContrib();
|
||||
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual void dump(std::ostream&out, unsigned ind) const;
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
|
||||
private:
|
||||
@@ -68,10 +68,10 @@ class AProcess : public LineInfo {
|
||||
ivl_process_type_t type() const { return type_; }
|
||||
Statement*statement() { return statement_; }
|
||||
|
||||
map<perm_string,PExpr*> attributes;
|
||||
std::map<perm_string,PExpr*> attributes;
|
||||
|
||||
// Dump the analog process
|
||||
void dump(ostream&out, unsigned ind) const;
|
||||
void dump(std::ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
ivl_process_type_t type_;
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
_build/
|
||||
!Makefile
|
||||
@@ -0,0 +1,20 @@
|
||||
# Minimal makefile for Sphinx documentation
|
||||
#
|
||||
|
||||
# You can set these variables from the command line.
|
||||
SPHINXOPTS =
|
||||
SPHINXBUILD = sphinx-build
|
||||
SPHINXPROJ = IcarusVerilog
|
||||
SOURCEDIR = .
|
||||
BUILDDIR = _build
|
||||
|
||||
# Put it first so that "make" without argument is like "make help".
|
||||
help:
|
||||
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
|
||||
.PHONY: help Makefile
|
||||
|
||||
# Catch-all target: route all unknown targets to Sphinx using the new
|
||||
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
|
||||
%: Makefile
|
||||
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
@@ -0,0 +1,155 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Configuration file for the Sphinx documentation builder.
|
||||
#
|
||||
# This file does only contain a selection of the most common options. For a
|
||||
# full list see the documentation:
|
||||
# http://www.sphinx-doc.org/en/master/config
|
||||
|
||||
# -- Path setup --------------------------------------------------------------
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
#
|
||||
# import os
|
||||
# import sys
|
||||
# sys.path.insert(0, os.path.abspath('.'))
|
||||
|
||||
|
||||
# -- Project information -----------------------------------------------------
|
||||
|
||||
project = 'Icarus Verilog'
|
||||
copyright = '2022, Stephen Williams'
|
||||
author = 'Stephen Williams'
|
||||
|
||||
# The short X.Y version
|
||||
version = ''
|
||||
# The full version, including alpha/beta/rc tags
|
||||
release = ''
|
||||
|
||||
|
||||
# -- General configuration ---------------------------------------------------
|
||||
|
||||
# If your documentation needs a minimal Sphinx version, state it here.
|
||||
#
|
||||
# needs_sphinx = '1.0'
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
# ones.
|
||||
extensions = [
|
||||
]
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
|
||||
# The suffix(es) of source filenames.
|
||||
# You can specify multiple suffix as a list of string:
|
||||
#
|
||||
# source_suffix = ['.rst', '.md']
|
||||
source_suffix = '.rst'
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = 'index'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
#
|
||||
# This is also used if you do content translation via gettext catalogs.
|
||||
# Usually you set "language" from the command line for these cases.
|
||||
language = None
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
# This pattern also affects html_static_path and html_extra_path .
|
||||
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
|
||||
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = 'sphinx'
|
||||
|
||||
|
||||
# -- Options for HTML output -------------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
#
|
||||
html_theme = 'alabaster'
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
# documentation.
|
||||
#
|
||||
# html_theme_options = {}
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ['_static']
|
||||
|
||||
# Custom sidebar templates, must be a dictionary that maps document names
|
||||
# to template names.
|
||||
#
|
||||
# The default sidebars (for documents that don't match any pattern) are
|
||||
# defined by theme itself. Builtin themes are using these templates by
|
||||
# default: ``['localtoc.html', 'relations.html', 'sourcelink.html',
|
||||
# 'searchbox.html']``.
|
||||
#
|
||||
# html_sidebars = {}
|
||||
|
||||
|
||||
# -- Options for HTMLHelp output ---------------------------------------------
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = 'IcarusVerilogdoc'
|
||||
|
||||
|
||||
# -- Options for LaTeX output ------------------------------------------------
|
||||
|
||||
latex_elements = {
|
||||
# The paper size ('letterpaper' or 'a4paper').
|
||||
#
|
||||
# 'papersize': 'letterpaper',
|
||||
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
#
|
||||
# 'pointsize': '10pt',
|
||||
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#
|
||||
# 'preamble': '',
|
||||
|
||||
# Latex figure (float) alignment
|
||||
#
|
||||
# 'figure_align': 'htbp',
|
||||
}
|
||||
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title,
|
||||
# author, documentclass [howto, manual, or own class]).
|
||||
latex_documents = [
|
||||
(master_doc, 'IcarusVerilog.tex', 'Icarus Verilog Documentation',
|
||||
'Stephen Williams', 'manual'),
|
||||
]
|
||||
|
||||
|
||||
# -- Options for manual page output ------------------------------------------
|
||||
|
||||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
man_pages = [
|
||||
(master_doc, 'icarusverilog', 'Icarus Verilog Documentation',
|
||||
[author], 1)
|
||||
]
|
||||
|
||||
|
||||
# -- Options for Texinfo output ----------------------------------------------
|
||||
|
||||
# Grouping the document tree into Texinfo files. List of tuples
|
||||
# (source start file, target name, title, author,
|
||||
# dir menu entry, description, category)
|
||||
texinfo_documents = [
|
||||
(master_doc, 'IcarusVerilog', 'Icarus Verilog Documentation',
|
||||
author, 'IcarusVerilog', 'One line description of project.',
|
||||
'Miscellaneous'),
|
||||
]
|
||||
@@ -0,0 +1,225 @@
|
||||
|
||||
Getting Started as a Contributer
|
||||
================================
|
||||
|
||||
Icarus Verilog development is centered around the github repository at
|
||||
`github.com/steveicarus/iverilog <http://github.com/steveicarus/iverilog>`_.
|
||||
Contributing to Icarus Verilog requires a basic knowledge of git and github,
|
||||
so see the github documentation for more information. The sections below will
|
||||
step you through the basics of getting the source code from github, making a
|
||||
branch, and submitting a pull request for review.
|
||||
|
||||
Getting Icarus Verilog
|
||||
----------------------
|
||||
|
||||
To start, you will need to clone the code. It is preferred that you use the
|
||||
"ssh" method, and the ssh based clone with the command:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
% git clone [email protected]:steveicarus/iverilog.git
|
||||
|
||||
This assumes that you have a github account (accounts are free) and you have
|
||||
set up your ssh authentication keys. See the
|
||||
`Authentication Guides here <https://docs.github.com/en/authentication>`_.
|
||||
|
||||
The "git clone" command will get you all the source:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
% git clone [email protected]:steveicarus/iverilog.git
|
||||
Cloning into 'iverilog'...
|
||||
remote: Enumerating objects: 66234, done.
|
||||
remote: Counting objects: 100% (6472/6472), done.
|
||||
remote: Compressing objects: 100% (4123/4123), done.
|
||||
remote: Total 66234 (delta 2412), reused 6039 (delta 2190), pack-reused 59762
|
||||
Receiving objects: 100% (66234/66234), 27.98 MiB | 2.53 MiB/s, done.
|
||||
Resolving deltas: 100% (50234/50234), done.
|
||||
% cd iverilog/
|
||||
|
||||
Normally, this is enough as you are now pointing at the most current
|
||||
development code, and you have implicitly created a branch "master" that
|
||||
tracks the development head. However, If you want to actually be working on a
|
||||
specific version, say for example version 11, the v11-branch, you checkout
|
||||
that branch with the command:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
% git checkout --track -b v11-branch origin/v11-branch
|
||||
|
||||
This creates a local branch that tracks the v11-branch in the repository, and
|
||||
switches you over to your new v11-branch. The tracking is important as it
|
||||
causes pulls from the repository to re-merge your local branch with the remote
|
||||
v11-branch. You always work on a local branch, then merge only when you
|
||||
push/pull from the remote repository.
|
||||
|
||||
Now that you've cloned the repository and optionally selected the branch you
|
||||
want to work on, your local source tree may later be synced up with the
|
||||
development source by using the git command:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
% git pull
|
||||
Already up to date.
|
||||
|
||||
Finally, configuration files are built by the extra step:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
% sh autoconf.sh
|
||||
Autoconf in root...
|
||||
Precompiling lexor_keyword.gperf
|
||||
Precompiling vhdlpp/lexor_keyword.gperf
|
||||
|
||||
You will need autoconf and gperf installed in order for the script to work.
|
||||
If you get errors such as:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
% sh autoconf.sh
|
||||
Autoconf in root...
|
||||
autoconf.sh: 10: autoconf: not found
|
||||
Precompiling lexor_keyword.gperf
|
||||
autoconf.sh: 13: gperf: not found.
|
||||
|
||||
You will need to install download and install the autoconf and gperf tools.
|
||||
|
||||
Now you are ready to configure and compile the source.
|
||||
|
||||
Icarus Specific Configuration Options
|
||||
-------------------------------------
|
||||
|
||||
Icarus takes many of the standard configuration options and those will not be
|
||||
described here. The following are specific to Icarus Verilog:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
--enable-suffix[=suffix]
|
||||
|
||||
This option allows the user to build Icarus with a default suffix or when
|
||||
provided a user defined suffix. All programs or directories are tagged with
|
||||
this suffix. e.g.(iverilog-0.8, vvp-0.8, etc.). The output of iverilog will
|
||||
reference the correct run time files and directories. The run time will check
|
||||
that it is running a file with a compatible version e.g.(you can not run a
|
||||
V0.9 file with the V0.8 run time).
|
||||
|
||||
A debug options is:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
--with-valgrind
|
||||
|
||||
This option adds extra memory cleanup code and pool management code to allow
|
||||
better memory leak checking when valgrind is available. This option is not
|
||||
need when checking for basic errors with valgrind.
|
||||
|
||||
Compiling on Linux
|
||||
------------------
|
||||
|
||||
(Note: You will need to install bison, flex, g++ and gcc) This is probably the
|
||||
easiest step. Given that you have the source tree from the above instructions,
|
||||
the compile and install is generally as simple as:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
% ./configure
|
||||
configure: loading site script /usr/share/site/x86_64-unknown-linux-gnu
|
||||
checking build system type... x86_64-unknown-linux-gnu
|
||||
checking host system type... x86_64-unknown-linux-gnu
|
||||
checking for gcc... gcc
|
||||
checking whether the C compiler works... yes
|
||||
checking for C compiler default output file name... a.out
|
||||
checking for suffix of executables...
|
||||
[...and so on...]
|
||||
|
||||
% make
|
||||
mkdir dep
|
||||
Using git-describe for VERSION_TAG
|
||||
g++ -DHAVE_CONFIG_H -I. -Ilibmisc -Wall -Wextra -Wshadow -g -O2 -MD -c main.cc -o main.o
|
||||
mv main.d dep/main.d
|
||||
g++ -DHAVE_CONFIG_H -I. -Ilibmisc -Wall -Wextra -Wshadow -g -O2 -MD -c async.cc -o async.o
|
||||
mv async.d dep/async.d
|
||||
g++ -DHAVE_CONFIG_H -I. -Ilibmisc -Wall -Wextra -Wshadow -g -O2 -MD -c design_dump.cc -o design_dump.o
|
||||
mv design_dump.d dep/design_dump.d
|
||||
g++ -DHAVE_CONFIG_H -I. -Ilibmisc -Wall -Wextra -Wshadow -g -O2 -MD -c discipline.cc -o discipline.o
|
||||
[...and so on...]
|
||||
|
||||
The end result is a complete build of Icarus Verilog. You can install your
|
||||
compiled version with a command like this:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
% sudo make install
|
||||
|
||||
Regression Tests
|
||||
----------------
|
||||
|
||||
Icarus Verilog comes with a fairly extensive regression test suite. As of
|
||||
2022, that test suite is included with the source in the "ivtest"
|
||||
directory. Contained in that directory are a couple driver scripts that run
|
||||
all the regression tests on the installed version of Icarus Verilog. So for
|
||||
example:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
% cd ivtest
|
||||
% ./vvp_reg.pl --strict
|
||||
|
||||
will run all the regression tests for the simulation engine. (This is what
|
||||
most people will want to do.) You should rerun this test before submitting
|
||||
patches to the developers. Also, if you are adding a new feature, you should
|
||||
add test programs to the regression test suite to validate your new feature
|
||||
(or bug fix.)
|
||||
|
||||
Note that pull requests will be required to pass these regression tests before
|
||||
being merged.
|
||||
|
||||
Forks, Branches and Pull Requests
|
||||
---------------------------------
|
||||
|
||||
Currently, the preferred way to submit patches to Icarus Verilog is via pull
|
||||
requests.
|
||||
`Pull requests <https://docs.github.com/en/github-ae@latest/pull-requests>`_
|
||||
can be created from the main repository if you have write access (very few
|
||||
people have write access) or more commonly from a fork, so the first step is
|
||||
to create a fork that you can work with. It is easy enough to create a fork,
|
||||
just go to the
|
||||
`github.com/steveicarus/iverilog <http://github.com/steveicarus/iverilog>`_
|
||||
page and use the "fork" button in the upper right corner. This will create
|
||||
a new repository that you can clone instead of the steveicarus/iverilog
|
||||
repository. You then use your local repository to create feature branches,
|
||||
then submit them for inclusion in the main repository as pull
|
||||
requests. Remember to `synchronize your fork
|
||||
<https://docs.github.com/en/github-ae@latest/pull-requests/collaborating-with-pull-requests/working-with-forks/syncing-a-fork>`_
|
||||
periodically with the main repository. This will make sure your work is based
|
||||
on the latest upstream and avoid merge conflicts.
|
||||
|
||||
Create your patch by first creating a branch that contains your commits:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
% git checkout -b my-github-id/branch-name
|
||||
|
||||
We are encouraging using this scheme for naming your branches that are
|
||||
destined for pull requests. Use your github id in the branch name. So for
|
||||
example:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
% git checkout -b steveicarus/foo-feature
|
||||
|
||||
Do your work in this branch, then when you are ready to create a pull request,
|
||||
first push the branch up to github:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
% git push -u origin my-github-id/branch-name
|
||||
|
||||
Then go to github.com to create your pull request. `Create your pull request
|
||||
against the "master" branch of the upstream repository
|
||||
<https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request-from-a-fork>`_,
|
||||
or the version branch that you are working on. Your pull reuqest will be run
|
||||
through continuous integration, and reviewed by one of the main
|
||||
authors. Feedback may be offered to your PR, and once accepted, an approved
|
||||
individual will merge it for you. Then you are done.
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
|
||||
Icarus Verilog Developer Support
|
||||
================================
|
||||
|
||||
This section contains documents to help support developers who contribute to
|
||||
Icarus Verilog.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
getting_started
|
||||
version_stamps
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
|
||||
Files With Version Information
|
||||
==============================
|
||||
|
||||
These are the only files that have version information in them:
|
||||
|
||||
* version_base.h -- This should be the 1 source for version info.
|
||||
* version_tag.h -- Generated automatically with git tag information.
|
||||
* verilog.spec -- Used to stamp RPM packages
|
||||
|
||||
When versions are changed, the above files need to be edited to account for
|
||||
the new version information. The following used to have verion information in
|
||||
them, but now their version information is generated:
|
||||
|
||||
Replaced with version_base.h, which is edited manually, and
|
||||
version_tag.h which is generated from git tag information.
|
||||
|
||||
* version-base.in -- Most compiled code gets version from here
|
||||
|
||||
These are now edited by the makefile and the version.exe program.
|
||||
|
||||
* iverilog-vpi.man -- The .TH tag has a version string
|
||||
* driver/iverilog.man -- The .TH tag has a version string
|
||||
* driver-vpi/res.rc -- Used to build Windows version stamp
|
||||
* vvp/vvp.man -- The .TH tag has a version string
|
||||
|
||||
This now includes version_base.h to get the version
|
||||
|
||||
* vpi/vams_simparam.c -- Hard coded result to simulatorVersion query
|
||||
@@ -0,0 +1,25 @@
|
||||
.. Icarus Verilog documentation master file, created by
|
||||
sphinx-quickstart on Sun Apr 10 16:28:38 2022.
|
||||
You can adapt this file completely to your liking, but it should at least
|
||||
contain the root `toctree` directive.
|
||||
|
||||
Icarus Verilog
|
||||
==============
|
||||
|
||||
Welcome to the documentation for Icarus Verilog.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:caption: Contents:
|
||||
|
||||
usage/index
|
||||
targets/index
|
||||
developer/index
|
||||
|
||||
|
||||
Indices and tables
|
||||
==================
|
||||
|
||||
* :ref:`genindex`
|
||||
* :ref:`modindex`
|
||||
* :ref:`search`
|
||||
@@ -0,0 +1,36 @@
|
||||
@ECHO OFF
|
||||
|
||||
pushd %~dp0
|
||||
|
||||
REM Command file for Sphinx documentation
|
||||
|
||||
if "%SPHINXBUILD%" == "" (
|
||||
set SPHINXBUILD=sphinx-build
|
||||
)
|
||||
set SOURCEDIR=.
|
||||
set BUILDDIR=_build
|
||||
set SPHINXPROJ=IcarusVerilog
|
||||
|
||||
if "%1" == "" goto help
|
||||
|
||||
%SPHINXBUILD% >NUL 2>NUL
|
||||
if errorlevel 9009 (
|
||||
echo.
|
||||
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
|
||||
echo.installed, then set the SPHINXBUILD environment variable to point
|
||||
echo.to the full path of the 'sphinx-build' executable. Alternatively you
|
||||
echo.may add the Sphinx directory to PATH.
|
||||
echo.
|
||||
echo.If you don't have Sphinx installed, grab it from
|
||||
echo.http://sphinx-doc.org/
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
|
||||
goto end
|
||||
|
||||
:help
|
||||
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
|
||||
|
||||
:end
|
||||
popd
|
||||
@@ -0,0 +1,18 @@
|
||||
|
||||
The Icarus Verilog Targets
|
||||
==========================
|
||||
|
||||
Icarus Verilog elaborates the design, then sends to the design to code
|
||||
generates (targets) for processing. new code generators can be added by
|
||||
external packages, but these are the code generators that are bundled with
|
||||
Icarus Verilog. The code generator is selected by the "-t" command line flag.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
vvp
|
||||
stub
|
||||
null
|
||||
vhdl
|
||||
verilog95
|
||||
pcb
|
||||
@@ -0,0 +1,7 @@
|
||||
|
||||
The null Code Generator (-tnull)
|
||||
================================
|
||||
|
||||
The null target generates no code. Invoking this code generator causes no code
|
||||
generation to happen.
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
|
||||
Using the PCB code generator
|
||||
============================
|
||||
|
||||
The PCB target code generator is designed to allow a user to enter a netlist
|
||||
in Verilog format, then generate input files for the GNU PCB layout program.
|
||||
|
||||
Invocation
|
||||
----------
|
||||
|
||||
The PCB target code generation is invoked with the -tpcb flag to the iverilog
|
||||
command. The default output file, "a.out", contains the generated .PCB
|
||||
file. Use the "-o" flag to set the output file name explicitly. The default
|
||||
output file contains only the elements. To generate a "netlist" file, add the
|
||||
flag "-pnetlist=<path>" command line flag.
|
||||
|
||||
Altogether, this example generates the foo.net and foo.pcb files from the
|
||||
foo.v source file::
|
||||
|
||||
% iverilog -tpcb -ofoo.pcb -pnetlist=foo.net foo.v
|
||||
|
||||
Flags
|
||||
-----
|
||||
|
||||
* -o <path>
|
||||
|
||||
Set the output (pcb) file path
|
||||
|
||||
* -pnetlist=path
|
||||
|
||||
Write a netlist file to the given path.
|
||||
|
||||
Attributes Summary
|
||||
------------------
|
||||
|
||||
Attributes are attached to various constructs using the Verilog "(\* \*)"
|
||||
attribute syntax.
|
||||
|
||||
* ivl_black_box
|
||||
|
||||
Attached to a module declaration or module instantiation, this indicates
|
||||
that the module is a black box. The code generator will create an element
|
||||
for black box instances.
|
||||
|
||||
Parameters Summary
|
||||
------------------
|
||||
|
||||
Within modules, The PCB code generator uses certain parameters to control
|
||||
details. Parameters may have defaults, and can be overridden using the usual
|
||||
Verilog parameter override syntax. Parameters have preferred types.
|
||||
|
||||
* description (string, default="")
|
||||
|
||||
The "description" is a text string that describes the black box. This string
|
||||
is written into the description field of the PCB Element.
|
||||
|
||||
* value (string, default="")
|
||||
|
||||
The "value" is a text tring that describes some value for the black
|
||||
box. Like the description, the code generator does not interpret this value,
|
||||
other then to write it to the appropriate field in the PCB Element."
|
||||
@@ -0,0 +1,7 @@
|
||||
|
||||
The stub Code Generator (-tstub)
|
||||
================================
|
||||
|
||||
The stub code generator is a debugging aid for the Icarus Verilog compiler
|
||||
itself. It outputs a text dump of the elaborated design as it is passed to
|
||||
code generators.
|
||||
@@ -0,0 +1,101 @@
|
||||
|
||||
Using The Verilog '95 Code Generator
|
||||
====================================
|
||||
|
||||
Icarus Verilog contains a code generator to emit 1995 compliant Verilog from
|
||||
the input Verilog netlist. This allows Icarus Verilog to function as a Verilog
|
||||
> 1995 to Verilog 1995 translator. The main goal of the project was to convert
|
||||
@*, ANSI style arguments and other constructs to something allowed in 1995
|
||||
Verilog.
|
||||
|
||||
Invocation
|
||||
----------
|
||||
|
||||
To translate a Verilog program to 1995 compliant Verilog, invoke "iverilog"
|
||||
with the -tvlog95 flag::
|
||||
|
||||
% iverilog -tvlog95 -o my_design_95.v my_design.v
|
||||
|
||||
The generated Verilog will be placed in a single file (a.out by default), even
|
||||
if the input Verilog is spread over multiple files.
|
||||
|
||||
Generator Flags
|
||||
---------------
|
||||
|
||||
* -pspacing=N
|
||||
|
||||
Set the indent spacing (the default is 2).
|
||||
|
||||
* -pallowsigned=1
|
||||
|
||||
Allow emitting the various signed constructs as an extension to 1995 Verilog
|
||||
(off by default).
|
||||
|
||||
* -pfileline=1
|
||||
|
||||
Emit the original file and line information as a comment for each generated
|
||||
line (off by default).
|
||||
|
||||
Structures that cannot be converted to 1995 compatible Verilog
|
||||
--------------------------------------------------------------
|
||||
|
||||
The following Verilog constructs are not translatable to 1995 compatible Verilog:
|
||||
|
||||
* Automatic tasks or functions.
|
||||
|
||||
* The power operator (**). Expressions of the form (2**N)**<variable> (where N
|
||||
is a constant) can be converter to a shift.
|
||||
|
||||
* Some System Verilog constructs (e.g. final blocks, ++/-- operators,
|
||||
etc.). 2-state variables are converted to 4-state variables.
|
||||
|
||||
Icarus extensions that cannot be translated:
|
||||
|
||||
* Integer constants greater than 32 bits.
|
||||
|
||||
* Real valued nets.
|
||||
|
||||
* Real modulus.
|
||||
|
||||
* Most Verilog-A constructs.
|
||||
|
||||
|
||||
Known Issues and Limitations
|
||||
----------------------------
|
||||
|
||||
Some things are just not finished and should generate an appropriate
|
||||
warning. Here is a list of the major things that still need to be looked at.
|
||||
|
||||
* There are still a few module instantiation port issues (pr1723367 and
|
||||
partselsynth).
|
||||
|
||||
* inout ports are not converted (tran-VP).
|
||||
|
||||
* Variable selects of a non-zero based vector in a continuous assignment are
|
||||
not converted.
|
||||
|
||||
* There is no support for translating a zero repeat in a continuous
|
||||
assignment. It is currently just dropped.
|
||||
|
||||
* A pull device connected to a signal select is not translated correctly (this
|
||||
may be fixed).
|
||||
|
||||
* L-value indexed part selects with a constant undefined base in a continuous
|
||||
assignment are not translated.
|
||||
|
||||
* Logic gates are not arrayed exactly the same as the input and the instance
|
||||
name is not always the same.
|
||||
|
||||
* The signed support does not generate $signed() or $unsigned() function calls
|
||||
in a continuous assignment expression.
|
||||
|
||||
* The special power operator cases are not converted in a continuous
|
||||
assignment.
|
||||
|
||||
* Currently a signed constant that sets the MSB in an unsigned context will be
|
||||
displayed as a negative value (e.g. bit = 1 translates to bit = -1).
|
||||
|
||||
* Can net arrays, etc. be unrolled?
|
||||
|
||||
* Can generate blocks be converted?
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
|
||||
The VHDL Code Generator (-tvhdl)
|
||||
================================
|
||||
|
||||
Icarus Verilog contains a code generator to emit VHDL from the Verilog
|
||||
netlist. This allows Icarus Verilog to function as a Verilog to VHDL
|
||||
translator.
|
||||
|
||||
Invocation
|
||||
----------
|
||||
|
||||
To translate a Verilog program to VHDL, invoke "iverilog" with the -tvhdl
|
||||
flag::
|
||||
|
||||
% iverilog -t vhdl -o my_design.vhd my_design.v
|
||||
|
||||
The generated VHDL will be placed in a single file (a.out by default), even if
|
||||
the Verilog is spread over multiple files.
|
||||
|
||||
Flags
|
||||
-----
|
||||
|
||||
* -pdebug=1
|
||||
|
||||
Print progress messages as the code generator visits each part of the
|
||||
design.
|
||||
|
||||
* -pdepth=N
|
||||
|
||||
Only output VHDL entities for modules found at depth < N in the
|
||||
hierarchy. N=0, the default, outputs all entities. For example, -pdepth=1
|
||||
outputs only the top-level entity.
|
||||
|
||||
Supported Constructs
|
||||
--------------------
|
||||
|
||||
TODO
|
||||
|
||||
Limitations
|
||||
-----------
|
||||
|
||||
Signal Values and Resolution
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
There are several cases where the behaviour of the translated VHDL deviates
|
||||
from the source Verilog:
|
||||
|
||||
* The result of division by zero is x in Verilog but raises an exception in
|
||||
VHDL.
|
||||
|
||||
* Similarly, the result of reading past the end of an array in Verilog is x,
|
||||
whereas VHDL raises an exception.
|
||||
|
||||
* Any signal that is driven by two or more processes will have the value
|
||||
'U'. This is the result of the signal resolution function in the
|
||||
std_logic_1164 package.
|
||||
|
||||
Constructs Not Supported
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The following Verilog constructs cannot be translated to VHDL:
|
||||
|
||||
* fork and join
|
||||
|
||||
* force and release
|
||||
|
||||
* disable
|
||||
|
||||
* real-valued variables
|
||||
|
||||
* switches
|
||||
|
||||
* hierarchical dereferencing
|
||||
|
||||
Other Limitations
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
* The test expressions in case statements must be constant.
|
||||
|
||||
* Translation of a parameter to a corresponding VHDL generic
|
||||
declaration. Instead the default parameter value is used.
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
|
||||
The vvp Code Generator (-tvvp)
|
||||
==============================
|
||||
|
||||
The vvp target generates code for the "vvp" run time. This is the most
|
||||
commonly used target for Icarus Verilog, as it is the main simulation engine.
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 40 KiB |
@@ -0,0 +1,198 @@
|
||||
|
||||
Command File Format
|
||||
===================
|
||||
|
||||
The basic format of a command file is one source file or compiler argument per
|
||||
line. Command files may also have comments of various form, and options for
|
||||
controlling the compiler.
|
||||
|
||||
Comments
|
||||
--------
|
||||
|
||||
Lines that start with a "#" character are comments. All text after the "#"
|
||||
character, is ignored.
|
||||
|
||||
The "//" character sequence also starts a comment that continues to the end of
|
||||
the line.
|
||||
|
||||
The "/\*" and "\*/" character sequences surround multi-line comments. All the
|
||||
text between the comment start and comment end sequences is ignored, even when
|
||||
that text spans multiple lines. This style of comment does not nest, so a "/\*"
|
||||
sequence within a multi-line comment is probably an error.
|
||||
|
||||
Plus-args
|
||||
---------
|
||||
|
||||
Outside of comments, lines that start with a "+" character are compiler
|
||||
arguments. These are called plusargs but they are not the same as extended
|
||||
arguments passed to the "vvp" command. The supported plusargs are definitively
|
||||
listed in the iverilog manual page.
|
||||
|
||||
The plusargs lines are generally "+<name>+..." where the name is the name of
|
||||
an switch, and the arguments are separated by "+" characters, as in::
|
||||
|
||||
+libext+.v+.V+.ver
|
||||
|
||||
With plusargs lines, the "+" character separates tokens, and not white space,
|
||||
so arguments, which may include file paths, may include spaces. A plusarg line
|
||||
is terminated by the line end.
|
||||
|
||||
The line in the command file may also be a "-y" argument. This works exactly
|
||||
the same as the::
|
||||
|
||||
-y <path>
|
||||
|
||||
argument to the compiler; it declares a library directory. The "-y" syntax is
|
||||
also a shorthand for the "+libdir" plusarg, which is a more general form::
|
||||
|
||||
+libdir+<path>...
|
||||
|
||||
File Names
|
||||
----------
|
||||
|
||||
Any lines that are not comments, compiler arguments or plusargs are taken by
|
||||
the compiler to be a source file. The path can contain any characters (other
|
||||
then comment sequences) including blanks, although leading and trailing white
|
||||
space characters are stripped. The restriction of one file name per line is in
|
||||
support of operating systems that can name files any which way. It is not
|
||||
appropriate to expect white spaces to separate file names.
|
||||
|
||||
Variable Substitution
|
||||
---------------------
|
||||
|
||||
The syntax "$(name)" is a variable reference, and may be used anywhere within
|
||||
filenames or directory names. The contents of the variable are read from the
|
||||
environment and substituted in place of the variable reference. In Windows,
|
||||
these environment variables are the very same variables that are set through
|
||||
the Control Panel->System dialog box, and in UNIX these variables are
|
||||
environment variables as exported by your shell.
|
||||
|
||||
Variables are useful for giving command files some installation
|
||||
independence. For example, one can import a vendor library with the line::
|
||||
|
||||
-y $(VENDOR)/verilog/library
|
||||
|
||||
in the command file, and the next programmer will be able to use this command
|
||||
file without editing it to point to the location of VENDOR on his
|
||||
machine. Note the use of forward slashes as a directory separator. This works
|
||||
even under Windows, so always use forward slashes in file paths and Windows
|
||||
and UNIX users will be able to share command files.
|
||||
|
||||
An Example
|
||||
----------
|
||||
|
||||
This sample::
|
||||
|
||||
# This is a comment in a command file.
|
||||
# The -y statement declares a library
|
||||
# search directory
|
||||
-y $(PROJ_LIBRARY)/prims
|
||||
#
|
||||
# This plusarg tells the compiler that
|
||||
# files in libraries may have .v or .vl
|
||||
# extensions.
|
||||
+libext+.v+.vl
|
||||
#
|
||||
main.v // This is a source file
|
||||
#
|
||||
# This is a file name with blanks.
|
||||
C:/Project Directory/file name.vl
|
||||
|
||||
is a command file that demonstrates the major syntactic elements of command
|
||||
files. It demonstrates the use of comments, variables, plusargs and file
|
||||
names. It contains a lot of information about the hypothetical project, and
|
||||
suggests that command files can be used to describe the project as a whole
|
||||
fairly concisely.
|
||||
|
||||
The syntax of command files is rich enough that they can be used to document
|
||||
and control the assembly and compilation of large Verilog programs. It is not
|
||||
unusual to have command files that are hundreds of lines long, although
|
||||
judicious use of libraries can lead to very short command files even for large
|
||||
designs. It is also practical to have different command files that pull
|
||||
together combinations of sources and compiler arguments to make different
|
||||
designs from the same Verilog source files.
|
||||
|
||||
Summary
|
||||
-------
|
||||
|
||||
Given the above description of the command file format, the following is a
|
||||
list of the special records with their meaning.
|
||||
|
||||
* +libdir+*dir-path*
|
||||
|
||||
Specify directories to be searched for library modules. The *dir-path* can
|
||||
have multiple directories, separated by "+" characters.
|
||||
|
||||
* +libdir-nocase+dir-path
|
||||
|
||||
This is the same as "+libdir+", but when searching "nocase" libraries for
|
||||
module files, case will not be taken as significant. This is useful when the
|
||||
library is on a case insensitive file system.
|
||||
|
||||
* +libext+*suffix-string*
|
||||
|
||||
Declare the suffix strings to use when searching library directories for
|
||||
Verilog files. The compiler may test a list of suffix strings to support a
|
||||
variety of naming conventions.
|
||||
|
||||
* -y dir-path
|
||||
|
||||
This is like "+libdir+" but each line takes only one path. Like "+libdir+"
|
||||
there can be multiple "-y" records to declare multiple library
|
||||
directories. This is similar to the "-y" flag on the iverilog command line.
|
||||
|
||||
* -v *file-name* or -l *file-name*
|
||||
|
||||
This declares a library file. A library file is just like any other Verilog
|
||||
source file, except that modules declared within it are not implicitly
|
||||
possible root modules.
|
||||
|
||||
NOTE: The "-l" alias is new as of 2 October 2016. It will become available
|
||||
in releases and snapshots made after that date.
|
||||
|
||||
* +incdir+*include-dir-path*
|
||||
|
||||
Declare a directory or list of directories to search for files included by
|
||||
the "include" compiler directive. The directories are searched in
|
||||
order. This is similar to the "-I" flag on the iverilog command line.
|
||||
|
||||
* +define+*name=value*
|
||||
|
||||
Define the preprocessor symbol "name" to have the string value "value". If
|
||||
the value (and the "=") are omitted, then it is assumed to be the string
|
||||
"1". This is similar to the "-D" on the iverilog command line.
|
||||
|
||||
* +timescale+*units/precision*
|
||||
|
||||
Define the default timescale. This is the timescale that is used if there is
|
||||
no other timescale directive in the Verilog source. The compiler default
|
||||
default is "+timescale+1s/1s", which this command file setting can
|
||||
change. The format of the units/precision is the same as that for the
|
||||
timescale directive in the verilog source.
|
||||
|
||||
* +toupper-filename
|
||||
|
||||
This token causes file names after this in the command file to be translated
|
||||
to uppercase. this helps with situations where a directory has passed
|
||||
through a DOS machine (or a FAT file system) and in the process the file
|
||||
names become munged. This is not meant to be used in general, but only in
|
||||
emergencies.
|
||||
|
||||
* +tolower-filename
|
||||
|
||||
The is the lowercase version of "+toupper-filename".
|
||||
|
||||
* +parameter+*name=value*
|
||||
|
||||
This token causes the compiler to override a parameter value for a top-level
|
||||
module. For example, if the module main has the parameter WIDTH, set the
|
||||
width like this "+parameter+main.WIDTH=5". Note the use of the complete
|
||||
hierarchical name. This currently only works for parameters defined in root
|
||||
(top level) modules and a defparam may override the command file value.
|
||||
|
||||
* +vhdl-work+*path*
|
||||
|
||||
When compiling VHDL, this token allows control over the directory to use for
|
||||
holding working package declarations. For example, "+vhdl-work+workdir" will
|
||||
cause the directory "workdir" to be used as a directory for holding working
|
||||
working copies of package headers.
|
||||
@@ -0,0 +1,444 @@
|
||||
|
||||
|
||||
iverilog Command Line Flags
|
||||
===========================
|
||||
|
||||
The iverilog command is the compiler/driver that takes the Verilog input and
|
||||
generates the output format, whether the simulation file or synthesis
|
||||
results. This information is at least summarized in the iverilog man page
|
||||
distributed in typical installations, but here we try to include more detail.
|
||||
|
||||
General
|
||||
-------
|
||||
|
||||
These flags affect the general behavior of the compiler.
|
||||
|
||||
* -c <cmdfile>
|
||||
|
||||
This flag selects the command file to use. The command file is an
|
||||
alternative to writing a long command line with a lot of file names and
|
||||
compiler flags. See the Command File Format page for more information.
|
||||
|
||||
* -d <flag>
|
||||
|
||||
Enable compiler debug output. These are aids for debugging Icarus Verilog,
|
||||
and this flag is not commonly used.
|
||||
The flag is one of these debug classes:
|
||||
|
||||
* scope
|
||||
* eval_tree
|
||||
* elaborate
|
||||
* synth2
|
||||
|
||||
* -g <generation flag>
|
||||
the generation is the compiler language, and specifies the language and
|
||||
extensions to use during the compile. The language level can be selected
|
||||
by a major level selector, and by controlling various features. Various
|
||||
"-g" flags can be compined. For example, to get Verilog 2001 without
|
||||
specify supoprt, use "-g2001 -gno-specify".
|
||||
|
||||
The supported flags are:
|
||||
|
||||
* 1995
|
||||
|
||||
This flag enables the IEEE1364-1995 standard.
|
||||
|
||||
* 2001
|
||||
|
||||
This flag enables the IEEE1364-2001 standard.
|
||||
|
||||
* 2001-noconfig
|
||||
|
||||
This flag enables the IEEE1364-2001 standard with config file support
|
||||
disabled. This eliminates the config file keywords from the language and
|
||||
so helps some programs written to older 2001 support compile.
|
||||
|
||||
* 2005
|
||||
This flag enables the IEEE1364-2005 standard. This is default enabled
|
||||
after v0.9.
|
||||
|
||||
* 2009
|
||||
This flag enables the IEEE1800-2009 standard, which includes
|
||||
SystemVerilog. The SystemVerilog support is not present in v0.9 and
|
||||
earlier. It is new to git master as of November 2009. Actual SystemVerilog
|
||||
support is ongoing.
|
||||
|
||||
* 2012
|
||||
|
||||
This flag enables the IEEE1800-2012 standard, which includes
|
||||
SystemVerilog.
|
||||
|
||||
* verilog-ams
|
||||
|
||||
This flag enables Verilog-AMS features that are supported by Icarus
|
||||
Verilog. (This is new as of 5 May 2008.)
|
||||
|
||||
* assertions/supported-assertions/no-assertions
|
||||
|
||||
Enable or disable SystemVerilog assertions. When enabled, assertion
|
||||
statements are elaborated. When disabled, assertion statements are parsed
|
||||
but ignored. The supported-assertions option only enables assertions that
|
||||
are currently supported by the compiler.
|
||||
|
||||
* specify/no-specify
|
||||
|
||||
Enable or disable support for specify block timing controls. When
|
||||
disabled, specify blocks are parsed but ignored. When enabled, specify
|
||||
blocks cause timing path and timing checks to be active.
|
||||
|
||||
* std-include/no-std-include
|
||||
|
||||
Enable or disable the search of a standard installation include directory
|
||||
after all other explicit include directories. This standard include
|
||||
directory is a convenient place to install standard header files that a
|
||||
Verilog program may include.
|
||||
|
||||
* relative-include/no-relative-include
|
||||
|
||||
Enable or disable adding the local files directory to the beginning of the
|
||||
include file search path. This allows files to be included relative to the
|
||||
current file.
|
||||
|
||||
* xtypes/no-xtypes
|
||||
|
||||
Enable or disable support for extended types. Enabling types allows for
|
||||
new types and type syntax that are Icarus Verilog extensions.
|
||||
|
||||
* io-range-error/no-io-range-error
|
||||
|
||||
When enabled the range for a port and any associated net declaration must
|
||||
match exactly. When disabled a scalar port is allowed to have a net
|
||||
declaration with a range (obsolete usage). A warning message will be
|
||||
printed for this combination. All other permutations are still considered
|
||||
an error.
|
||||
|
||||
* strict-ca-eval/no-strict-ca-eval
|
||||
|
||||
The standard requires that if any input to a continuous assignment
|
||||
expression changes value, the entire expression is re-evaluated. By
|
||||
default, parts of the expression that do not depend on the changed input
|
||||
value(s) are not re-evaluated. If an expression contains a call to a
|
||||
function that doesn't depend solely on its input values or that has side
|
||||
effects, the resulting behavior will differ from that required by the
|
||||
standard. Enabling strict-ca-eval will force standard compliant behavior
|
||||
(with some loss in performance).
|
||||
|
||||
* strict-expr-width/no-strict-expr-width
|
||||
|
||||
Enable or disable strict compliance with the standard rules for
|
||||
determining expression bit lengths. When disabled, the RHS of a parameter
|
||||
assignment is evaluated as a lossless expression, as is any expression
|
||||
containing an unsized constant number, and unsized constant numbers are
|
||||
not truncated to integer width.
|
||||
|
||||
* shared-loop-index/no-shared-loop-index
|
||||
|
||||
Enable or disable the exclusion of for-loop control variables from
|
||||
implicit event_expression lists. When enabled, if a for-loop control
|
||||
variable (loop index) is only used inside the for-loop statement, the
|
||||
compiler will not include it in an implicit event_expression list it
|
||||
calculates for that statement or any enclosing statement. This allows the
|
||||
same control variable to be used in multiple processes without risk of
|
||||
entering an infinite loop caused by each process triggering all other
|
||||
processes that use the same variable. For strict compliance with the
|
||||
standards, this behaviour should be disabled.
|
||||
|
||||
* -i
|
||||
|
||||
Ignore missing modules. Normally it is an error if a module instantiation
|
||||
refers to an undefined module. This option causes the compiler to skip over
|
||||
that instantiation. It will also stop the compiler returning an error if
|
||||
there are no top level modules. This allows the compiler to be used to check
|
||||
incomplete designs for errors.
|
||||
|
||||
NOTE: The "-i" flag was added in v11.0.
|
||||
|
||||
* -L <path>
|
||||
|
||||
Add the specified directory to the path list used to locate VPI modules. The
|
||||
default path includes only the install directory for the system.vpi module,
|
||||
but this flag can add other directories. Multiple paths are allowed, and the
|
||||
paths will be searched in order.
|
||||
|
||||
NOTE: The "-L" flag was added in v11.0.
|
||||
|
||||
* -l <path>
|
||||
|
||||
Add the specified file to the list of source files to be compiled, but mark
|
||||
it as a library file. All modules contained within that file will be treated
|
||||
as library modules, and only elaborated if they are instantiated by other
|
||||
modules in the design.
|
||||
|
||||
NOTE: The "-l" flag is new as of 2 October 2016. It will become available in
|
||||
releases and snapshots made after that date.
|
||||
|
||||
* -M<mode>=<path>
|
||||
|
||||
Write into the file specified by path a list of files that contribute to the
|
||||
compilation of the design.
|
||||
|
||||
If _mode_ is *all* or *prefix*, this includes files that are included by
|
||||
include directives and files that are automatically loaded by library
|
||||
support as well as the files explicitly specified by the user.
|
||||
|
||||
If _mode_ is *include*, only files that are included by include directives
|
||||
are listed.
|
||||
|
||||
If _mode_ is *module*, only files that are specified by the user or that are
|
||||
automatically loaded by library support are listed. The output is one file
|
||||
name per line, with no leading or trailing space.
|
||||
|
||||
If _mode_ is *prefix*, files that are included by include directives are
|
||||
prefixed by "I " and other files are prefixed by "M ".
|
||||
|
||||
* -m<module>
|
||||
|
||||
Add this module to the list of VPI modules to be loaded by the
|
||||
simulation. Many modules can be specified, and all will be loaded, in the
|
||||
order specified. The system module is implicit and always included (and
|
||||
loaded last).
|
||||
|
||||
If the specified name includes at least one directory character, it is
|
||||
assumed to be prefixed by the path to the module, otherwise the module is
|
||||
searched for in the paths specified by preceding -L options, and if not
|
||||
found there, in the iverilog base directory.
|
||||
|
||||
NOTE: The "-m" flag was added in v11.0.
|
||||
|
||||
* -o <path>
|
||||
|
||||
Specify the output file. The <path> is the name of the file to hold the
|
||||
output. The default is "a.out".
|
||||
|
||||
* -S
|
||||
|
||||
Activate synthesis. This flag tells the compiler to do what synthesis it can
|
||||
do before calling the code generator. This flag is rarely used explicitly,
|
||||
and certain code generators will implicitly enable this flag.
|
||||
|
||||
* -u
|
||||
|
||||
Treat each source file as a separate compilation unit (as defined in
|
||||
SystemVerilog). If compiling for an IEEE1364 generation, this will just
|
||||
reset all compiler directives (including macro definitions) before each new
|
||||
file is processed.
|
||||
|
||||
NOTE: The "-u" flag was added in v11.0.
|
||||
|
||||
* -v
|
||||
|
||||
Be verbose. Print copyright information, progress messages, and some timing
|
||||
information about various compilation phases.
|
||||
|
||||
(New in snapshots after 2014-12-16) If the selected target is vvp, the -v
|
||||
switch is appended to the shebang line in the compiler output file, so
|
||||
directly executing the compiler output file will turn on verbose messages in
|
||||
vvp. This extra verbosity can be avoided by using the vvp command to
|
||||
indirectly execute the compiler output file.
|
||||
|
||||
* -V
|
||||
|
||||
Print the version information. This skips all compilation. Just print the
|
||||
version information, including version details for the various components of
|
||||
the compiler.
|
||||
|
||||
* -R
|
||||
|
||||
Print the runtime paths of the compiler. This can be useful to find, e.g.,
|
||||
the include path of vpi_user.h.
|
||||
|
||||
* -W<warning class>
|
||||
|
||||
Enable/disable warnings. All the warning types (other then "all") can be
|
||||
prefixed with no- to disable that warning.
|
||||
|
||||
* all
|
||||
|
||||
This enables almost all of the available warnings. More specifically, it
|
||||
enables these warnings::
|
||||
|
||||
-Wanachronisms
|
||||
-Wimplicit
|
||||
-Wimplicit-dimensions
|
||||
-Wmacro-replacement
|
||||
-Wportbind
|
||||
-Wselect-range
|
||||
-Wtimescale
|
||||
-Wsensitivity-entire-array
|
||||
|
||||
* anachronisms
|
||||
|
||||
This enables warnings for use of features that have been deprecated or
|
||||
removed in the selected generation of the Verilog language.
|
||||
|
||||
* implicit
|
||||
|
||||
This enables warnings for creation of implicit declarations. For example,
|
||||
if a scalar wire X is used but not declared in the Verilog source, this
|
||||
will print a warning at its first use.
|
||||
|
||||
* implicit-dimensions
|
||||
|
||||
This enables warnings for the case where a port declaration or a var/net
|
||||
declaration for the same name is missing dimensions. Normally, Verilog
|
||||
allows you to do this (the undecorated declaration gets its dimensions
|
||||
form the decorated declaration) but this is no longer common, and some
|
||||
other tools (notable Xilix synthesizers) do not handle this correctly.
|
||||
|
||||
This flag is supported in release 10.1 or master branch snapshots after
|
||||
2016-02-06.
|
||||
|
||||
* macro-redefinition
|
||||
|
||||
This enables warnings when a macro is redefined, even if the macro text
|
||||
remains the same.
|
||||
|
||||
NOTE: The "macro-redefinition" flag was added in v11.0.
|
||||
|
||||
* macro-replacement
|
||||
|
||||
This enables warnings when a macro is redefined and the macro text
|
||||
changes. Use no-macro-redefinition to disable this,
|
||||
|
||||
NOTE: The "macro-replacement" flag was added in v11.0.
|
||||
|
||||
* portbind
|
||||
|
||||
This enables warnings for ports of module instantiations that are not
|
||||
connected properly, but probably should be. Dangling input ports, for
|
||||
example, will generate a warning.
|
||||
|
||||
* select-range
|
||||
|
||||
This enables warnings for constant out-of-bound selects. This includes
|
||||
partial or fully out-of-bound select as well as a select containing a 'bx
|
||||
or 'bz in the index.
|
||||
|
||||
* timescale
|
||||
|
||||
This enables warnings for inconsistent use of the timescale directive. It
|
||||
detects if some modules have no timescale, or if modules inherit timescale
|
||||
from another file. Both probably mean that timescales are inconsistent,
|
||||
and simulation timing can be confusing and dependent on compilation order.
|
||||
|
||||
* infloop
|
||||
|
||||
This enables warnings for always statements that may have runtime infinite
|
||||
loops (i.e. has paths with zero or no delay). This class of warnings is
|
||||
not included in -Wall and hence does not have a no- variant. A fatal error
|
||||
message will always be printed when the compiler can determine that there
|
||||
will definitely be an infinite loop (all paths have no or zero delay).
|
||||
|
||||
When you suspect an always statement is producing a runtine infinite loop,
|
||||
use this flag to find the always statements that need to have their logic
|
||||
verified. it is expected that many of the warnings will be false
|
||||
positives, since the code treats the value of all variables and signals as
|
||||
indeterninite.
|
||||
|
||||
* sensitivity-entire-vector
|
||||
|
||||
This enables warnings for when a part select with an "always @*" statement
|
||||
results in the entire vector being added to the implicit sensitivity
|
||||
list. Although this behavior is prescribed by the IEEE standard, it is not
|
||||
what might be expected and can have performance implications if the vector
|
||||
is large.
|
||||
|
||||
* sensitivity-entire-array
|
||||
|
||||
This enables warnings for when a word select with an "always @*" statement
|
||||
results in the entire array being added to the implicit sensitivity
|
||||
list. Although this behavior is prescribed by the IEEE standard, it is not
|
||||
what might be expected and can have performance implications if the array
|
||||
is large.
|
||||
|
||||
* floating-nets
|
||||
|
||||
This enables warnings for nets that are present but have no drivers.
|
||||
|
||||
This flag was added in version 11.0 or later (and is in the master branch
|
||||
as of 2015-10-01).
|
||||
|
||||
* -y<libdir>
|
||||
|
||||
Append the directory to the library module search path. When the compiler
|
||||
finds an undefined module, it looks in these directories for files with the
|
||||
right name.
|
||||
|
||||
* -Y<suf>
|
||||
|
||||
Appends suf to the list of file extensions that are used to resolve an
|
||||
undefined module to a file name. Should be specified before any -y flag. For
|
||||
example, this command::
|
||||
|
||||
% iverilog -Y .sv -y sources src.v
|
||||
|
||||
will try to resolve any undefined module m by looking into the directory
|
||||
sources and checking if there exist files named m.v or m.sv.
|
||||
|
||||
|
||||
Preprocessor Flags
|
||||
------------------
|
||||
|
||||
These flags control the behavior of the preprocessor. They are similar to
|
||||
flags for the typical "C" compiler, so C programmers will find them familiar.
|
||||
|
||||
* -E
|
||||
|
||||
This flag is special in that it tells the compiler to only run the
|
||||
preprocessor. This is useful for example as a way to resolve preprocessing
|
||||
for other tools. For example, this command::
|
||||
|
||||
% iverilog -E -ofoo.v -DKEY=10 src1.v src2.v
|
||||
|
||||
runs the preprocessor on the source files src1.v and src2.v and produces the
|
||||
single output file foo.v that has all the preprocessing (including header
|
||||
includes and ifdefs) processed.
|
||||
|
||||
* -D<macro>
|
||||
|
||||
Assign a value to the macro name. The format of this flag is one of::
|
||||
|
||||
-Dkey=value
|
||||
-Dkey
|
||||
|
||||
The key is defined to have the given value. If no value is given, then it is
|
||||
assumed to be "1". The above examples are the same as these defines in
|
||||
Verilog source::
|
||||
|
||||
`define key value
|
||||
`define key
|
||||
|
||||
* -I<path>
|
||||
|
||||
Append directory <path> to list of directories searched for Verilog include
|
||||
files. The -I switch may be used many times to specify several directories
|
||||
to search, the directories are searched in the order they appear on the
|
||||
command line.
|
||||
|
||||
Elaboration Flags
|
||||
-----------------
|
||||
|
||||
These are flags that pass information to the elaboration steps.
|
||||
|
||||
* -P<symbol>=<value>
|
||||
|
||||
Define a parameter using the defparam behavior to override a parameter
|
||||
values. This can only be used for parameters of root module instances.
|
||||
|
||||
* -s <topmodule>
|
||||
|
||||
Specify the top level module to elaborate. Icarus Verilog will by default
|
||||
choose modules that are not instantiated in any other modules, but sometimes
|
||||
that is not sufficient, or instantiates too many modules. If the user
|
||||
specifies one or more root modules with "-s" flags, then they will be used
|
||||
as root modules instead.
|
||||
|
||||
* -Tmin, -Ttyp, -Tmax
|
||||
|
||||
Select the timings to use. The Verilog language allows many timings to be
|
||||
specified as three numbers, min:typical:max, but for simulation you need to
|
||||
choose which set to use. The "-Tmin" flag tells the compiler to at
|
||||
elaboration time choose "min" times. The default is "-Ttyp".
|
||||
|
||||
Target Flags
|
||||
------------
|
||||
@@ -0,0 +1,167 @@
|
||||
|
||||
Getting Started With Icarus Verilog
|
||||
===================================
|
||||
|
||||
Before getting started with actual examples, here are a few notes on
|
||||
conventions. First, command lines and sequences take the same arguments on all
|
||||
supported operating environments, including Linux, Windows and the various
|
||||
Unix systems. When an example command is shown in a figure, the generic prompt
|
||||
character "% " takes the place of whatever prompt string is appropriate for
|
||||
your system. Under Windows, the commands are invoked in a command window.
|
||||
|
||||
Second, when creating a file to hold Verilog code, it is common to use the
|
||||
".v" or the ".vl" suffix. This is not a requirement imposed by Icarus Verilog,
|
||||
but a useful convention. Some people also use the suffixes ".ver" or even
|
||||
".vlg". Examples in this book will use the ".v" suffix.
|
||||
|
||||
So let us start. Given that you are going to use Icarus Verilog as part of
|
||||
your design process, the first thing to do as a designer is learn how to
|
||||
compile and execute even the most trivial design. For the purposes of
|
||||
simulation, we use as our example the most trivial simulation, a simple Hello,
|
||||
World program.
|
||||
|
||||
.. code-block:: verilog
|
||||
|
||||
module hello;
|
||||
initial
|
||||
begin
|
||||
$display("Hello, World");
|
||||
$finish ;
|
||||
end
|
||||
endmodule
|
||||
|
||||
Use a text editor to place the program in a text file, hello.v, then compile
|
||||
this program with the command::
|
||||
|
||||
% iverilog -o hello hello.v
|
||||
|
||||
The results of this compile are placed into the file "hello", because the "-o"
|
||||
flag tells the compiler where to place the compiled result. Next, execute the
|
||||
compiled program like so::
|
||||
|
||||
% vvp hello
|
||||
Hello, World
|
||||
|
||||
And there it is, the program has been executed. So what happened? The first
|
||||
step, the "iverilog" command, read and interpreted the source file, then
|
||||
generated a compiled result. The compiled form may be selected by command line
|
||||
switches, but the default is the "vvp" format, which is actually run later, as
|
||||
needed. The "vvp" command of the second step interpreted the "hello" file from
|
||||
the first step, causing the program to execute.
|
||||
|
||||
The "iverilog" and "vvp" commands are the most important commands available to
|
||||
users of Icarus Verilog. The "iverilog" command is the compiler, and the "vvp"
|
||||
command is the simulation runtime engine. What sort of output the compiler
|
||||
actually creates is controlled by command line switches, but normally it
|
||||
produces output in the default vvp format, which is in turn executed by the
|
||||
vvp program.
|
||||
|
||||
As designs get larger and more complex, they gain hierarchy in the form of
|
||||
modules that are instantiated within others, and it becomes convenient to
|
||||
organize them into multiple files. A common convention is to write one
|
||||
moderate sized module per file (or group related tiny modules into a single
|
||||
file) then combine the files of the design together during compilation. For
|
||||
example, the counter model in counter.v
|
||||
|
||||
.. code-block:: verilog
|
||||
|
||||
module counter(output, clk, reset);
|
||||
|
||||
parameter WIDTH = 8;
|
||||
|
||||
output [WIDTH-1 : 0] output;
|
||||
input clk, reset;
|
||||
|
||||
reg [WIDTH-1 : 0] out;
|
||||
wire clk, reset;
|
||||
|
||||
always @(posedge clk or posedge reset)
|
||||
if (reset)
|
||||
output <= 0;
|
||||
else
|
||||
output <= output + 1;
|
||||
|
||||
endmodule // counter
|
||||
|
||||
and the test bench in counter_tb.v
|
||||
|
||||
.. code-block:: verilog
|
||||
|
||||
module test;
|
||||
|
||||
/* Make a reset that pulses once. */
|
||||
reg reset = 0;
|
||||
initial begin
|
||||
# 17 reset = 1;
|
||||
# 11 reset = 0;
|
||||
# 29 reset = 1;
|
||||
# 11 reset = 0;
|
||||
# 100 $stop;
|
||||
end
|
||||
|
||||
/* Make a regular pulsing clock. */
|
||||
reg clk = 0;
|
||||
always #5 clk = !clk;
|
||||
|
||||
wire [7:0] value;
|
||||
counter c1 (value, clk, reset);
|
||||
|
||||
initial
|
||||
$monitor("At time %t, value = %h (%0d)",
|
||||
$time, value, value);
|
||||
endmodule // test
|
||||
|
||||
are written into different files.
|
||||
|
||||
The "iverilog" command supports multi-file designs by two methods. The
|
||||
simplest is to list the files on the command line::
|
||||
|
||||
% iverilog -o my_design counter_tb.v counter.v
|
||||
% vvp my_design
|
||||
|
||||
This command compiles the design, which is spread across two input files, and
|
||||
generates the compiled result into the "my_design" file. This works for small
|
||||
to medium sized designs, but gets cumbersome when there are lots of files.
|
||||
|
||||
Another technique is to use a commandfile, which lists the input files in a
|
||||
text file. For example, create a text file called "file_list.txt" with the
|
||||
files listed one per line::
|
||||
|
||||
counter.v
|
||||
counter_tb.v
|
||||
|
||||
Then compile and execute the design with a command like so::
|
||||
|
||||
% iverilog -o my_design -c file_list.txt
|
||||
% vvp my_design
|
||||
|
||||
The command file technique clearly supports much larger designs simply by
|
||||
saving you the trouble of listing all the source files on the command
|
||||
line. Name the files that are part of the design in the command file and use
|
||||
the "-c" flag to tell iverilog to read the command file as a list of Verilog
|
||||
input files.
|
||||
|
||||
As designs get more complicated, they almost certainly contain many Verilog
|
||||
modules that represent the hierarchy of your design. Typically, there is one
|
||||
module that instantiates other modules but is not instantiated by any other
|
||||
modules. This is called a root module. Icarus Verilog chooses as roots (There
|
||||
can be more than one root) all the modules that are not instantiated by other
|
||||
modules. If there are no such modules, the compiler will not be able to choose
|
||||
any root, and the designer must use the "-sroot" switch to identify the root
|
||||
module, like this::
|
||||
|
||||
% iverilog -s main -o hello hello.v
|
||||
|
||||
If there are multiple candidate roots, all of them will be elaborated. The
|
||||
compiler will do this even if there are many root modules that you do not
|
||||
intend to simulate, or that have no effect on the simulation. This can happen,
|
||||
for example, if you include a source file that has multiple modules, but are
|
||||
only really interested in some of them. The "-s" flag identifies a specific
|
||||
root module and also turns off the automatic search for other root
|
||||
modules. You can use this feature to prevent instantiation of unwanted roots.
|
||||
|
||||
As designs get even larger, they become spread across many dozens or even
|
||||
hundreds of files. When designs are that complex, more advanced source code
|
||||
management techniques become necessary. These are described in later chapters,
|
||||
along with other advanced design management techniques supported by Icarus
|
||||
Verilog.
|
||||
@@ -0,0 +1,118 @@
|
||||
|
||||
Waveforms With GTKWave
|
||||
======================
|
||||
|
||||
GTKWave is a VCD waveform viewer based on the GTK library. This viewer support
|
||||
VCD and LXT formats for signal dumps. GTKWAVE is available on github
|
||||
`here <https://github.com/gtkwave/gtkwave>`_. Most Linux distributions already
|
||||
include gtkwave prepackaged.
|
||||
|
||||
.. image:: GTKWave_Example2.png
|
||||
|
||||
Generating VCD/FST files for GTKWAVE ------------------------------------
|
||||
Waveform dumps are written by the Icarus Verilog runtime program vvp. The user
|
||||
uses $dumpfile and $dumpvars system tasks to enable waveform dumping, then the
|
||||
vvp runtime takes care of the rest. The output is written into the file
|
||||
specified by the $dumpfile system task. If the $dumpfile call is absent, the
|
||||
compiler will choose the file name dump.vcd or dump.lxt or dump.fst, depending
|
||||
on runtime flags. The example below dumps everything in and below the test
|
||||
module:
|
||||
|
||||
.. code-block:: verilog
|
||||
|
||||
// Do this in your test bench
|
||||
|
||||
initial
|
||||
begin
|
||||
$dumpfile("test.vcd");
|
||||
$dumpvars(0,test);
|
||||
end
|
||||
|
||||
By default, the vvp runtime will generate VCD dump output. This is the default
|
||||
because it is the most portable. However, when using gtkwave, the FST output
|
||||
format is faster and most compact. Use the "-fst" extended argument to
|
||||
activate LXT output. For example, if your compiled output is written into the
|
||||
file "foo.vvp", the command:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
% vvp foo.vvp -fst <other-plusargs>
|
||||
|
||||
will cause the dumpfile output to be written in FST format. Absent any
|
||||
specific $dumpfile command, this file will be called dump.fst, which can be
|
||||
viewed with the command:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
% gtkwave dump.fst
|
||||
|
||||
A Working Example
|
||||
-----------------
|
||||
|
||||
First, the design itself:
|
||||
|
||||
.. code-block:: verilog
|
||||
|
||||
module counter(out, clk, reset);
|
||||
|
||||
parameter WIDTH = 8;
|
||||
|
||||
output [WIDTH-1 : 0] out;
|
||||
input clk, reset;
|
||||
|
||||
reg [WIDTH-1 : 0] out;
|
||||
wire clk, reset;
|
||||
|
||||
always @(posedge clk)
|
||||
out <= out + 1;
|
||||
|
||||
always @reset
|
||||
if (reset)
|
||||
assign out = 0;
|
||||
else
|
||||
deassign out;
|
||||
|
||||
endmodule // counter
|
||||
|
||||
Then the simulation file:
|
||||
|
||||
.. code-block:: verilog
|
||||
|
||||
module test;
|
||||
|
||||
/* Make a reset that pulses once. */
|
||||
reg reset = 0;
|
||||
initial begin
|
||||
$dumpfile("test.vcd");
|
||||
$dumpvars(0,test);
|
||||
|
||||
# 17 reset = 1;
|
||||
# 11 reset = 0;
|
||||
# 29 reset = 1;
|
||||
# 5 reset =0;
|
||||
# 513 $finish;
|
||||
end
|
||||
|
||||
/* Make a regular pulsing clock. */
|
||||
reg clk = 0;
|
||||
always #1 clk = !clk;
|
||||
|
||||
wire [7:0] value;
|
||||
counter c1 (value, clk, reset);
|
||||
|
||||
initial
|
||||
$monitor("At time %t, value = %h (%0d)",
|
||||
$time, value, value);
|
||||
endmodule // test
|
||||
|
||||
Compile, run, and view waveforms with these commands:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
% iverilog -o dsn counter_tb.v counter.v
|
||||
% vvp dsn
|
||||
% gtkwave test.vcd &
|
||||
|
||||
Click on the 'test', then 'c1' in the top left box on GTKWAVE, then drag the
|
||||
signals to the Signals box. You will be able to add signals to display,
|
||||
scanning by scope.
|
||||
@@ -0,0 +1,22 @@
|
||||
|
||||
Icarus Verilog Usage
|
||||
====================
|
||||
|
||||
This section contains documents to help support developers who contribute to
|
||||
Icarus Verilog.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
installation
|
||||
getting_started
|
||||
simulation
|
||||
command_line_flags
|
||||
command_files
|
||||
verilog_attributes
|
||||
vvp_flags
|
||||
gtkwave
|
||||
vvp_debug
|
||||
vpi
|
||||
ivl_target
|
||||
reporting_issues
|
||||
@@ -0,0 +1,146 @@
|
||||
|
||||
Installation Guide
|
||||
==================
|
||||
|
||||
Icarus Verilog may be installed from source code, or from pre-packaged binary
|
||||
distributions. If you don't have need for the very latest, and prepackaged
|
||||
binaries are available, that would be the best place to start.
|
||||
|
||||
Installation From Source
|
||||
------------------------
|
||||
|
||||
Icarus is developed for Unix-like environments but can also be compiled on
|
||||
Windows systems using the Cygwin environment or MinGW compilers. The following
|
||||
instructions are the common steps for obtaining the Icarus Verilog source,
|
||||
compiling and installing. Note that there are precompiled and/or prepackaged
|
||||
versions for a variety of systems, so if you find an appropriate packaged
|
||||
version, then that is the easiest way to install.
|
||||
|
||||
The source code for Icarus is stored under the git source code control
|
||||
system. You can use git to get the latest development head or the latest of a
|
||||
specific branch. Stable releases are placed on branches, and in particular v11
|
||||
stable releases are on the branch "v11-branch" To get the development version
|
||||
of the code follow these steps::
|
||||
|
||||
% git config --global user.name "Your Name Goes Here"
|
||||
% git config --global user.email [email protected]
|
||||
% git clone https://github.com/steveicarus/iverilog.git
|
||||
|
||||
The first two lines are optional and are used to tell git who you are. This
|
||||
information is important if/when you submit a patch. We suggest that you add
|
||||
this information now so you don't forget to do it later. The clone will create
|
||||
a directory, named iverilog, containing the source tree, and will populate
|
||||
that directory with the most current source from the HEAD of the repository.
|
||||
|
||||
Change into this directory using::
|
||||
|
||||
% cd iverilog
|
||||
|
||||
Normally, this is enough as you are now pointing at the most current
|
||||
development code, and you have implicitly created a branch "master" that
|
||||
tracks the development head. However, If you want to actually be working on
|
||||
the v11-branch (the branch where the latest v11 patches are) then you checkout
|
||||
that branch with the command::
|
||||
|
||||
% git checkout --track -b v11-branch origin/v11-branch
|
||||
|
||||
This creates a local branch that tracks the v11-branch in the repository, and
|
||||
switches you over to your new v11-branch. The tracking is important as it
|
||||
causes pulls from the repository to re-merge your local branch with the remote
|
||||
v11-branch. You always work on a local branch, then merge only when you
|
||||
push/pull from the remote repository.
|
||||
|
||||
Now that you've cloned the repository and optionally selected the branch you
|
||||
want to work on, your local source tree may later be synced up with the
|
||||
development source by using the git command::
|
||||
|
||||
% git pull
|
||||
|
||||
The git system remembers the repository that it was cloned from, so you don't
|
||||
need to re-enter it when you pull.
|
||||
|
||||
Finally, configuration files are built by the extra step::
|
||||
|
||||
% sh autoconf.sh
|
||||
|
||||
The source is then compiled as appropriate for your system. See the specific
|
||||
build instructions below for your operation system for what to do next.
|
||||
|
||||
You will need autoconf and gperf installed in order for the script to work.
|
||||
If you get errors such as::
|
||||
|
||||
Autoconf in root...
|
||||
autoconf.sh: 10: autoconf: not found
|
||||
Precompiling lexor_keyword.gperf
|
||||
autoconf.sh: 13: gperf: not found.
|
||||
|
||||
You will need to install download and install the autoconf and gperf tools.
|
||||
|
||||
Icarus Specific Configuration Options
|
||||
-------------------------------------
|
||||
|
||||
Icarus takes many of the standard configuration options and those will not be
|
||||
described here. The following are specific to Icarus::
|
||||
|
||||
--enable-suffix[=suffix]
|
||||
|
||||
This option allows the user to build Icarus with a default suffix or when
|
||||
provided a user defined suffix. Older stable releases have this flag on by
|
||||
default e.g.(V0.8 by default will build with a "-0.8" suffix). All versions
|
||||
have an appropriate default suffix ("-<base_version>").
|
||||
|
||||
All programs or directories are tagged with this suffix. e.g.(iverilog-0.8,
|
||||
vvp-0.8, etc.). The output of iverilog will reference the correct run time
|
||||
files and directories. The run time will check that it is running a file with
|
||||
a compatible version e.g.(you can not run a V0.9 file with the V0.8 run
|
||||
time). ::
|
||||
|
||||
--with-valgrind
|
||||
|
||||
This option adds extra memory cleanup code and pool management code to allow
|
||||
better memory leak checking when valgrind is available. This option is not
|
||||
need when checking for basic errors with valgrind.
|
||||
|
||||
Compiling on Linux/Unix
|
||||
-----------------------
|
||||
|
||||
(Note: You will need to install bison, flex, g++ and gcc) This is probably the
|
||||
easiest case. Given that you have the source tree from the above instructions,
|
||||
the compile and install is generally as simple as::
|
||||
|
||||
% ./configure
|
||||
% make
|
||||
(su to root)
|
||||
# make install
|
||||
|
||||
The "make install" typically needs to be done as root so that it can install
|
||||
in directories such as "/usr/local/bin" etc. You can change where you want to
|
||||
install by passing a prefix to the "configure" command::
|
||||
|
||||
% ./configure --prefix=/my/special/directory
|
||||
|
||||
This will configure the source for eventual installation in the directory that
|
||||
you specify. Note that "rpm" packages of binaries for Linux are typically
|
||||
configured with "--prefix=/usr" per the Linux File System Standard.
|
||||
|
||||
Make sure you have the latest version of flex otherwise you will get an error
|
||||
when parsing lexor.lex.
|
||||
|
||||
Compiling on Macintosh OS X
|
||||
---------------------------
|
||||
|
||||
Since Mac OS X is a BSD flavor of Unix, you can install Icarus Verilog from
|
||||
source using the procedure described above. You need to install the Xcode
|
||||
software, which includes the C and C++ compilers for Mac OS X. The package is
|
||||
available for free download from Apple's developer site. Once Xcode is
|
||||
installed, you can build Icarus Verilog in a terminal window just like any
|
||||
other Unix install.
|
||||
|
||||
For versions newer than 10.3 the GNU Bison tool (packaged with Xcode) needs to
|
||||
be updated to version 3. ::
|
||||
|
||||
brew install bison
|
||||
echo 'export PATH="/usr/local/opt/bison/bin:$PATH"' >> ~/.bash_profile
|
||||
|
||||
Icarus Verilog is also available through the Homebrew package manager: "brew
|
||||
install icarus-verilog".
|
||||
@@ -0,0 +1,106 @@
|
||||
|
||||
Loadable Target API (ivl_target.h)
|
||||
==================================
|
||||
|
||||
In addition to the standard VPI API, Icarus Verilog supports a non-standard
|
||||
loadable target module API. This API helps C programmers write modules that
|
||||
Icarus Verilog can use to generate code. These modules are used at compile
|
||||
time to write the elaborated design to the simulation or netlist files. For
|
||||
example, the vvp code generator is a loadable target module that writes vvp
|
||||
code into the specified file.
|
||||
|
||||
Loadable target modules gain access to the 'elaborated' design. That means,
|
||||
the source files have been checked for syntax and correctness, any synthesis
|
||||
and general optimization steps have been performed, and what is left is a
|
||||
design that reflects but is not exactly the same as the input Verilog source
|
||||
code. This relieves the modules of the burden of supporting all the odd
|
||||
corners and complexities of the Verilog language.
|
||||
|
||||
The Target Module API
|
||||
---------------------
|
||||
|
||||
The API is defined in the header file "ivl_target.h" which is installed with
|
||||
Icarus Verilog. The header defines the functions that the module writer can
|
||||
use to get at the elaborated design during the course of writing the output
|
||||
format.
|
||||
|
||||
The target module API function "target_design" is special in that the API does
|
||||
not provide this function: The target module itself provides it. When the
|
||||
compiler loads the target module, it invokes the "target_design" function with
|
||||
a handle to the design. This is the point where the target module takes over
|
||||
to process the design.
|
||||
|
||||
Compiling Target Modules
|
||||
------------------------
|
||||
|
||||
Compiling loadable target modules is similar to compiling VPI modules, in that
|
||||
the module must be compiled with the "-fPIC" flag to gcc, and linked with the
|
||||
"-shared" flag. The module that you compile is then installed in a place where
|
||||
the "iverilog" command can find it, and configuration files are adjusted to
|
||||
account for the new module.
|
||||
|
||||
This code::
|
||||
|
||||
# include <ivl_target.h>
|
||||
|
||||
int target_design(ivl_design_t des)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
is an example module that we can write into the file "empty.c"; and let us
|
||||
compile it into the module file "empty.tgt" like so::
|
||||
|
||||
% gcc -o empty.tgt -fpic -shared empty.c
|
||||
|
||||
This makes the "empty.tgt" file an a dynamically loaded shared object.
|
||||
|
||||
Creating the Target Config File
|
||||
-------------------------------
|
||||
|
||||
The target config file tells the Icarus Verilog core how to process your new
|
||||
code generator. The ivl core expects two configuration files: the name.conf
|
||||
and the name-s.config files. The "-s" version is what is used if the user
|
||||
gives the "-S" (synthesis) flag on the command line.
|
||||
|
||||
The stub target, included in most distributions, demonstrates the config
|
||||
files. The "stub.conf" file is::
|
||||
|
||||
functor:cprop
|
||||
functor:nodangle
|
||||
-t:dll
|
||||
flag:DLL=stub.tgt
|
||||
|
||||
and the "stub-s.conf" file is::
|
||||
|
||||
functor:synth2
|
||||
functor:synth
|
||||
functor:syn-rules
|
||||
functor:cprop
|
||||
functor:nodangle
|
||||
-t:dll
|
||||
flag:DLL=stub.tgt
|
||||
|
||||
Note that the "stub-s.conf" file contains more lines to invoke internal
|
||||
synthesis functions, whereas the "stub.conf" invokes only the basic
|
||||
optimization steps.
|
||||
|
||||
In general, only the last line (The "flag:DLL=<name>.tgt" record) varies for
|
||||
each target. For your target, replace the <name> with the name of your target
|
||||
and you have a configuration file ready to install. Note that this is the name
|
||||
of your target module. This is in fact how the config file tells the compiler
|
||||
the name of your module.
|
||||
|
||||
The rest of the config file is best taken as boiler plate and installed as is,
|
||||
with one difference. If your target is a synthesis target (for example a mosis
|
||||
code generator or a pld code generator) that expects synthesis to happen, then
|
||||
it makes the most sense to create both your config file like the "stub-s.conf"
|
||||
config file. This causes the compiler to do synthesis for your target whether
|
||||
the user gives the "-S" flag or not.
|
||||
|
||||
Installing the Target Module
|
||||
----------------------------
|
||||
|
||||
Finally, the "empty.conf", the "empty-s.conf" and the "empty.tgt" files need
|
||||
to be installed. Where they go depends on your system, but in Linux they are
|
||||
normally installed in "/usr/lib/ivl".
|
||||
@@ -0,0 +1,37 @@
|
||||
|
||||
Reporting Issues
|
||||
================
|
||||
|
||||
The developers of and contributers to Icarus Verilog use github to track
|
||||
issues and to create patches for the product. If you believe you have found a
|
||||
problem, use the Issues tracker at the
|
||||
`Icarus Verilog github page <https://github.com/steveicarus/iverilog>`_.
|
||||
|
||||
On the main page, you will find a row of selections near the top. Click the
|
||||
`Issues <https://github.com/steveicarus/iverilog/issues>`_ link to get to the
|
||||
list of issues, open and closed. You will find a friendly green button where
|
||||
you can create a new issue. You will be asked to create a title for your
|
||||
issue, and to write a detailed description of your issue. Please include
|
||||
enough information that anyone who sees your issue can understand and
|
||||
reproduce it.
|
||||
|
||||
One key characteristic of a well reported issue is a small sample program that
|
||||
demonstrates the issue. The smaller the better. No developer wants to wade
|
||||
through hundreds of lines of working Verilog to find the few lines that cause
|
||||
trouble, so if you can get it down to a 10 line sample program, then your
|
||||
issue will be far more likely to be addressed.
|
||||
|
||||
Be prepared to have a conversation about your issue. More often then you would
|
||||
expect, the issue turns out to be a bug in your program, and the person
|
||||
looking into your issue may point out a bug in your code. You learn something,
|
||||
and we all win. We are not always correct, though, so if we are incorrect,
|
||||
help us see our error, if that's appropriate. If we don't understand what your
|
||||
issue is, we will label your issue with a "Need info" label, and if we never
|
||||
hear from you again, your issue may be closed summarily.
|
||||
|
||||
If you can submit a complete, working program that we can use in the
|
||||
regression test suite, then that is the best. Check out the existing tests in
|
||||
the regression test suite to see how they are structured. If you have a
|
||||
complete test that can go into the test suite, then that saves everyone a lot
|
||||
of grief, and again you increase the odds that your issue will be addressed.
|
||||
|
||||
@@ -0,0 +1,495 @@
|
||||
|
||||
Simulation Using Icarus Verilog
|
||||
===============================
|
||||
|
||||
Simulation is the process of creating models that mimic the behavior of the
|
||||
device you are designing (simulation models) and creating models to exercise
|
||||
the device (test benches). The simulation model need not reflect any
|
||||
understanding of the underlying technology, and the simulator need not know
|
||||
that the design is intended for any specific technology.
|
||||
|
||||
The Verilog simulator, in fact, is usually a different program than the
|
||||
synthesizer. It may even come from a different vendor. The simulator need not
|
||||
know of or generate netlists for the target technology, so it is possible to
|
||||
write one simulator that can be used to model designs intended for a wide
|
||||
variety of technologies. A synthesizer, on the other hand, does need to know a
|
||||
great deal about the target technology in order to generate efficient
|
||||
netlists. Synthesizers are often technology specific and come from vendors
|
||||
with specialized knowledge, whereas simulators are more general purpose.
|
||||
|
||||
Simulation models and test benches, therefore, can use the full range of
|
||||
Verilog features to model the intended design as clearly as possible. This is
|
||||
the time to test the algorithms of the design using language that is
|
||||
relatively easy for humans to read. The simulator, along with the test bench,
|
||||
can test that the clearly written model really does behave as intended, and
|
||||
that the intended behavior really does meet expectations.
|
||||
|
||||
The test benches model the world outside the design, so they are rarely
|
||||
destined for real hardware. They are written in Verilog simply as a matter of
|
||||
convenience, and sometimes they are not written in Verilog at all. The test
|
||||
benches are not throw-away code either, as they are used to retest the device
|
||||
under test as it is transformed from a simulation model to a synthesizeable
|
||||
description.
|
||||
|
||||
Compilation and Elaboration
|
||||
---------------------------
|
||||
|
||||
Simulation of a design amounts to compiling and executing a program. The
|
||||
Verilog source that represents the simulation model and the test bench is
|
||||
compiled into an executable form and executed by a simulation
|
||||
engine. Internally, Icarus Verilog divides the compilation of program source
|
||||
to an executable form into several steps, and basic understanding of these
|
||||
steps helps understand the nature of failures and errors. The first step is
|
||||
macro preprocessing, then compilation, elaboration, optional optimizations and
|
||||
finally code generation. The boundary between these steps is often blurred,
|
||||
but this progression remains a useful model of the compilation process.
|
||||
|
||||
The macro preprocessing step performs textual substitutions of macros defined
|
||||
with "\`define" statements, textual inclusion with "\`include" statements, and
|
||||
conditional compilation by "\`ifdef" and "\`ifndef" statements. The
|
||||
macropreprocessor for Icarus Verilog is internally a separate program that can
|
||||
be accessed independently by using the "-E" flag to the "iverilog" command,
|
||||
like so::
|
||||
|
||||
% iverilog -E -o out.v example.v
|
||||
|
||||
This command causes the input Verilog file "example.v" to be preprocessed, and
|
||||
the output, a Verilog file without preprocessor statements, written into
|
||||
"out.v". The "\`include" and "\`ifdef" directives in the input file are interpreted,
|
||||
and defined macros substituted, so that the output, a single file, is the same
|
||||
Verilog but with the preprocessor directives gone. All the explicitly
|
||||
specified source files are also combined by the preprocessor, so that the
|
||||
preprocessed result is a single Verilog stream.
|
||||
|
||||
Normally, however, the "-E" flag is not used and the preprocessed Verilog is
|
||||
instead sent directly to the next step, the compiler. The compiler core takes
|
||||
as input preprocessed Verilog and generates an internal parsed form. The
|
||||
parsed form is an internal representation of the Verilog source, in a format
|
||||
convenient for further processing, and is not accessible to the user.
|
||||
|
||||
The next step, elaboration, takes the parsed form, chooses the root modules,
|
||||
and instantiates (makes *instances* of) those roots. The root instances may
|
||||
contain instances of other modules, which may in turn contain instances of yet
|
||||
other modules. The elaboration process creates a hierarchy of module instances
|
||||
that ends with primitive gates and statements.
|
||||
|
||||
Note that there is a difference between a module and a module instance. A
|
||||
module is a type. It is a description of the contents of module instances that
|
||||
have its type. When a module is instantiated within another module, the module
|
||||
name identifies the type of the instance, and the instance name identifies the
|
||||
specific instance of the module. There can be many instances of any given
|
||||
module.
|
||||
|
||||
Root modules are a special case, in that the programmer does not give them
|
||||
instance names. Instead, the instance names of root modules are the same as
|
||||
the name of the module. This is valid because, due to the nature of the
|
||||
Verilog syntax, a module can be a root module only once, so the module name
|
||||
itself is a safe instance name.
|
||||
|
||||
Elaboration creates a hierarchy of scopes. Each module instance creates a new
|
||||
scope within its parent module, with each root module starting a
|
||||
hierarchy. Every module instance in the elaborated program has a unique scope
|
||||
path, a hierarchical name, that starts with its root scope and ends with its
|
||||
own instance name. Every named object, including variables, parameters, nets
|
||||
and gates, also has a hierarchical name that starts with a root scope and ends
|
||||
with its own base name. The compiler uses hierarchical names in error messages
|
||||
generated during or after elaboration, so that erroneous items can be
|
||||
completely identified. These hierarchical names are also used by waveform
|
||||
viewers that display waveform output from simulations.
|
||||
|
||||
The elaboration process creates from the parsed form the scope hierarchy
|
||||
including the primitive objects within each scope. The elaborated design then
|
||||
is optimized to reduce it to a more optimal, but equivalent design. The
|
||||
optimization step takes the fully elaborated design and transforms it to an
|
||||
equivalent design that is smaller or more efficient. These optimizations are,
|
||||
for example, forms of constant propagation and dead code elimination. Useless
|
||||
logic is eliminated, and constant expressions are pre-calculated. The
|
||||
resulting design behaves as if the optimizations were not performed, but is
|
||||
smaller and more efficient. The elimination (and spontaneous creation) of
|
||||
gates and statements only affects the programmer when writing VPI modules,
|
||||
which through the API have limited access to the structures of the design.
|
||||
|
||||
Finally, the optimized design, which is still in an internal form not
|
||||
accessible to users, is passed to a code generator that writes the design into
|
||||
an executable form. For simulation, the code generator is selected to generate
|
||||
the vvp format--a text format that can be executed by the simulation
|
||||
engine. Other code generators may be selected by the Icarus Verilog user, even
|
||||
third party code generators, but the vvp code generator is the default for
|
||||
simulation purposes.
|
||||
|
||||
Making and Using Libraries
|
||||
--------------------------
|
||||
|
||||
Although simple programs may be written into a single source file, this gets
|
||||
inconvenient as the designs get larger. Also, writing the entire program into
|
||||
a single file makes it difficult for different programs to share common
|
||||
code. It therefore makes sense to divide large programs into several source
|
||||
files, and to put generally useful source code files somewhere accessible to
|
||||
multiple designs.
|
||||
|
||||
Once the program is divided into many files, the compiler needs to be told how
|
||||
to find the files of the program. The simplest way to do that is to list the
|
||||
source files on the command line or in a command file. This is for example the
|
||||
best way to divide up and integrate test bench code with the simulation model
|
||||
of the device under test.
|
||||
|
||||
The Macro Preprocessor
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Another technique is to use the macro preprocessor to include library files
|
||||
into a main file. The `include` directive takes the name of a source file to
|
||||
include. The preprocessor inserts the entire contents of the included file in
|
||||
place of the `include` directive. The preprocessor normally looks in the
|
||||
current working directory (the current working directory of the running
|
||||
compiler, and not the directory where the source file is located) for the
|
||||
included file, but the "-I" switch to "iverilog" can add directories to the
|
||||
search locations list. ::
|
||||
|
||||
% iverilog -I/directory/to/search example.v
|
||||
|
||||
It is common to create include directories shared by a set of programs. The
|
||||
preprocessor `include` directive can be used by the individual programs to
|
||||
include the source files that it needs.
|
||||
|
||||
The preprocessor method of placing source code into libraries is general
|
||||
(arbitrary source code can be placed in the included files) but is static, in
|
||||
the sense that the programmer must explicitly include the desired library
|
||||
files. The automatic module library is a bit more constrained, but is
|
||||
automatic.
|
||||
|
||||
Automatic Module Libraries
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
A common use for libraries is to store module definitions that may be of use
|
||||
to a variety of programs. If modules are divided into a single module per
|
||||
file, and the files are named appropriately, and the compiler is told where to
|
||||
look, then the compiler can automatically locate library files when it finds
|
||||
that a module definition is missing.
|
||||
|
||||
For this to work properly, the library files must be Verilog source, they
|
||||
should contain a single module definition, and the files must be named after
|
||||
the module they contain. For example, if the module "AND2" is a module in the
|
||||
library, then it belongs in a file called "AND2.v" and that file contains only
|
||||
the "AND2" module. A library, then, is a directory that contains properly
|
||||
named and formatted source files. ::
|
||||
|
||||
% iverilog -y/library/to/search example.v
|
||||
|
||||
The "-y" flag to "iverilog" tells the compiler to look in the specified
|
||||
directory for library modules whenever the program instantiates a module that
|
||||
is not otherwise defined. The programmer may include several "-y" flags on the
|
||||
command line (or in a command file) and the compiler will search each
|
||||
directory in order until an appropriate library file is found to resolve the
|
||||
module.
|
||||
|
||||
Once a module is defined, either in the program or by reading a library
|
||||
module, the loaded definition is used from then on within the program. If the
|
||||
module is defined within a program file or within an included file, then the
|
||||
included definition is used instead of any library definition. If a module is
|
||||
defined in multiple libraries, then the first definition that the compiler
|
||||
finds is used, and later definitions are never read.
|
||||
|
||||
Icarus Verilog accesses automatic libraries during elaboration, after it has
|
||||
already preprocessed and parsed the non-library source files. Modules in
|
||||
libraries are not candidates for root modules, and are not even parsed unless
|
||||
they are instantiated in other source files. However, a library module may
|
||||
reference other library modules, and reading in a library module causes it to
|
||||
be parsed and elaborated, and further library references resolved, just like a
|
||||
non-library module. The library lookup and resolution process iterates until
|
||||
all referenced modules are resolved, or known to be missing from the
|
||||
libraries.
|
||||
|
||||
The automatic module library technique is useful for including vendor or
|
||||
technology libraries into a program. Many EDA vendors offer module libraries
|
||||
that are formatted appropriately; and with this technique, Icarus Verilog can
|
||||
use them for simulation.
|
||||
|
||||
Advanced Command Files
|
||||
----------------------
|
||||
|
||||
Command files were mentioned in the "Getting Started" chapter, but only
|
||||
briefly. In practice, Verilog programs quickly grow far beyond the usefulness
|
||||
of simple command line options, and even the macro preprocessor lacks the
|
||||
flexibility to combine source and library modules according to the advancing
|
||||
development process.
|
||||
|
||||
The main contents of a command file is a list of Verilog source files. You can
|
||||
name in a command file all the source files that make up your design. This is
|
||||
a convenient way to collect together all the files that make up your
|
||||
design. Compiling the design can then be reduced to a simple command line like
|
||||
the following::
|
||||
|
||||
% iverilog -c example.cf
|
||||
|
||||
The command file describes a configuration. That is, it lists the specific
|
||||
files that make up your design. It is reasonable, during the course of
|
||||
development, to have a set of different but similar variations of your
|
||||
design. These variations may have different source files but also many common
|
||||
source files. A command file can be written for each variation, and each
|
||||
command file lists the source file names used by each variation.
|
||||
|
||||
A configuration may also specify the use of libraries. For example, different
|
||||
configurations may be implementations for different technologies so may use
|
||||
different parts libraries. To make this work, command files may include "-y"
|
||||
statements. These work in command files exactly how they work on "iverilog"
|
||||
command line. Each "-y" flag is followed by a directory name, and the
|
||||
directories are searched for library modules in the order that they are listed
|
||||
in the command file.
|
||||
|
||||
The include search path can also be specified in configuration files with
|
||||
"+incdir+" tokens. These tokens start with the "+incdir+" string, then
|
||||
continue with directory paths, separated from each other with "+" characters
|
||||
(not spaces) for the length of the line.
|
||||
|
||||
Other information can be included in the command file. See the section Command
|
||||
File Format for complete details on what can go in a command file.
|
||||
|
||||
Input Data at Runtime
|
||||
---------------------
|
||||
|
||||
Often, it is useful to compile a program into an executable simulation, then
|
||||
run the simulation with various inputs. This requires some means to pass data
|
||||
and arguments to the compiled program each time it is executed. For example,
|
||||
if the design models a micro-controller, one would like to run the compiled
|
||||
simulation against a variety of different ROM images.
|
||||
|
||||
There are a variety of ways for a Verilog program to get data from the outside
|
||||
world into the program at run time. Arguments can be entered on the command
|
||||
line, and larger amounts of data can be read from files. The simplest method
|
||||
is to take arguments from the command line.
|
||||
|
||||
Consider this running example of a square root calculator
|
||||
|
||||
.. code-block:: verilog
|
||||
|
||||
module sqrt32(clk, rdy, reset, x, .y(acc));
|
||||
input clk;
|
||||
output rdy;
|
||||
input reset;
|
||||
|
||||
input [31:0] x;
|
||||
output [15:0] acc;
|
||||
|
||||
// acc holds the accumulated result, and acc2 is
|
||||
// the accumulated square of the accumulated result.
|
||||
reg [15:0] acc;
|
||||
reg [31:0] acc2;
|
||||
|
||||
// Keep track of which bit I'm working on.
|
||||
reg [4:0] bitl;
|
||||
wire [15:0] bit = 1 << bitl;
|
||||
wire [31:0] bit2 = 1 << (bitl << 1);
|
||||
|
||||
// The output is ready when the bitl counter underflows.
|
||||
wire rdy = bitl[4];
|
||||
|
||||
// guess holds the potential next values for acc,
|
||||
// and guess2 holds the square of that guess.
|
||||
wire [15:0] guess = acc | bit;
|
||||
wire [31:0] guess2 = acc2 + bit2 + ((acc << bitl) << 1);
|
||||
|
||||
task clear;
|
||||
begin
|
||||
acc = 0;
|
||||
acc2 = 0;
|
||||
bitl = 15;
|
||||
end
|
||||
endtask
|
||||
|
||||
initial clear;
|
||||
|
||||
always @(reset or posedge clk)
|
||||
if (reset)
|
||||
clear;
|
||||
else begin
|
||||
if (guess2 <= x) begin
|
||||
acc <= guess;
|
||||
acc2 <= guess2;
|
||||
end
|
||||
bitl <= bitl - 1;
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
One could write the test bench as a program that passes a representative set
|
||||
of input values into the device and checks the output result. However, we can
|
||||
also write a program that takes on the command line an integer value to be
|
||||
used as input to the device. We can write and compile this program, then pass
|
||||
different input values on the run time command line without recompiling the
|
||||
simulation.
|
||||
|
||||
This example demonstrates the use of the "$value$plusargs" to access command
|
||||
line arguments of a simulation
|
||||
|
||||
.. code-block:: verilog
|
||||
|
||||
module main;
|
||||
|
||||
reg clk, reset;
|
||||
reg [31:0] x;
|
||||
wire [15:0] y;
|
||||
wire rdy;
|
||||
|
||||
sqrt32 dut (clk, rdy, reset, x, y);
|
||||
|
||||
always #10 clk = ~clk;
|
||||
|
||||
initial begin
|
||||
clk = 0;
|
||||
reset = 1;
|
||||
|
||||
if (! $value$plusargs("x=%d", x)) begin
|
||||
$display("ERROR: please specify +x=<value> to start.");
|
||||
$finish;
|
||||
end
|
||||
|
||||
#35 reset = 0;
|
||||
|
||||
wait (rdy) $display("y=%d", y);
|
||||
$finish;
|
||||
end // initial begin
|
||||
|
||||
endmodule // main
|
||||
|
||||
The "$value$plusargs" system function takes a string pattern that describes
|
||||
the format of the command line argument, and a reference to a variable that
|
||||
receives the value. The "sqrt_plusargs" program can be compiled and executed
|
||||
like this::
|
||||
|
||||
% iverilog -osqrt_plusargs.vvp sqrt_plusargs.v sqrt.v
|
||||
% vvp sqrt_plusargs.vvp +x=81
|
||||
y= 9
|
||||
|
||||
Notice that the "x=%d" string of the "$value$plusargs" function describes the
|
||||
format of the argument. The "%d" matches a decimal value, which in the sample
|
||||
run is "81". This gets assigned to "x" by the "$value$plusargs" function,
|
||||
which returns TRUE, and the simulation continues from there.
|
||||
|
||||
If two arguments have to be passed to the testbench then the main module would
|
||||
be modified as follows
|
||||
|
||||
.. code-block:: verilog
|
||||
|
||||
module main;
|
||||
|
||||
reg clk, reset;
|
||||
reg [31:0] x;
|
||||
reg [31:0] z;
|
||||
wire [15:0] y1,y2;
|
||||
wire rdy1,rdy2;
|
||||
|
||||
sqrt32 dut1 (clk, rdy1, reset, x, y1);
|
||||
sqrt32 dut2 (clk, rdy2, reset, z, y2);
|
||||
|
||||
always #10 clk = ~clk;
|
||||
|
||||
initial begin
|
||||
clk = 0;
|
||||
reset = 1;
|
||||
|
||||
if (! $value$plusargs("x=%d", x)) begin
|
||||
$display("ERROR: please specify +x=<value> to start.");
|
||||
$finish;
|
||||
end
|
||||
|
||||
if (! $value$plusargs("z=%d", z)) begin
|
||||
$display("ERROR: please specify +z=<value> to start.");
|
||||
$finish;
|
||||
end
|
||||
|
||||
|
||||
#35 reset = 0;
|
||||
|
||||
wait (rdy1) $display("y1=%d", y1);
|
||||
wait (rdy2) $display("y2=%d", y2);
|
||||
$finish;
|
||||
end // initial begin
|
||||
|
||||
endmodule // main
|
||||
|
||||
and the "sqrt_plusargs" program would be compiled and executed as follows::
|
||||
|
||||
% iverilog -osqrt_plusargs.vvp sqrt_plusargs.v sqrt.v
|
||||
% vvp sqrt_plusargs.vvp +x=81 +z=64
|
||||
y1= 9
|
||||
y2= 8
|
||||
|
||||
In general, the "vvp" command that executes the compiled simulation takes a
|
||||
few predefined argument flags, then the file name of the simulation. All the
|
||||
arguments after the simulation file name are extended arguments to "vvp" and
|
||||
are passed to the executed design. Extended arguments that start with a "+"
|
||||
character are accessible through the "$test$plusargs" and "$value$plusargs"
|
||||
system functions. Extended arguments that do not start with a "+" character
|
||||
are only accessible to system tasks and functions written in C using the VPI.
|
||||
|
||||
In the previous example, the program pulls the argument from the command line,
|
||||
assigns it to the variable "x", and runs the sqrt device under test with that
|
||||
value. This program can take the integer square root of any single value. Of
|
||||
course, if you wish to test with a large number of input values, executing the
|
||||
program many times may become tedious.
|
||||
|
||||
Another technique would be to put a set of input values into a data file, and
|
||||
write the test bench to read the file. We can then edit the file to add new
|
||||
input values, then rerun the simulation without compiling it again. The
|
||||
advantage of this technique is that we can accumulate a large set of test
|
||||
input values, and run the lot as a batch.
|
||||
|
||||
This example
|
||||
|
||||
.. code-block:: verilog
|
||||
|
||||
module main;
|
||||
|
||||
reg clk, reset;
|
||||
reg [31:0] data[4:0];
|
||||
reg [31:0] x;
|
||||
wire [15:0] y;
|
||||
wire rdy;
|
||||
|
||||
sqrt32 dut (clk, rdy, reset, x, y);
|
||||
|
||||
always #10 clk = ~clk;
|
||||
|
||||
integer i;
|
||||
initial begin
|
||||
/* Load the data set from the hex file. */
|
||||
$readmemh("sqrt.hex", data);
|
||||
for (i = 0 ; i <= 4 ; i = i + 1) begin
|
||||
clk = 0;
|
||||
reset = 1;
|
||||
|
||||
x = data[i];
|
||||
|
||||
#35 reset = 0;
|
||||
|
||||
wait (rdy) $display("y=%d", y);
|
||||
end
|
||||
$finish;
|
||||
end // initial begin
|
||||
|
||||
endmodule // main
|
||||
|
||||
demonstrates the use of "$readmemh" to read data samples from a file into a
|
||||
Verilog array. Start by putting into the file "sqrt.hex" the numbers::
|
||||
|
||||
51
|
||||
19
|
||||
1a
|
||||
18
|
||||
1
|
||||
|
||||
Then run the simulation with the command sequence::
|
||||
|
||||
% iverilog -osqrt_readmem.vvp sqrt_readmem.vl sqrt.vl
|
||||
% vvp sqrt_readmem.vvp
|
||||
y= 9
|
||||
y= 5
|
||||
y= 5
|
||||
y= 4
|
||||
y= 1
|
||||
|
||||
It is easy enough to change this program to work with larger data sets, or to
|
||||
change the "data.hex" file to contain different data. This technique is also
|
||||
common for simulating algorithms that take in larger data sets. One can extend
|
||||
this idea slightly by using a "$value$plusargs" statement to select the file
|
||||
to read.
|
||||
@@ -0,0 +1,35 @@
|
||||
|
||||
Verilog Attributes
|
||||
==================
|
||||
|
||||
This is a description of the various attributes that the Icarus Verilog tools
|
||||
understand. The attributes are attached to objects using the "(\* ... \*)"
|
||||
syntax, which is described by the Verilog LRM.
|
||||
|
||||
Attributes that start with "ivl\_" are Icarus Verilog specific are are probably
|
||||
ignored by other tools.
|
||||
|
||||
Optimizations
|
||||
-------------
|
||||
|
||||
* ivl_do_not_elide (snapshot 20140619 or later)
|
||||
|
||||
This applies to signals (i.e. reg, wire, etc.) and tells the optimizer to
|
||||
not elide the signal, even if it is not referenced anywhere in the
|
||||
design. This is useful if the signal is for some reason only accessed by
|
||||
VPI/PLI code.
|
||||
|
||||
Synthesis
|
||||
---------
|
||||
|
||||
* ivl_synthesis_cell
|
||||
|
||||
Applied to a module definition, this tells the synthesizer that the module
|
||||
is a cell. The synthesizer does not descend into synthesis cells, as they
|
||||
are assumed to be primitives in the target technology.
|
||||
|
||||
* ivl_synthesis_off
|
||||
|
||||
Attached to an "always" statement, this tells the synthesizer that the
|
||||
statement is not to be synthesized. This may be useful, for example, to tell
|
||||
the compiler that a stretch of code is test-bench code.
|
||||
@@ -0,0 +1,246 @@
|
||||
|
||||
Using VPI
|
||||
=========
|
||||
|
||||
Icarus Verilog implements a portion of the PLI 2.0 API to Verilog. This allows
|
||||
programmers to write C code that interfaces with Verilog simulations to
|
||||
perform tasks otherwise impractical with straight Verilog. Many Verilog
|
||||
designers, especially those who only use Verilog as a synthesis tool, can
|
||||
safely ignore the entire matter of the PLI (and this chapter) but the designer
|
||||
who wishes to interface a simulation with the outside world cannot escape VPI.
|
||||
|
||||
The rest of this article assumes some knowledge of C programming, Verilog PLI,
|
||||
and of the compiler on your system. In most cases, Icarus Verilog assumes the
|
||||
GNU Compilation System is the compiler you are using, so tips and instructions
|
||||
that follow reflect that. If you are not a C programmer, or are not planning
|
||||
any VPI modules, you can skip this entire article. There are references at the
|
||||
bottom for information about more general topics.
|
||||
|
||||
How It Works
|
||||
------------
|
||||
|
||||
The VPI modules are compiled loadable object code that the runtime loads at
|
||||
the user's request. The user commands vvp to locate and load modules with the
|
||||
"-m" switch. For example, to load the "sample.vpi" module::
|
||||
|
||||
% vvp -msample foo.vvp
|
||||
|
||||
The vvp run-time loads the modules first, before executing any of the
|
||||
simulation, or even before compiling the vvp code. Part of the loading
|
||||
includes invoking initialization routines. These routines register with the
|
||||
run-time all the system tasks and functions that the module implements. Once
|
||||
this is done, the run time loader can match names of the called system tasks
|
||||
of the design with the implementations in the VPI modules.
|
||||
|
||||
(There is a special module, the system.vpi module, that is always loaded to
|
||||
provide the core system tasks.)
|
||||
|
||||
The simulator run time (The "vvp" program) gets a handle on a freshly loaded
|
||||
module by looking for the symbol "vlog_startup_routines" in the loaded
|
||||
module. This table, provided by the module author and compiled into the
|
||||
module, is a null terminated table of function pointers. The simulator calls
|
||||
each of the functions in the table in order. The following simple C definition
|
||||
defines a sample table::
|
||||
|
||||
void (*vlog_startup_routines[])() = {
|
||||
hello_register,
|
||||
0
|
||||
};
|
||||
|
||||
Note that the "vlog_startup_routines" table is an array of function pointers,
|
||||
with the last pointer a 0 to mark the end. The programmer can organize the
|
||||
module to include many startup functions in this table, if desired.
|
||||
|
||||
The job of the startup functions that are collected in the startup table is to
|
||||
declare the system tasks and functions that the module provides. A module may
|
||||
implement as many tasks/functions as desired, so a module can legitimately be
|
||||
called a library of system tasks and functions.
|
||||
|
||||
Compiling VPI Modules
|
||||
---------------------
|
||||
|
||||
To compile and link a VPI module for use with Icarus Verilog, you must compile
|
||||
all the source files of a module as if you were compiling for a DLL or shared
|
||||
object. With gcc under Linux, this means compiling with the "-fpic" flag. The
|
||||
module is then linked together with the vpi library like so::
|
||||
|
||||
% gcc -c -fpic hello.c
|
||||
% gcc -shared -o hello.vpi hello.o -lvpi
|
||||
|
||||
This assumes that the "vpi_user.h header file and the libvpi.a library file
|
||||
are installed on your system so that gcc may find them. This is normally the
|
||||
case under Linux and UNIX systems. An easier, the preferred method that works
|
||||
on all supported systems is to use the single command::
|
||||
|
||||
% iverilog-vpi hello.c
|
||||
|
||||
The "iverilog-vpi" command takes as command arguments the source files for
|
||||
your VPI module, compiles them with proper compiler flags, and links them into
|
||||
a vpi module with any system specific libraries and linker flags that are
|
||||
required. This simple command makes the "hello.vpi" module with minimum fuss.
|
||||
|
||||
A Worked Example
|
||||
----------------
|
||||
|
||||
Let us try a complete, working example. Place the C code that follows into the
|
||||
file hello.c::
|
||||
|
||||
# include <vpi_user.h>
|
||||
|
||||
static int hello_compiletf(char*user_data)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hello_calltf(char*user_data)
|
||||
{
|
||||
vpi_printf("Hello, World!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void hello_register()
|
||||
{
|
||||
s_vpi_systf_data tf_data;
|
||||
|
||||
tf_data.type = vpiSysTask;
|
||||
tf_data.tfname = "$hello";
|
||||
tf_data.calltf = hello_calltf;
|
||||
tf_data.compiletf = hello_compiletf;
|
||||
tf_data.sizetf = 0;
|
||||
tf_data.user_data = 0;
|
||||
vpi_register_systf(&tf_data);
|
||||
}
|
||||
|
||||
void (*vlog_startup_routines[])() = {
|
||||
hello_register,
|
||||
0
|
||||
};
|
||||
|
||||
and place the Verilog code that follows into hello.v::
|
||||
|
||||
module main;
|
||||
initial $hello;
|
||||
endmodule
|
||||
|
||||
Next, compile and execute the code with these steps::
|
||||
|
||||
% iverilog-vpi hello.c
|
||||
% iverilog -ohello.vvp hello.v
|
||||
% vvp -M. -mhello hello.vvp
|
||||
Hello, World!
|
||||
|
||||
The compile and link in this example are conveniently combined into the
|
||||
"iverilog-vpi" command. The "iverilog" command then compiles the "hello.v"
|
||||
Verilog source file to the "hello.vvp" program. Next, the "vvp" command
|
||||
demonstrates the use of the "-M" and "-m" flags to specify a vpi module search
|
||||
directory and vpi module name. Specifically, they tell the "vvp" command where
|
||||
to find the module we just compiled.
|
||||
|
||||
The "vvp" command, when executed as above, loads the "hello.vpi" module that
|
||||
it finds in the current working directory. When the module is loaded, the
|
||||
vlog_startup_routines table is scanned, and the "hello_register" function is
|
||||
executed. The "hello_register" function in turn tells "vvp" about the system
|
||||
tasks that are included in this module.
|
||||
|
||||
After the modules are all loaded, the "hello.vvp" design file is loaded and
|
||||
its call to the "$hello" system task is matched up to the version declared by
|
||||
the module. While "vvp" compiles the "hello.vvp" source, any calls to "$hello"
|
||||
are referred to the "compiletf" function. This function is called at compile
|
||||
time and can be used to check parameters to system tasks or function. It can
|
||||
be left empty like this, or left out completely. The "compiletf" function can
|
||||
help performance by collecting parameter checks in compile time, so they do
|
||||
not need to be done each time the system task is run, thus potentially saving
|
||||
execution time overall.
|
||||
|
||||
When the run-time executes the call to the hello system task, the
|
||||
"hello_calltf" function is invoked in the loaded module, and thus the output
|
||||
is generated. The "calltf" function is called at run time when the Verilog
|
||||
code actually executes the system task. This is where the active code of the
|
||||
task belongs.
|
||||
|
||||
System Function Return Types
|
||||
----------------------------
|
||||
|
||||
Icarus Verilog supports system functions as well as system tasks, but there is
|
||||
a complication. Notice how the module that you compile is only loaded by the
|
||||
"vvp" program. This is mostly not an issue, but elaboration of expressions
|
||||
needs to keep track of types, so the main compiler needs to know the return
|
||||
type of functions.
|
||||
|
||||
Starting with Icarus Verilog v11, the solution is quite simple. The names and
|
||||
locations of the user's VPI modules can be passed to the compiler via the
|
||||
"iverilog" -m and -L flags and the IVERILOG_VPI_MODULE_PATH environment
|
||||
variable. The compiler will load and analyse the specified modules to
|
||||
automatically determine any function return types. The compiler will also
|
||||
automatically pass the names and locations of the specified modules to the
|
||||
"vvp" program, so that they don't need to be specified again on the "vvp"
|
||||
command line.
|
||||
|
||||
For Icarus Verilog versions prior to v11, the solution requires that the
|
||||
developer of a module include the table in a form that the compiler can
|
||||
read. The System Function Table file carries this information. A simple
|
||||
example looks like this::
|
||||
|
||||
# Example sft declarations of some common functions
|
||||
$random vpiSysFuncInt
|
||||
$bitstoreal vpiSysFuncReal
|
||||
$realtobits vpiSysFuncSized 64 unsigned
|
||||
|
||||
This demonstrates the format of the file and support types. Each line contains
|
||||
a comment (starts with "#") or a type declaration for a single function. The
|
||||
declaration starts with the name of the system function (including the leading
|
||||
"$") and ends with the type. The supported types are:
|
||||
|
||||
* vpiSysFuncInt
|
||||
* vpiSysFuncReal
|
||||
* vpiSysFuncSized <wid> <signed|unsigned>
|
||||
|
||||
Any functions that do not have an explicit type declaration in an SFT file are
|
||||
implicitly taken to be "vpiSysFuncSized 32 unsigned".
|
||||
|
||||
The module author provides, along with the ".vpi" file that is the module, a
|
||||
".sft" that declares all the function return types. For example, if the file
|
||||
is named "example.sft", pass it to the "iverilog" command line or in the
|
||||
command file exactly as if it were an ordinary source file.
|
||||
|
||||
Cadence PLI Modules
|
||||
-------------------
|
||||
|
||||
With the cadpli module, Icarus Verilog is able to load PLI1 applications that
|
||||
were compiled and linked to be dynamic loaded by Verilog-XL or
|
||||
NC-Verilog. This allows Icarus Verilog users to run third-party modules that
|
||||
were compiled to interface with XL or NC. Obviously, this only works on the
|
||||
operating system that the PLI application was compiled to run on. For example,
|
||||
a Linux module can only be loaded and run under Linux. In addition, a 64-bit
|
||||
version of vvp can only load 64-bit PLI1 applications, etc.
|
||||
|
||||
Icarus Verilog uses an interface module, the "cadpli" module, to connect the
|
||||
worlds. This module is installed with Icarus Verilog, and is invoked by the
|
||||
usual -m flag to iverilog or vvp. This module in turn scans the extended
|
||||
arguments, looking for -cadpli= arguments. The latter specify the share object
|
||||
and bootstrap function for running the module. For example, to run the module
|
||||
product.so, that has the bootstrap function "my_boot"::
|
||||
|
||||
% vvp -mcadpli a.out -cadpli=./product.so:my_boot
|
||||
|
||||
The "-mcadpli" argument causes vvp to load the cadpli.vpl library module. This
|
||||
activates the -cadpli= argument interpreter. The -cadpli=<module>:<boot_func>
|
||||
argument, then, causes vvp, through the cadpli module, to load the loadable
|
||||
PLI application, invoke the my_boot function to get a veriusertfs table, and
|
||||
scan that table to register the system tasks and functions exported by that
|
||||
object. The format of the -cadpli= extended argument is essentially the same
|
||||
as the +loadpli1= argument to Verilog-XL.
|
||||
|
||||
The integration from this point is seamless. The PLI application hardly knows
|
||||
that it is being invoked by Icarus Verilog instead of Verilog-XL, so operates
|
||||
as it would otherwise.
|
||||
|
||||
Other References
|
||||
----------------
|
||||
|
||||
Since the above only explains how to get PLI/VPI working with Icarus Verilog,
|
||||
here are some references to material to help with the common aspects of
|
||||
PLI/VPI.
|
||||
|
||||
* Principles of Verilog PLI by Swapnajit Mittra. ISBN 0-7923-8477-6
|
||||
* The Verilog PLI Handbook by Stuart Sutherland. ISBN 0-7923-8489-X
|
||||
@@ -0,0 +1,148 @@
|
||||
Vvp Interactive Mode
|
||||
====================
|
||||
|
||||
The vvp command has an interactive debug mode, where you can stop the
|
||||
simulation and browse the current state of the simulation. There are
|
||||
a couple ways to enter the debug mode, but once in interactive debug
|
||||
mode, the usage is the same. Consider the example below:
|
||||
|
||||
.. code-block:: verilog
|
||||
|
||||
module clock(output reg clock);
|
||||
initial clock = 1'b1;
|
||||
always #100 clock = !clock;
|
||||
endmodule // clock
|
||||
|
||||
module main;
|
||||
|
||||
reg [2:0] foo;
|
||||
wire clk;
|
||||
|
||||
clock foo_clock(clk);
|
||||
|
||||
always @(posedge clk)
|
||||
foo <= foo + 1;
|
||||
|
||||
initial begin
|
||||
foo = 3'b000;
|
||||
#250 $stop;
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
In examples that follow, we will use the above sample program.
|
||||
|
||||
Enter Interactive Mode
|
||||
----------------------
|
||||
|
||||
The first and most common method is to put "$stop" system task
|
||||
calls in the simulation at the times where you want to simulation
|
||||
to break and enter interactive mode. The example above has a $stop,
|
||||
so the output looks like this::
|
||||
|
||||
../foo.vl:25: $stop called at 250 (1s)
|
||||
** VVP Stop(0) **
|
||||
** Flushing output streams.
|
||||
** Current simulation time is 250 ticks.
|
||||
>
|
||||
|
||||
You can get some interactive help by using the "help" command::
|
||||
|
||||
> help
|
||||
Commands can be from the following table of base commands,
|
||||
or can be invocations of system tasks/functions.
|
||||
|
||||
cd - Synonym for push.
|
||||
cont - Resume (continue) the simulation
|
||||
finish - Finish the simulation.
|
||||
help - Get help.
|
||||
list - List items in the current scope.
|
||||
load - Load a VPI module, a la vvp -m.
|
||||
ls - Shorthand for "list".
|
||||
pop - Pop one scope from the scope stack.
|
||||
push - Descend into the named scope.
|
||||
step - Single-step the scheduler for 1 event.
|
||||
time - Print the current simulation time.
|
||||
trace - Control statement tracing (on/off) when the code is instrumented.
|
||||
where - Show current scope, and scope hierarchy stack.
|
||||
|
||||
If the command name starts with a '$' character, it
|
||||
is taken to be the name of a system task, and a call is
|
||||
built up and executed. For example, "$display foo" will
|
||||
call the function as $display(foo).
|
||||
|
||||
You can also enter interactive mode at the terminal by interrupting the
|
||||
execution with a "^C" (Control-C) character. The vvp engine catches the
|
||||
terminal interrupt and drops you into the interactive prompt::
|
||||
|
||||
^C** VVP Stop(0) **
|
||||
** Flushing output streams.
|
||||
** Current simulation time is 533928600 ticks.
|
||||
>
|
||||
|
||||
This could be useful if you suspect that your simulation is stuck in
|
||||
an infinite loop and you want to rummage around and see what's going on.
|
||||
|
||||
And finally, you can pass the "-s" command line flag to vvp to tell it
|
||||
to execute "$stop" at the beginning of the simulation, before any other
|
||||
events are executed. This may be useful as a way to manually set up some
|
||||
details about the simulation.
|
||||
|
||||
Browsing the Design
|
||||
-------------------
|
||||
|
||||
Now that you are in the interactive prompt, you can browse
|
||||
around the design::
|
||||
|
||||
> ls
|
||||
2 items in this scope:
|
||||
package : $unit
|
||||
module : main
|
||||
> cd main
|
||||
> ls
|
||||
3 items in this scope:
|
||||
reg : foo[2:0]
|
||||
module : foo_clock
|
||||
net : clk
|
||||
> where
|
||||
module main
|
||||
> $display foo
|
||||
1
|
||||
> cd foo_clock
|
||||
> where
|
||||
module foo_clock
|
||||
module main
|
||||
> ls
|
||||
2 items in this scope:
|
||||
port : clock -- output
|
||||
reg : clock
|
||||
|
||||
In the above example, the 'cd' and 'pop' commands descend into a scope
|
||||
or pop back up a scope level. The 'where' command shows the scope stack,
|
||||
and the 'ls' command lists the items present in the scope. With these
|
||||
commands, one can browse freely throughout the design scope hierarchy.
|
||||
|
||||
It is also possible to call system tasks within the debug mode. The call
|
||||
to the "$display" function is an example of this. In general, any system
|
||||
task can be invoked, in the current context, with the objects that are
|
||||
included on the command line passed as arguments. The arguments can be
|
||||
variables or nets, and various kinds of literals::
|
||||
|
||||
> ls
|
||||
2 items in this scope:
|
||||
port : clock -- output
|
||||
reg : clock
|
||||
> $display "Hello, World! " 10 " " clock
|
||||
Hello, World! 10 1
|
||||
|
||||
This is a great way to call custom system tasks as well. And system task
|
||||
that vvp knows about can be invoked this way.
|
||||
|
||||
Leave Interactive Mode
|
||||
----------------------
|
||||
|
||||
After you are done probing around in the interactive mode, you can
|
||||
resume the simulation, or termimate execution. Resume the simulation
|
||||
with the "cont" command, and terminate the simulation with the
|
||||
"finish" command. The latter is the same as executing the
|
||||
"$finish" system task.
|
||||
@@ -0,0 +1,109 @@
|
||||
VVP Command Line Flags
|
||||
======================
|
||||
|
||||
The vvp command is the simulation run-time engine. The command line for vvp
|
||||
execution is first the options and flags, then the vvp input file, and finally
|
||||
extended arguments. Typical usage looks like this::
|
||||
|
||||
% vvp <flags> foo.vvp <extended arguments>
|
||||
|
||||
Options/Flags
|
||||
-------------
|
||||
|
||||
These options/flags go before the path to the vvp-executable program. They
|
||||
effect behavior of the vvp runtime engine, including preparation for
|
||||
simulation.
|
||||
|
||||
* -l<logfile>
|
||||
|
||||
This flag specifies a logfile where all MCI <stdlog> output goes. Specify
|
||||
logfile as '-' to send log output to <stderr>. $display and friends send
|
||||
their output both to <stdout> and <stdlog>.
|
||||
|
||||
* -M<path>
|
||||
|
||||
Add the directory path to the (VPI) module search path. Multiple "-M" flags
|
||||
are allowed, and the directories are added in the order that they are given
|
||||
on the command line.
|
||||
|
||||
The string "-M-" is special, in that it doesn't add a directory to the
|
||||
path. It instead *removes* the compiled directory. This is generally used
|
||||
only for development of the vvp engine.
|
||||
|
||||
* -m<module>
|
||||
|
||||
Name a VPI module that should be loaded. The vvp engine looks for the named
|
||||
module in the module search path, which includes the compiled in default
|
||||
directory and directories given by "-M" flags.
|
||||
|
||||
NOTE: Starting with v11.0, the VPI modules to be loaded can be specified
|
||||
when you compile your design. This allows the compiler to automatically
|
||||
determine the return types of user-defined system functions. If specified at
|
||||
compile-time, there is no need to specify them again here.
|
||||
|
||||
* -s
|
||||
|
||||
$stop right away, in the beginning of the simulation. This kicks the
|
||||
vvp program into interactive debug mode.
|
||||
|
||||
* -v
|
||||
|
||||
Show verbose progress while setting up or cleaning up the runtime
|
||||
engine. This also displays some performance information.
|
||||
|
||||
Extended Arguments
|
||||
------------------
|
||||
|
||||
The extended arguments are available to the simulation runtime, especially
|
||||
system tasks, system functions and any VPI/PLI code. Extended arguments that
|
||||
start with a "+" character are left for use by the user via the $plus$flag and
|
||||
$plus$value functions.
|
||||
|
||||
VCD/FST/LXT Arguments
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
If not otherwise specified, the vvp engine will by default use VCD formats to
|
||||
support the $dumpvars system task. The flags described here can alter that
|
||||
behavior.
|
||||
|
||||
* -none/-vcd-none/-vcd-off/-fst-none
|
||||
|
||||
Disable trace output. The trace output will be stubbed so that no trace file
|
||||
is created and the cost of dumping is avoided. All off these options are
|
||||
synonyms for turning of dumping.
|
||||
|
||||
* -fst
|
||||
|
||||
Generate FST format outputs instead of VCD format waveform dumps. This is
|
||||
the preferred output format if using GTKWave for viewing waveforms.
|
||||
|
||||
* -lxt/-lxt2
|
||||
|
||||
Generate LXT or LXT2format instead of VCD format waveform dumps. The LXT2
|
||||
format is more advanced.
|
||||
|
||||
SDF Support
|
||||
^^^^^^^^^^^
|
||||
|
||||
The Icarus Verilog support for SDF back-annotation can take some extended
|
||||
arguments to control aspects of SDF support.
|
||||
|
||||
* -sdf-warn
|
||||
|
||||
Print warnings during load of/annotation from an SDF file.
|
||||
|
||||
* -sdf-info
|
||||
|
||||
Print interesting information about an SDF file while parsing it.
|
||||
|
||||
* -sdf-verbose
|
||||
|
||||
Print warnings and info messages.
|
||||
|
||||
Environment Variables
|
||||
---------------------
|
||||
|
||||
The vvp program pays attention to certain environment variables.
|
||||
|
||||
* IVERILOG_DUMPER
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef IVL_HName_H
|
||||
#define IVL_HName_H
|
||||
/*
|
||||
* Copyright (c) 2001-2014 Stephen Williams ([email protected])
|
||||
* Copyright (c) 2001-2021 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -36,7 +36,7 @@
|
||||
|
||||
class hname_t {
|
||||
|
||||
friend ostream& operator<< (ostream&out, const hname_t&that);
|
||||
friend std::ostream& operator<< (std::ostream&out, const hname_t&that);
|
||||
|
||||
public:
|
||||
hname_t ();
|
||||
@@ -92,14 +92,14 @@ inline size_t hname_t::has_numbers() const
|
||||
return number_.size();
|
||||
}
|
||||
|
||||
extern ostream& operator<< (ostream&, const hname_t&);
|
||||
extern std::ostream& operator<< (std::ostream&, const hname_t&);
|
||||
|
||||
inline bool operator != (const hname_t&l, const hname_t&r)
|
||||
{ return ! (l == r); }
|
||||
|
||||
inline ostream& operator<< (ostream&out, const list<hname_t>&ll)
|
||||
inline std::ostream& operator<< (std::ostream&out, const std::list<hname_t>&ll)
|
||||
{
|
||||
list<hname_t>::const_iterator cur = ll.begin();
|
||||
std::list<hname_t>::const_iterator cur = ll.begin();
|
||||
out << *cur;
|
||||
++ cur;
|
||||
while (cur != ll.end()) {
|
||||
|
||||
@@ -19,8 +19,8 @@ diffs or instructions to the address given in the `README' so they can
|
||||
be considered for the next release. If at some point `config.cache'
|
||||
contains results you don't want to keep, you may remove or edit it.
|
||||
|
||||
The file `configure.in' is used to create `configure' by a program
|
||||
called `autoconf'. You only need `configure.in' if you want to change
|
||||
The file `configure.ac' is used to create `configure' by a program
|
||||
called `autoconf'. You only need `configure.ac' if you want to change
|
||||
it or regenerate `configure' using a newer version of `autoconf'.
|
||||
|
||||
The simplest way to compile this package is:
|
||||
@@ -178,4 +178,3 @@ operates.
|
||||
script, and exit.
|
||||
|
||||
`configure' also accepts some other, not widely useful, options.
|
||||
|
||||
|
||||
+5
-4
@@ -106,7 +106,7 @@ FF = cprop.o exposenodes.o nodangle.o synth.o synth2.o syn-rules.o
|
||||
O = main.o async.o design_dump.o discipline.o dup_expr.o elaborate.o \
|
||||
elab_expr.o elaborate_analog.o elab_lval.o elab_net.o \
|
||||
elab_scope.o elab_sig.o elab_sig_analog.o elab_type.o \
|
||||
emit.o eval.o eval_attrib.o \
|
||||
emit.o eval_attrib.o \
|
||||
eval_tree.o expr_synth.o functor.o lexor.o lexor_keyword.o link_const.o \
|
||||
load_module.o netlist.o netmisc.o nettypes.o net_analog.o net_assign.o \
|
||||
net_design.o netclass.o netdarray.o \
|
||||
@@ -116,7 +116,7 @@ O = main.o async.o design_dump.o discipline.o dup_expr.o elaborate.o \
|
||||
net_nex_input.o net_nex_output.o net_proc.o net_scope.o net_tran.o \
|
||||
net_udp.o pad_to_width.o parse.o parse_misc.o pform.o pform_analog.o \
|
||||
pform_disciplines.o pform_dump.o pform_package.o pform_pclass.o \
|
||||
pform_class_type.o pform_string_type.o pform_struct_type.o pform_types.o \
|
||||
pform_types.o \
|
||||
symbol_search.o sync.o sys_funcs.o verinum.o verireal.o vpi_modules.o target.o \
|
||||
Attrib.o HName.o Module.o PClass.o PDelays.o PEvent.o PExpr.o PFunction.o \
|
||||
PGate.o PGenerate.o PModport.o PNamedItem.o PPackage.o PScope.o PSpec.o \
|
||||
@@ -175,10 +175,11 @@ endif
|
||||
rm -rf autom4te.cache
|
||||
|
||||
cppcheck: $(O:.o=.cc) $(srcdir)/dosify.c $(srcdir)/version.c
|
||||
cppcheck --enable=all --std=posix --std=c99 --std=c++03 -f \
|
||||
cppcheck --enable=all --std=c99 --std=c++03 -f \
|
||||
--suppressions-list=$(srcdir)/cppcheck.sup \
|
||||
-UYYPARSE_PARAM -UYYPRINT -Ushort -Usize_t -Uyyoverflow \
|
||||
-UYYTYPE_INT8 -UYYTYPE_INT16 -UYYTYPE_UINT8 -UYYTYPE_UINT16 \
|
||||
-UYYSTYPE -U__SIZE_TYPE__ -Umalloc -Ufree \
|
||||
--relative-paths=$(srcdir) $(INCLUDE_PATH) $^
|
||||
|
||||
cppcheck-all:
|
||||
@@ -202,7 +203,7 @@ stamp-_pli_types-h: $(srcdir)/_pli_types.h.in config.status
|
||||
./config.status _pli_types.h
|
||||
_pli_types.h: stamp-_pli_types-h
|
||||
|
||||
$(srcdir)/configure: $(srcdir)/configure.in $(srcdir)/aclocal.m4
|
||||
$(srcdir)/configure: $(srcdir)/configure.ac $(srcdir)/aclocal.m4
|
||||
cd $(srcdir) && autoconf
|
||||
|
||||
config.status: $(srcdir)/configure
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998-2019 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2021 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -24,6 +24,8 @@
|
||||
# include "PWire.h"
|
||||
# include <cassert>
|
||||
|
||||
using namespace std;
|
||||
|
||||
list<Module::named_expr_t> Module::user_defparms;
|
||||
|
||||
/* n is a permallocated string. */
|
||||
@@ -104,6 +106,11 @@ perm_string Module::get_port_name(unsigned idx) const
|
||||
return ports[idx]->name;
|
||||
}
|
||||
|
||||
PExpr* Module::get_port_default_value(unsigned idx) const
|
||||
{
|
||||
assert(idx < ports.size());
|
||||
return ports[idx] ? ports[idx]->default_value : 0;
|
||||
}
|
||||
|
||||
|
||||
PGate* Module::get_gate(perm_string name)
|
||||
@@ -132,3 +139,19 @@ PNamedItem::SymbolType Module::symbol_type() const
|
||||
|
||||
return MODULE;
|
||||
}
|
||||
|
||||
bool Module::can_be_toplevel() const
|
||||
{
|
||||
// Don't choose library modules.
|
||||
if (library_flag)
|
||||
return false;
|
||||
|
||||
// Don't choose modules with parameters without default value
|
||||
for (std::map<perm_string,param_expr_t*>::const_iterator cur =
|
||||
parameters.begin(); cur != parameters.end(); cur++) {
|
||||
if (cur->second->expr == 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef IVL_Module_H
|
||||
#define IVL_Module_H
|
||||
/*
|
||||
* Copyright (c) 1998-2019 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2021 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -60,11 +60,13 @@ class Module : public PScopeExtra, public PNamedItem {
|
||||
objects. Each port has a name and an ordered list of
|
||||
wires. The name is the means that the outside uses to
|
||||
access the port, the wires are the internal connections to
|
||||
the port. */
|
||||
the port. In SystemVerilog, input ports may also have a
|
||||
default value. */
|
||||
public:
|
||||
struct port_t {
|
||||
perm_string name;
|
||||
vector<PEIdent*> expr;
|
||||
std::vector<PEIdent*> expr;
|
||||
PExpr*default_value;
|
||||
};
|
||||
|
||||
public:
|
||||
@@ -97,15 +99,15 @@ class Module : public PScopeExtra, public PNamedItem {
|
||||
/* specparams are simpler than other parameters, in that they
|
||||
can have a range, but not an explicit type. The restrictions
|
||||
are enforced by the parser. */
|
||||
map<perm_string,param_expr_t*>specparams;
|
||||
std::map<perm_string,param_expr_t*>specparams;
|
||||
|
||||
/* The module also has defparam assignments which don't create
|
||||
new parameters within the module, but may be used to set
|
||||
values within this module (when instantiated) or in other
|
||||
instantiated modules. */
|
||||
typedef pair<pform_name_t,PExpr*> named_expr_t;
|
||||
list<named_expr_t>defparms;
|
||||
static list<named_expr_t>user_defparms;
|
||||
typedef std::pair<pform_name_t,PExpr*> named_expr_t;
|
||||
std::list<named_expr_t>defparms;
|
||||
static std::list<named_expr_t>user_defparms;
|
||||
|
||||
/* Parameters may be overridden at instantiation time;
|
||||
the overrides do not contain explicit parameter names,
|
||||
@@ -113,17 +115,17 @@ class Module : public PScopeExtra, public PNamedItem {
|
||||
appear in the instantiated module. Therefore a
|
||||
list of names in module-order is needed to pass from
|
||||
a parameter-index to its name. */
|
||||
list<perm_string> param_names;
|
||||
std::list<perm_string> param_names;
|
||||
|
||||
/* This is an array of port descriptors, which is in turn a
|
||||
named array of PEident pointers. */
|
||||
vector<port_t*> ports;
|
||||
std::vector<port_t*> ports;
|
||||
|
||||
map<perm_string,PExpr*> attributes;
|
||||
std::map<perm_string,PExpr*> attributes;
|
||||
|
||||
/* The module has a list of generate schemes that appear in
|
||||
the module definition. These are used at elaboration time. */
|
||||
list<PGenerate*> generate_schemes;
|
||||
std::list<PGenerate*> generate_schemes;
|
||||
|
||||
/* Nested modules are placed here, and are not elaborated
|
||||
unless they are instantiated, implicitly or explicitly. */
|
||||
@@ -132,9 +134,9 @@ class Module : public PScopeExtra, public PNamedItem {
|
||||
/* An interface can contain one or more named modport lists.
|
||||
The parser will ensure these don't appear in modules or
|
||||
program blocks. */
|
||||
map<perm_string,PModport*> modports;
|
||||
std::map<perm_string,PModport*> modports;
|
||||
|
||||
list<PSpecPath*> specify_paths;
|
||||
std::list<PSpecPath*> specify_paths;
|
||||
|
||||
// The mod_name() is the name of the module type.
|
||||
perm_string mod_name() const { return pscope_name(); }
|
||||
@@ -142,29 +144,33 @@ class Module : public PScopeExtra, public PNamedItem {
|
||||
void add_gate(PGate*gate);
|
||||
|
||||
unsigned port_count() const;
|
||||
const vector<PEIdent*>& get_port(unsigned idx) const;
|
||||
const std::vector<PEIdent*>& get_port(unsigned idx) const;
|
||||
unsigned find_port(const char*name) const;
|
||||
|
||||
// Return port name ("" for undeclared port)
|
||||
perm_string get_port_name(unsigned idx) const;
|
||||
|
||||
PExpr* get_port_default_value(unsigned idx) const;
|
||||
|
||||
PGate* get_gate(perm_string name);
|
||||
|
||||
const list<PGate*>& get_gates() const;
|
||||
const std::list<PGate*>& get_gates() const;
|
||||
|
||||
void dump(ostream&out) const;
|
||||
void dump(std::ostream&out) const;
|
||||
bool elaborate(Design*, NetScope*scope) const;
|
||||
|
||||
typedef map<perm_string,PExpr*> replace_t;
|
||||
typedef std::map<perm_string,PExpr*> replace_t;
|
||||
bool elaborate_scope(Design*, NetScope*scope, const replace_t&rep);
|
||||
|
||||
bool elaborate_sig(Design*, NetScope*scope) const;
|
||||
|
||||
SymbolType symbol_type() const;
|
||||
|
||||
bool can_be_toplevel() const;
|
||||
|
||||
private:
|
||||
void dump_specparams_(ostream&out, unsigned indent) const;
|
||||
list<PGate*> gates_;
|
||||
void dump_specparams_(std::ostream&out, unsigned indent) const;
|
||||
std::list<PGate*> gates_;
|
||||
|
||||
private: // Not implemented
|
||||
Module(const Module&);
|
||||
|
||||
+3
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2017 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1999-2021 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -26,6 +26,8 @@
|
||||
# include "verinum.h"
|
||||
# include "netmisc.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
PDelays::PDelays()
|
||||
{
|
||||
delete_flag_ = true;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef IVL_PDelays_H
|
||||
#define IVL_PDelays_H
|
||||
/*
|
||||
* Copyright (c) 1999-2014 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1999-2021 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -19,17 +19,10 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
# include "svector.h"
|
||||
# include <string>
|
||||
# include <list>
|
||||
# include <iostream>
|
||||
|
||||
#ifdef __GNUC__
|
||||
#if __GNUC__ > 2
|
||||
using namespace std;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
class Design;
|
||||
class NetScope;
|
||||
class NetExpr;
|
||||
@@ -49,7 +42,7 @@ class PDelays {
|
||||
this object takes ownership of the expressions, and will
|
||||
delete it in the destructor. */
|
||||
void set_delay(PExpr*);
|
||||
void set_delays(const list<PExpr*>*del, bool delete_flag=true);
|
||||
void set_delays(const std::list<PExpr*>*del, bool delete_flag=true);
|
||||
|
||||
unsigned delay_count() const;
|
||||
|
||||
@@ -59,7 +52,7 @@ class PDelays {
|
||||
NetExpr*&decay_time,
|
||||
bool as_nets_flag =false) const;
|
||||
|
||||
void dump_delays(ostream&out) const;
|
||||
void dump_delays(std::ostream&out) const;
|
||||
|
||||
private:
|
||||
PExpr* delay_[3];
|
||||
@@ -70,6 +63,6 @@ class PDelays {
|
||||
PDelays& operator= (const PDelays&);
|
||||
};
|
||||
|
||||
ostream& operator << (ostream&o, const PDelays&);
|
||||
std::ostream& operator << (std::ostream&o, const PDelays&);
|
||||
|
||||
#endif /* IVL_PDelays_H */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998-2020 Stephen Williams <[email protected]>
|
||||
* Copyright (c) 1998-2021 Stephen Williams <[email protected]>
|
||||
* Copyright CERN 2013 / Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
@@ -30,9 +30,11 @@
|
||||
# include "util.h"
|
||||
# include <typeinfo>
|
||||
|
||||
using namespace std;
|
||||
|
||||
PExpr::PExpr()
|
||||
: expr_type_(IVL_VT_NO_TYPE)
|
||||
{
|
||||
expr_type_ = IVL_VT_NO_TYPE;
|
||||
expr_width_ = 0;
|
||||
min_width_ = 0;
|
||||
signed_flag_ = false;
|
||||
@@ -51,11 +53,6 @@ bool PExpr::has_aa_term(Design*, NetScope*) const
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PExpr::is_the_same(const PExpr*that) const
|
||||
{
|
||||
return typeid(this) == typeid(that);
|
||||
}
|
||||
|
||||
NetNet* PExpr::elaborate_lnet(Design*, NetScope*) const
|
||||
{
|
||||
cerr << get_fileline() << ": error: "
|
||||
@@ -72,7 +69,7 @@ NetNet* PExpr::elaborate_bi_net(Design*, NetScope*) const
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool PExpr::is_collapsible_net(Design*, NetScope*) const
|
||||
bool PExpr::is_collapsible_net(Design*, NetScope*, NetNet::PortType) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -145,6 +142,11 @@ PECastSize::~PECastSize()
|
||||
{
|
||||
}
|
||||
|
||||
bool PECastSize::has_aa_term(Design *des, NetScope *scope) const
|
||||
{
|
||||
return base_->has_aa_term(des, scope);
|
||||
}
|
||||
|
||||
PECastType::PECastType(data_type_t*t, PExpr*b)
|
||||
: target_(t), base_(b)
|
||||
{
|
||||
@@ -154,6 +156,22 @@ PECastType::~PECastType()
|
||||
{
|
||||
}
|
||||
|
||||
bool PECastType::has_aa_term(Design *des, NetScope *scope) const
|
||||
{
|
||||
return base_->has_aa_term(des, scope);
|
||||
}
|
||||
|
||||
PECastSign::PECastSign(bool signed_flag, PExpr *base)
|
||||
: base_(base)
|
||||
{
|
||||
signed_flag_ = signed_flag;
|
||||
}
|
||||
|
||||
bool PECastSign::has_aa_term(Design *des, NetScope *scope) const
|
||||
{
|
||||
return base_->has_aa_term(des, scope);
|
||||
}
|
||||
|
||||
PEBComp::PEBComp(char op, PExpr*l, PExpr*r)
|
||||
: PEBinary(op, l, r)
|
||||
{
|
||||
@@ -386,6 +404,18 @@ PEIdent::~PEIdent()
|
||||
{
|
||||
}
|
||||
|
||||
static bool find_enum_constant(LexicalScope*scope, perm_string name)
|
||||
{
|
||||
for (vector<enum_type_t*>::const_iterator cur = scope->enum_sets.begin() ;
|
||||
cur != scope->enum_sets.end() ; ++ cur) {
|
||||
for (list<named_pexpr_t>::const_iterator idx = (*cur)->names->begin() ;
|
||||
idx != (*cur)->names->end() ; ++ idx) {
|
||||
if (idx->name == name) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void PEIdent::declare_implicit_nets(LexicalScope*scope, NetNet::Type type)
|
||||
{
|
||||
/* We create an implicit wire if:
|
||||
@@ -401,14 +431,14 @@ void PEIdent::declare_implicit_nets(LexicalScope*scope, NetNet::Type type)
|
||||
while (ss) {
|
||||
if (ss->wires.find(name) != ss->wires.end())
|
||||
return;
|
||||
if (ss->localparams.find(name) != ss->localparams.end())
|
||||
return;
|
||||
if (ss->parameters.find(name) != ss->parameters.end())
|
||||
return;
|
||||
if (ss->genvars.find(name) != ss->genvars.end())
|
||||
return;
|
||||
if (ss->events.find(name) != ss->events.end())
|
||||
return;
|
||||
if (find_enum_constant(ss, name))
|
||||
return;
|
||||
/* Strictly speaking, we should also check for name clashes
|
||||
with tasks, functions, named blocks, module instances,
|
||||
and generate blocks. However, this information is not
|
||||
@@ -418,10 +448,9 @@ void PEIdent::declare_implicit_nets(LexicalScope*scope, NetNet::Type type)
|
||||
|
||||
ss = ss->parent_scope();
|
||||
}
|
||||
PWire*net = new PWire(name, type, NetNet::NOT_A_PORT, IVL_VT_LOGIC);
|
||||
PWire*net = new PWire(name, type, NetNet::NOT_A_PORT);
|
||||
net->set_file(get_file());
|
||||
net->set_lineno(get_lineno());
|
||||
net->set_range_scalar(SR_NET);
|
||||
scope->wires[name] = net;
|
||||
if (warn_implicit) {
|
||||
cerr << get_fileline() << ": warning: implicit "
|
||||
@@ -432,18 +461,17 @@ void PEIdent::declare_implicit_nets(LexicalScope*scope, NetNet::Type type)
|
||||
|
||||
bool PEIdent::has_aa_term(Design*des, NetScope*scope) const
|
||||
{
|
||||
NetNet* net = 0;
|
||||
const NetExpr*par = 0;
|
||||
NetEvent* eve = 0;
|
||||
symbol_search_results sr;
|
||||
if (!symbol_search(this, des, scope, path_, &sr))
|
||||
return false;
|
||||
|
||||
const NetExpr*ex1, *ex2;
|
||||
// Class properties are not considered automatic since a non-blocking
|
||||
// assignment to an object stored in an automatic variable is supposed to
|
||||
// capture a reference to the object, not the variable.
|
||||
if (!sr.path_tail.empty() && sr.net && sr.net->class_type())
|
||||
return false;
|
||||
|
||||
scope = symbol_search(this, des, scope, path_, net, par, eve, ex1, ex2);
|
||||
|
||||
if (scope)
|
||||
return scope->is_auto();
|
||||
else
|
||||
return false;
|
||||
return sr.scope->is_auto();
|
||||
}
|
||||
|
||||
PENewArray::PENewArray(PExpr*size_expr, PExpr*init_expr)
|
||||
@@ -460,8 +488,8 @@ PENewClass::PENewClass(void)
|
||||
{
|
||||
}
|
||||
|
||||
PENewClass::PENewClass(const list<PExpr*>&p)
|
||||
: parms_(p.size())
|
||||
PENewClass::PENewClass(const list<PExpr*>&p, data_type_t *class_type)
|
||||
: parms_(p.size()), class_type_(class_type)
|
||||
{
|
||||
size_t tmp_idx = 0;
|
||||
for (list<PExpr*>::const_iterator cur = p.begin()
|
||||
@@ -499,15 +527,6 @@ const verinum& PENumber::value() const
|
||||
return *value_;
|
||||
}
|
||||
|
||||
bool PENumber::is_the_same(const PExpr*that) const
|
||||
{
|
||||
const PENumber*obj = dynamic_cast<const PENumber*>(that);
|
||||
if (obj == 0)
|
||||
return false;
|
||||
|
||||
return *value_ == *obj->value_;
|
||||
}
|
||||
|
||||
PEString::PEString(char*s)
|
||||
: text_(s)
|
||||
{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef IVL_PExpr_H
|
||||
#define IVL_PExpr_H
|
||||
/*
|
||||
* Copyright (c) 1998-2019 Stephen Williams <[email protected]>
|
||||
* Copyright (c) 1998-2021 Stephen Williams <[email protected]>
|
||||
* Copyright CERN 2013 / Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
@@ -23,6 +23,7 @@
|
||||
# include <string>
|
||||
# include <vector>
|
||||
# include <valarray>
|
||||
# include <memory>
|
||||
# include "netlist.h"
|
||||
# include "verinum.h"
|
||||
# include "LineInfo.h"
|
||||
@@ -35,6 +36,7 @@ class NetNet;
|
||||
class NetExpr;
|
||||
class NetScope;
|
||||
class PPackage;
|
||||
struct symbol_search_results;
|
||||
|
||||
/*
|
||||
* The PExpr class hierarchy supports the description of
|
||||
@@ -60,7 +62,7 @@ class PExpr : public LineInfo {
|
||||
PExpr();
|
||||
virtual ~PExpr();
|
||||
|
||||
virtual void dump(ostream&) const;
|
||||
virtual void dump(std::ostream&) const;
|
||||
|
||||
// This method tests whether the expression contains any identifiers
|
||||
// that have not been previously declared in the specified scope or
|
||||
@@ -172,21 +174,12 @@ class PExpr : public LineInfo {
|
||||
bool is_cassign,
|
||||
bool is_force) const;
|
||||
|
||||
// This attempts to evaluate a constant expression, and return
|
||||
// a verinum as a result. If the expression cannot be
|
||||
// evaluated, return 0.
|
||||
virtual verinum* eval_const(Design*des, NetScope*sc) const;
|
||||
|
||||
// This method returns true if the expression represents a
|
||||
// structural net that can have multiple drivers. This is
|
||||
// used to test whether an input port connection can be
|
||||
// collapsed to a single wire.
|
||||
virtual bool is_collapsible_net(Design*des, NetScope*scope) const;
|
||||
|
||||
// This method returns true if that expression is the same as
|
||||
// this expression. This method is used for comparing
|
||||
// expressions that must be structurally "identical".
|
||||
virtual bool is_the_same(const PExpr*that) const;
|
||||
virtual bool is_collapsible_net(Design*des, NetScope*scope,
|
||||
NetNet::PortType port_type) const;
|
||||
|
||||
protected:
|
||||
unsigned fix_width_(width_mode_t mode);
|
||||
@@ -202,7 +195,7 @@ class PExpr : public LineInfo {
|
||||
PExpr& operator= (const PExpr&);
|
||||
};
|
||||
|
||||
ostream& operator << (ostream&, const PExpr&);
|
||||
std::ostream& operator << (std::ostream&, const PExpr&);
|
||||
|
||||
class PEAssignPattern : public PExpr {
|
||||
public:
|
||||
@@ -230,11 +223,10 @@ class PEAssignPattern : public PExpr {
|
||||
class PEConcat : public PExpr {
|
||||
|
||||
public:
|
||||
PEConcat(const list<PExpr*>&p, PExpr*r =0);
|
||||
explicit PEConcat(const std::list<PExpr*>&p, PExpr*r =0);
|
||||
~PEConcat();
|
||||
|
||||
virtual verinum* eval_const(Design*des, NetScope*sc) const;
|
||||
virtual void dump(ostream&) const;
|
||||
virtual void dump(std::ostream&) const;
|
||||
|
||||
virtual void declare_implicit_nets(LexicalScope*scope, NetNet::Type type);
|
||||
|
||||
@@ -256,12 +248,13 @@ class PEConcat : public PExpr {
|
||||
NetScope*scope,
|
||||
bool is_cassign,
|
||||
bool is_force) const;
|
||||
virtual bool is_collapsible_net(Design*des, NetScope*scope) const;
|
||||
virtual bool is_collapsible_net(Design*des, NetScope*scope,
|
||||
NetNet::PortType port_type) const;
|
||||
private:
|
||||
NetNet* elaborate_lnet_common_(Design*des, NetScope*scope,
|
||||
bool bidirectional_flag) const;
|
||||
private:
|
||||
vector<PExpr*>parms_;
|
||||
std::vector<PExpr*>parms_;
|
||||
std::valarray<width_mode_t>width_modes_;
|
||||
|
||||
PExpr*repeat_;
|
||||
@@ -279,7 +272,7 @@ class PEConcat : public PExpr {
|
||||
class PEEvent : public PExpr {
|
||||
|
||||
public:
|
||||
enum edge_t {ANYEDGE, POSEDGE, NEGEDGE, POSITIVE};
|
||||
enum edge_t {ANYEDGE, POSEDGE, NEGEDGE, EDGE, POSITIVE};
|
||||
|
||||
// Use this constructor to create events based on edges or levels.
|
||||
PEEvent(edge_t t, PExpr*e);
|
||||
@@ -289,7 +282,7 @@ class PEEvent : public PExpr {
|
||||
edge_t type() const;
|
||||
PExpr* expr() const;
|
||||
|
||||
virtual void dump(ostream&) const;
|
||||
virtual void dump(std::ostream&) const;
|
||||
|
||||
virtual bool has_aa_term(Design*des, NetScope*scope) const;
|
||||
|
||||
@@ -309,11 +302,6 @@ class PEFNumber : public PExpr {
|
||||
|
||||
const verireal& value() const;
|
||||
|
||||
/* The eval_const method as applied to a floating point number
|
||||
gets the *integer* value of the number. This accounts for
|
||||
any rounding that is needed to get the value. */
|
||||
virtual verinum* eval_const(Design*des, NetScope*sc) const;
|
||||
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
width_mode_t&mode);
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
|
||||
@@ -322,7 +310,7 @@ class PEFNumber : public PExpr {
|
||||
unsigned expr_wid,
|
||||
unsigned flags) const;
|
||||
|
||||
virtual void dump(ostream&) const;
|
||||
virtual void dump(std::ostream&) const;
|
||||
|
||||
private:
|
||||
verireal*value_;
|
||||
@@ -340,7 +328,7 @@ class PEIdent : public PExpr {
|
||||
// current identifier.
|
||||
void append_name(perm_string);
|
||||
|
||||
virtual void dump(ostream&) const;
|
||||
virtual void dump(std::ostream&) const;
|
||||
|
||||
virtual void declare_implicit_nets(LexicalScope*scope, NetNet::Type type);
|
||||
|
||||
@@ -375,9 +363,8 @@ class PEIdent : public PExpr {
|
||||
// expressions can can be unpacked arrays.
|
||||
NetNet* elaborate_unpacked_net(Design*des, NetScope*sc) const;
|
||||
|
||||
verinum* eval_const(Design*des, NetScope*sc) const;
|
||||
|
||||
virtual bool is_collapsible_net(Design*des, NetScope*scope) const;
|
||||
virtual bool is_collapsible_net(Design*des, NetScope*scope,
|
||||
NetNet::PortType port_type) const;
|
||||
|
||||
const PPackage* package() const { return package_; }
|
||||
|
||||
@@ -404,10 +391,6 @@ class PEIdent : public PExpr {
|
||||
// flag is set to *false*.
|
||||
bool calculate_parts_(Design*, NetScope*, long&msb, long&lsb, bool&defined) const;
|
||||
NetExpr* calculate_up_do_base_(Design*, NetScope*, bool need_const) const;
|
||||
bool calculate_param_range_(Design*, NetScope*,
|
||||
const NetExpr*msb_ex, long&msb,
|
||||
const NetExpr*lsb_ex, long&lsb,
|
||||
long length) const;
|
||||
|
||||
bool calculate_up_do_width_(Design*, NetScope*, unsigned long&wid) const;
|
||||
|
||||
@@ -434,6 +417,7 @@ class PEIdent : public PExpr {
|
||||
index_component_t::ctype_t,
|
||||
bool need_const_idx) const;
|
||||
NetAssign_*elaborate_lval_net_class_member_(Design*, NetScope*,
|
||||
const netclass_t *class_type,
|
||||
NetNet*,
|
||||
pform_name_t) const;
|
||||
bool elaborate_lval_net_packed_member_(Design*, NetScope*,
|
||||
@@ -443,41 +427,46 @@ class PEIdent : public PExpr {
|
||||
NetAssign_*) const;
|
||||
|
||||
private:
|
||||
NetExpr* elaborate_expr_(Design *des, NetScope *scope,
|
||||
unsigned expr_wid, unsigned flags) const;
|
||||
|
||||
NetExpr*elaborate_expr_param_or_specparam_(Design*des,
|
||||
NetScope*scope,
|
||||
const NetExpr*par,
|
||||
NetScope*found_in,
|
||||
ivl_type_t par_type,
|
||||
unsigned expr_wid,
|
||||
unsigned flags) const;
|
||||
NetExpr*elaborate_expr_param_(Design*des,
|
||||
NetScope*scope,
|
||||
const NetExpr*par,
|
||||
NetScope*found_in,
|
||||
const NetExpr*par_msb,
|
||||
const NetExpr*par_lsb,
|
||||
const NetScope*found_in,
|
||||
ivl_type_t par_type,
|
||||
unsigned expr_wid,
|
||||
unsigned flags) const;
|
||||
NetExpr*elaborate_expr_param_bit_(Design*des,
|
||||
NetScope*scope,
|
||||
const NetExpr*par,
|
||||
NetScope*found_in,
|
||||
const NetExpr*par_msb,
|
||||
const NetExpr*par_lsb,
|
||||
const NetScope*found_in,
|
||||
ivl_type_t par_type,
|
||||
bool need_const) const;
|
||||
NetExpr*elaborate_expr_param_part_(Design*des,
|
||||
NetScope*scope,
|
||||
const NetExpr*par,
|
||||
NetScope*found_in,
|
||||
const NetExpr*par_msb,
|
||||
const NetExpr*par_lsb,
|
||||
const NetScope*found_in,
|
||||
ivl_type_t par_type,
|
||||
unsigned expr_wid) const;
|
||||
NetExpr*elaborate_expr_param_idx_up_(Design*des,
|
||||
NetScope*scope,
|
||||
const NetExpr*par,
|
||||
NetScope*found_in,
|
||||
const NetExpr*par_msb,
|
||||
const NetExpr*par_lsb,
|
||||
const NetScope*found_in,
|
||||
ivl_type_t par_type,
|
||||
bool need_const) const;
|
||||
NetExpr*elaborate_expr_param_idx_do_(Design*des,
|
||||
NetScope*scope,
|
||||
const NetExpr*par,
|
||||
NetScope*found_in,
|
||||
const NetExpr*par_msb,
|
||||
const NetExpr*par_lsb,
|
||||
const NetScope*found_in,
|
||||
ivl_type_t par_type,
|
||||
bool need_const) const;
|
||||
NetExpr*elaborate_expr_net(Design*des,
|
||||
NetScope*scope,
|
||||
@@ -522,8 +511,14 @@ class PEIdent : public PExpr {
|
||||
unsigned expr_wid,
|
||||
unsigned flags) const;
|
||||
|
||||
NetExpr *elaborate_expr_class_field_(Design*des, NetScope*scope,
|
||||
const symbol_search_results &sr,
|
||||
unsigned expr_wid,
|
||||
unsigned flags) const;
|
||||
|
||||
unsigned test_width_method_(Design*des, NetScope*scope, width_mode_t&mode);
|
||||
|
||||
unsigned test_width_parameter_(const NetExpr *par, width_mode_t&mode);
|
||||
|
||||
private:
|
||||
NetNet* elaborate_lnet_common_(Design*des, NetScope*scope,
|
||||
@@ -540,7 +535,7 @@ class PENewArray : public PExpr {
|
||||
explicit PENewArray (PExpr*s, PExpr*i);
|
||||
~PENewArray();
|
||||
|
||||
virtual void dump(ostream&) const;
|
||||
virtual void dump(std::ostream&) const;
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
width_mode_t&mode);
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
|
||||
@@ -560,11 +555,12 @@ class PENewClass : public PExpr {
|
||||
// New without (or with default) constructor
|
||||
explicit PENewClass ();
|
||||
// New with constructor arguments
|
||||
explicit PENewClass (const std::list<PExpr*>&p);
|
||||
explicit PENewClass (const std::list<PExpr*>&p,
|
||||
data_type_t *class_type = nullptr);
|
||||
|
||||
~PENewClass();
|
||||
|
||||
virtual void dump(ostream&) const;
|
||||
virtual void dump(std::ostream&) const;
|
||||
// Class objects don't have a useful width, but the expression
|
||||
// is IVL_VT_CLASS.
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
@@ -582,6 +578,7 @@ class PENewClass : public PExpr {
|
||||
|
||||
private:
|
||||
std::vector<PExpr*>parms_;
|
||||
data_type_t *class_type_;
|
||||
};
|
||||
|
||||
class PENewCopy : public PExpr {
|
||||
@@ -589,7 +586,7 @@ class PENewCopy : public PExpr {
|
||||
explicit PENewCopy(PExpr*src);
|
||||
~PENewCopy();
|
||||
|
||||
virtual void dump(ostream&) const;
|
||||
virtual void dump(std::ostream&) const;
|
||||
// Class objects don't have a useful width, but the expression
|
||||
// is IVL_VT_CLASS.
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
@@ -609,7 +606,7 @@ class PENull : public PExpr {
|
||||
explicit PENull();
|
||||
~PENull();
|
||||
|
||||
virtual void dump(ostream&) const;
|
||||
virtual void dump(std::ostream&) const;
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
width_mode_t&mode);
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
|
||||
@@ -627,7 +624,7 @@ class PENumber : public PExpr {
|
||||
|
||||
const verinum& value() const;
|
||||
|
||||
virtual void dump(ostream&) const;
|
||||
virtual void dump(std::ostream&) const;
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
width_mode_t&mode);
|
||||
|
||||
@@ -640,10 +637,6 @@ class PENumber : public PExpr {
|
||||
bool is_cassign,
|
||||
bool is_force) const;
|
||||
|
||||
virtual verinum* eval_const(Design*des, NetScope*sc) const;
|
||||
|
||||
virtual bool is_the_same(const PExpr*that) const;
|
||||
|
||||
private:
|
||||
verinum*const value_;
|
||||
};
|
||||
@@ -661,8 +654,8 @@ class PEString : public PExpr {
|
||||
explicit PEString(char*s);
|
||||
~PEString();
|
||||
|
||||
string value() const;
|
||||
virtual void dump(ostream&) const;
|
||||
std::string value() const;
|
||||
virtual void dump(std::ostream&) const;
|
||||
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
width_mode_t&mode);
|
||||
@@ -672,7 +665,6 @@ class PEString : public PExpr {
|
||||
|
||||
virtual NetEConst*elaborate_expr(Design*des, NetScope*,
|
||||
unsigned expr_wid, unsigned) const;
|
||||
verinum* eval_const(Design*, NetScope*) const;
|
||||
|
||||
private:
|
||||
char*text_;
|
||||
@@ -683,7 +675,7 @@ class PETypename : public PExpr {
|
||||
explicit PETypename(data_type_t*data_type);
|
||||
~PETypename();
|
||||
|
||||
virtual void dump(ostream&) const;
|
||||
virtual void dump(std::ostream&) const;
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
width_mode_t&mode);
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
|
||||
@@ -701,7 +693,7 @@ class PEUnary : public PExpr {
|
||||
explicit PEUnary(char op, PExpr*ex);
|
||||
~PEUnary();
|
||||
|
||||
virtual void dump(ostream&out) const;
|
||||
virtual void dump(std::ostream&out) const;
|
||||
|
||||
virtual void declare_implicit_nets(LexicalScope*scope, NetNet::Type type);
|
||||
|
||||
@@ -713,7 +705,6 @@ class PEUnary : public PExpr {
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
|
||||
unsigned expr_wid,
|
||||
unsigned flags) const;
|
||||
virtual verinum* eval_const(Design*des, NetScope*sc) const;
|
||||
|
||||
public:
|
||||
inline char get_op() const { return op_; }
|
||||
@@ -733,7 +724,7 @@ class PEBinary : public PExpr {
|
||||
explicit PEBinary(char op, PExpr*l, PExpr*r);
|
||||
~PEBinary();
|
||||
|
||||
virtual void dump(ostream&out) const;
|
||||
virtual void dump(std::ostream&out) const;
|
||||
|
||||
virtual void declare_implicit_nets(LexicalScope*scope, NetNet::Type type);
|
||||
|
||||
@@ -745,7 +736,6 @@ class PEBinary : public PExpr {
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
|
||||
unsigned expr_wid,
|
||||
unsigned flags) const;
|
||||
virtual verinum* eval_const(Design*des, NetScope*sc) const;
|
||||
|
||||
protected:
|
||||
char op_;
|
||||
@@ -858,7 +848,7 @@ class PETernary : public PExpr {
|
||||
explicit PETernary(PExpr*e, PExpr*t, PExpr*f);
|
||||
~PETernary();
|
||||
|
||||
virtual void dump(ostream&out) const;
|
||||
virtual void dump(std::ostream&out) const;
|
||||
|
||||
virtual void declare_implicit_nets(LexicalScope*scope, NetNet::Type type);
|
||||
|
||||
@@ -870,7 +860,6 @@ class PETernary : public PExpr {
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
|
||||
unsigned expr_wid,
|
||||
unsigned flags) const;
|
||||
virtual verinum* eval_const(Design*des, NetScope*sc) const;
|
||||
|
||||
private:
|
||||
NetExpr* elab_and_eval_alternative_(Design*des, NetScope*scope,
|
||||
@@ -890,7 +879,7 @@ class PETernary : public PExpr {
|
||||
*/
|
||||
class PECallFunction : public PExpr {
|
||||
public:
|
||||
explicit PECallFunction(const pform_name_t&n, const vector<PExpr *> &parms);
|
||||
explicit PECallFunction(const pform_name_t&n, const std::vector<PExpr *> &parms);
|
||||
// Call function defined in package.
|
||||
explicit PECallFunction(PPackage*pkg, perm_string n, const std::vector<PExpr *> &parms);
|
||||
explicit PECallFunction(PPackage*pkg, perm_string n, const std::list<PExpr *> &parms);
|
||||
@@ -899,16 +888,16 @@ class PECallFunction : public PExpr {
|
||||
explicit PECallFunction(PPackage*pkg, const pform_name_t&n, const std::vector<PExpr *> &parms);
|
||||
|
||||
// Call of system function (name is not hierarchical)
|
||||
explicit PECallFunction(perm_string n, const vector<PExpr *> &parms);
|
||||
explicit PECallFunction(perm_string n, const std::vector<PExpr *> &parms);
|
||||
explicit PECallFunction(perm_string n);
|
||||
|
||||
// std::list versions. Should be removed!
|
||||
explicit PECallFunction(const pform_name_t&n, const list<PExpr *> &parms);
|
||||
explicit PECallFunction(perm_string n, const list<PExpr *> &parms);
|
||||
explicit PECallFunction(const pform_name_t&n, const std::list<PExpr *> &parms);
|
||||
explicit PECallFunction(perm_string n, const std::list<PExpr *> &parms);
|
||||
|
||||
~PECallFunction();
|
||||
|
||||
virtual void dump(ostream &) const;
|
||||
virtual void dump(std::ostream &) const;
|
||||
|
||||
virtual void declare_implicit_nets(LexicalScope*scope, NetNet::Type type);
|
||||
|
||||
@@ -936,29 +925,33 @@ class PECallFunction : public PExpr {
|
||||
|
||||
NetExpr* cast_to_width_(NetExpr*expr, unsigned wid) const;
|
||||
|
||||
NetExpr* elaborate_expr_(Design *des, NetScope *scope,
|
||||
unsigned flags) const;
|
||||
|
||||
NetExpr*elaborate_expr_pkg_(Design*des, NetScope*scope,
|
||||
unsigned expr_wid, unsigned flags)const;
|
||||
NetExpr*elaborate_expr_method_(Design*des, NetScope*scope,
|
||||
unsigned expr_wid,
|
||||
bool add_this_flag = false) const;
|
||||
#if 0
|
||||
NetExpr*elaborate_expr_string_method_(Design*des, NetScope*scope) const;
|
||||
NetExpr*elaborate_expr_enum_method_(Design*des, NetScope*scope,
|
||||
unsigned expr_wid) const;
|
||||
#endif
|
||||
unsigned flags)const;
|
||||
|
||||
NetExpr* elaborate_expr_method_(Design*des, NetScope*scope,
|
||||
symbol_search_results&search_results)
|
||||
const;
|
||||
NetExpr* elaborate_expr_method_par_(Design*des, NetScope*scope,
|
||||
symbol_search_results&search_results)
|
||||
const;
|
||||
|
||||
|
||||
NetExpr* elaborate_sfunc_(Design*des, NetScope*scope,
|
||||
unsigned expr_wid,
|
||||
unsigned flags) const;
|
||||
NetExpr* elaborate_access_func_(Design*des, NetScope*scope, ivl_nature_t,
|
||||
unsigned expr_wid) const;
|
||||
NetExpr* elaborate_access_func_(Design*des, NetScope*scope, ivl_nature_t)
|
||||
const;
|
||||
unsigned test_width_sfunc_(Design*des, NetScope*scope,
|
||||
width_mode_t&mode);
|
||||
unsigned test_width_method_(Design*des, NetScope*scope,
|
||||
symbol_search_results&search_results,
|
||||
width_mode_t&mode);
|
||||
|
||||
NetExpr*elaborate_base_(Design*des, NetScope*scope, NetScope*dscope,
|
||||
unsigned expr_wid, unsigned flags) const;
|
||||
unsigned flags) const;
|
||||
|
||||
unsigned elaborate_arguments_(Design*des, NetScope*scope,
|
||||
NetFuncDef*def, bool need_const,
|
||||
@@ -975,12 +968,14 @@ class PECastSize : public PExpr {
|
||||
explicit PECastSize(PExpr*size, PExpr*base);
|
||||
~PECastSize();
|
||||
|
||||
void dump(ostream &out) const;
|
||||
void dump(std::ostream &out) const;
|
||||
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
|
||||
unsigned expr_wid,
|
||||
unsigned flags) const;
|
||||
|
||||
virtual bool has_aa_term(Design *des, NetScope *scope) const;
|
||||
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
width_mode_t&mode);
|
||||
|
||||
@@ -998,7 +993,7 @@ class PECastType : public PExpr {
|
||||
explicit PECastType(data_type_t*target, PExpr*base);
|
||||
~PECastType();
|
||||
|
||||
void dump(ostream &out) const;
|
||||
void dump(std::ostream &out) const;
|
||||
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
|
||||
ivl_type_t type, unsigned flags) const;
|
||||
@@ -1006,14 +1001,39 @@ class PECastType : public PExpr {
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
|
||||
unsigned expr_wid, unsigned flags) const;
|
||||
|
||||
virtual bool has_aa_term(Design *des, NetScope *scope) const;
|
||||
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
width_mode_t&mode);
|
||||
|
||||
private:
|
||||
data_type_t* target_;
|
||||
ivl_type_t target_type_;
|
||||
PExpr* base_;
|
||||
};
|
||||
|
||||
/*
|
||||
* Support the SystemVerilog sign cast.
|
||||
*/
|
||||
class PECastSign : public PExpr {
|
||||
|
||||
public:
|
||||
explicit PECastSign(bool signed_flag, PExpr *base);
|
||||
~PECastSign() = default;
|
||||
|
||||
void dump(std::ostream &out) const;
|
||||
|
||||
NetExpr* elaborate_expr(Design *des, NetScope *scope,
|
||||
unsigned expr_wid, unsigned flags) const;
|
||||
|
||||
virtual bool has_aa_term(Design *des, NetScope *scope) const;
|
||||
|
||||
unsigned test_width(Design *des, NetScope *scope, width_mode_t &mode);
|
||||
|
||||
private:
|
||||
std::unique_ptr<PExpr> base_;
|
||||
};
|
||||
|
||||
/*
|
||||
* This class is used for error recovery. All methods do nothing and return
|
||||
* null or default values.
|
||||
|
||||
+17
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2019 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1999-2021 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -23,6 +23,8 @@
|
||||
# include <cassert>
|
||||
# include "ivl_assert.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
PFunction::PFunction(perm_string name, LexicalScope*parent, bool is_auto__)
|
||||
: PTaskFunc(name, parent), statement_(0)
|
||||
{
|
||||
@@ -43,7 +45,7 @@ void PFunction::set_statement(Statement*s)
|
||||
|
||||
void PFunction::push_statement_front(Statement*stmt)
|
||||
{
|
||||
// This can only happen after the statement is initially set.
|
||||
// This should not be possible.
|
||||
ivl_assert(*this, statement_);
|
||||
|
||||
// Get the PBlock of the statement. If it is not a PBlock,
|
||||
@@ -75,7 +77,8 @@ PChainConstructor* PFunction::extract_chain_constructor()
|
||||
PChainConstructor*res = 0;
|
||||
|
||||
if ((res = dynamic_cast<PChainConstructor*> (statement_))) {
|
||||
statement_ = 0;
|
||||
statement_ = new PBlock(PBlock::BL_SEQ);
|
||||
statement_->set_line(*this);
|
||||
|
||||
} else if (PBlock*blk = dynamic_cast<PBlock*>(statement_)) {
|
||||
res = blk->extract_chain_constructor();
|
||||
@@ -88,3 +91,14 @@ PNamedItem::SymbolType PFunction::symbol_type() const
|
||||
{
|
||||
return FUNCTION;
|
||||
}
|
||||
|
||||
|
||||
PLet::PLet(perm_string name, LexicalScope*parent, list<let_port_t*>*ports,
|
||||
PExpr*expr)
|
||||
: PTaskFunc(name, parent), ports_(ports), expr_(expr)
|
||||
{
|
||||
}
|
||||
|
||||
PLet::~PLet()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2019 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1999-2021 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -24,6 +24,8 @@
|
||||
# include "verinum.h"
|
||||
# include <cassert>
|
||||
|
||||
using namespace std;
|
||||
|
||||
void PGate::set_pins_(list<PExpr*>*pins)
|
||||
{
|
||||
assert(pins);
|
||||
@@ -39,7 +41,7 @@ void PGate::set_pins_(list<PExpr*>*pins)
|
||||
}
|
||||
|
||||
PGate::PGate(perm_string name, list<PExpr*>*pins, const list<PExpr*>*del)
|
||||
: name_(name), pins_(pins? pins->size() : 0)
|
||||
: name_(name), pins_(pins? pins->size() : 0), ranges_(0)
|
||||
{
|
||||
if (pins) set_pins_(pins);
|
||||
if (del) delay_.set_delays(del);
|
||||
@@ -48,7 +50,7 @@ PGate::PGate(perm_string name, list<PExpr*>*pins, const list<PExpr*>*del)
|
||||
}
|
||||
|
||||
PGate::PGate(perm_string name, list<PExpr*>*pins, PExpr*del)
|
||||
: name_(name), pins_(pins? pins->size() : 0)
|
||||
: name_(name), pins_(pins? pins->size() : 0), ranges_(0)
|
||||
{
|
||||
if (pins) set_pins_(pins);
|
||||
if (del) delay_.set_delay(del);
|
||||
@@ -57,7 +59,7 @@ PGate::PGate(perm_string name, list<PExpr*>*pins, PExpr*del)
|
||||
}
|
||||
|
||||
PGate::PGate(perm_string name, list<PExpr*>*pins)
|
||||
: name_(name), pins_(pins? pins->size() : 0)
|
||||
: name_(name), pins_(pins? pins->size() : 0), ranges_(0)
|
||||
{
|
||||
if (pins) set_pins_(pins);
|
||||
str0_ = IVL_DR_STRONG;
|
||||
@@ -68,6 +70,12 @@ PGate::~PGate()
|
||||
{
|
||||
}
|
||||
|
||||
void PGate::set_ranges(list<pform_range_t>*ranges)
|
||||
{
|
||||
assert(ranges_ == 0);
|
||||
ranges_ = ranges;
|
||||
}
|
||||
|
||||
ivl_drive_t PGate::strength0() const
|
||||
{
|
||||
return str0_;
|
||||
@@ -141,14 +149,14 @@ PGAssign::~PGAssign()
|
||||
PGBuiltin::PGBuiltin(Type t, perm_string name,
|
||||
list<PExpr*>*pins,
|
||||
list<PExpr*>*del)
|
||||
: PGate(name, pins, del), type_(t), msb_(0), lsb_(0)
|
||||
: PGate(name, pins, del), type_(t)
|
||||
{
|
||||
}
|
||||
|
||||
PGBuiltin::PGBuiltin(Type t, perm_string name,
|
||||
list<PExpr*>*pins,
|
||||
PExpr*del)
|
||||
: PGate(name, pins, del), type_(t), msb_(0), lsb_(0)
|
||||
: PGate(name, pins, del), type_(t)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -157,15 +165,6 @@ PGBuiltin::~PGBuiltin()
|
||||
{
|
||||
}
|
||||
|
||||
void PGBuiltin::set_range(PExpr*msb, PExpr*lsb)
|
||||
{
|
||||
assert(msb_ == 0);
|
||||
assert(lsb_ == 0);
|
||||
|
||||
msb_ = msb;
|
||||
lsb_ = lsb;
|
||||
}
|
||||
|
||||
const char* PGBuiltin::gate_name() const
|
||||
{
|
||||
switch(type_) {
|
||||
@@ -266,20 +265,20 @@ const char* PGBuiltin::gate_name() const
|
||||
|
||||
PGModule::PGModule(perm_string type, perm_string name, list<PExpr*>*pins)
|
||||
: PGate(name, pins), bound_type_(0), type_(type), overrides_(0), pins_(0),
|
||||
npins_(0), parms_(0), nparms_(0), msb_(0), lsb_(0)
|
||||
npins_(0), parms_(0), nparms_(0)
|
||||
{
|
||||
}
|
||||
|
||||
PGModule::PGModule(perm_string type, perm_string name,
|
||||
named<PExpr*>*pins, unsigned npins)
|
||||
: PGate(name, 0), bound_type_(0), type_(type), overrides_(0), pins_(pins),
|
||||
npins_(npins), parms_(0), nparms_(0), msb_(0), lsb_(0)
|
||||
npins_(npins), parms_(0), nparms_(0)
|
||||
{
|
||||
}
|
||||
|
||||
PGModule::PGModule(Module*type, perm_string name)
|
||||
: PGate(name, 0), bound_type_(type), overrides_(0), pins_(0),
|
||||
npins_(0), parms_(0), nparms_(0), msb_(0), lsb_(0)
|
||||
npins_(0), parms_(0), nparms_(0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -301,15 +300,6 @@ void PGModule::set_parameters(named<PExpr*>*pa, unsigned npa)
|
||||
nparms_ = npa;
|
||||
}
|
||||
|
||||
void PGModule::set_range(PExpr*msb, PExpr*lsb)
|
||||
{
|
||||
assert(msb_ == 0);
|
||||
assert(lsb_ == 0);
|
||||
|
||||
msb_ = msb;
|
||||
lsb_ = lsb;
|
||||
}
|
||||
|
||||
perm_string PGModule::get_type() const
|
||||
{
|
||||
return type_;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef IVL_PGate_H
|
||||
#define IVL_PGate_H
|
||||
/*
|
||||
* Copyright (c) 1998-2019 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2021 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -19,7 +19,6 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
# include "svector.h"
|
||||
# include "StringHeap.h"
|
||||
# include "named.h"
|
||||
# include "PNamedItem.h"
|
||||
@@ -50,16 +49,19 @@ class Module;
|
||||
class PGate : public PNamedItem {
|
||||
|
||||
public:
|
||||
explicit PGate(perm_string name, list<PExpr*>*pins,
|
||||
const list<PExpr*>*del);
|
||||
explicit PGate(perm_string name, std::list<PExpr*>*pins,
|
||||
const std::list<PExpr*>*del);
|
||||
|
||||
explicit PGate(perm_string name, list<PExpr*>*pins,
|
||||
explicit PGate(perm_string name, std::list<PExpr*>*pins,
|
||||
PExpr*del);
|
||||
|
||||
explicit PGate(perm_string name, list<PExpr*>*pins);
|
||||
explicit PGate(perm_string name, std::list<PExpr*>*pins);
|
||||
|
||||
virtual ~PGate();
|
||||
|
||||
void set_ranges(std::list<pform_range_t>*ranges);
|
||||
bool is_array() const { return ranges_ != 0; }
|
||||
|
||||
perm_string get_name() const { return name_; }
|
||||
|
||||
// This evaluates the delays as far as possible, but returns
|
||||
@@ -81,9 +83,9 @@ class PGate : public PNamedItem {
|
||||
void strength0(ivl_drive_t);
|
||||
void strength1(ivl_drive_t);
|
||||
|
||||
map<perm_string,PExpr*> attributes;
|
||||
std::map<perm_string,PExpr*> attributes;
|
||||
|
||||
virtual void dump(ostream&out, unsigned ind =4) const;
|
||||
virtual void dump(std::ostream&out, unsigned ind =4) const;
|
||||
virtual void elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*sc) const;
|
||||
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
|
||||
@@ -91,19 +93,25 @@ class PGate : public PNamedItem {
|
||||
SymbolType symbol_type() const;
|
||||
|
||||
protected:
|
||||
const vector<PExpr*>& get_pins() const { return pins_; }
|
||||
const std::vector<PExpr*>& get_pins() const { return pins_; }
|
||||
|
||||
void dump_pins(ostream&out) const;
|
||||
void dump_delays(ostream&out) const;
|
||||
unsigned calculate_array_size_(Design*, NetScope*,
|
||||
long&high, long&low) const;
|
||||
|
||||
void dump_pins(std::ostream&out) const;
|
||||
void dump_delays(std::ostream&out) const;
|
||||
void dump_ranges(std::ostream&out) const;
|
||||
|
||||
private:
|
||||
perm_string name_;
|
||||
PDelays delay_;
|
||||
vector<PExpr*>pins_;
|
||||
std::vector<PExpr*>pins_;
|
||||
|
||||
std::list<pform_range_t>*ranges_;
|
||||
|
||||
ivl_drive_t str0_, str1_;
|
||||
|
||||
void set_pins_(list<PExpr*>*pins);
|
||||
void set_pins_(std::list<PExpr*>*pins);
|
||||
|
||||
private: // not implemented
|
||||
PGate(const PGate&);
|
||||
@@ -117,11 +125,11 @@ class PGate : public PNamedItem {
|
||||
class PGAssign : public PGate {
|
||||
|
||||
public:
|
||||
explicit PGAssign(list<PExpr*>*pins);
|
||||
explicit PGAssign(list<PExpr*>*pins, list<PExpr*>*dels);
|
||||
explicit PGAssign(std::list<PExpr*>*pins);
|
||||
explicit PGAssign(std::list<PExpr*>*pins, std::list<PExpr*>*dels);
|
||||
~PGAssign();
|
||||
|
||||
void dump(ostream&out, unsigned ind =4) const;
|
||||
void dump(std::ostream&out, unsigned ind =4) const;
|
||||
virtual void elaborate(Design*des, NetScope*scope) const;
|
||||
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
|
||||
|
||||
@@ -150,25 +158,21 @@ class PGBuiltin : public PGate {
|
||||
|
||||
public:
|
||||
explicit PGBuiltin(Type t, perm_string name,
|
||||
list<PExpr*>*pins,
|
||||
list<PExpr*>*del);
|
||||
std::list<PExpr*>*pins,
|
||||
std::list<PExpr*>*del);
|
||||
explicit PGBuiltin(Type t, perm_string name,
|
||||
list<PExpr*>*pins,
|
||||
std::list<PExpr*>*pins,
|
||||
PExpr*del);
|
||||
~PGBuiltin();
|
||||
|
||||
Type type() const { return type_; }
|
||||
const char * gate_name() const;
|
||||
void set_range(PExpr*msb, PExpr*lsb);
|
||||
|
||||
virtual void dump(ostream&out, unsigned ind =4) const;
|
||||
virtual void dump(std::ostream&out, unsigned ind =4) const;
|
||||
virtual void elaborate(Design*, NetScope*scope) const;
|
||||
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
|
||||
|
||||
private:
|
||||
unsigned calculate_array_count_(Design*, NetScope*,
|
||||
long&high, long&low) const;
|
||||
|
||||
void calculate_gate_and_lval_count_(unsigned&gate_count,
|
||||
unsigned&lval_count) const;
|
||||
|
||||
@@ -179,8 +183,6 @@ class PGBuiltin : public PGate {
|
||||
bool check_delay_count(Design*des) const;
|
||||
|
||||
Type type_;
|
||||
PExpr*msb_;
|
||||
PExpr*lsb_;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -197,7 +199,7 @@ class PGModule : public PGate {
|
||||
// If the binding of ports is by position, this constructor
|
||||
// builds everything all at once.
|
||||
explicit PGModule(perm_string type, perm_string name,
|
||||
list<PExpr*>*pins);
|
||||
std::list<PExpr*>*pins);
|
||||
|
||||
// If the binding of ports is by name, this constructor takes
|
||||
// the bindings and stores them for later elaboration.
|
||||
@@ -212,16 +214,12 @@ class PGModule : public PGate {
|
||||
|
||||
// Parameter overrides can come as an ordered list, or a set
|
||||
// of named expressions.
|
||||
void set_parameters(list<PExpr*>*o);
|
||||
void set_parameters(std::list<PExpr*>*o);
|
||||
void set_parameters(named<PExpr*>*pa, unsigned npa);
|
||||
|
||||
// Modules can be instantiated in ranges. The parser uses this
|
||||
// method to pass the range to the pform.
|
||||
void set_range(PExpr*msb, PExpr*lsb);
|
||||
std::map<perm_string,PExpr*> attributes;
|
||||
|
||||
map<perm_string,PExpr*> attributes;
|
||||
|
||||
virtual void dump(ostream&out, unsigned ind =4) const;
|
||||
virtual void dump(std::ostream&out, unsigned ind =4) const;
|
||||
virtual void elaborate(Design*, NetScope*scope) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*sc) const;
|
||||
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
|
||||
@@ -233,7 +231,7 @@ class PGModule : public PGate {
|
||||
private:
|
||||
Module*bound_type_;
|
||||
perm_string type_;
|
||||
list<PExpr*>*overrides_;
|
||||
std::list<PExpr*>*overrides_;
|
||||
named<PExpr*>*pins_;
|
||||
unsigned npins_;
|
||||
|
||||
@@ -241,16 +239,9 @@ class PGModule : public PGate {
|
||||
named<PExpr*>*parms_;
|
||||
unsigned nparms_;
|
||||
|
||||
// Arrays of modules are give if these are set.
|
||||
PExpr*msb_;
|
||||
PExpr*lsb_;
|
||||
|
||||
friend class delayed_elaborate_scope_mod_instances;
|
||||
void elaborate_mod_(Design*, Module*mod, NetScope*scope) const;
|
||||
void elaborate_udp_(Design*, PUdp *udp, NetScope*scope) const;
|
||||
unsigned calculate_instance_count_(Design*, NetScope*,
|
||||
long&high, long&low,
|
||||
perm_string name) const;
|
||||
void elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const;
|
||||
void elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*sc) const;
|
||||
bool elaborate_sig_mod_(Design*des, NetScope*scope, Module*mod) const;
|
||||
|
||||
+4
-47
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2020 Stephen Williams ([email protected])
|
||||
* Copyright (c) 2006-2021 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -21,11 +21,13 @@
|
||||
# include "PWire.h"
|
||||
# include "ivl_assert.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
PGenerate::PGenerate(LexicalScope*parent, unsigned id)
|
||||
: LexicalScope(parent), id_number(id)
|
||||
{
|
||||
direct_nested_ = false;
|
||||
scheme_type = GS_NONE;
|
||||
directly_nested = false;
|
||||
local_index = false;
|
||||
loop_init = 0;
|
||||
loop_test = 0;
|
||||
@@ -41,51 +43,6 @@ void PGenerate::add_gate(PGate*gate)
|
||||
gates.push_back(gate);
|
||||
}
|
||||
|
||||
void PGenerate::probe_for_direct_nesting_(void)
|
||||
{
|
||||
direct_nested_ = false;
|
||||
|
||||
ivl_assert(*this, scheme_type==GS_CASE_ITEM || scheme_type==GS_CONDIT || scheme_type==GS_ELSE);
|
||||
|
||||
// If this scheme has received an explicit name, then it
|
||||
// cannot be direct nested.
|
||||
if (scope_name[0] != '$') return;
|
||||
|
||||
if (! tasks.empty()) return;
|
||||
if (! funcs.empty()) return;
|
||||
if (! gates.empty()) return;
|
||||
if (! parameters.empty()) return;
|
||||
if (! localparams.empty()) return;
|
||||
if (! events.empty()) return;
|
||||
if (! wires.empty()) return;
|
||||
if (! genvars.empty()) return;
|
||||
if (! behaviors.empty()) return;
|
||||
if (! analog_behaviors.empty()) return;
|
||||
|
||||
if (generate_schemes.empty()) return;
|
||||
|
||||
switch (generate_schemes.size()) {
|
||||
case 1: {
|
||||
PGenerate*child = generate_schemes.front();
|
||||
if (child->scheme_type == GS_CONDIT)
|
||||
direct_nested_ = true;
|
||||
if (child->scheme_type == GS_CASE)
|
||||
direct_nested_ = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case 2: {
|
||||
PGenerate*child1 = generate_schemes.front();
|
||||
PGenerate*child2 = generate_schemes.back();
|
||||
if (child1->scheme_type==GS_CONDIT && child2->scheme_type==GS_ELSE)
|
||||
direct_nested_ = true;
|
||||
if (child2->scheme_type==GS_CONDIT && child1->scheme_type==GS_ELSE)
|
||||
direct_nested_ = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ostream& operator << (ostream&out, PGenerate::scheme_t type)
|
||||
{
|
||||
switch (type) {
|
||||
|
||||
+12
-16
@@ -1,7 +1,7 @@
|
||||
#ifndef IVL_PGenerate_H
|
||||
#define IVL_PGenerate_H
|
||||
/*
|
||||
* Copyright (c) 2006-2020 Stephen Williams ([email protected])
|
||||
* Copyright (c) 2006-2021 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -69,6 +69,8 @@ class PGenerate : public PNamedItem, public LexicalScope {
|
||||
GS_CASE, GS_CASE_ITEM, GS_NBLOCK};
|
||||
scheme_t scheme_type;
|
||||
|
||||
bool directly_nested;
|
||||
|
||||
// generate loops have an index variable and three
|
||||
// expressions: for (index = <init>; <test>; index=<step>)
|
||||
// the index is local if it was declared in the init expression,
|
||||
@@ -84,18 +86,18 @@ class PGenerate : public PNamedItem, public LexicalScope {
|
||||
std::valarray<PExpr*> item_test;
|
||||
|
||||
// defparam assignments found in this scope.
|
||||
typedef pair<pform_name_t,PExpr*> named_expr_t;
|
||||
list<named_expr_t>defparms;
|
||||
typedef std::pair<pform_name_t,PExpr*> named_expr_t;
|
||||
std::list<named_expr_t>defparms;
|
||||
|
||||
list<PGate*> gates;
|
||||
std::list<PGate*> gates;
|
||||
void add_gate(PGate*);
|
||||
|
||||
// Tasks instantiated within this scheme.
|
||||
map<perm_string,PTask*> tasks;
|
||||
map<perm_string,PFunction*>funcs;
|
||||
std::map<perm_string,PTask*> tasks;
|
||||
std::map<perm_string,PFunction*>funcs;
|
||||
|
||||
// Generate schemes can contain further generate schemes.
|
||||
list<PGenerate*> generate_schemes;
|
||||
std::list<PGenerate*> generate_schemes;
|
||||
// PGenerate*parent;
|
||||
|
||||
// This method is called by the elaboration of a module to
|
||||
@@ -108,29 +110,23 @@ class PGenerate : public PNamedItem, public LexicalScope {
|
||||
bool elaborate_sig(Design*des, NetScope*container) const;
|
||||
bool elaborate(Design*des, NetScope*container) const;
|
||||
|
||||
void dump(ostream&out, unsigned indent) const;
|
||||
void dump(std::ostream&out, unsigned indent) const;
|
||||
|
||||
SymbolType symbol_type() const;
|
||||
|
||||
private:
|
||||
void check_for_valid_genvar_value_(long value);
|
||||
bool generate_scope_loop_(Design*des, NetScope*container);
|
||||
bool generate_scope_condit_(Design*des, NetScope*container, bool else_flag);
|
||||
bool generate_scope_case_(Design*des, NetScope*container);
|
||||
bool generate_scope_nblock_(Design*des, NetScope*container);
|
||||
|
||||
// Call probe during elaborate_scope to calculate the
|
||||
// direct_nested_ flag. It is OK to store the direct_nested_
|
||||
// information here because "direct nested" is a property of
|
||||
// the lexical generate code.
|
||||
void probe_for_direct_nesting_(void);
|
||||
bool direct_nested_;
|
||||
|
||||
// Elaborate_scope within a generated scope.
|
||||
void elaborate_subscope_(Design*des, NetScope*scope);
|
||||
void elaborate_subscope_direct_(Design*des, NetScope*scope);
|
||||
|
||||
// These are the scopes created by generate_scope.
|
||||
list<NetScope*>scope_list_;
|
||||
std::list<NetScope*>scope_list_;
|
||||
// internal function called on each scope generated by this scheme.
|
||||
bool elaborate_sig_(Design*des, NetScope*scope) const;
|
||||
bool elaborate_sig_direct_(Design*des, NetScope*scope) const;
|
||||
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
#ifndef IVL_PModport_H
|
||||
#define IVL_PModport_H
|
||||
/*
|
||||
* Copyright (c) 2015-2019 Stephen Williams ([email protected])
|
||||
* Copyright (c) 2015-2021 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -38,8 +38,8 @@ class PModport : public PNamedItem {
|
||||
|
||||
perm_string name() const { return name_; }
|
||||
|
||||
typedef pair <NetNet::PortType,PExpr*> simple_port_t;
|
||||
map<perm_string,simple_port_t> simple_ports;
|
||||
typedef std::pair <NetNet::PortType,PExpr*> simple_port_t;
|
||||
std::map<perm_string,simple_port_t> simple_ports;
|
||||
|
||||
SymbolType symbol_type() const;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2019 Stephen Williams ([email protected])
|
||||
* Copyright (c) 2008-2021 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -19,6 +19,8 @@
|
||||
|
||||
# include "PScope.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
bool LexicalScope::var_init_needs_explicit_lifetime() const
|
||||
{
|
||||
return false;
|
||||
@@ -49,8 +51,8 @@ PScope::PScope(perm_string n, LexicalScope*parent)
|
||||
|
||||
PScope::~PScope()
|
||||
{
|
||||
for(map<perm_string, data_type_t*>::iterator it = typedefs.begin();
|
||||
it != typedefs.end(); ++it)
|
||||
for(typedef_map_t::iterator it = typedefs.begin(); it != typedefs.end();
|
||||
++it)
|
||||
delete it->second;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef IVL_PScope_H
|
||||
#define IVL_PScope_H
|
||||
/*
|
||||
* Copyright (c) 2008-2019 Stephen Williams ([email protected])
|
||||
* Copyright (c) 2008-2021 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -37,6 +37,7 @@ class PClass;
|
||||
class PTask;
|
||||
class PWire;
|
||||
class Statement;
|
||||
class PCallTask;
|
||||
|
||||
class Design;
|
||||
class NetScope;
|
||||
@@ -55,7 +56,9 @@ class LexicalScope {
|
||||
public:
|
||||
enum lifetime_t { INHERITED, STATIC, AUTOMATIC };
|
||||
|
||||
explicit LexicalScope(LexicalScope*parent) : default_lifetime(INHERITED), parent_(parent) { }
|
||||
explicit LexicalScope(LexicalScope*parent)
|
||||
: default_lifetime(INHERITED), has_parameter_port_list(false),
|
||||
generate_counter(0), parent_(parent) { }
|
||||
// A virtual destructor is so that dynamic_cast can work.
|
||||
virtual ~LexicalScope() { }
|
||||
|
||||
@@ -71,7 +74,7 @@ class LexicalScope {
|
||||
// Packages that are wildcard imported. When identifiers from
|
||||
// these packages are referenced, they will be added to the
|
||||
// explicit imports (IEEE 1800-2012 26.3).
|
||||
std::set<PPackage*>potential_imports;
|
||||
std::list<PPackage*>potential_imports;
|
||||
|
||||
// A task or function call may reference a task or function defined
|
||||
// later in the scope. So here we stash the potential imports for
|
||||
@@ -98,65 +101,76 @@ class LexicalScope {
|
||||
is elaborated. During parsing, I put the parameters into
|
||||
this map. */
|
||||
struct param_expr_t : public PNamedItem {
|
||||
param_expr_t() : type(IVL_VT_NO_TYPE), msb(0), lsb(0), signed_flag(false), expr(0), range(0) { }
|
||||
// Type information
|
||||
ivl_variable_type_t type;
|
||||
PExpr*msb;
|
||||
PExpr*lsb;
|
||||
bool signed_flag;
|
||||
inline param_expr_t() : data_type(0), expr(0), range(0),
|
||||
local_flag(false), overridable(true) { }
|
||||
// Type information.
|
||||
data_type_t*data_type;
|
||||
// Value expression
|
||||
PExpr*expr;
|
||||
// If there are range constraints, list them here
|
||||
range_t*range;
|
||||
// Whether it is a local parameter
|
||||
bool local_flag;
|
||||
// Whether the parameter can be overridden
|
||||
bool overridable;
|
||||
// Whether the parameter is a type parameter
|
||||
bool type_flag = false;
|
||||
|
||||
SymbolType symbol_type() const;
|
||||
};
|
||||
map<perm_string,param_expr_t*>parameters;
|
||||
map<perm_string,param_expr_t*>localparams;
|
||||
std::map<perm_string,param_expr_t*>parameters;
|
||||
bool has_parameter_port_list;
|
||||
|
||||
// Defined types in the scope.
|
||||
map<perm_string,data_type_t*>typedefs;
|
||||
typedef std::map<perm_string,typedef_t*> typedef_map_t;
|
||||
typedef_map_t typedefs;
|
||||
|
||||
// Named events in the scope.
|
||||
map<perm_string,PEvent*>events;
|
||||
std::map<perm_string,PEvent*>events;
|
||||
|
||||
// Nets and variables (wires) in the scope
|
||||
map<perm_string,PWire*>wires;
|
||||
std::map<perm_string,PWire*>wires;
|
||||
PWire* wires_find(perm_string name);
|
||||
|
||||
// Genvars in the scope. These will only be present in module
|
||||
// scopes, but are listed here to allow them to be found when
|
||||
// creating implicit nets.
|
||||
map<perm_string,LineInfo*> genvars;
|
||||
std::map<perm_string,LineInfo*> genvars;
|
||||
|
||||
// Variable initializations in this scope
|
||||
vector<Statement*> var_inits;
|
||||
std::vector<Statement*> var_inits;
|
||||
|
||||
// Behaviors (processes) in this scope
|
||||
list<PProcess*> behaviors;
|
||||
list<AProcess*> analog_behaviors;
|
||||
std::list<PProcess*> behaviors;
|
||||
std::list<AProcess*> analog_behaviors;
|
||||
|
||||
// The elaboration tasks in this scope
|
||||
std::list<PCallTask*> elab_tasks;
|
||||
|
||||
// Enumeration sets.
|
||||
std::set<enum_type_t*> enum_sets;
|
||||
std::vector<enum_type_t*> enum_sets;
|
||||
|
||||
// A count of the generate constructs in this scope. This is
|
||||
// used to automatically name unnamed generate blocks, as
|
||||
// specified in the LRM.
|
||||
unsigned generate_counter;
|
||||
|
||||
LexicalScope* parent_scope() const { return parent_; }
|
||||
|
||||
virtual bool var_init_needs_explicit_lifetime() const;
|
||||
|
||||
protected:
|
||||
void dump_typedefs_(ostream&out, unsigned indent) const;
|
||||
void dump_typedefs_(std::ostream&out, unsigned indent) const;
|
||||
|
||||
void dump_parameters_(ostream&out, unsigned indent) const;
|
||||
void dump_parameters_(std::ostream&out, unsigned indent) const;
|
||||
|
||||
void dump_localparams_(ostream&out, unsigned indent) const;
|
||||
void dump_enumerations_(std::ostream&out, unsigned indent) const;
|
||||
|
||||
void dump_enumerations_(ostream&out, unsigned indent) const;
|
||||
void dump_events_(std::ostream&out, unsigned indent) const;
|
||||
|
||||
void dump_events_(ostream&out, unsigned indent) const;
|
||||
void dump_wires_(std::ostream&out, unsigned indent) const;
|
||||
|
||||
void dump_wires_(ostream&out, unsigned indent) const;
|
||||
|
||||
void dump_var_inits_(ostream&out, unsigned indent) const;
|
||||
void dump_var_inits_(std::ostream&out, unsigned indent) const;
|
||||
|
||||
bool elaborate_var_inits_(Design*des, NetScope*scope) const;
|
||||
|
||||
@@ -227,9 +241,9 @@ class PScopeExtra : public PScope {
|
||||
bool time_prec_is_local;
|
||||
|
||||
protected:
|
||||
void dump_classes_(ostream&out, unsigned indent) const;
|
||||
void dump_tasks_(ostream&out, unsigned indent) const;
|
||||
void dump_funcs_(ostream&out, unsigned indent) const;
|
||||
void dump_classes_(std::ostream&out, unsigned indent) const;
|
||||
void dump_tasks_(std::ostream&out, unsigned indent) const;
|
||||
void dump_funcs_(std::ostream&out, unsigned indent) const;
|
||||
};
|
||||
|
||||
#endif /* IVL_PScope_H */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2019 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1999-2021 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -21,6 +21,8 @@
|
||||
# include "PTask.h"
|
||||
# include <cassert>
|
||||
|
||||
using namespace std;
|
||||
|
||||
PTaskFunc::PTaskFunc(perm_string n, LexicalScope*p)
|
||||
: PScope(n,p), this_type_(0), ports_(0)
|
||||
{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef IVL_PTask_H
|
||||
#define IVL_PTask_H
|
||||
/*
|
||||
* Copyright (c) 1999-2019 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1999-2021 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -97,7 +97,7 @@ class PTask : public PTaskFunc {
|
||||
|
||||
bool is_auto() const { return is_auto_; };
|
||||
|
||||
void dump(ostream&, unsigned) const;
|
||||
void dump(std::ostream&, unsigned) const;
|
||||
|
||||
SymbolType symbol_type() const;
|
||||
|
||||
@@ -148,7 +148,7 @@ class PFunction : public PTaskFunc {
|
||||
|
||||
bool is_auto() const { return is_auto_; };
|
||||
|
||||
void dump(ostream&, unsigned) const;
|
||||
void dump(std::ostream&, unsigned) const;
|
||||
|
||||
SymbolType symbol_type() const;
|
||||
|
||||
@@ -158,4 +158,31 @@ class PFunction : public PTaskFunc {
|
||||
bool is_auto_;
|
||||
};
|
||||
|
||||
// A let is like a simple function that is expanded in the compiler
|
||||
class PLet : public PTaskFunc {
|
||||
public:
|
||||
typedef struct let_port {
|
||||
data_type_t*type_;
|
||||
perm_string name_;
|
||||
std::list<pform_range_t>*range_;
|
||||
PExpr*def_;
|
||||
|
||||
void dump(std::ostream&, unsigned) const;
|
||||
} let_port_t;
|
||||
|
||||
// FIXME: Should the port list be a vector. Check once implemented completely
|
||||
explicit PLet(perm_string name, LexicalScope*parent,
|
||||
std::list<let_port_t*>*ports, PExpr*expr);
|
||||
~PLet();
|
||||
|
||||
void elaborate_sig(Design*des, NetScope*scope) const { (void)des; (void)scope; }
|
||||
void elaborate(Design*des, NetScope*scope) const { (void)des; (void)scope; }
|
||||
|
||||
void dump(std::ostream&, unsigned) const;
|
||||
|
||||
private:
|
||||
std::list<let_port_t*>*ports_;
|
||||
PExpr*expr_;
|
||||
};
|
||||
|
||||
#endif /* IVL_PTask_H */
|
||||
|
||||
@@ -26,12 +26,12 @@ PUdp::PUdp(perm_string n, unsigned nports)
|
||||
|
||||
unsigned PUdp::find_port(const char*name)
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < ports.count() ; idx += 1) {
|
||||
for (unsigned idx = 0 ; idx < ports.size() ; idx += 1) {
|
||||
|
||||
if (ports[idx] == name)
|
||||
return idx;
|
||||
}
|
||||
|
||||
return ports.count();
|
||||
return ports.size();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef IVL_PUdp_H
|
||||
#define IVL_PUdp_H
|
||||
/*
|
||||
* Copyright (c) 1998-2014 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2021 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -20,9 +20,9 @@
|
||||
*/
|
||||
|
||||
# include <map>
|
||||
# include <vector>
|
||||
# include "LineInfo.h"
|
||||
# include "StringHeap.h"
|
||||
# include "svector.h"
|
||||
# include "verinum.h"
|
||||
|
||||
class PExpr;
|
||||
@@ -53,20 +53,20 @@ class PUdp : public LineInfo {
|
||||
public:
|
||||
explicit PUdp(perm_string n, unsigned nports);
|
||||
|
||||
svector<string>ports;
|
||||
std::vector<std::string> ports;
|
||||
unsigned find_port(const char*name);
|
||||
|
||||
bool sequential;
|
||||
|
||||
svector<string>tinput;
|
||||
svector<char> tcurrent;
|
||||
svector<char> toutput;
|
||||
std::vector<std::string> tinput;
|
||||
std::vector<char> tcurrent;
|
||||
std::vector<char> toutput;
|
||||
|
||||
verinum::V initial;
|
||||
|
||||
map<string,PExpr*> attributes;
|
||||
std::map<std::string,PExpr*> attributes;
|
||||
|
||||
void dump(ostream&out) const;
|
||||
void dump(std::ostream&out) const;
|
||||
|
||||
perm_string name_;
|
||||
private:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2019 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1999-2021 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -18,24 +18,32 @@
|
||||
*/
|
||||
|
||||
# include "config.h"
|
||||
# include "ivl_assert.h"
|
||||
# include "PWire.h"
|
||||
# include "PExpr.h"
|
||||
# include <cassert>
|
||||
|
||||
using namespace std;
|
||||
|
||||
PWire::PWire(perm_string n,
|
||||
NetNet::Type t,
|
||||
NetNet::PortType pt,
|
||||
ivl_variable_type_t dt)
|
||||
: name_(n), type_(t), port_type_(pt), data_type_(dt),
|
||||
signed_(false), isint_(false),
|
||||
PWSRType rt)
|
||||
: name_(n), type_(t), port_type_(pt), signed_(false),
|
||||
port_set_(false), net_set_(false), is_scalar_(false),
|
||||
error_cnt_(0), uarray_type_(0), set_data_type_(0),
|
||||
discipline_(0)
|
||||
error_cnt_(0), discipline_(0)
|
||||
{
|
||||
if (t == NetNet::INTEGER) {
|
||||
type_ = NetNet::REG;
|
||||
signed_ = true;
|
||||
isint_ = true;
|
||||
switch (rt) {
|
||||
case SR_PORT:
|
||||
port_set_ = true;
|
||||
break;
|
||||
case SR_NET:
|
||||
net_set_ = true;
|
||||
break;
|
||||
case SR_BOTH:
|
||||
port_set_ = true;
|
||||
net_set_ = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,18 +70,9 @@ bool PWire::set_wire_type(NetNet::Type t)
|
||||
type_ = t;
|
||||
return true;
|
||||
}
|
||||
if (t == NetNet::INTEGER) {
|
||||
type_ = NetNet::REG;
|
||||
isint_ = true;
|
||||
return true;
|
||||
}
|
||||
if (t == NetNet::IMPLICIT_REG) return true;
|
||||
return false;
|
||||
case NetNet::REG:
|
||||
if (t == NetNet::INTEGER) {
|
||||
isint_ = true;
|
||||
return true;
|
||||
}
|
||||
if (t == NetNet::REG) return true;
|
||||
return false;
|
||||
default:
|
||||
@@ -96,12 +95,10 @@ bool PWire::set_port_type(NetNet::PortType pt)
|
||||
|
||||
switch (port_type_) {
|
||||
case NetNet::PIMPLICIT:
|
||||
case NetNet::NOT_A_PORT:
|
||||
port_type_ = pt;
|
||||
return true;
|
||||
|
||||
case NetNet::NOT_A_PORT:
|
||||
return false;
|
||||
|
||||
default:
|
||||
if (port_type_ != pt)
|
||||
return false;
|
||||
@@ -110,29 +107,15 @@ bool PWire::set_port_type(NetNet::PortType pt)
|
||||
}
|
||||
}
|
||||
|
||||
bool PWire::set_data_type(ivl_variable_type_t dt)
|
||||
{
|
||||
if (data_type_ != IVL_VT_NO_TYPE) {
|
||||
if (data_type_ != dt)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
assert(data_type_ == IVL_VT_NO_TYPE);
|
||||
data_type_ = dt;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
ivl_variable_type_t PWire::get_data_type() const
|
||||
{
|
||||
return data_type_;
|
||||
}
|
||||
|
||||
void PWire::set_signed(bool flag)
|
||||
{
|
||||
signed_ = flag;
|
||||
// For a non-ANSI style port declaration where the data type is
|
||||
// specified in a corresponding variable declaration, the signed
|
||||
// attribute may be attached to either the port declaration or to
|
||||
// the variable declaration (IEEE 1364-2005 section 12.3.3). The
|
||||
// signal is signed if either the port or the variable is signed.
|
||||
// Handle that here.
|
||||
signed_ = signed_ || flag;
|
||||
}
|
||||
|
||||
bool PWire::get_signed() const
|
||||
@@ -140,64 +123,23 @@ bool PWire::get_signed() const
|
||||
return signed_;
|
||||
}
|
||||
|
||||
bool PWire::get_isint() const
|
||||
void PWire::set_port(NetNet::PortType pt)
|
||||
{
|
||||
if (isint_)
|
||||
return true;
|
||||
ivl_assert(*this, !port_set_);
|
||||
port_set_ = true;
|
||||
|
||||
if (vector_type_t*tmp = dynamic_cast<vector_type_t*>(set_data_type_)) {
|
||||
return tmp->integer_flag;
|
||||
}
|
||||
|
||||
return false;
|
||||
bool rc = set_port_type(pt);
|
||||
ivl_assert(*this, rc);
|
||||
}
|
||||
|
||||
bool PWire::get_scalar() const
|
||||
void PWire::set_net(NetNet::Type t)
|
||||
{
|
||||
return is_scalar_;
|
||||
}
|
||||
ivl_assert(*this, !net_set_);
|
||||
net_set_ = true;
|
||||
|
||||
void PWire::set_range_scalar(PWSRType type)
|
||||
{
|
||||
is_scalar_ = true;
|
||||
switch (type) {
|
||||
case SR_PORT:
|
||||
if (port_set_) {
|
||||
cerr << get_fileline() << ": error: Port ``" << name_
|
||||
<< "'' has already been declared a port." << endl;
|
||||
error_cnt_ += 1;
|
||||
} else {
|
||||
port_set_ = true;
|
||||
}
|
||||
return;
|
||||
|
||||
case SR_NET:
|
||||
if (net_set_) {
|
||||
cerr << get_fileline() << ": error: Net ``" << name_
|
||||
<< "'' has already been declared." << endl;
|
||||
error_cnt_ += 1;
|
||||
} else {
|
||||
net_set_ = true;
|
||||
}
|
||||
return;
|
||||
|
||||
case SR_BOTH:
|
||||
if (port_set_ || net_set_) {
|
||||
if (port_set_) {
|
||||
cerr << get_fileline() << ": error: Port ``" << name_
|
||||
<< "'' has already been declared a port." << endl;
|
||||
error_cnt_ += 1;
|
||||
}
|
||||
if (net_set_) {
|
||||
cerr << get_fileline() << ": error: Net ``" << name_
|
||||
<< "'' has already been declared." << endl;
|
||||
error_cnt_ += 1;
|
||||
}
|
||||
} else {
|
||||
port_set_ = true;
|
||||
net_set_ = true;
|
||||
}
|
||||
return;
|
||||
if (t != NetNet::IMPLICIT) {
|
||||
bool rc = set_wire_type(t);
|
||||
ivl_assert(*this, rc);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -205,49 +147,21 @@ void PWire::set_range(const list<pform_range_t>&rlist, PWSRType type)
|
||||
{
|
||||
switch (type) {
|
||||
case SR_PORT:
|
||||
if (port_set_) {
|
||||
cerr << get_fileline() << ": error: Port ``" << name_
|
||||
<< "'' has already been declared a port." << endl;
|
||||
error_cnt_ += 1;
|
||||
} else {
|
||||
port_ = rlist;
|
||||
port_set_ = true;
|
||||
is_scalar_ = false;
|
||||
}
|
||||
return;
|
||||
|
||||
if (!port_.empty())
|
||||
return;
|
||||
port_ = rlist;
|
||||
break;
|
||||
case SR_NET:
|
||||
if (net_set_) {
|
||||
cerr << get_fileline() << ": error: Net ``" << name_
|
||||
<< "'' has already been declared." << endl;
|
||||
error_cnt_ += 1;
|
||||
} else {
|
||||
net_ = rlist;
|
||||
net_set_ = true;
|
||||
is_scalar_ = false;
|
||||
}
|
||||
return;
|
||||
|
||||
if (!net_.empty())
|
||||
return;
|
||||
net_ = rlist;
|
||||
break;
|
||||
case SR_BOTH:
|
||||
if (port_set_ || net_set_) {
|
||||
if (port_set_) {
|
||||
cerr << get_fileline() << ": error: Port ``" << name_
|
||||
<< "'' has already been declared a port." << endl;
|
||||
error_cnt_ += 1;
|
||||
}
|
||||
if (net_set_) {
|
||||
cerr << get_fileline() << ": error: Net ``" << name_
|
||||
<< "'' has already been declared." << endl;
|
||||
error_cnt_ += 1;
|
||||
}
|
||||
} else {
|
||||
port_ = rlist;
|
||||
port_set_ = true;
|
||||
net_ = rlist;
|
||||
net_set_ = true;
|
||||
is_scalar_ = false;
|
||||
}
|
||||
return;
|
||||
if (!port_.empty() || !net_.empty())
|
||||
return;
|
||||
port_ = rlist;
|
||||
net_ = rlist;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -264,13 +178,11 @@ void PWire::set_unpacked_idx(const list<pform_range_t>&ranges)
|
||||
|
||||
void PWire::set_data_type(data_type_t*type)
|
||||
{
|
||||
assert(set_data_type_ == 0);
|
||||
set_data_type_ = type;
|
||||
if (set_data_type_.get() == type)
|
||||
return;
|
||||
|
||||
if (vector_type_t*tmp = dynamic_cast<vector_type_t*>(type)) {
|
||||
if (tmp->integer_flag)
|
||||
isint_ = true;
|
||||
}
|
||||
assert(!set_data_type_.get());
|
||||
set_data_type_.reset(type);
|
||||
}
|
||||
|
||||
void PWire::set_discipline(ivl_discipline_t d)
|
||||
@@ -288,7 +200,6 @@ PNamedItem::SymbolType PWire::symbol_type() const
|
||||
{
|
||||
switch (type_) {
|
||||
case NetNet::IMPLICIT_REG:
|
||||
case NetNet::INTEGER:
|
||||
case NetNet::REG:
|
||||
return VAR;
|
||||
default:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef IVL_PWire_H
|
||||
#define IVL_PWire_H
|
||||
/*
|
||||
* Copyright (c) 1998-2019 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2021 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -28,7 +28,7 @@
|
||||
#ifdef HAVE_IOSFWD
|
||||
# include <iosfwd>
|
||||
#else
|
||||
class ostream;
|
||||
# include <iostream>
|
||||
#endif
|
||||
|
||||
class PExpr;
|
||||
@@ -57,7 +57,7 @@ class PWire : public PNamedItem {
|
||||
PWire(perm_string name,
|
||||
NetNet::Type t,
|
||||
NetNet::PortType pt,
|
||||
ivl_variable_type_t dt);
|
||||
PWSRType rt = SR_NET);
|
||||
|
||||
// Return a hierarchical name.
|
||||
perm_string basename() const;
|
||||
@@ -70,39 +70,35 @@ class PWire : public PNamedItem {
|
||||
|
||||
void set_signed(bool flag);
|
||||
bool get_signed() const;
|
||||
bool get_isint() const;
|
||||
bool get_scalar() const;
|
||||
|
||||
bool set_data_type(ivl_variable_type_t dt);
|
||||
ivl_variable_type_t get_data_type() const;
|
||||
|
||||
void set_range_scalar(PWSRType type);
|
||||
void set_range(const std::list<pform_range_t>&ranges, PWSRType type);
|
||||
|
||||
void set_unpacked_idx(const std::list<pform_range_t>&ranges);
|
||||
void set_uarray_type(uarray_type_t*type) { uarray_type_ = type; }
|
||||
|
||||
void set_data_type(data_type_t*type);
|
||||
|
||||
void set_discipline(ivl_discipline_t);
|
||||
ivl_discipline_t get_discipline(void) const;
|
||||
|
||||
map<perm_string,PExpr*> attributes;
|
||||
std::map<perm_string,PExpr*> attributes;
|
||||
|
||||
// Write myself to the specified stream.
|
||||
void dump(ostream&out, unsigned ind=4) const;
|
||||
void dump(std::ostream&out, unsigned ind=4) const;
|
||||
|
||||
NetNet* elaborate_sig(Design*, NetScope*scope) const;
|
||||
|
||||
SymbolType symbol_type() const;
|
||||
|
||||
bool is_net() const { return net_set_; };
|
||||
bool is_port() const { return port_set_; };
|
||||
void set_net(NetNet::Type t);
|
||||
void set_port(NetNet::PortType pt);
|
||||
|
||||
private:
|
||||
perm_string name_;
|
||||
NetNet::Type type_;
|
||||
NetNet::PortType port_type_;
|
||||
ivl_variable_type_t data_type_;
|
||||
bool signed_;
|
||||
bool isint_; // original type of integer
|
||||
|
||||
// These members hold expressions for the bit width of the
|
||||
// wire. If they do not exist, the wire is 1 bit wide. If they
|
||||
@@ -120,17 +116,23 @@ class PWire : public PNamedItem {
|
||||
// If this wire is actually a memory, these indices will give
|
||||
// me the size and address ranges of the memory.
|
||||
std::list<pform_range_t>unpacked_;
|
||||
uarray_type_t*uarray_type_;
|
||||
|
||||
// This is the complex type of the wire. the data_type_ may
|
||||
// modify how this is interpreted.
|
||||
data_type_t*set_data_type_;
|
||||
std::unique_ptr<data_type_t> set_data_type_;
|
||||
|
||||
ivl_discipline_t discipline_;
|
||||
|
||||
private: // not implemented
|
||||
PWire(const PWire&);
|
||||
PWire& operator= (const PWire&);
|
||||
|
||||
ivl_type_t elaborate_type(Design*des, NetScope*scope,
|
||||
const std::vector<netrange_t>&packed_dimensions) const;
|
||||
ivl_type_t elaborate_darray_type(Design*des, NetScope*scope,
|
||||
const char *darray_type,
|
||||
const std::vector<netrange_t>&packed_dimensions)
|
||||
const;
|
||||
};
|
||||
|
||||
#endif /* IVL_PWire_H */
|
||||
|
||||
@@ -0,0 +1,514 @@
|
||||
# The ICARUS Verilog Compilation System
|
||||
|
||||
Copyright 2000-2019 Stephen Williams
|
||||
|
||||
|
||||
## What is ICARUS Verilog?
|
||||
|
||||
Icarus Verilog is intended to compile ALL of the Verilog HDL as
|
||||
described in the IEEE-1364 standard. Of course, it's not quite there
|
||||
yet. It does currently handle a mix of structural and behavioural
|
||||
constructs. For a view of the current state of Icarus Verilog, see its
|
||||
home page at http://iverilog.icarus.com/.
|
||||
|
||||
Icarus Verilog is not aimed at being a simulator in the traditional
|
||||
sense, but a compiler that generates code employed by back-end
|
||||
tools.
|
||||
|
||||
> For instructions on how to run Icarus Verilog, see the `iverilog` man page.
|
||||
|
||||
|
||||
## Building/Installing Icarus Verilog From Source
|
||||
|
||||
If you are starting from the source, the build process is designed to be
|
||||
as simple as practical. Someone basically familiar with the target
|
||||
system and C/C++ compilation should be able to build the source
|
||||
distribution with little effort. Some actual programming skills are
|
||||
not required, but helpful in case of problems.
|
||||
|
||||
> If you are building on Windows, see the mingw.txt file.
|
||||
|
||||
### Compile Time Prerequisites
|
||||
|
||||
You need the following software to compile Icarus Verilog from source
|
||||
on a UNIX-like system:
|
||||
|
||||
- GNU Make
|
||||
The Makefiles use some GNU extensions, so a basic POSIX
|
||||
make will not work. Linux systems typically come with a
|
||||
satisfactory make. BSD based systems (i.e., NetBSD, FreeBSD)
|
||||
typically have GNU make as the gmake program.
|
||||
|
||||
- ISO C++ Compiler
|
||||
The ivl and ivlpp programs are written in C++ and make use
|
||||
of templates and some of the standard C++ library. egcs and
|
||||
recent gcc compilers with the associated libstdc++ are known
|
||||
to work. MSVC++ 5 and 6 are known to definitely *not* work.
|
||||
|
||||
- bison and flex
|
||||
OSX note: bison 2.3 shipped with MacOS including Catalina generates
|
||||
broken code, but bison 3+ works. We recommend using the Fink
|
||||
project version of bison and flex (finkproject.org), brew version
|
||||
works fine either.
|
||||
|
||||
- gperf 3.0 or later
|
||||
The lexical analyzer doesn't recognize keywords directly,
|
||||
but instead matches symbols and looks them up in a hash
|
||||
table in order to get the proper lexical code. The gperf
|
||||
program generates the lookup table.
|
||||
|
||||
A version problem with this program is the most common cause
|
||||
of difficulty. See the Icarus Verilog FAQ.
|
||||
|
||||
- readline 4.2 or later
|
||||
On Linux systems, this usually means the readline-devel
|
||||
rpm. In any case, it is the development headers of readline
|
||||
that are needed.
|
||||
|
||||
- termcap
|
||||
The readline library, in turn, uses termcap.
|
||||
|
||||
> If you are building from git, you will also need software to generate the configure scripts.
|
||||
|
||||
- autoconf 2.53 or later
|
||||
This generates configure scripts from configure.ac. The 2.53
|
||||
or later versions are known to work, autoconf 2.13 is
|
||||
reported to *not* work.
|
||||
|
||||
### Compilation
|
||||
|
||||
Unpack the tar-ball and cd into the `verilog-#########` directory
|
||||
(presumably, that is how you got to this README) and compile the source
|
||||
with the commands:
|
||||
|
||||
```
|
||||
./configure
|
||||
make
|
||||
```
|
||||
|
||||
If you are building from git, you have to run the command below before
|
||||
compiling the source. This will generate the "configure" file, which is
|
||||
automatically done when building from tarball.
|
||||
|
||||
```
|
||||
sh autoconf.sh
|
||||
```
|
||||
|
||||
Normally, this command automatically figures out everything it needs
|
||||
to know. It generally works pretty well. There are a few flags to the
|
||||
configure script that modify its behaviour:
|
||||
|
||||
```
|
||||
--prefix=<root>
|
||||
The default is /usr/local, which causes the tool suite to
|
||||
be compiled for install in /usr/local/bin,
|
||||
/usr/local/share/ivl, etc.
|
||||
|
||||
I recommend that if you are configuring for precompiled
|
||||
binaries, use --prefix=/usr. On Solaris systems, it is
|
||||
common to use --prefix=/opt. You can configure for a non-root
|
||||
install with --prefix=$HOME.
|
||||
|
||||
--enable-suffix
|
||||
--enable-suffix=<your-suffix>
|
||||
--disable-suffix
|
||||
Enable/disable changing the names of install files to use
|
||||
a suffix string so that this version or install can co-
|
||||
exist with other versions. This renames the installed
|
||||
commands (iverilog, iverilog-vpi, vvp) and the installed
|
||||
library files and include directory so that installations
|
||||
with the same prefix but different suffix are guaranteed
|
||||
to not interfere with each other.
|
||||
|
||||
--host=<host-type>
|
||||
Compile iverilog for a different platform. You can use:
|
||||
x64_64-w64-mingw32 for building 64-bit Windows executables
|
||||
i686-w64-mingw32 for building 32-bit Windows executables
|
||||
Both options require installing the required mingw-w64 packages.
|
||||
```
|
||||
|
||||
### (Optional) Testing
|
||||
|
||||
To run a simple test before installation, execute
|
||||
|
||||
```
|
||||
make check
|
||||
```
|
||||
|
||||
The commands printed by this run might help you in running Icarus
|
||||
Verilog on your own Verilog sources before the package is installed
|
||||
by root.
|
||||
|
||||
### Installation
|
||||
|
||||
Now install the files in an appropriate place. (The makefiles by
|
||||
default install in /usr/local unless you specify a different prefix
|
||||
with the `--prefix=<path>` flag to the configure command.) You may need
|
||||
to do this as root to gain access to installation directories.
|
||||
|
||||
```
|
||||
make install
|
||||
```
|
||||
|
||||
### Uninstallation
|
||||
|
||||
The generated Makefiles also include the uninstall target. This should
|
||||
remove all the files that `make install` creates.
|
||||
|
||||
## How Icarus Verilog Works
|
||||
|
||||
This tool includes a parser which reads in Verilog (plus extensions)
|
||||
and generates an internal netlist. The netlist is passed to various
|
||||
processing steps that transform the design to more optimal/practical
|
||||
forms, then is passed to a code generator for final output. The
|
||||
processing steps and the code generator are selected by command line
|
||||
switches.
|
||||
|
||||
### Preprocessing
|
||||
|
||||
There is a separate program, ivlpp, that does the preprocessing. This
|
||||
program implements the `` `include `` and `` `define `` directives producing
|
||||
output that is equivalent but without the directives. The output is a
|
||||
single file with line number directives, so that the actual compiler
|
||||
only sees a single input file. See ivlpp/ivlpp.txt for details.
|
||||
|
||||
### Parse
|
||||
|
||||
The Verilog compiler starts by parsing the Verilog source file. The
|
||||
output of the parse is a list of Module objects in "pform". The pform
|
||||
(see `pform.h`) is mostly a direct reflection of the compilation
|
||||
step. There may be dangling references, and it is not yet clear which
|
||||
module is the root.
|
||||
|
||||
One can see a human-readable version of the final pform by using the
|
||||
`-P <path>` flag to the `ivl` subcommand. This will cause ivl
|
||||
to dump the pform into the file named `<path>`. (Note that this is not
|
||||
normally done, unless debugging the `ivl` subcommand.)
|
||||
|
||||
### Elaboration
|
||||
|
||||
This phase takes the pform and generates a netlist. The driver selects
|
||||
(by user request or lucky guess) the root module to elaborate,
|
||||
resolves references and expands the instantiations to form the design
|
||||
netlist. (See netlist.txt.) Final semantic checks are performed during
|
||||
elaboration, and some simple optimizations are performed. The netlist
|
||||
includes all the behavioural descriptions, as well as gates and wires.
|
||||
|
||||
The `elaborate()` function performs the elaboration.
|
||||
|
||||
One can see a human-readable version of the final, elaborated and
|
||||
optimized netlist by using the `-N <path>` flag to the compiler. If
|
||||
elaboration succeeds, the final netlist (i.e., after optimizations but
|
||||
before code generation) will be dumped into the file named `<path>`.
|
||||
|
||||
Elaboration is performed in two steps: scopes and parameters
|
||||
first, followed by the structural and behavioural elaboration.
|
||||
|
||||
#### Scope Elaboration
|
||||
|
||||
This pass scans through the pform looking for scopes and parameters. A
|
||||
tree of NetScope objects is built up and placed in the Design object,
|
||||
with the root module represented by the root NetScope object. The
|
||||
`elab_scope.cc` file contains most of the code for handling this phase.
|
||||
|
||||
The tail of the elaborate_scope behaviour (after the pform is
|
||||
traversed) includes a scan of the NetScope tree to locate defparam
|
||||
assignments that were collected during scope elaboration. This is when
|
||||
the defparam overrides are applied to the parameters.
|
||||
|
||||
#### Netlist Elaboration
|
||||
|
||||
After the scopes and parameters are generated and the NetScope tree
|
||||
fully formed, the elaboration runs through the pform again, this time
|
||||
generating the structural and behavioural netlist. Parameters are
|
||||
elaborated and evaluated by now so all the constants of code
|
||||
generation are now known locally, so the netlist can be generated by
|
||||
simply passing through the pform.
|
||||
|
||||
### Optimization
|
||||
|
||||
This is a collection of processing steps that perform
|
||||
optimizations that do not depend on the target technology. Examples of
|
||||
some useful transformations are
|
||||
|
||||
- eliminate null effect circuitry
|
||||
- combinational reduction
|
||||
- constant propagation
|
||||
|
||||
The actual functions performed are specified on the `ivl` command line by
|
||||
the `-F` flags (see below).
|
||||
|
||||
### Code Generation
|
||||
|
||||
This step takes the design netlist and uses it to drive the code
|
||||
generator (see target.h). This may require transforming the
|
||||
design to suit the technology.
|
||||
|
||||
The `emit()` method of the Design class performs this step. It runs
|
||||
through the design elements, calling target functions as the need arises
|
||||
to generate actual output.
|
||||
|
||||
The user selects the target code generator with the `-t` flag on the
|
||||
command line.
|
||||
|
||||
### ATTRIBUTES
|
||||
|
||||
> NOTE: The $attribute syntax will soon be deprecated in favour of the Verilog-2001 attribute syntax, which is cleaner and standardized.
|
||||
|
||||
The parser accepts, as an extension to Verilog, the $attribute module
|
||||
item. The syntax of the $attribute item is:
|
||||
|
||||
```
|
||||
$attribute (<identifier>, <key>, <value>);
|
||||
```
|
||||
|
||||
The $attribute keyword looks like a system task invocation. The
|
||||
difference here is that the parameters are more restricted than those
|
||||
of a system task. The `<identifier>` must be an identifier. This will be
|
||||
the item to get an attribute. The `<key>` and `<value>` are strings, not
|
||||
expressions, that give the key and the value of the attribute to be
|
||||
attached to the identified object.
|
||||
|
||||
Attributes are `[<key> <value>]` pairs and are used to communicate with
|
||||
the various processing steps. See the documentation for the processing
|
||||
step for a list of the pertinent attributes.
|
||||
|
||||
Attributes can also be applied to gate types. When this is done, the
|
||||
attribute is given to every instantiation of the primitive. The syntax
|
||||
for the attribute statement is the same, except that the `<identifier>`
|
||||
names a primitive earlier in the compilation unit and the statement is
|
||||
placed in the global scope, instead of within a module. The semicolon is
|
||||
not part of a type attribute.
|
||||
|
||||
Note that attributes are also occasionally used for communication
|
||||
between processing steps. Processing steps that are aware of others
|
||||
may place attributes on netlist objects to communicate information to
|
||||
later steps.
|
||||
|
||||
Icarus Verilog also accepts the Verilog 2001 syntax for
|
||||
attributes. They have the same general meaning as with the $attribute
|
||||
syntax, but they are attached to objects by position instead of by
|
||||
name. Also, the key is a Verilog identifier instead of a string.
|
||||
|
||||
## Running iverilog
|
||||
|
||||
The preferred way to invoke the compiler is with the `iverilog`(1)
|
||||
command. This program invokes the preprocessor (ivlpp) and the
|
||||
compiler (`ivl`) with the proper command line options to get the job
|
||||
done in a friendly way. See the `iverilog`(1) man page for usage details.
|
||||
|
||||
|
||||
## EXAMPLES
|
||||
|
||||
Example: Compiling `"hello.vl"`
|
||||
|
||||
```
|
||||
------------------------ hello.vl ----------------------------
|
||||
module main();
|
||||
|
||||
initial
|
||||
begin
|
||||
$display("Hi there");
|
||||
$finish ;
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
--------------------------------------------------------------
|
||||
```
|
||||
|
||||
Ensure that `iverilog` is on your search path, and the vpi library
|
||||
is available.
|
||||
|
||||
To compile the program:
|
||||
|
||||
```
|
||||
iverilog hello.vl
|
||||
```
|
||||
|
||||
(The above presumes that /usr/local/include and /usr/local/lib are
|
||||
part of the compiler search path, which is usually the case for gcc.)
|
||||
|
||||
To run the program:
|
||||
|
||||
```
|
||||
./a.out
|
||||
```
|
||||
|
||||
You can use the `-o` switch to name the output command to be generated
|
||||
by the compiler. See the `iverilog`(1) man page.
|
||||
|
||||
## Unsupported Constructs
|
||||
|
||||
Icarus Verilog is in development - as such it still only supports a
|
||||
(growing) subset of Verilog. Below is a description of some of the
|
||||
currently unsupported Verilog features. This list is not exhaustive
|
||||
and does not account for errors in the compiler. See the Icarus
|
||||
Verilog web page for the current state of support for Verilog, and in
|
||||
particular, browse the bug report database for reported unsupported
|
||||
constructs.
|
||||
|
||||
- System functions are supported, but the return value is a little
|
||||
tricky. See SYSTEM FUNCTION TABLE FILES in the iverilog man page.
|
||||
|
||||
- Specify blocks are parsed but ignored in general.
|
||||
|
||||
- `trireg` is not supported. `tri0` and `tri1` are supported.
|
||||
|
||||
- tran primitives, i.e. `tran`, `tranif1`, `tranif0`, `rtran`, `rtranif1`
|
||||
and `rtranif0` are not supported.
|
||||
|
||||
- Net delays, of the form `wire #N foo;` do not work. Delays in
|
||||
every other context do work properly, including the V2001 form
|
||||
`wire #5 foo = bar;`
|
||||
|
||||
- Event controls inside non-blocking assignments are not supported.
|
||||
i.e.: `a <= @(posedge clk) b;`
|
||||
|
||||
- Macro arguments are not supported. `` `define `` macros are supported,
|
||||
but they cannot take arguments.
|
||||
|
||||
## Nonstandard Constructs or Behaviors
|
||||
|
||||
Icarus Verilog includes some features that are not part of the
|
||||
IEEE1364 standard, but have well-defined meaning, and also sometimes
|
||||
gives nonstandard (but extended) meanings to some features of the
|
||||
language that are defined. See the "extensions.txt" documentation for
|
||||
more details.
|
||||
|
||||
* `$is_signed(<expr>)`
|
||||
|
||||
This system function returns 1 if the expression contained is
|
||||
signed, or 0 otherwise. This is mostly of use for compiler
|
||||
regression tests.
|
||||
|
||||
* `$sizeof(<expr>)`, `$bits(<expr>)`
|
||||
|
||||
The `$bits` system function returns the size in bits of the
|
||||
expression that is its argument. The result of this
|
||||
function is undefined if the argument doesn't have a
|
||||
self-determined size.
|
||||
|
||||
The `$sizeof` function is deprecated in favour of `$bits`, which is
|
||||
the same thing, but included in the SystemVerilog definition.
|
||||
|
||||
* `$simtime`
|
||||
|
||||
The `$simtime` system function returns as a 64bit value the
|
||||
simulation time, unscaled by the time units of local
|
||||
scope. This is different from the $time and $stime functions
|
||||
which return the scaled times. This function is added for
|
||||
regression testing of the compiler and run time, but can be
|
||||
used by applications who really want the simulation time.
|
||||
|
||||
Note that the simulation time can be confusing if there are
|
||||
lots of different `` `timescales`` within a design. It is not in
|
||||
general possible to predict what the simulation precision will
|
||||
turn out to be.
|
||||
|
||||
* `$mti_random()`, `$mti_dist_uniform`
|
||||
|
||||
These functions are similar to the IEEE1364 standard $random
|
||||
functions, but they use the Mersenne Twister (MT19937)
|
||||
algorithm. This is considered an excellent random number
|
||||
generator, but does not generate the same sequence as the
|
||||
standardized $random.
|
||||
|
||||
### Builtin system functions
|
||||
|
||||
Certain of the system functions have well-defined meanings, so
|
||||
can theoretically be evaluated at compile-time, instead of
|
||||
using runtime VPI code. Doing so means that VPI cannot
|
||||
override the definitions of functions handled in this
|
||||
manner. On the other hand, this makes them synthesizable, and
|
||||
also allows for more aggressive constant propagation. The
|
||||
functions handled in this manner are:
|
||||
|
||||
* `$bits`
|
||||
* `$signed`
|
||||
* `$sizeof`
|
||||
* `$unsigned`
|
||||
|
||||
Implementations of these system functions in VPI modules will be ignored.
|
||||
|
||||
### Preprocessing Library Modules
|
||||
|
||||
Icarus Verilog does preprocess modules that are loaded from
|
||||
libraries via the -y mechanism. However, the only macros
|
||||
defined during the compilation of that file are those that it
|
||||
defines itself (or includes) or that are defined in the
|
||||
command line or command file.
|
||||
|
||||
Specifically, macros defined in the non-library source files
|
||||
are not remembered when the library module is loaded. This is
|
||||
intentional. If it were otherwise, then compilation results
|
||||
might vary depending on the order that libraries are loaded,
|
||||
and that is too unpredictable.
|
||||
|
||||
It is said that some commercial compilers do allow macro
|
||||
definitions to span library modules. That's just plain weird.
|
||||
|
||||
### Width in `%t` Time Formats
|
||||
|
||||
Standard Verilog does not allow width fields in the %t formats
|
||||
of display strings. For example, this is illegal:
|
||||
|
||||
```
|
||||
$display("Time is %0t", $time);
|
||||
```
|
||||
|
||||
Standard Verilog instead relies on the $timeformat to
|
||||
completely specify the format.
|
||||
|
||||
Icarus Verilog allows the programmer to specify the field
|
||||
width. The `%t` format in Icarus Verilog works exactly as it
|
||||
does in standard Verilog. However, if the programmer chooses
|
||||
to specify a minimum width (i.e., `%5t`), then for that display
|
||||
Icarus Verilog will override the `$timeformat` minimum width and
|
||||
use the explicit minimum width.
|
||||
|
||||
### vpiScope iterator on vpiScope objects.
|
||||
|
||||
In the VPI, the normal way to iterate over vpiScope objects
|
||||
contained within a vpiScope object, is the vpiInternalScope
|
||||
iterator. Icarus Verilog adds support for the vpiScope
|
||||
iterator of a vpiScope object, that iterates over *everything*
|
||||
the is contained in the current scope. This is useful in cases
|
||||
where one wants to iterate over all the objects in a scope
|
||||
without iterating over all the contained types explicitly.
|
||||
|
||||
### time 0 race resolution.
|
||||
|
||||
Combinational logic is routinely modelled using always
|
||||
blocks. However, this can lead to race conditions if the
|
||||
inputs to the combinational block are initialized in initial
|
||||
statements. Icarus Verilog slightly modifies time 0 scheduling
|
||||
by arranging for always statements with ANYEDGE sensitivity
|
||||
lists to be scheduled before any other threads. This causes
|
||||
combinational always blocks to be triggered when the values in
|
||||
the sensitivity list are initialized by initial threads.
|
||||
|
||||
### Nets with Types
|
||||
|
||||
Icarus Verilog supports an extended syntax that allows nets
|
||||
and regs to be explicitly typed. The currently supported types
|
||||
are logic, bool and real. This implies that `logic` and `bool`
|
||||
are new keywords. Typical syntax is:
|
||||
|
||||
```
|
||||
wire real foo = 1.0;
|
||||
reg logic bar, bat;
|
||||
```
|
||||
... and so forth. The syntax can be turned off by using the
|
||||
-g2 flag to iverilog, and turned on explicitly with the -g2x
|
||||
flag to iverilog.
|
||||
|
||||
|
||||
## CREDITS
|
||||
|
||||
Except where otherwise noted, Icarus Verilog, ivl and ivlpp are
|
||||
Copyright Stephen Williams. The proper notices are in the head of each
|
||||
file. However, I have early on received aid in the form of fixes,
|
||||
Verilog guidance, and especially testing from many people. Testers, in
|
||||
particular, include a larger community of people interested in a GPL
|
||||
Verilog for Linux.
|
||||
-493
@@ -1,493 +0,0 @@
|
||||
THE ICARUS VERILOG COMPILATION SYSTEM
|
||||
Copyright 2000-2019 Stephen Williams
|
||||
|
||||
|
||||
1.0 What is ICARUS Verilog?
|
||||
|
||||
Icarus Verilog is intended to compile ALL of the Verilog HDL as
|
||||
described in the IEEE-1364 standard. Of course, it's not quite there
|
||||
yet. It does currently handle a mix of structural and behavioural
|
||||
constructs. For a view of the current state of Icarus Verilog, see its
|
||||
home page at <http://iverilog.icarus.com/>.
|
||||
|
||||
Icarus Verilog is not aimed at being a simulator in the traditional
|
||||
sense, but a compiler that generates code employed by back-end
|
||||
tools.
|
||||
|
||||
For instructions on how to run Icarus Verilog,
|
||||
see the ``iverilog'' man page.
|
||||
|
||||
|
||||
2.0 Building/Installing Icarus Verilog From Source
|
||||
|
||||
If you are starting from the source, the build process is designed to be
|
||||
as simple as practical. Someone basically familiar with the target
|
||||
system and C/C++ compilation should be able to build the source
|
||||
distribution with little effort. Some actual programming skills are
|
||||
not required, but helpful in case of problems.
|
||||
|
||||
If you are building on Windows, see the mingw.txt file.
|
||||
|
||||
2.1 Compile Time Prerequisites
|
||||
|
||||
You need the following software to compile Icarus Verilog from source
|
||||
on a UNIX-like system:
|
||||
|
||||
- GNU Make
|
||||
The Makefiles use some GNU extensions, so a basic POSIX
|
||||
make will not work. Linux systems typically come with a
|
||||
satisfactory make. BSD based systems (i.e., NetBSD, FreeBSD)
|
||||
typically have GNU make as the gmake program.
|
||||
|
||||
- ISO C++ Compiler
|
||||
The ivl and ivlpp programs are written in C++ and make use
|
||||
of templates and some of the standard C++ library. egcs and
|
||||
recent gcc compilers with the associated libstdc++ are known
|
||||
to work. MSVC++ 5 and 6 are known to definitely *not* work.
|
||||
|
||||
- bison and flex
|
||||
OSX note: bison 2.3 shipped with MacOS including Catalina generates
|
||||
broken code, but bison 3+ works. We recommend using the Fink
|
||||
project version of bison and flex (finkproject.org), brew version
|
||||
works fine either.
|
||||
|
||||
- gperf 3.0 or later
|
||||
The lexical analyzer doesn't recognize keywords directly,
|
||||
but instead matches symbols and looks them up in a hash
|
||||
table in order to get the proper lexical code. The gperf
|
||||
program generates the lookup table.
|
||||
|
||||
A version problem with this program is the most common cause
|
||||
of difficulty. See the Icarus Verilog FAQ.
|
||||
|
||||
- readline 4.2 or later
|
||||
On Linux systems, this usually means the readline-devel
|
||||
rpm. In any case, it is the development headers of readline
|
||||
that are needed.
|
||||
|
||||
- termcap
|
||||
The readline library, in turn, uses termcap.
|
||||
|
||||
If you are building from git, you will also need software to generate
|
||||
the configure scripts.
|
||||
|
||||
- autoconf 2.53 or later
|
||||
This generates configure scripts from configure.in. The 2.53
|
||||
or later versions are known to work, autoconf 2.13 is
|
||||
reported to *not* work.
|
||||
|
||||
2.2 Compilation
|
||||
|
||||
Unpack the tar-ball and cd into the verilog-######### directory
|
||||
(presumably, that is how you got to this README) and compile the source
|
||||
with the commands:
|
||||
|
||||
./configure
|
||||
make
|
||||
|
||||
If you are building from git, you have to run the command below before
|
||||
compiling the source. This will generate the "configure" file, which is
|
||||
automatically done when building from tarball.
|
||||
|
||||
sh autoconf.sh
|
||||
|
||||
Normally, this command automatically figures out everything it needs
|
||||
to know. It generally works pretty well. There are a few flags to the
|
||||
configure script that modify its behaviour:
|
||||
|
||||
--prefix=<root>
|
||||
The default is /usr/local, which causes the tool suite to
|
||||
be compiled for install in /usr/local/bin,
|
||||
/usr/local/share/ivl, etc.
|
||||
|
||||
I recommend that if you are configuring for precompiled
|
||||
binaries, use --prefix=/usr. On Solaris systems, it is
|
||||
common to use --prefix=/opt. You can configure for a non-root
|
||||
install with --prefix=$HOME.
|
||||
|
||||
--enable-suffix
|
||||
--enable-suffix=<your-suffix>
|
||||
--disable-suffix
|
||||
Enable/disable changing the names of install files to use
|
||||
a suffix string so that this version or install can co-
|
||||
exist with other versions. This renames the installed
|
||||
commands (iverilog, iverilog-vpi, vvp) and the installed
|
||||
library files and include directory so that installations
|
||||
with the same prefix but different suffix are guaranteed
|
||||
to not interfere with each other.
|
||||
|
||||
--host=<host-type>
|
||||
Compile iverilog for a different platform. You can use:
|
||||
x64_64-w64-mingw32 for building 64-bit Windows executables
|
||||
i686-w64-mingw32 for building 32-bit Windows executables
|
||||
Both options require installing the required mingw-w64 packages.
|
||||
|
||||
2.3 (Optional) Testing
|
||||
|
||||
To run a simple test before installation, execute
|
||||
|
||||
make check
|
||||
|
||||
The commands printed by this run might help you in running Icarus
|
||||
Verilog on your own Verilog sources before the package is installed
|
||||
by root.
|
||||
|
||||
2.4 Installation
|
||||
|
||||
Now install the files in an appropriate place. (The makefiles by
|
||||
default install in /usr/local unless you specify a different prefix
|
||||
with the --prefix=<path> flag to the configure command.) You may need
|
||||
to do this as root to gain access to installation directories.
|
||||
|
||||
make install
|
||||
|
||||
2.5 Uninstallation
|
||||
|
||||
The generated Makefiles also include the uninstall target. This should
|
||||
remove all the files that ``make install'' creates.
|
||||
|
||||
3.0 How Icarus Verilog Works
|
||||
|
||||
This tool includes a parser which reads in Verilog (plus extensions)
|
||||
and generates an internal netlist. The netlist is passed to various
|
||||
processing steps that transform the design to more optimal/practical
|
||||
forms, then is passed to a code generator for final output. The
|
||||
processing steps and the code generator are selected by command line
|
||||
switches.
|
||||
|
||||
3.1 Preprocessing
|
||||
|
||||
There is a separate program, ivlpp, that does the preprocessing. This
|
||||
program implements the `include and `define directives producing
|
||||
output that is equivalent but without the directives. The output is a
|
||||
single file with line number directives, so that the actual compiler
|
||||
only sees a single input file. See ivlpp/ivlpp.txt for details.
|
||||
|
||||
3.2 Parse
|
||||
|
||||
The Verilog compiler starts by parsing the Verilog source file. The
|
||||
output of the parse is a list of Module objects in "pform". The pform
|
||||
(see pform.h) is mostly a direct reflection of the compilation
|
||||
step. There may be dangling references, and it is not yet clear which
|
||||
module is the root.
|
||||
|
||||
One can see a human-readable version of the final pform by using the
|
||||
``-P <path>'' flag to the ``ivl'' subcommand. This will cause ivl
|
||||
to dump the pform into the file named <path>. (Note that this is not
|
||||
normally done, unless debugging the ``ivl'' subcommand.)
|
||||
|
||||
3.3 Elaboration
|
||||
|
||||
This phase takes the pform and generates a netlist. The driver selects
|
||||
(by user request or lucky guess) the root module to elaborate,
|
||||
resolves references and expands the instantiations to form the design
|
||||
netlist. (See netlist.txt.) Final semantic checks are performed during
|
||||
elaboration, and some simple optimizations are performed. The netlist
|
||||
includes all the behavioural descriptions, as well as gates and wires.
|
||||
|
||||
The elaborate() function performs the elaboration.
|
||||
|
||||
One can see a human-readable version of the final, elaborated and
|
||||
optimized netlist by using the ``-N <path>'' flag to the compiler. If
|
||||
elaboration succeeds, the final netlist (i.e., after optimizations but
|
||||
before code generation) will be dumped into the file named <path>.
|
||||
|
||||
Elaboration is performed in two steps: scopes and parameters
|
||||
first, followed by the structural and behavioural elaboration.
|
||||
|
||||
3.3.1 Scope Elaboration
|
||||
|
||||
This pass scans through the pform looking for scopes and parameters. A
|
||||
tree of NetScope objects is built up and placed in the Design object,
|
||||
with the root module represented by the root NetScope object. The
|
||||
elab_scope.cc file contains most of the code for handling this phase.
|
||||
|
||||
The tail of the elaborate_scope behaviour (after the pform is
|
||||
traversed) includes a scan of the NetScope tree to locate defparam
|
||||
assignments that were collected during scope elaboration. This is when
|
||||
the defparam overrides are applied to the parameters.
|
||||
|
||||
3.3.2 Netlist Elaboration
|
||||
|
||||
After the scopes and parameters are generated and the NetScope tree
|
||||
fully formed, the elaboration runs through the pform again, this time
|
||||
generating the structural and behavioural netlist. Parameters are
|
||||
elaborated and evaluated by now so all the constants of code
|
||||
generation are now known locally, so the netlist can be generated by
|
||||
simply passing through the pform.
|
||||
|
||||
3.4 Optimization
|
||||
|
||||
This is a collection of processing steps that perform
|
||||
optimizations that do not depend on the target technology. Examples of
|
||||
some useful transformations are
|
||||
|
||||
- eliminate null effect circuitry
|
||||
- combinational reduction
|
||||
- constant propagation
|
||||
|
||||
The actual functions performed are specified on the ivl command line by
|
||||
the -F flags (see below).
|
||||
|
||||
3.5 Code Generation
|
||||
|
||||
This step takes the design netlist and uses it to drive the code
|
||||
generator (see target.h). This may require transforming the
|
||||
design to suit the technology.
|
||||
|
||||
The emit() method of the Design class performs this step. It runs
|
||||
through the design elements, calling target functions as the need arises
|
||||
to generate actual output.
|
||||
|
||||
The user selects the target code generator with the -t flag on the
|
||||
command line.
|
||||
|
||||
3.6 ATTRIBUTES
|
||||
|
||||
NOTE: The $attribute syntax will soon be deprecated in favour of the
|
||||
Verilog-2001 attribute syntax, which is cleaner and standardized.
|
||||
|
||||
The parser accepts, as an extension to Verilog, the $attribute module
|
||||
item. The syntax of the $attribute item is:
|
||||
|
||||
$attribute (<identifier>, <key>, <value>);
|
||||
|
||||
The $attribute keyword looks like a system task invocation. The
|
||||
difference here is that the parameters are more restricted than those
|
||||
of a system task. The <identifier> must be an identifier. This will be
|
||||
the item to get an attribute. The <key> and <value> are strings, not
|
||||
expressions, that give the key and the value of the attribute to be
|
||||
attached to the identified object.
|
||||
|
||||
Attributes are [<key> <value>] pairs and are used to communicate with
|
||||
the various processing steps. See the documentation for the processing
|
||||
step for a list of the pertinent attributes.
|
||||
|
||||
Attributes can also be applied to gate types. When this is done, the
|
||||
attribute is given to every instantiation of the primitive. The syntax
|
||||
for the attribute statement is the same, except that the <identifier>
|
||||
names a primitive earlier in the compilation unit and the statement is
|
||||
placed in the global scope, instead of within a module. The semicolon is
|
||||
not part of a type attribute.
|
||||
|
||||
Note that attributes are also occasionally used for communication
|
||||
between processing steps. Processing steps that are aware of others
|
||||
may place attributes on netlist objects to communicate information to
|
||||
later steps.
|
||||
|
||||
Icarus Verilog also accepts the Verilog 2001 syntax for
|
||||
attributes. They have the same general meaning as with the $attribute
|
||||
syntax, but they are attached to objects by position instead of by
|
||||
name. Also, the key is a Verilog identifier instead of a string.
|
||||
|
||||
4.0 Running iverilog
|
||||
|
||||
The preferred way to invoke the compiler is with the iverilog(1)
|
||||
command. This program invokes the preprocessor (ivlpp) and the
|
||||
compiler (ivl) with the proper command line options to get the job
|
||||
done in a friendly way. See the iverilog(1) man page for usage details.
|
||||
|
||||
|
||||
4.1 EXAMPLES
|
||||
|
||||
Example: Compiling "hello.vl"
|
||||
|
||||
------------------------ hello.vl ----------------------------
|
||||
module main();
|
||||
|
||||
initial
|
||||
begin
|
||||
$display("Hi there");
|
||||
$finish ;
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
--------------------------------------------------------------
|
||||
|
||||
Ensure that "iverilog" is on your search path, and the vpi library
|
||||
is available.
|
||||
|
||||
To compile the program:
|
||||
|
||||
iverilog hello.vl
|
||||
|
||||
(The above presumes that /usr/local/include and /usr/local/lib are
|
||||
part of the compiler search path, which is usually the case for gcc.)
|
||||
|
||||
To run the program:
|
||||
|
||||
./a.out
|
||||
|
||||
You can use the "-o" switch to name the output command to be generated
|
||||
by the compiler. See the iverilog(1) man page.
|
||||
|
||||
5.0 Unsupported Constructs
|
||||
|
||||
Icarus Verilog is in development - as such it still only supports a
|
||||
(growing) subset of Verilog. Below is a description of some of the
|
||||
currently unsupported Verilog features. This list is not exhaustive
|
||||
and does not account for errors in the compiler. See the Icarus
|
||||
Verilog web page for the current state of support for Verilog, and in
|
||||
particular, browse the bug report database for reported unsupported
|
||||
constructs.
|
||||
|
||||
- System functions are supported, but the return value is a little
|
||||
tricky. See SYSTEM FUNCTION TABLE FILES in the iverilog man page.
|
||||
|
||||
- Specify blocks are parsed but ignored in general.
|
||||
|
||||
- trireg is not supported. tri0 and tri1 are supported.
|
||||
|
||||
- tran primitives, i.e. tran, tranif1, tranif0, rtran, rtranif1
|
||||
and rtranif0 are not supported.
|
||||
|
||||
- Net delays, of the form "wire #N foo;" do not work. Delays in
|
||||
every other context do work properly, including the V2001 form
|
||||
"wire #5 foo = bar;"
|
||||
|
||||
- Event controls inside non-blocking assignments are not supported.
|
||||
i.e.: a <= @(posedge clk) b;
|
||||
|
||||
- Macro arguments are not supported. `define macros are supported,
|
||||
but they cannot take arguments.
|
||||
|
||||
5.1 Nonstandard Constructs or Behaviors
|
||||
|
||||
Icarus Verilog includes some features that are not part of the
|
||||
IEEE1364 standard, but have well-defined meaning, and also sometimes
|
||||
gives nonstandard (but extended) meanings to some features of the
|
||||
language that are defined. See the "extensions.txt" documentation for
|
||||
more details.
|
||||
|
||||
$is_signed(<expr>)
|
||||
This system function returns 1 if the expression contained is
|
||||
signed, or 0 otherwise. This is mostly of use for compiler
|
||||
regression tests.
|
||||
|
||||
$sizeof(<expr>)
|
||||
$bits(<expr>)
|
||||
The $bits system function returns the size in bits of the
|
||||
expression that is its argument. The result of this
|
||||
function is undefined if the argument doesn't have a
|
||||
self-determined size.
|
||||
|
||||
The $sizeof function is deprecated in favour of $bits, which is
|
||||
the same thing, but included in the SystemVerilog definition.
|
||||
|
||||
$simtime
|
||||
The $simtime system function returns as a 64bit value the
|
||||
simulation time, unscaled by the time units of local
|
||||
scope. This is different from the $time and $stime functions
|
||||
which return the scaled times. This function is added for
|
||||
regression testing of the compiler and run time, but can be
|
||||
used by applications who really want the simulation time.
|
||||
|
||||
Note that the simulation time can be confusing if there are
|
||||
lots of different `timescales within a design. It is not in
|
||||
general possible to predict what the simulation precision will
|
||||
turn out to be.
|
||||
|
||||
$mti_random()
|
||||
$mti_dist_uniform
|
||||
These functions are similar to the IEEE1364 standard $random
|
||||
functions, but they use the Mersenne Twister (MT19937)
|
||||
algorithm. This is considered an excellent random number
|
||||
generator, but does not generate the same sequence as the
|
||||
standardized $random.
|
||||
|
||||
Builtin system functions
|
||||
|
||||
Certain of the system functions have well-defined meanings, so
|
||||
can theoretically be evaluated at compile-time, instead of
|
||||
using runtime VPI code. Doing so means that VPI cannot
|
||||
override the definitions of functions handled in this
|
||||
manner. On the other hand, this makes them synthesizable, and
|
||||
also allows for more aggressive constant propagation. The
|
||||
functions handled in this manner are:
|
||||
|
||||
$bits
|
||||
$signed
|
||||
$sizeof
|
||||
$unsigned
|
||||
|
||||
Implementations of these system functions in VPI modules will
|
||||
be ignored.
|
||||
|
||||
Preprocessing Library Modules
|
||||
|
||||
Icarus Verilog does preprocess modules that are loaded from
|
||||
libraries via the -y mechanism. However, the only macros
|
||||
defined during the compilation of that file are those that it
|
||||
defines itself (or includes) or that are defined in the
|
||||
command line or command file.
|
||||
|
||||
Specifically, macros defined in the non-library source files
|
||||
are not remembered when the library module is loaded. This is
|
||||
intentional. If it were otherwise, then compilation results
|
||||
might vary depending on the order that libraries are loaded,
|
||||
and that is too unpredictable.
|
||||
|
||||
It is said that some commercial compilers do allow macro
|
||||
definitions to span library modules. That's just plain weird.
|
||||
|
||||
Width in %t Time Formats
|
||||
|
||||
Standard Verilog does not allow width fields in the %t formats
|
||||
of display strings. For example, this is illegal:
|
||||
|
||||
$display("Time is %0t", $time);
|
||||
|
||||
Standard Verilog instead relies on the $timeformat to
|
||||
completely specify the format.
|
||||
|
||||
Icarus Verilog allows the programmer to specify the field
|
||||
width. The "%t" format in Icarus Verilog works exactly as it
|
||||
does in standard Verilog. However, if the programmer chooses
|
||||
to specify a minimum width (i.e., "%5t"), then for that display
|
||||
Icarus Verilog will override the $timeformat minimum width and
|
||||
use the explicit minimum width.
|
||||
|
||||
vpiScope iterator on vpiScope objects.
|
||||
|
||||
In the VPI, the normal way to iterate over vpiScope objects
|
||||
contained within a vpiScope object, is the vpiInternalScope
|
||||
iterator. Icarus Verilog adds support for the vpiScope
|
||||
iterator of a vpiScope object, that iterates over *everything*
|
||||
the is contained in the current scope. This is useful in cases
|
||||
where one wants to iterate over all the objects in a scope
|
||||
without iterating over all the contained types explicitly.
|
||||
|
||||
time 0 race resolution.
|
||||
|
||||
Combinational logic is routinely modelled using always
|
||||
blocks. However, this can lead to race conditions if the
|
||||
inputs to the combinational block are initialized in initial
|
||||
statements. Icarus Verilog slightly modifies time 0 scheduling
|
||||
by arranging for always statements with ANYEDGE sensitivity
|
||||
lists to be scheduled before any other threads. This causes
|
||||
combinational always blocks to be triggered when the values in
|
||||
the sensitivity list are initialized by initial threads.
|
||||
|
||||
Nets with Types
|
||||
|
||||
Icarus Verilog supports an extended syntax that allows nets
|
||||
and regs to be explicitly typed. The currently supported types
|
||||
are logic, bool and real. This implies that "logic" and "bool"
|
||||
are new keywords. Typical syntax is:
|
||||
|
||||
wire real foo = 1.0;
|
||||
reg logic bar, bat;
|
||||
|
||||
... and so forth. The syntax can be turned off by using the
|
||||
-g2 flag to iverilog, and turned on explicitly with the -g2x
|
||||
flag to iverilog.
|
||||
|
||||
6.0 CREDITS
|
||||
|
||||
Except where otherwise noted, Icarus Verilog, ivl and ivlpp are
|
||||
Copyright Stephen Williams. The proper notices are in the head of each
|
||||
file. However, I have early on received aid in the form of fixes,
|
||||
Verilog guidance, and especially testing from many people. Testers, in
|
||||
particular, include a larger community of people interested in a GPL
|
||||
Verilog for Linux.
|
||||
+19
-8
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998-2019 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2021 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -23,6 +23,8 @@
|
||||
# include "PExpr.h"
|
||||
# include "ivl_assert.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
Statement::~Statement()
|
||||
{
|
||||
}
|
||||
@@ -206,7 +208,7 @@ const pform_name_t& PCallTask::path() const
|
||||
return path_;
|
||||
}
|
||||
|
||||
PCase::PCase(ivl_case_quality_t q, NetCase::TYPE t, PExpr*ex, svector<PCase::Item*>*l)
|
||||
PCase::PCase(ivl_case_quality_t q, NetCase::TYPE t, PExpr*ex, std::vector<PCase::Item*>*l)
|
||||
: quality_(q), type_(t), expr_(ex), items_(l)
|
||||
{
|
||||
}
|
||||
@@ -214,7 +216,7 @@ PCase::PCase(ivl_case_quality_t q, NetCase::TYPE t, PExpr*ex, svector<PCase::Ite
|
||||
PCase::~PCase()
|
||||
{
|
||||
delete expr_;
|
||||
for (unsigned idx = 0 ; idx < items_->count() ; idx += 1)
|
||||
for (unsigned idx = 0 ; idx < items_->size() ; idx += 1)
|
||||
if ((*items_)[idx]->stat) delete (*items_)[idx]->stat;
|
||||
|
||||
delete[]items_;
|
||||
@@ -298,10 +300,10 @@ PDoWhile::~PDoWhile()
|
||||
delete statement_;
|
||||
}
|
||||
|
||||
PEventStatement::PEventStatement(const svector<PEEvent*>&ee)
|
||||
PEventStatement::PEventStatement(const std::vector<PEEvent*>&ee)
|
||||
: expr_(ee), statement_(0), always_sens_(false)
|
||||
{
|
||||
assert(expr_.count() > 0);
|
||||
assert(expr_.size() > 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -329,7 +331,7 @@ void PEventStatement::set_statement(Statement*st)
|
||||
bool PEventStatement::has_aa_term(Design*des, NetScope*scope)
|
||||
{
|
||||
bool flag = false;
|
||||
for (unsigned idx = 0 ; idx < expr_.count() ; idx += 1) {
|
||||
for (unsigned idx = 0 ; idx < expr_.size() ; idx += 1) {
|
||||
flag = expr_[idx]->has_aa_term(des, scope) || flag;
|
||||
}
|
||||
return flag;
|
||||
@@ -416,8 +418,8 @@ PReturn::~PReturn()
|
||||
delete expr_;
|
||||
}
|
||||
|
||||
PTrigger::PTrigger(PPackage*pkg, const pform_name_t&e)
|
||||
: package_(pkg), event_(e)
|
||||
PTrigger::PTrigger(PPackage*pkg, const pform_name_t&ev)
|
||||
: package_(pkg), event_(ev)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -425,6 +427,15 @@ PTrigger::~PTrigger()
|
||||
{
|
||||
}
|
||||
|
||||
PNBTrigger::PNBTrigger(const pform_name_t&ev, PExpr*dly)
|
||||
: event_(ev), dly_(dly)
|
||||
{
|
||||
}
|
||||
|
||||
PNBTrigger::~PNBTrigger()
|
||||
{
|
||||
}
|
||||
|
||||
PWhile::PWhile(PExpr*ex, Statement*st)
|
||||
: cond_(ex), statement_(st)
|
||||
{
|
||||
|
||||
+62
-39
@@ -1,7 +1,7 @@
|
||||
#ifndef IVL_Statement_H
|
||||
#define IVL_Statement_H
|
||||
/*
|
||||
* Copyright (c) 1998-2020 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2021 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -23,7 +23,6 @@
|
||||
# include <vector>
|
||||
# include <list>
|
||||
# include "ivl_target.h"
|
||||
# include "svector.h"
|
||||
# include "StringHeap.h"
|
||||
# include "PDelays.h"
|
||||
# include "PExpr.h"
|
||||
@@ -61,9 +60,9 @@ class PProcess : public LineInfo {
|
||||
ivl_process_type_t type() const { return type_; }
|
||||
Statement*statement() { return statement_; }
|
||||
|
||||
map<perm_string,PExpr*> attributes;
|
||||
std::map<perm_string,PExpr*> attributes;
|
||||
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual void dump(std::ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
ivl_process_type_t type_;
|
||||
@@ -81,12 +80,12 @@ class Statement : virtual public LineInfo {
|
||||
Statement() { }
|
||||
virtual ~Statement() =0;
|
||||
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual void dump(std::ostream&out, unsigned ind) const;
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_sig(Design*des, NetScope*scope) const;
|
||||
|
||||
map<perm_string,PExpr*> attributes;
|
||||
std::map<perm_string,PExpr*> attributes;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -139,7 +138,7 @@ class PAssign : public PAssign_ {
|
||||
explicit PAssign(PExpr*lval, PExpr*ex, bool is_constant);
|
||||
~PAssign();
|
||||
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual void dump(std::ostream&out, unsigned ind) const;
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
|
||||
private:
|
||||
@@ -155,7 +154,7 @@ class PAssignNB : public PAssign_ {
|
||||
explicit PAssignNB(PExpr*lval, PExpr*cnt, PEventStatement*de, PExpr*ex);
|
||||
~PAssignNB();
|
||||
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual void dump(std::ostream&out, unsigned ind) const;
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
|
||||
private:
|
||||
@@ -200,7 +199,7 @@ class PBlock : public PScope, public Statement, public PNamedItem {
|
||||
// block.
|
||||
void push_statement_front(Statement*that);
|
||||
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual void dump(std::ostream&out, unsigned ind) const;
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_sig(Design*des, NetScope*scope) const;
|
||||
@@ -215,16 +214,20 @@ class PBlock : public PScope, public Statement, public PNamedItem {
|
||||
class PCallTask : public Statement {
|
||||
|
||||
public:
|
||||
explicit PCallTask(PPackage*pkg, const pform_name_t&n, const list<PExpr*>&parms);
|
||||
explicit PCallTask(const pform_name_t&n, const list<PExpr*>&parms);
|
||||
explicit PCallTask(perm_string n, const list<PExpr*>&parms);
|
||||
explicit PCallTask(PPackage*pkg, const pform_name_t&n, const std::list<PExpr*>&parms);
|
||||
explicit PCallTask(const pform_name_t&n, const std::list<PExpr*>&parms);
|
||||
explicit PCallTask(perm_string n, const std::list<PExpr*>&parms);
|
||||
~PCallTask();
|
||||
|
||||
const pform_name_t& path() const;
|
||||
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual void dump(std::ostream&out, unsigned ind) const;
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
|
||||
bool elaborate_elab(Design*des, NetScope*scope) const;
|
||||
|
||||
void void_cast() { void_cast_ = true; }
|
||||
|
||||
private:
|
||||
NetProc* elaborate_sys(Design*des, NetScope*scope) const;
|
||||
NetProc* elaborate_usr(Design*des, NetScope*scope) const;
|
||||
@@ -234,6 +237,7 @@ class PCallTask : public Statement {
|
||||
NetProc*elaborate_function_(Design*des, NetScope*scope) const;
|
||||
NetProc*elaborate_void_function_(Design*des, NetScope*scope,
|
||||
NetFuncDef*def) const;
|
||||
NetProc *elaborate_non_void_function_(Design *des, NetScope *scope) const;
|
||||
|
||||
NetProc*elaborate_build_call_(Design*des, NetScope*scope,
|
||||
NetScope*task, NetExpr*use_this) const;
|
||||
@@ -245,35 +249,41 @@ class PCallTask : public Statement {
|
||||
NetNet*net,
|
||||
perm_string method_name,
|
||||
const char*sys_task_name) const;
|
||||
NetProc*elaborate_method_func_(NetScope*scope,
|
||||
NetNet*net,
|
||||
ivl_type_t type,
|
||||
perm_string method_name,
|
||||
const char*sys_task_name) const;
|
||||
bool test_task_calls_ok_(Design*des, NetScope*scope) const;
|
||||
|
||||
PPackage*package_;
|
||||
pform_name_t path_;
|
||||
vector<PExpr*> parms_;
|
||||
std::vector<PExpr*> parms_;
|
||||
bool void_cast_ = false;
|
||||
};
|
||||
|
||||
class PCase : public Statement {
|
||||
|
||||
public:
|
||||
struct Item {
|
||||
list<PExpr*>expr;
|
||||
std::list<PExpr*>expr;
|
||||
Statement*stat;
|
||||
};
|
||||
|
||||
PCase(ivl_case_quality_t, NetCase::TYPE, PExpr*ex, svector<Item*>*);
|
||||
PCase(ivl_case_quality_t, NetCase::TYPE, PExpr*ex, std::vector<Item*>*);
|
||||
~PCase();
|
||||
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_sig(Design*des, NetScope*scope) const;
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual void dump(std::ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
ivl_case_quality_t quality_;
|
||||
NetCase::TYPE type_;
|
||||
PExpr*expr_;
|
||||
|
||||
svector<Item*>*items_;
|
||||
std::vector<Item*>*items_;
|
||||
|
||||
private: // not implemented
|
||||
PCase(const PCase&);
|
||||
@@ -287,7 +297,7 @@ class PCAssign : public Statement {
|
||||
~PCAssign();
|
||||
|
||||
virtual NetCAssign* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual void dump(std::ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
PExpr*lval_;
|
||||
@@ -301,11 +311,11 @@ class PCAssign : public Statement {
|
||||
*/
|
||||
class PChainConstructor : public Statement {
|
||||
public:
|
||||
explicit PChainConstructor(const list<PExpr*>&parms);
|
||||
explicit PChainConstructor(const std::list<PExpr*>&parms);
|
||||
~PChainConstructor();
|
||||
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual void dump(std::ostream&out, unsigned ind) const;
|
||||
|
||||
inline const std::vector<PExpr*>& chain_args(void) const
|
||||
{ return parms_; }
|
||||
@@ -323,7 +333,7 @@ class PCondit : public Statement {
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_sig(Design*des, NetScope*scope) const;
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual void dump(std::ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
PExpr*expr_;
|
||||
@@ -342,7 +352,7 @@ class PDeassign : public Statement {
|
||||
~PDeassign();
|
||||
|
||||
virtual NetDeassign* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual void dump(std::ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
PExpr*lval_;
|
||||
@@ -354,7 +364,7 @@ class PDelayStatement : public Statement {
|
||||
PDelayStatement(PExpr*d, Statement*st);
|
||||
~PDelayStatement();
|
||||
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual void dump(std::ostream&out, unsigned ind) const;
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_sig(Design*des, NetScope*scope) const;
|
||||
@@ -374,7 +384,7 @@ class PDisable : public Statement {
|
||||
explicit PDisable(const pform_name_t&sc);
|
||||
~PDisable();
|
||||
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual void dump(std::ostream&out, unsigned ind) const;
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
|
||||
private:
|
||||
@@ -390,7 +400,7 @@ class PDoWhile : public Statement {
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_sig(Design*des, NetScope*scope) const;
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual void dump(std::ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
PExpr*cond_;
|
||||
@@ -409,7 +419,7 @@ class PEventStatement : public Statement {
|
||||
|
||||
public:
|
||||
|
||||
explicit PEventStatement(const svector<PEEvent*>&ee);
|
||||
explicit PEventStatement(const std::vector<PEEvent*>&ee);
|
||||
explicit PEventStatement(PEEvent*ee);
|
||||
// Make an @* statement or make a special @* version with the items
|
||||
// from functions added and outputs removed for always_comb/latch.
|
||||
@@ -419,10 +429,10 @@ class PEventStatement : public Statement {
|
||||
|
||||
void set_statement(Statement*st);
|
||||
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual void dump(std::ostream&out, unsigned ind) const;
|
||||
// Call this with a NULL statement only. It is used to print
|
||||
// the event expression for inter-assignment event controls.
|
||||
virtual void dump_inline(ostream&out) const;
|
||||
virtual void dump_inline(std::ostream&out) const;
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_sig(Design*des, NetScope*scope) const;
|
||||
@@ -437,12 +447,12 @@ class PEventStatement : public Statement {
|
||||
NetProc* elaborate_wait_fork(Design*des, NetScope*scope) const;
|
||||
|
||||
private:
|
||||
svector<PEEvent*>expr_;
|
||||
std::vector<PEEvent*>expr_;
|
||||
Statement*statement_;
|
||||
bool always_sens_;
|
||||
};
|
||||
|
||||
ostream& operator << (ostream&o, const PEventStatement&obj);
|
||||
std::ostream& operator << (std::ostream&o, const PEventStatement&obj);
|
||||
|
||||
class PForce : public Statement {
|
||||
|
||||
@@ -451,7 +461,7 @@ class PForce : public Statement {
|
||||
~PForce();
|
||||
|
||||
virtual NetForce* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual void dump(std::ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
PExpr*lval_;
|
||||
@@ -466,7 +476,7 @@ class PForeach : public Statement {
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_sig(Design*des, NetScope*scope) const;
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual void dump(std::ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
NetProc* elaborate_static_array_(Design*des, NetScope*scope,
|
||||
@@ -486,7 +496,7 @@ class PForever : public Statement {
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_sig(Design*des, NetScope*scope) const;
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual void dump(std::ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
Statement*statement_;
|
||||
@@ -502,7 +512,7 @@ class PForStatement : public Statement {
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_sig(Design*des, NetScope*scope) const;
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual void dump(std::ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
PExpr* name1_;
|
||||
@@ -530,7 +540,7 @@ class PRepeat : public Statement {
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_sig(Design*des, NetScope*scope) const;
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual void dump(std::ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
PExpr*expr_;
|
||||
@@ -544,7 +554,7 @@ class PRelease : public Statement {
|
||||
~PRelease();
|
||||
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual void dump(std::ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
PExpr*lval_;
|
||||
@@ -574,13 +584,26 @@ class PTrigger : public Statement {
|
||||
~PTrigger();
|
||||
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual void dump(std::ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
PPackage*package_;
|
||||
pform_name_t event_;
|
||||
};
|
||||
|
||||
class PNBTrigger : public Statement {
|
||||
public:
|
||||
explicit PNBTrigger(const pform_name_t&ev, PExpr*dly);
|
||||
~PNBTrigger();
|
||||
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void dump(std::ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
pform_name_t event_;
|
||||
PExpr*dly_;
|
||||
};
|
||||
|
||||
class PWhile : public Statement {
|
||||
|
||||
public:
|
||||
@@ -590,7 +613,7 @@ class PWhile : public Statement {
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_sig(Design*des, NetScope*scope) const;
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual void dump(std::ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
PExpr*cond_;
|
||||
|
||||
Vendored
+35
-22
@@ -6,7 +6,7 @@
|
||||
# different builds. Remember to change the default suffix string to some
|
||||
# value appropriate for the current version.
|
||||
AC_DEFUN([AX_ENABLE_SUFFIX],
|
||||
[AC_ARG_ENABLE([suffix],[AC_HELP_STRING([--enable-suffix],
|
||||
[AC_ARG_ENABLE([suffix],[AS_HELP_STRING([--enable-suffix],
|
||||
[Use/set the installation command suffix])],
|
||||
[true],[enable_suffix=no])
|
||||
if test X$enable_suffix = Xyes; then
|
||||
@@ -250,7 +250,7 @@ echo "timestamp for $_config_header" > `AS_DIRNAME(["$_config_header"])`/[]$_sta
|
||||
]) #_AC_AM_CONFIG_HEADER_HOOK
|
||||
|
||||
# ===========================================================================
|
||||
# http://www.gnu.org/software/autoconf-archive/ax_prog_cc_for_build.html
|
||||
# https://www.gnu.org/software/autoconf-archive/ax_prog_cc_for_build.html
|
||||
# ===========================================================================
|
||||
#
|
||||
# SYNOPSIS
|
||||
@@ -283,31 +283,35 @@ echo "timestamp for $_config_header" > `AS_DIRNAME(["$_config_header"])`/[]$_sta
|
||||
# and this notice are preserved. This file is offered as-is, without any
|
||||
# warranty.
|
||||
|
||||
#serial 8
|
||||
#serial 18
|
||||
|
||||
AU_ALIAS([AC_PROG_CC_FOR_BUILD], [AX_PROG_CC_FOR_BUILD])
|
||||
AC_DEFUN([AX_PROG_CC_FOR_BUILD], [dnl
|
||||
AC_REQUIRE([AC_PROG_CC])dnl
|
||||
AC_REQUIRE([AC_PROG_CPP])dnl
|
||||
AC_REQUIRE([AC_EXEEXT])dnl
|
||||
AC_REQUIRE([AC_CANONICAL_HOST])dnl
|
||||
AC_REQUIRE([AC_CANONICAL_BUILD])dnl
|
||||
|
||||
dnl Use the standard macros, but make them use other variable names
|
||||
dnl
|
||||
pushdef([ac_cv_prog_CPP], ac_cv_build_prog_CPP)dnl
|
||||
pushdef([ac_cv_prog_cc_c89], ac_cv_build_prog_cc_c89)dnl
|
||||
pushdef([ac_cv_prog_gcc], ac_cv_build_prog_gcc)dnl
|
||||
pushdef([ac_cv_prog_cc_works], ac_cv_build_prog_cc_works)dnl
|
||||
pushdef([ac_cv_prog_cc_cross], ac_cv_build_prog_cc_cross)dnl
|
||||
pushdef([ac_cv_prog_cc_g], ac_cv_build_prog_cc_g)dnl
|
||||
pushdef([ac_cv_c_compiler_gnu], ac_cv_build_c_compiler_gnu)dnl
|
||||
pushdef([ac_cv_exeext], ac_cv_build_exeext)dnl
|
||||
pushdef([ac_cv_objext], ac_cv_build_objext)dnl
|
||||
pushdef([ac_exeext], ac_build_exeext)dnl
|
||||
pushdef([ac_objext], ac_build_objext)dnl
|
||||
pushdef([CC], CC_FOR_BUILD)dnl
|
||||
pushdef([CPP], CPP_FOR_BUILD)dnl
|
||||
pushdef([GCC], GCC_FOR_BUILD)dnl
|
||||
pushdef([CFLAGS], CFLAGS_FOR_BUILD)dnl
|
||||
pushdef([CPPFLAGS], CPPFLAGS_FOR_BUILD)dnl
|
||||
pushdef([EXEEXT], BUILD_EXEEXT)dnl
|
||||
pushdef([LDFLAGS], LDFLAGS_FOR_BUILD)dnl
|
||||
pushdef([OBJEXT], BUILD_OBJEXT)dnl
|
||||
pushdef([host], build)dnl
|
||||
pushdef([host_alias], build_alias)dnl
|
||||
pushdef([host_cpu], build_cpu)dnl
|
||||
@@ -318,27 +322,29 @@ pushdef([ac_cv_host_alias], ac_cv_build_alias)dnl
|
||||
pushdef([ac_cv_host_cpu], ac_cv_build_cpu)dnl
|
||||
pushdef([ac_cv_host_vendor], ac_cv_build_vendor)dnl
|
||||
pushdef([ac_cv_host_os], ac_cv_build_os)dnl
|
||||
pushdef([ac_cpp], ac_build_cpp)dnl
|
||||
pushdef([ac_compile], ac_build_compile)dnl
|
||||
pushdef([ac_link], ac_build_link)dnl
|
||||
pushdef([ac_tool_prefix], ac_build_tool_prefix)dnl
|
||||
pushdef([am_cv_CC_dependencies_compiler_type], am_cv_build_CC_dependencies_compiler_type)dnl
|
||||
pushdef([am_cv_prog_cc_c_o], am_cv_build_prog_cc_c_o)dnl
|
||||
pushdef([cross_compiling], cross_compiling_build)dnl
|
||||
|
||||
save_cross_compiling=$cross_compiling
|
||||
save_ac_tool_prefix=$ac_tool_prefix
|
||||
cross_compiling=no
|
||||
ac_tool_prefix=
|
||||
cross_compiling_build=no
|
||||
|
||||
ac_build_tool_prefix=
|
||||
AS_IF([test -n "$build"], [ac_build_tool_prefix="$build-"],
|
||||
[test -n "$build_alias"],[ac_build_tool_prefix="$build_alias-"])
|
||||
|
||||
AC_LANG_PUSH([C])
|
||||
AC_PROG_CC
|
||||
_AC_COMPILER_EXEEXT
|
||||
_AC_COMPILER_OBJEXT
|
||||
AC_PROG_CPP
|
||||
AC_EXEEXT
|
||||
|
||||
ac_tool_prefix=$save_ac_tool_prefix
|
||||
cross_compiling=$save_cross_compiling
|
||||
|
||||
dnl Restore the old definitions
|
||||
dnl
|
||||
popdef([ac_link])dnl
|
||||
popdef([ac_compile])dnl
|
||||
popdef([ac_cpp])dnl
|
||||
popdef([cross_compiling])dnl
|
||||
popdef([am_cv_prog_cc_c_o])dnl
|
||||
popdef([am_cv_CC_dependencies_compiler_type])dnl
|
||||
popdef([ac_tool_prefix])dnl
|
||||
popdef([ac_cv_host_os])dnl
|
||||
popdef([ac_cv_host_vendor])dnl
|
||||
popdef([ac_cv_host_cpu])dnl
|
||||
@@ -349,29 +355,36 @@ popdef([host_vendor])dnl
|
||||
popdef([host_cpu])dnl
|
||||
popdef([host_alias])dnl
|
||||
popdef([host])dnl
|
||||
popdef([OBJEXT])dnl
|
||||
popdef([LDFLAGS])dnl
|
||||
popdef([EXEEXT])dnl
|
||||
popdef([CPPFLAGS])dnl
|
||||
popdef([CFLAGS])dnl
|
||||
popdef([GCC])dnl
|
||||
popdef([CPP])dnl
|
||||
popdef([CC])dnl
|
||||
popdef([ac_objext])dnl
|
||||
popdef([ac_exeext])dnl
|
||||
popdef([ac_cv_objext])dnl
|
||||
popdef([ac_cv_exeext])dnl
|
||||
popdef([ac_cv_c_compiler_gnu])dnl
|
||||
popdef([ac_cv_prog_cc_g])dnl
|
||||
popdef([ac_cv_prog_cc_cross])dnl
|
||||
popdef([ac_cv_prog_cc_works])dnl
|
||||
popdef([ac_cv_prog_cc_c89])dnl
|
||||
popdef([ac_cv_prog_gcc])dnl
|
||||
popdef([ac_cv_prog_CPP])dnl
|
||||
|
||||
dnl restore global variables ac_ext, ac_cpp, ac_compile,
|
||||
dnl ac_link, ac_compiler_gnu (dependant on the current
|
||||
dnl language after popping):
|
||||
AC_LANG_POP([C])
|
||||
|
||||
dnl Finally, set Makefile variables
|
||||
dnl
|
||||
BUILD_EXEEXT=$ac_build_exeext
|
||||
BUILD_OBJEXT=$ac_build_objext
|
||||
AC_SUBST(BUILD_EXEEXT)dnl
|
||||
AC_SUBST(BUILD_OBJEXT)dnl
|
||||
AC_SUBST([CFLAGS_FOR_BUILD])dnl
|
||||
AC_SUBST([CPPFLAGS_FOR_BUILD])dnl
|
||||
AC_SUBST([LDFLAGS_FOR_BUILD])dnl
|
||||
])
|
||||
|
||||
|
||||
+1
-1
@@ -59,7 +59,7 @@ distclean: clean
|
||||
rm -f Makefile config.log
|
||||
|
||||
cppcheck: $(O:.o=.c)
|
||||
cppcheck --enable=all --std=posix --std=c99 --std=c++03 -f $(INCLUDE_PATH) $^
|
||||
cppcheck --enable=all --std=c99 --std=c++03 -f $(INCLUDE_PATH) $^
|
||||
|
||||
Makefile: $(srcdir)/Makefile.in ../config.status
|
||||
cd ..; ./config.status --file=cadpli/$@
|
||||
|
||||
+6
-4
@@ -1,7 +1,7 @@
|
||||
#ifndef IVL_compiler_H
|
||||
#define IVL_compiler_H
|
||||
/*
|
||||
* Copyright (c) 1999-2019 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1999-2021 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -147,7 +147,7 @@ extern unsigned long array_size_limit;
|
||||
extern const char*basedir;
|
||||
|
||||
/* This is an ordered list of library suffixes to search. */
|
||||
extern list<const char*>library_suff;
|
||||
extern std::list<const char*>library_suff;
|
||||
extern int build_library_index(const char*path, bool key_case_sensitive);
|
||||
|
||||
/* This is the generation of Verilog that the compiler is asked to
|
||||
@@ -244,14 +244,14 @@ extern int lexor_keyword_mask;
|
||||
/* This is the string to use to invoke the preprocessor. */
|
||||
extern char*ivlpp_string;
|
||||
|
||||
extern map<perm_string,unsigned> missing_modules;
|
||||
extern std::map<perm_string,unsigned> missing_modules;
|
||||
|
||||
/* Files that are library files are in this map. The lexor compares
|
||||
file names as it processes `line directives, and if the file name
|
||||
matches an entry in this table, it will turn on the
|
||||
library_active_flag so that modules know that they are in a
|
||||
library. */
|
||||
extern map<perm_string,bool> library_file_map;
|
||||
extern std::map<perm_string,bool> library_file_map;
|
||||
|
||||
/*
|
||||
* the lex_strings are perm_strings made up of tokens from the source
|
||||
@@ -308,4 +308,6 @@ extern bool load_vpi_module(const char*path);
|
||||
*/
|
||||
extern ivl_sfunc_as_task_t def_sfunc_as_task;
|
||||
|
||||
extern void pre_process_failed(const char*text);
|
||||
|
||||
#endif /* IVL_compiler_H */
|
||||
|
||||
+1
-9
@@ -1,7 +1,7 @@
|
||||
#ifndef IVL_config_H /* -*- c++ -*- */
|
||||
#define IVL_config_H
|
||||
/*
|
||||
* Copyright (c) 2001-2015 Stephen Williams ([email protected])
|
||||
* Copyright (c) 2001-2021 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -19,14 +19,6 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#if defined(__cplusplus)
|
||||
# if !defined(__GNUC__)
|
||||
using namespace std;
|
||||
# elif (__GNUC__ == 3)
|
||||
using namespace std;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
# undef NEED_LU
|
||||
# undef NEED_TU
|
||||
# undef WLU
|
||||
|
||||
+26
-27
@@ -1,21 +1,22 @@
|
||||
dnl Process this file with autoconf to produce a configure script.
|
||||
AC_INIT(netlist.h)
|
||||
AC_CONFIG_HEADER(config.h)
|
||||
AC_CONFIG_HEADER(_pli_types.h)
|
||||
AC_CONFIG_HEADER(vhdlpp/vhdlpp_config.h)
|
||||
AC_CONFIG_HEADER(vvp/config.h)
|
||||
AC_CONFIG_HEADER(vpi/vpi_config.h)
|
||||
AC_CONFIG_HEADER(libveriuser/config.h)
|
||||
AC_CONFIG_HEADER(tgt-vvp/vvp_config.h)
|
||||
AC_CONFIG_HEADER(tgt-vhdl/vhdl_config.h)
|
||||
AC_CONFIG_HEADER(tgt-pcb/pcb_config.h)
|
||||
AC_INIT
|
||||
AC_CONFIG_SRCDIR([netlist.h])
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
AC_CONFIG_HEADERS([_pli_types.h])
|
||||
AC_CONFIG_HEADERS([vhdlpp/vhdlpp_config.h])
|
||||
AC_CONFIG_HEADERS([vvp/config.h])
|
||||
AC_CONFIG_HEADERS([vpi/vpi_config.h])
|
||||
AC_CONFIG_HEADERS([libveriuser/config.h])
|
||||
AC_CONFIG_HEADERS([tgt-vvp/vvp_config.h])
|
||||
AC_CONFIG_HEADERS([tgt-vhdl/vhdl_config.h])
|
||||
AC_CONFIG_HEADERS([tgt-pcb/pcb_config.h])
|
||||
|
||||
AC_CANONICAL_HOST
|
||||
dnl Checks for programs.
|
||||
AC_PROG_CC
|
||||
# AC_PROG_CC_C99 is only available in autoconf version 2.60 and later.
|
||||
AC_PREREQ([2.60])
|
||||
AC_PROG_CC_C99
|
||||
AX_PROG_CC_FOR_BUILD
|
||||
AC_PREREQ([2.62])
|
||||
m4_version_prereq([2.70], [], [AC_PROG_CC_C99])
|
||||
AC_PROG_CXX
|
||||
AC_PROG_RANLIB
|
||||
AC_CHECK_TOOL(LD, ld, false)
|
||||
@@ -92,7 +93,7 @@ fi
|
||||
|
||||
AC_LANG(C++)
|
||||
|
||||
AC_ARG_WITH([m32], [AC_HELP_STRING([--with-m32], [Compile 32-bit on x86_64])],
|
||||
AC_ARG_WITH([m32], [AS_HELP_STRING([--with-m32],[Compile 32-bit on x86_64])],
|
||||
[ with_m32=yes ],[ with_m32=no ])
|
||||
|
||||
AS_IF( [test "x$with_m32" = xyes],
|
||||
@@ -103,7 +104,7 @@ AS_IF( [test "x$with_m32" = xyes],
|
||||
[])
|
||||
|
||||
CFLAGS="$CTARGETFLAGS $CFLAGS"
|
||||
CXXFLAGS="$CTARGETFLAGS $CXXFLAGS"
|
||||
CXXFLAGS="$CTARGETFLAGS $CXXFLAGS -std=c++11"
|
||||
LDFLAGS="$CTARGETFLAGS $LDFLAGS"
|
||||
|
||||
# Check that we are using either the GNU compilers or the Sun compilers
|
||||
@@ -135,6 +136,7 @@ CXXFLAGS="$iverilog_temp_cxxflags"
|
||||
AC_CHECK_SIZEOF(unsigned long long)
|
||||
AC_CHECK_SIZEOF(unsigned long)
|
||||
AC_CHECK_SIZEOF(unsigned)
|
||||
AC_CHECK_SIZEOF(void *)
|
||||
|
||||
# vvp uses these...
|
||||
AC_CHECK_LIB(termcap, tputs)
|
||||
@@ -169,8 +171,7 @@ AC_FUNC_ALLOCA
|
||||
AC_FUNC_FSEEKO
|
||||
|
||||
# valgrind checks
|
||||
AC_ARG_WITH([valgrind], [AC_HELP_STRING([--with-valgrind],
|
||||
[Add valgrind hooks])],
|
||||
AC_ARG_WITH([valgrind], [AS_HELP_STRING([--with-valgrind],[Add valgrind hooks])],
|
||||
[], [check_valgrind=yes])
|
||||
|
||||
AS_IF([test "x$check_valgrind" = xyes],
|
||||
@@ -181,14 +182,11 @@ AS_IF([test "x$check_valgrind" = xyes],
|
||||
[AC_MSG_ERROR([Could not find <valgrind/memcheck.h>])])])
|
||||
|
||||
AC_MSG_CHECKING(for sys/times)
|
||||
AC_TRY_LINK(
|
||||
#include <unistd.h>
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <unistd.h>
|
||||
#include <sys/times.h>
|
||||
,{clock_t a = times(0)/sysconf(_SC_CLK_TCK);},
|
||||
do_times=yes
|
||||
AC_DEFINE([HAVE_TIMES], [1], [The times system call is available in the host operating system.]),
|
||||
do_times=no
|
||||
)
|
||||
]], [[{clock_t a = times(0)/sysconf(_SC_CLK_TCK);}]])],[do_times=yes
|
||||
AC_DEFINE(HAVE_TIMES, 1, The times system call is available in the host operating system.)],[do_times=no
|
||||
])
|
||||
AC_MSG_RESULT($do_times)
|
||||
|
||||
# --
|
||||
@@ -261,7 +259,8 @@ AC_CHECK_FUNCS(fopen64)
|
||||
# The following math functions may be defined in the math library so look
|
||||
# in the default libraries first and then look in -lm for them. On some
|
||||
# systems we may need to use the compiler in C99 mode to get a definition.
|
||||
# We requested C99 mode earlier with AC_PROG_CC_C99.
|
||||
# autoconf >= 2.70 will enable C99 if it is available. For older autoconf
|
||||
# versions, we requested C99 mode earlier with AC_PROG_CC_C99.
|
||||
AC_SEARCH_LIBS([lround], [m], [AC_DEFINE([HAVE_LROUND], [1])])
|
||||
AC_SEARCH_LIBS([llround], [m], [AC_DEFINE([HAVE_LLROUND], [1])])
|
||||
AC_SEARCH_LIBS([nan], [m], [AC_DEFINE([HAVE_NAN], [1])])
|
||||
@@ -335,5 +334,5 @@ then
|
||||
AC_MSG_ERROR(cannot configure white space in libdir: $libdir)
|
||||
fi
|
||||
AC_MSG_RESULT(ok)
|
||||
AX_PROG_CC_FOR_BUILD
|
||||
AC_OUTPUT(Makefile ivlpp/Makefile vhdlpp/Makefile vvp/Makefile vpi/Makefile driver/Makefile driver-vpi/Makefile cadpli/Makefile libveriuser/Makefile tgt-null/Makefile tgt-stub/Makefile tgt-vvp/Makefile tgt-vhdl/Makefile tgt-fpga/Makefile tgt-verilog/Makefile tgt-pal/Makefile tgt-vlog95/Makefile tgt-pcb/Makefile tgt-blif/Makefile tgt-sizer/Makefile)
|
||||
AC_CONFIG_FILES([Makefile ivlpp/Makefile vhdlpp/Makefile vvp/Makefile vpi/Makefile driver/Makefile driver-vpi/Makefile cadpli/Makefile libveriuser/Makefile tgt-null/Makefile tgt-stub/Makefile tgt-vvp/Makefile tgt-vhdl/Makefile tgt-fpga/Makefile tgt-verilog/Makefile tgt-pal/Makefile tgt-vlog95/Makefile tgt-pcb/Makefile tgt-blif/Makefile tgt-sizer/Makefile])
|
||||
AC_OUTPUT
|
||||
+347
-328
@@ -1,6 +1,20 @@
|
||||
// These are correct and are used to find the base (zero) pin.
|
||||
thisSubtraction:netlist.h:5126
|
||||
thisSubtraction:netlist.h:5135
|
||||
thisSubtraction:netlist.h:5213
|
||||
thisSubtraction:netlist.h:5222
|
||||
|
||||
// This is used when running a debugger
|
||||
// debugger_release
|
||||
knownConditionTrueFalse:main.cc:919
|
||||
|
||||
// This are just stubs
|
||||
// vpi_control()
|
||||
unusedFunction:vpi_modules.cc:107
|
||||
// vpi_mcd_printf()
|
||||
unusedFunction:vpi_modules.cc:84
|
||||
// vpi_printf()
|
||||
unusedFunction:vpi_modules.cc:88
|
||||
// vpi_sim_control()
|
||||
unusedFunction:vpi_modules.cc:108
|
||||
|
||||
// These are the functions that the compiler exports to the targets.
|
||||
//ivl_branch_island()
|
||||
@@ -9,36 +23,36 @@ unusedFunction:t-dll-api.cc:39
|
||||
unusedFunction:t-dll-api.cc:45
|
||||
|
||||
//ivl_const_bits()
|
||||
unusedFunction:t-dll-api.cc:196
|
||||
unusedFunction:t-dll-api.cc:189
|
||||
//ivl_const_delay()
|
||||
unusedFunction:t-dll-api.cc:214
|
||||
unusedFunction:t-dll-api.cc:207
|
||||
//ivl_const_file()
|
||||
unusedFunction:t-dll-api.cc:221
|
||||
unusedFunction:t-dll-api.cc:214
|
||||
//ivl_const_lineno()
|
||||
unusedFunction:t-dll-api.cc:227
|
||||
unusedFunction:t-dll-api.cc:220
|
||||
//ivl_const_nex()
|
||||
unusedFunction:t-dll-api.cc:233
|
||||
unusedFunction:t-dll-api.cc:226
|
||||
//ivl_const_real()
|
||||
unusedFunction:t-dll-api.cc:239
|
||||
unusedFunction:t-dll-api.cc:232
|
||||
//ivl_const_scope()
|
||||
unusedFunction:t-dll-api.cc:246
|
||||
unusedFunction:t-dll-api.cc:239
|
||||
//ivl_const_signed()
|
||||
unusedFunction:t-dll-api.cc:252
|
||||
unusedFunction:t-dll-api.cc:245
|
||||
//ivl_const_type()
|
||||
unusedFunction:t-dll-api.cc:190
|
||||
unusedFunction:t-dll-api.cc:183
|
||||
//ivl_const_width()
|
||||
unusedFunction:t-dll-api.cc:258
|
||||
unusedFunction:t-dll-api.cc:251
|
||||
|
||||
//ivl_design_const()
|
||||
unusedFunction:t-dll-api.cc:127
|
||||
unusedFunction:t-dll-api.cc:120
|
||||
//ivl_design_consts()
|
||||
unusedFunction:t-dll-api.cc:121
|
||||
unusedFunction:t-dll-api.cc:114
|
||||
//ivl_design_delay_sel()
|
||||
unusedFunction:t-dll-api.cc:52
|
||||
//ivl_design_discipline()
|
||||
unusedFunction:t-dll-api.cc:140
|
||||
unusedFunction:t-dll-api.cc:133
|
||||
//ivl_design_disciplines()
|
||||
unusedFunction:t-dll-api.cc:134
|
||||
unusedFunction:t-dll-api.cc:127
|
||||
//ivl_design_flag()
|
||||
unusedFunction:t-dll-api.cc:59
|
||||
//ivl_design_process()
|
||||
@@ -48,211 +62,211 @@ unusedFunction:t-dll-api.cc:80
|
||||
//ivl_design_roots()
|
||||
unusedFunction:t-dll-api.cc:89
|
||||
//ivl_design_time_precision()
|
||||
unusedFunction:t-dll-api.cc:115
|
||||
unusedFunction:t-dll-api.cc:108
|
||||
|
||||
//ivl_discipline_domain()
|
||||
unusedFunction:t-dll-api.cc:147
|
||||
unusedFunction:t-dll-api.cc:140
|
||||
//ivl_discipline_flow()
|
||||
unusedFunction:t-dll-api.cc:153
|
||||
unusedFunction:t-dll-api.cc:146
|
||||
//ivl_discipline_name()
|
||||
unusedFunction:t-dll-api.cc:159
|
||||
unusedFunction:t-dll-api.cc:152
|
||||
//ivl_discipline_potential()
|
||||
unusedFunction:t-dll-api.cc:165
|
||||
unusedFunction:t-dll-api.cc:158
|
||||
|
||||
//ivl_enum_bits()
|
||||
unusedFunction:t-dll-api.cc:277
|
||||
//ivl_enum_file()
|
||||
unusedFunction:t-dll-api.cc:302
|
||||
//ivl_enum_lineno()
|
||||
unusedFunction:t-dll-api.cc:308
|
||||
//ivl_enum_name()
|
||||
unusedFunction:t-dll-api.cc:270
|
||||
//ivl_enum_file()
|
||||
unusedFunction:t-dll-api.cc:295
|
||||
//ivl_enum_lineno()
|
||||
unusedFunction:t-dll-api.cc:301
|
||||
//ivl_enum_name()
|
||||
unusedFunction:t-dll-api.cc:263
|
||||
//ivl_enum_names()
|
||||
unusedFunction:t-dll-api.cc:264
|
||||
unusedFunction:t-dll-api.cc:257
|
||||
//ivl_enum_signed()
|
||||
unusedFunction:t-dll-api.cc:296
|
||||
unusedFunction:t-dll-api.cc:289
|
||||
//ivl_enum_type()
|
||||
unusedFunction:t-dll-api.cc:284
|
||||
unusedFunction:t-dll-api.cc:277
|
||||
//ivl_enum_width()
|
||||
unusedFunction:t-dll-api.cc:290
|
||||
unusedFunction:t-dll-api.cc:283
|
||||
|
||||
//ivl_event_any()
|
||||
unusedFunction:t-dll-api.cc:369
|
||||
unusedFunction:t-dll-api.cc:362
|
||||
//ivl_event_file()
|
||||
unusedFunction:t-dll-api.cc:345
|
||||
unusedFunction:t-dll-api.cc:338
|
||||
//ivl_event_lineno()
|
||||
unusedFunction:t-dll-api.cc:351
|
||||
unusedFunction:t-dll-api.cc:344
|
||||
//ivl_event_name()
|
||||
unusedFunction:t-dll-api.cc:314
|
||||
unusedFunction:t-dll-api.cc:307
|
||||
//ivl_event_nany()
|
||||
unusedFunction:t-dll-api.cc:363
|
||||
unusedFunction:t-dll-api.cc:356
|
||||
//ivl_event_neg()
|
||||
unusedFunction:t-dll-api.cc:382
|
||||
unusedFunction:t-dll-api.cc:375
|
||||
//ivl_event_nneg()
|
||||
unusedFunction:t-dll-api.cc:376
|
||||
unusedFunction:t-dll-api.cc:369
|
||||
//ivl_event_npos()
|
||||
unusedFunction:t-dll-api.cc:389
|
||||
unusedFunction:t-dll-api.cc:382
|
||||
//ivl_event_pos()
|
||||
unusedFunction:t-dll-api.cc:395
|
||||
unusedFunction:t-dll-api.cc:388
|
||||
//ivl_event_scope()
|
||||
unusedFunction:t-dll-api.cc:357
|
||||
unusedFunction:t-dll-api.cc:350
|
||||
|
||||
//ivl_expr_bits()
|
||||
unusedFunction:t-dll-api.cc:402
|
||||
unusedFunction:t-dll-api.cc:395
|
||||
//ivl_expr_branch()
|
||||
unusedFunction:t-dll-api.cc:409
|
||||
unusedFunction:t-dll-api.cc:402
|
||||
//ivl_expr_def()
|
||||
unusedFunction:t-dll-api.cc:416
|
||||
unusedFunction:t-dll-api.cc:409
|
||||
//ivl_expr_delay_val()
|
||||
unusedFunction:t-dll-api.cc:432
|
||||
unusedFunction:t-dll-api.cc:425
|
||||
//ivl_expr_dvalue()
|
||||
unusedFunction:t-dll-api.cc:439
|
||||
unusedFunction:t-dll-api.cc:432
|
||||
//ivl_expr_enumtype()
|
||||
unusedFunction:t-dll-api.cc:446
|
||||
unusedFunction:t-dll-api.cc:439
|
||||
//ivl_expr_event()
|
||||
unusedFunction:t-dll-api.cc:656
|
||||
//ivl_expr_file()
|
||||
unusedFunction:t-dll-api.cc:178
|
||||
//ivl_expr_lineno()
|
||||
unusedFunction:t-dll-api.cc:184
|
||||
//ivl_expr_name()
|
||||
unusedFunction:t-dll-api.cc:459
|
||||
//ivl_expr_nature()
|
||||
unusedFunction:t-dll-api.cc:483
|
||||
//ivl_expr_net_type()
|
||||
unusedFunction:t-dll-api.cc:453
|
||||
//ivl_expr_opcode()
|
||||
unusedFunction:t-dll-api.cc:490
|
||||
//ivl_expr_oper1()
|
||||
unusedFunction:t-dll-api.cc:506
|
||||
//ivl_expr_oper2()
|
||||
unusedFunction:t-dll-api.cc:544
|
||||
//ivl_expr_oper3()
|
||||
unusedFunction:t-dll-api.cc:570
|
||||
//ivl_expr_parameter()
|
||||
unusedFunction:t-dll-api.cc:584
|
||||
//ivl_expr_parm()
|
||||
unusedFunction:t-dll-api.cc:599
|
||||
//ivl_expr_parms()
|
||||
unusedFunction:t-dll-api.cc:626
|
||||
//ivl_expr_repeat()
|
||||
unusedFunction:t-dll-api.cc:649
|
||||
//ivl_expr_scope()
|
||||
unusedFunction:t-dll-api.cc:670
|
||||
//ivl_expr_sel_type()
|
||||
unusedFunction:t-dll-api.cc:677
|
||||
//ivl_expr_signed()
|
||||
unusedFunction:t-dll-api.cc:702
|
||||
//ivl_expr_sized()
|
||||
unusedFunction:t-dll-api.cc:708
|
||||
//ivl_expr_string()
|
||||
unusedFunction:t-dll-api.cc:714
|
||||
//ivl_expr_type()
|
||||
//ivl_expr_file()
|
||||
unusedFunction:t-dll-api.cc:171
|
||||
//ivl_expr_lineno()
|
||||
unusedFunction:t-dll-api.cc:177
|
||||
//ivl_expr_name()
|
||||
unusedFunction:t-dll-api.cc:452
|
||||
//ivl_expr_nature()
|
||||
unusedFunction:t-dll-api.cc:476
|
||||
//ivl_expr_net_type()
|
||||
unusedFunction:t-dll-api.cc:446
|
||||
//ivl_expr_opcode()
|
||||
unusedFunction:t-dll-api.cc:483
|
||||
//ivl_expr_oper1()
|
||||
unusedFunction:t-dll-api.cc:499
|
||||
//ivl_expr_oper2()
|
||||
unusedFunction:t-dll-api.cc:537
|
||||
//ivl_expr_oper3()
|
||||
unusedFunction:t-dll-api.cc:563
|
||||
//ivl_expr_parameter()
|
||||
unusedFunction:t-dll-api.cc:577
|
||||
//ivl_expr_parm()
|
||||
unusedFunction:t-dll-api.cc:592
|
||||
//ivl_expr_parms()
|
||||
unusedFunction:t-dll-api.cc:619
|
||||
//ivl_expr_repeat()
|
||||
unusedFunction:t-dll-api.cc:642
|
||||
//ivl_expr_scope()
|
||||
unusedFunction:t-dll-api.cc:663
|
||||
//ivl_expr_sel_type()
|
||||
unusedFunction:t-dll-api.cc:670
|
||||
//ivl_expr_signed()
|
||||
unusedFunction:t-dll-api.cc:795
|
||||
//ivl_expr_sized()
|
||||
unusedFunction:t-dll-api.cc:701
|
||||
//ivl_expr_string()
|
||||
unusedFunction:t-dll-api.cc:707
|
||||
//ivl_expr_type()
|
||||
unusedFunction:t-dll-api.cc:164
|
||||
//ivl_expr_uvalue()
|
||||
unusedFunction:t-dll-api.cc:721
|
||||
unusedFunction:t-dll-api.cc:714
|
||||
//ivl_expr_value()
|
||||
unusedFunction:t-dll-api.cc:747
|
||||
unusedFunction:t-dll-api.cc:740
|
||||
//ivl_expr_width()
|
||||
unusedFunction:t-dll-api.cc:753
|
||||
unusedFunction:t-dll-api.cc:746
|
||||
|
||||
//ivl_file_table_index()
|
||||
unusedFunction:t-dll-api.cc:795
|
||||
unusedFunction:t-dll-api.cc:788
|
||||
//ivl_file_table_item()
|
||||
unusedFunction:t-dll-api.cc:785
|
||||
unusedFunction:t-dll-api.cc:778
|
||||
//ivl_file_table_size()
|
||||
unusedFunction:t-dll-api.cc:813
|
||||
unusedFunction:t-dll-api.cc:806
|
||||
|
||||
//ivl_island_flag_set()
|
||||
unusedFunction:t-dll-api.cc:822
|
||||
unusedFunction:t-dll-api.cc:815
|
||||
//ivl_island_flag_test()
|
||||
unusedFunction:t-dll-api.cc:837
|
||||
unusedFunction:t-dll-api.cc:830
|
||||
|
||||
//ivl_logic_attr()
|
||||
unusedFunction:t-dll-api.cc:864
|
||||
unusedFunction:t-dll-api.cc:857
|
||||
//ivl_logic_attr_cnt()
|
||||
unusedFunction:t-dll-api.cc:880
|
||||
unusedFunction:t-dll-api.cc:873
|
||||
//ivl_logic_attr_val()
|
||||
unusedFunction:t-dll-api.cc:886
|
||||
unusedFunction:t-dll-api.cc:879
|
||||
//ivl_logic_basename()
|
||||
unusedFunction:t-dll-api.cc:935
|
||||
//ivl_logic_delay()
|
||||
unusedFunction:t-dll-api.cc:974
|
||||
//ivl_logic_drive0()
|
||||
unusedFunction:t-dll-api.cc:894
|
||||
//ivl_logic_drive1()
|
||||
unusedFunction:t-dll-api.cc:911
|
||||
//ivl_logic_file()
|
||||
unusedFunction:t-dll-api.cc:846
|
||||
//ivl_logic_is_cassign()
|
||||
unusedFunction:t-dll-api.cc:858
|
||||
//ivl_logic_lineno()
|
||||
unusedFunction:t-dll-api.cc:852
|
||||
//ivl_logic_name()
|
||||
unusedFunction:t-dll-api.cc:928
|
||||
//ivl_logic_delay()
|
||||
unusedFunction:t-dll-api.cc:967
|
||||
//ivl_logic_drive0()
|
||||
unusedFunction:t-dll-api.cc:887
|
||||
//ivl_logic_drive1()
|
||||
unusedFunction:t-dll-api.cc:904
|
||||
//ivl_logic_file()
|
||||
unusedFunction:t-dll-api.cc:839
|
||||
//ivl_logic_is_cassign()
|
||||
unusedFunction:t-dll-api.cc:851
|
||||
//ivl_logic_lineno()
|
||||
unusedFunction:t-dll-api.cc:845
|
||||
//ivl_logic_name()
|
||||
unusedFunction:t-dll-api.cc:921
|
||||
//ivl_logic_pins()
|
||||
unusedFunction:t-dll-api.cc:953
|
||||
unusedFunction:t-dll-api.cc:946
|
||||
//ivl_logic_scope()
|
||||
unusedFunction:t-dll-api.cc:941
|
||||
unusedFunction:t-dll-api.cc:934
|
||||
//ivl_logic_type()
|
||||
unusedFunction:t-dll-api.cc:947
|
||||
unusedFunction:t-dll-api.cc:940
|
||||
//ivl_logic_udp()
|
||||
unusedFunction:t-dll-api.cc:966
|
||||
unusedFunction:t-dll-api.cc:959
|
||||
//ivl_logic_width()
|
||||
unusedFunction:t-dll-api.cc:981
|
||||
unusedFunction:t-dll-api.cc:974
|
||||
|
||||
//ivl_lpm_array()
|
||||
unusedFunction:t-dll-api.cc:1109
|
||||
unusedFunction:t-dll-api.cc:1102
|
||||
//ivl_lpm_aset_value()
|
||||
unusedFunction:t-dll-api.cc:1160
|
||||
unusedFunction:t-dll-api.cc:1153
|
||||
//ivl_lpm_async_clr()
|
||||
unusedFunction:t-dll-api.cc:1054
|
||||
unusedFunction:t-dll-api.cc:1047
|
||||
//ivl_lpm_async_set()
|
||||
unusedFunction:t-dll-api.cc:1085
|
||||
//ivl_lpm_base()
|
||||
unusedFunction:t-dll-api.cc:1121
|
||||
//ivl_lpm_basename()
|
||||
unusedFunction:t-dll-api.cc:1048
|
||||
//ivl_lpm_clk()
|
||||
unusedFunction:t-dll-api.cc:1148
|
||||
//ivl_lpm_data()
|
||||
unusedFunction:t-dll-api.cc:1221
|
||||
//ivl_lpm_datab()
|
||||
unusedFunction:t-dll-api.cc:1321
|
||||
//ivl_lpm_define()
|
||||
unusedFunction:t-dll-api.cc:1183
|
||||
//ivl_lpm_delay()
|
||||
unusedFunction:t-dll-api.cc:1078
|
||||
//ivl_lpm_base()
|
||||
unusedFunction:t-dll-api.cc:1114
|
||||
//ivl_lpm_basename()
|
||||
unusedFunction:t-dll-api.cc:1041
|
||||
//ivl_lpm_clk()
|
||||
unusedFunction:t-dll-api.cc:1141
|
||||
//ivl_lpm_data()
|
||||
unusedFunction:t-dll-api.cc:1214
|
||||
//ivl_lpm_datab()
|
||||
unusedFunction:t-dll-api.cc:1316
|
||||
//ivl_lpm_define()
|
||||
unusedFunction:t-dll-api.cc:1176
|
||||
//ivl_lpm_delay()
|
||||
unusedFunction:t-dll-api.cc:1071
|
||||
//ivl_lpm_drive0()
|
||||
unusedFunction:t-dll-api.cc:1453
|
||||
unusedFunction:t-dll-api.cc:1450
|
||||
//ivl_lpm_drive1()
|
||||
unusedFunction:t-dll-api.cc:1470
|
||||
unusedFunction:t-dll-api.cc:1467
|
||||
//ivl_lpm_enable()
|
||||
unusedFunction:t-dll-api.cc:1195
|
||||
unusedFunction:t-dll-api.cc:1188
|
||||
//ivl_lpm_file()
|
||||
unusedFunction:t-dll-api.cc:1209
|
||||
unusedFunction:t-dll-api.cc:1202
|
||||
//ivl_lpm_lineno()
|
||||
unusedFunction:t-dll-api.cc:1215
|
||||
unusedFunction:t-dll-api.cc:1208
|
||||
//ivl_lpm_name()
|
||||
unusedFunction:t-dll-api.cc:1355
|
||||
unusedFunction:t-dll-api.cc:1350
|
||||
//ivl_lpm_negedge()
|
||||
unusedFunction:t-dll-api.cc:1136
|
||||
unusedFunction:t-dll-api.cc:1129
|
||||
//ivl_lpm_select()
|
||||
unusedFunction:t-dll-api.cc:1493
|
||||
unusedFunction:t-dll-api.cc:1490
|
||||
//ivl_lpm_selects()
|
||||
unusedFunction:t-dll-api.cc:1510
|
||||
unusedFunction:t-dll-api.cc:1507
|
||||
//ivl_lpm_signed()
|
||||
unusedFunction:t-dll-api.cc:1528
|
||||
unusedFunction:t-dll-api.cc:1526
|
||||
//ivl_lpm_size()
|
||||
unusedFunction:t-dll-api.cc:1587
|
||||
//ivl_lpm_sset_value()
|
||||
unusedFunction:t-dll-api.cc:1171
|
||||
unusedFunction:t-dll-api.cc:1164
|
||||
//ivl_lpm_string()
|
||||
unusedFunction:t-dll-api.cc:1640
|
||||
//ivl_lpm_sync_clr()
|
||||
unusedFunction:t-dll-api.cc:1066
|
||||
unusedFunction:t-dll-api.cc:1059
|
||||
//ivl_lpm_sync_set()
|
||||
unusedFunction:t-dll-api.cc:1097
|
||||
unusedFunction:t-dll-api.cc:1090
|
||||
//ivl_lpm_trigger()
|
||||
unusedFunction:t-dll-api.cc:1659
|
||||
//ivl_lpm_type()
|
||||
@@ -317,303 +331,308 @@ unusedFunction:t-dll-api.cc:1887
|
||||
//ivl_path_condit()
|
||||
unusedFunction:t-dll-api.cc:1920
|
||||
//ivl_path_delay()
|
||||
unusedFunction:t-dll-api.cc:1932
|
||||
unusedFunction:t-dll-api.cc:1938
|
||||
//ivl_path_is_condit()
|
||||
unusedFunction:t-dll-api.cc:1926
|
||||
//ivl_path_is_parallel()
|
||||
unusedFunction:t-dll-api.cc:1932
|
||||
//ivl_path_scope()
|
||||
unusedFunction:t-dll-api.cc:1938
|
||||
unusedFunction:t-dll-api.cc:1944
|
||||
//ivl_path_source()
|
||||
unusedFunction:t-dll-api.cc:1945
|
||||
//ivl_path_source_negedge()
|
||||
unusedFunction:t-dll-api.cc:1957
|
||||
//ivl_path_source_posedge()
|
||||
unusedFunction:t-dll-api.cc:1951
|
||||
//ivl_path_source_negedge()
|
||||
unusedFunction:t-dll-api.cc:1963
|
||||
//ivl_path_source_posedge()
|
||||
unusedFunction:t-dll-api.cc:1957
|
||||
|
||||
//ivl_process_analog()
|
||||
unusedFunction:t-dll-api.cc:1981
|
||||
//ivl_process_attr_cnt()
|
||||
unusedFunction:t-dll-api.cc:1999
|
||||
//ivl_process_attr_val()
|
||||
unusedFunction:t-dll-api.cc:2005
|
||||
//ivl_process_file()
|
||||
unusedFunction:t-dll-api.cc:1963
|
||||
//ivl_process_lineno()
|
||||
unusedFunction:t-dll-api.cc:1969
|
||||
//ivl_process_scope()
|
||||
unusedFunction:t-dll-api.cc:1987
|
||||
//ivl_process_stmt()
|
||||
unusedFunction:t-dll-api.cc:1993
|
||||
//ivl_process_type()
|
||||
//ivl_process_attr_cnt()
|
||||
unusedFunction:t-dll-api.cc:2005
|
||||
//ivl_process_attr_val()
|
||||
unusedFunction:t-dll-api.cc:2011
|
||||
//ivl_process_file()
|
||||
unusedFunction:t-dll-api.cc:1969
|
||||
//ivl_process_lineno()
|
||||
unusedFunction:t-dll-api.cc:1975
|
||||
//ivl_process_scope()
|
||||
unusedFunction:t-dll-api.cc:1993
|
||||
//ivl_process_stmt()
|
||||
unusedFunction:t-dll-api.cc:1999
|
||||
//ivl_process_type()
|
||||
unusedFunction:t-dll-api.cc:1981
|
||||
|
||||
//ivl_scope_attr_cnt()
|
||||
unusedFunction:t-dll-api.cc:2013
|
||||
//ivl_scope_attr_val()
|
||||
unusedFunction:t-dll-api.cc:2019
|
||||
//ivl_scope_attr_val()
|
||||
unusedFunction:t-dll-api.cc:2025
|
||||
//ivl_scope_basename()
|
||||
unusedFunction:t-dll-api.cc:2027
|
||||
//ivl_scope_child()
|
||||
unusedFunction:t-dll-api.cc:2054
|
||||
//ivl_scope_children()
|
||||
unusedFunction:t-dll-api.cc:2033
|
||||
//ivl_scope_child()
|
||||
unusedFunction:t-dll-api.cc:2060
|
||||
//ivl_scope_children()
|
||||
unusedFunction:t-dll-api.cc:2039
|
||||
//ivl_scope_childs()
|
||||
unusedFunction:t-dll-api.cc:2047
|
||||
unusedFunction:t-dll-api.cc:2053
|
||||
//ivl_scope_class()
|
||||
unusedFunction:t-dll-api.cc:2061
|
||||
unusedFunction:t-dll-api.cc:2067
|
||||
//ivl_scope_classes()
|
||||
unusedFunction:t-dll-api.cc:2068
|
||||
unusedFunction:t-dll-api.cc:2074
|
||||
//ivl_scope_def()
|
||||
unusedFunction:t-dll-api.cc:2075
|
||||
//ivl_scope_def_file()
|
||||
unusedFunction:t-dll-api.cc:2081
|
||||
//ivl_scope_def_lineno()
|
||||
//ivl_scope_def_file()
|
||||
unusedFunction:t-dll-api.cc:2087
|
||||
//ivl_scope_enumerate()
|
||||
unusedFunction:t-dll-api.cc:2099
|
||||
//ivl_scope_enumerates()
|
||||
//ivl_scope_def_lineno()
|
||||
unusedFunction:t-dll-api.cc:2093
|
||||
//ivl_scope_enumerate()
|
||||
unusedFunction:t-dll-api.cc:2105
|
||||
//ivl_scope_enumerates()
|
||||
unusedFunction:t-dll-api.cc:2099
|
||||
//ivl_scope_event()
|
||||
unusedFunction:t-dll-api.cc:2112
|
||||
unusedFunction:t-dll-api.cc:2118
|
||||
//ivl_scope_events()
|
||||
unusedFunction:t-dll-api.cc:2106
|
||||
unusedFunction:t-dll-api.cc:2112
|
||||
//ivl_scope_file()
|
||||
unusedFunction:t-dll-api.cc:2119
|
||||
//ivl_scope_func_signed
|
||||
unusedFunction:t-dll-api.cc:2132
|
||||
//ivl_scope_func_type
|
||||
unusedFunction:t-dll-api.cc:2125
|
||||
//ivl_scope_func_signed
|
||||
unusedFunction:t-dll-api.cc:2138
|
||||
//ivl_scope_func_type
|
||||
unusedFunction:t-dll-api.cc:2131
|
||||
//ivl_scope_func_width
|
||||
unusedFunction:t-dll-api.cc:2140
|
||||
unusedFunction:t-dll-api.cc:2146
|
||||
//ivl_scope_is_auto()
|
||||
unusedFunction:t-dll-api.cc:2148
|
||||
//ivl_scope_is_cell()
|
||||
unusedFunction:t-dll-api.cc:2154
|
||||
//ivl_scope_lineno()
|
||||
//ivl_scope_is_cell()
|
||||
unusedFunction:t-dll-api.cc:2160
|
||||
//ivl_scope_log()
|
||||
unusedFunction:t-dll-api.cc:2172
|
||||
//ivl_scope_logs()
|
||||
//ivl_scope_lineno()
|
||||
unusedFunction:t-dll-api.cc:2166
|
||||
//ivl_scope_log()
|
||||
unusedFunction:t-dll-api.cc:2178
|
||||
//ivl_scope_logs()
|
||||
unusedFunction:t-dll-api.cc:2172
|
||||
//ivl_scope_lpm()
|
||||
unusedFunction:t-dll-api.cc:2185
|
||||
unusedFunction:t-dll-api.cc:2191
|
||||
//ivl_scope_lpms()
|
||||
unusedFunction:t-dll-api.cc:2179
|
||||
unusedFunction:t-dll-api.cc:2185
|
||||
//ivl_scope_mod_module_port_name()
|
||||
unusedFunction:t-dll-api.cc:2264
|
||||
unusedFunction:t-dll-api.cc:2270
|
||||
//ivl_scope_mod_module_port_type()
|
||||
unusedFunction:t-dll-api.cc:2273
|
||||
unusedFunction:t-dll-api.cc:2279
|
||||
//ivl_scope_mod_module_port_width()
|
||||
unusedFunction:t-dll-api.cc:2285
|
||||
unusedFunction:t-dll-api.cc:2291
|
||||
//ivl_scope_mod_module_ports()
|
||||
unusedFunction:t-dll-api.cc:2257
|
||||
unusedFunction:t-dll-api.cc:2263
|
||||
//ivl_scope_mod_port()
|
||||
unusedFunction:t-dll-api.cc:2310
|
||||
unusedFunction:t-dll-api.cc:2316
|
||||
//ivl_scope_param()
|
||||
unusedFunction:t-dll-api.cc:2243
|
||||
unusedFunction:t-dll-api.cc:2249
|
||||
//ivl_scope_params()
|
||||
unusedFunction:t-dll-api.cc:2237
|
||||
unusedFunction:t-dll-api.cc:2243
|
||||
//ivl_scope_parent()
|
||||
unusedFunction:t-dll-api.cc:2250
|
||||
unusedFunction:t-dll-api.cc:2256
|
||||
//ivl_scope_port()
|
||||
unusedFunction:t-dll-api.cc:2301
|
||||
unusedFunction:t-dll-api.cc:2307
|
||||
//ivl_scope_ports()
|
||||
unusedFunction:t-dll-api.cc:2292
|
||||
unusedFunction:t-dll-api.cc:2298
|
||||
//ivl_scope_sig()
|
||||
unusedFunction:t-dll-api.cc:2324
|
||||
unusedFunction:t-dll-api.cc:2330
|
||||
//ivl_scope_sigs()
|
||||
unusedFunction:t-dll-api.cc:2318
|
||||
unusedFunction:t-dll-api.cc:2324
|
||||
//ivl_scope_switch()
|
||||
unusedFunction:t-dll-api.cc:2337
|
||||
unusedFunction:t-dll-api.cc:2343
|
||||
//ivl_scope_switches()
|
||||
unusedFunction:t-dll-api.cc:2331
|
||||
unusedFunction:t-dll-api.cc:2337
|
||||
//ivl_scope_time_precision()
|
||||
unusedFunction:t-dll-api.cc:2344
|
||||
//ivl_scope_time_units()
|
||||
unusedFunction:t-dll-api.cc:2350
|
||||
//ivl_scope_tname()
|
||||
unusedFunction:t-dll-api.cc:2362
|
||||
//ivl_scope_type()
|
||||
//ivl_scope_time_units()
|
||||
unusedFunction:t-dll-api.cc:2356
|
||||
//ivl_scope_tname()
|
||||
unusedFunction:t-dll-api.cc:2368
|
||||
//ivl_scope_type()
|
||||
unusedFunction:t-dll-api.cc:2362
|
||||
|
||||
//ivl_signal_array_addr_swapped()
|
||||
unusedFunction:t-dll-api.cc:2380
|
||||
//ivl_signal_array_base()
|
||||
unusedFunction:t-dll-api.cc:2368
|
||||
//ivl_signal_array_count()
|
||||
unusedFunction:t-dll-api.cc:2374
|
||||
//ivl_signal_attr()
|
||||
unusedFunction:t-dll-api.cc:2398
|
||||
//ivl_signal_attr_cnt()
|
||||
unusedFunction:t-dll-api.cc:2414
|
||||
//ivl_signal_attr_val()
|
||||
unusedFunction:t-dll-api.cc:2420
|
||||
//ivl_signal_basename()
|
||||
unusedFunction:t-dll-api.cc:2427
|
||||
//ivl_signal_data_type()
|
||||
unusedFunction:t-dll-api.cc:2578
|
||||
//ivl_signal_dimensions()
|
||||
unusedFunction:t-dll-api.cc:2386
|
||||
//ivl_signal_discipline()
|
||||
unusedFunction:t-dll-api.cc:2392
|
||||
//ivl_signal_file()
|
||||
unusedFunction:t-dll-api.cc:2555
|
||||
//ivl_signal_forced_net()
|
||||
unusedFunction:t-dll-api.cc:2549
|
||||
//ivl_signal_integer()
|
||||
unusedFunction:t-dll-api.cc:2567
|
||||
//ivl_signal_lineno()
|
||||
unusedFunction:t-dll-api.cc:2561
|
||||
//ivl_signal_local()
|
||||
unusedFunction:t-dll-api.cc:2536
|
||||
//ivl_signal_lsb()
|
||||
unusedFunction:t-dll-api.cc:2501
|
||||
//ivl_signal_module_port_index()
|
||||
unusedFunction:t-dll-api.cc:2530
|
||||
//ivl_signal_msb()
|
||||
unusedFunction:t-dll-api.cc:2491
|
||||
//ivl_signal_name()
|
||||
//ivl_signal_array_base()
|
||||
unusedFunction:t-dll-api.cc:2374
|
||||
//ivl_signal_array_count()
|
||||
unusedFunction:t-dll-api.cc:2380
|
||||
//ivl_signal_attr()
|
||||
unusedFunction:t-dll-api.cc:2404
|
||||
//ivl_signal_attr_cnt()
|
||||
unusedFunction:t-dll-api.cc:2420
|
||||
//ivl_signal_attr_val()
|
||||
unusedFunction:t-dll-api.cc:2426
|
||||
//ivl_signal_basename()
|
||||
unusedFunction:t-dll-api.cc:2433
|
||||
//ivl_signal_nex()
|
||||
unusedFunction:t-dll-api.cc:2454
|
||||
//ivl_signal_npath()
|
||||
unusedFunction:t-dll-api.cc:2591
|
||||
//ivl_signal_packed_dimensions()
|
||||
unusedFunction:t-dll-api.cc:2471
|
||||
//ivl_signal_packed_lsb()
|
||||
unusedFunction:t-dll-api.cc:2484
|
||||
//ivl_signal_packed_msb()
|
||||
unusedFunction:t-dll-api.cc:2477
|
||||
//ivl_signal_path()
|
||||
unusedFunction:t-dll-api.cc:2597
|
||||
//ivl_signal_port()
|
||||
unusedFunction:t-dll-api.cc:2524
|
||||
//ivl_signal_scope()
|
||||
unusedFunction:t-dll-api.cc:2511
|
||||
//ivl_signal_signed()
|
||||
//ivl_signal_data_type()
|
||||
unusedFunction:t-dll-api.cc:2584
|
||||
//ivl_signal_dimensions()
|
||||
unusedFunction:t-dll-api.cc:2392
|
||||
//ivl_signal_discipline()
|
||||
unusedFunction:t-dll-api.cc:2398
|
||||
//ivl_signal_file()
|
||||
unusedFunction:t-dll-api.cc:2561
|
||||
//ivl_signal_forced_net()
|
||||
unusedFunction:t-dll-api.cc:2555
|
||||
//ivl_signal_integer()
|
||||
unusedFunction:t-dll-api.cc:2573
|
||||
//ivl_signal_lineno()
|
||||
unusedFunction:t-dll-api.cc:2567
|
||||
//ivl_signal_local()
|
||||
unusedFunction:t-dll-api.cc:2542
|
||||
//ivl_signal_width()
|
||||
//ivl_signal_lsb()
|
||||
unusedFunction:t-dll-api.cc:2507
|
||||
//ivl_signal_module_port_index()
|
||||
unusedFunction:t-dll-api.cc:2536
|
||||
//ivl_signal_msb()
|
||||
unusedFunction:t-dll-api.cc:2497
|
||||
//ivl_signal_name()
|
||||
unusedFunction:t-dll-api.cc:2439
|
||||
//ivl_signal_nex()
|
||||
unusedFunction:t-dll-api.cc:2460
|
||||
//ivl_signal_npath()
|
||||
unusedFunction:t-dll-api.cc:2597
|
||||
//ivl_signal_packed_dimensions()
|
||||
unusedFunction:t-dll-api.cc:2477
|
||||
//ivl_signal_packed_lsb()
|
||||
unusedFunction:t-dll-api.cc:2490
|
||||
//ivl_signal_packed_msb()
|
||||
unusedFunction:t-dll-api.cc:2483
|
||||
//ivl_signal_path()
|
||||
unusedFunction:t-dll-api.cc:2603
|
||||
//ivl_signal_port()
|
||||
unusedFunction:t-dll-api.cc:2530
|
||||
//ivl_signal_scope()
|
||||
unusedFunction:t-dll-api.cc:2517
|
||||
//ivl_signal_signed()
|
||||
unusedFunction:t-dll-api.cc:2548
|
||||
//ivl_signal_width()
|
||||
unusedFunction:t-dll-api.cc:2523
|
||||
|
||||
//ivl_statement_type()
|
||||
unusedFunction:t-dll-api.cc:2610
|
||||
unusedFunction:t-dll-api.cc:2616
|
||||
|
||||
//ivl_stmt_block_count()
|
||||
unusedFunction:t-dll-api.cc:2643
|
||||
unusedFunction:t-dll-api.cc:2649
|
||||
//ivl_stmt_block_scope()
|
||||
unusedFunction:t-dll-api.cc:2628
|
||||
unusedFunction:t-dll-api.cc:2634
|
||||
//ivl_stmt_block_stmt()
|
||||
unusedFunction:t-dll-api.cc:2658
|
||||
unusedFunction:t-dll-api.cc:2664
|
||||
//ivl_stmt_call()
|
||||
unusedFunction:t-dll-api.cc:2674
|
||||
unusedFunction:t-dll-api.cc:2680
|
||||
//ivl_stmt_case_count()
|
||||
unusedFunction:t-dll-api.cc:2695
|
||||
unusedFunction:t-dll-api.cc:2701
|
||||
//ivl_stmt_case_expr()
|
||||
unusedFunction:t-dll-api.cc:2710
|
||||
unusedFunction:t-dll-api.cc:2716
|
||||
//ivl_stmt_case_quality()
|
||||
unusedFunction:t-dll-api.cc:2733
|
||||
//ivl_stmt_case_stmt()
|
||||
unusedFunction:t-dll-api.cc:2727
|
||||
unusedFunction:t-dll-api.cc:2749
|
||||
//ivl_stmt_cond_expr()
|
||||
unusedFunction:t-dll-api.cc:2744
|
||||
unusedFunction:t-dll-api.cc:2766
|
||||
//ivl_stmt_cond_false()
|
||||
unusedFunction:t-dll-api.cc:2771
|
||||
unusedFunction:t-dll-api.cc:2793
|
||||
//ivl_stmt_cond_true()
|
||||
unusedFunction:t-dll-api.cc:2781
|
||||
unusedFunction:t-dll-api.cc:2803
|
||||
//ivl_stmt_delay_expr()
|
||||
unusedFunction:t-dll-api.cc:2791
|
||||
unusedFunction:t-dll-api.cc:2813
|
||||
//ivl_stmt_delay_val()
|
||||
unusedFunction:t-dll-api.cc:2808
|
||||
unusedFunction:t-dll-api.cc:2830
|
||||
//ivl_stmt_events()
|
||||
unusedFunction:t-dll-api.cc:2834
|
||||
unusedFunction:t-dll-api.cc:2866
|
||||
//ivl_stmt_file()
|
||||
unusedFunction:t-dll-api.cc:2616
|
||||
//ivl_stmt_lexp()
|
||||
unusedFunction:t-dll-api.cc:2862
|
||||
//ivl_stmt_lineno()
|
||||
unusedFunction:t-dll-api.cc:2622
|
||||
//ivl_stmt_lexp()
|
||||
unusedFunction:t-dll-api.cc:2894
|
||||
//ivl_stmt_lineno()
|
||||
unusedFunction:t-dll-api.cc:2628
|
||||
//ivl_stmt_lval()
|
||||
unusedFunction:t-dll-api.cc:2874
|
||||
unusedFunction:t-dll-api.cc:2906
|
||||
//ivl_stmt_lvals()
|
||||
unusedFunction:t-dll-api.cc:2893
|
||||
unusedFunction:t-dll-api.cc:2925
|
||||
//ivl_stmt_lwidth()
|
||||
unusedFunction:t-dll-api.cc:2911
|
||||
unusedFunction:t-dll-api.cc:2943
|
||||
//ivl_stmt_name()
|
||||
unusedFunction:t-dll-api.cc:2944
|
||||
unusedFunction:t-dll-api.cc:2976
|
||||
//ivl_stmt_needs_t0_trigger()
|
||||
unusedFunction:t-dll-api.cc:2837
|
||||
//ivl_stmt_nevent()
|
||||
unusedFunction:t-dll-api.cc:2815
|
||||
unusedFunction:t-dll-api.cc:2847
|
||||
//ivl_stmt_opcode()
|
||||
unusedFunction:t-dll-api.cc:2957
|
||||
unusedFunction:t-dll-api.cc:2989
|
||||
//ivl_stmt_parm()
|
||||
unusedFunction:t-dll-api.cc:2969
|
||||
unusedFunction:t-dll-api.cc:3001
|
||||
//ivl_stmt_parm_count()
|
||||
unusedFunction:t-dll-api.cc:2983
|
||||
unusedFunction:t-dll-api.cc:3015
|
||||
//ivl_stmt_rval()
|
||||
unusedFunction:t-dll-api.cc:2995
|
||||
unusedFunction:t-dll-api.cc:3027
|
||||
//ivl_stmt_sfunc_as_task()
|
||||
unusedFunction:t-dll-api.cc:3013
|
||||
unusedFunction:t-dll-api.cc:3045
|
||||
//ivl_stmt_sub_stmt()
|
||||
unusedFunction:t-dll-api.cc:3026
|
||||
unusedFunction:t-dll-api.cc:3058
|
||||
|
||||
//ivl_switch_a()
|
||||
unusedFunction:t-dll-api.cc:3067
|
||||
unusedFunction:t-dll-api.cc:3099
|
||||
//ivl_switch_b()
|
||||
unusedFunction:t-dll-api.cc:3073
|
||||
unusedFunction:t-dll-api.cc:3105
|
||||
//ivl_switch_basename()
|
||||
unusedFunction:t-dll-api.cc:3049
|
||||
unusedFunction:t-dll-api.cc:3081
|
||||
//ivl_switch_delay()
|
||||
unusedFunction:t-dll-api.cc:3103
|
||||
unusedFunction:t-dll-api.cc:3135
|
||||
//ivl_switch_enable()
|
||||
unusedFunction:t-dll-api.cc:3079
|
||||
unusedFunction:t-dll-api.cc:3111
|
||||
//ivl_switch_file()
|
||||
unusedFunction:t-dll-api.cc:3110
|
||||
unusedFunction:t-dll-api.cc:3142
|
||||
//ivl_switch_island()
|
||||
unusedFunction:t-dll-api.cc:3116
|
||||
unusedFunction:t-dll-api.cc:3148
|
||||
//ivl_switch_lineno()
|
||||
unusedFunction:t-dll-api.cc:3122
|
||||
unusedFunction:t-dll-api.cc:3154
|
||||
//ivl_switch_offset()
|
||||
unusedFunction:t-dll-api.cc:3097
|
||||
unusedFunction:t-dll-api.cc:3129
|
||||
//ivl_switch_part()
|
||||
unusedFunction:t-dll-api.cc:3091
|
||||
unusedFunction:t-dll-api.cc:3123
|
||||
//ivl_switch_scope()
|
||||
unusedFunction:t-dll-api.cc:3055
|
||||
unusedFunction:t-dll-api.cc:3087
|
||||
//ivl_switch_type()
|
||||
unusedFunction:t-dll-api.cc:3061
|
||||
unusedFunction:t-dll-api.cc:3093
|
||||
//ivl_switch_width()
|
||||
unusedFunction:t-dll-api.cc:3085
|
||||
unusedFunction:t-dll-api.cc:3117
|
||||
|
||||
//ivl_type_base()
|
||||
unusedFunction:t-dll-api.cc:3128
|
||||
//unusedFunction:t-dll-api.cc:3128 Used in netmisc.cc
|
||||
//ivl_type_element()
|
||||
unusedFunction:t-dll-api.cc:3134
|
||||
//ivl_type_name()
|
||||
unusedFunction:t-dll-api.cc:3166
|
||||
//ivl_type_name()
|
||||
unusedFunction:t-dll-api.cc:3198
|
||||
//ivl_type_packed_dimensions()
|
||||
unusedFunction:t-dll-api.cc:3143
|
||||
unusedFunction:t-dll-api.cc:3175
|
||||
//ivl_type_packed_lsb()
|
||||
unusedFunction:t-dll-api.cc:3150
|
||||
unusedFunction:t-dll-api.cc:3182
|
||||
//ivl_type_packed_msb()
|
||||
unusedFunction:t-dll-api.cc:3158
|
||||
unusedFunction:t-dll-api.cc:3190
|
||||
//ivl_type_prop_type()
|
||||
unusedFunction:t-dll-api.cc:3191
|
||||
unusedFunction:t-dll-api.cc:3223
|
||||
//ivl_type_properties()
|
||||
unusedFunction:t-dll-api.cc:3174
|
||||
unusedFunction:t-dll-api.cc:3206
|
||||
//ivl_type_signed()
|
||||
unusedFunction:t-dll-api.cc:3199
|
||||
unusedFunction:t-dll-api.cc:3231
|
||||
|
||||
//ivl_udp_file()
|
||||
unusedFunction:t-dll-api.cc:1036
|
||||
//ivl_udp_init()
|
||||
unusedFunction:t-dll-api.cc:999
|
||||
//ivl_udp_lineno()
|
||||
unusedFunction:t-dll-api.cc:1042
|
||||
//ivl_udp_name()
|
||||
unusedFunction:t-dll-api.cc:1029
|
||||
//ivl_udp_init()
|
||||
unusedFunction:t-dll-api.cc:992
|
||||
//ivl_udp_lineno()
|
||||
unusedFunction:t-dll-api.cc:1035
|
||||
//ivl_udp_name()
|
||||
unusedFunction:t-dll-api.cc:1022
|
||||
//ivl_udp_nin()
|
||||
unusedFunction:t-dll-api.cc:993
|
||||
unusedFunction:t-dll-api.cc:986
|
||||
//ivl_udp_port()
|
||||
unusedFunction:t-dll-api.cc:1005
|
||||
unusedFunction:t-dll-api.cc:998
|
||||
//ivl_udp_row()
|
||||
unusedFunction:t-dll-api.cc:1014
|
||||
unusedFunction:t-dll-api.cc:1007
|
||||
//ivl_udp_rows()
|
||||
unusedFunction:t-dll-api.cc:1023
|
||||
unusedFunction:t-dll-api.cc:1016
|
||||
// ivl_udp_sequ()
|
||||
unusedFunction:t-dll-api.cc:987
|
||||
|
||||
unusedFunction:t-dll-api.cc:980
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998-2013 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2021 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -28,6 +28,7 @@
|
||||
# include "compiler.h"
|
||||
# include "ivl_assert.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
/*
|
||||
* The cprop function below invokes constant propagation where
|
||||
@@ -42,14 +43,14 @@ struct cprop_functor : public functor_t {
|
||||
|
||||
virtual void signal(Design*des, NetNet*obj);
|
||||
virtual void lpm_add_sub(Design*des, NetAddSub*obj);
|
||||
virtual void lpm_compare(Design*des, NetCompare*obj);
|
||||
virtual void lpm_compare(Design*des, const NetCompare*obj);
|
||||
virtual void lpm_concat(Design*des, NetConcat*obj);
|
||||
virtual void lpm_ff(Design*des, NetFF*obj);
|
||||
virtual void lpm_logic(Design*des, NetLogic*obj);
|
||||
virtual void lpm_mux(Design*des, NetMux*obj);
|
||||
virtual void lpm_part_select(Design*des, NetPartSelect*obj);
|
||||
|
||||
void lpm_compare_eq_(Design*des, NetCompare*obj);
|
||||
void lpm_compare_eq_(Design*des, const NetCompare*obj);
|
||||
};
|
||||
|
||||
void cprop_functor::signal(Design*, NetNet*)
|
||||
@@ -60,7 +61,7 @@ void cprop_functor::lpm_add_sub(Design*, NetAddSub*)
|
||||
{
|
||||
}
|
||||
|
||||
void cprop_functor::lpm_compare(Design*des, NetCompare*obj)
|
||||
void cprop_functor::lpm_compare(Design*des, const NetCompare*obj)
|
||||
{
|
||||
if (obj->pin_AEB().is_linked()) {
|
||||
assert( ! obj->pin_AGB().is_linked() );
|
||||
@@ -74,7 +75,7 @@ void cprop_functor::lpm_compare(Design*des, NetCompare*obj)
|
||||
}
|
||||
}
|
||||
|
||||
void cprop_functor::lpm_compare_eq_(Design*, NetCompare*)
|
||||
void cprop_functor::lpm_compare_eq_(Design*, const NetCompare*)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -295,11 +296,11 @@ void cprop_functor::lpm_part_select(Design*des, NetPartSelect*obj)
|
||||
if (off < sig_width)
|
||||
part_count += 1;
|
||||
|
||||
NetConcat*concat = new NetConcat(scope, scope->local_symbol(),
|
||||
NetConcat*cncat = new NetConcat(scope, scope->local_symbol(),
|
||||
sig_width, part_count);
|
||||
concat->set_line(*obj);
|
||||
des->add_node(concat);
|
||||
connect(concat->pin(0), obj->pin(1));
|
||||
cncat->set_line(*obj);
|
||||
des->add_node(cncat);
|
||||
connect(cncat->pin(0), obj->pin(1));
|
||||
|
||||
off = 0;
|
||||
size_t concat_pin = 1;
|
||||
@@ -307,20 +308,20 @@ void cprop_functor::lpm_part_select(Design*des, NetPartSelect*obj)
|
||||
NetPartSelect*cobj = obj_set[idx];
|
||||
if (cobj->base() > off) {
|
||||
NetNet*zzz = make_const_z(des, scope, cobj->base()-off);
|
||||
connect(concat->pin(concat_pin), zzz->pin(0));
|
||||
connect(cncat->pin(concat_pin), zzz->pin(0));
|
||||
concat_pin += 1;
|
||||
off = cobj->base();
|
||||
}
|
||||
connect(concat->pin(concat_pin), cobj->pin(0));
|
||||
connect(cncat->pin(concat_pin), cobj->pin(0));
|
||||
concat_pin += 1;
|
||||
off += cobj->width();
|
||||
}
|
||||
if (off < sig_width) {
|
||||
NetNet*zzz = make_const_z(des, scope, sig_width-off);
|
||||
connect(concat->pin(concat_pin), zzz->pin(0));
|
||||
connect(cncat->pin(concat_pin), zzz->pin(0));
|
||||
concat_pin += 1;
|
||||
}
|
||||
ivl_assert(*obj, concat_pin == concat->pin_count());
|
||||
ivl_assert(*obj, concat_pin == cncat->pin_count());
|
||||
|
||||
for (size_t idx = 0 ; idx < obj_set.size() ; idx += 1) {
|
||||
delete obj_set[idx];
|
||||
@@ -392,7 +393,7 @@ void cprop_dc_functor::lpm_const(Design*, NetConst*obj)
|
||||
unsigned pin;
|
||||
clnk->cur_link(cur, pin);
|
||||
|
||||
NetNet*tmp = dynamic_cast<NetNet*>(cur);
|
||||
const NetNet*tmp = dynamic_cast<NetNet*>(cur);
|
||||
if (tmp == 0)
|
||||
continue;
|
||||
|
||||
|
||||
+43
-13
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998-2020 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2021 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -31,10 +31,13 @@
|
||||
# include "netclass.h"
|
||||
# include "netdarray.h"
|
||||
# include "netqueue.h"
|
||||
# include "netscalar.h"
|
||||
# include "netvector.h"
|
||||
# include "ivl_assert.h"
|
||||
# include "PExpr.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
static ostream& operator<< (ostream&o, NetBlock::Type t)
|
||||
{
|
||||
switch (t) {
|
||||
@@ -238,6 +241,17 @@ ostream& netqueue_t::debug_dump(ostream&fd) const
|
||||
return fd;
|
||||
}
|
||||
|
||||
ostream& netreal_t::debug_dump(ostream&fd) const
|
||||
{
|
||||
fd << "real";
|
||||
return fd;
|
||||
}
|
||||
ostream& netstring_t::debug_dump(ostream&fd) const
|
||||
{
|
||||
fd << "string";
|
||||
return fd;
|
||||
}
|
||||
|
||||
ostream& netvector_t::debug_dump(ostream&o) const
|
||||
{
|
||||
o << "netvector_t:" << type_ << (signed_? " signed" : " unsigned") << packed_dims_;
|
||||
@@ -1110,7 +1124,10 @@ void NetAssign::dump(ostream&o, unsigned ind) const
|
||||
if (const NetExpr*de = get_delay())
|
||||
o << "#(" << *de << ") ";
|
||||
|
||||
o << *rval() << ";" << endl;
|
||||
if (rval())
|
||||
o << *rval() << ";" << endl;
|
||||
else
|
||||
o << "<rval elaboration error>;" << endl;
|
||||
}
|
||||
|
||||
void NetAssignNB::dump(ostream&o, unsigned ind) const
|
||||
@@ -1128,7 +1145,10 @@ void NetAssignNB::dump(ostream&o, unsigned ind) const
|
||||
o << *event_;
|
||||
}
|
||||
|
||||
o << *rval() << ";" << endl;
|
||||
if (rval())
|
||||
o << *rval() << ";" << endl;
|
||||
else
|
||||
o << "rval elaboration error>;" << endl;
|
||||
|
||||
}
|
||||
|
||||
@@ -1273,6 +1293,9 @@ void NetEvProbe::dump_node(ostream&o, unsigned ind) const
|
||||
case NEGEDGE:
|
||||
o << "negedge ";
|
||||
break;
|
||||
case EDGE:
|
||||
o << "edge ";
|
||||
break;
|
||||
}
|
||||
o << setw(ind) << "" << "-> " << event_->name() << "; " << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
@@ -1285,6 +1308,13 @@ void NetEvTrig::dump(ostream&o, unsigned ind) const
|
||||
<< "// " << get_fileline() << endl;
|
||||
}
|
||||
|
||||
void NetEvNBTrig::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "->> " ;
|
||||
if (dly_) o << "#" << *dly_ << " ";
|
||||
o << event_->name() << "; " << "// " << get_fileline() << endl;
|
||||
}
|
||||
|
||||
void NetEvWait::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "";
|
||||
@@ -1351,9 +1381,15 @@ void NetForever::dump(ostream&o, unsigned ind) const
|
||||
|
||||
void NetForLoop::dump(ostream&fd, unsigned ind) const
|
||||
{
|
||||
fd << setw(ind) << "" << "FOR LOOP index=" << index_->name() << endl;
|
||||
fd << setw(ind) << "" << "FOR LOOP index=";
|
||||
if (index_)
|
||||
fd << index_->name();
|
||||
else
|
||||
fd << "<nil>";
|
||||
fd << endl;
|
||||
statement_->dump(fd, ind+4);
|
||||
step_statement_->dump(fd, ind+4);
|
||||
if (step_statement_)
|
||||
step_statement_->dump(fd, ind+4);
|
||||
}
|
||||
|
||||
void NetFree::dump(ostream&o, unsigned ind) const
|
||||
@@ -1465,14 +1501,8 @@ void NetScope::dump(ostream&o) const
|
||||
else
|
||||
o << " parameter ";
|
||||
|
||||
o << pp->second.type << " ";
|
||||
|
||||
if ((*pp).second.signed_flag)
|
||||
o << "signed ";
|
||||
|
||||
if ((*pp).second.msb)
|
||||
o << "[" << *(*pp).second.msb
|
||||
<< ":" << *(*pp).second.lsb << "] ";
|
||||
if (pp->second.ivl_type)
|
||||
pp->second.ivl_type->debug_dump(o);
|
||||
|
||||
o << (*pp).first << " = ";
|
||||
if (pp->second.val)
|
||||
|
||||
+4
-4
@@ -1,7 +1,7 @@
|
||||
#ifndef IVL_discipline_H
|
||||
#define IVL_discipline_H
|
||||
/*
|
||||
* Copyright (c) 2008-2014 Stephen Williams ([email protected])
|
||||
* Copyright (c) 2008-2021 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -69,9 +69,9 @@ class ivl_discipline_s : public LineInfo {
|
||||
ivl_discipline_s& operator = (const ivl_discipline_s&);
|
||||
};
|
||||
|
||||
extern map<perm_string,ivl_nature_t> natures;
|
||||
extern map<perm_string,ivl_discipline_t> disciplines;
|
||||
extern std::map<perm_string,ivl_nature_t> natures;
|
||||
extern std::map<perm_string,ivl_discipline_t> disciplines;
|
||||
// Map access function name to the nature that it accesses.
|
||||
extern map<perm_string,ivl_nature_t> access_function_nature;
|
||||
extern std::map<perm_string,ivl_nature_t> access_function_nature;
|
||||
|
||||
#endif /* IVL_discipline_H */
|
||||
|
||||
@@ -66,7 +66,7 @@ distclean: clean
|
||||
rm -f Makefile config.log
|
||||
|
||||
cppcheck: main.c
|
||||
cppcheck --enable=all --std=posix --std=c99 --std=c++03 -f $(INCLUDE_PATH) $^
|
||||
cppcheck --enable=all --std=c99 --std=c++03 -f $(INCLUDE_PATH) $^
|
||||
|
||||
Makefile: $(srcdir)/Makefile.in ../config.status
|
||||
cd ..; ./config.status --file=driver-vpi/$@
|
||||
@@ -99,7 +99,7 @@ install: all installdirs installfiles
|
||||
F = ./iverilog-vpi@EXEEXT@
|
||||
|
||||
installfiles: $(F) | installdirs
|
||||
$(INSTALL_PROGRAM) ./iverilog-vpi@EXEEXT@ "$(bindir)/iverilog-vpi$(suffix)@EXEEXT@"
|
||||
$(INSTALL_PROGRAM) ./iverilog-vpi@EXEEXT@ "$(DESTDIR)$(bindir)/iverilog-vpi$(suffix)@EXEEXT@"
|
||||
ifeq (@WIN32@,yes)
|
||||
ifneq ($(HOSTCC),$(CC))
|
||||
$(INSTALL_PROGRAM) $(shell $(HOSTCC) --print-file-name=libwinpthread-1.dll) "$(DESTDIR)$(bindir)"
|
||||
@@ -109,7 +109,7 @@ endif
|
||||
endif
|
||||
|
||||
installdirs: $(srcdir)/../mkinstalldirs
|
||||
$(srcdir)/../mkinstalldirs "$(bindir)"
|
||||
$(srcdir)/../mkinstalldirs "$(DESTDIR)$(bindir)"
|
||||
|
||||
uninstall:
|
||||
rm -f $(bindir)/iverilog-vpi$(suffix)@EXEEXT@
|
||||
rm -f $(DESTDIR)$(bindir)/iverilog-vpi$(suffix)@EXEEXT@
|
||||
|
||||
+7
-7
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2015-2022 Martin Whitaker
|
||||
* Copyright (c) 2002 Gus Baldauf ([email protected])
|
||||
* Copyright (c) 2015 Martin Whitaker
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -241,13 +241,13 @@ static int GetRegistryKey(char *key, char **value)
|
||||
|
||||
lrv = RegQueryValueEx(hkKey, key, NULL, ®KeyType, NULL, ®KeySize);
|
||||
if ((lrv != ERROR_SUCCESS) || (regKeyType != REG_SZ) || (!regKeySize)) {
|
||||
lrv = RegCloseKey(hkKey);
|
||||
RegCloseKey(hkKey);
|
||||
return 0;
|
||||
}
|
||||
|
||||
regKeyBuffer = (char *) malloc(regKeySize+1);
|
||||
if (!regKeyBuffer) {
|
||||
lrv = RegCloseKey(hkKey);
|
||||
RegCloseKey(hkKey);
|
||||
fprintf(stderr, "error: out of memory\n");
|
||||
myExit(4);
|
||||
}
|
||||
@@ -257,7 +257,7 @@ static int GetRegistryKey(char *key, char **value)
|
||||
lrv = RegQueryValueEx(hkKey, key, NULL, ®KeyType,
|
||||
(unsigned char *) regKeyBuffer, ®KeySize);
|
||||
if ((lrv != ERROR_SUCCESS) || (regKeyType != REG_SZ) || (!regKeySize)) {
|
||||
lrv = RegCloseKey(hkKey);
|
||||
RegCloseKey(hkKey);
|
||||
free(regKeyBuffer);
|
||||
return 0;
|
||||
}
|
||||
@@ -564,10 +564,10 @@ static void compile(char *pSource, char *pFlags, char **pObject, int *compile_er
|
||||
assignn(&src, ptr1, len);
|
||||
|
||||
/* Build the object file name */
|
||||
ostart = strrchr(ptr1, '/');
|
||||
if (ostart == NULL) ostart = ptr1;
|
||||
ostart = strrchr(src, '/');
|
||||
if (ostart == NULL) ostart = src;
|
||||
else ostart += 1;
|
||||
olen = strrchr(ptr1, '.') - ostart;
|
||||
olen = strrchr(ostart, '.') - ostart;
|
||||
assignn(&obj, ostart, olen);
|
||||
append(&obj, ".o");
|
||||
|
||||
|
||||
+3
-2
@@ -67,10 +67,11 @@ distclean: clean
|
||||
rm -f Makefile config.log
|
||||
|
||||
cppcheck: $(O:.o=.c)
|
||||
cppcheck --enable=all --std=posix --std=c99 --std=c++03 -f \
|
||||
cppcheck --enable=all --std=c99 --std=c++03 -f \
|
||||
-UYY_USER_INIT \
|
||||
-UYYPARSE_PARAM -UYYPRINT -Ushort -Uyyoverflow \
|
||||
-UYYTYPE_INT8 -UYYTYPE_INT16 -UYYTYPE_UINT8 -UYYTYPE_UINT16 \
|
||||
-UYYSTYPE -U__SIZE_TYPE__ -Umalloc -Usize_t -Ufree \
|
||||
$(INCLUDE_PATH) $^
|
||||
|
||||
Makefile: $(srcdir)/Makefile.in ../config.status
|
||||
@@ -94,7 +95,7 @@ cfparse%c cfparse%h: $(srcdir)/cfparse%y
|
||||
mv $*.d dep
|
||||
|
||||
main.o: main.c globals.h $(srcdir)/../version_base.h ../version_tag.h Makefile
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) @DEPENDENCY_FLAG@ -c -DIVL_ROOT='"@libdir@/ivl$(suffix)"' -DIVL_SUFFIX='"$(suffix)"' -DIVL_INC='"@includedir@"' -DIVL_LIB='"@libdir@"' -DDLLIB='"@DLLIB@"' $(srcdir)/main.c
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) @DEPENDENCY_FLAG@ -c -DIVL_ROOT='"@libdir@/ivl$(suffix)"' -DIVL_SUFFIX='"$(suffix)"' -DIVL_INC='"@includedir@"' -DIVL_LIB='"@libdir@"' -DDLLIB='"@DLLIB@"' -DIVL_INCLUDE_INSTALL_DIR="\"$(realpath $(DESTDIR)/$(includedir))\"" $(srcdir)/main.c
|
||||
mv $*.d dep
|
||||
|
||||
cflexor.o: cflexor.c cfparse.h
|
||||
|
||||
+44
-13
@@ -4,7 +4,7 @@
|
||||
|
||||
%{
|
||||
/*
|
||||
* Copyright (c) 2001-2017 Stephen Williams ([email protected])
|
||||
* Copyright (c) 2001-2021 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -45,6 +45,17 @@ typedef struct t_cmdfile {
|
||||
s_cmdfile cmdfile_stack[MAX_CMDFILE_DEPTH];
|
||||
int cmdfile_stack_ptr = 0;
|
||||
|
||||
# define PROCESS_EOF \
|
||||
if (--cmdfile_stack_ptr < 0) { \
|
||||
free(current_file); \
|
||||
yyterminate(); \
|
||||
} else { \
|
||||
yy_delete_buffer(YY_CURRENT_BUFFER); \
|
||||
yy_switch_to_buffer(cmdfile_stack[cmdfile_stack_ptr].buffer); \
|
||||
free(current_file); \
|
||||
current_file = cmdfile_stack[cmdfile_stack_ptr].cmdfile; \
|
||||
}
|
||||
|
||||
%}
|
||||
|
||||
%x CCOMMENT
|
||||
@@ -59,12 +70,26 @@ int cmdfile_stack_ptr = 0;
|
||||
<LCOMMENT>. { yymore(); }
|
||||
<LCOMMENT>\n { cflloc.first_line += 1; BEGIN(comment_enter); }
|
||||
|
||||
<LCOMMENT><<EOF>> {
|
||||
fprintf(stderr, "%s:%u: ERROR: Comment not terminated.\n",
|
||||
current_file, cflloc.first_line);
|
||||
command_file_errors += 1;
|
||||
BEGIN(0);
|
||||
PROCESS_EOF }
|
||||
|
||||
/* Accept C style comments. */
|
||||
"/*" { comment_enter = YY_START; BEGIN(CCOMMENT); }
|
||||
<CCOMMENT>. { yymore(); }
|
||||
<CCOMMENT>\n { cflloc.first_line += 1; yymore(); }
|
||||
<CCOMMENT>"*/" { BEGIN(comment_enter); }
|
||||
|
||||
<CCOMMENT><<EOF>> {
|
||||
fprintf(stderr, "%s:%u: ERROR: Comment not terminated.\n",
|
||||
current_file, cflloc.first_line);
|
||||
command_file_errors += 1;
|
||||
BEGIN(0);
|
||||
PROCESS_EOF }
|
||||
|
||||
/* Accept shell type comments. */
|
||||
^"#".* { ; }
|
||||
|
||||
@@ -119,6 +144,13 @@ int cmdfile_stack_ptr = 0;
|
||||
cflloc.first_line += 1;
|
||||
BEGIN(0); }
|
||||
|
||||
<PLUS_ARGS><<EOF>> {
|
||||
BEGIN(0);
|
||||
fprintf(stderr, "%s:%u: ERROR: Plusargs statement not terminated.\n",
|
||||
current_file, cflloc.first_line);
|
||||
command_file_errors += 1;
|
||||
PROCESS_EOF }
|
||||
|
||||
/* Notice the -a flag. */
|
||||
"-a" { return TOK_Da; }
|
||||
|
||||
@@ -159,21 +191,19 @@ int cmdfile_stack_ptr = 0;
|
||||
cflval.text = trim_trailing_white(yytext, 0);
|
||||
BEGIN(0);
|
||||
return TOK_STRING; }
|
||||
<FILE_NAME><<EOF>> {
|
||||
cflval.text = trim_trailing_white(yytext, 0);
|
||||
BEGIN(0);
|
||||
fprintf(stderr, "%s:%u: ERROR: File name not terminated.\n",
|
||||
current_file, cflloc.first_line);
|
||||
command_file_errors += 1;
|
||||
PROCESS_EOF }
|
||||
|
||||
/* Fallback match. */
|
||||
. { return yytext[0]; }
|
||||
|
||||
/* At the end of file switch back to the previous buffer. */
|
||||
<<EOF>> {
|
||||
if (--cmdfile_stack_ptr < 0) {
|
||||
free(current_file);
|
||||
yyterminate();
|
||||
} else {
|
||||
yy_delete_buffer(YY_CURRENT_BUFFER);
|
||||
yy_switch_to_buffer(cmdfile_stack[cmdfile_stack_ptr].buffer);
|
||||
free(current_file);
|
||||
current_file = cmdfile_stack[cmdfile_stack_ptr].cmdfile;
|
||||
} }
|
||||
<<EOF>> { PROCESS_EOF }
|
||||
|
||||
%%
|
||||
|
||||
@@ -203,7 +233,7 @@ void switch_to_command_file(const char *file)
|
||||
|
||||
if (cmdfile_stack_ptr >= MAX_CMDFILE_DEPTH) {
|
||||
fprintf(stderr, "Error: command files nested too deeply (%d) "
|
||||
"at %s:%d.\n", MAX_CMDFILE_DEPTH, current_file,
|
||||
"at %s:%u.\n", MAX_CMDFILE_DEPTH, current_file,
|
||||
cflloc.first_line);
|
||||
exit(1);
|
||||
}
|
||||
@@ -230,7 +260,7 @@ void switch_to_command_file(const char *file)
|
||||
yyin = fopen(path, "r");
|
||||
if (yyin == NULL) {
|
||||
fprintf(stderr, "Error: unable to read nested command file (%s) "
|
||||
"at %s:%d.\n", path, current_file, cflloc.first_line);
|
||||
"at %s:%u.\n", path, current_file, cflloc.first_line);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -241,6 +271,7 @@ void switch_to_command_file(const char *file)
|
||||
|
||||
void cfreset(FILE*fd, const char*path)
|
||||
{
|
||||
command_file_errors = 0;
|
||||
yyin = fd;
|
||||
yyrestart(fd);
|
||||
current_file = strdup(path);
|
||||
|
||||
@@ -268,8 +268,11 @@ skip_arg : TOK_PLUSARG
|
||||
|
||||
%%
|
||||
|
||||
int command_file_errors = 0;
|
||||
|
||||
int yyerror(const char*msg)
|
||||
{
|
||||
(void)msg; /* Parameter is not used. */
|
||||
command_file_errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -21,6 +21,9 @@
|
||||
|
||||
# include <stddef.h>
|
||||
|
||||
/* Count errors in the command file. */
|
||||
extern int command_file_errors;
|
||||
|
||||
/* This is the integer-width argument that will be passed to ivl. */
|
||||
extern unsigned integer_width;
|
||||
|
||||
|
||||
+13
-5
@@ -1,10 +1,10 @@
|
||||
.TH iverilog 1 "Aug 10th, 2020" "" "Version %M.%n%E"
|
||||
.TH iverilog 1 "Jan 14th, 2021" "" "Version %M.%n%E"
|
||||
.SH NAME
|
||||
iverilog - Icarus Verilog compiler
|
||||
|
||||
.SH SYNOPSIS
|
||||
.B iverilog
|
||||
[\-EiSuVv] [\-Bpath] [\-ccmdfile|\-fcmdfile] [\-Dmacro[=defn]]
|
||||
[\-EiRSuVv] [\-Bpath] [\-ccmdfile|\-fcmdfile] [\-Dmacro[=defn]]
|
||||
[\-Pparameter=value] [\-pflag=value] [\-dname]
|
||||
[\-g1995\:|\-g2001\:|\-g2005\:|\-g2005-sv\:|\-g2009\:|\-g2012\:|\-g<feature>]
|
||||
[\-Iincludedir] [\-Lmoduledir] [\-mmodule] [\-M[mode=]file] [\-Nfile]
|
||||
@@ -122,7 +122,8 @@ practice in the past to only specify the range for the net/register
|
||||
declaration and some tools still allow this. By default any mismatch is
|
||||
reported as a error. Using \fB\-gno\-io\-range\-error\fP will produce a
|
||||
warning instead of a fatal error for the case of a vectored net/register
|
||||
and a scalar port declaration.
|
||||
and a scalar port declaration. This warning is included in the
|
||||
\fBanachronisms\fP category.
|
||||
.TP 8
|
||||
.B -gstrict-ca-eval\fI|\fP-gno-strict-ca-eval
|
||||
The standard requires that if any input to a continuous assignment
|
||||
@@ -271,6 +272,9 @@ indirectly execute the compiler output file.
|
||||
.B -V
|
||||
Print the version of the compiler, and exit.
|
||||
.TP 8
|
||||
.B -R
|
||||
Print the runtime paths of the compiler, and exit.
|
||||
.TP 8
|
||||
.B -W\fIclass\fP
|
||||
Turn on different classes of warnings. See the \fBWARNING TYPES\fP
|
||||
section below for descriptions of the different warning groups. If
|
||||
@@ -582,9 +586,13 @@ The following macros are predefined by the compiler:
|
||||
.B __ICARUS__ = 1
|
||||
This is always defined when compiling with Icarus Verilog.
|
||||
|
||||
.TP 8
|
||||
.B __ICARUS_SYNTH__ = 1
|
||||
This is defined when synthesis is enabled.
|
||||
|
||||
.TP 8
|
||||
.B __VAMS_ENABLE__ = 1
|
||||
This is defined if Verilog\-AMS is enabled.
|
||||
This is defined when Verilog\-AMS is enabled.
|
||||
|
||||
.SH ENVIRONMENT
|
||||
.PP
|
||||
@@ -633,7 +641,7 @@ Tips on using, debugging, and developing the compiler can be found at
|
||||
|
||||
.SH COPYRIGHT
|
||||
.nf
|
||||
Copyright \(co 2002\-2020 Stephen Williams
|
||||
Copyright \(co 2002\-2021 Stephen Williams
|
||||
|
||||
This document can be freely redistributed according to the terms of the
|
||||
GNU General Public License version 2.0
|
||||
|
||||
+33
-17
@@ -1,6 +1,6 @@
|
||||
const char COPYRIGHT[] =
|
||||
"Copyright (c) 2000-2021 Stephen Williams ([email protected])";
|
||||
/*
|
||||
* Copyright (c) 2000-2020 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
@@ -38,7 +38,7 @@ const char NOTICE[] =
|
||||
;
|
||||
|
||||
const char HELP[] =
|
||||
"Usage: iverilog [-EiSuvV] [-B base] [-c cmdfile|-f cmdfile]\n"
|
||||
"Usage: iverilog [-EiRSuvV] [-B base] [-c cmdfile|-f cmdfile]\n"
|
||||
" [-g1995|-g2001|-g2005|-g2005-sv|-g2009|-g2012] [-g<feature>]\n"
|
||||
" [-D macro[=defn]] [-I includedir] [-L moduledir]\n"
|
||||
" [-M [mode=]depfile] [-m module]\n"
|
||||
@@ -184,7 +184,7 @@ int verbose_flag = 0;
|
||||
FILE *fp;
|
||||
|
||||
char line[MAXSIZE];
|
||||
char tmp[MAXSIZE];
|
||||
char tmp[MAXSIZE+24];
|
||||
|
||||
static char ivl_root[MAXSIZE];
|
||||
|
||||
@@ -355,15 +355,15 @@ static int t_version_only(void)
|
||||
|
||||
static void build_preprocess_command(int e_flag)
|
||||
{
|
||||
snprintf(tmp, sizeof tmp, "%s%civlpp %s%s%s -F\"%s\" -f\"%s\" -p\"%s\"%s",
|
||||
snprintf(tmp, sizeof tmp, "%s%civlpp%s%s%s -F\"%s\" -f\"%s\" -p\"%s\"%s",
|
||||
ivlpp_dir, sep,
|
||||
verbose_flag ? " -v" : "",
|
||||
e_flag ? "" : " -L",
|
||||
strchr(warning_flags, 'r') ? " -Wredef-all " :
|
||||
strchr(warning_flags, 'R') ? " -Wredef-chg " : "",
|
||||
strchr(warning_flags, 'r') ? " -Wredef-all" :
|
||||
strchr(warning_flags, 'R') ? " -Wredef-chg" : "",
|
||||
defines_path, source_path,
|
||||
compiled_defines_path,
|
||||
e_flag ? "" : " | ");
|
||||
e_flag ? "" : " |");
|
||||
}
|
||||
|
||||
static int t_preprocess_only(void)
|
||||
@@ -382,7 +382,6 @@ static int t_preprocess_only(void)
|
||||
snprintf(tmp, sizeof tmp, " > \"%s\"", opath);
|
||||
cmd = realloc(cmd, ncmd+strlen(tmp)+1);
|
||||
strcpy(cmd+ncmd, tmp);
|
||||
ncmd += strlen(tmp);
|
||||
}
|
||||
|
||||
if (verbose_flag)
|
||||
@@ -483,7 +482,6 @@ static int t_compile(void)
|
||||
rc = strlen(tmp);
|
||||
cmd = realloc(cmd, ncmd+rc+1);
|
||||
strcpy(cmd+ncmd, tmp);
|
||||
ncmd += rc;
|
||||
|
||||
|
||||
if (verbose_flag)
|
||||
@@ -1046,7 +1044,7 @@ static void find_ivl_root(void)
|
||||
if the user has overridden $(bindir) or $(libdir), but there's
|
||||
not a lot we can do in that case.
|
||||
*/
|
||||
#ifdef __MINGW32__
|
||||
#if defined(__MINGW32__)
|
||||
char tmppath[MAXSIZE];
|
||||
len = GetModuleFileName(NULL, tmppath, sizeof tmppath);
|
||||
if (len >= (ssize_t) sizeof ivl_root) {
|
||||
@@ -1054,6 +1052,9 @@ static void find_ivl_root(void)
|
||||
}
|
||||
/* Convert to a short name to remove any embedded spaces. */
|
||||
len = GetShortPathName(tmppath, ivl_root, sizeof ivl_root);
|
||||
#elif defined(__APPLE__)
|
||||
uint32_t size = sizeof ivl_root;
|
||||
len = _NSGetExecutablePath(ivl_root, &size) + 1;
|
||||
#else
|
||||
len = readlink("/proc/self/exe", ivl_root, sizeof ivl_root);
|
||||
#endif
|
||||
@@ -1061,7 +1062,11 @@ static void find_ivl_root(void)
|
||||
find_ivl_root_failed("command path exceeds size of string buffer.");
|
||||
}
|
||||
if (len <= 0) {
|
||||
find_ivl_root_failed("couldn't get command path from OS.");
|
||||
// We've failed, but we may yet find a -B option on the command line.
|
||||
// Use the built-in path so the user sees a sensible error message.
|
||||
assert(strlen(IVL_ROOT) < sizeof ivl_root);
|
||||
strcpy(ivl_root, IVL_ROOT);
|
||||
return;
|
||||
}
|
||||
s = strrchr(ivl_root, sep);
|
||||
if (s == 0) {
|
||||
@@ -1083,6 +1088,10 @@ static void find_ivl_root(void)
|
||||
strcat(ivl_root, ivl_lib_suffix);
|
||||
}
|
||||
|
||||
static void print_runtime_paths(void) {
|
||||
printf("includedir: %s\n", IVL_INCLUDE_INSTALL_DIR);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int e_flag = 0;
|
||||
@@ -1116,8 +1125,6 @@ int main(int argc, char **argv)
|
||||
}
|
||||
|
||||
fprintf(defines_file, "D:__ICARUS__=1\n");
|
||||
if (strcmp(gen_verilog_ams,"verilog-ams") == 0)
|
||||
fprintf(defines_file, "D:__VAMS_ENABLE__=1\n");
|
||||
|
||||
/* Create another temporary file for passing configuration
|
||||
information to ivl. */
|
||||
@@ -1154,7 +1161,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
while ((opt = getopt(argc, argv, "B:c:D:d:Ef:g:hl:I:iL:M:m:N:o:P:p:Ss:T:t:uvVW:y:Y:")) != EOF) {
|
||||
while ((opt = getopt(argc, argv, "B:c:D:d:Ef:g:hl:I:iL:M:m:N:o:P:p:RSs:T:t:uvVW:y:Y:")) != EOF) {
|
||||
|
||||
switch (opt) {
|
||||
case 'B':
|
||||
@@ -1241,6 +1248,10 @@ int main(int argc, char **argv)
|
||||
opath = optarg;
|
||||
break;
|
||||
|
||||
case 'R':
|
||||
print_runtime_paths();
|
||||
return 0;
|
||||
|
||||
case 'S':
|
||||
synth_flag = 1;
|
||||
break;
|
||||
@@ -1301,6 +1312,11 @@ int main(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
if (strcmp(gen_verilog_ams,"verilog-ams") == 0)
|
||||
fprintf(defines_file, "D:__VAMS_ENABLE__=1\n");
|
||||
if (synth_flag)
|
||||
fprintf(defines_file, "D:__ICARUS_SYNTH__=1\n");
|
||||
|
||||
if (vpi_dir == 0)
|
||||
vpi_dir = base;
|
||||
if (ivlpp_dir == 0)
|
||||
@@ -1310,7 +1326,7 @@ int main(int argc, char **argv)
|
||||
|
||||
if (version_flag || verbose_flag) {
|
||||
printf("Icarus Verilog version " VERSION " (" VERSION_TAG ")\n\n");
|
||||
printf("Copyright 1998-2020 Stephen Williams\n\n");
|
||||
printf("%s\n\n", COPYRIGHT);
|
||||
puts(NOTICE);
|
||||
}
|
||||
|
||||
@@ -1379,7 +1395,7 @@ int main(int argc, char **argv)
|
||||
|
||||
cfreset(fp, command_filename);
|
||||
rc = cfparse();
|
||||
if (rc != 0) {
|
||||
if (rc != 0 || command_file_errors > 0) {
|
||||
fprintf(stderr, "%s: parsing failed in base command "
|
||||
"file %s.\n", argv[0], command_filename);
|
||||
return 1;
|
||||
|
||||
+4
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2019 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2021 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -24,6 +24,8 @@
|
||||
# include <cstdlib>
|
||||
# include "ivl_assert.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
NetEAccess* NetEAccess::dup_expr() const
|
||||
{
|
||||
NetEAccess*tmp = new NetEAccess(branch_, nature_);
|
||||
@@ -146,7 +148,7 @@ NetEConst* NetEConst::dup_expr() const
|
||||
|
||||
NetEConstEnum* NetEConstEnum::dup_expr() const
|
||||
{
|
||||
NetEConstEnum*tmp = new NetEConstEnum(scope_, name_, enum_set_, value());
|
||||
NetEConstEnum*tmp = new NetEConstEnum(name_, enum_set_, value());
|
||||
ivl_assert(*this, tmp);
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
|
||||
-166
@@ -1,166 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2003 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
# include "config.h"
|
||||
|
||||
/*
|
||||
* The elaborate_anet methods elaborate expressions that are intended
|
||||
* to be the left side of procedural continuous assignments.
|
||||
*/
|
||||
|
||||
# include "PExpr.h"
|
||||
# include "netlist.h"
|
||||
# include "netmisc.h"
|
||||
# include <iostream>
|
||||
|
||||
NetNet* PExpr::elaborate_anet(Design*des, NetScope*scope) const
|
||||
{
|
||||
cerr << get_line() << ": error: Invalid expression on left side "
|
||||
<< "of procedural continuous assignment." << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
NetNet* PEConcat::elaborate_anet(Design*des, NetScope*scope) const
|
||||
{
|
||||
if (repeat_) {
|
||||
cerr << get_line() << ": error: Repeat concatenations make "
|
||||
"no sense in l-value expressions. I refuse." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
svector<NetNet*>nets (parms_.count());
|
||||
unsigned pins = 0;
|
||||
unsigned errors = 0;
|
||||
|
||||
for (unsigned idx = 0 ; idx < nets.count() ; idx += 1) {
|
||||
|
||||
if (parms_[idx] == 0) {
|
||||
cerr << get_line() << ": error: Empty expressions "
|
||||
<< "not allowed in concatenations." << endl;
|
||||
errors += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
nets[idx] = parms_[idx]->elaborate_anet(des, scope);
|
||||
if (nets[idx] == 0)
|
||||
errors += 1;
|
||||
else
|
||||
pins += nets[idx]->pin_count();
|
||||
}
|
||||
|
||||
/* If any of the sub expressions failed to elaborate, then
|
||||
delete all those that did and abort myself. */
|
||||
if (errors) {
|
||||
for (unsigned idx = 0 ; idx < nets.count() ; idx += 1) {
|
||||
if (nets[idx]) delete nets[idx];
|
||||
}
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Make the temporary signal that connects to all the
|
||||
operands, and connect it up. Scan the operands of the
|
||||
concat operator from least significant to most significant,
|
||||
which is opposite from how they are given in the list.
|
||||
|
||||
Allow for a repeat count other than 1 by repeating the
|
||||
connect loop as many times as necessary. */
|
||||
|
||||
NetNet*osig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT_REG, pins);
|
||||
/* Assume that all the data types are the same. */
|
||||
osig->data_type(nets[0]->data_type());
|
||||
|
||||
pins = 0;
|
||||
for (unsigned idx = nets.count() ; idx > 0 ; idx -= 1) {
|
||||
NetNet*cur = nets[idx-1];
|
||||
assert(cur->data_type() == osig->data_type());
|
||||
for (unsigned pin = 0; pin < cur->pin_count(); pin += 1) {
|
||||
connect(osig->pin(pins), cur->pin(pin));
|
||||
pins += 1;
|
||||
}
|
||||
}
|
||||
|
||||
osig->local_flag(true);
|
||||
return osig;
|
||||
}
|
||||
|
||||
NetNet* PEIdent::elaborate_anet(Design*des, NetScope*scope) const
|
||||
{
|
||||
assert(scope);
|
||||
|
||||
NetNet* sig = 0;
|
||||
NetMemory* mem = 0;
|
||||
const NetExpr*par = 0;
|
||||
NetEvent* eve = 0;
|
||||
|
||||
symbol_search(this, des, scope, path_, sig, mem, par, eve);
|
||||
|
||||
|
||||
if (mem != 0) {
|
||||
cerr << get_line() << ": error: memories not allowed "
|
||||
<< "on left side of procedural continuous "
|
||||
<< "assignment." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (eve != 0) {
|
||||
cerr << get_line() << ": error: named events not allowed "
|
||||
<< "on left side of procedural continuous "
|
||||
<< "assignment." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sig == 0) {
|
||||
cerr << get_line() << ": error: reg ``" << path_ << "'' "
|
||||
<< "is undefined in this scope." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (sig->type()) {
|
||||
case NetNet::REG:
|
||||
case NetNet::IMPLICIT_REG:
|
||||
break;
|
||||
|
||||
default:
|
||||
cerr << get_line() << ": error: " << path_ << " is not "
|
||||
<< "a reg in this context." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(sig);
|
||||
|
||||
if (msb_ || lsb_) {
|
||||
|
||||
cerr << get_line() << ": error: bit/part selects not allowed "
|
||||
<< "on left side of procedural continuous assignment."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return sig;
|
||||
}
|
||||
|
||||
+1645
-818
File diff suppressed because it is too large
Load Diff
+116
-63
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2019 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2021 Stephen Williams (steve@icarus.com)
|
||||
* Copyright CERN 2012-2013 / Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
@@ -36,6 +36,8 @@
|
||||
# include <climits>
|
||||
# include "ivl_assert.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
/*
|
||||
* These methods generate a NetAssign_ object for the l-value of the
|
||||
* assignment. This is common code for the = and <= statements.
|
||||
@@ -157,9 +159,6 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
||||
bool is_cassign,
|
||||
bool is_force) const
|
||||
{
|
||||
NetNet* reg = 0;
|
||||
const NetExpr*par = 0;
|
||||
NetEvent* eve = 0;
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PEIdent::elaborate_lval: "
|
||||
@@ -180,25 +179,12 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
||||
ivl_assert(*this, use_scope);
|
||||
}
|
||||
|
||||
/* Try to find the base part of the path that names the
|
||||
variable. The remainer is the member path. For example, if
|
||||
the path is a.b.c.d, and a.b is the path to a variable,
|
||||
then a.b becomes the base_path and c.d becomes the
|
||||
member_path. If we cannot find the variable with any
|
||||
prefix, then the base_path will be empty after this loop
|
||||
and reg will remain nil. */
|
||||
pform_name_t base_path = path_;
|
||||
pform_name_t member_path;
|
||||
while (reg == 0 && base_path.size() > 0) {
|
||||
symbol_search(this, des, use_scope, base_path, reg, par, eve);
|
||||
// Found it!
|
||||
if (reg != 0) break;
|
||||
// Not found. Try to pop another name off the base_path
|
||||
// and push it to the front of the member_path.
|
||||
member_path.push_front( base_path.back() );
|
||||
base_path.pop_back();
|
||||
}
|
||||
symbol_search_results sr;
|
||||
symbol_search(this, des, use_scope, path_, &sr);
|
||||
|
||||
NetNet *reg = sr.net;
|
||||
pform_name_t &base_path = sr.path_head;
|
||||
pform_name_t &member_path = sr.path_tail;
|
||||
|
||||
/* The l-value must be a variable. If not, then give up and
|
||||
print a useful error message. */
|
||||
@@ -222,18 +208,28 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
||||
ivl_assert(*this, reg);
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PEIdent::elaborate_lval: "
|
||||
cerr << get_fileline() << ": " << __func__ << ": "
|
||||
<< "Found l-value path_=" << path_
|
||||
<< " as reg=" << reg->name()
|
||||
<< " as reg=" << reg->name() << endl;
|
||||
cerr << get_fileline() << ": " << __func__ << ": "
|
||||
<< "reg->type()=" << reg->type()
|
||||
<< ", reg->unpacked_dimensions()=" << reg->unpacked_dimensions()
|
||||
<< endl;
|
||||
if (reg->net_type())
|
||||
cerr << get_fileline() << ": " << __func__ << ": "
|
||||
<< "reg->net_type()=" << *reg->net_type() << endl;
|
||||
else
|
||||
cerr << get_fileline() << ": " << __func__ << ": "
|
||||
<< "reg->net_type()=<nil>" << endl;
|
||||
cerr << get_fileline() << ": " << __func__ << ": "
|
||||
<< " base_path=" << base_path
|
||||
<< ", member_path=" << member_path
|
||||
<< " unpacked_dimensions()=" << reg->unpacked_dimensions() << endl;
|
||||
<< endl;
|
||||
}
|
||||
|
||||
// We are processing the tail of a string of names. For
|
||||
// example, the Verilog may be "a.b.c", so we are processing
|
||||
// "c" at this point. (Note that if method_name is not nil,
|
||||
// then this is "a.b.c.method" and "a.b.c" is a struct or class.)
|
||||
// "c" at this point.
|
||||
const name_component_t&name_tail = path_.back();
|
||||
|
||||
// Use the last index to determine what kind of select
|
||||
@@ -247,12 +243,18 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
||||
use_sel = name_tail.index.back().sel;
|
||||
|
||||
// Special case: The l-value is an entire memory, or array
|
||||
// slice. This is, in fact, an error in l-values. Detect the
|
||||
// situation by noting if the index count is less than the
|
||||
// array dimensions (unpacked).
|
||||
// slice. Detect the situation by noting if the index count
|
||||
// is less than the array dimensions (unpacked).
|
||||
if (reg->unpacked_dimensions() > name_tail.index.size()) {
|
||||
cerr << get_fileline() << ": error: Cannot assign to array "
|
||||
<< path_ << ". Did you forget a word index?" << endl;
|
||||
if (gn_system_verilog()) {
|
||||
cerr << get_fileline() << ": sorry: Assignment to an entire"
|
||||
" array or to an array slice is not yet supported."
|
||||
<< endl;
|
||||
} else {
|
||||
cerr << get_fileline() << ": error: Assignment to an entire"
|
||||
" array or to an array slice requires SystemVerilog."
|
||||
<< endl;
|
||||
}
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
@@ -275,7 +277,7 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
||||
|
||||
// If we find that the matched variable is a packed struct,
|
||||
// then we can handled it with the net_packed_member_ method.
|
||||
if (reg->struct_type() && member_path.size() > 0) {
|
||||
if (reg->struct_type() && !member_path.empty()) {
|
||||
NetAssign_*lv = new NetAssign_(reg);
|
||||
elaborate_lval_net_packed_member_(des, use_scope, lv, member_path);
|
||||
return lv;
|
||||
@@ -283,8 +285,9 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
||||
|
||||
// If the variable is a class object, then handle it with the
|
||||
// net_class_member_ method.
|
||||
if (reg->class_type() && member_path.size() > 0 && gn_system_verilog()) {
|
||||
NetAssign_*lv = elaborate_lval_net_class_member_(des, use_scope, reg, member_path);
|
||||
const netclass_t *class_type = dynamic_cast<const netclass_t *>(sr.type);
|
||||
if (class_type && !member_path.empty() && gn_system_verilog()) {
|
||||
NetAssign_*lv = elaborate_lval_net_class_member_(des, use_scope, class_type, reg, member_path);
|
||||
return lv;
|
||||
}
|
||||
|
||||
@@ -292,7 +295,7 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
||||
// Past this point, we should have taken care of the cases
|
||||
// where the name is a member/method of a struct/class.
|
||||
// XXXX ivl_assert(*this, method_name.nil());
|
||||
ivl_assert(*this, member_path.size() == 0);
|
||||
ivl_assert(*this, member_path.empty());
|
||||
|
||||
bool need_const_idx = is_cassign || is_force || (reg->type()==NetNet::UNRESOLVED_WIRE);
|
||||
|
||||
@@ -375,10 +378,17 @@ NetAssign_* PEIdent::elaborate_lval_method_class_member_(Design*des,
|
||||
if (pidx < 0)
|
||||
return 0;
|
||||
|
||||
property_qualifier_t qual = class_type->get_prop_qual(pidx);
|
||||
|
||||
// Static properties are handled as normal signals. Regular symbol
|
||||
// search will find it.
|
||||
if (qual.test_static())
|
||||
return 0;
|
||||
|
||||
NetScope*scope_method = find_method_containing_scope(*this, scope);
|
||||
ivl_assert(*this, scope_method);
|
||||
|
||||
NetNet*this_net = scope_method->find_signal(perm_string::literal("@"));
|
||||
NetNet*this_net = scope_method->find_signal(perm_string::literal(THIS_TOKEN));
|
||||
if (this_net == 0) {
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<< "Unable to find 'this' port of " << scope_path(scope_method)
|
||||
@@ -410,7 +420,6 @@ NetAssign_* PEIdent::elaborate_lval_method_class_member_(Design*des,
|
||||
// Detect assignment to constant properties. Note that the
|
||||
// initializer constructor MAY assign to constant properties,
|
||||
// as this is how the property gets its value.
|
||||
property_qualifier_t qual = class_type->get_prop_qual(pidx);
|
||||
if (qual.test_const()) {
|
||||
if (class_type->get_prop_initialized(pidx)) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
@@ -467,7 +476,7 @@ NetAssign_* PEIdent::elaborate_lval_method_class_member_(Design*des,
|
||||
}
|
||||
|
||||
NetAssign_*this_lval = new NetAssign_(this_net);
|
||||
this_lval->set_property(member_name);
|
||||
this_lval->set_property(member_name, pidx);
|
||||
if (canon_index) this_lval->set_word(canon_index);
|
||||
|
||||
return this_lval;
|
||||
@@ -853,12 +862,20 @@ bool PEIdent::elaborate_lval_net_part_(Design*des,
|
||||
// If there are fewer indices then there are packed
|
||||
// dimensions, then this is a range of slices. Calculate
|
||||
// it into a big slice.
|
||||
bool lrc;
|
||||
bool lrc, mrc;
|
||||
unsigned long tmp_lwid, tmp_mwid;
|
||||
lrc = reg->sb_to_slice(prefix_indices,lsb, loff, tmp_lwid);
|
||||
ivl_assert(*this, lrc);
|
||||
lrc = reg->sb_to_slice(prefix_indices,msb, moff, tmp_mwid);
|
||||
ivl_assert(*this, lrc);
|
||||
lrc = reg->sb_to_slice(prefix_indices, lsb, loff, tmp_lwid);
|
||||
mrc = reg->sb_to_slice(prefix_indices, msb, moff, tmp_mwid);
|
||||
if (!mrc || !lrc) {
|
||||
cerr << get_fileline() << ": error: ";
|
||||
cerr << "Part-select [" << msb << ":" << lsb;
|
||||
cerr << "] exceeds the declared bounds for ";
|
||||
cerr << reg->name();
|
||||
if (reg->unpacked_dimensions() > 0) cerr << "[]";
|
||||
cerr << "." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (loff < moff) {
|
||||
moff = moff + tmp_mwid - 1;
|
||||
@@ -938,21 +955,58 @@ bool PEIdent::elaborate_lval_net_idx_(Design*des,
|
||||
// we will handle it in the code generator.
|
||||
if (base_c->value().is_defined()) {
|
||||
long lsv = base_c->value().as_long();
|
||||
long offset = 0;
|
||||
long rel_base = 0;
|
||||
// Get the signal range.
|
||||
const vector<netrange_t>&packed = reg->packed_dims();
|
||||
ivl_assert(*this, packed.size() == prefix_indices.size()+1);
|
||||
if (prefix_indices.size()+1 < reg->packed_dims().size()) {
|
||||
// Here we are selecting one or more sub-arrays.
|
||||
// Make this work by finding the indexed sub-arrays and
|
||||
// creating a generated slice that spans the whole range.
|
||||
long loff, moff;
|
||||
unsigned long lwid, mwid;
|
||||
bool lrc, mrc;
|
||||
mrc = reg->sb_to_slice(prefix_indices, lsv, moff, mwid);
|
||||
if (use_sel == index_component_t::SEL_IDX_UP)
|
||||
lrc = reg->sb_to_slice(prefix_indices, lsv+wid-1, loff, lwid);
|
||||
else
|
||||
lrc = reg->sb_to_slice(prefix_indices, lsv-wid+1, loff, lwid);
|
||||
if (!mrc || !lrc) {
|
||||
cerr << get_fileline() << ": error: ";
|
||||
cerr << "Part-select [" << lsv;
|
||||
if (index_tail.sel == index_component_t::SEL_IDX_UP) {
|
||||
cerr << "+:";
|
||||
} else {
|
||||
cerr << "-:";
|
||||
}
|
||||
cerr << wid << "] exceeds the declared bounds for ";
|
||||
cerr << reg->name();
|
||||
if (reg->unpacked_dimensions() > 0) cerr << "[]";
|
||||
cerr << "." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
ivl_assert(*this, lwid == mwid);
|
||||
|
||||
// We want the last range, which is where we work.
|
||||
const netrange_t&rng = packed.back();
|
||||
if (((rng.get_msb() < rng.get_lsb()) &&
|
||||
use_sel == index_component_t::SEL_IDX_UP) ||
|
||||
((rng.get_msb() > rng.get_lsb()) &&
|
||||
use_sel == index_component_t::SEL_IDX_DO)) {
|
||||
offset = -wid + 1;
|
||||
if (moff > loff) {
|
||||
rel_base = loff;
|
||||
wid = moff + mwid - loff;
|
||||
} else {
|
||||
rel_base = moff;
|
||||
wid = loff + lwid - moff;
|
||||
}
|
||||
} else {
|
||||
long offset = 0;
|
||||
// We want the last range, which is where we work.
|
||||
const netrange_t&rng = packed.back();
|
||||
if (((rng.get_msb() < rng.get_lsb()) &&
|
||||
use_sel == index_component_t::SEL_IDX_UP) ||
|
||||
((rng.get_msb() > rng.get_lsb()) &&
|
||||
use_sel == index_component_t::SEL_IDX_DO)) {
|
||||
offset = -wid + 1;
|
||||
}
|
||||
rel_base = reg->sb_to_idx(prefix_indices,lsv) + offset;
|
||||
}
|
||||
delete base;
|
||||
long rel_base = reg->sb_to_idx(prefix_indices,lsv) + offset;
|
||||
/* If we cover the entire lvalue just skip the select. */
|
||||
if (rel_base == 0 && wid == reg->vector_width()) return true;
|
||||
base = new NetEConst(verinum(rel_base));
|
||||
@@ -980,7 +1034,7 @@ bool PEIdent::elaborate_lval_net_idx_(Design*des,
|
||||
cerr << wid << "] is selecting after vector." << endl;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
} else if (warn_ob_select) {
|
||||
cerr << get_fileline() << ": warning: L-value indexed part "
|
||||
<< "select of " << reg->name();
|
||||
if (reg->unpacked_dimensions() > 0) cerr << "[]";
|
||||
@@ -1025,7 +1079,8 @@ bool PEIdent::elaborate_lval_net_idx_(Design*des,
|
||||
* obj, and member_path=base.x.
|
||||
*/
|
||||
NetAssign_* PEIdent::elaborate_lval_net_class_member_(Design*des, NetScope*scope,
|
||||
NetNet*sig, pform_name_t member_path) const
|
||||
const netclass_t *class_type, NetNet*sig,
|
||||
pform_name_t member_path) const
|
||||
{
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PEIdent::elaborate_lval_net_class_member_: "
|
||||
@@ -1033,7 +1088,6 @@ NetAssign_* PEIdent::elaborate_lval_net_class_member_(Design*des, NetScope*scope
|
||||
<< " of " << sig->name() << "." << endl;
|
||||
}
|
||||
|
||||
const netclass_t*class_type = sig->class_type();
|
||||
ivl_assert(*this, class_type);
|
||||
|
||||
// Iterate over the member_path. This handles nested class
|
||||
@@ -1096,7 +1150,7 @@ NetAssign_* PEIdent::elaborate_lval_net_class_member_(Design*des, NetScope*scope
|
||||
}
|
||||
|
||||
lv = lv? new NetAssign_(lv) : new NetAssign_(sig);
|
||||
lv->set_property(method_name);
|
||||
lv->set_property(method_name, pidx);
|
||||
|
||||
// Now get the type of the property.
|
||||
ivl_type_t ptype = class_type->get_prop_type(pidx);
|
||||
@@ -1115,7 +1169,7 @@ NetAssign_* PEIdent::elaborate_lval_net_class_member_(Design*des, NetScope*scope
|
||||
// class type.
|
||||
class_type = dynamic_cast<const netclass_t*>(ptype);
|
||||
|
||||
} while (member_path.size() > 0);
|
||||
} while (!member_path.empty());
|
||||
|
||||
|
||||
return lv;
|
||||
@@ -1279,7 +1333,7 @@ bool PEIdent::elaborate_lval_net_packed_member_(Design*des, NetScope*scope,
|
||||
// In any case, this should be the tail of the
|
||||
// member_path, because the array element of this
|
||||
// kind of array cannot be a struct.
|
||||
if (member_comp.index.size() > 0) {
|
||||
if (!member_comp.index.empty()) {
|
||||
// These are the dimensions defined by the type
|
||||
const vector<netrange_t>&mem_packed_dims = mem_vec->packed_dims();
|
||||
|
||||
@@ -1346,7 +1400,7 @@ bool PEIdent::elaborate_lval_net_packed_member_(Design*des, NetScope*scope,
|
||||
// possibly iterate through more of the member_path.
|
||||
|
||||
ivl_assert(*this, array->packed());
|
||||
ivl_assert(*this, member_comp.index.size() > 0);
|
||||
ivl_assert(*this, !member_comp.index.empty());
|
||||
|
||||
// These are the dimensions defined by the type
|
||||
const vector<netrange_t>&mem_packed_dims = array->static_dimensions();
|
||||
@@ -1438,7 +1492,6 @@ bool PEIdent::elaborate_lval_net_packed_member_(Design*des, NetScope*scope,
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
struct_type = 0;
|
||||
}
|
||||
|
||||
// Complete this component of the path, mark it
|
||||
@@ -1446,7 +1499,7 @@ bool PEIdent::elaborate_lval_net_packed_member_(Design*des, NetScope*scope,
|
||||
completed_path .push_back(member_comp);
|
||||
member_path.pop_front();
|
||||
|
||||
} while (member_path.size() > 0 && struct_type != 0);
|
||||
} while (!member_path.empty() && struct_type != 0);
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PEIdent::elaborate_lval_net_packed_member_: "
|
||||
|
||||
+258
-161
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2021 Stephen Williams (steve@icarus.com)
|
||||
* Copyright CERN 2012 / Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
@@ -32,6 +32,8 @@
|
||||
# include <iostream>
|
||||
# include "ivl_assert.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
/*
|
||||
* The concatenation is also OK an an l-value. This method elaborates
|
||||
* it as a structural l-value. The return values is the *input* net of
|
||||
@@ -44,7 +46,7 @@ NetNet* PEConcat::elaborate_lnet_common_(Design*des, NetScope*scope,
|
||||
{
|
||||
assert(scope);
|
||||
|
||||
svector<NetNet*>nets (parms_.size());
|
||||
std::vector<NetNet*> nets(parms_.size());
|
||||
unsigned width = 0;
|
||||
unsigned errors = 0;
|
||||
|
||||
@@ -55,11 +57,11 @@ NetNet* PEConcat::elaborate_lnet_common_(Design*des, NetScope*scope,
|
||||
}
|
||||
|
||||
/* Elaborate the operands of the concatenation. */
|
||||
for (unsigned idx = 0 ; idx < nets.count() ; idx += 1) {
|
||||
for (unsigned idx = 0 ; idx < nets.size() ; idx += 1) {
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: Elaborate subexpression "
|
||||
<< idx << " of " << nets.count() << " l-values: "
|
||||
<< idx << " of " << nets.size() << " l-values: "
|
||||
<< *parms_[idx] << endl;
|
||||
}
|
||||
|
||||
@@ -115,7 +117,7 @@ NetNet* PEConcat::elaborate_lnet_common_(Design*des, NetScope*scope,
|
||||
<< endl;
|
||||
}
|
||||
|
||||
for (unsigned idx = 0 ; idx < nets.count() ; idx += 1) {
|
||||
for (unsigned idx = 0 ; idx < nets.size() ; idx += 1) {
|
||||
unsigned wid = nets[idx]->vector_width();
|
||||
unsigned off = width - wid;
|
||||
NetTran*ps = new NetTran(scope, scope->local_symbol(),
|
||||
@@ -139,7 +141,7 @@ NetNet* PEConcat::elaborate_lnet_common_(Design*des, NetScope*scope,
|
||||
|
||||
NetPartSelect::dir_t part_dir = NetPartSelect::VP;
|
||||
|
||||
for (unsigned idx = 0 ; idx < nets.count() ; idx += 1) {
|
||||
for (unsigned idx = 0 ; idx < nets.size() ; idx += 1) {
|
||||
unsigned wid = nets[idx]->vector_width();
|
||||
unsigned off = width - wid;
|
||||
NetPartSelect*ps = new NetPartSelect(osig, off, wid, part_dir);
|
||||
@@ -168,7 +170,8 @@ NetNet* PEConcat::elaborate_bi_net(Design*des, NetScope*scope) const
|
||||
return elaborate_lnet_common_(des, scope, true);
|
||||
}
|
||||
|
||||
bool PEConcat::is_collapsible_net(Design*des, NetScope*scope) const
|
||||
bool PEConcat::is_collapsible_net(Design*des, NetScope*scope,
|
||||
NetNet::PortType port_type) const
|
||||
{
|
||||
assert(scope);
|
||||
|
||||
@@ -183,7 +186,7 @@ bool PEConcat::is_collapsible_net(Design*des, NetScope*scope) const
|
||||
if (parms_[idx] == 0)
|
||||
return false;
|
||||
|
||||
if (!parms_[idx]->is_collapsible_net(des, scope))
|
||||
if (!parms_[idx]->is_collapsible_net(des, scope, port_type))
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -262,49 +265,87 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
|
||||
}
|
||||
|
||||
long midx_val = tmp->value().as_long();
|
||||
midx = sig->sb_to_idx(prefix_indices, midx_val);
|
||||
delete tmp_ex;
|
||||
if (prefix_indices.size()+1 < sig->packed_dims().size()) {
|
||||
// Here we are selecting one or more sub-arrays.
|
||||
// Make this work by finding the indexed sub-arrays and
|
||||
// creating a generated slice that spans the whole range.
|
||||
long loff, moff;
|
||||
unsigned long lwid, mwid;
|
||||
bool mrc, lrc;
|
||||
mrc = sig->sb_to_slice(prefix_indices, midx_val, moff, mwid);
|
||||
if (index_tail.sel == index_component_t::SEL_IDX_UP)
|
||||
lrc = sig->sb_to_slice(prefix_indices, midx_val+wid-1, loff, lwid);
|
||||
else
|
||||
lrc = sig->sb_to_slice(prefix_indices, midx_val-wid+1, loff, lwid);
|
||||
if (!mrc || !lrc) {
|
||||
cerr << get_fileline() << ": error: ";
|
||||
cerr << "Part-select [" << midx_val;
|
||||
if (index_tail.sel == index_component_t::SEL_IDX_UP) {
|
||||
cerr << "+:";
|
||||
} else {
|
||||
cerr << "-:";
|
||||
}
|
||||
cerr << wid << "] exceeds the declared bounds for ";
|
||||
cerr << sig->name();
|
||||
if (sig->unpacked_dimensions() > 0) cerr << "[]";
|
||||
cerr << "." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
ivl_assert(*this, lwid == mwid);
|
||||
|
||||
if (index_tail.sel == index_component_t::SEL_IDX_UP)
|
||||
lidx = sig->sb_to_idx(prefix_indices, midx_val+wid-1);
|
||||
else
|
||||
lidx = sig->sb_to_idx(prefix_indices, midx_val-wid+1);
|
||||
|
||||
if (midx < lidx) {
|
||||
long tmpx = midx;
|
||||
midx = lidx;
|
||||
lidx = tmpx;
|
||||
}
|
||||
|
||||
/* Warn about an indexed part select that is out of range. */
|
||||
if (warn_ob_select && (lidx < 0)) {
|
||||
cerr << get_fileline() << ": warning: " << sig->name();
|
||||
if (sig->unpacked_dimensions() > 0) cerr << "[]";
|
||||
cerr << "[" << midx_val;
|
||||
if (index_tail.sel == index_component_t::SEL_IDX_UP) {
|
||||
cerr << "+:";
|
||||
if (moff > loff) {
|
||||
lidx = loff;
|
||||
midx = moff + mwid - 1;
|
||||
} else {
|
||||
cerr << "-:";
|
||||
lidx = moff;
|
||||
midx = loff + lwid - 1;
|
||||
}
|
||||
cerr << wid << "] is selecting before vector." << endl;
|
||||
}
|
||||
if (warn_ob_select && (midx >= (long)sig->vector_width())) {
|
||||
cerr << get_fileline() << ": warning: " << sig->name();
|
||||
if (sig->unpacked_dimensions() > 0) {
|
||||
cerr << "[]";
|
||||
}
|
||||
cerr << "[" << midx_val;
|
||||
if (index_tail.sel == index_component_t::SEL_IDX_UP) {
|
||||
cerr << "+:";
|
||||
} else {
|
||||
cerr << "-:";
|
||||
}
|
||||
cerr << wid << "] is selecting after vector." << endl;
|
||||
}
|
||||
} else {
|
||||
midx = sig->sb_to_idx(prefix_indices, midx_val);
|
||||
|
||||
/* This is completely out side the signal so just skip it. */
|
||||
if (lidx >= (long)sig->vector_width() || midx < 0) {
|
||||
return false;
|
||||
if (index_tail.sel == index_component_t::SEL_IDX_UP)
|
||||
lidx = sig->sb_to_idx(prefix_indices, midx_val+wid-1);
|
||||
else
|
||||
lidx = sig->sb_to_idx(prefix_indices, midx_val-wid+1);
|
||||
|
||||
if (midx < lidx) {
|
||||
long tmpx = midx;
|
||||
midx = lidx;
|
||||
lidx = tmpx;
|
||||
}
|
||||
|
||||
/* Warn about an indexed part select that is out of range. */
|
||||
if (warn_ob_select && (lidx < 0)) {
|
||||
cerr << get_fileline() << ": warning: " << sig->name();
|
||||
if (sig->unpacked_dimensions() > 0) cerr << "[]";
|
||||
cerr << "[" << midx_val;
|
||||
if (index_tail.sel == index_component_t::SEL_IDX_UP) {
|
||||
cerr << "+:";
|
||||
} else {
|
||||
cerr << "-:";
|
||||
}
|
||||
cerr << wid << "] is selecting before vector." << endl;
|
||||
}
|
||||
if (warn_ob_select && (midx >= (long)sig->vector_width())) {
|
||||
cerr << get_fileline() << ": warning: " << sig->name();
|
||||
if (sig->unpacked_dimensions() > 0) {
|
||||
cerr << "[]";
|
||||
}
|
||||
cerr << "[" << midx_val;
|
||||
if (index_tail.sel == index_component_t::SEL_IDX_UP) {
|
||||
cerr << "+:";
|
||||
} else {
|
||||
cerr << "-:";
|
||||
}
|
||||
cerr << wid << "] is selecting after vector." << endl;
|
||||
}
|
||||
|
||||
/* This is completely out side the signal so just skip it. */
|
||||
if (lidx >= (long)sig->vector_width() || midx < 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -338,11 +379,19 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
|
||||
// range.
|
||||
long loff, moff;
|
||||
unsigned long lwid, mwid;
|
||||
bool lrc;
|
||||
bool lrc, mrc;
|
||||
lrc = sig->sb_to_slice(prefix_indices, lsb, loff, lwid);
|
||||
ivl_assert(*this, lrc);
|
||||
lrc = sig->sb_to_slice(prefix_indices, msb, moff, mwid);
|
||||
ivl_assert(*this, lrc);
|
||||
mrc = sig->sb_to_slice(prefix_indices, msb, moff, mwid);
|
||||
if (!mrc || !lrc) {
|
||||
cerr << get_fileline() << ": error: ";
|
||||
cerr << "Part-select [" << msb << ":" << lsb;
|
||||
cerr << "] exceeds the declared bounds for ";
|
||||
cerr << sig->name();
|
||||
if (sig->unpacked_dimensions() > 0) cerr << "[]";
|
||||
cerr << "." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
ivl_assert(*this, lwid == mwid);
|
||||
|
||||
if (moff > loff) {
|
||||
@@ -456,7 +505,6 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
|
||||
NetNet* sig = 0;
|
||||
const NetExpr*par = 0;
|
||||
NetEvent* eve = 0;
|
||||
perm_string method_name;
|
||||
|
||||
symbol_search(this, des, scope, path_, sig, par, eve);
|
||||
|
||||
@@ -468,33 +516,16 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Break the path_ into the tail name and the prefix. For
|
||||
// example, a name "a.b.c" is broken into name_tail="c" and
|
||||
// path_prefix="a.b".
|
||||
const name_component_t&path_tail = path_.back();
|
||||
pform_name_t path_prefix = path_;
|
||||
path_prefix.pop_back();
|
||||
|
||||
/* If the signal is not found, check to see if this is a
|
||||
member of a struct. Take the name of the form "a.b.member",
|
||||
remove the member and store it into method_name, and retry
|
||||
the search with "a.b". */
|
||||
if (sig == 0 && path_.size() >= 2) {
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PEIdent::elaborate_lnet_common_: "
|
||||
"Symbol not found, try again with path_prefix=" << path_prefix
|
||||
<< " and method_name=" << path_tail.name << endl;
|
||||
}
|
||||
method_name = path_tail.name;
|
||||
symbol_search(this, des, scope, path_prefix, sig, par, eve);
|
||||
|
||||
// Whoops, not a struct signal, so give up on this avenue.
|
||||
if (sig && sig->struct_type() == 0) {
|
||||
cerr << get_fileline() << ": XXXXX: sig=" << sig->name()
|
||||
<< " is found, but not a struct with member " << method_name << endl;
|
||||
method_name = perm_string();
|
||||
sig = 0;
|
||||
}
|
||||
pform_name_t base_path = path_;
|
||||
pform_name_t member_path;
|
||||
while (sig == 0 && !base_path.empty()) {
|
||||
symbol_search(this, des, scope, base_path, sig, par, eve);
|
||||
// Found it!
|
||||
if (sig != 0) break;
|
||||
// Not found. Try to pop another name off the base_path
|
||||
// and push it to the front of the member_path.
|
||||
member_path.push_front( base_path.back() );
|
||||
base_path.pop_back();
|
||||
}
|
||||
|
||||
if (sig == 0) {
|
||||
@@ -504,18 +535,27 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(sig);
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": " << __func__ << ": "
|
||||
<< "Found l-value path_=" << path_
|
||||
<< " as sig=" << sig->name()
|
||||
<< " base_path=" << base_path
|
||||
<< " member_path=" << member_path
|
||||
<< " unpacked_dimensions()=" << sig->unpacked_dimensions()
|
||||
<< endl;
|
||||
}
|
||||
|
||||
/* If this is SystemVerilog and the variable is not yet
|
||||
assigned by anything, then convert it to an unresolved
|
||||
wire. */
|
||||
|
||||
// If this is SystemVerilog and the variable is not yet
|
||||
// assigned by anything, then convert it to an unresolved
|
||||
// wire.
|
||||
if (gn_var_can_be_uwire()
|
||||
&& (sig->type() == NetNet::REG)
|
||||
&& (sig->peek_lref() == 0) ) {
|
||||
sig->type(NetNet::UNRESOLVED_WIRE);
|
||||
}
|
||||
|
||||
/* Don't allow registers as assign l-values. */
|
||||
// Don't allow registers as assign l-values.
|
||||
if (sig->type() == NetNet::REG) {
|
||||
cerr << get_fileline() << ": error: reg " << sig->name()
|
||||
<< "; cannot be driven by primitives"
|
||||
@@ -524,66 +564,139 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Default part select is the entire word.
|
||||
// Some parts below need the tail component. This is a convenient
|
||||
// reference to it.
|
||||
const name_component_t&path_tail = path_.back();
|
||||
|
||||
// Default part select is the entire word.
|
||||
unsigned midx = sig->vector_width()-1, lidx = 0;
|
||||
// The default word select is the first.
|
||||
// The default word select is the first.
|
||||
long widx = 0;
|
||||
// Set this to true if we calculate the word index. This is
|
||||
// used to distinguish between unpacked array assignment and
|
||||
// array word assignment.
|
||||
// Set this to true if we calculate the word index. This is
|
||||
// used to distinguish between unpacked array assignment and
|
||||
// array word assignment.
|
||||
bool widx_flag = false;
|
||||
|
||||
list<long> unpacked_indices_const;
|
||||
|
||||
// Detect the net is a structure and there was a method path
|
||||
// detected. We have already broken the path_ into the path to
|
||||
// the net, and the path of member names. For example, if the
|
||||
// path_ is a.b.x.y, we have determined that a.b is a reference
|
||||
// to the net, and that x.y are the member_path. So in this case
|
||||
// we handle the member_path.
|
||||
const netstruct_t*struct_type = 0;
|
||||
if ((struct_type = sig->struct_type()) && !method_name.nil()) {
|
||||
|
||||
// Detect the variable is a structure and there was a
|
||||
// method name detected. We've already found that
|
||||
// the path_ is <>.sig.method_name and signal
|
||||
// (NetNet). We also know that sig is struct_type(), so
|
||||
// look for a method named method_name.
|
||||
if (debug_elaborate)
|
||||
cerr << get_fileline() << ": PEIdent::elaborate_lnet_common_: "
|
||||
<< "Signal " << sig->name() << " is a structure, "
|
||||
<< "try to match member " << method_name << endl;
|
||||
|
||||
unsigned long member_off = 0;
|
||||
const struct netstruct_t::member_t*member = struct_type->packed_member(method_name, member_off);
|
||||
ivl_assert(*this, member);
|
||||
if ((struct_type = sig->struct_type()) && !member_path.empty()) {
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PEIdent::elaborate_lnet_common_: "
|
||||
<< "Member " << method_name
|
||||
<< " has type " << *member->net_type << "." << endl;
|
||||
cerr << get_fileline() << ": : "
|
||||
<< "Tail name has " << path_tail.index.size() << " indices." << endl;
|
||||
cerr << get_fileline() << ": PEIdent::elaborate_lnet_common_: "
|
||||
<< "Signal " << sig->name() << " is a structure, "
|
||||
<< "try to match member path " << member_path << endl;
|
||||
}
|
||||
|
||||
// Rewrite a member select of a packed structure as a
|
||||
// part select of the base variable.
|
||||
lidx = member_off;
|
||||
midx = lidx + member->net_type->packed_width() - 1;
|
||||
unsigned long member_off = 0;
|
||||
unsigned long member_width = sig->vector_width();
|
||||
|
||||
// The dimensions of the tail of the prefix must match
|
||||
// the dimensions of the signal at this point. (The sig
|
||||
// has a packed dimension for the packed struct size.)
|
||||
// For example, if the path_=a[<m>][<n>].member, then
|
||||
// sig must have 3 packed dimensions: one for the struct
|
||||
// members and two actual packed dimensions.
|
||||
ivl_assert(*this, path_prefix.back().index.size()+1 == sig->packed_dimensions());
|
||||
|
||||
// Elaborate an expression from the packed indices and
|
||||
// the member offset (into the structure) to get a
|
||||
// canonical expression into the packed signal vector.
|
||||
NetExpr*packed_base = 0;
|
||||
// Might be an array of structs, like a.b[N].x.y. (A packed
|
||||
// array.) Handle that here by taking a part select that
|
||||
// reflects the array index.
|
||||
if (sig->packed_dimensions() > 1) {
|
||||
list<index_component_t>tmp_index = path_prefix.back().index;
|
||||
list<index_component_t>tmp_index = base_path.back().index;
|
||||
index_component_t member_select;
|
||||
member_select.sel = index_component_t::SEL_BIT;
|
||||
member_select.msb = new PENumber(new verinum(member_off));
|
||||
tmp_index.push_back(member_select);
|
||||
packed_base = collapse_array_indices(des, scope, sig, tmp_index);
|
||||
NetExpr*packed_base = collapse_array_indices(des, scope, sig, tmp_index);
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": " << __func__ << ": "
|
||||
<< "packed_base=" << *packed_base
|
||||
<< endl;
|
||||
}
|
||||
|
||||
long tmp;
|
||||
if (packed_base && eval_as_long(tmp, packed_base)) {
|
||||
member_off = tmp;
|
||||
member_width = struct_type->packed_width();
|
||||
delete packed_base;
|
||||
packed_base = 0;
|
||||
}
|
||||
|
||||
// Only support constant dimensions here.
|
||||
ivl_assert(*this, packed_base == 0);
|
||||
}
|
||||
|
||||
// Now run through the member names, possibly nested, to take
|
||||
// further part selects reflected by the member name. So for
|
||||
// example, (.x.y) member x has an offset and width within the
|
||||
// containing vector, and member y an offset and width within
|
||||
// that.
|
||||
pform_name_t use_path = member_path;
|
||||
while (! use_path.empty()) {
|
||||
const name_component_t member_comp = use_path.front();
|
||||
const perm_string&member_name = member_comp.name;
|
||||
|
||||
unsigned long tmp_off;
|
||||
const struct netstruct_t::member_t*member = struct_type->packed_member(member_name, tmp_off);
|
||||
ivl_assert(*this, member);
|
||||
member_off += tmp_off;
|
||||
member_width = member->net_type->packed_width();
|
||||
|
||||
if (const netstruct_t*tmp_struct = dynamic_cast<const netstruct_t*> (member->net_type)) {
|
||||
struct_type = tmp_struct;
|
||||
} else {
|
||||
struct_type = 0;
|
||||
}
|
||||
|
||||
use_path.pop_front();
|
||||
}
|
||||
|
||||
// Look for part selects on the final member. For example if
|
||||
// the path is a.b.x.y[3:0], the end of the member_path will
|
||||
// have an index that needs to be handled.
|
||||
// For now, assume there is unly a single part/bit select, and
|
||||
// assume it's constant.
|
||||
if (member_path.back().index.size() > 0) {
|
||||
list<index_component_t>tmp_index = member_path.back().index;
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": " << __func__ << ": "
|
||||
<< "Process trailing bit/part select. "
|
||||
<< "index.size()=" << tmp_index.size()
|
||||
<< endl;
|
||||
}
|
||||
ivl_assert(*this, tmp_index.size() == 1);
|
||||
const index_component_t&tail_sel = tmp_index.back();
|
||||
ivl_assert(*this, tail_sel.sel == index_component_t::SEL_PART || tail_sel.sel == index_component_t::SEL_BIT);
|
||||
long tmp_off;
|
||||
unsigned long tmp_wid;
|
||||
bool rc = calculate_part(this, des, scope, tail_sel, tmp_off, tmp_wid);
|
||||
ivl_assert(*this, rc);
|
||||
member_off += tmp_off;
|
||||
member_width = tmp_wid;
|
||||
}
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": " << __func__ << ": "
|
||||
<< "Final, calculated member " << member_path
|
||||
<< " offset=" << member_off
|
||||
<< " width=" << member_width
|
||||
<< endl;
|
||||
}
|
||||
|
||||
// Rewrite a member select of a packed structure as a
|
||||
// part select of the base variable.
|
||||
lidx = member_off;
|
||||
midx = lidx + member_width - 1;
|
||||
|
||||
// Elaborate an expression from the packed indices and
|
||||
// the member offset (into the structure) to get a
|
||||
// canonical expression into the packed signal vector.
|
||||
if (sig->packed_dimensions() > 1) {
|
||||
list<index_component_t>tmp_index = base_path.back().index;
|
||||
index_component_t member_select;
|
||||
member_select.sel = index_component_t::SEL_BIT;
|
||||
member_select.msb = new PENumber(new verinum(member_off));
|
||||
tmp_index.push_back(member_select);
|
||||
NetExpr*packed_base = collapse_array_indices(des, scope, sig, tmp_index);
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PEIdent::elaborate_lnet_common_: "
|
||||
@@ -592,36 +705,6 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
|
||||
}
|
||||
}
|
||||
|
||||
long tmp;
|
||||
if (packed_base && eval_as_long(tmp, packed_base)) {
|
||||
lidx = tmp;
|
||||
midx = lidx + member->net_type->packed_width() - 1;
|
||||
delete packed_base;
|
||||
packed_base = 0;
|
||||
}
|
||||
|
||||
// Currently, only support const dimensions here.
|
||||
ivl_assert(*this, packed_base == 0);
|
||||
|
||||
// Now the lidx/midx values get us to the member. Next
|
||||
// up, deal with bit/part selects from the member
|
||||
// itself.
|
||||
//XXXXivl_assert(*this, member->packed_dims.size() <= 1);
|
||||
ivl_assert(*this, path_tail.index.size() <= 1);
|
||||
if (! path_tail.index.empty()) {
|
||||
long tmp_off;
|
||||
unsigned long tmp_wid;
|
||||
const index_component_t&tail_sel = path_tail.index.back();
|
||||
ivl_assert(*this, tail_sel.sel == index_component_t::SEL_PART || tail_sel.sel == index_component_t::SEL_BIT);
|
||||
bool rc = calculate_part(this, des, scope, tail_sel, tmp_off, tmp_wid);
|
||||
ivl_assert(*this, rc);
|
||||
if (debug_elaborate)
|
||||
cerr << get_fileline() << ": PEIdent::elaborate_lnet_common_: "
|
||||
<< "tmp_off=" << tmp_off << ", tmp_wid=" << tmp_wid << endl;
|
||||
lidx += tmp_off;
|
||||
midx = lidx + tmp_wid - 1;
|
||||
}
|
||||
|
||||
} else if (gn_system_verilog() && sig->unpacked_dimensions() > 0 && path_tail.index.empty()) {
|
||||
|
||||
// In this case, we are doing a continuous assignment to
|
||||
@@ -1024,13 +1107,26 @@ NetNet*PEIdent::elaborate_unpacked_net(Design*des, NetScope*scope) const
|
||||
perm_string method_name;
|
||||
|
||||
symbol_search(this, des, scope, path_, sig, par, eve);
|
||||
if (!sig) {
|
||||
cerr << get_fileline() << ": error: Net " << path_
|
||||
<< " is not defined in this context." << endl;
|
||||
des->errors += 1;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ivl_assert(*this, sig);
|
||||
const name_component_t&name_tail = path_.back();
|
||||
if (name_tail.index.size() != 0) {
|
||||
cerr << get_fileline() << ": sorry: Array slices are not yet "
|
||||
<< "supported for continuous assignment." << endl;
|
||||
des->errors += 1;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return sig;
|
||||
}
|
||||
|
||||
bool PEIdent::is_collapsible_net(Design*des, NetScope*scope) const
|
||||
bool PEIdent::is_collapsible_net(Design*des, NetScope*scope,
|
||||
NetNet::PortType port_type) const
|
||||
{
|
||||
assert(scope);
|
||||
|
||||
@@ -1051,9 +1147,10 @@ bool PEIdent::is_collapsible_net(Design*des, NetScope*scope) const
|
||||
/* If this is SystemVerilog and the variable is not yet
|
||||
assigned by anything, then convert it to an unresolved
|
||||
wire. */
|
||||
if (gn_var_can_be_uwire()
|
||||
&& (sig->type() == NetNet::REG)
|
||||
&& (sig->peek_eref() == 0) ) {
|
||||
if (gn_var_can_be_uwire() &&
|
||||
(sig->type() == NetNet::REG) &&
|
||||
(sig->peek_eref() == 0) &&
|
||||
(port_type == NetNet::POUTPUT)) {
|
||||
sig->type(NetNet::UNRESOLVED_WIRE);
|
||||
}
|
||||
|
||||
|
||||
+172
-161
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2020 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2021 Stephen Williams (steve@icarus.com)
|
||||
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
@@ -21,6 +21,8 @@
|
||||
# include "config.h"
|
||||
# include "compiler.h"
|
||||
# include "netmisc.h"
|
||||
# include "netvector.h"
|
||||
# include "netparray.h"
|
||||
# include <cstring>
|
||||
# include <iostream>
|
||||
# include <cstdlib>
|
||||
@@ -48,12 +50,14 @@
|
||||
# include "netlist.h"
|
||||
# include "netclass.h"
|
||||
# include "netenum.h"
|
||||
# include "netqueue.h"
|
||||
# include "parse_api.h"
|
||||
# include "util.h"
|
||||
# include <typeinfo>
|
||||
# include <cassert>
|
||||
# include "ivl_assert.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
void set_scope_timescale(Design*des, NetScope*scope, PScope*pscope)
|
||||
{
|
||||
@@ -65,11 +69,26 @@ void set_scope_timescale(Design*des, NetScope*scope, PScope*pscope)
|
||||
|
||||
typedef map<perm_string,LexicalScope::param_expr_t*>::const_iterator mparm_it_t;
|
||||
|
||||
static void collect_parm_item_(Design*des, NetScope*scope, perm_string name,
|
||||
const LexicalScope::param_expr_t&cur,
|
||||
bool is_annotatable,
|
||||
bool local_flag)
|
||||
static void collect_parm_item(Design*des, NetScope*scope, perm_string name,
|
||||
const LexicalScope::param_expr_t&cur,
|
||||
bool is_annotatable)
|
||||
{
|
||||
if (debug_scopes) {
|
||||
cerr << cur.get_fileline() << ": " << __func__ << ": "
|
||||
<< "parameter " << name << " ";
|
||||
if (cur.data_type)
|
||||
cerr << *cur.data_type;
|
||||
else
|
||||
cerr << "(nil type)";
|
||||
ivl_assert(cur, cur.expr);
|
||||
cerr << " = " << *cur.expr << "; ";
|
||||
if (cur.range)
|
||||
cerr << "with ranges ";
|
||||
else
|
||||
cerr << "without ranges ";
|
||||
cerr << "; in scope " << scope_path(scope) << endl;
|
||||
}
|
||||
|
||||
NetScope::range_t*range_list = 0;
|
||||
for (LexicalScope::range_t*range = cur.range ; range ; range = range->next) {
|
||||
NetScope::range_t*tmp = new NetScope::range_t;
|
||||
@@ -104,38 +123,41 @@ static void collect_parm_item_(Design*des, NetScope*scope, perm_string name,
|
||||
range_list = tmp;
|
||||
}
|
||||
|
||||
|
||||
scope->set_parameter(name, is_annotatable, cur.expr, cur.type, cur.msb,
|
||||
cur.lsb, cur.signed_flag, local_flag, range_list, cur);
|
||||
// The type of the parameter, if unspecified in the source, will come
|
||||
// from the type of the value assigned to it. Therefore, if the type is
|
||||
// not yet known, don't try to guess here, put the type guess off. Also
|
||||
// don't try to elaborate it here, because there may be references to
|
||||
// other parameters still being located during scope elaboration.
|
||||
scope->set_parameter(name, is_annotatable, cur, range_list);
|
||||
}
|
||||
|
||||
static void collect_scope_parameters_(Design*des, NetScope*scope,
|
||||
static void collect_scope_parameters(Design*des, NetScope*scope,
|
||||
const map<perm_string,LexicalScope::param_expr_t*>¶meters)
|
||||
{
|
||||
if (debug_scopes) {
|
||||
cerr << scope->get_fileline() << ": " << __func__ << ": "
|
||||
<< "collect parameters for " << scope_path(scope) << "." << endl;
|
||||
}
|
||||
|
||||
for (mparm_it_t cur = parameters.begin()
|
||||
; cur != parameters.end() ; ++ cur ) {
|
||||
|
||||
collect_parm_item_(des, scope, cur->first, *(cur->second), false, false);
|
||||
collect_parm_item(des, scope, cur->first, *(cur->second), false);
|
||||
}
|
||||
}
|
||||
|
||||
static void collect_scope_localparams_(Design*des, NetScope*scope,
|
||||
const map<perm_string,LexicalScope::param_expr_t*>&localparams)
|
||||
{
|
||||
for (mparm_it_t cur = localparams.begin()
|
||||
; cur != localparams.end() ; ++ cur ) {
|
||||
|
||||
collect_parm_item_(des, scope, cur->first, *(cur->second), false, true);
|
||||
}
|
||||
}
|
||||
|
||||
static void collect_scope_specparams_(Design*des, NetScope*scope,
|
||||
static void collect_scope_specparams(Design*des, NetScope*scope,
|
||||
const map<perm_string,LexicalScope::param_expr_t*>&specparams)
|
||||
{
|
||||
if (debug_scopes) {
|
||||
cerr << scope->get_fileline() << ": " << __func__ << ": "
|
||||
<< "collect specparams for " << scope_path(scope) << "." << endl;
|
||||
}
|
||||
|
||||
for (mparm_it_t cur = specparams.begin()
|
||||
; cur != specparams.end() ; ++ cur ) {
|
||||
|
||||
collect_parm_item_(des, scope, cur->first, *(cur->second), true, false);
|
||||
collect_parm_item(des, scope, cur->first, *(cur->second), true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,46 +168,31 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope,
|
||||
enum_type_t*enum_type)
|
||||
{
|
||||
bool rc_flag;
|
||||
assert(enum_type->range->size() == 1);
|
||||
pform_range_t&range = enum_type->range->front();
|
||||
NetExpr*msb_ex = elab_and_eval(des, scope, range.first, -1);
|
||||
NetExpr*lsb_ex = elab_and_eval(des, scope, range.second, -1);
|
||||
|
||||
long msb = 0;
|
||||
rc_flag = eval_as_long(msb, msb_ex);
|
||||
assert(rc_flag);
|
||||
long lsb = 0;
|
||||
rc_flag = eval_as_long(lsb, lsb_ex);
|
||||
assert(rc_flag);
|
||||
enum_type->elaborate_type(des, scope);
|
||||
|
||||
netenum_t*use_enum = new netenum_t(enum_type->base_type,
|
||||
enum_type->signed_flag,
|
||||
enum_type->integer_flag, msb, lsb,
|
||||
enum_type->names->size(),
|
||||
enum_type);
|
||||
|
||||
use_enum->set_line(enum_type->li);
|
||||
scope->add_enumeration_set(enum_type, use_enum);
|
||||
netenum_t *use_enum = scope->enumeration_for_key(enum_type);
|
||||
|
||||
size_t name_idx = 0;
|
||||
// Find the enumeration width.
|
||||
long raw_width = use_enum->packed_width();
|
||||
assert(raw_width > 0);
|
||||
unsigned enum_width = (unsigned)raw_width;
|
||||
bool is_signed = use_enum->get_signed();
|
||||
// Define the default start value and the increment value to be the
|
||||
// correct type for this enumeration.
|
||||
verinum cur_value ((uint64_t)0, enum_width);
|
||||
cur_value.has_sign(enum_type->signed_flag);
|
||||
cur_value.has_sign(is_signed);
|
||||
verinum one_value ((uint64_t)1, enum_width);
|
||||
one_value.has_sign(enum_type->signed_flag);
|
||||
one_value.has_sign(is_signed);
|
||||
// Find the maximum allowed enumeration value.
|
||||
verinum max_value (0);
|
||||
if (enum_type->signed_flag) {
|
||||
if (is_signed) {
|
||||
max_value = pow(verinum(2), verinum(enum_width-1)) - one_value;
|
||||
} else {
|
||||
max_value = pow(verinum(2), verinum(enum_width)) - one_value;
|
||||
}
|
||||
max_value.has_sign(enum_type->signed_flag);
|
||||
max_value.has_sign(is_signed);
|
||||
// Variable to indicate when a defined value wraps.
|
||||
bool implicit_wrapped = false;
|
||||
// Process the enumeration definition.
|
||||
@@ -210,7 +217,7 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope,
|
||||
implicit_wrapped = false;
|
||||
|
||||
// A 2-state value can not have a constant with X/Z bits.
|
||||
if (enum_type->base_type==IVL_VT_BOOL &&
|
||||
if (use_enum->base_type() == IVL_VT_BOOL &&
|
||||
! cur_value.is_defined()) {
|
||||
cerr << use_enum->get_fileline()
|
||||
<< ": error: Enumeration name " << cur->name
|
||||
@@ -235,7 +242,7 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope,
|
||||
// value does not have a defined width.
|
||||
if (((cur_value.len() != enum_width) ||
|
||||
! cur_value.has_len()) &&
|
||||
! enum_type->signed_flag && cur_value.is_negative()) {
|
||||
! is_signed && cur_value.is_negative()) {
|
||||
cerr << use_enum->get_fileline()
|
||||
<< ": error: Enumeration name " << cur->name
|
||||
<< " has a negative value." << endl;
|
||||
@@ -258,7 +265,7 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope,
|
||||
if (cur_value[idx] != cur_value[check_width]) {
|
||||
// If this is an unsigned enumeration
|
||||
// then zero padding is okay.
|
||||
if (! enum_type->signed_flag &&
|
||||
if (!is_signed &&
|
||||
(idx == enum_width) &&
|
||||
(cur_value[idx] == verinum::V0)) {
|
||||
check_width += 1;
|
||||
@@ -304,7 +311,7 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope,
|
||||
// At this point the value has the correct size and needs
|
||||
// to have the correct sign attribute set.
|
||||
cur_value.has_len(true);
|
||||
cur_value.has_sign(enum_type->signed_flag);
|
||||
cur_value.has_sign(is_signed);
|
||||
|
||||
} else if (! cur_value.is_defined()) {
|
||||
cerr << use_enum->get_fileline()
|
||||
@@ -354,9 +361,16 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope,
|
||||
}
|
||||
|
||||
static void elaborate_scope_enumerations(Design*des, NetScope*scope,
|
||||
const set<enum_type_t*>&enum_types)
|
||||
const vector<enum_type_t*>&enum_types)
|
||||
{
|
||||
for (set<enum_type_t*>::const_iterator cur = enum_types.begin()
|
||||
if (debug_scopes) {
|
||||
cerr << scope->get_fileline() << ": " << __func__ << ": "
|
||||
<< "Elaborate " << enum_types.size() << " enumerations"
|
||||
<< " in scope " << scope_path(scope) << "."
|
||||
<< endl;
|
||||
}
|
||||
|
||||
for (vector<enum_type_t*>::const_iterator cur = enum_types.begin()
|
||||
; cur != enum_types.end() ; ++ cur) {
|
||||
enum_type_t*curp = *cur;
|
||||
elaborate_scope_enumeration(des, scope, curp);
|
||||
@@ -405,7 +419,7 @@ static void blend_class_constructors(PClass*pclass)
|
||||
|
||||
// If we do not have an explicit constructor chain, but there
|
||||
// is a parent class, then create an implicit chain.
|
||||
if (chain_new==0 && pclass->type->base_type!=0) {
|
||||
if (chain_new==0 && pclass->type->base_type) {
|
||||
chain_new = new PChainConstructor(pclass->type->base_args);
|
||||
chain_new->set_line(*pclass);
|
||||
}
|
||||
@@ -458,40 +472,34 @@ static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass)
|
||||
<< endl;
|
||||
}
|
||||
|
||||
class_type_t*base_class = dynamic_cast<class_type_t*> (use_type->base_type);
|
||||
if (use_type->base_type && !base_class) {
|
||||
cerr << pclass->get_fileline() << ": error: "
|
||||
<< "Base type of " << use_type->name
|
||||
<< " is not a class." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
netclass_t*use_base_class = 0;
|
||||
if (base_class) {
|
||||
use_base_class = scope->find_class(base_class->name);
|
||||
if (use_base_class == 0) {
|
||||
const netclass_t*use_base_class = 0;
|
||||
if (use_type->base_type) {
|
||||
ivl_type_t base_type = use_type->base_type->elaborate_type(des, scope);
|
||||
use_base_class = dynamic_cast<const netclass_t *>(base_type);
|
||||
if (!use_base_class) {
|
||||
cerr << pclass->get_fileline() << ": error: "
|
||||
<< "Base class " << base_class->name
|
||||
<< " not found." << endl;
|
||||
<< "Base type of " << use_type->name
|
||||
<< " is not a class." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
}
|
||||
|
||||
netclass_t*use_class = new netclass_t(use_type->name, use_base_class);
|
||||
|
||||
ivl_assert(*pclass, use_type->save_elaborated_type == 0);
|
||||
use_type->save_elaborated_type = use_class;
|
||||
|
||||
NetScope*class_scope = new NetScope(scope, hname_t(pclass->pscope_name()),
|
||||
NetScope::CLASS, scope->unit());
|
||||
class_scope->set_line(pclass);
|
||||
class_scope->set_class_def(use_class);
|
||||
use_class->set_class_scope(class_scope);
|
||||
use_class->set_definition_scope(scope);
|
||||
use_class->set_virtual(use_type->virtual_class);
|
||||
set_scope_timescale(des, class_scope, pclass);
|
||||
|
||||
class_scope->add_typedefs(&pclass->typedefs);
|
||||
|
||||
collect_scope_parameters(des, class_scope, pclass->parameters);
|
||||
|
||||
// Elaborate enum types declared in the class. We need these
|
||||
// now because enumeration constants can be used during scope
|
||||
// elaboration.
|
||||
@@ -504,28 +512,19 @@ static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass)
|
||||
}
|
||||
elaborate_scope_enumerations(des, class_scope, pclass->enum_sets);
|
||||
|
||||
// Collect the properties, elaborate them, and add them to the
|
||||
// elaborated class definition.
|
||||
for (map<perm_string, class_type_t::prop_info_t>::iterator cur = use_type->properties.begin()
|
||||
; cur != use_type->properties.end() ; ++ cur) {
|
||||
|
||||
ivl_type_s*tmp = cur->second.type->elaborate_type(des, class_scope);
|
||||
ivl_assert(*pclass, tmp);
|
||||
if (debug_scopes) {
|
||||
cerr << pclass->get_fileline() << ": elaborate_scope_class: "
|
||||
<< " Property " << cur->first
|
||||
<< " type=" << *tmp << endl;
|
||||
}
|
||||
use_class->set_property(cur->first, cur->second.qual, tmp);
|
||||
|
||||
}
|
||||
|
||||
for (map<perm_string,PTask*>::iterator cur = pclass->tasks.begin()
|
||||
; cur != pclass->tasks.end() ; ++cur) {
|
||||
|
||||
hname_t use_name (cur->first);
|
||||
NetScope*method_scope = new NetScope(class_scope, use_name, NetScope::TASK);
|
||||
|
||||
// Task methods are always automatic...
|
||||
if (!cur->second->is_auto()) {
|
||||
cerr << "error: Lifetime of method `"
|
||||
<< scope_path(method_scope)
|
||||
<< "` must not be static" << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
method_scope->is_auto(true);
|
||||
method_scope->set_line(cur->second);
|
||||
method_scope->add_imports(&cur->second->explicit_imports);
|
||||
@@ -544,7 +543,14 @@ static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass)
|
||||
|
||||
hname_t use_name (cur->first);
|
||||
NetScope*method_scope = new NetScope(class_scope, use_name, NetScope::FUNC);
|
||||
|
||||
// Function methods are always automatic...
|
||||
if (!cur->second->is_auto()) {
|
||||
cerr << "error: Lifetime of method `"
|
||||
<< scope_path(method_scope)
|
||||
<< "` must not be static" << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
method_scope->is_auto(true);
|
||||
method_scope->set_line(cur->second);
|
||||
method_scope->add_imports(&cur->second->explicit_imports);
|
||||
@@ -564,15 +570,27 @@ static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass)
|
||||
static void elaborate_scope_classes(Design*des, NetScope*scope,
|
||||
const vector<PClass*>&classes)
|
||||
{
|
||||
if (debug_scopes) {
|
||||
cerr << scope->get_fileline() << ": " << __func__ << ": "
|
||||
<< "Elaborate " << classes.size() << " classes"
|
||||
<< " in scope " << scope_path(scope) << "."
|
||||
<< endl;
|
||||
}
|
||||
|
||||
for (size_t idx = 0 ; idx < classes.size() ; idx += 1) {
|
||||
blend_class_constructors(classes[idx]);
|
||||
elaborate_scope_class(des, scope, classes[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
static void replace_scope_parameters_(NetScope*scope, const LineInfo&loc,
|
||||
const Module::replace_t&replacements)
|
||||
static void replace_scope_parameters(Design *des, NetScope*scope, const LineInfo&loc,
|
||||
const Module::replace_t&replacements)
|
||||
{
|
||||
if (debug_scopes) {
|
||||
cerr << scope->get_fileline() << ": " << __func__ << ": "
|
||||
<< "Replace scope parameters for " << scope_path(scope) << "." << endl;
|
||||
}
|
||||
|
||||
for (Module::replace_t::const_iterator cur = replacements.begin()
|
||||
; cur != replacements.end() ; ++ cur ) {
|
||||
|
||||
@@ -591,13 +609,7 @@ static void replace_scope_parameters_(NetScope*scope, const LineInfo&loc,
|
||||
cerr << loc.get_fileline() << ": : "
|
||||
<< "Type=" << val->expr_type() << endl;
|
||||
}
|
||||
bool flag = scope->replace_parameter((*cur).first, val,
|
||||
scope->parent());
|
||||
if (! flag) {
|
||||
cerr << val->get_fileline() << ": warning: parameter "
|
||||
<< (*cur).first << " not found in "
|
||||
<< scope_path(scope) << "." << endl;
|
||||
}
|
||||
scope->replace_parameter(des, (*cur).first, val, scope->parent());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -652,7 +664,8 @@ static void elaborate_scope_func(Design*des, NetScope*scope, PFunction*task)
|
||||
|
||||
if (debug_scopes) {
|
||||
cerr << task->get_fileline() << ": elaborate_scope_func: "
|
||||
<< "Elaborate task scope " << scope_path(task_scope) << endl;
|
||||
<< "Elaborate function scope " << scope_path(task_scope)
|
||||
<< endl;
|
||||
}
|
||||
|
||||
task->elaborate_scope(des, task_scope);
|
||||
@@ -712,8 +725,7 @@ bool PPackage::elaborate_scope(Design*des, NetScope*scope)
|
||||
|
||||
scope->add_typedefs(&typedefs);
|
||||
|
||||
collect_scope_parameters_(des, scope, parameters);
|
||||
collect_scope_localparams_(des, scope, localparams);
|
||||
collect_scope_parameters(des, scope, parameters);
|
||||
|
||||
if (debug_scopes) {
|
||||
cerr << get_fileline() << ": PPackage::elaborate_scope: "
|
||||
@@ -751,23 +763,15 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
|
||||
// will be evaluated later, once all parameter overrides for this
|
||||
// module have been done.
|
||||
|
||||
collect_scope_parameters_(des, scope, parameters);
|
||||
collect_scope_parameters(des, scope, parameters);
|
||||
|
||||
collect_scope_localparams_(des, scope, localparams);
|
||||
|
||||
collect_scope_specparams_(des, scope, specparams);
|
||||
collect_scope_specparams(des, scope, specparams);
|
||||
|
||||
// Run parameter replacements that were collected from the
|
||||
// containing scope and meant for me.
|
||||
|
||||
replace_scope_parameters_(scope, *this, replacements);
|
||||
replace_scope_parameters(des, scope, *this, replacements);
|
||||
|
||||
if (debug_scopes) {
|
||||
cerr << get_fileline() << ": Module::elaborate_scope: "
|
||||
<< "Elaborate " << enum_sets.size() << " enumerations"
|
||||
<< " in scope " << scope_path(scope) << "."
|
||||
<< endl;
|
||||
}
|
||||
elaborate_scope_enumerations(des, scope, enum_sets);
|
||||
|
||||
assert(classes.size() == classes_lexical.size());
|
||||
@@ -796,7 +800,7 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
|
||||
// we can not do that until defparams are run, so push it off
|
||||
// into an elaborate work item.
|
||||
if (debug_scopes)
|
||||
cerr << get_fileline() << ": debug: "
|
||||
cerr << get_fileline() << ": " << __func__ << ": "
|
||||
<< "Schedule generates within " << scope_path(scope)
|
||||
<< " for elaboration after defparams." << endl;
|
||||
|
||||
@@ -894,6 +898,18 @@ bool PGenerate::generate_scope(Design*des, NetScope*container)
|
||||
}
|
||||
}
|
||||
|
||||
void PGenerate::check_for_valid_genvar_value_(long value)
|
||||
{
|
||||
if (generation_flag < GN_VER2005 && value < 0) {
|
||||
cerr << get_fileline() << ": warning: A negative value (" << value
|
||||
<< ") has been assigned to genvar '" << loop_index << "'."
|
||||
<< endl;
|
||||
cerr << get_fileline() << ": : This is illegal in "
|
||||
"Verilog-2001. Use at least -g2005 to remove this warning."
|
||||
<< endl;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the elaborate scope method for a generate loop.
|
||||
*/
|
||||
@@ -903,8 +919,16 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
|
||||
// Check that the loop_index variable was declared in a
|
||||
// genvar statement.
|
||||
NetScope*cscope = container;
|
||||
while (cscope && !cscope->find_genvar(loop_index))
|
||||
while (cscope && !cscope->find_genvar(loop_index)) {
|
||||
if (cscope->symbol_exists(loop_index)) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< "generate loop variable '" << loop_index
|
||||
<< "' is not a genvar in this scope." << endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
cscope = cscope->parent();
|
||||
}
|
||||
if (!cscope) {
|
||||
cerr << get_fileline() << ": error: genvar is missing for "
|
||||
"generate \"loop\" variable '" << loop_index << "'."
|
||||
@@ -915,7 +939,7 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
|
||||
}
|
||||
|
||||
// We're going to need a genvar...
|
||||
int genvar;
|
||||
long genvar;
|
||||
|
||||
// The initial value for the genvar does not need (nor can it
|
||||
// use) the genvar itself, so we can evaluate this expression
|
||||
@@ -930,6 +954,7 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
|
||||
}
|
||||
|
||||
genvar = init->value().as_long();
|
||||
check_for_valid_genvar_value_(genvar);
|
||||
delete init_ex;
|
||||
|
||||
if (debug_scopes)
|
||||
@@ -966,7 +991,11 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
|
||||
// block. Code within this scope thus has access to the
|
||||
// genvar as a constant.
|
||||
{
|
||||
verinum genvar_verinum(genvar);
|
||||
verinum genvar_verinum;
|
||||
if (gn_strict_expr_width_flag)
|
||||
genvar_verinum = verinum(genvar, integer_width);
|
||||
else
|
||||
genvar_verinum = verinum(genvar);
|
||||
genvar_verinum.has_sign(true);
|
||||
NetEConstParam*gp = new NetEConstParam(scope,
|
||||
loop_index,
|
||||
@@ -996,6 +1025,7 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
|
||||
<< genvar << " to " << step->value().as_long() << endl;
|
||||
|
||||
genvar = step->value().as_long();
|
||||
check_for_valid_genvar_value_(genvar);
|
||||
container->genvar_tmp_val = genvar;
|
||||
delete step;
|
||||
delete test_ex;
|
||||
@@ -1042,8 +1072,7 @@ bool PGenerate::generate_scope_condit_(Design*des, NetScope*container, bool else
|
||||
<< " value=" << test->value() << ": Generate scope="
|
||||
<< use_name << endl;
|
||||
|
||||
probe_for_direct_nesting_();
|
||||
if (direct_nested_) {
|
||||
if (directly_nested) {
|
||||
if (debug_scopes)
|
||||
cerr << get_fileline() << ": debug: Generate condition "
|
||||
<< (else_flag? "(else)" : "(if)")
|
||||
@@ -1141,8 +1170,7 @@ bool PGenerate::generate_scope_case_(Design*des, NetScope*container)
|
||||
// The name of the scope to generate, whatever that item is.
|
||||
hname_t use_name (item->scope_name);
|
||||
|
||||
item->probe_for_direct_nesting_();
|
||||
if (item->direct_nested_) {
|
||||
if (item->directly_nested) {
|
||||
if (debug_scopes)
|
||||
cerr << get_fileline() << ": debug: Generate case item " << scope_name
|
||||
<< " detected direct nesting." << endl;
|
||||
@@ -1208,11 +1236,11 @@ void PGenerate::elaborate_subscope_(Design*des, NetScope*scope)
|
||||
scope->add_genvar((*cur).first, (*cur).second);
|
||||
}
|
||||
|
||||
// Scan the localparams in this scope, and store the information
|
||||
// Scan the parameters in this scope, and store the information
|
||||
// needed to evaluate the parameter expressions. The expressions
|
||||
// will be evaluated later, once all parameter overrides for this
|
||||
// module have been done.
|
||||
collect_scope_localparams_(des, scope, localparams);
|
||||
collect_scope_parameters(des, scope, parameters);
|
||||
|
||||
// Run through the defparams for this scope and save the result
|
||||
// in a table for later final override.
|
||||
@@ -1355,7 +1383,7 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
|
||||
return;
|
||||
}
|
||||
|
||||
if (msb_ || lsb_) {
|
||||
if (is_array()) {
|
||||
// If there are expressions to evaluate in order to know
|
||||
// the actual number of instances that will be
|
||||
// instantiated, then we have to delay further scope
|
||||
@@ -1385,41 +1413,17 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
|
||||
*/
|
||||
void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*sc) const
|
||||
{
|
||||
NetExpr*mse = msb_ ? elab_and_eval(des, sc, msb_, -1, true) : 0;
|
||||
NetExpr*lse = lsb_ ? elab_and_eval(des, sc, lsb_, -1, true) : 0;
|
||||
NetEConst*msb = dynamic_cast<NetEConst*> (mse);
|
||||
NetEConst*lsb = dynamic_cast<NetEConst*> (lse);
|
||||
|
||||
assert( (msb == 0) || (lsb != 0) );
|
||||
|
||||
long instance_low = 0;
|
||||
long instance_high = 0;
|
||||
long instance_count = 1;
|
||||
bool instance_array = false;
|
||||
|
||||
if (msb) {
|
||||
instance_array = true;
|
||||
instance_high = msb->value().as_long();
|
||||
instance_low = lsb->value().as_long();
|
||||
if (instance_high > instance_low)
|
||||
instance_count = instance_high - instance_low + 1;
|
||||
else
|
||||
instance_count = instance_low - instance_high + 1;
|
||||
|
||||
delete mse;
|
||||
delete lse;
|
||||
}
|
||||
long instance_count = calculate_array_size_(des, sc, instance_high, instance_low);
|
||||
if (instance_count == 0)
|
||||
return;
|
||||
|
||||
NetScope::scope_vec_t instances (instance_count);
|
||||
if (debug_scopes) {
|
||||
cerr << get_fileline() << ": debug: Create " << instance_count
|
||||
<< " instances of " << get_name()
|
||||
<< "." << endl;
|
||||
}
|
||||
|
||||
struct attrib_list_t*attrib_list;
|
||||
unsigned attrib_list_n = 0;
|
||||
attrib_list = evaluate_attributes(attributes, attrib_list_n, des, sc);
|
||||
struct attrib_list_t*attrib_list;
|
||||
unsigned attrib_list_n = 0;
|
||||
attrib_list = evaluate_attributes(attributes, attrib_list_n, des, sc);
|
||||
|
||||
// Run through the module instances, and make scopes out of
|
||||
// them. Also do parameter overrides that are done on the
|
||||
@@ -1428,8 +1432,8 @@ void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*s
|
||||
|
||||
hname_t use_name (get_name());
|
||||
|
||||
if (instance_array) {
|
||||
int instance_idx = idx;
|
||||
if (is_array()) {
|
||||
int instance_idx;
|
||||
if (instance_low < instance_high)
|
||||
instance_idx = instance_low + idx;
|
||||
else
|
||||
@@ -1483,8 +1487,21 @@ void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*s
|
||||
for (;;) {
|
||||
if (jdx == overrides_->end())
|
||||
break;
|
||||
if (cur == mod->param_names.end())
|
||||
// If we reached here we have more overrides than
|
||||
// module parameters, so print a warning.
|
||||
if (cur == mod->param_names.end()) {
|
||||
cerr << get_fileline() << ": warning: "
|
||||
"ignoring "
|
||||
<< overrides_->size() -
|
||||
mod->param_names.size()
|
||||
<< " extra parameter override(s) for "
|
||||
"instance '" << use_name
|
||||
<< "' of module '" << mod->mod_name()
|
||||
<< "' which expects "
|
||||
<< mod->param_names.size()
|
||||
<< " parameter(s)." << endl;
|
||||
break;
|
||||
}
|
||||
|
||||
// No expression means that the parameter is not
|
||||
// replaced at all.
|
||||
@@ -1545,7 +1562,7 @@ void PEvent::elaborate_scope(Design*, NetScope*scope) const
|
||||
|
||||
void PFunction::elaborate_scope(Design*des, NetScope*scope) const
|
||||
{
|
||||
assert(scope->type() == NetScope::FUNC);
|
||||
ivl_assert(*this, scope->type() == NetScope::FUNC);
|
||||
|
||||
// Save a reference to the pform representation of the function
|
||||
// in case we need to perform early elaboration.
|
||||
@@ -1560,9 +1577,7 @@ void PFunction::elaborate_scope(Design*des, NetScope*scope) const
|
||||
// Scan the parameters in the function, and store the information
|
||||
// needed to evaluate the parameter expressions.
|
||||
|
||||
collect_scope_parameters_(des, scope, parameters);
|
||||
|
||||
collect_scope_localparams_(des, scope, localparams);
|
||||
collect_scope_parameters(des, scope, parameters);
|
||||
|
||||
// Scan through all the named events in this scope.
|
||||
elaborate_scope_events_(des, scope, events);
|
||||
@@ -1580,9 +1595,7 @@ void PTask::elaborate_scope(Design*des, NetScope*scope) const
|
||||
// Scan the parameters in the task, and store the information
|
||||
// needed to evaluate the parameter expressions.
|
||||
|
||||
collect_scope_parameters_(des, scope, parameters);
|
||||
|
||||
collect_scope_localparams_(des, scope, localparams);
|
||||
collect_scope_parameters(des, scope, parameters);
|
||||
|
||||
// Scan through all the named events in this scope.
|
||||
elaborate_scope_events_(des, scope, events);
|
||||
@@ -1630,9 +1643,7 @@ void PBlock::elaborate_scope(Design*des, NetScope*scope) const
|
||||
// Scan the parameters in the scope, and store the information
|
||||
// needed to evaluate the parameter expressions.
|
||||
|
||||
collect_scope_parameters_(des, my_scope, parameters);
|
||||
|
||||
collect_scope_localparams_(des, my_scope, localparams);
|
||||
collect_scope_parameters(des, my_scope, parameters);
|
||||
|
||||
// Scan through all the named events in this scope.
|
||||
elaborate_scope_events_(des, my_scope, events);
|
||||
@@ -1650,7 +1661,7 @@ void PBlock::elaborate_scope(Design*des, NetScope*scope) const
|
||||
void PCase::elaborate_scope(Design*des, NetScope*scope) const
|
||||
{
|
||||
assert(items_);
|
||||
for (unsigned idx = 0 ; idx < (*items_).count() ; idx += 1) {
|
||||
for (unsigned idx = 0 ; idx < (*items_).size() ; idx += 1) {
|
||||
assert( (*items_)[idx] );
|
||||
|
||||
if (Statement*sp = (*items_)[idx]->stat)
|
||||
|
||||
+210
-327
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2020 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2021 Stephen Williams (steve@icarus.com)
|
||||
* Copyright CERN 2012 / Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
@@ -42,6 +42,7 @@
|
||||
# include "netdarray.h"
|
||||
# include "netparray.h"
|
||||
# include "netqueue.h"
|
||||
# include "netscalar.h"
|
||||
# include "util.h"
|
||||
# include "ivl_assert.h"
|
||||
|
||||
@@ -89,6 +90,92 @@ void Statement::elaborate_sig(Design*, NetScope*) const
|
||||
{
|
||||
}
|
||||
|
||||
static void sig_check_data_type(Design*des, NetScope*scope,
|
||||
PWire *wire, NetNet *sig)
|
||||
{
|
||||
ivl_type_t type = sig->net_type();
|
||||
|
||||
if (!type)
|
||||
return;
|
||||
|
||||
if (type->packed()) {
|
||||
switch (type->base_type()) {
|
||||
case IVL_VT_LOGIC: // 4-state packed is allowed by the standard
|
||||
case IVL_VT_BOOL: // Icarus allows 2-state packed as an extension
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Icarus allows real nets as an extension
|
||||
if (type->base_type() == IVL_VT_REAL)
|
||||
return;
|
||||
|
||||
if (wire->symbol_type() == PNamedItem::NET) {
|
||||
cerr << wire->get_fileline() << ": error: Net `"
|
||||
<< wire->basename() << "` can not be of type `"
|
||||
<< sig->data_type() << "`." << endl;
|
||||
des->errors++;
|
||||
} else if (scope->type() == NetScope::MODULE &&
|
||||
sig->port_type() != NetNet::NOT_A_PORT) {
|
||||
// Module ports only support wire types a the moment
|
||||
cerr << wire->get_fileline() << ": sorry: Port `"
|
||||
<< wire->basename() << "` of module `"
|
||||
<< scope->module_name()
|
||||
<< "` with type `" << sig->data_type()
|
||||
<< "` is not supported."
|
||||
<< endl;
|
||||
des->errors++;
|
||||
}
|
||||
}
|
||||
|
||||
static void sig_check_port_type(Design*des, NetScope*scope,
|
||||
PWire *wire, NetNet *sig)
|
||||
{
|
||||
if (sig->port_type() == NetNet::PREF) {
|
||||
cerr << wire->get_fileline() << ": sorry: "
|
||||
<< "Reference ports not supported yet." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
// Some extra checks for module ports
|
||||
if (scope->type() != NetScope::MODULE)
|
||||
return;
|
||||
|
||||
/* If the signal is an input and is also declared as a
|
||||
reg, then report an error. In SystemVerilog a input
|
||||
is allowed to be a register. It will get converted
|
||||
to a unresolved wire when the port is connected. */
|
||||
|
||||
if (sig->port_type() == NetNet::PINPUT &&
|
||||
sig->type() == NetNet::REG && !gn_var_can_be_uwire()) {
|
||||
cerr << wire->get_fileline() << ": error: Port `"
|
||||
<< wire->basename() << "` of module `"
|
||||
<< scope->module_name()
|
||||
<< "` is declared as input and as a reg type." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
if (sig->port_type() == NetNet::PINOUT &&
|
||||
sig->type() == NetNet::REG) {
|
||||
cerr << wire->get_fileline() << ": error: Port `"
|
||||
<< wire->basename() << "` of module `"
|
||||
<< scope->module_name()
|
||||
<< "` is declared as inout and as a reg type." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
if (sig->port_type() == NetNet::PINOUT &&
|
||||
sig->data_type() == IVL_VT_REAL) {
|
||||
cerr << wire->get_fileline() << ": error: Port `"
|
||||
<< wire->basename() << "` of module `"
|
||||
<< scope->module_name()
|
||||
<< "` is declared as a real inout port." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
}
|
||||
|
||||
bool PScope::elaborate_sig_wires_(Design*des, NetScope*scope) const
|
||||
{
|
||||
bool flag = true;
|
||||
@@ -99,53 +186,11 @@ bool PScope::elaborate_sig_wires_(Design*des, NetScope*scope) const
|
||||
PWire*cur = (*wt).second;
|
||||
NetNet*sig = cur->elaborate_sig(des, scope);
|
||||
|
||||
if (sig && (sig->scope() == scope)
|
||||
&& (sig->port_type() == NetNet::PREF)) {
|
||||
if (!sig || sig->scope() != scope)
|
||||
continue;
|
||||
|
||||
cerr << cur->get_fileline() << ": sorry: "
|
||||
<< "Reference ports not supported yet." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
|
||||
/* If the signal is an input and is also declared as a
|
||||
reg, then report an error. */
|
||||
|
||||
if (sig && (sig->scope() == scope)
|
||||
&& (scope->type() == NetScope::MODULE)
|
||||
&& (sig->port_type() == NetNet::PINPUT)
|
||||
&& (sig->type() == NetNet::REG)) {
|
||||
|
||||
cerr << cur->get_fileline() << ": error: Port "
|
||||
<< cur->basename() << " of module "
|
||||
<< scope->module_name()
|
||||
<< " is declared as input and as a reg type." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
if (sig && (sig->scope() == scope)
|
||||
&& (scope->type() == NetScope::MODULE)
|
||||
&& (sig->port_type() == NetNet::PINOUT)
|
||||
&& (sig->type() == NetNet::REG)) {
|
||||
|
||||
cerr << cur->get_fileline() << ": error: Port "
|
||||
<< cur->basename() << " of module "
|
||||
<< scope->module_name()
|
||||
<< " is declared as inout and as a reg type." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
if (sig && (sig->scope() == scope)
|
||||
&& (scope->type() == NetScope::MODULE)
|
||||
&& (sig->port_type() == NetNet::PINOUT)
|
||||
&& (sig->data_type() == IVL_VT_REAL)) {
|
||||
|
||||
cerr << cur->get_fileline() << ": error: Port "
|
||||
<< cur->basename() << " of module "
|
||||
<< scope->module_name()
|
||||
<< " is declared as a real inout port." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
sig_check_data_type(des, scope, cur, sig);
|
||||
sig_check_port_type(des, scope, cur, sig);
|
||||
|
||||
}
|
||||
|
||||
@@ -198,7 +243,7 @@ static void elaborate_sig_classes(Design*des, NetScope*scope,
|
||||
{
|
||||
for (map<perm_string,PClass*>::const_iterator cur = classes.begin()
|
||||
; cur != classes.end() ; ++ cur) {
|
||||
netclass_t*use_class = scope->find_class(cur->second->pscope_name());
|
||||
netclass_t*use_class = scope->find_class(des, cur->second->pscope_name());
|
||||
use_class->elaborate_sig(des, cur->second);
|
||||
}
|
||||
}
|
||||
@@ -329,9 +374,25 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const
|
||||
|
||||
void netclass_t::elaborate_sig(Design*des, PClass*pclass)
|
||||
{
|
||||
// Collect the properties, elaborate them, and add them to the
|
||||
// elaborated class definition.
|
||||
for (map<perm_string,struct class_type_t::prop_info_t>::iterator cur = pclass->type->properties.begin()
|
||||
; cur != pclass->type->properties.end() ; ++ cur) {
|
||||
|
||||
ivl_type_t use_type = cur->second.type->elaborate_type(des, class_scope_);
|
||||
if (debug_scopes) {
|
||||
cerr << pclass->get_fileline() << ": elaborate_scope_class: "
|
||||
<< " Property " << cur->first
|
||||
<< " type=" << *use_type << endl;
|
||||
}
|
||||
|
||||
if (dynamic_cast<const netqueue_t *> (use_type)) {
|
||||
cerr << cur->second.get_fileline() << ": sorry: "
|
||||
<< "Queues inside classes are not yet supported." << endl;
|
||||
des->errors++;
|
||||
}
|
||||
set_property(cur->first, cur->second.qual, use_type);
|
||||
|
||||
if (! cur->second.qual.test_static())
|
||||
continue;
|
||||
|
||||
@@ -343,7 +404,6 @@ void netclass_t::elaborate_sig(Design*des, PClass*pclass)
|
||||
}
|
||||
|
||||
list<netrange_t> nil_list;
|
||||
ivl_type_t use_type = cur->second.type->elaborate_type(des, class_scope_);
|
||||
/* NetNet*sig = */ new NetNet(class_scope_, cur->first, NetNet::REG,
|
||||
nil_list, use_type);
|
||||
}
|
||||
@@ -429,7 +489,7 @@ bool PGModule::elaborate_sig_udp_(Design*des, NetScope*scope, PUdp*udp) const
|
||||
|
||||
bool PGenerate::elaborate_sig(Design*des, NetScope*container) const
|
||||
{
|
||||
if (direct_nested_)
|
||||
if (directly_nested)
|
||||
return elaborate_sig_direct_(des, container);
|
||||
|
||||
bool flag = true;
|
||||
@@ -448,7 +508,7 @@ bool PGenerate::elaborate_sig(Design*des, NetScope*container) const
|
||||
for (generate_it_t cur = generate_schemes.begin()
|
||||
; cur != generate_schemes.end() ; ++ cur ) {
|
||||
PGenerate*item = *cur;
|
||||
if (item->direct_nested_ || !item->scope_list_.empty()) {
|
||||
if (item->directly_nested || !item->scope_list_.empty()) {
|
||||
flag &= item->elaborate_sig(des, container);
|
||||
}
|
||||
}
|
||||
@@ -496,12 +556,12 @@ bool PGenerate::elaborate_sig_direct_(Design*des, NetScope*container) const
|
||||
for (generate_it_t icur = item->generate_schemes.begin()
|
||||
; icur != item->generate_schemes.end() ; ++ icur ) {
|
||||
PGenerate*case_item = *icur;
|
||||
if (case_item->direct_nested_ || !case_item->scope_list_.empty()) {
|
||||
if (case_item->directly_nested || !case_item->scope_list_.empty()) {
|
||||
flag &= case_item->elaborate_sig(des, container);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (item->direct_nested_ || !item->scope_list_.empty()) {
|
||||
if (item->directly_nested || !item->scope_list_.empty()) {
|
||||
// Found the item, and it is direct nested.
|
||||
flag &= item->elaborate_sig(des, container);
|
||||
}
|
||||
@@ -578,10 +638,10 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
||||
// source code for the definition may be:
|
||||
// function new(...);
|
||||
// endfunction
|
||||
// In this case, the "@" port is the synthetic "this"
|
||||
// argument and we also use it as a return value at the
|
||||
// same time.
|
||||
ret_sig = scope->find_signal(perm_string::literal("@"));
|
||||
// In this case, the "@" port (THIS_TOKEN) is the synthetic
|
||||
// "this" argument and we also use it as a return value at
|
||||
// the same time.
|
||||
ret_sig = scope->find_signal(perm_string::literal(THIS_TOKEN));
|
||||
ivl_assert(*this, ret_sig);
|
||||
|
||||
if (debug_elaborate)
|
||||
@@ -602,7 +662,6 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
||||
}
|
||||
} else {
|
||||
netvector_t*tmp = new netvector_t(IVL_VT_LOGIC);
|
||||
tmp->set_scalar(true);
|
||||
ret_type = tmp;
|
||||
}
|
||||
|
||||
@@ -719,8 +778,19 @@ void PTaskFunc::elaborate_sig_ports_(Design*des, NetScope*scope,
|
||||
// that expression here.
|
||||
if (ports_->at(idx).defe != 0) {
|
||||
if (tmp->port_type() == NetNet::PINPUT) {
|
||||
tmp_def = elab_and_eval(des, scope, ports_->at(idx).defe,
|
||||
-1, scope->need_const_func());
|
||||
// Elaborate a class port default in the context of
|
||||
// the class type.
|
||||
if (tmp->data_type() == IVL_VT_CLASS) {
|
||||
tmp_def = elab_and_eval(des, scope,
|
||||
ports_->at(idx).defe,
|
||||
tmp->net_type(),
|
||||
scope->need_const_func());
|
||||
} else {
|
||||
tmp_def = elab_and_eval(des, scope,
|
||||
ports_->at(idx).defe,
|
||||
-1,
|
||||
scope->need_const_func());
|
||||
}
|
||||
if (tmp_def == 0) {
|
||||
cerr << get_fileline()
|
||||
<< ": error: Unable to evaluate "
|
||||
@@ -799,7 +869,7 @@ void PCase::elaborate_sig(Design*des, NetScope*scope) const
|
||||
if (items_ == 0)
|
||||
return;
|
||||
|
||||
for (unsigned idx = 0 ; idx < items_->count() ; idx += 1) {
|
||||
for (unsigned idx = 0 ; idx < items_->size() ; idx += 1) {
|
||||
if ( (*items_)[idx]->stat )
|
||||
(*items_)[idx]->stat ->elaborate_sig(des,scope);
|
||||
}
|
||||
@@ -861,37 +931,6 @@ void PWhile::elaborate_sig(Design*des, NetScope*scope) const
|
||||
statement_->elaborate_sig(des, scope);
|
||||
}
|
||||
|
||||
static ivl_type_s*elaborate_type(Design*des, NetScope*scope,
|
||||
data_type_t*pform_type)
|
||||
{
|
||||
if (struct_type_t*struct_type = dynamic_cast<struct_type_t*>(pform_type)) {
|
||||
ivl_type_s*use_type = struct_type->elaborate_type(des, scope);
|
||||
return use_type;
|
||||
}
|
||||
|
||||
cerr << pform_type->get_fileline() << ": sorry: I don't know how to elaborate "
|
||||
<< typeid(*pform_type).name() << " here." << endl;
|
||||
des->errors += 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static netparray_t* elaborate_parray_type(Design*des, NetScope*scope, const LineInfo*li,
|
||||
parray_type_t*data_type)
|
||||
{
|
||||
|
||||
vector<netrange_t>packed_dimensions;
|
||||
bool dimensions_ok = evaluate_ranges(des, scope, li, packed_dimensions, * data_type->dims);
|
||||
ivl_assert(*data_type, dimensions_ok);
|
||||
|
||||
ivl_type_s*element_type = elaborate_type(des, scope, data_type->base_type);
|
||||
|
||||
netparray_t*res = new netparray_t(packed_dimensions, element_type);
|
||||
//res->set_line(*data_type);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
bool test_ranges_eeq(const vector<netrange_t>&lef, const vector<netrange_t>&rig)
|
||||
{
|
||||
if (lef.size() != rig.size())
|
||||
@@ -912,6 +951,43 @@ bool test_ranges_eeq(const vector<netrange_t>&lef, const vector<netrange_t>&rig)
|
||||
return true;
|
||||
}
|
||||
|
||||
ivl_type_t PWire::elaborate_type(Design*des, NetScope*scope,
|
||||
const std::vector<netrange_t>&packed_dimensions) const
|
||||
{
|
||||
vector_type_t *vec_type = dynamic_cast<vector_type_t*>(set_data_type_.get());
|
||||
if (set_data_type_ && !vec_type) {
|
||||
ivl_assert(*this, packed_dimensions.empty());
|
||||
return set_data_type_->elaborate_type(des, scope);
|
||||
}
|
||||
|
||||
// Fallback method. Create vector type.
|
||||
|
||||
ivl_variable_type_t use_data_type;
|
||||
if (vec_type) {
|
||||
use_data_type = vec_type->base_type;
|
||||
} else {
|
||||
use_data_type = IVL_VT_LOGIC;
|
||||
}
|
||||
|
||||
if (use_data_type == IVL_VT_NO_TYPE) {
|
||||
use_data_type = IVL_VT_LOGIC;
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PWire::elaborate_sig: "
|
||||
<< "Signal " << name_
|
||||
<< " in scope " << scope_path(scope)
|
||||
<< " defaults to data type " << use_data_type << endl;
|
||||
}
|
||||
}
|
||||
|
||||
ivl_assert(*this, use_data_type == IVL_VT_LOGIC ||
|
||||
use_data_type == IVL_VT_BOOL);
|
||||
|
||||
netvector_t*vec = new netvector_t(packed_dimensions, use_data_type);
|
||||
vec->set_signed(get_signed());
|
||||
|
||||
return vec;
|
||||
}
|
||||
|
||||
/*
|
||||
* Elaborate a source wire. The "wire" is the declaration of wires,
|
||||
* registers, ports and memories. The parser has already merged the
|
||||
@@ -927,38 +1003,28 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
const long warn_dimension_size = 1 << 30;
|
||||
|
||||
NetNet::Type wtype = type_;
|
||||
bool is_implicit_scalar = false;
|
||||
if (wtype == NetNet::IMPLICIT) {
|
||||
if (wtype == NetNet::IMPLICIT)
|
||||
wtype = NetNet::WIRE;
|
||||
is_implicit_scalar = true;
|
||||
}
|
||||
|
||||
// Certain contexts, such as arguments to functions, presume
|
||||
// "reg" instead of "wire". The parser reports these as
|
||||
// IMPLICIT_REG. Also, certain cases, such as:
|
||||
// fun(string arg1) ...
|
||||
// are implicitly NOT scalar, so detect that case here.
|
||||
if (wtype == NetNet::IMPLICIT_REG) {
|
||||
// IMPLICIT_REG.
|
||||
if (wtype == NetNet::IMPLICIT_REG)
|
||||
wtype = NetNet::REG;
|
||||
if (data_type_!=IVL_VT_STRING)
|
||||
is_implicit_scalar = true;
|
||||
}
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PWire::elaborate_sig: "
|
||||
<< "Signal " << basename()
|
||||
<< ", wtype=" << wtype
|
||||
<< ", data_type_=" << data_type_
|
||||
<< ", is_implicit_scalar=" << (is_implicit_scalar?"true":"false")
|
||||
<< ", wtype=" << wtype;
|
||||
if (set_data_type_)
|
||||
cerr << ", set_data_type_=" << *set_data_type_;
|
||||
cerr << ", unpacked_.size()=" << unpacked_.size()
|
||||
<< endl;
|
||||
}
|
||||
|
||||
unsigned wid = 1;
|
||||
vector<netrange_t>packed_dimensions;
|
||||
|
||||
NetScope*base_type_scope = scope;
|
||||
if (set_data_type_ && !set_data_type_->name.nil())
|
||||
base_type_scope = scope->find_typedef_scope(des, set_data_type_);
|
||||
|
||||
des->errors += error_cnt_;
|
||||
|
||||
if (port_set_ || net_set_) {
|
||||
@@ -988,9 +1054,6 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
<< "Evaluate ranges for port " << basename() << endl;
|
||||
}
|
||||
dimensions_ok &= evaluate_ranges(des, scope, this, plist, port_);
|
||||
nlist = plist;
|
||||
/* An implicit port can have a range so note that here. */
|
||||
is_implicit_scalar = false;
|
||||
}
|
||||
assert(port_set_ || port_.empty());
|
||||
|
||||
@@ -1001,7 +1064,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
cerr << get_fileline() << ": PWire::elaborate_sig: "
|
||||
<< "Evaluate ranges for net " << basename() << endl;
|
||||
}
|
||||
dimensions_ok &= evaluate_ranges(des, base_type_scope, this, nlist, net_);
|
||||
dimensions_ok &= evaluate_ranges(des, scope, this, nlist, net_);
|
||||
}
|
||||
assert(net_set_ || net_.empty());
|
||||
|
||||
@@ -1011,23 +1074,23 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
<< ". Now check for consistency." << endl;
|
||||
}
|
||||
|
||||
/* We have a port size error */
|
||||
if (port_set_ && net_set_ && !test_ranges_eeq(plist, nlist)) {
|
||||
|
||||
/* We have a port size error. Skip this if the dimensions could not
|
||||
* be evaluated since it will likely print nonsensical errors. */
|
||||
if (port_set_ && net_set_ && !test_ranges_eeq(plist, nlist) &&
|
||||
dimensions_ok) {
|
||||
/* Scalar port with a vector net/etc. definition */
|
||||
if (port_.empty()) {
|
||||
if (!gn_io_range_error_flag) {
|
||||
cerr << get_fileline()
|
||||
<< ": warning: Scalar port ``" << name_
|
||||
<< "'' has a vectored net declaration "
|
||||
<< nlist << "." << endl;
|
||||
} else {
|
||||
if (gn_io_range_error_flag) {
|
||||
cerr << get_fileline()
|
||||
<< ": error: Scalar port ``" << name_
|
||||
<< "'' has a vectored net declaration "
|
||||
<< nlist << "." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
} else if (warn_anachronisms) {
|
||||
cerr << get_fileline()
|
||||
<< ": warning: Scalar port ``" << name_
|
||||
<< "'' has a vectored net declaration "
|
||||
<< nlist << "." << endl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1039,7 +1102,6 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
<< " has a scalar net declaration at "
|
||||
<< get_fileline() << "." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Both vectored, but they have different ranges. */
|
||||
@@ -1051,11 +1113,10 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
<< " at " << net_.front().first->get_fileline()
|
||||
<< " that does not match." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
packed_dimensions = nlist;
|
||||
packed_dimensions = net_set_ ? nlist : plist;
|
||||
wid = netrange_width(packed_dimensions);
|
||||
if (wid > warn_dimension_size) {
|
||||
cerr << get_fileline() << ": warning: Vector size "
|
||||
@@ -1068,97 +1129,6 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
attrib_list_t*attrib_list = evaluate_attributes(attributes, nattrib,
|
||||
des, scope);
|
||||
|
||||
|
||||
list<netrange_t>unpacked_dimensions;
|
||||
netdarray_t*netdarray = 0;
|
||||
|
||||
NetScope*array_type_scope = scope;
|
||||
if (uarray_type_ && !uarray_type_->name.nil())
|
||||
array_type_scope = scope->find_typedef_scope(des, uarray_type_);
|
||||
|
||||
for (list<pform_range_t>::const_iterator cur = unpacked_.begin()
|
||||
; cur != unpacked_.end() ; ++cur) {
|
||||
PExpr*use_lidx = cur->first;
|
||||
PExpr*use_ridx = cur->second;
|
||||
|
||||
// Special case: If we encounter an undefined
|
||||
// dimensions, then turn this into a dynamic array and
|
||||
// put all the packed dimensions there.
|
||||
if (use_lidx==0 && use_ridx==0) {
|
||||
netvector_t*vec = new netvector_t(packed_dimensions, data_type_);
|
||||
vec->set_signed(get_signed());
|
||||
packed_dimensions.clear();
|
||||
ivl_assert(*this, netdarray==0);
|
||||
netdarray = new netdarray_t(vec);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Special case: Detect the mark for a QUEUE
|
||||
// declaration, which is the dimensions [null:max_idx].
|
||||
if (dynamic_cast<PENull*>(use_lidx)) {
|
||||
netvector_t*vec = new netvector_t(packed_dimensions, data_type_);
|
||||
vec->set_signed(get_signed());
|
||||
packed_dimensions.clear();
|
||||
ivl_assert(*this, netdarray==0);
|
||||
long max_idx;
|
||||
if (use_ridx) {
|
||||
NetExpr*tmp = elab_and_eval(des, array_type_scope, use_ridx,
|
||||
-1, true);
|
||||
NetEConst*cv = dynamic_cast<NetEConst*>(tmp);
|
||||
if (cv == 0) {
|
||||
cerr << get_fileline() << ": error: queue '" << name_
|
||||
<< "' bound must be a constant!" << endl;
|
||||
des->errors += 1;
|
||||
max_idx = -1;
|
||||
} else {
|
||||
verinum res = cv->value();
|
||||
if (res.is_defined()) {
|
||||
max_idx = res.as_long();
|
||||
if (max_idx < 0) {
|
||||
cerr << get_fileline() << ": error: queue '"
|
||||
<< name_ << "' bound must be positive ("
|
||||
<< max_idx << ")!" << endl;
|
||||
des->errors += 1;
|
||||
max_idx = -1;
|
||||
}
|
||||
} else {
|
||||
cerr << get_fileline() << ": error: queue '" << name_
|
||||
<< "' bound is undefined!" << endl;
|
||||
des->errors += 1;
|
||||
max_idx = -1;
|
||||
}
|
||||
}
|
||||
} else max_idx = -1;
|
||||
netdarray = new netqueue_t(vec, max_idx);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Cannot handle dynamic arrays of arrays yet.
|
||||
ivl_assert(*this, netdarray==0);
|
||||
|
||||
long index_l, index_r;
|
||||
evaluate_range(des, array_type_scope, this, *cur, index_l, index_r);
|
||||
|
||||
if (abs(index_r - index_l) > warn_dimension_size) {
|
||||
cerr << get_fileline() << ": warning: Array dimension "
|
||||
"is greater than " << warn_dimension_size
|
||||
<< "." << endl;
|
||||
}
|
||||
|
||||
unpacked_dimensions.push_back(netrange_t(index_l, index_r));
|
||||
}
|
||||
|
||||
if (data_type_ == IVL_VT_REAL && !packed_dimensions.empty()) {
|
||||
cerr << get_fileline() << ": error: real ";
|
||||
if (wtype == NetNet::REG) cerr << "variable";
|
||||
else cerr << "net";
|
||||
cerr << " '" << name_
|
||||
<< "' cannot be declared as a vector, found a range "
|
||||
<< packed_dimensions << "." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If the net type is supply0 or supply1, replace it
|
||||
with a simple wire with a pulldown/pullup with supply
|
||||
strength. In other words, transform:
|
||||
@@ -1195,118 +1165,31 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
wtype = NetNet::WIRE;
|
||||
}
|
||||
|
||||
ivl_type_t type = elaborate_type(des, scope, packed_dimensions);
|
||||
// Create the type for the unpacked dimensions. If the
|
||||
// unpacked_dimensions are empty this will just return the base type.
|
||||
type = elaborate_array_type(des, scope, *this, type, unpacked_);
|
||||
|
||||
NetNet*sig = 0;
|
||||
|
||||
if (class_type_t*class_type = dynamic_cast<class_type_t*>(set_data_type_)) {
|
||||
// If this is a class variable, then the class type
|
||||
// should already have been elaborated. All we need to
|
||||
// do right now is locate the netclass_t object for the
|
||||
// class, and use that to build the net.
|
||||
|
||||
ivl_assert(*this, class_type->save_elaborated_type);
|
||||
netclass_t*use_type = class_type->save_elaborated_type;
|
||||
|
||||
sig = new NetNet(scope, name_, wtype, unpacked_dimensions, use_type);
|
||||
|
||||
} else if (struct_type_t*struct_type = dynamic_cast<struct_type_t*>(set_data_type_)) {
|
||||
// If this is a struct type, then build the net with the
|
||||
// struct type.
|
||||
ivl_type_s*tmp_type = struct_type->elaborate_type(des, scope);
|
||||
netstruct_t*use_type = dynamic_cast<netstruct_t*>(tmp_type);
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: Create signal " << wtype;
|
||||
if (use_type->packed())
|
||||
cerr << " " << use_type->packed_width() << " bit packed struct ";
|
||||
else
|
||||
cerr << " struct <> ";
|
||||
cerr << name_;
|
||||
cerr << " in scope " << scope_path(scope) << endl;
|
||||
}
|
||||
|
||||
sig = new NetNet(scope, name_, wtype, unpacked_dimensions, use_type);
|
||||
|
||||
} else if (enum_type_t*enum_type = dynamic_cast<enum_type_t*>(set_data_type_)) {
|
||||
list<named_pexpr_t>::const_iterator sample_name = enum_type->names->begin();
|
||||
const netenum_t*use_enum = base_type_scope->find_enumeration_for_name(des, sample_name->name);
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: Create signal " << wtype
|
||||
<< " enumeration "
|
||||
<< name_ << " in scope " << scope_path(scope)
|
||||
<< " with packed_dimensions=" << packed_dimensions
|
||||
<< " and packed_width=" << use_enum->packed_width() << endl;
|
||||
}
|
||||
|
||||
ivl_assert(*this, packed_dimensions.empty());
|
||||
sig = new NetNet(scope, name_, wtype, unpacked_dimensions, use_enum);
|
||||
|
||||
|
||||
} else if (netdarray) {
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: Create signal " << wtype
|
||||
<< " dynamic array "
|
||||
<< name_ << " in scope " << scope_path(scope) << endl;
|
||||
}
|
||||
|
||||
ivl_assert(*this, packed_dimensions.empty());
|
||||
ivl_assert(*this, unpacked_dimensions.empty());
|
||||
sig = new NetNet(scope, name_, wtype, netdarray);
|
||||
|
||||
} else if (parray_type_t*parray_type = dynamic_cast<parray_type_t*>(set_data_type_)) {
|
||||
// The pform gives us a parray_type_t for packed arrays
|
||||
// that show up in type definitions. This can be handled
|
||||
// a lot like packed dimensions from other means.
|
||||
|
||||
// The trick here is that the parray type has an
|
||||
// arbitrary sub-type, and not just a scalar bit...
|
||||
netparray_t*use_type = elaborate_parray_type(des, scope, this, parray_type);
|
||||
// Should not be getting packed dimensions other than
|
||||
// through the parray type declaration.
|
||||
ivl_assert(*this, packed_dimensions.empty());
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: Create signal " << wtype
|
||||
<< " parray=" << use_type->static_dimensions()
|
||||
<< " " << name_ << unpacked_dimensions
|
||||
<< " in scope " << scope_path(scope) << endl;
|
||||
}
|
||||
|
||||
sig = new NetNet(scope, name_, wtype, unpacked_dimensions, use_type);
|
||||
|
||||
|
||||
} else {
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: Create signal " << wtype;
|
||||
if (!get_scalar()) {
|
||||
cerr << " " << packed_dimensions;
|
||||
}
|
||||
cerr << " " << name_ << unpacked_dimensions;
|
||||
cerr << " in scope " << scope_path(scope) << endl;
|
||||
}
|
||||
|
||||
ivl_variable_type_t use_data_type = data_type_;
|
||||
if (use_data_type == IVL_VT_NO_TYPE) {
|
||||
use_data_type = IVL_VT_LOGIC;
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: "
|
||||
<< "Signal " << name_
|
||||
<< " in scope " << scope_path(scope)
|
||||
<< " defaults to data type " << use_data_type << endl;
|
||||
}
|
||||
}
|
||||
|
||||
netvector_t*vec = new netvector_t(packed_dimensions, use_data_type);
|
||||
vec->set_signed(get_signed());
|
||||
vec->set_isint(get_isint());
|
||||
if (is_implicit_scalar) vec->set_scalar(true);
|
||||
else vec->set_scalar(get_scalar());
|
||||
packed_dimensions.clear();
|
||||
sig = new NetNet(scope, name_, wtype, unpacked_dimensions, vec);
|
||||
|
||||
list<netrange_t> unpacked_dimensions;
|
||||
// If this is an unpacked array extract the base type and unpacked
|
||||
// dimensions as these are separate properties of the NetNet.
|
||||
while (const netuarray_t *atype = dynamic_cast<const netuarray_t*>(type)) {
|
||||
unpacked_dimensions.insert(unpacked_dimensions.begin(),
|
||||
atype->static_dimensions().begin(),
|
||||
atype->static_dimensions().end());
|
||||
type = atype->element_type();
|
||||
}
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: Create signal " << wtype;
|
||||
if (set_data_type_)
|
||||
cout << " " << *set_data_type_;
|
||||
cout << name_ << unpacked_dimensions << " in scope "
|
||||
<< scope_path(scope) << endl;
|
||||
}
|
||||
|
||||
NetNet*sig = new NetNet(scope, name_, wtype, unpacked_dimensions, type);
|
||||
|
||||
if (wtype == NetNet::WIRE) sig->devirtualize_pins();
|
||||
sig->set_line(*this);
|
||||
sig->port_type(port_type_);
|
||||
|
||||
+323
-108
@@ -18,6 +18,7 @@
|
||||
*/
|
||||
|
||||
# include "PExpr.h"
|
||||
# include "PScope.h"
|
||||
# include "pform_types.h"
|
||||
# include "netlist.h"
|
||||
# include "netclass.h"
|
||||
@@ -34,68 +35,44 @@
|
||||
|
||||
using namespace std;
|
||||
|
||||
/*
|
||||
* Some types have a list of ranges that need to be elaborated. This
|
||||
* function elaborates the ranges referenced by "dims" into the vector
|
||||
* "ranges".
|
||||
*/
|
||||
static void elaborate_array_ranges(Design*des, NetScope*scope,
|
||||
vector<netrange_t>&ranges,
|
||||
const list<pform_range_t>*dims)
|
||||
{
|
||||
if (dims == 0)
|
||||
return;
|
||||
|
||||
for (list<pform_range_t>::const_iterator cur = dims->begin()
|
||||
; cur != dims->end() ; ++ cur) {
|
||||
|
||||
NetExpr*me = elab_and_eval(des, scope, cur->first, 0, true);
|
||||
|
||||
NetExpr*le = elab_and_eval(des, scope, cur->second, 0, true);
|
||||
|
||||
/* If elaboration failed for either expression, we
|
||||
should have already reported the error, so just
|
||||
skip the following evaluation to recover. */
|
||||
|
||||
long mnum = 0, lnum = 0;
|
||||
if ( me && ! eval_as_long(mnum, me) ) {
|
||||
assert(0);
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
if ( le && ! eval_as_long(lnum, le) ) {
|
||||
assert(0);
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
ranges.push_back(netrange_t(mnum, lnum));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Elaborations of types may vary depending on the scope that it is
|
||||
* done in, so keep a per-scope cache of the results.
|
||||
*/
|
||||
ivl_type_s* data_type_t::elaborate_type(Design*des, NetScope*scope)
|
||||
ivl_type_t data_type_t::elaborate_type(Design*des, NetScope*scope)
|
||||
{
|
||||
// User-defined types must be elaborated in the context
|
||||
// where they were defined.
|
||||
if (!name.nil())
|
||||
scope = scope->find_typedef_scope(des, this);
|
||||
scope = find_scope(des, scope);
|
||||
|
||||
ivl_assert(*this, scope);
|
||||
Definitions*use_definitions = scope;
|
||||
|
||||
map<Definitions*,ivl_type_s*>::iterator pos = cache_type_elaborate_.lower_bound(use_definitions);
|
||||
map<Definitions*,ivl_type_t>::iterator pos = cache_type_elaborate_.lower_bound(use_definitions);
|
||||
if (pos != cache_type_elaborate_.end() && pos->first == use_definitions)
|
||||
return pos->second;
|
||||
|
||||
ivl_type_s*tmp = elaborate_type_raw(des, scope);
|
||||
cache_type_elaborate_.insert(pos, pair<NetScope*,ivl_type_s*>(scope, tmp));
|
||||
ivl_type_t tmp;
|
||||
if (elaborating) {
|
||||
des->errors++;
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< "Circular type definition found involving `" << *this << "`."
|
||||
<< endl;
|
||||
// Try to recover
|
||||
tmp = netvector_t::integer_type();
|
||||
} else {
|
||||
elaborating = true;
|
||||
tmp = elaborate_type_raw(des, scope);
|
||||
elaborating = false;
|
||||
}
|
||||
|
||||
cache_type_elaborate_.insert(pos, pair<NetScope*,ivl_type_t>(scope, tmp));
|
||||
return tmp;
|
||||
}
|
||||
|
||||
ivl_type_s* data_type_t::elaborate_type_raw(Design*des, NetScope*) const
|
||||
NetScope *data_type_t::find_scope(Design *, NetScope *scope) const
|
||||
{
|
||||
return scope;
|
||||
}
|
||||
|
||||
ivl_type_t data_type_t::elaborate_type_raw(Design*des, NetScope*) const
|
||||
{
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<< "Elaborate method not implemented for " << typeid(*this).name()
|
||||
@@ -104,28 +81,37 @@ ivl_type_s* data_type_t::elaborate_type_raw(Design*des, NetScope*) const
|
||||
return 0;
|
||||
}
|
||||
|
||||
ivl_type_s* atom2_type_t::elaborate_type_raw(Design*des, NetScope*) const
|
||||
ivl_type_t atom_type_t::elaborate_type_raw(Design*des, NetScope*) const
|
||||
{
|
||||
switch (type_code) {
|
||||
case 64:
|
||||
case INTEGER:
|
||||
return netvector_t::integer_type(signed_flag);
|
||||
|
||||
case TIME:
|
||||
if (signed_flag)
|
||||
return &netvector_t::time_signed;
|
||||
else
|
||||
return &netvector_t::time_unsigned;
|
||||
|
||||
case LONGINT:
|
||||
if (signed_flag)
|
||||
return &netvector_t::atom2s64;
|
||||
else
|
||||
return &netvector_t::atom2u64;
|
||||
|
||||
case 32:
|
||||
case INT:
|
||||
if (signed_flag)
|
||||
return &netvector_t::atom2s32;
|
||||
else
|
||||
return &netvector_t::atom2u32;
|
||||
|
||||
case 16:
|
||||
case SHORTINT:
|
||||
if (signed_flag)
|
||||
return &netvector_t::atom2s16;
|
||||
else
|
||||
return &netvector_t::atom2u16;
|
||||
|
||||
case 8:
|
||||
case BYTE:
|
||||
if (signed_flag)
|
||||
return &netvector_t::atom2s8;
|
||||
else
|
||||
@@ -133,16 +119,15 @@ ivl_type_s* atom2_type_t::elaborate_type_raw(Design*des, NetScope*) const
|
||||
|
||||
default:
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<< "atom2_type_t type_code=" << type_code << "." << endl;
|
||||
<< "atom_type_t type_code=" << type_code << "." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
ivl_type_s* class_type_t::elaborate_type_raw(Design*, NetScope*) const
|
||||
ivl_type_t class_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
|
||||
{
|
||||
ivl_assert(*this, save_elaborated_type);
|
||||
return save_elaborated_type;
|
||||
return scope->find_class(des, name);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -151,31 +136,53 @@ ivl_type_s* class_type_t::elaborate_type_raw(Design*, NetScope*) const
|
||||
* available at the right time. At that time, the netenum_t* object is
|
||||
* stashed in the scope so that I can retrieve it here.
|
||||
*/
|
||||
ivl_type_s* enum_type_t::elaborate_type_raw(Design*, NetScope*scope) const
|
||||
ivl_type_t enum_type_t::elaborate_type_raw(Design *des, NetScope *scope) const
|
||||
{
|
||||
ivl_assert(*this, scope);
|
||||
ivl_type_s*tmp = scope->enumeration_for_key(this);
|
||||
if (tmp == 0 && scope->unit()) {
|
||||
tmp = scope->unit()->enumeration_for_key(this);
|
||||
}
|
||||
return tmp;
|
||||
ivl_type_t base = base_type->elaborate_type(des, scope);
|
||||
|
||||
const class netvector_t *vec_type = dynamic_cast<const netvector_t*>(base);
|
||||
|
||||
if (!vec_type && !dynamic_cast<const netparray_t*>(base)) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< "Invalid enum base type `" << *base << "`."
|
||||
<< endl;
|
||||
des->errors++;
|
||||
} else if (base->slice_dimensions().size() > 1) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< "Enum type must not have more than 1 packed dimension."
|
||||
<< endl;
|
||||
des->errors++;
|
||||
}
|
||||
|
||||
bool integer_flag = false;
|
||||
if (vec_type)
|
||||
integer_flag = vec_type->get_isint();
|
||||
|
||||
netenum_t *type = new netenum_t(base, names->size(), integer_flag);
|
||||
type->set_line(*this);
|
||||
|
||||
scope->add_enumeration_set(this, type);
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
ivl_type_s* vector_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
|
||||
ivl_type_t vector_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
|
||||
{
|
||||
vector<netrange_t> packed;
|
||||
elaborate_array_ranges(des, scope, packed, pdims.get());
|
||||
if (pdims.get())
|
||||
evaluate_ranges(des, scope, this, packed, *pdims);
|
||||
|
||||
netvector_t*tmp = new netvector_t(packed, base_type);
|
||||
tmp->set_signed(signed_flag);
|
||||
tmp->set_isint(integer_flag);
|
||||
tmp->set_implicit(implicit_flag);
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
ivl_type_s* real_type_t::elaborate_type_raw(Design*, NetScope*) const
|
||||
ivl_type_t real_type_t::elaborate_type_raw(Design*, NetScope*) const
|
||||
{
|
||||
switch (type_code) {
|
||||
switch (type_code_) {
|
||||
case REAL:
|
||||
return &netreal_t::type_real;
|
||||
case SHORTREAL:
|
||||
@@ -184,26 +191,37 @@ ivl_type_s* real_type_t::elaborate_type_raw(Design*, NetScope*) const
|
||||
return 0;
|
||||
}
|
||||
|
||||
ivl_type_s* string_type_t::elaborate_type_raw(Design*, NetScope*) const
|
||||
ivl_type_t string_type_t::elaborate_type_raw(Design*, NetScope*) const
|
||||
{
|
||||
return &netstring_t::type_string;
|
||||
}
|
||||
|
||||
ivl_type_s* parray_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
|
||||
ivl_type_t parray_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
|
||||
{
|
||||
vector<netrange_t>packed;
|
||||
elaborate_array_ranges(des, scope, packed, dims.get());
|
||||
if (dims.get())
|
||||
evaluate_ranges(des, scope, this, packed, *dims);
|
||||
|
||||
ivl_type_t etype = base_type->elaborate_type(des, scope);
|
||||
if (!etype->packed()) {
|
||||
cerr << this->get_fileline() << " error: Packed array ";
|
||||
cerr << "base-type `";
|
||||
cerr << *base_type;
|
||||
cerr << "` is not packed." << endl;
|
||||
des->errors++;
|
||||
}
|
||||
|
||||
return new netparray_t(packed, etype);
|
||||
}
|
||||
|
||||
netstruct_t* struct_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
|
||||
ivl_type_t struct_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
|
||||
{
|
||||
netstruct_t*res = new netstruct_t;
|
||||
|
||||
res->set_line(*this);
|
||||
|
||||
res->packed(packed_flag);
|
||||
res->set_signed(signed_flag);
|
||||
|
||||
if (union_flag)
|
||||
res->union_flag(true);
|
||||
@@ -226,7 +244,8 @@ netstruct_t* struct_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
|
||||
|
||||
netstruct_t::member_t memb;
|
||||
memb.name = namep->name;
|
||||
memb.net_type = mem_vec;
|
||||
memb.net_type = elaborate_array_type(des, scope, *this,
|
||||
mem_vec, namep->index);
|
||||
res->append_member(des, memb);
|
||||
}
|
||||
}
|
||||
@@ -234,43 +253,239 @@ netstruct_t* struct_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
|
||||
return res;
|
||||
}
|
||||
|
||||
ivl_type_s* uarray_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
|
||||
static ivl_type_t elaborate_darray_check_type(Design *des, const LineInfo &li,
|
||||
ivl_type_t type,
|
||||
const char *darray_type)
|
||||
{
|
||||
if (dynamic_cast<const netvector_t*>(type) ||
|
||||
dynamic_cast<const netparray_t*>(type) ||
|
||||
dynamic_cast<const netreal_t*>(type) ||
|
||||
dynamic_cast<const netstring_t*>(type))
|
||||
return type;
|
||||
|
||||
cerr << li.get_fileline() << ": Sorry: "
|
||||
<< darray_type << " of type `" << *type
|
||||
<< "` is not yet supported." << endl;
|
||||
des->errors++;
|
||||
|
||||
// Return something to recover
|
||||
return new netvector_t(IVL_VT_LOGIC);
|
||||
}
|
||||
|
||||
static ivl_type_t elaborate_queue_type(Design *des, NetScope *scope,
|
||||
const LineInfo &li, ivl_type_t base_type,
|
||||
PExpr *ridx)
|
||||
{
|
||||
base_type = elaborate_darray_check_type(des, li, base_type, "Queue");
|
||||
|
||||
long max_idx = -1;
|
||||
if (ridx) {
|
||||
NetExpr*tmp = elab_and_eval(des, scope, ridx, -1, true);
|
||||
NetEConst*cv = dynamic_cast<NetEConst*>(tmp);
|
||||
if (cv == 0) {
|
||||
cerr << li.get_fileline() << ": error: "
|
||||
<< "queue bound must be constant."
|
||||
<< endl;
|
||||
des->errors++;
|
||||
} else {
|
||||
verinum res = cv->value();
|
||||
if (res.is_defined()) {
|
||||
max_idx = res.as_long();
|
||||
if (max_idx < 0) {
|
||||
cerr << li.get_fileline() << ": error: "
|
||||
<< "queue bound must be positive ("
|
||||
<< max_idx << ")." << endl;
|
||||
des->errors++;
|
||||
max_idx = -1;
|
||||
}
|
||||
} else {
|
||||
cerr << li.get_fileline() << ": error: "
|
||||
<< "queue bound must be defined."
|
||||
<< endl;
|
||||
des->errors++;
|
||||
}
|
||||
}
|
||||
delete cv;
|
||||
}
|
||||
|
||||
return new netqueue_t(base_type, max_idx);
|
||||
}
|
||||
|
||||
// If dims is not empty create a unpacked array type and clear dims, otherwise
|
||||
// return the base type. Also check that we actually support the base type.
|
||||
static ivl_type_t elaborate_static_array_type(Design *des, const LineInfo &li,
|
||||
ivl_type_t base_type,
|
||||
std::vector<netrange_t> &dims)
|
||||
{
|
||||
if (dims.empty())
|
||||
return base_type;
|
||||
|
||||
if (dynamic_cast<const netqueue_t*>(base_type)) {
|
||||
cerr << li.get_fileline() << ": sorry: "
|
||||
<< "array of queue type is not yet supported."
|
||||
<< endl;
|
||||
des->errors++;
|
||||
// Recover
|
||||
base_type = new netvector_t(IVL_VT_LOGIC);
|
||||
} else if (dynamic_cast<const netdarray_t*>(base_type)) {
|
||||
cerr << li.get_fileline() << ": sorry: "
|
||||
<< "array of dynamic array type is not yet supported."
|
||||
<< endl;
|
||||
des->errors++;
|
||||
// Recover
|
||||
base_type = new netvector_t(IVL_VT_LOGIC);
|
||||
}
|
||||
|
||||
ivl_type_t type = new netuarray_t(dims, base_type);
|
||||
dims.clear();
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
ivl_type_t elaborate_array_type(Design *des, NetScope *scope,
|
||||
const LineInfo &li, ivl_type_t base_type,
|
||||
const list<pform_range_t> &dims)
|
||||
{
|
||||
const long warn_dimension_size = 1 << 30;
|
||||
std::vector<netrange_t> dimensions;
|
||||
dimensions.reserve(dims.size());
|
||||
|
||||
ivl_type_t type = base_type;
|
||||
|
||||
for (list<pform_range_t>::const_iterator cur = dims.begin();
|
||||
cur != dims.end() ; ++cur) {
|
||||
PExpr *lidx = cur->first;
|
||||
PExpr *ridx = cur->second;
|
||||
|
||||
if (lidx == 0 && ridx == 0) {
|
||||
// Special case: If we encounter an undefined dimensions,
|
||||
// then turn this into a dynamic array and put all the
|
||||
// packed dimensions there.
|
||||
type = elaborate_static_array_type(des, li, type, dimensions);
|
||||
type = elaborate_darray_check_type(des, li, type, "Dynamic array");
|
||||
type = new netdarray_t(type);
|
||||
continue;
|
||||
} else if (dynamic_cast<PENull*>(lidx)) {
|
||||
// Special case: Detect the mark for a QUEUE declaration,
|
||||
// which is the dimensions [null:max_idx].
|
||||
type = elaborate_static_array_type(des, li, type, dimensions);
|
||||
type = elaborate_queue_type(des, scope, li, type, ridx);
|
||||
continue;
|
||||
}
|
||||
|
||||
long index_l, index_r;
|
||||
evaluate_range(des, scope, &li, *cur, index_l, index_r);
|
||||
|
||||
if (abs(index_r - index_l) > warn_dimension_size) {
|
||||
cerr << li.get_fileline() << ": warning: "
|
||||
<< "Array dimension is greater than "
|
||||
<< warn_dimension_size << "."
|
||||
<< endl;
|
||||
}
|
||||
|
||||
dimensions.push_back(netrange_t(index_l, index_r));
|
||||
}
|
||||
|
||||
return elaborate_static_array_type(des, li, type, dimensions);
|
||||
}
|
||||
|
||||
ivl_type_t uarray_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
|
||||
{
|
||||
ivl_type_t btype = base_type->elaborate_type(des, scope);
|
||||
|
||||
assert(dims->size() >= 1);
|
||||
list<pform_range_t>::const_iterator cur = dims->begin();
|
||||
|
||||
// Special case: if the dimension is nil:nil, this is a
|
||||
// dynamic array. Note that we only know how to handle dynamic
|
||||
// arrays with 1 dimension at a time.
|
||||
if (cur->first==0 && cur->second==0) {
|
||||
assert(dims->size()==1);
|
||||
ivl_type_s*res = new netdarray_t(btype);
|
||||
return res;
|
||||
}
|
||||
|
||||
// Special case: if the dimension is null:nil. this is a queue.
|
||||
if (dynamic_cast<PENull*>(cur->first)) {
|
||||
cerr << get_fileline() << ": sorry: "
|
||||
<< "SV queues inside classes are not yet supported." << endl;
|
||||
des->errors += 1;
|
||||
|
||||
// FIXME: Need to set the max size if cur->second is defined
|
||||
ivl_type_s*res = new netqueue_t(btype, -1);
|
||||
return res;
|
||||
}
|
||||
|
||||
vector<netrange_t> dimensions;
|
||||
bool dimensions_ok = evaluate_ranges(des, scope, this, dimensions, *dims);
|
||||
|
||||
if (!dimensions_ok) {
|
||||
cerr << get_fileline() << " : warning: "
|
||||
<< "Bad dimensions for type here." << endl;
|
||||
}
|
||||
|
||||
ivl_assert(*this, btype);
|
||||
ivl_type_s*res = new netuarray_t(dimensions, btype);
|
||||
return res;
|
||||
return elaborate_array_type(des, scope, *this, btype, *dims.get());
|
||||
}
|
||||
|
||||
ivl_type_t typeref_t::elaborate_type_raw(Design*des, NetScope*s) const
|
||||
{
|
||||
if (!s) {
|
||||
// Try to recover
|
||||
return new netvector_t(IVL_VT_LOGIC);
|
||||
}
|
||||
|
||||
return type->elaborate_type(des, s);
|
||||
}
|
||||
|
||||
NetScope *typeref_t::find_scope(Design *des, NetScope *s) const
|
||||
{
|
||||
// If a scope has been specified use that as a starting point for the
|
||||
// search
|
||||
if (scope)
|
||||
s = des->find_package(scope->pscope_name());
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
ivl_type_t typedef_t::elaborate_type(Design *des, NetScope *scope)
|
||||
{
|
||||
if (!data_type.get()) {
|
||||
cerr << get_fileline() << ": error: Undefined type `" << name << "`."
|
||||
<< endl;
|
||||
des->errors++;
|
||||
|
||||
// Try to recover
|
||||
return netvector_t::integer_type();
|
||||
}
|
||||
|
||||
// Search upwards from where the type was referenced
|
||||
scope = scope->find_typedef_scope(des, this);
|
||||
if (!scope) {
|
||||
cerr << get_fileline() << ": sorry: "
|
||||
<< "Can not find the scope type defintion `" << name << "`."
|
||||
<< endl;
|
||||
des->errors++;
|
||||
|
||||
// Try to recover
|
||||
return netvector_t::integer_type();
|
||||
}
|
||||
|
||||
ivl_type_t elab_type = data_type->elaborate_type(des, scope);
|
||||
if (!elab_type)
|
||||
return netvector_t::integer_type();
|
||||
|
||||
bool type_ok = true;
|
||||
switch (basic_type) {
|
||||
case ENUM:
|
||||
type_ok = dynamic_cast<const netenum_t *>(elab_type);
|
||||
break;
|
||||
case STRUCT: {
|
||||
const netstruct_t *struct_type = dynamic_cast<const netstruct_t *>(elab_type);
|
||||
type_ok = struct_type && !struct_type->union_flag();
|
||||
break;
|
||||
}
|
||||
case UNION: {
|
||||
const netstruct_t *struct_type = dynamic_cast<const netstruct_t *>(elab_type);
|
||||
type_ok = struct_type && struct_type->union_flag();
|
||||
break;
|
||||
}
|
||||
case CLASS:
|
||||
type_ok = dynamic_cast<const netclass_t *>(elab_type);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!type_ok) {
|
||||
cerr << data_type->get_fileline() << " error: "
|
||||
<< "Unexpected type `" << *elab_type << "` for `" << name
|
||||
<< "`. It was forward declared as `" << basic_type
|
||||
<< "` at " << get_fileline() << "."
|
||||
<< endl;
|
||||
des->errors++;
|
||||
}
|
||||
|
||||
return elab_type;
|
||||
}
|
||||
|
||||
ivl_type_t type_parameter_t::elaborate_type_raw(Design *des, NetScope*scope) const
|
||||
{
|
||||
ivl_type_t type;
|
||||
|
||||
scope->get_parameter(des, name, type);
|
||||
|
||||
// Recover
|
||||
if (!type)
|
||||
return netvector_t::integer_type();
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
+823
-361
File diff suppressed because it is too large
Load Diff
+3
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2012 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2008-2021 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -26,6 +26,8 @@
|
||||
|
||||
# include <typeinfo>
|
||||
|
||||
using namespace std;
|
||||
|
||||
NetProc* AContrib::elaborate(Design*des, NetScope*scope) const
|
||||
{
|
||||
NetExpr*lval = elab_and_eval(des, scope, lval_, -1);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998-2017 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-2021 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -33,6 +33,8 @@
|
||||
# include <cassert>
|
||||
# include <cstring>
|
||||
|
||||
using namespace std;
|
||||
|
||||
bool NetNode::emit_node(struct target_t*) const
|
||||
{
|
||||
cerr << "EMIT: Gate type? " << typeid(*this).name() << endl;
|
||||
@@ -389,6 +391,11 @@ bool NetEvTrig::emit_proc(struct target_t*tgt) const
|
||||
return tgt->proc_trigger(this);
|
||||
}
|
||||
|
||||
bool NetEvNBTrig::emit_proc(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->proc_nb_trigger(this);
|
||||
}
|
||||
|
||||
bool NetEvWait::emit_proc(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->proc_wait(this);
|
||||
|
||||
@@ -1,280 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1998-2014 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# include <cstring>
|
||||
# include <iostream>
|
||||
|
||||
# include "PExpr.h"
|
||||
# include "netlist.h"
|
||||
# include "netmisc.h"
|
||||
# include "compiler.h"
|
||||
|
||||
verinum* PExpr::eval_const(Design*, NetScope*) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
verinum* PEBinary::eval_const(Design*des, NetScope*scope) const
|
||||
{
|
||||
verinum*l = left_->eval_const(des, scope);
|
||||
if (l == 0) return 0;
|
||||
verinum*r = right_->eval_const(des, scope);
|
||||
if (r == 0) {
|
||||
delete l;
|
||||
return 0;
|
||||
}
|
||||
verinum*res;
|
||||
|
||||
switch (op_) {
|
||||
case 'p': {
|
||||
if (l->is_defined() && r->is_defined()) {
|
||||
res = new verinum(pow(*l, *r));
|
||||
} else {
|
||||
res = new verinum(verinum::Vx, l->len());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case '+': {
|
||||
if (l->is_defined() && r->is_defined()) {
|
||||
res = new verinum(*l + *r);
|
||||
} else {
|
||||
res = new verinum(verinum::Vx, l->len());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case '-': {
|
||||
if (l->is_defined() && r->is_defined()) {
|
||||
res = new verinum(*l - *r);
|
||||
} else {
|
||||
res = new verinum(verinum::Vx, l->len());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case '*': {
|
||||
if (l->is_defined() && r->is_defined()) {
|
||||
res = new verinum(*l * *r);
|
||||
} else {
|
||||
res = new verinum(verinum::Vx, l->len());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case '/': {
|
||||
if (l->is_defined() && r->is_defined()) {
|
||||
long lv = l->as_long();
|
||||
long rv = r->as_long();
|
||||
res = new verinum(lv / rv, l->len());
|
||||
} else {
|
||||
res = new verinum(verinum::Vx, l->len());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case '%': {
|
||||
if (l->is_defined() && r->is_defined()) {
|
||||
long lv = l->as_long();
|
||||
long rv = r->as_long();
|
||||
res = new verinum(lv % rv, l->len());
|
||||
} else {
|
||||
res = new verinum(verinum::Vx, l->len());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case '>': {
|
||||
if (l->is_defined() && r->is_defined()) {
|
||||
long lv = l->as_long();
|
||||
long rv = r->as_long();
|
||||
res = new verinum(lv > rv, l->len());
|
||||
} else {
|
||||
res = new verinum(verinum::Vx, l->len());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case '<': {
|
||||
if (l->is_defined() && r->is_defined()) {
|
||||
long lv = l->as_long();
|
||||
long rv = r->as_long();
|
||||
res = new verinum(lv < rv, l->len());
|
||||
} else {
|
||||
res = new verinum(verinum::Vx, l->len());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'l': { // left shift (<<)
|
||||
assert(r->is_defined());
|
||||
unsigned long rv = r->as_ulong();
|
||||
res = new verinum(verinum::V0, l->len());
|
||||
if (rv < res->len()) {
|
||||
unsigned cnt = res->len() - rv;
|
||||
for (unsigned idx = 0 ; idx < cnt ; idx += 1)
|
||||
res->set(idx+rv, l->get(idx));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'r': { // right shift (>>)
|
||||
assert(r->is_defined());
|
||||
unsigned long rv = r->as_ulong();
|
||||
res = new verinum(verinum::V0, l->len());
|
||||
if (rv < res->len()) {
|
||||
unsigned cnt = res->len() - rv;
|
||||
for (unsigned idx = 0 ; idx < cnt ; idx += 1)
|
||||
res->set(idx, l->get(idx+rv));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
delete l;
|
||||
delete r;
|
||||
return 0;
|
||||
}
|
||||
|
||||
delete l;
|
||||
delete r;
|
||||
return res;
|
||||
}
|
||||
verinum* PEConcat::eval_const(Design*des, NetScope*scope) const
|
||||
{
|
||||
verinum*accum = parms_[0]->eval_const(des, scope);
|
||||
if (accum == 0)
|
||||
return 0;
|
||||
|
||||
for (unsigned idx = 1 ; idx < parms_.size() ; idx += 1) {
|
||||
|
||||
verinum*tmp = parms_[idx]->eval_const(des, scope);
|
||||
if (tmp == 0) {
|
||||
delete accum;
|
||||
return 0;
|
||||
}
|
||||
assert(tmp);
|
||||
|
||||
*accum = concat(*accum, *tmp);
|
||||
delete tmp;
|
||||
}
|
||||
|
||||
return accum;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Evaluate an identifier as a constant expression. This is only
|
||||
* possible if the identifier is that of a parameter.
|
||||
*/
|
||||
verinum* PEIdent::eval_const(Design*des, NetScope*scope) const
|
||||
{
|
||||
assert(scope);
|
||||
NetNet*net;
|
||||
NetEvent*eve;
|
||||
const NetExpr*expr;
|
||||
|
||||
const name_component_t&name_tail = path_.back();
|
||||
|
||||
// Handle the special case that this ident is a genvar
|
||||
// variable name. In that case, the genvar meaning preempts
|
||||
// everything and we just return that value immediately.
|
||||
if (scope->genvar_tmp
|
||||
&& strcmp(name_tail.name,scope->genvar_tmp) == 0) {
|
||||
return new verinum(scope->genvar_tmp_val);
|
||||
}
|
||||
|
||||
symbol_search(this, des, scope, path_, net, expr, eve);
|
||||
|
||||
if (expr == 0)
|
||||
return 0;
|
||||
|
||||
const NetEConst*eval = dynamic_cast<const NetEConst*>(expr);
|
||||
if (eval == 0) {
|
||||
cerr << get_fileline() << ": internal error: Unable to evaluate "
|
||||
<< "constant expression (parameter=" << path_
|
||||
<< "): " << *expr << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(eval);
|
||||
|
||||
if (!name_tail.index.empty())
|
||||
return 0;
|
||||
|
||||
|
||||
return new verinum(eval->value());
|
||||
}
|
||||
|
||||
verinum* PEFNumber::eval_const(Design*, NetScope*) const
|
||||
{
|
||||
long val = value_->as_long();
|
||||
return new verinum(val);
|
||||
}
|
||||
|
||||
verinum* PENumber::eval_const(Design*, NetScope*) const
|
||||
{
|
||||
return new verinum(value());
|
||||
}
|
||||
|
||||
verinum* PEString::eval_const(Design*, NetScope*) const
|
||||
{
|
||||
return new verinum(string(text_));
|
||||
}
|
||||
|
||||
verinum* PETernary::eval_const(Design*des, NetScope*scope) const
|
||||
{
|
||||
verinum*test = expr_->eval_const(des, scope);
|
||||
if (test == 0)
|
||||
return 0;
|
||||
|
||||
verinum::V bit = test->get(0);
|
||||
delete test;
|
||||
switch (bit) {
|
||||
case verinum::V0:
|
||||
return fal_->eval_const(des, scope);
|
||||
case verinum::V1:
|
||||
return tru_->eval_const(des, scope);
|
||||
default:
|
||||
return 0;
|
||||
// XXXX It is possible to handle this case if both fal_
|
||||
// and tru_ are constant. Someday...
|
||||
}
|
||||
}
|
||||
|
||||
verinum* PEUnary::eval_const(Design*des, NetScope*scope) const
|
||||
{
|
||||
verinum*val = expr_->eval_const(des, scope);
|
||||
if (val == 0)
|
||||
return 0;
|
||||
|
||||
switch (op_) {
|
||||
case '+':
|
||||
return val;
|
||||
|
||||
case '-': {
|
||||
/* We need to expand the value a bit if we are
|
||||
taking the 2's complement so that we are
|
||||
guaranteed to not overflow. */
|
||||
verinum tmp ((uint64_t)0, val->len()+1);
|
||||
for (unsigned idx = 0 ; idx < val->len() ; idx += 1)
|
||||
tmp.set(idx, val->get(idx));
|
||||
|
||||
*val = -tmp;
|
||||
val->has_sign(true);
|
||||
return val;
|
||||
}
|
||||
|
||||
}
|
||||
delete val;
|
||||
return 0;
|
||||
}
|
||||
+18
-13
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002-2010 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2002-2021 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -21,9 +21,12 @@
|
||||
# include "util.h"
|
||||
# include "PExpr.h"
|
||||
# include "netlist.h"
|
||||
# include "netmisc.h"
|
||||
# include <iostream>
|
||||
# include <cassert>
|
||||
|
||||
using namespace std;
|
||||
|
||||
/*
|
||||
* The evaluate_attributes function evaluates the attribute
|
||||
* expressions from the map, and returns a table in a form suitable
|
||||
@@ -50,23 +53,25 @@ attrib_list_t* evaluate_attributes(const map<perm_string,PExpr*>&att,
|
||||
/* If the attribute value is given in the source, then
|
||||
evaluate it as a constant. If the value is not
|
||||
given, then assume the value is 1. */
|
||||
verinum*tmp = 0;
|
||||
if (exp) {
|
||||
tmp = exp->eval_const(des, scope);
|
||||
if (tmp == 0) {
|
||||
NetExpr *tmp = elab_and_eval(des, scope, exp, -1, true);
|
||||
if (!tmp)
|
||||
continue;
|
||||
|
||||
if (NetEConst *ce = dynamic_cast<NetEConst*>(tmp)) {
|
||||
table[idx].val = ce->value();
|
||||
} else if (NetECReal *cer = dynamic_cast<NetECReal*>(tmp)) {
|
||||
table[idx].val = verinum(cer->value().as_long());
|
||||
} else {
|
||||
cerr << exp->get_fileline() << ": error: ``"
|
||||
<< *exp << "'' is not a constant expression."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
}
|
||||
if (tmp == 0)
|
||||
tmp = new verinum(1);
|
||||
|
||||
assert(tmp);
|
||||
|
||||
table[idx].val = *tmp;
|
||||
delete tmp;
|
||||
}
|
||||
delete tmp;
|
||||
} else {
|
||||
table[idx].val = verinum(1);
|
||||
}
|
||||
}
|
||||
|
||||
assert(idx == natt);
|
||||
|
||||
+53
-22
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2020 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2021 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -29,6 +29,8 @@
|
||||
# include "ivl_assert.h"
|
||||
# include "netmisc.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
NetExpr* NetExpr::eval_tree()
|
||||
{
|
||||
return 0;
|
||||
@@ -69,7 +71,7 @@ static bool get_real_arg_(const NetExpr*expr, verireal&val)
|
||||
return false;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
ivl_assert(*expr, 0);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -362,7 +364,7 @@ NetEConst* NetEBComp::must_be_leeq_(const NetExpr*le, const verinum&rv, bool eq_
|
||||
// or 'z' values.
|
||||
if (le->expr_type() == IVL_VT_LOGIC) return 0;
|
||||
|
||||
assert(le->expr_width() > 0);
|
||||
ivl_assert(*le, le->expr_width() > 0);
|
||||
verinum lv (verinum::V1, le->expr_width());
|
||||
if (le->has_sign() && rv.has_sign()) {
|
||||
// If the expression is signed, then the largest
|
||||
@@ -404,7 +406,6 @@ NetEConst* NetEBComp::eval_leeq_(const NetExpr*le, const NetExpr*re) const
|
||||
{
|
||||
if (le->expr_type() == IVL_VT_REAL || re->expr_type() == IVL_VT_REAL)
|
||||
return eval_leeq_real_(le, re, true);
|
||||
// assert(expr_type() == IVL_VT_LOGIC);
|
||||
|
||||
const NetEConst*r = dynamic_cast<const NetEConst*>(re);
|
||||
if (r == 0) return 0;
|
||||
@@ -416,12 +417,6 @@ NetEConst* NetEBComp::eval_leeq_(const NetExpr*le, const NetExpr*re) const
|
||||
return res;
|
||||
}
|
||||
|
||||
if (le->expr_width() == 0) {
|
||||
cerr << get_fileline() << ": internal error: Something wrong "
|
||||
<< "with the left side width of <= ?" << endl;
|
||||
cerr << get_fileline() << ": : " << *this << endl;
|
||||
}
|
||||
|
||||
if (NetEConst*tmp = must_be_leeq_(le, rv, true)) {
|
||||
return tmp;
|
||||
}
|
||||
@@ -776,7 +771,7 @@ NetExpr* NetEBDiv::eval_tree_real_(const NetExpr*l, const NetExpr*r) const
|
||||
NetExpr* NetEBDiv::eval_arguments_(const NetExpr*l, const NetExpr*r) const
|
||||
{
|
||||
if (expr_type() == IVL_VT_REAL) return eval_tree_real_(l,r);
|
||||
assert(expr_type() == IVL_VT_LOGIC);
|
||||
ivl_assert(*this, expr_type() == IVL_VT_LOGIC);
|
||||
|
||||
const NetEConst*lc = dynamic_cast<const NetEConst*>(l);
|
||||
const NetEConst*rc = dynamic_cast<const NetEConst*>(r);
|
||||
@@ -812,10 +807,40 @@ NetEConst* NetEBLogic::eval_arguments_(const NetExpr*l, const NetExpr*r) const
|
||||
{
|
||||
// NetEBLogic arguments should have already been reduced so real is not possible.
|
||||
ivl_assert(*this, (l->expr_type() != IVL_VT_REAL) && (r->expr_type() != IVL_VT_REAL));
|
||||
assert(expr_type() == IVL_VT_LOGIC);
|
||||
ivl_assert(*this, expr_type() == IVL_VT_LOGIC);
|
||||
|
||||
const NetEConst*lc = dynamic_cast<const NetEConst*>(l);
|
||||
const NetEConst*rc = dynamic_cast<const NetEConst*>(r);
|
||||
|
||||
// If the left side is constant and the right side is short circuited
|
||||
// replace the expression with a constant
|
||||
if (rc == 0 && lc != 0) {
|
||||
verinum v = lc->value();
|
||||
verinum::V res = verinum::Vx;
|
||||
switch (op_) {
|
||||
case 'a': // Logical AND (&&)
|
||||
if (v.is_zero())
|
||||
res = verinum::V0;
|
||||
break;
|
||||
case 'o': // Logical OR (||)
|
||||
if (! v.is_zero() && v.is_defined())
|
||||
res = verinum::V1;
|
||||
break;
|
||||
case 'q': // Logical implication (->)
|
||||
if (v.is_zero())
|
||||
res = verinum::V1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (res != verinum::Vx) {
|
||||
NetEConst*tmp = new NetEConst(verinum(res, 1));
|
||||
ivl_assert(*this, tmp);
|
||||
eval_debug(this, tmp, false);
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
|
||||
if (lc == 0 || rc == 0) return 0;
|
||||
|
||||
verinum::V lv = verinum::V0;
|
||||
@@ -918,7 +943,7 @@ NetExpr* NetEBMinMax::eval_tree_real_(const NetExpr*l, const NetExpr*r) const
|
||||
NetExpr* NetEBMinMax::eval_arguments_(const NetExpr*l, const NetExpr*r) const
|
||||
{
|
||||
if (expr_type() == IVL_VT_REAL) return eval_tree_real_(l,r);
|
||||
assert(expr_type() == IVL_VT_LOGIC);
|
||||
ivl_assert(*this, expr_type() == IVL_VT_LOGIC);
|
||||
|
||||
const NetEConst*lc = dynamic_cast<const NetEConst*>(l);
|
||||
const NetEConst*rc = dynamic_cast<const NetEConst*>(r);
|
||||
@@ -971,7 +996,7 @@ NetExpr* NetEBMult::eval_tree_real_(const NetExpr*l, const NetExpr*r) const
|
||||
NetExpr* NetEBMult::eval_arguments_(const NetExpr*l, const NetExpr*r) const
|
||||
{
|
||||
if (expr_type() == IVL_VT_REAL) return eval_tree_real_(l,r);
|
||||
assert(expr_type() == IVL_VT_LOGIC);
|
||||
ivl_assert(*this, expr_type() == IVL_VT_LOGIC);
|
||||
|
||||
const NetEConst*lc = dynamic_cast<const NetEConst*>(l);
|
||||
const NetEConst*rc = dynamic_cast<const NetEConst*>(r);
|
||||
@@ -1009,7 +1034,7 @@ NetExpr* NetEBPow::eval_tree_real_(const NetExpr*l, const NetExpr*r) const
|
||||
NetExpr* NetEBPow::eval_arguments_(const NetExpr*l, const NetExpr*r) const
|
||||
{
|
||||
if (expr_type() == IVL_VT_REAL) return eval_tree_real_(l,r);
|
||||
assert(expr_type() == IVL_VT_LOGIC);
|
||||
ivl_assert(*this, expr_type() == IVL_VT_LOGIC);
|
||||
|
||||
const NetEConst*lc = dynamic_cast<const NetEConst*>(l);
|
||||
const NetEConst*rc = dynamic_cast<const NetEConst*>(r);
|
||||
@@ -1092,7 +1117,7 @@ NetEConst* NetEConcat::eval_tree()
|
||||
// Finally, try to evaluate the parameter expression
|
||||
// that is here. If I succeed, reset the parameter to
|
||||
// the evaluated value.
|
||||
assert(parms_[idx]);
|
||||
ivl_assert(*this, parms_[idx]);
|
||||
NetExpr*expr = parms_[idx]->eval_tree();
|
||||
if (expr) {
|
||||
expr->set_line(*parms_[idx]);
|
||||
@@ -1225,7 +1250,7 @@ static void print_ternary_cond(NetExpr*expr)
|
||||
cerr << c->value() << endl;
|
||||
return;
|
||||
}
|
||||
assert(0);
|
||||
ivl_assert(*expr, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1250,6 +1275,9 @@ NetExpr* NetETernary::eval_tree()
|
||||
<< *false_val_ << endl;
|
||||
}
|
||||
|
||||
// Elaborate the alternate expression to check for errors.
|
||||
eval_expr(true_val_);
|
||||
|
||||
if (expr_type() == IVL_VT_REAL &&
|
||||
false_val_->expr_type() != IVL_VT_REAL) {
|
||||
verireal f;
|
||||
@@ -1272,6 +1300,9 @@ NetExpr* NetETernary::eval_tree()
|
||||
<< *true_val_ << endl;
|
||||
}
|
||||
|
||||
// Elaborate the alternate expression to check for errors.
|
||||
eval_expr(false_val_);
|
||||
|
||||
if (expr_type() == IVL_VT_REAL &&
|
||||
true_val_->expr_type() != IVL_VT_REAL) {
|
||||
verireal t;
|
||||
@@ -1437,7 +1468,7 @@ NetExpr* NetEUnary::eval_arguments_(const NetExpr*ex) const
|
||||
break;
|
||||
|
||||
case '!':
|
||||
assert(0);
|
||||
ivl_assert(*this, 0);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
@@ -2012,7 +2043,7 @@ NetEConst* NetESFunc::evaluate_dimensions_(const NetExpr*arg) const
|
||||
* make these routines work correct add one if this is a
|
||||
* string data type. */
|
||||
if (sig->data_type() == IVL_VT_STRING) {
|
||||
assert(sig->packed_dimensions() == 0);
|
||||
ivl_assert(*this, sig->packed_dimensions() == 0);
|
||||
res += 1;
|
||||
}
|
||||
}
|
||||
@@ -2046,7 +2077,7 @@ NetEConst* NetESFunc::evaluate_isunknown_(const NetExpr* arg) const
|
||||
return res;
|
||||
}
|
||||
|
||||
static bool is_onehot(verinum&value, bool zero_is_okay)
|
||||
static bool is_onehot(const verinum&value, bool zero_is_okay)
|
||||
{
|
||||
bool found_a_one = false;
|
||||
|
||||
@@ -2141,7 +2172,7 @@ static bool get_array_info(const NetExpr*arg, long dim,
|
||||
long &left, long &right, bool&defer)
|
||||
{
|
||||
if (const NetEConstParam*param = dynamic_cast<const NetEConstParam*>(arg)) {
|
||||
assert(dim == 1);
|
||||
ivl_assert(*arg, dim == 1);
|
||||
left = param->expr_width() - 1;
|
||||
right = 0;
|
||||
return false;
|
||||
@@ -2226,7 +2257,7 @@ NetEConst* NetESFunc::evaluate_array_funcs_(ID id,
|
||||
break;
|
||||
default:
|
||||
res = 0;
|
||||
assert(0);
|
||||
ivl_assert(*this, 0);
|
||||
}
|
||||
/* Return the result as an integer sized constant. */
|
||||
return new NetEConst(verinum(verinum(res), integer_width));
|
||||
|
||||
+2
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Martin Whitaker (icarus@martin-whitaker.me.uk)
|
||||
* Copyright (c) 2016-2021 Martin Whitaker (icarus@martin-whitaker.me.uk)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -26,6 +26,7 @@
|
||||
# include "compiler.h"
|
||||
# include "ivl_assert.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
/*
|
||||
* The exposenodes functor is primarily provided for use by the vlog95
|
||||
|
||||
+8
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2020 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2021 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -28,6 +28,8 @@
|
||||
# include "netmisc.h"
|
||||
# include "ivl_assert.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
static NetNet* convert_to_real_const(Design*des, NetScope*scope, NetEConst*expr)
|
||||
{
|
||||
verireal vrl(expr->value().as_double());
|
||||
@@ -780,12 +782,12 @@ NetNet* NetEConcat::synthesize(Design*des, NetScope*scope, NetExpr*root)
|
||||
osig->set_line(*this);
|
||||
osig->local_flag(true);
|
||||
|
||||
NetConcat*concat = new NetConcat(scope, scope->local_symbol(),
|
||||
NetConcat*cncat = new NetConcat(scope, scope->local_symbol(),
|
||||
osig->vector_width(),
|
||||
num_parms * repeat());
|
||||
concat->set_line(*this);
|
||||
des->add_node(concat);
|
||||
connect(concat->pin(0), osig->pin(0));
|
||||
cncat->set_line(*this);
|
||||
des->add_node(cncat);
|
||||
connect(cncat->pin(0), osig->pin(0));
|
||||
|
||||
unsigned count_input_width = 0;
|
||||
unsigned cur_pin = 1;
|
||||
@@ -793,7 +795,7 @@ NetNet* NetEConcat::synthesize(Design*des, NetScope*scope, NetExpr*root)
|
||||
for (unsigned idx = 0 ; idx < parms_.size() ; idx += 1) {
|
||||
unsigned concat_item = parms_.size()-idx-1;
|
||||
if (tmp[concat_item] == 0) continue;
|
||||
connect(concat->pin(cur_pin), tmp[concat_item]->pin(0));
|
||||
connect(cncat->pin(cur_pin), tmp[concat_item]->pin(0));
|
||||
cur_pin += 1;
|
||||
count_input_width += tmp[concat_item]->vector_width();
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2016 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2021 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -50,7 +50,7 @@ void functor_t::lpm_add_sub(Design*, NetAddSub*)
|
||||
{
|
||||
}
|
||||
|
||||
void functor_t::lpm_compare(Design*, NetCompare*)
|
||||
void functor_t::lpm_compare(Design*, const NetCompare*)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef IVL_functor_H
|
||||
#define IVL_functor_H
|
||||
/*
|
||||
* Copyright (c) 1999-2016 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2021 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -40,65 +40,65 @@ struct functor_t {
|
||||
virtual ~functor_t();
|
||||
|
||||
/* Events are scanned here. */
|
||||
virtual void event(class Design*des, class NetEvent*);
|
||||
virtual void event(Design*des, class NetEvent*);
|
||||
|
||||
/* This is called once for each signal in the design. */
|
||||
virtual void signal(class Design*des, class NetNet*);
|
||||
virtual void signal(Design*des, NetNet*);
|
||||
|
||||
/* This method is called for each process in the design. */
|
||||
virtual void process(class Design*des, class NetProcTop*);
|
||||
virtual void process(Design*des, NetProcTop*);
|
||||
|
||||
/* This method is called for each structural abs(). */
|
||||
virtual void lpm_abs(class Design*des, class NetAbs*);
|
||||
virtual void lpm_abs(Design*des, class NetAbs*);
|
||||
|
||||
/* This method is called for each structural adder. */
|
||||
virtual void lpm_add_sub(class Design*des, class NetAddSub*);
|
||||
virtual void lpm_add_sub(Design*des, class NetAddSub*);
|
||||
|
||||
/* This method is called for each structural comparator. */
|
||||
virtual void lpm_compare(class Design*des, class NetCompare*);
|
||||
virtual void lpm_compare(Design*des, const class NetCompare*);
|
||||
|
||||
/* This method is called for each structural concatenation. */
|
||||
virtual void lpm_concat(class Design*des, class NetConcat*);
|
||||
virtual void lpm_concat(Design*des, class NetConcat*);
|
||||
|
||||
/* This method is called for each structural constant. */
|
||||
virtual void lpm_const(class Design*des, class NetConst*);
|
||||
virtual void lpm_const(Design*des, class NetConst*);
|
||||
|
||||
/* This method is called for each structural constant. */
|
||||
virtual void lpm_divide(class Design*des, class NetDivide*);
|
||||
virtual void lpm_divide(Design*des, class NetDivide*);
|
||||
|
||||
/* Constant literals. */
|
||||
virtual void lpm_literal(class Design*des, class NetLiteral*);
|
||||
virtual void lpm_literal(Design*des, class NetLiteral*);
|
||||
|
||||
/* This method is called for each structural constant. */
|
||||
virtual void lpm_modulo(class Design*des, class NetModulo*);
|
||||
virtual void lpm_modulo(Design*des, class NetModulo*);
|
||||
|
||||
/* This method is called for each FF in the design. */
|
||||
virtual void lpm_ff(class Design*des, class NetFF*);
|
||||
virtual void lpm_ff(Design*des, class NetFF*);
|
||||
|
||||
/* This method is called for each LATCH in the design. */
|
||||
virtual void lpm_latch(class Design*des, class NetLatch*);
|
||||
virtual void lpm_latch(Design*des, class NetLatch*);
|
||||
|
||||
/* Handle LPM combinational logic devices. */
|
||||
virtual void lpm_logic(class Design*des, class NetLogic*);
|
||||
virtual void lpm_logic(Design*des, class NetLogic*);
|
||||
|
||||
/* This method is called for each multiplier. */
|
||||
virtual void lpm_mult(class Design*des, class NetMult*);
|
||||
virtual void lpm_mult(Design*des, class NetMult*);
|
||||
|
||||
/* This method is called for each MUX. */
|
||||
virtual void lpm_mux(class Design*des, class NetMux*);
|
||||
virtual void lpm_mux(Design*des, class NetMux*);
|
||||
|
||||
virtual void lpm_part_select(class Design*des, class NetPartSelect*);
|
||||
virtual void lpm_part_select(Design*des, class NetPartSelect*);
|
||||
|
||||
/* This method is called for each power. */
|
||||
virtual void lpm_pow(class Design*des, class NetPow*);
|
||||
virtual void lpm_pow(Design*des, class NetPow*);
|
||||
|
||||
/* This method is called for each part substitute. */
|
||||
virtual void lpm_substitute(class Design*des, class NetSubstitute*);
|
||||
virtual void lpm_substitute(Design*des, class NetSubstitute*);
|
||||
|
||||
/* This method is called for each unary reduction gate. */
|
||||
virtual void lpm_ureduce(class Design*des, class NetUReduce*);
|
||||
virtual void lpm_ureduce(Design*des, class NetUReduce*);
|
||||
|
||||
virtual void sign_extend(class Design*des, class NetSignExtend*);
|
||||
virtual void sign_extend(Design*des, class NetSignExtend*);
|
||||
};
|
||||
|
||||
struct proc_match_t {
|
||||
|
||||
@@ -41,10 +41,12 @@ ivl_enum_width
|
||||
|
||||
ivl_event_any
|
||||
ivl_event_basename
|
||||
ivl_event_edg
|
||||
ivl_event_file
|
||||
ivl_event_lineno
|
||||
ivl_event_name
|
||||
ivl_event_nany
|
||||
ivl_event_nedg
|
||||
ivl_event_neg
|
||||
ivl_event_nneg
|
||||
ivl_event_npos
|
||||
@@ -170,6 +172,7 @@ ivl_nexus_ptr_switch
|
||||
ivl_parameter_basename
|
||||
ivl_parameter_expr
|
||||
ivl_parameter_file
|
||||
ivl_parameter_is_type
|
||||
ivl_parameter_lineno
|
||||
ivl_parameter_local
|
||||
ivl_parameter_lsb
|
||||
@@ -290,8 +293,9 @@ ivl_stmt_delay_expr
|
||||
ivl_stmt_delay_val
|
||||
ivl_stmt_events
|
||||
ivl_stmt_file
|
||||
ivl_stmt_lineno
|
||||
ivl_stmt_flow_control
|
||||
ivl_stmt_lexp
|
||||
ivl_stmt_lineno
|
||||
ivl_stmt_lval
|
||||
ivl_stmt_lvals
|
||||
ivl_stmt_lwidth
|
||||
@@ -325,6 +329,7 @@ ivl_type_name
|
||||
ivl_type_packed_dimensions
|
||||
ivl_type_packed_lsb
|
||||
ivl_type_packed_msb
|
||||
ivl_type_packed_width
|
||||
ivl_type_prop_name
|
||||
ivl_type_prop_type
|
||||
ivl_type_properties
|
||||
|
||||
+4
-4
@@ -1,7 +1,7 @@
|
||||
#ifndef IVL_ivl_assert_H
|
||||
#define IVL_ivl_assert_H
|
||||
/*
|
||||
* Copyright (c) 2007-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2007-2021 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -24,9 +24,9 @@
|
||||
#define ivl_assert(tok, expression) \
|
||||
do { \
|
||||
if (! (expression)) { \
|
||||
cerr << (tok).get_fileline() << ": assert: " \
|
||||
<< __FILE__ << ":" << __LINE__ \
|
||||
<< ": failed assertion " << #expression << endl; \
|
||||
std::cerr << (tok).get_fileline() << ": assert: " \
|
||||
<< __FILE__ << ":" << __LINE__ \
|
||||
<< ": failed assertion " << #expression << std::endl; \
|
||||
abort(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
+16
-1
@@ -1,7 +1,7 @@
|
||||
#ifndef IVL_ivl_target_H
|
||||
#define IVL_ivl_target_H
|
||||
/*
|
||||
* Copyright (c) 2000-2020 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2021 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
# include <inttypes.h>
|
||||
# include <stddef.h>
|
||||
# include <stdbool.h>
|
||||
|
||||
/* Re the _CLASS define: clang++ wants this to be class to match the
|
||||
* definition, but clang (the C) compiler needs it to be a struct
|
||||
@@ -426,6 +427,7 @@ typedef enum ivl_statement_type_e {
|
||||
IVL_ST_FORK_JOIN_ANY = 28,
|
||||
IVL_ST_FORK_JOIN_NONE = 29,
|
||||
IVL_ST_FREE = 26,
|
||||
IVL_ST_NB_TRIGGER = 31,
|
||||
IVL_ST_RELEASE = 17,
|
||||
IVL_ST_REPEAT = 18,
|
||||
IVL_ST_STASK = 19,
|
||||
@@ -768,6 +770,9 @@ extern ivl_scope_t ivl_event_scope(ivl_event_t net);
|
||||
extern unsigned ivl_event_nany(ivl_event_t net);
|
||||
extern ivl_nexus_t ivl_event_any(ivl_event_t net, unsigned idx);
|
||||
|
||||
extern unsigned ivl_event_nedg(ivl_event_t net);
|
||||
extern ivl_nexus_t ivl_event_edg(ivl_event_t net, unsigned idx);
|
||||
|
||||
extern unsigned ivl_event_nneg(ivl_event_t net);
|
||||
extern ivl_nexus_t ivl_event_neg(ivl_event_t net, unsigned idx);
|
||||
|
||||
@@ -1690,6 +1695,9 @@ extern ivl_signal_t ivl_nexus_ptr_sig(ivl_nexus_ptr_t net);
|
||||
* Return whether parameter was local (localparam, implicit genvar etc)
|
||||
* or not.
|
||||
*
|
||||
* ivl_parameter_is_type
|
||||
* Return whether the parameter is a type parameter or not.
|
||||
*
|
||||
* ivl_parameter_file
|
||||
* ivl_parameter_lineno
|
||||
* Returns the file and line where this parameter is defined
|
||||
@@ -1702,6 +1710,7 @@ extern int ivl_parameter_lsb(ivl_parameter_t net);
|
||||
extern unsigned ivl_parameter_width(ivl_parameter_t net);
|
||||
extern int ivl_parameter_signed(ivl_parameter_t net);
|
||||
extern int ivl_parameter_local(ivl_parameter_t net);
|
||||
extern int ivl_parameter_is_type(ivl_parameter_t net);
|
||||
extern const char* ivl_parameter_file(ivl_parameter_t net);
|
||||
extern unsigned ivl_parameter_lineno(ivl_parameter_t net);
|
||||
|
||||
@@ -2255,6 +2264,8 @@ extern uint64_t ivl_stmt_delay_val(ivl_statement_t net);
|
||||
extern unsigned ivl_stmt_needs_t0_trigger(ivl_statement_t net);
|
||||
extern unsigned ivl_stmt_nevent(ivl_statement_t net);
|
||||
extern ivl_event_t ivl_stmt_events(ivl_statement_t net, unsigned idx);
|
||||
/* IVL_ST_DISABLE */
|
||||
extern bool ivl_stmt_flow_control(ivl_statement_t net);
|
||||
/* IVL_ST_CONTRIB */
|
||||
extern ivl_expr_t ivl_stmt_lexp(ivl_statement_t net);
|
||||
/* IVL_ST_ASSIGN IVL_ST_ASSIGN_NB IVL_ST_CASSIGN IVL_ST_DEASSIGN
|
||||
@@ -2341,6 +2352,9 @@ extern unsigned ivl_switch_lineno(ivl_switch_t net);
|
||||
* Return the type of the element of an array. This is only valid
|
||||
* for array types.
|
||||
*
|
||||
* ivl_type_packed_width
|
||||
* Returns the total width of all packed dimensions.
|
||||
*
|
||||
* ivl_type_signed
|
||||
* Return TRUE if the type represents a signed packed vector or
|
||||
* signed atomic type, and FALSE otherwise.
|
||||
@@ -2354,6 +2368,7 @@ extern ivl_type_t ivl_type_element(ivl_type_t net);
|
||||
extern unsigned ivl_type_packed_dimensions(ivl_type_t net);
|
||||
extern int ivl_type_packed_lsb(ivl_type_t net, unsigned dim);
|
||||
extern int ivl_type_packed_msb(ivl_type_t net, unsigned dim);
|
||||
extern unsigned ivl_type_packed_width(ivl_type_t net);
|
||||
extern int ivl_type_signed(ivl_type_t net);
|
||||
extern const char* ivl_type_name(ivl_type_t net);
|
||||
extern int ivl_type_properties(ivl_type_t net);
|
||||
|
||||
+1
-1
@@ -60,7 +60,7 @@ distclean: clean
|
||||
rm -f Makefile config.log
|
||||
|
||||
cppcheck: $(O:.o=.c)
|
||||
cppcheck --enable=all --std=posix --std=c99 --std=c++03 -f $(INCLUDE_PATH) $^
|
||||
cppcheck --enable=all --std=c99 --std=c++03 -f $(INCLUDE_PATH) $^
|
||||
|
||||
Makefile: $(srcdir)/Makefile.in ../config.status
|
||||
cd ..; ./config.status --file=ivlpp/$@
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user