mirror of
https://github.com/steveicarus/iverilog.git
synced 2026-08-23 06:16:47 +02:00
Compare commits
769
Commits
performance
...
s20081118
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dafe61b0f9 | ||
|
|
7529034c7a | ||
|
|
ec0e718151 | ||
|
|
35e0a98732 | ||
|
|
3190066013 | ||
|
|
95065819f1 | ||
|
|
e191fcdd28 | ||
|
|
a8a8d3ce5b | ||
|
|
4bc90f7cfd | ||
|
|
e0a1b41b37 | ||
|
|
fe38f7a9a9 | ||
|
|
4892e93a09 | ||
|
|
a42eb5cf94 | ||
|
|
1d4ade80b2 | ||
|
|
fe199a7593 | ||
|
|
407ce5e152 | ||
|
|
1d41037009 | ||
|
|
574c8a870d | ||
|
|
c278b4e41f | ||
|
|
91972cd9a1 | ||
|
|
dc6a9e03c9 | ||
|
|
221b83b932 | ||
|
|
69428bb050 | ||
|
|
256454960c | ||
|
|
d06092d7d7 | ||
|
|
416bd35f2e | ||
|
|
87654f8661 | ||
|
|
9f2b5cd9b7 | ||
|
|
5fd32937f2 | ||
|
|
f1a2e71aab | ||
|
|
7c50c9aedf | ||
|
|
04377151bc | ||
|
|
bbdf622ea5 | ||
|
|
1e06a2ddef | ||
|
|
049290d0fc | ||
|
|
4c67bd0b35 | ||
|
|
4f7457fcec | ||
|
|
95ea159e75 | ||
|
|
ddb2c60701 | ||
|
|
77eb68d314 | ||
|
|
f4687757f1 | ||
|
|
b20019d8b6 | ||
|
|
6cac1d2cab | ||
|
|
520d9b9dd0 | ||
|
|
403a1e9415 | ||
|
|
9b640f3114 | ||
|
|
7ac35e478b | ||
|
|
2c7fe8aa2a | ||
|
|
1ec09327e9 | ||
|
|
ea9bbf804c | ||
|
|
1922a0df9e | ||
|
|
18edf2f15f | ||
|
|
ea057a7574 | ||
|
|
b7d3276e4d | ||
|
|
22ddb26389 | ||
|
|
9b89ca49bb | ||
|
|
94e7d71b97 | ||
|
|
810686d88e | ||
|
|
0bd1739225 | ||
|
|
038b024e71 | ||
|
|
27410f5d88 | ||
|
|
0af896a7ff | ||
|
|
81a0007f22 | ||
|
|
2a5ea9e874 | ||
|
|
b9272f750d | ||
|
|
f49a4e4336 | ||
|
|
26e1693b2f | ||
|
|
68fbb94b3a | ||
|
|
5aa810dde7 | ||
|
|
365960df9d | ||
|
|
644465ccc1 | ||
|
|
904e76f176 | ||
|
|
de2b10b445 | ||
|
|
a654bdc169 | ||
|
|
cb2ed9210c | ||
|
|
50550ca79e | ||
|
|
f3cb18343a | ||
|
|
c6a5a43620 | ||
|
|
b0e57a1a67 | ||
|
|
5fdd9d8339 | ||
|
|
8a3309d79d | ||
|
|
a47b7352b4 | ||
|
|
fff5e494ed | ||
|
|
1c90997499 | ||
|
|
1a3e655285 | ||
|
|
3adcbb5611 | ||
|
|
647b3e5bda | ||
|
|
c41fb50929 | ||
|
|
c5d4d9eec1 | ||
|
|
9cb62a4d64 | ||
|
|
25f6282a54 | ||
|
|
55b8ff4441 | ||
|
|
62f518c205 | ||
|
|
864a86f7ee | ||
|
|
995fc380e8 | ||
|
|
bd71b7fbb2 | ||
|
|
3a99a5e800 | ||
|
|
a9497e9c6a | ||
|
|
c85eff93f2 | ||
|
|
c010145eaf | ||
|
|
b5ad161f90 | ||
|
|
610dedc2b8 | ||
|
|
082e06edb0 | ||
|
|
fd4018cb33 | ||
|
|
b40de5ccb0 | ||
|
|
a7cbb38248 | ||
|
|
4394aff909 | ||
|
|
5cfe47da2b | ||
|
|
cc9e3d1536 | ||
|
|
03fd124d5a | ||
|
|
18de6980ff | ||
|
|
5fd3be570e | ||
|
|
bd504ea14e | ||
|
|
aebd9c2bc7 | ||
|
|
7b4fda8785 | ||
|
|
feba5d9470 | ||
|
|
6b62cce14a | ||
|
|
3bce8bb995 | ||
|
|
716853699f | ||
|
|
55a15d604d | ||
|
|
b548dec070 | ||
|
|
2da50e1788 | ||
|
|
3aaea46144 | ||
|
|
2251844124 | ||
|
|
729771e562 | ||
|
|
0bb1f9740b | ||
|
|
7ebcc6b357 | ||
|
|
3296b1dee3 | ||
|
|
42d412c626 | ||
|
|
4919b70da6 | ||
|
|
d3f17f27c1 | ||
|
|
873ed60ff8 | ||
|
|
ce7dd6b4ff | ||
|
|
2381fc72b0 | ||
|
|
6e12c1f236 | ||
|
|
dc313436c1 | ||
|
|
46bf03bba4 | ||
|
|
103b351641 | ||
|
|
f7d3c7c711 | ||
|
|
a39b9d4ef1 | ||
|
|
a4973c217d | ||
|
|
626394d198 | ||
|
|
8ffec473ef | ||
|
|
38e62bb1d2 | ||
|
|
2d1e0b3ade | ||
|
|
3ba9e945d7 | ||
|
|
2a1608c075 | ||
|
|
411ee517ee | ||
|
|
8b0ca902a6 | ||
|
|
6f46930c23 | ||
|
|
0e699ca226 | ||
|
|
5463e5e66b | ||
|
|
441f173ced | ||
|
|
d3d54144ff | ||
|
|
e4c9ad2b17 | ||
|
|
0339e9eb1e | ||
|
|
7d6b391572 | ||
|
|
804f5a94d5 | ||
|
|
3d5998cd63 | ||
|
|
eda1df5df2 | ||
|
|
3d86cc1a15 | ||
|
|
c5263268ed | ||
|
|
e5abe182c1 | ||
|
|
e5343ef73f | ||
|
|
1f9f73a4be | ||
|
|
1e60754ff0 | ||
|
|
cdfb2315cf | ||
|
|
2516d63805 | ||
|
|
3abf51dcad | ||
|
|
5dfecb3789 | ||
|
|
088c7f3feb | ||
|
|
3982781e97 | ||
|
|
f233793061 | ||
|
|
8704e3e34f | ||
|
|
ec2511da64 | ||
|
|
05f129211e | ||
|
|
eb9d037bf0 | ||
|
|
90f55a1d00 | ||
|
|
527f5c4849 | ||
|
|
4898cd04c6 | ||
|
|
6411e96193 | ||
|
|
dd47599d55 | ||
|
|
8fc35fa32a | ||
|
|
6fe7583784 | ||
|
|
a34348bb35 | ||
|
|
8717a85f7f | ||
|
|
5bf55485d5 | ||
|
|
38970fea65 | ||
|
|
90fbac6e33 | ||
|
|
66949122cf | ||
|
|
6f002935d7 | ||
|
|
5f0b723534 | ||
|
|
7beb059d90 | ||
|
|
60169f6353 | ||
|
|
e4411777ed | ||
|
|
456fffa7ed | ||
|
|
4cb2090978 | ||
|
|
ff766899b0 | ||
|
|
122890fef4 | ||
|
|
1944f372c5 | ||
|
|
8fbfdffe91 | ||
|
|
23127852c7 | ||
|
|
c150223a3a | ||
|
|
c0a4b7c670 | ||
|
|
319b886118 | ||
|
|
fc476aa281 | ||
|
|
49c4f2d106 | ||
|
|
bc3411e28e | ||
|
|
97e662d667 | ||
|
|
f900b6d541 | ||
|
|
0804eccfec | ||
|
|
2e97b28185 | ||
|
|
2d3cd7cb9a | ||
|
|
c9efe87146 | ||
|
|
1ca8241b88 | ||
|
|
8d21c0390e | ||
|
|
3b778b1a06 | ||
|
|
e322cce650 | ||
|
|
ed929a37bb | ||
|
|
4c7144afc0 | ||
|
|
5d5228b6b8 | ||
|
|
e6c2637367 | ||
|
|
468f45b4db | ||
|
|
8c38872b4b | ||
|
|
d15e2a2f73 | ||
|
|
150d51c19b | ||
|
|
b455f3af5d | ||
|
|
0e458501b3 | ||
|
|
3b8dc81a97 | ||
|
|
0ae8f744c4 | ||
|
|
370ff9719f | ||
|
|
3ed0c4e809 | ||
|
|
0121c41942 | ||
|
|
091a546387 | ||
|
|
8323d5d01d | ||
|
|
b5e65ac9ed | ||
|
|
63e200726f | ||
|
|
b2b0f45473 | ||
|
|
bccb762e9f | ||
|
|
c26ee8534d | ||
|
|
924ddb787a | ||
|
|
0341679360 | ||
|
|
65c3bc91de | ||
|
|
be3d7b435d | ||
|
|
92dd13a225 | ||
|
|
8e023d1227 | ||
|
|
d21b3258e3 | ||
|
|
331a51e842 | ||
|
|
63a1e25129 | ||
|
|
fae7ab2418 | ||
|
|
65a4f36de5 | ||
|
|
04d49fcf35 | ||
|
|
535ef6be38 | ||
|
|
d3b7d7a13d | ||
|
|
b92b62a8fb | ||
|
|
7eb34013dd | ||
|
|
e18eb32d8b | ||
|
|
4ebe09bb72 | ||
|
|
a07dc968e7 | ||
|
|
28991d30f4 | ||
|
|
11109f519c | ||
|
|
5e512e6570 | ||
|
|
c032d28aaa | ||
|
|
768633e464 | ||
|
|
e501bbdd27 | ||
|
|
cb1d4fd278 | ||
|
|
e1deba51ab | ||
|
|
d53014a07f | ||
|
|
7865264de0 | ||
|
|
86661c1538 | ||
|
|
e2dd7425bd | ||
|
|
e01b16e586 | ||
|
|
6adc3c9f13 | ||
|
|
0de2dcb211 | ||
|
|
a8ad505af7 | ||
|
|
e8804500b0 | ||
|
|
66bed241f1 | ||
|
|
f8bd8e1bd6 | ||
|
|
d2eba7eefe | ||
|
|
5ddf34d39b | ||
|
|
2c1426a44d | ||
|
|
30e6cfce41 | ||
|
|
1ae2c0c9e0 | ||
|
|
1f5b11246e | ||
|
|
d3caa547ba | ||
|
|
026d941734 | ||
|
|
61b9c5e069 | ||
|
|
4b646aca90 | ||
|
|
50c1533fdd | ||
|
|
a577ee447b | ||
|
|
d7b85c42a0 | ||
|
|
3def0e0dec | ||
|
|
dc6d3f4afb | ||
|
|
3d1f363be8 | ||
|
|
dea54df71b | ||
|
|
6051150c14 | ||
|
|
a3929330b0 | ||
|
|
c404b761b7 | ||
|
|
9b1f2d5971 | ||
|
|
9d7e4ac15f | ||
|
|
d55a3a073a | ||
|
|
01bf741983 | ||
|
|
bf3734110e | ||
|
|
6dcf936807 | ||
|
|
1d884cb0e9 | ||
|
|
8e0bf3ebff | ||
|
|
380e3a8121 | ||
|
|
1f8ff7ff8d | ||
|
|
b1f1c11441 | ||
|
|
c918cf4a46 | ||
|
|
f835c7569e | ||
|
|
5aecd044c5 | ||
|
|
2a389a9abe | ||
|
|
6527262348 | ||
|
|
79e1273814 | ||
|
|
709c850e69 | ||
|
|
7ed8c0915d | ||
|
|
eef1c968dc | ||
|
|
0985158090 | ||
|
|
090ae5fa56 | ||
|
|
13cb81f4bb | ||
|
|
ef66ca6498 | ||
|
|
d43452f88d | ||
|
|
e719dc250a | ||
|
|
bb0efda526 | ||
|
|
e4d0a92d7c | ||
|
|
28d782e13c | ||
|
|
6f5f700cb9 | ||
|
|
a17924f819 | ||
|
|
893aae2ca4 | ||
|
|
4cbec1c817 | ||
|
|
d84771428a | ||
|
|
484d3ea36b | ||
|
|
c71e930ffa | ||
|
|
15584a4f81 | ||
|
|
f86f454956 | ||
|
|
e01e038cf9 | ||
|
|
c849dfeec4 | ||
|
|
8d7b03576c | ||
|
|
b292a5fc05 | ||
|
|
72019959a8 | ||
|
|
9565ea1034 | ||
|
|
49a2693357 | ||
|
|
10a5ca199d | ||
|
|
c2f622327f | ||
|
|
0e2628a3fb | ||
|
|
45dfa28dba | ||
|
|
c8cbac58f5 | ||
|
|
c1b5424ca6 | ||
|
|
c706c94e38 | ||
|
|
fad8abee34 | ||
|
|
9448c5939c | ||
|
|
752a90dc2f | ||
|
|
a60216ec15 | ||
|
|
5d0df8d880 | ||
|
|
1cd13ecdbd | ||
|
|
c14987aa18 | ||
|
|
aeec93a322 | ||
|
|
61930c3b6e | ||
|
|
296f1bacc1 | ||
|
|
bb80b432e6 | ||
|
|
be551a6b68 | ||
|
|
e0834f7f38 | ||
|
|
a26d91557b | ||
|
|
3f73c9bb54 | ||
|
|
09f3eb4a36 | ||
|
|
33885ed891 | ||
|
|
d21277f1b9 | ||
|
|
7b0f675785 | ||
|
|
db339b8fc3 | ||
|
|
eca8a46b40 | ||
|
|
4ca7f2a9bd | ||
|
|
221c63b766 | ||
|
|
9f04641fc7 | ||
|
|
3191b3efcb | ||
|
|
1a41ac3145 | ||
|
|
6d4dd5ae3b | ||
|
|
6cb3d86d15 | ||
|
|
7a4f85d382 | ||
|
|
5207be0778 | ||
|
|
2ceb0539af | ||
|
|
f9c67e21b2 | ||
|
|
baa2363e85 | ||
|
|
e5b8abfb23 | ||
|
|
9f6f711f8d | ||
|
|
9a5b7bb0b0 | ||
|
|
eaf1cc9120 | ||
|
|
3bcd42dc8f | ||
|
|
744fbed783 | ||
|
|
c9454b346e | ||
|
|
5ec2c37e7e | ||
|
|
25602e487d | ||
|
|
e037ffd952 | ||
|
|
48c1a7982c | ||
|
|
a842b327c7 | ||
|
|
f8034d69ef | ||
|
|
d94dac28a8 | ||
|
|
680c6f0503 | ||
|
|
39717989a8 | ||
|
|
c26b7ce675 | ||
|
|
c6f6ea7358 | ||
|
|
c0c838f1bc | ||
|
|
1a45e9164f | ||
|
|
8a5f129e56 | ||
|
|
65c2ceb89d | ||
|
|
7a2e9c02cd | ||
|
|
f88415b1d7 | ||
|
|
1250010696 | ||
|
|
506a0ba7d6 | ||
|
|
1d4914c590 | ||
|
|
3e28a10676 | ||
|
|
78028a3310 | ||
|
|
25a27f9dd9 | ||
|
|
03e306c805 | ||
|
|
b9cecbef64 | ||
|
|
8b32096e2a | ||
|
|
ba462eb8b7 | ||
|
|
5a09819729 | ||
|
|
d3296d4895 | ||
|
|
39c9c54760 | ||
|
|
8bee5b1108 | ||
|
|
e4c2400eb2 | ||
|
|
1409207def | ||
|
|
30fdadc525 | ||
|
|
a5db0297b0 | ||
|
|
e25f946ac0 | ||
|
|
2f4f075005 | ||
|
|
3ca85491ee | ||
|
|
d8351ec1b2 | ||
|
|
77508b9afa | ||
|
|
38de6ebf3a | ||
|
|
af3ee49f57 | ||
|
|
0cb6ea34d7 | ||
|
|
b6df73d3b9 | ||
|
|
2d79e1a2e0 | ||
|
|
7b311b6adb | ||
|
|
df4a380e42 | ||
|
|
6ff80e80a4 | ||
|
|
8b6b111541 | ||
|
|
fd8f01e317 | ||
|
|
00317dd47f | ||
|
|
e9637f6d11 | ||
|
|
1f9ed2c5ec | ||
|
|
7677b59650 | ||
|
|
9cf4792d53 | ||
|
|
4d9f029000 | ||
|
|
9916686c24 | ||
|
|
c86377790f | ||
|
|
2a791bfb38 | ||
|
|
1d3ac6bc1f | ||
|
|
3fa5a04947 | ||
|
|
7c5b0f737c | ||
|
|
c116808fdb | ||
|
|
553f3d77a9 | ||
|
|
642fbe9fc5 | ||
|
|
395a2248d8 | ||
|
|
be67cae29f | ||
|
|
f62a00bedb | ||
|
|
646a6056a2 | ||
|
|
4504c2bceb | ||
|
|
d343db34fd | ||
|
|
b5e12077b2 | ||
|
|
f3753ea9ad | ||
|
|
45e289d32d | ||
|
|
40cabff44f | ||
|
|
a9c98ad5f2 | ||
|
|
b8e758edf0 | ||
|
|
0b48f69b4e | ||
|
|
d1e7e325b7 | ||
|
|
75b1db0add | ||
|
|
6e965523a1 | ||
|
|
8589c0691b | ||
|
|
99ef8ec4f1 | ||
|
|
d22c9a8b05 | ||
|
|
f84f50842c | ||
|
|
65720f49fe | ||
|
|
6243736481 | ||
|
|
e331e4831b | ||
|
|
78ee61558d | ||
|
|
07c4ff7ea7 | ||
|
|
e5422dddd2 | ||
|
|
6af201ea03 | ||
|
|
27a40cfdcd | ||
|
|
3bd480a375 | ||
|
|
aa951af2b7 | ||
|
|
55747bf79d | ||
|
|
1cd7689d03 | ||
|
|
bd5cc96956 | ||
|
|
a0dbb1aa5d | ||
|
|
4777966b4c | ||
|
|
860a74ddd8 | ||
|
|
2bb645e0bc | ||
|
|
47db80315c | ||
|
|
0348664512 | ||
|
|
3987e0753d | ||
|
|
6b73cc39a5 | ||
|
|
b0de1a8d7e | ||
|
|
37fe6e4219 | ||
|
|
89cdbf63be | ||
|
|
7f955cc070 | ||
|
|
4db5b9d7ed | ||
|
|
dadd145d09 | ||
|
|
bdf5ee7ab7 | ||
|
|
ebaa4c7d5d | ||
|
|
c33600bcc3 | ||
|
|
85d2cc78d6 | ||
|
|
18071562ba | ||
|
|
5aeff6d47d | ||
|
|
a298b03735 | ||
|
|
3d0a2b55ce | ||
|
|
19871efd5a | ||
|
|
1410c339de | ||
|
|
96d32b29c9 | ||
|
|
88816e150a | ||
|
|
409fc4dc19 | ||
|
|
c54b36c902 | ||
|
|
19cbab78b2 | ||
|
|
1736cd9bc8 | ||
|
|
a5264e9995 | ||
|
|
6868127ba3 | ||
|
|
dbbadbc309 | ||
|
|
fb08164cbc | ||
|
|
7e999c5496 | ||
|
|
4fac825457 | ||
|
|
35c66744db | ||
|
|
930e04f6c7 | ||
|
|
37756b8d06 | ||
|
|
596c93ce7e | ||
|
|
edfae1abfb | ||
|
|
624943b3ca | ||
|
|
ef89a760d6 | ||
|
|
050aa277ae | ||
|
|
f03dfb50ad | ||
|
|
6e8474f584 | ||
|
|
4e73b1b133 | ||
|
|
e08e29c8b4 | ||
|
|
b82ca28190 | ||
|
|
e02d186946 | ||
|
|
d9b02657a7 | ||
|
|
d761a2273c | ||
|
|
e3d9cc30a8 | ||
|
|
1ef7994ae2 | ||
|
|
081f397460 | ||
|
|
f800298d01 | ||
|
|
301a25303f | ||
|
|
b24eb6ce88 | ||
|
|
fd60bfd3d2 | ||
|
|
da2c4b0fa1 | ||
|
|
4251979e8b | ||
|
|
12783674cb | ||
|
|
c17ffcae2c | ||
|
|
897f14e60a | ||
|
|
4163eb28d0 | ||
|
|
500442e5c5 | ||
|
|
8c54803094 | ||
|
|
2baf31dff8 | ||
|
|
d997397c38 | ||
|
|
7773000c36 | ||
|
|
042f7ccbcd | ||
|
|
44aa8a6b91 | ||
|
|
43c671cb5c | ||
|
|
a3df37b851 | ||
|
|
c01c2bd742 | ||
|
|
533ee87bb1 | ||
|
|
c810406195 | ||
|
|
3ec8a867db | ||
|
|
899a70908e | ||
|
|
bf95d77562 | ||
|
|
db992e808f | ||
|
|
f2aca68b82 | ||
|
|
12b448ef01 | ||
|
|
e77bb0157e | ||
|
|
75631bd8f1 | ||
|
|
63b1887ff2 | ||
|
|
ba36e47575 | ||
|
|
3866c4526e | ||
|
|
cb08f02de1 | ||
|
|
4188fbecee | ||
|
|
f261bf7e97 | ||
|
|
88dc9b6b63 | ||
|
|
632a265e14 | ||
|
|
449cd0a76e | ||
|
|
181a53d3ed | ||
|
|
44958409f5 | ||
|
|
f81129aa68 | ||
|
|
e5ef0d97bd | ||
|
|
469036990a | ||
|
|
d06f5c7c54 | ||
|
|
9911939576 | ||
|
|
c9ace14c40 | ||
|
|
d5cdb91d55 | ||
|
|
360be597a8 | ||
|
|
75f7c9ae0c | ||
|
|
c926454a41 | ||
|
|
5cfe7ea0aa | ||
|
|
c70fb4ba08 | ||
|
|
7cba9f3cb2 | ||
|
|
d6acb8d059 | ||
|
|
ec23b70bb7 | ||
|
|
58f2f5007d | ||
|
|
0caf4fd9d0 | ||
|
|
037ce08f72 | ||
|
|
27cdd27889 | ||
|
|
f60a6561bb | ||
|
|
204862ac3c | ||
|
|
0f50849fbb | ||
|
|
404c22ac86 | ||
|
|
fe555e4539 | ||
|
|
c87e629150 | ||
|
|
b9d6c816f1 | ||
|
|
0153a25061 | ||
|
|
476a4c7bc4 | ||
|
|
08d80b35cb | ||
|
|
6622b5fe3a | ||
|
|
d7bb5658f2 | ||
|
|
2f3627cd6d | ||
|
|
ce9fd0147f | ||
|
|
be12f56856 | ||
|
|
e0f41198d6 | ||
|
|
fb31a88c51 | ||
|
|
254ccb9ccb | ||
|
|
d2bebee9d9 | ||
|
|
b2c9352bb5 | ||
|
|
15481a9520 | ||
|
|
37723698dc | ||
|
|
af8c08e6a7 | ||
|
|
01249000c3 | ||
|
|
f6edd098a9 | ||
|
|
6321fb6a92 | ||
|
|
69ba009439 | ||
|
|
86e5762b1c | ||
|
|
49363c660c | ||
|
|
1debbc3100 | ||
|
|
ae0b09dd3a | ||
|
|
8d0afa632d | ||
|
|
561953e494 | ||
|
|
83a7796b74 | ||
|
|
ce72eb4eb4 | ||
|
|
7cde5f247e | ||
|
|
849e7cb4d5 | ||
|
|
92c823680a | ||
|
|
05f1541903 | ||
|
|
30d42e2806 | ||
|
|
ebdf4e478a | ||
|
|
f6bc1afcbb | ||
|
|
9013dcb527 | ||
|
|
dbe13aecea | ||
|
|
6521ceaf92 | ||
|
|
f497dbf01e | ||
|
|
8a9486eb49 | ||
|
|
2fb57805ea | ||
|
|
919c1d695c | ||
|
|
1530594b4b | ||
|
|
6f0d8e8dda | ||
|
|
62d7c081dc | ||
|
|
f78994b66c | ||
|
|
50a8c17cf8 | ||
|
|
6f9643df79 | ||
|
|
aeaf8e8433 | ||
|
|
7afb280990 | ||
|
|
99a46fd5af | ||
|
|
eed4ff7e2d | ||
|
|
659714f45d | ||
|
|
8f70c5ca35 | ||
|
|
0ea64ad8ab | ||
|
|
9fbb449e06 | ||
|
|
be3c4cf268 | ||
|
|
0a8fd50c4a | ||
|
|
70db096b6d | ||
|
|
005df31a0d | ||
|
|
d6193c1622 | ||
|
|
a74f2827b2 | ||
|
|
392b162024 | ||
|
|
4af4c8cca9 | ||
|
|
3c4346acb2 | ||
|
|
b8c1f9ab67 | ||
|
|
2e9970a98c | ||
|
|
4914b734dc | ||
|
|
0df3eabe26 | ||
|
|
8fe2211e2b | ||
|
|
645ee2003f | ||
|
|
d6f1162547 | ||
|
|
46991aa65c | ||
|
|
7eb41304e6 | ||
|
|
24da00bd5a | ||
|
|
34efc7db51 | ||
|
|
acf010326c | ||
|
|
d7814ed767 | ||
|
|
19e60b698f | ||
|
|
a7cfdc3a87 | ||
|
|
b010b8e3ca | ||
|
|
26a2c69c2e | ||
|
|
608bad26cf | ||
|
|
70768176f9 | ||
|
|
694a6ed4a1 | ||
|
|
dc15fa965b | ||
|
|
d78739d163 | ||
|
|
d90ce68f5d | ||
|
|
d2c52ff35b | ||
|
|
813b4cf74c | ||
|
|
a437b38270 | ||
|
|
f9d060146c | ||
|
|
7f0c6b9c21 | ||
|
|
5a7cfd8c02 | ||
|
|
babe694366 | ||
|
|
7560b29fb9 | ||
|
|
f6753a9013 | ||
|
|
647e53bcbb | ||
|
|
8439fc6c19 | ||
|
|
6f61cf2e4e | ||
|
|
191187ed1b | ||
|
|
1fb01d4d98 | ||
|
|
3106fe0ed6 | ||
|
|
e29954e03f | ||
|
|
3b5d56e087 | ||
|
|
aa91186119 | ||
|
|
d08f5af9c6 | ||
|
|
b96e471fa2 | ||
|
|
7120ab7b13 | ||
|
|
2f5dcda3b6 | ||
|
|
120b5dc80e | ||
|
|
d762253f74 | ||
|
|
1d28b935e8 | ||
|
|
4b4a1c6cac | ||
|
|
110a1b2ac7 | ||
|
|
79558910d1 | ||
|
|
fbf85398da | ||
|
|
1e4b96aa0a | ||
|
|
c064ae6bc3 | ||
|
|
39228f3495 | ||
|
|
12e2237131 | ||
|
|
066a9b7a61 | ||
|
|
cdb180e1d4 | ||
|
|
a8ecce7421 | ||
|
|
8c3461f0ff | ||
|
|
305f448d05 | ||
|
|
5f90a3e48c | ||
|
|
96cf190720 | ||
|
|
373832ba22 | ||
|
|
4f472e451e | ||
|
|
d36bbec5b5 | ||
|
|
e258058cf1 | ||
|
|
c3ac1aac8c | ||
|
|
234f73e7bf | ||
|
|
f49dd97d24 | ||
|
|
7bd1565cfb | ||
|
|
6e448da90d | ||
|
|
9f035108e1 | ||
|
|
4bf2e1669d | ||
|
|
dd30c1b39d | ||
|
|
94006cb44c | ||
|
|
2e6ec91ce0 | ||
|
|
fe80da362c | ||
|
|
82aca1b02e | ||
|
|
4211e651d0 | ||
|
|
f9e1289463 | ||
|
|
a09b4e3b92 | ||
|
|
ab6ae621cb | ||
|
|
17ae0a6a09 | ||
|
|
041925c123 | ||
|
|
9292a087e8 | ||
|
|
fef0fd82ff | ||
|
|
5cbd587833 | ||
|
|
7c9d154461 | ||
|
|
8189c4ee43 | ||
|
|
05de2f56b4 | ||
|
|
e38494a10c | ||
|
|
e178baefbd | ||
|
|
bfa2bfc8ae |
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) 2008 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
|
||||
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# include "AStatement.h"
|
||||
|
||||
AContrib::AContrib(PExpr*lv, PExpr*rv)
|
||||
: lval_(lv), rval_(rv)
|
||||
{
|
||||
}
|
||||
|
||||
AContrib::~AContrib()
|
||||
{
|
||||
delete lval_;
|
||||
delete rval_;
|
||||
}
|
||||
|
||||
AProcess::~AProcess()
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
#ifndef __AStatement_H
|
||||
#define __AStatement_H
|
||||
/*
|
||||
* Copyright (c) 2008 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
|
||||
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
# include <map>
|
||||
# include "ivl_target.h"
|
||||
# include "StringHeap.h"
|
||||
# include "LineInfo.h"
|
||||
# include "Statement.h"
|
||||
# include "PExpr.h"
|
||||
|
||||
class PExpr;
|
||||
class NetAnalog;
|
||||
class NetScope;
|
||||
class Design;
|
||||
|
||||
/*
|
||||
* A contribution statement is like an assignment: there is an l-value
|
||||
* expression and an r-value expression. The l-value is a branch probe
|
||||
* expression.
|
||||
*/
|
||||
class AContrib : public Statement {
|
||||
|
||||
public:
|
||||
AContrib(PExpr*lval, PExpr*rval);
|
||||
~AContrib();
|
||||
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
|
||||
private:
|
||||
PExpr*lval_;
|
||||
PExpr*rval_;
|
||||
};
|
||||
|
||||
/*
|
||||
* An analog process is not a statement, but contains an analog
|
||||
* statement. The process is where we attach process characteristics
|
||||
* such as initial vs. always, attributes....
|
||||
*/
|
||||
class AProcess : public LineInfo {
|
||||
|
||||
public:
|
||||
AProcess(ivl_process_type_t t, Statement*st)
|
||||
: type_(t), statement_(st) { }
|
||||
|
||||
~AProcess();
|
||||
|
||||
bool elaborate(Design*des, NetScope*scope) const;
|
||||
|
||||
ivl_process_type_t type() const { return type_; }
|
||||
Statement*statement() { return statement_; }
|
||||
|
||||
map<perm_string,PExpr*> attributes;
|
||||
|
||||
// Dump the analog process
|
||||
void dump(ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
ivl_process_type_t type_;
|
||||
Statement*statement_;
|
||||
|
||||
private: // not implemented
|
||||
AProcess(const AProcess&);
|
||||
AProcess& operator= (const AProcess&);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -4,23 +4,24 @@ HOW TO REPORT BUGS
|
||||
Before I can fix an error, I need to understand what the problem
|
||||
is. Try to explain what is wrong and why you think it is wrong. Please
|
||||
try to include sample code that demonstrates the problem. Include a
|
||||
description of what ivl does that is wrong, and what you expect should
|
||||
happen. And include the command line flags passed to the compiler to make
|
||||
the error happen. (This is often overlooked, and sometimes important.)
|
||||
description of what Icarus Verilog does that is wrong, and what you
|
||||
expect should happen. And include the command line flags passed to the
|
||||
compiler to make the error happen. (This is often overlooked, and
|
||||
sometimes important.)
|
||||
|
||||
* The Compiler Doesn't Compile
|
||||
|
||||
If the Icarus Verilog don't compile, I need to know about the
|
||||
If Icarus Verilog doesn't compile, I need to know about the
|
||||
compilation tools you are using. Specifically, I need to know:
|
||||
|
||||
- Operating system and processor type,
|
||||
- Compiler w/ version,
|
||||
- Library version, and
|
||||
- Versions of any libraries being linked, and
|
||||
- anything else you think relevant.
|
||||
|
||||
Be aware that I do not have at my disposal a porting lab. I have the
|
||||
alpha on my desk, and the Linux/Intel box with a logic analyzer and
|
||||
'scope hanging off it.
|
||||
workstation on my desk, a Mac laptop, and the Linux/Intel box with a
|
||||
logic analyzer and 'scope hanging off it.
|
||||
|
||||
* The Compiler Crashes
|
||||
|
||||
@@ -28,26 +29,26 @@ No compiler should crash, no matter what kind of garbage is fed to
|
||||
it. If the compiler crashes, you definitely found a bug and I need to
|
||||
know about it.
|
||||
|
||||
Ivl internally checks its state while it works, and if it detects
|
||||
something wrong that it cannot recover from, it will abort
|
||||
Icarus Verilog internally checks its state while it works, and if it
|
||||
detects something wrong that it cannot recover from, it will abort
|
||||
intentionally. The "assertion failure" message that the program
|
||||
prints in the process of dying is very important. It tells me where in
|
||||
the source the bad thing happened. Include that message in the bug
|
||||
report.
|
||||
|
||||
If there are not assertion messages, I need to know that as well.
|
||||
If there are no assertion messages, I need to know that as well.
|
||||
|
||||
I also need a complete test program that demonstrates the crash.
|
||||
|
||||
* It Doesn't Like My Perfectly Valid Program(tm)
|
||||
|
||||
I need to know what you think is right that ivl gets wrong. Does it
|
||||
reject your "Perfectly Valid Program(tm)" or does it compile it but
|
||||
give incorrect results? The latter is the most insidious as it doesn't
|
||||
scream out to be fixed unless someone is watching closely. However, if
|
||||
I get a sample program from you, and I can compile it, and I run it
|
||||
and nuclear junk doesn't fall from the sky, I'm moving on to the next
|
||||
problem.
|
||||
I need to know what you think is right that Icarus Verilog gets
|
||||
wrong. Does it reject your "Perfectly Valid Program(tm)" or does it
|
||||
compile it but give incorrect results? The latter is the most
|
||||
insidious as it doesn't scream out to be fixed unless someone is
|
||||
watching closely. However, if I get a sample program from you, and I
|
||||
can compile it, and I run it and nuclear junk doesn't fall from the
|
||||
sky, I'm moving on to the next problem.
|
||||
|
||||
So, if your program doesn't compile, tell me so, tell me where the
|
||||
error occurs, and include a complete Perfectly Valid Test Program(tm).
|
||||
@@ -57,24 +58,25 @@ know. What's on my disk is more recent then the latest snapshot.
|
||||
|
||||
If your program does compile, but generates incorrect output, I need
|
||||
to know what it says and what you think it should say. From this I can
|
||||
take your sample program and work on ivl until it gets the proper
|
||||
results. For this to work, of course, I first need to know what is
|
||||
wrong with the output. Spell it out, because I've been known to miss
|
||||
the obvious. Compiler writers often get buried in the details of the
|
||||
wrong problem.
|
||||
take your sample program and work on Icarus Verilog until it gets the
|
||||
proper results. For this to work, of course, I first need to know what
|
||||
is wrong with the output. Spell it out, because I've been known to
|
||||
miss the obvious. Compiler writers often get buried in the details of
|
||||
the wrong problem.
|
||||
|
||||
* It Generates Incorrect Target Code (XNF, EDIF/LPM, etc.)
|
||||
* It Generates Incorrect Target Code
|
||||
|
||||
As ivl adds target code generators, there will be cases where errors
|
||||
in the output netlist format occur. This is a tough nut because I
|
||||
might not have all the tools to test the target format you are
|
||||
reporting problems with. However, if you clearly explain what is right
|
||||
and wrong about the generated netlist, I will probably be able to fix
|
||||
the problem. It may take a few iterations.
|
||||
As Icarus Verilog adds target code generators, there will be cases
|
||||
where errors in the output netlist format occur. This is a tough nut
|
||||
because I might not have all the tools to test the target format you
|
||||
are reporting problems with. However, if you clearly explain what is
|
||||
right and wrong about the generated output, I will probably be able
|
||||
to fix the problem. It may take a few iterations.
|
||||
|
||||
In this case, if possible include not only the sample Verilog program,
|
||||
but the generated netlist file(s) and a clear indication of what went
|
||||
wrong. If it is not clear to me, I will ask for clarification.
|
||||
wrong or what is expected. If it is not clear to me, I will ask for
|
||||
clarification.
|
||||
|
||||
* The Output is Correct, But Less Than Ideal
|
||||
|
||||
@@ -91,13 +93,13 @@ demonstrates the problem. If the error occurs after elaboration,
|
||||
please include a top level module in the program that is suitable for
|
||||
the target format. If I have to write the module myself, I might not
|
||||
write it in a way that tickles the bug. So please, send all the
|
||||
Verilog source (after preprocessing) that I need to invoke the error.
|
||||
Verilog source that I need to invoke the error.
|
||||
|
||||
Also, include the command line you use to invoke the compiler. For
|
||||
example:
|
||||
|
||||
ivl foo.vl -o foo.cc -tvvm
|
||||
ivl foo.vl -s starthere
|
||||
iverilog -o foo.out -tvvp foo.v
|
||||
iverilog foo.vl -s starthere
|
||||
|
||||
If the error occurs with the null target (``-tnull'') then a top level
|
||||
module may not be needed as long as the ``-s <name>'' switch is
|
||||
@@ -108,15 +110,19 @@ invoke the error without any Verilog other than what is included?" And
|
||||
while we are at it, please place a copyright notice in your test
|
||||
program and include a GPL license statement if you can. Your test
|
||||
program may find its way into the test suite, and the notices will
|
||||
make it all nice and legal.
|
||||
make it all nice and legal. Please look at the existing tests in the
|
||||
test suite <http://sourceforge.net/ivtest> for examples of good test
|
||||
programs.
|
||||
|
||||
RESEARCHING EXISTING/PAST BUGS, AND FILING REPORTS
|
||||
|
||||
The URL <http://www.icarus.com/cgi-bin/ivl-bugs> is the main bug
|
||||
tracking system. Once you believe you have found a bug, you may browse
|
||||
the bugs database for existing bugs that may be related to yours. You
|
||||
might find that your bug has already been fixed in a later release or
|
||||
snapshot. If that's the case, then you are set.
|
||||
The URL <http://sourceforge.net/tracker/?group_id=149850> is the main
|
||||
bug tracking system. Once you believe you have found a bug, you may
|
||||
browse the bugs database for existing bugs that may be related to
|
||||
yours. You might find that your bug has already been fixed in a later
|
||||
release or snapshot. If that's the case, then you are set. Also,
|
||||
consider if you are reporting a bug or really asking for a new
|
||||
feature, and use the appropriate tracker.
|
||||
|
||||
The bug database supports basic keyword searches, and you can
|
||||
optionally limit your search to active bugs, or fixed bugs. You may
|
||||
@@ -125,8 +131,7 @@ broken. You may for example find a related bug that explains your
|
||||
symptom.
|
||||
|
||||
The root page of the bug report database describes how to submit your
|
||||
completed bug report. You may submit it via the web form, or via
|
||||
e-mail.
|
||||
completed bug report.
|
||||
|
||||
HOW TO SEND PATCHES
|
||||
|
||||
@@ -134,21 +139,26 @@ Bug reports with patches are very welcome, especially if they are
|
||||
formatted such that I can inspect them, decide that they are obviously
|
||||
correct, and apply them without worry.
|
||||
|
||||
I prefer context diffs as emitted by diff from GNU diffutils. Human
|
||||
beings can read such things, and they are resilient to changing
|
||||
originals. A good set of flags to diff are ``diff -cNB''. With such
|
||||
diffs, I can look at the changes you are offering and probably tell at
|
||||
a glance that they are plausible. Then I can use patch(1) to apply
|
||||
them. Or I can apply them by hand.
|
||||
I prefer patches generated by the git source code tracking system. If
|
||||
you are editing the source, you really should be using the latest
|
||||
version from git. Please see the developer documentation for more
|
||||
detailed instructions -- <http://iverilog.wikia.com/wiki/>.
|
||||
|
||||
However, if you send patches, *please* tell me what this patch is
|
||||
supposed to accomplish, and if appropriate include a test program that
|
||||
demonstrates the efficacy of the patch. (If I have no idea what the
|
||||
patch is for, I will ask for clarification before applying it.)
|
||||
When you make a patch, submit it to the "Patches" tracker at
|
||||
<http://sourceforge.net/tracker/?group_id=149850>. Patches added to
|
||||
the "Patches" tracker enter the developer workflow, are checked,
|
||||
applied to the appropriate git branch, and are pushed. Then the
|
||||
tracker item is closed.
|
||||
|
||||
If you send patches, *please* tell me what this patch is supposed to
|
||||
accomplish, which branch you intended to be patched, and if
|
||||
appropriate include a test program that demonstrates the efficacy of
|
||||
the patch. (If I have no idea what the patch is for, I will ask for
|
||||
clarification before applying it.)
|
||||
|
||||
COPYRIGHT ISSUES
|
||||
|
||||
Icarus Verilog is Copyright (c) 1998-2003 Stephen Williams except
|
||||
Icarus Verilog is Copyright (c) 1998-2008 Stephen Williams except
|
||||
where otherwise noted. Minor patches are covered as derivative works
|
||||
(or editorial comment or whatever the appropriate legal term is) and
|
||||
folded into the rest of ivl. However, if a submission can reasonably
|
||||
@@ -158,19 +168,3 @@ then falls under the "otherwise noted" category.
|
||||
|
||||
I must insist that any copyright material submitted for inclusion
|
||||
include the GPL license notice as shown in the rest of the source.
|
||||
|
||||
|
||||
$Id: BUGS.txt,v 1.5 2007/03/22 16:08:14 steve Exp $
|
||||
$Log: BUGS.txt,v $
|
||||
Revision 1.5 2007/03/22 16:08:14 steve
|
||||
Spelling fixes from Larry
|
||||
|
||||
Revision 1.4 2003/02/19 04:36:31 steve
|
||||
Notes on hte bug database.
|
||||
|
||||
Revision 1.3 2003/01/30 16:23:07 steve
|
||||
Spelling fixes.
|
||||
|
||||
Revision 1.2 1999/08/06 04:05:28 steve
|
||||
Handle scope of parameters.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __HName_H
|
||||
#define __HName_H
|
||||
/*
|
||||
* Copyright (c) 2001-2007 Stephen Williams ([email protected])
|
||||
* Copyright (c) 2001-2008 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,11 +18,9 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: HName.h,v 1.7 2007/06/02 03:42:12 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <iostream>
|
||||
# include <list>
|
||||
# include "StringHeap.h"
|
||||
#ifdef __GNUC__
|
||||
#if __GNUC__ > 2
|
||||
@@ -57,7 +55,7 @@ class hname_t {
|
||||
|
||||
private:
|
||||
perm_string name_;
|
||||
// If the number is anything other then INT_MIN, then this is
|
||||
// If the number is anything other than INT_MIN, then this is
|
||||
// the numeric part of the name. Otherwise, it is not part of
|
||||
// the name at all.
|
||||
int number_;
|
||||
@@ -70,30 +68,16 @@ extern bool operator == (const hname_t&, const hname_t&);
|
||||
extern bool operator != (const hname_t&, const hname_t&);
|
||||
extern ostream& operator<< (ostream&, const hname_t&);
|
||||
|
||||
/*
|
||||
* $Log: HName.h,v $
|
||||
* Revision 1.7 2007/06/02 03:42:12 steve
|
||||
* Properly evaluate scope path expressions.
|
||||
*
|
||||
* Revision 1.6 2007/05/16 19:12:33 steve
|
||||
* Fix hname_t use of space for 1 perm_string.
|
||||
*
|
||||
* Revision 1.5 2007/04/26 03:06:21 steve
|
||||
* Rework hname_t to use perm_strings.
|
||||
*
|
||||
* Revision 1.4 2002/11/02 03:27:51 steve
|
||||
* Allow named events to be referenced by
|
||||
* hierarchical names.
|
||||
*
|
||||
* Revision 1.3 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.2 2002/06/14 03:25:51 steve
|
||||
* Compiler portability.
|
||||
*
|
||||
* Revision 1.1 2001/12/03 04:47:14 steve
|
||||
* Parser and pform use hierarchical names as hname_t
|
||||
* objects instead of encoded strings.
|
||||
*
|
||||
*/
|
||||
inline ostream& operator<< (ostream&out, const list<hname_t>&ll)
|
||||
{
|
||||
list<hname_t>::const_iterator cur = ll.begin();
|
||||
out << *cur;
|
||||
cur ++;
|
||||
while (cur != ll.end()) {
|
||||
out << "." << *cur;
|
||||
cur ++;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+70
-66
@@ -18,12 +18,35 @@
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
|
||||
# Normally, the "make" will build all the files only by dependencies.
|
||||
# The MODE, however, can control your rebuild intentions. The proper way
|
||||
# to use the MODE is on the make command like, this this:
|
||||
#
|
||||
# make MODE=XXXX all
|
||||
#
|
||||
# The possible MODE= values are:
|
||||
#
|
||||
# regular
|
||||
# Build as normal
|
||||
#
|
||||
# full
|
||||
# Do some extra builds. in particular:
|
||||
# Build version.h again, even if it already exists.
|
||||
#
|
||||
MODE=regular
|
||||
|
||||
# This version string is only used in the version message printed
|
||||
# by the compiler. It reflects the assigned version number for the
|
||||
# product as a whole. Most components also print the CVS Name: token
|
||||
# in order to get a more automatic version stamp as well.
|
||||
VERSION = 0.9.devel
|
||||
|
||||
# This string is used as an installation suffix. It modifies certain
|
||||
# key install paths/files such that a build and install of Icarus Verilog
|
||||
# with the same $(prefix) but a different $(suffix) will not interfere.
|
||||
# The normal configuratin leaves suffix empty
|
||||
suffix = @install_suffix@
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
srcdir = @srcdir@
|
||||
@@ -35,7 +58,9 @@ VPATH = $(srcdir)
|
||||
|
||||
bindir = @bindir@
|
||||
libdir = @libdir@
|
||||
includedir = @includedir@
|
||||
# This is actually the directory where we install our own header files.
|
||||
# It is a little different from the generic includedir.
|
||||
includedir = @includedir@/verilog$(suffix)
|
||||
mandir = @mandir@
|
||||
|
||||
dllib=@DLLIB@
|
||||
@@ -52,15 +77,15 @@ MAN = @MAN@
|
||||
PS2PDF = @PS2PDF@
|
||||
GIT = @GIT@
|
||||
|
||||
CPPFLAGS = @ident_support@ @DEFS@ -I. -I$(srcdir) @CPPFLAGS@
|
||||
CPPFLAGS = @ident_support@ @DEFS@ -I. -I$(srcdir) -DVERSION='"$(VERSION)"' @CPPFLAGS@
|
||||
CXXFLAGS = -Wall @CXXFLAGS@
|
||||
PICFLAGS = @PICFLAG@
|
||||
LDFLAGS = @rdynamic@ @LDFLAGS@
|
||||
|
||||
all: dep version.h ivl@EXEEXT@
|
||||
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) $@); done
|
||||
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) VERSION=$(VERSION) $@); done
|
||||
for dir in ivlpp ; \
|
||||
do (cd $$dir ; $(MAKE) $@); done
|
||||
do (cd $$dir ; $(MAKE) VERSION=$(VERSION) $@); done
|
||||
cd driver ; $(MAKE) VERSION=$(VERSION) $@
|
||||
|
||||
# In the windows world, the installer will need a dosify program to
|
||||
@@ -99,20 +124,22 @@ distclean: clean
|
||||
TT = t-dll.o t-dll-api.o t-dll-expr.o t-dll-proc.o
|
||||
FF = cprop.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 \
|
||||
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_pexpr.o elab_scope.o \
|
||||
elab_sig.o emit.o eval.o eval_attrib.o \
|
||||
elab_sig.o elab_sig_analog.o emit.o eval.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 net_assign.o \
|
||||
net_design.o net_event.o net_expr.o net_force.o net_func.o \
|
||||
load_module.o netlist.o netmisc.o net_analog.o net_assign.o \
|
||||
net_design.o net_event.o net_expr.o net_func.o \
|
||||
net_link.o net_modulo.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_disciplines.o pform_dump.o pform_types.o \
|
||||
parse.o parse_misc.o pform.o pform_analog.o pform_disciplines.o \
|
||||
pform_dump.o pform_types.o \
|
||||
set_width.o symbol_search.o sync.o sys_funcs.o \
|
||||
verinum.o verireal.o target.o targets.o \
|
||||
verinum.o verireal.o target.o \
|
||||
Attrib.o HName.o LineInfo.o Module.o PDelays.o PEvent.o \
|
||||
PExpr.o PGate.o PGenerate.o PScope.o PSpec.o \
|
||||
PTask.o PUdp.o PFunction.o PWire.o Statement.o StringHeap.o \
|
||||
PTask.o PUdp.o PFunction.o PWire.o Statement.o AStatement.o StringHeap.o \
|
||||
$(FF) $(TT)
|
||||
|
||||
Makefile: Makefile.in config.h.in config.status
|
||||
@@ -141,10 +168,11 @@ all: dep iverilog-vpi
|
||||
|
||||
iverilog-vpi: iverilog-vpi.sh
|
||||
sed -e 's;@SHARED@;@shared@;' -e 's;@PIC@;@PICFLAG@;' \
|
||||
-e 's;@SUFFIX@;$(suffix);' \
|
||||
-e 's;@IVCC@;$(CC);' \
|
||||
-e 's;@IVCXX@;$(CXX);' \
|
||||
-e 's;@IVCFLAGS@;$(CXXFLAGS);' \
|
||||
-e 's;@INCLUDEDIR@;@includedir@;' \
|
||||
-e 's;@INCLUDEDIR@;$(includedir);' \
|
||||
-e 's;@LIBDIR@;@libdir@;' $< > $@
|
||||
chmod +x $@
|
||||
endif
|
||||
@@ -185,7 +213,9 @@ iverilog-vpi.pdf: iverilog-vpi.ps
|
||||
# For VERSION_TAG in driver/main.c, first try git-describe, then look for a
|
||||
# version.h file in the source tree (included in snapshots and releases), and
|
||||
# finally use nothing.
|
||||
ifeq ($(MODE),full)
|
||||
.PHONY: version.h
|
||||
endif
|
||||
# "true" and "false" in the next few lines are Unix shell command names
|
||||
ifeq ($(GIT),none)
|
||||
GIT_PRESENT = false
|
||||
@@ -208,51 +238,43 @@ version.h:
|
||||
|
||||
ifeq (@MINGW32@,yes)
|
||||
ifeq ($(MAN),none)
|
||||
INSTALL_DOC = $(mandir)/man1/iverilog-vpi.1
|
||||
INSTALL_DOC = $(mandir)/man1/iverilog-vpi$(suffix).1
|
||||
else
|
||||
ifeq ($(PS2PDF),none)
|
||||
INSTALL_DOC = $(mandir)/man1/iverilog-vpi.1
|
||||
INSTALL_DOC = $(mandir)/man1/iverilog-vpi$(suffix).1
|
||||
else
|
||||
INSTALL_DOC = $(prefix)/iverilog-vpi.pdf $(mandir)/man1/iverilog-vpi.1
|
||||
INSTALL_DOC = $(prefix)/iverilog-vpi$(suffix).pdf $(mandir)/man1/iverilog-vpi$(suffix).1
|
||||
all: dep iverilog-vpi.pdf
|
||||
endif
|
||||
endif
|
||||
INSTALL_DOCDIR = $(mandir)/man1
|
||||
else
|
||||
INSTALL_DOC = $(mandir)/man1/iverilog-vpi.1
|
||||
INSTALL_DOC = $(mandir)/man1/iverilog-vpi$(suffix).1
|
||||
INSTALL_DOCDIR = $(mandir)/man1
|
||||
endif
|
||||
|
||||
ifeq (@MINGW32@,yes)
|
||||
WIN32_INSTALL = $(prefix)/hello.vl $(prefix)/sqrt.vl $(prefix)/sqrt-virtex.v $(prefix)/QUICK_START.txt
|
||||
WIN32_INSTALL =
|
||||
else
|
||||
WIN32_INSTALL = $(bindir)/iverilog-vpi
|
||||
WIN32_INSTALL = $(bindir)/iverilog-vpi$(suffix)
|
||||
endif
|
||||
|
||||
XNF_INSTALL = $(libdir)/ivl/xnf.conf $(libdir)/ivl/xnf-s.conf
|
||||
|
||||
install: all installdirs $(libdir)/ivl/ivl@EXEEXT@ $(libdir)/ivl/include/constants.vams $(libdir)/ivl/include/disciplines.vams $(includedir)/ivl_target.h $(includedir)/_pli_types.h $(includedir)/vpi_user.h $(includedir)/acc_user.h $(includedir)/veriuser.h $(WIN32_INSTALL) $(INSTALL_DOC)
|
||||
install: all installdirs $(libdir)/ivl$(suffix)/ivl@EXEEXT@ $(libdir)/ivl$(suffix)/include/constants.vams $(libdir)/ivl$(suffix)/include/disciplines.vams $(includedir)/ivl_target.h $(includedir)/_pli_types.h $(includedir)/vpi_user.h $(includedir)/acc_user.h $(includedir)/veriuser.h $(WIN32_INSTALL) $(INSTALL_DOC)
|
||||
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) $@); done
|
||||
for dir in vpi ivlpp driver; \
|
||||
do (cd $$dir ; $(MAKE) $@); done
|
||||
|
||||
$(bindir)/iverilog-vpi: ./iverilog-vpi
|
||||
$(INSTALL_SCRIPT) ./iverilog-vpi $(DESTDIR)$(bindir)/iverilog-vpi
|
||||
$(bindir)/iverilog-vpi$(suffix): ./iverilog-vpi
|
||||
$(INSTALL_SCRIPT) ./iverilog-vpi $(DESTDIR)$(bindir)/iverilog-vpi$(suffix)
|
||||
|
||||
$(libdir)/ivl/ivl@EXEEXT@: ./ivl@EXEEXT@
|
||||
$(INSTALL_PROGRAM) ./ivl@EXEEXT@ $(DESTDIR)$(libdir)/ivl/ivl@EXEEXT@
|
||||
$(libdir)/ivl$(suffix)/ivl@EXEEXT@: ./ivl@EXEEXT@
|
||||
$(INSTALL_PROGRAM) ./ivl@EXEEXT@ $(DESTDIR)$(libdir)/ivl$(suffix)/ivl@EXEEXT@
|
||||
|
||||
$(libdir)/ivl/include/constants.vams: $(srcdir)/constants.vams
|
||||
$(INSTALL_DATA) $(srcdir)/constants.vams $@
|
||||
$(libdir)/ivl$(suffix)/include/constants.vams: $(srcdir)/constants.vams
|
||||
$(INSTALL_DATA) $(srcdir)/constants.vams $(DESTDIR)$(libdir)/ivl$(suffix)/include/constants.vams
|
||||
|
||||
$(libdir)/ivl/include/disciplines.vams: $(srcdir)/disciplines.vams
|
||||
$(INSTALL_DATA) $(srcdir)/disciplines.vams $@
|
||||
|
||||
$(libdir)/ivl/xnf-s.conf: $(srcdir)/xnf-s.conf
|
||||
$(INSTALL_DATA) $(srcdir)/xnf-s.conf $(DESTDIR)$(libdir)/ivl/xnf-s.conf
|
||||
|
||||
$(libdir)/ivl/xnf.conf: $(srcdir)/xnf.conf
|
||||
$(INSTALL_DATA) $(srcdir)/xnf.conf $(DESTDIR)$(libdir)/ivl/xnf.conf
|
||||
$(libdir)/ivl$(suffix)/include/disciplines.vams: $(srcdir)/disciplines.vams
|
||||
$(INSTALL_DATA) $(srcdir)/disciplines.vams $(DESTDIR)$(libdir)/ivl$(suffix)/include/disciplines.vams
|
||||
|
||||
$(includedir)/ivl_target.h: $(srcdir)/ivl_target.h
|
||||
$(INSTALL_DATA) $(srcdir)/ivl_target.h $(DESTDIR)$(includedir)/ivl_target.h
|
||||
@@ -269,49 +291,31 @@ $(includedir)/acc_user.h: $(srcdir)/acc_user.h
|
||||
$(includedir)/veriuser.h: $(srcdir)/veriuser.h
|
||||
$(INSTALL_DATA) $(srcdir)/veriuser.h $(DESTDIR)$(includedir)/veriuser.h
|
||||
|
||||
$(mandir)/man1/iverilog-vpi.1: $(srcdir)/iverilog-vpi.man
|
||||
$(INSTALL_DATA) $(srcdir)/iverilog-vpi.man $(DESTDIR)$(mandir)/man1/iverilog-vpi.1
|
||||
$(mandir)/man1/iverilog-vpi$(suffix).1: $(srcdir)/iverilog-vpi.man
|
||||
$(INSTALL_DATA) $(srcdir)/iverilog-vpi.man $(DESTDIR)$(mandir)/man1/iverilog-vpi$(suffix).1
|
||||
|
||||
$(prefix)/iverilog-vpi.pdf: iverilog-vpi.pdf
|
||||
$(INSTALL_DATA) iverilog-vpi.pdf $(DESTDIR)$(prefix)/iverilog-vpi.pdf
|
||||
$(prefix)/iverilog-vpi$(suffix).pdf: iverilog-vpi.pdf
|
||||
$(INSTALL_DATA) iverilog-vpi.pdf $(DESTDIR)$(prefix)/iverilog-vpi$(suffix).pdf
|
||||
|
||||
# In windows installations, put a few examples and the quick_start
|
||||
# into the destination directory.
|
||||
ifeq (@MINGW32@,yes)
|
||||
$(prefix)/hello.vl: $(srcdir)/examples/hello.vl
|
||||
./dosify.exe $(srcdir)/examples/hello.vl tmp.vl
|
||||
mv tmp.vl $(prefix)/hello.vl
|
||||
|
||||
$(prefix)/sqrt.vl: $(srcdir)/examples/sqrt.vl
|
||||
./dosify.exe $(srcdir)/examples/sqrt.vl tmp.vl
|
||||
mv tmp.vl $(prefix)/sqrt.vl
|
||||
|
||||
$(prefix)/sqrt-virtex.v: $(srcdir)/examples/sqrt-virtex.v
|
||||
./dosify.exe $(srcdir)/examples/sqrt-virtex.v tmp.vl
|
||||
mv tmp.vl $(prefix)/sqrt-virtex.v
|
||||
|
||||
$(prefix)/QUICK_START.txt: $(srcdir)/QUICK_START.txt
|
||||
./dosify.exe $(srcdir)/QUICK_START.txt tmp.txt
|
||||
mv tmp.txt $(prefix)/QUICK_START.txt
|
||||
endif
|
||||
|
||||
installdirs: mkinstalldirs
|
||||
$(srcdir)/mkinstalldirs $(DESTDIR)$(bindir) $(DESTDIR)$(includedir) $(DESTDIR)$(libdir)/ivl \
|
||||
$(DESTDIR)$(libdir)/ivl/include $(DESTDIR)$(mandir) $(DESTDIR)$(mandir)/man1
|
||||
$(srcdir)/mkinstalldirs $(DESTDIR)$(bindir) $(DESTDIR)$(includedir) $(DESTDIR)$(libdir)/ivl$(suffix) \
|
||||
$(DESTDIR)$(libdir)/ivl$(suffix)/include $(DESTDIR)$(mandir) $(DESTDIR)$(mandir)/man1
|
||||
|
||||
uninstall:
|
||||
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) $@); done
|
||||
for dir in vpi ivlpp driver; \
|
||||
do (cd $$dir ; $(MAKE) $@); done
|
||||
for f in xnf.conf xnf-s.conf ivl@EXEEXT@ include/constants.vams include/disciplines.vams; \
|
||||
do rm -f $(DESTDIR)$(libdir)/ivl/$$f; done
|
||||
-rmdir $(DESTDIR)$(libdir)/ivl/include
|
||||
-rmdir $(DESTDIR)$(libdir)/ivl
|
||||
for f in verilog iverilog-vpi gverilog@EXEEXT@; \
|
||||
for f in ivl@EXEEXT@ include/constants.vams include/disciplines.vams; \
|
||||
do rm -f $(DESTDIR)$(libdir)/ivl$(suffix)/$$f; done
|
||||
-rmdir $(DESTDIR)$(libdir)/ivl$(suffix)/include
|
||||
-rmdir $(DESTDIR)$(libdir)/ivl$(suffix)
|
||||
for f in verilog$(suffix) iverilog-vpi$(suffix) gverilog$(suffix)@EXEEXT@; \
|
||||
do rm -f $(DESTDIR)$(bindir)/$$f; done
|
||||
for f in ivl_target.h vpi_user.h _pli_types.h acc_user.h veriuser.h; \
|
||||
do rm -f $(DESTDIR)$(includedir)/$$f; done
|
||||
rm -f $(DESTDIR)$(mandir)/man1/iverilog-vpi.1 $(DESTDIR)$(prefix)/iverilog-vpi.pdf
|
||||
-test X$(suffix) = X || rmdir $(DESTDIR)/$(includedir)
|
||||
rm -f $(DESTDIR)$(mandir)/man1/iverilog-vpi$(suffix).1 $(DESTDIR)$(prefix)/iverilog-vpi$(suffix).pdf
|
||||
|
||||
|
||||
-include $(patsubst %.o, dep/%.d, $O)
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
/* n is a permallocated string. */
|
||||
Module::Module(perm_string n)
|
||||
: PScope(n, 0)
|
||||
: PScope(n)
|
||||
{
|
||||
library_flag = false;
|
||||
default_nettype = NetNet::NONE;
|
||||
@@ -41,19 +41,9 @@ void Module::add_gate(PGate*gate)
|
||||
gates_.push_back(gate);
|
||||
}
|
||||
|
||||
void Module::add_task(perm_string name, PTask*task)
|
||||
{
|
||||
tasks_[name] = task;
|
||||
}
|
||||
|
||||
void Module::add_function(perm_string name, PFunction *func)
|
||||
{
|
||||
funcs_[name] = func;
|
||||
}
|
||||
|
||||
unsigned Module::port_count() const
|
||||
{
|
||||
return ports.count();
|
||||
return ports.size();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -61,10 +51,10 @@ unsigned Module::port_count() const
|
||||
* module. If the port is internally unconnected, return an empty
|
||||
* array.
|
||||
*/
|
||||
const svector<PEIdent*>& Module::get_port(unsigned idx) const
|
||||
const vector<PEIdent*>& Module::get_port(unsigned idx) const
|
||||
{
|
||||
assert(idx < ports.count());
|
||||
static svector<PEIdent*> zero;
|
||||
assert(idx < ports.size());
|
||||
static const vector<PEIdent*> zero;
|
||||
|
||||
if (ports[idx])
|
||||
return ports[idx]->expr;
|
||||
@@ -75,7 +65,7 @@ const svector<PEIdent*>& Module::get_port(unsigned idx) const
|
||||
unsigned Module::find_port(const char*name) const
|
||||
{
|
||||
assert(name != 0);
|
||||
for (unsigned idx = 0 ; idx < ports.count() ; idx += 1) {
|
||||
for (unsigned idx = 0 ; idx < ports.size() ; idx += 1) {
|
||||
if (ports[idx] == 0) {
|
||||
/* It is possible to have undeclared ports. These
|
||||
are ports that are skipped in the declaration,
|
||||
@@ -89,7 +79,7 @@ unsigned Module::find_port(const char*name) const
|
||||
return idx;
|
||||
}
|
||||
|
||||
return ports.count();
|
||||
return ports.size();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -22,7 +22,8 @@
|
||||
|
||||
# include <list>
|
||||
# include <map>
|
||||
# include "svector.h"
|
||||
# include <vector>
|
||||
# include <utility>
|
||||
# include "StringHeap.h"
|
||||
# include "HName.h"
|
||||
# include "named.h"
|
||||
@@ -58,7 +59,7 @@ class Module : public PScope, public LineInfo {
|
||||
public:
|
||||
struct port_t {
|
||||
perm_string name;
|
||||
svector<PEIdent*> expr;
|
||||
vector<PEIdent*> expr;
|
||||
};
|
||||
|
||||
public:
|
||||
@@ -75,40 +76,6 @@ class Module : public PScope, public LineInfo {
|
||||
|
||||
NetNet::Type default_nettype;
|
||||
|
||||
struct range_t {
|
||||
// True if this is an exclude
|
||||
bool exclude_flag;
|
||||
// lower bound
|
||||
// If low_open_flag is false and low_expr=0, then use -inf
|
||||
bool low_open_flag;
|
||||
PExpr*low_expr;
|
||||
// upper bound
|
||||
// If high_open_flag is false and high_expr=0, then use +inf
|
||||
bool high_open_flag;
|
||||
PExpr*high_expr;
|
||||
// Next range description in list
|
||||
struct range_t*next;
|
||||
};
|
||||
|
||||
/* The module has parameters that are evaluated when the
|
||||
module is elaborated. During parsing, I put the parameters
|
||||
into this map. */
|
||||
struct param_expr_t : public LineInfo {
|
||||
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;
|
||||
// Value expression
|
||||
PExpr*expr;
|
||||
// If there are range constrants, list them here
|
||||
range_t*range;
|
||||
};
|
||||
map<perm_string,param_expr_t>parameters;
|
||||
map<perm_string,param_expr_t>localparams;
|
||||
|
||||
|
||||
/* specparams are simpler then other params, in that they have
|
||||
no type information. They are merely constant
|
||||
expressions. */
|
||||
@@ -118,7 +85,8 @@ class Module : public PScope, public LineInfo {
|
||||
new parameters within the module, but may be used to set
|
||||
values within this module (when instantiated) or in other
|
||||
instantiated modules. */
|
||||
map<pform_name_t,PExpr*>defparms;
|
||||
typedef pair<pform_name_t,PExpr*> named_expr_t;
|
||||
list<named_expr_t>defparms;
|
||||
|
||||
/* Parameters may be overridden at instantiation time;
|
||||
the overrides do not contain explicit parameter names,
|
||||
@@ -130,7 +98,7 @@ class Module : public PScope, public LineInfo {
|
||||
|
||||
/* This is an array of port descriptors, which is in turn a
|
||||
named array of PEident pointers. */
|
||||
svector<port_t*> ports;
|
||||
vector<port_t*> ports;
|
||||
|
||||
map<perm_string,PExpr*> attributes;
|
||||
|
||||
@@ -138,6 +106,10 @@ class Module : public PScope, public LineInfo {
|
||||
set by the `timescale directive. */
|
||||
int time_unit, time_precision;
|
||||
|
||||
/* Task definitions within this module */
|
||||
map<perm_string,PTask*> tasks;
|
||||
map<perm_string,PFunction*> funcs;
|
||||
|
||||
/* The module has a list of genvars that may be used in
|
||||
various generate schemes. */
|
||||
map<perm_string,LineInfo*> genvars;
|
||||
@@ -152,11 +124,9 @@ class Module : public PScope, public LineInfo {
|
||||
perm_string mod_name() const { return pscope_name(); }
|
||||
|
||||
void add_gate(PGate*gate);
|
||||
void add_task(perm_string name, PTask*def);
|
||||
void add_function(perm_string name, PFunction*def);
|
||||
|
||||
unsigned port_count() const;
|
||||
const svector<PEIdent*>& get_port(unsigned idx) const;
|
||||
const vector<PEIdent*>& get_port(unsigned idx) const;
|
||||
unsigned find_port(const char*name) const;
|
||||
|
||||
PGate* get_gate(perm_string name);
|
||||
@@ -167,14 +137,12 @@ class Module : public PScope, public LineInfo {
|
||||
bool elaborate(Design*, NetScope*scope) const;
|
||||
|
||||
typedef map<perm_string,NetExpr*> replace_t;
|
||||
bool elaborate_scope(Design*, NetScope*scope, const replace_t&rep) const;
|
||||
bool elaborate_scope(Design*, NetScope*scope, const replace_t&rep);
|
||||
|
||||
bool elaborate_sig(Design*, NetScope*scope) const;
|
||||
|
||||
private:
|
||||
list<PGate*> gates_;
|
||||
map<perm_string,PTask*> tasks_;
|
||||
map<perm_string,PFunction*> funcs_;
|
||||
|
||||
static void elaborate_parm_item_(perm_string name, const param_expr_t&cur,
|
||||
Design*des, NetScope*scope);
|
||||
|
||||
+5
-5
@@ -101,7 +101,7 @@ static NetExpr*calculate_val(Design*des, NetScope*scope, const PExpr*expr)
|
||||
return dex;
|
||||
}
|
||||
|
||||
static NetExpr* make_delay_nets(Design*des, NetExpr*expr)
|
||||
static NetExpr* make_delay_nets(Design*des, NetScope*scope, NetExpr*expr)
|
||||
{
|
||||
if (dynamic_cast<NetESignal*> (expr))
|
||||
return expr;
|
||||
@@ -109,7 +109,7 @@ static NetExpr* make_delay_nets(Design*des, NetExpr*expr)
|
||||
if (dynamic_cast<NetEConst*> (expr))
|
||||
return expr;
|
||||
|
||||
NetNet*sig = expr->synthesize(des);
|
||||
NetNet*sig = expr->synthesize(des, scope);
|
||||
if (sig == 0) {
|
||||
cerr << expr->get_fileline() << ": error: Expression " << *expr
|
||||
<< " is not suitable for delay expression." << endl;
|
||||
@@ -132,17 +132,17 @@ void PDelays::eval_delays(Design*des, NetScope*scope,
|
||||
if (delay_[0]) {
|
||||
rise_time = calculate_val(des, scope, delay_[0]);
|
||||
if (as_nets_flag)
|
||||
rise_time = make_delay_nets(des, rise_time);
|
||||
rise_time = make_delay_nets(des, scope, rise_time);
|
||||
|
||||
if (delay_[1]) {
|
||||
fall_time = calculate_val(des, scope, delay_[1]);
|
||||
if (as_nets_flag)
|
||||
fall_time = make_delay_nets(des, fall_time);
|
||||
fall_time = make_delay_nets(des, scope, fall_time);
|
||||
|
||||
if (delay_[2]) {
|
||||
decay_time = calculate_val(des, scope, delay_[2]);
|
||||
if (as_nets_flag)
|
||||
decay_time = make_delay_nets(des, decay_time);
|
||||
decay_time = make_delay_nets(des, scope, decay_time);
|
||||
|
||||
} else {
|
||||
if (rise_time < fall_time)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998-2007 Stephen Williams <[email protected]>
|
||||
* Copyright (c) 1998-2008 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,28 +21,31 @@
|
||||
|
||||
# include <iostream>
|
||||
|
||||
# include "compiler.h"
|
||||
# include "PExpr.h"
|
||||
# include "Module.h"
|
||||
# include "netmisc.h"
|
||||
# include <typeinfo>
|
||||
|
||||
PExpr::PExpr()
|
||||
{
|
||||
expr_type_ = IVL_VT_NO_TYPE;
|
||||
}
|
||||
|
||||
PExpr::~PExpr()
|
||||
{
|
||||
}
|
||||
|
||||
bool PExpr::has_aa_term(Design*, NetScope*) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PExpr::is_the_same(const PExpr*that) const
|
||||
{
|
||||
return typeid(this) == typeid(that);
|
||||
}
|
||||
|
||||
bool PExpr::is_constant(Module*) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
NetNet* PExpr::elaborate_lnet(Design*des, NetScope*) const
|
||||
{
|
||||
cerr << get_fileline() << ": error: expression not valid in assign l-value: "
|
||||
@@ -67,9 +70,10 @@ PEBinary::~PEBinary()
|
||||
{
|
||||
}
|
||||
|
||||
bool PEBinary::is_constant(Module*mod) const
|
||||
bool PEBinary::has_aa_term(Design*des, NetScope*scope) const
|
||||
{
|
||||
return left_->is_constant(mod) && right_->is_constant(mod);
|
||||
assert(left_ && right_);
|
||||
return left_->has_aa_term(des, scope) || right_->has_aa_term(des, scope);
|
||||
}
|
||||
|
||||
PEBComp::PEBComp(char op, PExpr*l, PExpr*r)
|
||||
@@ -81,6 +85,16 @@ PEBComp::~PEBComp()
|
||||
{
|
||||
}
|
||||
|
||||
PEBLogic::PEBLogic(char op, PExpr*l, PExpr*r)
|
||||
: PEBinary(op, l, r)
|
||||
{
|
||||
assert(op == 'a' || op == 'o');
|
||||
}
|
||||
|
||||
PEBLogic::~PEBLogic()
|
||||
{
|
||||
}
|
||||
|
||||
PEBShift::PEBShift(char op, PExpr*l, PExpr*r)
|
||||
: PEBinary(op, l, r)
|
||||
{
|
||||
@@ -90,7 +104,7 @@ PEBShift::~PEBShift()
|
||||
{
|
||||
}
|
||||
|
||||
PECallFunction::PECallFunction(const pform_name_t&n, const svector<PExpr *> &parms)
|
||||
PECallFunction::PECallFunction(const pform_name_t&n, const vector<PExpr *> &parms)
|
||||
: path_(n), parms_(parms)
|
||||
{
|
||||
}
|
||||
@@ -103,7 +117,7 @@ static pform_name_t pn_from_ps(perm_string n)
|
||||
return tmp;
|
||||
}
|
||||
|
||||
PECallFunction::PECallFunction(perm_string n, const svector<PExpr*>&parms)
|
||||
PECallFunction::PECallFunction(perm_string n, const vector<PExpr*>&parms)
|
||||
: path_(pn_from_ps(n)), parms_(parms)
|
||||
{
|
||||
}
|
||||
@@ -113,29 +127,52 @@ PECallFunction::PECallFunction(perm_string n)
|
||||
{
|
||||
}
|
||||
|
||||
// NOTE: Anachronism. Try to work all use of svector out.
|
||||
PECallFunction::PECallFunction(const pform_name_t&n, const svector<PExpr *> &parms)
|
||||
: path_(n), parms_(vector_from_svector(parms))
|
||||
{
|
||||
}
|
||||
|
||||
PECallFunction::PECallFunction(perm_string n, const svector<PExpr*>&parms)
|
||||
: path_(pn_from_ps(n)), parms_(vector_from_svector(parms))
|
||||
{
|
||||
}
|
||||
|
||||
PECallFunction::~PECallFunction()
|
||||
{
|
||||
}
|
||||
|
||||
bool PECallFunction::has_aa_term(Design*des, NetScope*scope) const
|
||||
{
|
||||
bool flag = false;
|
||||
for (unsigned idx = 0 ; idx < parms_.size() ; idx += 1) {
|
||||
flag = parms_[idx]->has_aa_term(des, scope) || flag;
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
PEConcat::PEConcat(const svector<PExpr*>&p, PExpr*r)
|
||||
: parms_(p), repeat_(r)
|
||||
{
|
||||
}
|
||||
|
||||
bool PEConcat::is_constant(Module *mod) const
|
||||
{
|
||||
bool constant = repeat_? repeat_->is_constant(mod) : true;
|
||||
for (unsigned i = 0; constant && i < parms_.count(); ++i) {
|
||||
constant = constant && parms_[i]->is_constant(mod);
|
||||
}
|
||||
return constant;
|
||||
}
|
||||
|
||||
PEConcat::~PEConcat()
|
||||
{
|
||||
delete repeat_;
|
||||
}
|
||||
|
||||
bool PEConcat::has_aa_term(Design*des, NetScope*scope) const
|
||||
{
|
||||
bool flag = false;
|
||||
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) {
|
||||
flag = parms_[idx]->has_aa_term(des, scope) || flag;
|
||||
}
|
||||
if (repeat_)
|
||||
flag = repeat_->has_aa_term(des, scope) || flag;
|
||||
|
||||
return flag;
|
||||
}
|
||||
|
||||
PEEvent::PEEvent(PEEvent::edge_t t, PExpr*e)
|
||||
: type_(t), expr_(e)
|
||||
{
|
||||
@@ -150,6 +187,12 @@ PEEvent::edge_t PEEvent::type() const
|
||||
return type_;
|
||||
}
|
||||
|
||||
bool PEEvent::has_aa_term(Design*des, NetScope*scope) const
|
||||
{
|
||||
assert(expr_);
|
||||
return expr_->has_aa_term(des, scope);
|
||||
}
|
||||
|
||||
PExpr* PEEvent::expr() const
|
||||
{
|
||||
return expr_;
|
||||
@@ -170,11 +213,6 @@ const verireal& PEFNumber::value() const
|
||||
return *value_;
|
||||
}
|
||||
|
||||
bool PEFNumber::is_constant(Module*) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
PEIdent::PEIdent(const pform_name_t&that)
|
||||
: path_(that)
|
||||
{
|
||||
@@ -189,35 +227,20 @@ PEIdent::~PEIdent()
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* An identifier can be in a constant expression if (and only if) it is
|
||||
* a parameter or genvar.
|
||||
*
|
||||
* NOTE: This test does not work if the name is hierarchical!
|
||||
*/
|
||||
bool PEIdent::is_constant(Module*mod) const
|
||||
bool PEIdent::has_aa_term(Design*des, NetScope*scope) const
|
||||
{
|
||||
if (mod == 0) return false;
|
||||
NetNet* net = 0;
|
||||
const NetExpr*par = 0;
|
||||
NetEvent* eve = 0;
|
||||
|
||||
/* */
|
||||
perm_string tmp = path_.back().name;
|
||||
const NetExpr*ex1, *ex2;
|
||||
|
||||
{ map<perm_string,Module::param_expr_t>::const_iterator cur;
|
||||
cur = mod->parameters.find(tmp);
|
||||
if (cur != mod->parameters.end()) return true;
|
||||
}
|
||||
scope = symbol_search(0, des, scope, path_, net, par, eve, ex1, ex2);
|
||||
|
||||
{ map<perm_string,Module::param_expr_t>::const_iterator cur;
|
||||
cur = mod->localparams.find(tmp);
|
||||
if (cur != mod->localparams.end()) return true;
|
||||
}
|
||||
|
||||
{ map<perm_string,LineInfo*>::const_iterator cur;
|
||||
cur = mod->genvars.find(tmp);
|
||||
if (cur != mod->genvars.end()) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
if (scope)
|
||||
return scope->is_auto();
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
PENumber::PENumber(verinum*vp)
|
||||
@@ -245,11 +268,6 @@ bool PENumber::is_the_same(const PExpr*that) const
|
||||
return *value_ == *obj->value_;
|
||||
}
|
||||
|
||||
bool PENumber::is_constant(Module*) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
PEString::PEString(char*s)
|
||||
: text_(s)
|
||||
{
|
||||
@@ -265,11 +283,6 @@ string PEString::value() const
|
||||
return text_;
|
||||
}
|
||||
|
||||
bool PEString::is_constant(Module*) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
PETernary::PETernary(PExpr*e, PExpr*t, PExpr*f)
|
||||
: expr_(e), tru_(t), fal_(f)
|
||||
{
|
||||
@@ -279,11 +292,12 @@ PETernary::~PETernary()
|
||||
{
|
||||
}
|
||||
|
||||
bool PETernary::is_constant(Module*m) const
|
||||
bool PETernary::has_aa_term(Design*des, NetScope*scope) const
|
||||
{
|
||||
return expr_->is_constant(m)
|
||||
&& tru_->is_constant(m)
|
||||
&& fal_->is_constant(m);
|
||||
assert(expr_ && tru_ && fal_);
|
||||
return expr_->has_aa_term(des, scope)
|
||||
|| tru_->has_aa_term(des, scope)
|
||||
|| fal_->has_aa_term(des, scope);
|
||||
}
|
||||
|
||||
PEUnary::PEUnary(char op, PExpr*ex)
|
||||
@@ -295,8 +309,8 @@ PEUnary::~PEUnary()
|
||||
{
|
||||
}
|
||||
|
||||
bool PEUnary::is_constant(Module*m) const
|
||||
bool PEUnary::has_aa_term(Design*des, NetScope*scope) const
|
||||
{
|
||||
return expr_->is_constant(m);
|
||||
assert(expr_);
|
||||
return expr_->has_aa_term(des, scope);
|
||||
}
|
||||
|
||||
|
||||
@@ -36,9 +36,6 @@ class NetScope;
|
||||
* The PExpr class hierarchy supports the description of
|
||||
* expressions. The parser can generate expression objects from the
|
||||
* source, possibly reducing things that it knows how to reduce.
|
||||
*
|
||||
* The elaborate_net method is used by structural elaboration to build
|
||||
* up a netlist interpretation of the expression.
|
||||
*/
|
||||
|
||||
class PExpr : public LineInfo {
|
||||
@@ -49,11 +46,15 @@ class PExpr : public LineInfo {
|
||||
|
||||
virtual void dump(ostream&) const;
|
||||
|
||||
// This method tests whether the expression contains any
|
||||
// references to automatically allocated variables.
|
||||
virtual bool has_aa_term(Design*des, NetScope*scope) const;
|
||||
|
||||
// This method tests the width that the expression wants to
|
||||
// be. It is used by elaboration of assignments to figure out
|
||||
// the width of the expression.
|
||||
//
|
||||
// The "min" is the width of the local context, so it the
|
||||
// The "min" is the width of the local context, so is the
|
||||
// minimum width that this function should return. Initially
|
||||
// this is the same as the lval width.
|
||||
//
|
||||
@@ -66,13 +67,22 @@ class PExpr : public LineInfo {
|
||||
// the subexpression should not make l-value related
|
||||
// optimizations.
|
||||
//
|
||||
// The unsigned_flag is set to true if the expression is
|
||||
// The expr_type is an output argument that gives the
|
||||
// calculated type for the expression.
|
||||
//
|
||||
// The unsized_flag is set to true if the expression is
|
||||
// unsized and therefore expandable. This happens if a
|
||||
// sub-expression is an unsized literal. Some expressions make
|
||||
// special use of that.
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
unsigned min, unsigned lval,
|
||||
bool&unsized_flag) const;
|
||||
ivl_variable_type_t&expr_type,
|
||||
bool&unsized_flag);
|
||||
|
||||
// After the test_width method is complete, these methods
|
||||
// return valid results.
|
||||
ivl_variable_type_t expr_type() const { return expr_type_; }
|
||||
unsigned expr_width() const { return expr_width_; }
|
||||
|
||||
// During the elaborate_sig phase, we may need to scan
|
||||
// expressions to find implicit net declarations.
|
||||
@@ -98,17 +108,6 @@ class PExpr : public LineInfo {
|
||||
// evaluation of parameters.
|
||||
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
|
||||
// This method elaborate the expression as gates, for use in a
|
||||
// continuous assign or other wholly structural context.
|
||||
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
|
||||
unsigned lwidth,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0 =Link::STRONG,
|
||||
Link::strength_t drive1 =Link::STRONG)
|
||||
const;
|
||||
|
||||
// This method elaborates the expression as gates, but
|
||||
// restricted for use as l-values of continuous assignments.
|
||||
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope) const;
|
||||
@@ -138,11 +137,12 @@ class PExpr : public LineInfo {
|
||||
// expressions that must be structurally "identical".
|
||||
virtual bool is_the_same(const PExpr*that) const;
|
||||
|
||||
// Return true if this expression is a valid constant
|
||||
// expression. the Module pointer is needed to find parameter
|
||||
// identifiers and any other module specific interpretations
|
||||
// of expressions.
|
||||
virtual bool is_constant(Module*) const;
|
||||
protected:
|
||||
// The derived class test_width methods should fill these in.
|
||||
ivl_variable_type_t expr_type_;
|
||||
unsigned expr_width_;
|
||||
|
||||
static void suppress_binary_operand_sign_if_needed_(NetExpr*lp, NetExpr*rp);
|
||||
|
||||
private: // not implemented
|
||||
PExpr(const PExpr&);
|
||||
@@ -160,24 +160,22 @@ class PEConcat : public PExpr {
|
||||
virtual verinum* eval_const(Design*des, NetScope*sc) const;
|
||||
virtual void dump(ostream&) const;
|
||||
|
||||
virtual bool has_aa_term(Design*des, NetScope*scope) const;
|
||||
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
unsigned min, unsigned lval,
|
||||
ivl_variable_type_t&expr_type,
|
||||
bool&unsized_flag);
|
||||
|
||||
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
|
||||
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope) const;
|
||||
virtual NetNet* elaborate_bi_net(Design*des, NetScope*scope) const;
|
||||
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
|
||||
unsigned width,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
|
||||
int expr_width, bool sys_task_arg) const;
|
||||
virtual NetEConcat*elaborate_pexpr(Design*des, NetScope*) const;
|
||||
virtual NetAssign_* elaborate_lval(Design*des,
|
||||
NetScope*scope,
|
||||
bool is_force) const;
|
||||
virtual bool is_constant(Module*) const;
|
||||
|
||||
private:
|
||||
NetNet* elaborate_lnet_common_(Design*des, NetScope*scope,
|
||||
bool bidirectional_flag) const;
|
||||
@@ -208,6 +206,8 @@ class PEEvent : public PExpr {
|
||||
|
||||
virtual void dump(ostream&) const;
|
||||
|
||||
virtual bool has_aa_term(Design*des, NetScope*scope) const;
|
||||
|
||||
private:
|
||||
edge_t type_;
|
||||
PExpr *expr_;
|
||||
@@ -229,21 +229,14 @@ class PEFNumber : public PExpr {
|
||||
any rounding that is needed to get the value. */
|
||||
virtual verinum* eval_const(Design*des, NetScope*sc) const;
|
||||
|
||||
/* A PEFNumber is a constant, so this returns true. */
|
||||
virtual bool is_constant(Module*) const;
|
||||
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
unsigned min, unsigned lval,
|
||||
ivl_variable_type_t&expr_type,
|
||||
bool&unsized_flag);
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
|
||||
int expr_width, bool sys_task_arg) const;
|
||||
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
|
||||
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
|
||||
unsigned lwidth,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
|
||||
virtual void dump(ostream&) const;
|
||||
|
||||
private:
|
||||
@@ -262,9 +255,13 @@ class PEIdent : public PExpr {
|
||||
void append_name(perm_string);
|
||||
|
||||
virtual void dump(ostream&) const;
|
||||
|
||||
virtual bool has_aa_term(Design*des, NetScope*scope) const;
|
||||
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
unsigned min, unsigned lval,
|
||||
bool&unsized_flag) const;
|
||||
ivl_variable_type_t&expr_type,
|
||||
bool&unsized_flag);
|
||||
|
||||
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
|
||||
|
||||
@@ -278,15 +275,6 @@ class PEIdent : public PExpr {
|
||||
NetScope*scope,
|
||||
bool is_force) const;
|
||||
|
||||
// Structural r-values are OK.
|
||||
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
|
||||
unsigned lwidth,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
|
||||
int expr_width, bool sys_task_arg) const;
|
||||
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
@@ -295,7 +283,6 @@ class PEIdent : public PExpr {
|
||||
// only applies to Ident expressions.
|
||||
NetNet* elaborate_port(Design*des, NetScope*sc) const;
|
||||
|
||||
virtual bool is_constant(Module*) const;
|
||||
verinum* eval_const(Design*des, NetScope*sc) const;
|
||||
|
||||
const pform_name_t& path() const { return path_; }
|
||||
@@ -315,17 +302,19 @@ class PEIdent : public PExpr {
|
||||
|
||||
private:
|
||||
NetAssign_*elaborate_lval_net_word_(Design*, NetScope*, NetNet*) const;
|
||||
bool elaborate_lval_net_bit_(Design*, NetScope*, NetAssign_*) const;
|
||||
bool elaborate_lval_net_part_(Design*, NetScope*, NetAssign_*) const;
|
||||
bool elaborate_lval_net_idx_(Design*, NetScope*, NetAssign_*,
|
||||
index_component_t::ctype_t) const;
|
||||
|
||||
private:
|
||||
NetExpr*elaborate_expr_param(Design*des,
|
||||
NetScope*scope,
|
||||
const NetExpr*par,
|
||||
NetScope*found,
|
||||
const NetExpr*par_msb,
|
||||
const NetExpr*par_lsb) const;
|
||||
NetExpr*elaborate_expr_param_(Design*des,
|
||||
NetScope*scope,
|
||||
const NetExpr*par,
|
||||
NetScope*found,
|
||||
const NetExpr*par_msb,
|
||||
const NetExpr*par_lsb,
|
||||
int expr_wid) const;
|
||||
NetExpr*elaborate_expr_param_part_(Design*des,
|
||||
NetScope*scope,
|
||||
const NetExpr*par,
|
||||
@@ -365,38 +354,6 @@ class PEIdent : public PExpr {
|
||||
NetESignal*net,
|
||||
NetScope*found) const;
|
||||
|
||||
public:
|
||||
|
||||
NetNet* elaborate_net_array_(Design*des, NetScope*scope,
|
||||
NetNet*sig, unsigned lwidth,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
|
||||
NetNet* elaborate_net_net_(Design*des, NetScope*scope,
|
||||
NetNet*sig, unsigned lwidth,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
NetNet* elaborate_net_net_idx_up_(Design*des, NetScope*scope,
|
||||
NetNet*sig, unsigned lwidth,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
NetNet* elaborate_net_bitmux_(Design*des, NetScope*scope,
|
||||
NetNet*sig,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
|
||||
private:
|
||||
NetNet* elaborate_lnet_common_(Design*des, NetScope*scope,
|
||||
bool bidirectional_flag) const;
|
||||
@@ -405,8 +362,6 @@ class PEIdent : public PExpr {
|
||||
|
||||
bool eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
|
||||
long&midx, long&lidx) const;
|
||||
NetNet*process_select_(Design*des, NetScope*scope, NetNet*sig) const;
|
||||
|
||||
};
|
||||
|
||||
class PENumber : public PExpr {
|
||||
@@ -420,15 +375,9 @@ class PENumber : public PExpr {
|
||||
virtual void dump(ostream&) const;
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
unsigned min, unsigned lval,
|
||||
bool&unsized_flag) const;
|
||||
ivl_variable_type_t&expr_type,
|
||||
bool&unsized_flag);
|
||||
|
||||
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
|
||||
unsigned lwidth,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
virtual NetEConst*elaborate_expr(Design*des, NetScope*,
|
||||
int expr_width, bool) const;
|
||||
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
@@ -439,7 +388,6 @@ class PENumber : public PExpr {
|
||||
virtual verinum* eval_const(Design*des, NetScope*sc) const;
|
||||
|
||||
virtual bool is_the_same(const PExpr*that) const;
|
||||
virtual bool is_constant(Module*) const;
|
||||
|
||||
private:
|
||||
verinum*const value_;
|
||||
@@ -463,22 +411,14 @@ class PEString : public PExpr {
|
||||
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
unsigned min, unsigned lval,
|
||||
bool&unsized_flag) const;
|
||||
ivl_variable_type_t&expr_type,
|
||||
bool&unsized_flag);
|
||||
|
||||
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
|
||||
unsigned width,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
virtual NetEConst*elaborate_expr(Design*des, NetScope*,
|
||||
int expr_width, bool) const;
|
||||
virtual NetEConst*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
verinum* eval_const(Design*, NetScope*) const;
|
||||
|
||||
virtual bool is_constant(Module*) const;
|
||||
|
||||
private:
|
||||
char*text_;
|
||||
};
|
||||
@@ -491,47 +431,22 @@ class PEUnary : public PExpr {
|
||||
|
||||
virtual void dump(ostream&out) const;
|
||||
|
||||
virtual bool has_aa_term(Design*des, NetScope*scope) const;
|
||||
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
unsigned min, unsigned lval,
|
||||
ivl_variable_type_t&expr_type,
|
||||
bool&unsized_flag);
|
||||
|
||||
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
|
||||
|
||||
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
|
||||
unsigned width,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
|
||||
int expr_width, bool sys_task_arg) const;
|
||||
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
virtual verinum* eval_const(Design*des, NetScope*sc) const;
|
||||
|
||||
virtual bool is_constant(Module*) const;
|
||||
|
||||
private:
|
||||
NetNet* elab_net_uminus_const_logic_(Design*des, NetScope*scope,
|
||||
NetEConst*expr,
|
||||
unsigned width,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
NetNet* elab_net_uminus_const_real_(Design*des, NetScope*scope,
|
||||
NetECReal*expr,
|
||||
unsigned width,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
NetNet* elab_net_unary_real_(Design*des, NetScope*scope,
|
||||
NetExpr*expr,
|
||||
unsigned width,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
NetExpr* elaborate_expr_bits_(NetExpr*operand, int expr_wid) const;
|
||||
|
||||
private:
|
||||
char op_;
|
||||
@@ -544,23 +459,17 @@ class PEBinary : public PExpr {
|
||||
explicit PEBinary(char op, PExpr*l, PExpr*r);
|
||||
~PEBinary();
|
||||
|
||||
virtual bool is_constant(Module*) const;
|
||||
|
||||
virtual void dump(ostream&out) const;
|
||||
|
||||
virtual bool has_aa_term(Design*des, NetScope*scope) const;
|
||||
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
unsigned min, unsigned lval,
|
||||
bool&unsized_flag) const;
|
||||
ivl_variable_type_t&expr_type,
|
||||
bool&unsized_flag);
|
||||
|
||||
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
|
||||
|
||||
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
|
||||
unsigned width,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
|
||||
int expr_width, bool sys_task_arg) const;
|
||||
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
@@ -574,54 +483,13 @@ class PEBinary : public PExpr {
|
||||
NetExpr*elaborate_expr_base_(Design*, NetExpr*lp, NetExpr*rp, int use_wid) const;
|
||||
NetExpr*elaborate_eval_expr_base_(Design*, NetExpr*lp, NetExpr*rp, int use_wid) const;
|
||||
|
||||
static void suppress_operand_sign_if_needed_(NetExpr*lp, NetExpr*rp);
|
||||
NetExpr*elaborate_expr_base_bits_(Design*, NetExpr*lp, NetExpr*rp, int use_wid) const;
|
||||
NetExpr*elaborate_expr_base_div_(Design*, NetExpr*lp, NetExpr*rp, int use_wid) const;
|
||||
NetExpr*elaborate_expr_base_lshift_(Design*, NetExpr*lp, NetExpr*rp, int use_wid) const;
|
||||
NetExpr*elaborate_expr_base_rshift_(Design*, NetExpr*lp, NetExpr*rp, int use_wid) const;
|
||||
NetExpr*elaborate_expr_base_mult_(Design*, NetExpr*lp, NetExpr*rp, int use_wid) const;
|
||||
NetExpr*elaborate_expr_base_add_(Design*, NetExpr*lp, NetExpr*rp, int use_wid) const;
|
||||
|
||||
private:
|
||||
NetNet* elaborate_net_add_(Design*des, NetScope*scope,
|
||||
unsigned lwidth,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay) const;
|
||||
NetNet* elaborate_net_bit_(Design*des, NetScope*scope,
|
||||
unsigned lwidth,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay) const;
|
||||
NetNet* elaborate_net_cmp_(Design*des, NetScope*scope,
|
||||
unsigned lwidth,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay) const;
|
||||
NetNet* elaborate_net_div_(Design*des, NetScope*scope,
|
||||
unsigned lwidth,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay) const;
|
||||
NetNet* elaborate_net_mod_(Design*des, NetScope*scope,
|
||||
unsigned lwidth,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay) const;
|
||||
NetNet* elaborate_net_log_(Design*des, NetScope*scope,
|
||||
unsigned lwidth,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay) const;
|
||||
NetNet* elaborate_net_mul_(Design*des, NetScope*scope,
|
||||
unsigned lwidth,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay) const;
|
||||
NetNet* elaborate_net_pow_(Design*des, NetScope*scope,
|
||||
unsigned lwidth,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay) const;
|
||||
NetNet* elaborate_net_shift_(Design*des, NetScope*scope,
|
||||
unsigned lwidth,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay) const;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -636,10 +504,31 @@ class PEBComp : public PEBinary {
|
||||
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
unsigned min, unsigned lval,
|
||||
bool&flag) const;
|
||||
ivl_variable_type_t&expr_type,
|
||||
bool&flag);
|
||||
|
||||
NetExpr* elaborate_expr(Design*des, NetScope*scope,
|
||||
int expr_width, bool sys_task_arg) const;
|
||||
NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
};
|
||||
|
||||
/*
|
||||
* This derived class is for handling logical expressions: && and ||.
|
||||
*/
|
||||
class PEBLogic : public PEBinary {
|
||||
|
||||
public:
|
||||
explicit PEBLogic(char op, PExpr*l, PExpr*r);
|
||||
~PEBLogic();
|
||||
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
unsigned min, unsigned lval,
|
||||
ivl_variable_type_t&expr_type,
|
||||
bool&flag);
|
||||
|
||||
NetExpr* elaborate_expr(Design*des, NetScope*scope,
|
||||
int expr_width, bool sys_task_arg) const;
|
||||
NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
};
|
||||
|
||||
class PEBShift : public PEBinary {
|
||||
@@ -649,7 +538,11 @@ class PEBShift : public PEBinary {
|
||||
~PEBShift();
|
||||
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
unsigned min, unsigned lval, bool&flag) const;
|
||||
unsigned min, unsigned lval,
|
||||
ivl_variable_type_t&expr_type,
|
||||
bool&flag);
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
|
||||
int expr_width, bool sys_task_arg) const;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -662,23 +555,18 @@ class PETernary : public PExpr {
|
||||
explicit PETernary(PExpr*e, PExpr*t, PExpr*f);
|
||||
~PETernary();
|
||||
|
||||
virtual bool is_constant(Module*) const;
|
||||
|
||||
virtual void dump(ostream&out) const;
|
||||
|
||||
virtual bool has_aa_term(Design*des, NetScope*scope) const;
|
||||
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
unsigned min, unsigned lval,
|
||||
bool&unsized_flag) const;
|
||||
ivl_variable_type_t&expr_type,
|
||||
bool&unsized_flag);
|
||||
|
||||
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
|
||||
|
||||
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
|
||||
unsigned width,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
virtual NetETernary*elaborate_expr(Design*des, NetScope*,
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
|
||||
int expr_width, bool sys_task_arg) const;
|
||||
virtual NetETernary*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
virtual verinum* eval_const(Design*des, NetScope*sc) const;
|
||||
@@ -696,45 +584,42 @@ class PETernary : public PExpr {
|
||||
*/
|
||||
class PECallFunction : public PExpr {
|
||||
public:
|
||||
explicit PECallFunction(const pform_name_t&n, const svector<PExpr *> &parms);
|
||||
explicit PECallFunction(const pform_name_t&n, const vector<PExpr *> &parms);
|
||||
// Call of system function (name is not hierarchical)
|
||||
explicit PECallFunction(perm_string n, const svector<PExpr *> &parms);
|
||||
explicit PECallFunction(perm_string n, const vector<PExpr *> &parms);
|
||||
explicit PECallFunction(perm_string n);
|
||||
|
||||
// svector versions. Should be removed!
|
||||
explicit PECallFunction(const pform_name_t&n, const svector<PExpr *> &parms);
|
||||
explicit PECallFunction(perm_string n, const svector<PExpr *> &parms);
|
||||
|
||||
~PECallFunction();
|
||||
|
||||
virtual void dump(ostream &) const;
|
||||
|
||||
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
|
||||
unsigned width,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
virtual bool has_aa_term(Design*des, NetScope*scope) const;
|
||||
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
|
||||
int expr_wid, bool sys_task_arg) const;
|
||||
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
unsigned min, unsigned lval,
|
||||
bool&unsized_flag) const;
|
||||
ivl_variable_type_t&expr_type,
|
||||
bool&unsized_flag);
|
||||
|
||||
private:
|
||||
pform_name_t path_;
|
||||
svector<PExpr *> parms_;
|
||||
vector<PExpr *> parms_;
|
||||
|
||||
bool check_call_matches_definition_(Design*des, NetScope*dscope) const;
|
||||
|
||||
NetExpr* elaborate_sfunc_(Design*des, NetScope*scope, int expr_wid) const;
|
||||
NetNet* elaborate_net_sfunc_(Design*des, NetScope*scope,
|
||||
unsigned width,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
NetExpr* elaborate_access_func_(Design*des, NetScope*scope, int expr_wid) const;
|
||||
unsigned test_width_sfunc_(Design*des, NetScope*scope,
|
||||
unsigned min, unsigned lval,
|
||||
bool&unsized_flag) const;
|
||||
ivl_variable_type_t&expr_type,
|
||||
bool&unsized_flag);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
+2
-1
@@ -21,9 +21,10 @@
|
||||
|
||||
#include "PTask.h"
|
||||
|
||||
PFunction::PFunction(perm_string name, PScope*parent)
|
||||
PFunction::PFunction(perm_string name, PScope*parent, bool is_auto__)
|
||||
: PScope(name, parent), ports_(0), statement_(0)
|
||||
{
|
||||
is_auto_ = is_auto__;
|
||||
return_type_.type = PTF_NONE;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __PGate_H
|
||||
#define __PGate_H
|
||||
/*
|
||||
* Copyright (c) 1998-2004 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2008 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,9 +18,6 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PGate.h,v 1.32 2006/04/10 00:37:42 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "svector.h"
|
||||
# include "StringHeap.h"
|
||||
@@ -83,7 +80,7 @@ class PGate : public LineInfo {
|
||||
bool as_net_flag =false) const;
|
||||
|
||||
unsigned pin_count() const { return pins_? pins_->count() : 0; }
|
||||
const PExpr*pin(unsigned idx) const { return (*pins_)[idx]; }
|
||||
PExpr*pin(unsigned idx) const { return (*pins_)[idx]; }
|
||||
|
||||
strength_t strength0() const;
|
||||
strength_t strength1() const;
|
||||
@@ -170,8 +167,16 @@ class PGBuiltin : public PGate {
|
||||
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
|
||||
|
||||
private:
|
||||
Type type_;
|
||||
unsigned calculate_array_count_(Design*, NetScope*,
|
||||
long&high, long&low) const;
|
||||
|
||||
unsigned calculate_output_count_(void) const;
|
||||
|
||||
NetNode* create_gate_for_output_(Design*, NetScope*,
|
||||
perm_string gate_name,
|
||||
unsigned instance_width) const;
|
||||
|
||||
Type type_;
|
||||
PExpr*msb_;
|
||||
PExpr*lsb_;
|
||||
};
|
||||
@@ -232,15 +237,17 @@ class PGModule : public PGate {
|
||||
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;
|
||||
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;
|
||||
bool elaborate_sig_udp_(Design*des, NetScope*scope, PUdp*udp) const;
|
||||
|
||||
NetNet*resize_net_to_port_(Design*des, NetScope*scope,
|
||||
NetNet*sig, unsigned port_wid,
|
||||
NetNet::PortType dir) const;
|
||||
NetNet::PortType dir, bool as_signed) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
+1
-14
@@ -27,27 +27,14 @@ PGenerate::PGenerate(unsigned id)
|
||||
: id_number(id)
|
||||
{
|
||||
parent = 0;
|
||||
lexical_scope = 0;
|
||||
}
|
||||
|
||||
PGenerate::~PGenerate()
|
||||
{
|
||||
}
|
||||
|
||||
PWire* PGenerate::get_wire(perm_string name) const
|
||||
{
|
||||
map<perm_string,PWire*>::const_iterator obj = wires.find(name);
|
||||
if (obj == wires.end())
|
||||
return 0;
|
||||
else
|
||||
return (*obj).second;
|
||||
}
|
||||
|
||||
void PGenerate::add_gate(PGate*gate)
|
||||
{
|
||||
gates.push_back(gate);
|
||||
}
|
||||
|
||||
void PGenerate::add_behavior(PProcess*proc)
|
||||
{
|
||||
behaviors.push_back(proc);
|
||||
}
|
||||
|
||||
+17
-13
@@ -1,7 +1,7 @@
|
||||
#ifndef __PGenerate_H
|
||||
#define __PGenerate_H
|
||||
/*
|
||||
* Copyright (c) 2006 Stephen Williams ([email protected])
|
||||
* Copyright (c) 2006-2008 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,13 +18,11 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PGenerate.h,v 1.4 2007/06/02 03:42:12 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "LineInfo.h"
|
||||
# include "StringHeap.h"
|
||||
# include "HName.h"
|
||||
# include "PScope.h"
|
||||
# include <list>
|
||||
# include <map>
|
||||
# include "pform_types.h"
|
||||
@@ -32,7 +30,9 @@
|
||||
class Design;
|
||||
class NetScope;
|
||||
class PExpr;
|
||||
class PFunction;
|
||||
class PProcess;
|
||||
class PTask;
|
||||
class PGate;
|
||||
class PWire;
|
||||
|
||||
@@ -49,10 +49,10 @@ class PWire;
|
||||
* The parent points to the GS_CASE that contains this item.
|
||||
* the loop_test is compared with the parent->loop_test expression.
|
||||
*/
|
||||
class PGenerate : public LineInfo {
|
||||
class PGenerate : public LineInfo, public LexicalScope {
|
||||
|
||||
public:
|
||||
PGenerate(unsigned id_number);
|
||||
explicit PGenerate(unsigned id_number);
|
||||
~PGenerate();
|
||||
|
||||
// Generate schemes have an ID number, for when the scope is
|
||||
@@ -60,8 +60,12 @@ class PGenerate : public LineInfo {
|
||||
const unsigned id_number;
|
||||
perm_string scope_name;
|
||||
|
||||
// This is used during parsing to stack lexical scopes within
|
||||
// this generate scheme.
|
||||
PScope*lexical_scope;
|
||||
|
||||
enum scheme_t {GS_NONE, GS_LOOP, GS_CONDIT, GS_ELSE,
|
||||
GS_CASE, GS_CASE_ITEM};
|
||||
GS_CASE, GS_CASE_ITEM, GS_NBLOCK};
|
||||
scheme_t scheme_type;
|
||||
|
||||
// generate loops have an index variable and three
|
||||
@@ -71,16 +75,15 @@ class PGenerate : public LineInfo {
|
||||
PExpr*loop_test;
|
||||
PExpr*loop_step;
|
||||
|
||||
map<perm_string,PWire*>wires;
|
||||
PWire* get_wire(perm_string name) const;
|
||||
|
||||
list<PGate*> gates;
|
||||
void add_gate(PGate*);
|
||||
|
||||
list<PProcess*> behaviors;
|
||||
void add_behavior(PProcess*behave);
|
||||
// Tasks instantiated within this scheme.
|
||||
map<perm_string,PTask*> tasks;
|
||||
map<perm_string,PFunction*>funcs;
|
||||
|
||||
list<PGenerate*> generates;
|
||||
// Generate schemes can contain further generate schemes.
|
||||
list<PGenerate*> generate_schemes;
|
||||
PGenerate*parent;
|
||||
|
||||
// This method is called by the elaboration of a module to
|
||||
@@ -99,6 +102,7 @@ class PGenerate : public LineInfo {
|
||||
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);
|
||||
|
||||
// Elaborate_scope within a generated scope.
|
||||
void elaborate_subscope_(Design*des, NetScope*scope);
|
||||
|
||||
@@ -19,8 +19,13 @@
|
||||
|
||||
# include "PScope.h"
|
||||
|
||||
PScope::PScope(perm_string n, PScope*p)
|
||||
: name_(n), parent_(p)
|
||||
PScope::PScope(perm_string n, PScope*parent)
|
||||
: name_(n), parent_(parent)
|
||||
{
|
||||
}
|
||||
|
||||
PScope::PScope(perm_string n)
|
||||
: name_(n), parent_(0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -28,7 +33,7 @@ PScope::~PScope()
|
||||
{
|
||||
}
|
||||
|
||||
PWire* PScope::wires_find(perm_string name)
|
||||
PWire* LexicalScope::wires_find(perm_string name)
|
||||
{
|
||||
map<perm_string,PWire*>::const_iterator cur = wires.find(name);
|
||||
if (cur == wires.end())
|
||||
|
||||
@@ -19,11 +19,15 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
# include "LineInfo.h"
|
||||
# include "StringHeap.h"
|
||||
# include "pform_types.h"
|
||||
# include "ivl_target.h"
|
||||
# include <map>
|
||||
|
||||
class PEvent;
|
||||
class PExpr;
|
||||
class AProcess;
|
||||
class PProcess;
|
||||
class PWire;
|
||||
|
||||
@@ -35,10 +39,74 @@ class NetScope;
|
||||
* represents lexical scope. For example, a module, a function/task, a
|
||||
* named block is derived from a PScope.
|
||||
*
|
||||
* NOTE: This is note the same concept as the "scope" of an elaborated
|
||||
* NOTE: This is not the same concept as the "scope" of an elaborated
|
||||
* hierarchy. That is represented by NetScope objects after elaboration.
|
||||
*/
|
||||
class PScope {
|
||||
|
||||
class LexicalScope {
|
||||
|
||||
public:
|
||||
explicit LexicalScope() { }
|
||||
// A virtual destructor is so that dynamic_cast can work.
|
||||
virtual ~LexicalScope() { }
|
||||
|
||||
struct range_t {
|
||||
// True if this is an exclude
|
||||
bool exclude_flag;
|
||||
// lower bound
|
||||
// If low_open_flag is false and low_expr=0, then use -inf
|
||||
bool low_open_flag;
|
||||
PExpr*low_expr;
|
||||
// upper bound
|
||||
// If high_open_flag is false and high_expr=0, then use +inf
|
||||
bool high_open_flag;
|
||||
PExpr*high_expr;
|
||||
// Next range description in list
|
||||
struct range_t*next;
|
||||
};
|
||||
|
||||
/* The scope has parameters that are evaluated when the scope
|
||||
is elaborated. During parsing, I put the parameters into
|
||||
this map. */
|
||||
struct param_expr_t : public LineInfo {
|
||||
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;
|
||||
// Value expression
|
||||
PExpr*expr;
|
||||
// If there are range constraints, list them here
|
||||
range_t*range;
|
||||
};
|
||||
map<perm_string,param_expr_t>parameters;
|
||||
map<perm_string,param_expr_t>localparams;
|
||||
|
||||
// Named events in the scope.
|
||||
map<perm_string,PEvent*>events;
|
||||
|
||||
// Nets and variables (wires) in the scope
|
||||
map<perm_string,PWire*>wires;
|
||||
PWire* wires_find(perm_string name);
|
||||
|
||||
// Behaviors (processes) in this scope
|
||||
list<PProcess*> behaviors;
|
||||
list<AProcess*> analog_behaviors;
|
||||
|
||||
protected:
|
||||
void dump_parameters_(ostream&out, unsigned indent) const;
|
||||
|
||||
void dump_localparams_(ostream&out, unsigned indent) const;
|
||||
|
||||
void dump_events_(ostream&out, unsigned indent) const;
|
||||
|
||||
void dump_wires_(ostream&out, unsigned indent) const;
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
class PScope : public LexicalScope {
|
||||
|
||||
public:
|
||||
// When created, a scope has a name and a parent. The name is
|
||||
@@ -50,24 +118,13 @@ class PScope {
|
||||
// modules. Scopes for tasks and functions point to their
|
||||
// containing module.
|
||||
PScope(perm_string name, PScope*parent);
|
||||
PScope(perm_string name);
|
||||
virtual ~PScope();
|
||||
|
||||
perm_string pscope_name() const { return name_; }
|
||||
PScope* pscope_parent() { return parent_; }
|
||||
|
||||
// Nets an variables (wires) in the scope
|
||||
map<perm_string,PWire*>wires;
|
||||
PWire* wires_find(perm_string name);
|
||||
|
||||
// Named events in the scope.
|
||||
map<perm_string,PEvent*>events;
|
||||
|
||||
// Behaviors (processes) in this scope
|
||||
list<PProcess*> behaviors;
|
||||
|
||||
protected:
|
||||
void dump_wires_(ostream&out, unsigned indent) const;
|
||||
|
||||
bool elaborate_sig_wires_(Design*des, NetScope*scope) const;
|
||||
|
||||
bool elaborate_behaviors_(Design*des, NetScope*scope) const;
|
||||
|
||||
@@ -21,9 +21,10 @@
|
||||
|
||||
# include "PTask.h"
|
||||
|
||||
PTask::PTask(perm_string name, PScope*parent)
|
||||
PTask::PTask(perm_string name, PScope*parent, bool is_auto__)
|
||||
: PScope(name, parent), ports_(0), statement_(0)
|
||||
{
|
||||
is_auto_ = is_auto__;
|
||||
}
|
||||
|
||||
PTask::~PTask()
|
||||
@@ -41,31 +42,3 @@ void PTask::set_statement(Statement*s)
|
||||
assert(statement_ == 0);
|
||||
statement_ = s;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* $Log: PTask.cc,v $
|
||||
* Revision 1.7 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.6 2001/07/25 03:10:48 steve
|
||||
* Create a config.h.in file to hold all the config
|
||||
* junk, and support gcc 3.0. (Stephan Boettcher)
|
||||
*
|
||||
* Revision 1.5 2001/04/19 03:04:47 steve
|
||||
* Spurious assert of empty statemnt.
|
||||
*
|
||||
* Revision 1.4 2001/01/13 22:20:08 steve
|
||||
* Parse parameters within nested scopes.
|
||||
*
|
||||
* Revision 1.3 2000/02/23 02:56:53 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.2 1999/07/24 02:11:19 steve
|
||||
* Elaborate task input ports.
|
||||
*
|
||||
* Revision 1.1 1999/07/03 02:12:51 steve
|
||||
* Elaborate user defined tasks.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ struct PTaskFuncArg {
|
||||
class PTask : public PScope, public LineInfo {
|
||||
|
||||
public:
|
||||
explicit PTask(perm_string name, PScope*parent);
|
||||
explicit PTask(perm_string name, PScope*parent, bool is_auto);
|
||||
~PTask();
|
||||
|
||||
void set_ports(svector<PWire *>*p);
|
||||
@@ -69,11 +69,14 @@ class PTask : public PScope, public LineInfo {
|
||||
// Elaborate the statement to finish off the task definition.
|
||||
void elaborate(Design*des, NetScope*scope) const;
|
||||
|
||||
bool is_auto() const { return is_auto_; };
|
||||
|
||||
void dump(ostream&, unsigned) const;
|
||||
|
||||
private:
|
||||
svector<PWire*>*ports_;
|
||||
Statement*statement_;
|
||||
bool is_auto_;
|
||||
|
||||
private: // Not implemented
|
||||
PTask(const PTask&);
|
||||
@@ -90,7 +93,7 @@ class PTask : public PScope, public LineInfo {
|
||||
class PFunction : public PScope, public LineInfo {
|
||||
|
||||
public:
|
||||
explicit PFunction(perm_string name, PScope*parent);
|
||||
explicit PFunction(perm_string name, PScope*parent, bool is_auto);
|
||||
~PFunction();
|
||||
|
||||
void set_ports(svector<PWire *>*p);
|
||||
@@ -105,12 +108,15 @@ class PFunction : public PScope, public LineInfo {
|
||||
/* Elaborate the behavioral statement. */
|
||||
void elaborate(Design *des, NetScope*) const;
|
||||
|
||||
bool is_auto() const { return is_auto_; };
|
||||
|
||||
void dump(ostream&, unsigned) const;
|
||||
|
||||
private:
|
||||
PTaskFuncArg return_type_;
|
||||
svector<PWire *> *ports_;
|
||||
Statement *statement_;
|
||||
bool is_auto_;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -198,13 +198,13 @@ void PWire::set_memory_idx(PExpr*ldx, PExpr*rdx)
|
||||
}
|
||||
}
|
||||
|
||||
void PWire::set_discipline(discipline_t*d)
|
||||
void PWire::set_discipline(ivl_discipline_t d)
|
||||
{
|
||||
assert(discipline_ == 0);
|
||||
discipline_ = d;
|
||||
}
|
||||
|
||||
discipline_t* PWire::get_discipline(void) const
|
||||
ivl_discipline_t PWire::get_discipline(void) const
|
||||
{
|
||||
return discipline_;
|
||||
}
|
||||
|
||||
@@ -18,9 +18,6 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PWire.h,v 1.21 2007/05/24 04:07:11 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
# include "LineInfo.h"
|
||||
@@ -36,7 +33,6 @@ class ostream;
|
||||
|
||||
class PExpr;
|
||||
class Design;
|
||||
class discipline_t;
|
||||
|
||||
/*
|
||||
* The different type of PWire::set_range() calls.
|
||||
@@ -82,8 +78,8 @@ class PWire : public LineInfo {
|
||||
|
||||
void set_memory_idx(PExpr*ldx, PExpr*rdx);
|
||||
|
||||
void set_discipline(discipline_t*);
|
||||
discipline_t* get_discipline(void) const;
|
||||
void set_discipline(ivl_discipline_t);
|
||||
ivl_discipline_t get_discipline(void) const;
|
||||
|
||||
map<perm_string,PExpr*> attributes;
|
||||
|
||||
@@ -115,7 +111,7 @@ class PWire : public LineInfo {
|
||||
PExpr*lidx_;
|
||||
PExpr*ridx_;
|
||||
|
||||
discipline_t*discipline_;
|
||||
ivl_discipline_t discipline_;
|
||||
|
||||
private: // not implemented
|
||||
PWire(const PWire&);
|
||||
|
||||
+11
-29
@@ -12,10 +12,7 @@ home page at <http://www.icarus.com/eda/verilog>.
|
||||
|
||||
Icarus Verilog is not aimed at being a simulator in the traditional
|
||||
sense, but a compiler that generates code employed by back-end
|
||||
tools. These back-end tools currently include a simulator engine
|
||||
called VVP, an XNF (Xilinx Netlist Format) generator and an EDIF FPGA
|
||||
netlist generator. In the future, backends are expected for EDIF/LPM,
|
||||
structural Verilog, VHDL, etc.
|
||||
tools.
|
||||
|
||||
For instructions on how to run Icarus Verilog,
|
||||
see the ``iverilog'' man page.
|
||||
@@ -88,10 +85,6 @@ 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 behavior:
|
||||
|
||||
--without-ipal
|
||||
This turns off support for Icarus PAL, whether ipal
|
||||
libraries are installed or not.
|
||||
|
||||
--prefix=<root>
|
||||
The default is /usr/local, which causes the tool suite to
|
||||
be compiled for install in /usr/local/bin,
|
||||
@@ -102,27 +95,16 @@ configure script that modify its behavior:
|
||||
common to use --prefix=/opt. You can configure for a non-root
|
||||
install with --prefix=$HOME.
|
||||
|
||||
--enable-vvp32 (experimental)
|
||||
If compiling on AMD64 systems, this enables the
|
||||
compilation of 32bit compatible vvp (vvp32) and the vpi
|
||||
modules that match.
|
||||
|
||||
2.2.1 Special AMD64 Instructions
|
||||
|
||||
(The Icarus Verilog RPM for x86_64 is build using these instructions.)
|
||||
|
||||
If you are building for Linux/AMD64 (a.k.a x86_64) then to get the
|
||||
most out of your install, first make sure you have both 64bit and
|
||||
32bit development libraries installed. Then configure with this
|
||||
somewhat more complicated command:
|
||||
|
||||
./configure libdir64='$(prefix)/lib64' vpidir1=vpi64 vpidir2=. --enable-vvp32
|
||||
|
||||
This reflects the convention on AMD64 systems that 64bit libraries go
|
||||
into lib64 directories. The "--enable-vvp32" also turns on 32bit
|
||||
compatibility files. A 32bit version of vvp (vvp32) will be created,
|
||||
as well as 32bit versions of the development libraries and bundled VPI
|
||||
libraries.
|
||||
--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.
|
||||
|
||||
2.3 (Optional) Testing
|
||||
|
||||
|
||||
+37
-56
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998-1999 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2008 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
|
||||
@@ -16,9 +16,6 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: Statement.cc,v 1.30 2007/05/24 04:07:11 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
@@ -29,20 +26,20 @@ Statement::~Statement()
|
||||
{
|
||||
}
|
||||
|
||||
PAssign_::PAssign_(PExpr*lval, PExpr*ex)
|
||||
: event_(0), lval_(lval), rval_(ex)
|
||||
PAssign_::PAssign_(PExpr*lval__, PExpr*ex, bool is_constant)
|
||||
: event_(0), count_(0), lval_(lval__), rval_(ex), is_constant_(is_constant)
|
||||
{
|
||||
delay_ = 0;
|
||||
}
|
||||
|
||||
PAssign_::PAssign_(PExpr*lval, PExpr*de, PExpr*ex)
|
||||
: event_(0), lval_(lval), rval_(ex)
|
||||
PAssign_::PAssign_(PExpr*lval__, PExpr*de, PExpr*ex)
|
||||
: event_(0), count_(0), lval_(lval__), rval_(ex), is_constant_(false)
|
||||
{
|
||||
delay_ = de;
|
||||
}
|
||||
|
||||
PAssign_::PAssign_(PExpr*lval, PEventStatement*ev, PExpr*ex)
|
||||
: event_(ev), lval_(lval), rval_(ex)
|
||||
PAssign_::PAssign_(PExpr*lval__, PExpr*cnt, PEventStatement*ev, PExpr*ex)
|
||||
: event_(ev), count_(cnt), lval_(lval__), rval_(ex), is_constant_(false)
|
||||
{
|
||||
delay_ = 0;
|
||||
}
|
||||
@@ -53,18 +50,23 @@ PAssign_::~PAssign_()
|
||||
delete rval_;
|
||||
}
|
||||
|
||||
PAssign::PAssign(PExpr*lval, PExpr*ex)
|
||||
: PAssign_(lval, ex)
|
||||
PAssign::PAssign(PExpr*lval__, PExpr*ex)
|
||||
: PAssign_(lval__, ex, false)
|
||||
{
|
||||
}
|
||||
|
||||
PAssign::PAssign(PExpr*lval, PExpr*d, PExpr*ex)
|
||||
: PAssign_(lval, d, ex)
|
||||
PAssign::PAssign(PExpr*lval__, PExpr*d, PExpr*ex)
|
||||
: PAssign_(lval__, d, ex)
|
||||
{
|
||||
}
|
||||
|
||||
PAssign::PAssign(PExpr*lval, PEventStatement*d, PExpr*ex)
|
||||
: PAssign_(lval, d, ex)
|
||||
PAssign::PAssign(PExpr*lval__, PExpr*cnt, PEventStatement*d, PExpr*ex)
|
||||
: PAssign_(lval__, cnt, d, ex)
|
||||
{
|
||||
}
|
||||
|
||||
PAssign::PAssign(PExpr*lval__, PExpr*ex, bool is_constant)
|
||||
: PAssign_(lval__, ex, is_constant)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -72,13 +74,18 @@ PAssign::~PAssign()
|
||||
{
|
||||
}
|
||||
|
||||
PAssignNB::PAssignNB(PExpr*lval, PExpr*ex)
|
||||
: PAssign_(lval, ex)
|
||||
PAssignNB::PAssignNB(PExpr*lval__, PExpr*ex)
|
||||
: PAssign_(lval__, ex, false)
|
||||
{
|
||||
}
|
||||
|
||||
PAssignNB::PAssignNB(PExpr*lval, PExpr*d, PExpr*ex)
|
||||
: PAssign_(lval, d, ex)
|
||||
PAssignNB::PAssignNB(PExpr*lval__, PExpr*d, PExpr*ex)
|
||||
: PAssign_(lval__, d, ex)
|
||||
{
|
||||
}
|
||||
|
||||
PAssignNB::PAssignNB(PExpr*lval__, PExpr*cnt, PEventStatement*d, PExpr*ex)
|
||||
: PAssign_(lval__, cnt, d, ex)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -92,7 +99,7 @@ PBlock::PBlock(perm_string n, PScope*parent, BL_TYPE t)
|
||||
}
|
||||
|
||||
PBlock::PBlock(BL_TYPE t)
|
||||
: PScope(perm_string(),0), bl_type_(t)
|
||||
: PScope(perm_string()), bl_type_(t)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -221,6 +228,15 @@ void PEventStatement::set_statement(Statement*st)
|
||||
statement_ = st;
|
||||
}
|
||||
|
||||
bool PEventStatement::has_aa_term(Design*des, NetScope*scope)
|
||||
{
|
||||
bool flag = false;
|
||||
for (unsigned idx = 0 ; idx < expr_.count() ; idx += 1) {
|
||||
flag = expr_[idx]->has_aa_term(des, scope) || flag;
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
PForce::PForce(PExpr*l, PExpr*r)
|
||||
: lval_(l), expr_(r)
|
||||
{
|
||||
@@ -298,38 +314,3 @@ PWhile::~PWhile()
|
||||
delete cond_;
|
||||
delete statement_;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: Statement.cc,v $
|
||||
* Revision 1.30 2007/05/24 04:07:11 steve
|
||||
* Rework the heirarchical identifier parse syntax and pform
|
||||
* to handle more general combinations of heirarch and bit selects.
|
||||
*
|
||||
* Revision 1.29 2004/02/18 17:11:54 steve
|
||||
* Use perm_strings for named langiage items.
|
||||
*
|
||||
* Revision 1.28 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.27 2002/04/21 22:31:02 steve
|
||||
* Redo handling of assignment internal delays.
|
||||
* Leave it possible for them to be calculated
|
||||
* at run time.
|
||||
*
|
||||
* Revision 1.26 2002/04/21 04:59:07 steve
|
||||
* Add support for conbinational events by finding
|
||||
* the inputs to expressions and some statements.
|
||||
* Get case and assignment statements working.
|
||||
*
|
||||
* Revision 1.25 2001/12/03 04:47:14 steve
|
||||
* Parser and pform use hierarchical names as hname_t
|
||||
* objects instead of encoded strings.
|
||||
*
|
||||
* Revision 1.24 2001/11/22 06:20:59 steve
|
||||
* Use NetScope instead of string for scope path.
|
||||
*
|
||||
* Revision 1.23 2001/07/25 03:10:48 steve
|
||||
* Create a config.h.in file to hold all the config
|
||||
* junk, and support gcc 3.0. (Stephan Boettcher)
|
||||
*/
|
||||
|
||||
|
||||
+23
-9
@@ -20,6 +20,7 @@
|
||||
*/
|
||||
|
||||
# include <string>
|
||||
# include "ivl_target.h"
|
||||
# include "svector.h"
|
||||
# include "StringHeap.h"
|
||||
# include "PDelays.h"
|
||||
@@ -46,16 +47,14 @@ class NetScope;
|
||||
class PProcess : public LineInfo {
|
||||
|
||||
public:
|
||||
enum Type { PR_INITIAL, PR_ALWAYS };
|
||||
|
||||
PProcess(Type t, Statement*st)
|
||||
PProcess(ivl_process_type_t t, Statement*st)
|
||||
: type_(t), statement_(st) { }
|
||||
|
||||
virtual ~PProcess();
|
||||
|
||||
bool elaborate(Design*des, NetScope*scope) const;
|
||||
|
||||
Type type() const { return type_; }
|
||||
ivl_process_type_t type() const { return type_; }
|
||||
Statement*statement() { return statement_; }
|
||||
|
||||
map<perm_string,PExpr*> attributes;
|
||||
@@ -63,7 +62,7 @@ class PProcess : public LineInfo {
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
Type type_;
|
||||
ivl_process_type_t type_;
|
||||
Statement*statement_;
|
||||
};
|
||||
|
||||
@@ -82,6 +81,8 @@ class Statement : public LineInfo {
|
||||
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;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -91,23 +92,27 @@ class Statement : public LineInfo {
|
||||
*/
|
||||
class PAssign_ : public Statement {
|
||||
public:
|
||||
explicit PAssign_(PExpr*lval, PExpr*ex);
|
||||
explicit PAssign_(PExpr*lval, PExpr*ex, bool is_constant);
|
||||
explicit PAssign_(PExpr*lval, PExpr*de, PExpr*ex);
|
||||
explicit PAssign_(PExpr*lval, PEventStatement*de, PExpr*ex);
|
||||
explicit PAssign_(PExpr*lval, PExpr*cnt, PEventStatement*de, PExpr*ex);
|
||||
virtual ~PAssign_() =0;
|
||||
|
||||
const PExpr* lval() const { return lval_; }
|
||||
const PExpr* rval() const { return rval_; }
|
||||
PExpr* rval() const { return rval_; }
|
||||
|
||||
protected:
|
||||
NetAssign_* elaborate_lval(Design*, NetScope*scope) const;
|
||||
NetExpr* elaborate_rval_(Design*, NetScope*, unsigned lv_width,
|
||||
ivl_variable_type_t type) const;
|
||||
|
||||
PExpr* delay_;
|
||||
PEventStatement*event_;
|
||||
PExpr* count_;
|
||||
|
||||
private:
|
||||
PExpr* lval_;
|
||||
PExpr* rval_;
|
||||
bool is_constant_;
|
||||
};
|
||||
|
||||
class PAssign : public PAssign_ {
|
||||
@@ -115,7 +120,8 @@ class PAssign : public PAssign_ {
|
||||
public:
|
||||
explicit PAssign(PExpr*lval, PExpr*ex);
|
||||
explicit PAssign(PExpr*lval, PExpr*de, PExpr*ex);
|
||||
explicit PAssign(PExpr*lval, PEventStatement*de, PExpr*ex);
|
||||
explicit PAssign(PExpr*lval, PExpr*cnt, PEventStatement*de, PExpr*ex);
|
||||
explicit PAssign(PExpr*lval, PExpr*ex, bool is_constant);
|
||||
~PAssign();
|
||||
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
@@ -129,6 +135,7 @@ class PAssignNB : public PAssign_ {
|
||||
public:
|
||||
explicit PAssignNB(PExpr*lval, PExpr*ex);
|
||||
explicit PAssignNB(PExpr*lval, PExpr*de, PExpr*ex);
|
||||
explicit PAssignNB(PExpr*lval, PExpr*cnt, PEventStatement*de, PExpr*ex);
|
||||
~PAssignNB();
|
||||
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
@@ -333,10 +340,15 @@ class PEventStatement : public Statement {
|
||||
void set_statement(Statement*st);
|
||||
|
||||
virtual void dump(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 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;
|
||||
|
||||
bool has_aa_term(Design*des, NetScope*scope);
|
||||
|
||||
// This method is used to elaborate, but attach a previously
|
||||
// elaborated statement to the event.
|
||||
NetProc* elaborate_st(Design*des, NetScope*scope, NetProc*st) const;
|
||||
@@ -348,6 +360,8 @@ class PEventStatement : public Statement {
|
||||
Statement*statement_;
|
||||
};
|
||||
|
||||
ostream& operator << (ostream&o, const PEventStatement&obj);
|
||||
|
||||
class PForce : public Statement {
|
||||
|
||||
public:
|
||||
|
||||
Vendored
+17
@@ -24,6 +24,23 @@ fi
|
||||
AC_SUBST(ident_support)
|
||||
])# AC_CPP_IDENT
|
||||
|
||||
# AX_ENABLE_SUFFIX
|
||||
# ----------------
|
||||
# Create the configure option --enable-suffix[=suffix] to generate suffix
|
||||
# strings for the installed commands. This allows for shared installs of
|
||||
# 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],[Set the installation command suffix],[true],[enable_suffix=no])
|
||||
if test X$enable_suffix = Xyes; then
|
||||
install_suffix='-0.9'
|
||||
elif test X$enable_suffix = Xno; then
|
||||
install_suffix=''
|
||||
else
|
||||
install_suffix="$enable_suffix"
|
||||
fi
|
||||
AC_SUBST(install_suffix)
|
||||
])# AX_ENABLE_SUFFIX
|
||||
|
||||
# _AX_C_UNDERSCORES_MATCH_IFELSE(PATTERN, ACTION-IF-MATCH, ACTION-IF-NOMATCH)
|
||||
# ------------------------------
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002 Stephen Williams ([email protected])
|
||||
* Copyright (c) 2002-2008 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
|
||||
@@ -16,9 +16,6 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: async.cc,v 1.7 2004/01/18 23:26:54 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
@@ -87,34 +84,8 @@ bool NetProc::is_asynchronous()
|
||||
|
||||
bool NetProcTop::is_asynchronous()
|
||||
{
|
||||
if (type_ == NetProcTop::KINITIAL)
|
||||
if (type_ == IVL_PR_INITIAL)
|
||||
return false;
|
||||
|
||||
return statement_->is_asynchronous();
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: async.cc,v $
|
||||
* Revision 1.7 2004/01/18 23:26:54 steve
|
||||
* The is_combinational function really need not recurse.
|
||||
*
|
||||
* Revision 1.6 2003/12/20 00:33:39 steve
|
||||
* More thorough check that NetEvWait is asynchronous.
|
||||
*
|
||||
* Revision 1.5 2003/09/04 20:28:05 steve
|
||||
* Support time0 resolution of combinational threads.
|
||||
*
|
||||
* Revision 1.4 2002/08/18 22:07:16 steve
|
||||
* Detect temporaries in sequential block synthesis.
|
||||
*
|
||||
* Revision 1.3 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.2 2002/07/04 00:24:16 steve
|
||||
* initial statements are not asynchronous.
|
||||
*
|
||||
* Revision 1.1 2002/06/30 02:21:31 steve
|
||||
* Add structure for asynchronous logic synthesis.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@
|
||||
echo "Autoconf in root..."
|
||||
autoconf -f
|
||||
|
||||
for dir in vpip vpi vvp tgt-vvp tgt-fpga tgt-stub libveriuser cadpli
|
||||
for dir in vpi vvp tgt-vvp tgt-fpga tgt-stub tgt-vhdl libveriuser cadpli
|
||||
do
|
||||
echo "Autoconf in $dir..."
|
||||
( cd ./$dir ; autoconf -f --include=.. )
|
||||
|
||||
+6
-4
@@ -20,6 +20,8 @@ SHELL = /bin/sh
|
||||
|
||||
VERSION = 0.9.devel
|
||||
|
||||
suffix = @install_suffix@
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
srcdir = @srcdir@
|
||||
@@ -30,7 +32,7 @@ bindir = @bindir@
|
||||
libdir = @libdir@
|
||||
includedir = $(prefix)/include
|
||||
|
||||
vpidir = @libdir@/ivl
|
||||
vpidir = @libdir@/ivl$(suffix)
|
||||
|
||||
CC = @CC@
|
||||
INSTALL = @INSTALL@
|
||||
@@ -76,13 +78,13 @@ distclean: clean
|
||||
install: all installdirs $(vpidir)/cadpli.vpl $(INSTALL32)
|
||||
|
||||
$(vpidir)/cadpli.vpl: ./cadpli.vpl
|
||||
$(INSTALL_PROGRAM) ./cadpli.vpl $(vpidir)/cadpli.vpl
|
||||
$(INSTALL_PROGRAM) ./cadpli.vpl $(DESTDIR)$(vpidir)/cadpli.vpl
|
||||
|
||||
installdirs: ../mkinstalldirs
|
||||
$(srcdir)/../mkinstalldirs $(vpidir)
|
||||
$(srcdir)/../mkinstalldirs $(DESTDIR)$(vpidir)
|
||||
|
||||
uninstall: $(UNINSTALL32)
|
||||
rm -f $(vpidir)/cadpli.vpl
|
||||
rm -f $(DESTDIR)$(vpidir)/cadpli.vpl
|
||||
|
||||
uninstall32:
|
||||
|
||||
|
||||
@@ -10,6 +10,8 @@ AC_SUBST(EXEEXT)
|
||||
# Combined check for Microsoft-related bogosities; sets WIN32 if found
|
||||
AX_WIN32
|
||||
|
||||
AX_ENABLE_SUFFIX
|
||||
|
||||
AC_PROG_INSTALL
|
||||
|
||||
AC_CHECK_HEADERS(malloc.h)
|
||||
|
||||
+11
-11
@@ -35,16 +35,16 @@ typedef shl_t ivl_dll_t;
|
||||
#endif
|
||||
|
||||
#if defined(__MINGW32__)
|
||||
static inline ivl_dll_t ivl_dlopen(const char *name)
|
||||
static __inline__ ivl_dll_t ivl_dlopen(const char *name)
|
||||
{ return (void *)LoadLibrary(name); }
|
||||
|
||||
static inline void *ivl_dlsym(ivl_dll_t dll, const char *nm)
|
||||
static __inline__ void *ivl_dlsym(ivl_dll_t dll, const char *nm)
|
||||
{ return (void *)GetProcAddress((HINSTANCE)dll,nm);}
|
||||
|
||||
static inline void ivl_dlclose(ivl_dll_t dll)
|
||||
static __inline__ void ivl_dlclose(ivl_dll_t dll)
|
||||
{ (void)FreeLibrary((HINSTANCE)dll);}
|
||||
|
||||
static inline const char *dlerror(void)
|
||||
static __inline__ const char *dlerror(void)
|
||||
{
|
||||
static char msg[256];
|
||||
unsigned long err = GetLastError();
|
||||
@@ -61,10 +61,10 @@ static inline const char *dlerror(void)
|
||||
}
|
||||
|
||||
#elif defined(HAVE_DLFCN_H)
|
||||
static inline ivl_dll_t ivl_dlopen(const char*name)
|
||||
static __inline__ ivl_dll_t ivl_dlopen(const char*name)
|
||||
{ return dlopen(name,RTLD_LAZY); }
|
||||
|
||||
static inline void* ivl_dlsym(ivl_dll_t dll, const char*nm)
|
||||
static __inline__ void* ivl_dlsym(ivl_dll_t dll, const char*nm)
|
||||
{
|
||||
void*sym = dlsym(dll, nm);
|
||||
/* Not found? try without the leading _ */
|
||||
@@ -73,24 +73,24 @@ static inline void* ivl_dlsym(ivl_dll_t dll, const char*nm)
|
||||
return sym;
|
||||
}
|
||||
|
||||
static inline void ivl_dlclose(ivl_dll_t dll)
|
||||
static __inline__ void ivl_dlclose(ivl_dll_t dll)
|
||||
{ dlclose(dll); }
|
||||
|
||||
#elif defined(HAVE_DL_H)
|
||||
static inline ivl_dll_t ivl_dlopen(const char*name)
|
||||
static __inline__ ivl_dll_t ivl_dlopen(const char*name)
|
||||
{ return shl_load(name, BIND_IMMEDIATE, 0); }
|
||||
|
||||
static inline void* ivl_dlsym(ivl_dll_t dll, const char*nm)
|
||||
static __inline__ void* ivl_dlsym(ivl_dll_t dll, const char*nm)
|
||||
{
|
||||
void*sym;
|
||||
int rc = shl_findsym(&dll, nm, TYPE_PROCEDURE, &sym);
|
||||
return (rc == 0) ? sym : 0;
|
||||
}
|
||||
|
||||
static inline void ivl_dlclose(ivl_dll_t dll)
|
||||
static __inline__ void ivl_dlclose(ivl_dll_t dll)
|
||||
{ shl_unload(dll); }
|
||||
|
||||
static inline const char*dlerror(void)
|
||||
static __inline__ const char*dlerror(void)
|
||||
{ return strerror( errno ); }
|
||||
#endif
|
||||
|
||||
|
||||
@@ -87,6 +87,7 @@ extern bool debug_eval_tree;
|
||||
extern bool debug_elaborate;
|
||||
extern bool debug_synth2;
|
||||
extern bool debug_optimizer;
|
||||
extern bool debug_automatic;
|
||||
|
||||
/* Path to a directory useful for finding subcomponents. */
|
||||
extern const char*basedir;
|
||||
|
||||
+1
-1
@@ -93,4 +93,4 @@
|
||||
* junk, and support gcc 3.0. (Stephan Boettcher)
|
||||
*
|
||||
*/
|
||||
#endif // __config_H
|
||||
#endif /* __config_H */
|
||||
|
||||
+3
-1
@@ -92,6 +92,8 @@ AC_C_BIGENDIAN
|
||||
|
||||
# $host
|
||||
|
||||
AX_ENABLE_SUFFIX
|
||||
|
||||
AX_LD_EXTRALIBS
|
||||
|
||||
# Compiler option for position independent code, needed when making shared objects.
|
||||
@@ -122,6 +124,6 @@ AX_C_UNDERSCORES_TRAILING
|
||||
AX_CPP_IDENT
|
||||
|
||||
# XXX disable tgt-fpga for the moment
|
||||
AC_CONFIG_SUBDIRS(vvp vpi tgt-stub tgt-null tgt-vvp libveriuser cadpli)
|
||||
AC_CONFIG_SUBDIRS(vvp vpi tgt-stub tgt-null tgt-vvp tgt-vhdl libveriuser cadpli)
|
||||
|
||||
AC_OUTPUT(Makefile ivlpp/Makefile driver/Makefile driver-vpi/Makefile tgt-null/Makefile tgt-verilog/Makefile tgt-pal/Makefile)
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
`ifdef CONSTANTS_VAMS
|
||||
`else
|
||||
`define CONSTANTS_VAMS 1
|
||||
|
||||
|
||||
// M_ is a mathematical constant
|
||||
`define M_E 2.7182818284590452354
|
||||
`define M_LOG2E 1.4426950408889634074
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998-2005 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2008 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
|
||||
@@ -739,7 +739,8 @@ v }
|
||||
}
|
||||
}
|
||||
|
||||
static void replace_with_bufif(Design*des, NetMux*obj, NetLogic::TYPE type)
|
||||
#if 0
|
||||
static void replace_with_mos(Design*des, NetMux*obj, NetLogic::TYPE type)
|
||||
{
|
||||
NetScope*scope = obj->scope();
|
||||
NetLogic*tmp = new NetLogic(obj->scope(),
|
||||
@@ -749,7 +750,7 @@ static void replace_with_bufif(Design*des, NetMux*obj, NetLogic::TYPE type)
|
||||
des->add_node(tmp);
|
||||
|
||||
connect(obj->pin_Result(), tmp->pin(0));
|
||||
connect(obj->pin_Data(type==NetLogic::BUFIF0? 0 : 1), tmp->pin(1));
|
||||
connect(obj->pin_Data(type==NetLogic::PMOS? 0 : 1), tmp->pin(1));
|
||||
|
||||
if (obj->width() == 1) {
|
||||
/* Special case that the expression is 1 bit
|
||||
@@ -780,10 +781,11 @@ static void replace_with_bufif(Design*des, NetMux*obj, NetLogic::TYPE type)
|
||||
|
||||
delete obj;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This detects the case where the mux selects between a value and
|
||||
* Vz. In this case, replace the device with a bufif with the sel
|
||||
* Vz. In this case, replace the device with a mos with the sel
|
||||
* input used to enable the output.
|
||||
*/
|
||||
void cprop_functor::lpm_mux(Design*des, NetMux*obj)
|
||||
@@ -793,45 +795,34 @@ void cprop_functor::lpm_mux(Design*des, NetMux*obj)
|
||||
if (obj->sel_width() != 1)
|
||||
return;
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* This is slower than the actual MUXZ so we are skipping this for now.
|
||||
* If we had a half mux functor this could be faster and more compact
|
||||
* so I'm leaving the code for future reference.
|
||||
*/
|
||||
/* If the first input is all constant Vz, then replace the
|
||||
NetMux with an array of BUFIF1 devices, with the enable
|
||||
NetMux with an array of NMOS devices, with the enable
|
||||
connected to the select input. */
|
||||
bool flag = true;
|
||||
|
||||
if (! obj->pin_Data(0).nexus()->drivers_constant()) {
|
||||
flag = false;
|
||||
}
|
||||
|
||||
if (flag && obj->pin_Data(0).nexus()->driven_value() != verinum::Vz) {
|
||||
flag = false;
|
||||
}
|
||||
|
||||
if (flag) {
|
||||
replace_with_bufif(des, obj, NetLogic::BUFIF1);
|
||||
if (obj->pin_Data(0).nexus()->drivers_constant() &&
|
||||
obj->pin_Data(0).nexus()->driven_value() == verinum::Vz) {
|
||||
replace_with_mos(des, obj, NetLogic::NMOS);
|
||||
count += 1;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* If instead the second input is all constant Vz, replace the
|
||||
NetMux with an array of BUFIF0 devices. */
|
||||
flag = true;
|
||||
if (! obj->pin_Data(1).nexus()->drivers_constant()) {
|
||||
flag = false;
|
||||
}
|
||||
|
||||
if (flag && obj->pin_Data(1).nexus()->driven_value() != verinum::Vz) {
|
||||
flag = false;
|
||||
}
|
||||
|
||||
if (flag) {
|
||||
replace_with_bufif(des, obj, NetLogic::BUFIF0);
|
||||
NetMux with an array of PMOS devices. */
|
||||
if (obj->pin_Data(1).nexus()->drivers_constant() &&
|
||||
obj->pin_Data(1).nexus()->driven_value() == verinum::Vz) {
|
||||
replace_with_mos(des, obj, NetLogic::PMOS);
|
||||
count += 1;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If the select input is constant, then replace with a BUFZ */
|
||||
flag = obj->pin_Sel().nexus()->drivers_constant();
|
||||
bool flag = obj->pin_Sel().nexus()->drivers_constant();
|
||||
verinum::V sel_val = flag? obj->pin_Sel().nexus()->driven_value() : verinum::Vx;
|
||||
if ((sel_val != verinum::Vz) && (sel_val != verinum::Vx)) {
|
||||
NetBUFZ*tmp = new NetBUFZ(obj->scope(), obj->name(), obj->width());
|
||||
@@ -897,7 +888,7 @@ void cprop_dc_functor::lpm_const(Design*des, NetConst*obj)
|
||||
for (Link*clnk = nex->first_nlink()
|
||||
; clnk ; clnk = clnk->next_nlink()) {
|
||||
|
||||
NetObj*cur;
|
||||
NetPins*cur;
|
||||
unsigned pin;
|
||||
clnk->cur_link(cur, pin);
|
||||
|
||||
@@ -923,7 +914,7 @@ void cprop_dc_functor::lpm_const(Design*des, NetConst*obj)
|
||||
for (Link*clnk = nex->first_nlink()
|
||||
; clnk ; clnk = clnk->next_nlink()) {
|
||||
|
||||
NetObj*cur;
|
||||
NetPins*cur;
|
||||
unsigned pin;
|
||||
clnk->cur_link(cur, pin);
|
||||
|
||||
@@ -974,4 +965,3 @@ void cprop(Design*des)
|
||||
cprop_dc_functor dc;
|
||||
des->functor(&dc);
|
||||
}
|
||||
|
||||
|
||||
+138
-16
@@ -27,6 +27,7 @@
|
||||
# include <iomanip>
|
||||
# include "netlist.h"
|
||||
# include "compiler.h"
|
||||
# include "discipline.h"
|
||||
# include "ivl_assert.h"
|
||||
|
||||
static ostream& operator<< (ostream&o, NetBlock::Type t)
|
||||
@@ -187,6 +188,10 @@ void NetNet::dump_net(ostream&o, unsigned ind) const
|
||||
o << " inout";
|
||||
break;
|
||||
}
|
||||
|
||||
if (ivl_discipline_t dis = get_discipline())
|
||||
o << " discipline=" << dis->name();
|
||||
|
||||
o << " (eref=" << peek_eref() << ", lref=" << peek_lref() << ")";
|
||||
if (scope())
|
||||
o << " scope=" << scope_path(scope());
|
||||
@@ -236,11 +241,14 @@ void NetNode::dump_node(ostream&o, unsigned ind) const
|
||||
/* This is the generic dumping of all the signals connected to each
|
||||
pin of the object. The "this" object is not printed, only the
|
||||
signals connected to this. */
|
||||
void NetObj::dump_node_pins(ostream&o, unsigned ind) const
|
||||
void NetPins::dump_node_pins(ostream&o, unsigned ind, const char**pin_names) const
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) {
|
||||
o << setw(ind) << "" << idx << " " << pin(idx).get_name()
|
||||
<< "<" << pin(idx).get_inst() << ">";
|
||||
o << setw(ind) << "" << idx;
|
||||
if (pin_names && pin_names[idx])
|
||||
o << " " << pin_names[idx];
|
||||
else
|
||||
o << " pin" << idx;
|
||||
|
||||
switch (pin(idx).get_dir()) {
|
||||
case Link::PASSIVE:
|
||||
@@ -289,7 +297,14 @@ void NetAddSub::dump_node(ostream&o, unsigned ind) const
|
||||
o << setw(ind) << "" << "Adder (NetAddSub): " << name()
|
||||
<< " width=" << width() << " pin_count=" << pin_count()
|
||||
<< endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
static const char* pin_names[] = {
|
||||
"Cout ",
|
||||
"DataA ",
|
||||
"DataB ",
|
||||
"Result"
|
||||
};
|
||||
|
||||
dump_node_pins(o, ind+4, pin_names);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
@@ -302,6 +317,22 @@ void NetArrayDq::dump_node(ostream&o, unsigned ind) const
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetCastInt::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "Cast to int. (NetCastInt): " <<
|
||||
name() << " width=" << width() << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetCastReal::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "Cast to real (NetCastReal): " <<
|
||||
name() << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetCLShift::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "Combinatorial shift (NetCLShift): " <<
|
||||
@@ -312,7 +343,9 @@ void NetCLShift::dump_node(ostream&o, unsigned ind) const
|
||||
|
||||
void NetCompare::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "LPM_COMPARE (NetCompare): " << name() << endl;
|
||||
o << setw(ind) << "" << "LPM_COMPARE (NetCompare "
|
||||
<< (get_signed()? "signed" : "unsigned") << "): "
|
||||
<< name() << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
@@ -546,8 +579,14 @@ void NetReplicate::dump_node(ostream&o, unsigned ind) const
|
||||
|
||||
void NetSignExtend::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "NetSignExtend: "
|
||||
<< name() << " output width=" << width_ << endl;
|
||||
o << setw(ind) << "" << "NetSignExtend: " << name();
|
||||
if (rise_time())
|
||||
o << " #(" << *rise_time()
|
||||
<< "," << *fall_time()
|
||||
<< "," << *decay_time() << ")";
|
||||
else
|
||||
o << " #(.,.,.)";
|
||||
o << " output width=" << width_ << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
@@ -663,11 +702,11 @@ void NetUDP::dump_node(ostream&o, unsigned ind) const
|
||||
void NetProcTop::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
switch (type_) {
|
||||
case NetProcTop::KINITIAL:
|
||||
case IVL_PR_INITIAL:
|
||||
o << "initial /* " << get_fileline() << " in "
|
||||
<< scope_path(scope_) << " */" << endl;
|
||||
break;
|
||||
case NetProcTop::KALWAYS:
|
||||
case IVL_PR_ALWAYS:
|
||||
o << "always /* " << get_fileline() << " in "
|
||||
<< scope_path(scope_) << " */" << endl;
|
||||
break;
|
||||
@@ -681,6 +720,28 @@ void NetProcTop::dump(ostream&o, unsigned ind) const
|
||||
statement_->dump(o, ind+2);
|
||||
}
|
||||
|
||||
void NetAnalogTop::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
switch (type_) {
|
||||
case IVL_PR_INITIAL:
|
||||
o << "analog initial /* " << get_fileline() << " in "
|
||||
<< scope_path(scope_) << " */" << endl;
|
||||
break;
|
||||
|
||||
case IVL_PR_ALWAYS:
|
||||
o << "analog /* " << get_fileline() << " in "
|
||||
<< scope_path(scope_) << " */" << endl;
|
||||
break;
|
||||
}
|
||||
|
||||
statement_->dump(o, ind+2);
|
||||
}
|
||||
|
||||
void NetAlloc::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "// allocate storage : " << scope_path(scope_) << endl;
|
||||
}
|
||||
|
||||
void NetAssign_::dump_lval(ostream&o) const
|
||||
{
|
||||
if (sig_) {
|
||||
@@ -732,6 +793,11 @@ void NetAssignNB::dump(ostream&o, unsigned ind) const
|
||||
|
||||
if (const NetExpr*de = get_delay())
|
||||
o << "#(" << *de << ") ";
|
||||
if (count_)
|
||||
o << "repeat(" << *count_ << ") ";
|
||||
if (event_) {
|
||||
o << *event_;
|
||||
}
|
||||
|
||||
o << *rval() << ";" << endl;
|
||||
|
||||
@@ -819,6 +885,15 @@ void NetCondit::dump(ostream&o, unsigned ind) const
|
||||
}
|
||||
}
|
||||
|
||||
void NetContribution::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "";
|
||||
lval_->dump(o);
|
||||
o << " <+ ";
|
||||
rval_->dump(o);
|
||||
o << ";" << endl;
|
||||
}
|
||||
|
||||
void NetDeassign::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "deassign ";
|
||||
@@ -876,6 +951,25 @@ void NetEvWait::dump(ostream&o, unsigned ind) const
|
||||
o << setw(ind+2) << "" << "/* noop */ ;" << endl;
|
||||
}
|
||||
|
||||
ostream& operator << (ostream&out, const NetEvWait&obj)
|
||||
{
|
||||
obj.dump_inline(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
void NetEvWait::dump_inline(ostream&o) const
|
||||
{
|
||||
o << "@(";
|
||||
|
||||
if (nevents() > 0)
|
||||
o << event(0)->name();
|
||||
|
||||
for (unsigned idx = 1 ; idx < nevents() ; idx += 1)
|
||||
o << " or " << event(idx)->name();
|
||||
|
||||
o << ") ";
|
||||
}
|
||||
|
||||
void NetForce::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "force ";
|
||||
@@ -889,6 +983,11 @@ void NetForever::dump(ostream&o, unsigned ind) const
|
||||
statement_->dump(o, ind+2);
|
||||
}
|
||||
|
||||
void NetFree::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "// free storage : " << scope_path(scope_) << endl;
|
||||
}
|
||||
|
||||
void NetFuncDef::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "function definition for " << scope_path(scope_) << endl;
|
||||
@@ -982,6 +1081,7 @@ void NetScope::dump(ostream&o) const
|
||||
o << " generate block";
|
||||
break;
|
||||
}
|
||||
if (is_auto()) o << " (automatic)";
|
||||
o << endl;
|
||||
|
||||
for (unsigned idx = 0 ; idx < attr_cnt() ; idx += 1)
|
||||
@@ -998,6 +1098,8 @@ void NetScope::dump(ostream&o) const
|
||||
; pp != parameters.end() ; pp ++) {
|
||||
o << " parameter ";
|
||||
|
||||
o << pp->second.type << " ";
|
||||
|
||||
if ((*pp).second.signed_flag)
|
||||
o << "signed ";
|
||||
|
||||
@@ -1047,7 +1149,7 @@ void NetScope::dump(ostream&o) const
|
||||
|
||||
/* Dump the saved defparam assignments here. */
|
||||
{
|
||||
map<pform_name_t,NetExpr*>::const_iterator pp;
|
||||
list<pair<pform_name_t,NetExpr*> >::const_iterator pp;
|
||||
for (pp = defparams.begin()
|
||||
; pp != defparams.end() ; pp ++ ) {
|
||||
o << " defparam " << (*pp).first << " = " <<
|
||||
@@ -1055,6 +1157,15 @@ void NetScope::dump(ostream&o) const
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
list<pair<list<hname_t>,NetExpr*> >::const_iterator pp;
|
||||
for (pp = defparams_later.begin()
|
||||
; pp != defparams_later.end() ; pp ++ ) {
|
||||
o << " defparam(later) " << pp->first << " = " <<
|
||||
*(pp->second) << ";" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
/* Dump the events in this scope. */
|
||||
for (NetEvent*cur = events_ ; cur ; cur = cur->snext_) {
|
||||
o << " event " << cur->name() << "; nprobe="
|
||||
@@ -1063,12 +1174,9 @@ void NetScope::dump(ostream&o) const
|
||||
}
|
||||
|
||||
// Dump the signals,
|
||||
if (signals_) {
|
||||
NetNet*cur = signals_->sig_next_;
|
||||
do {
|
||||
cur->dump_net(o, 4);
|
||||
cur = cur->sig_next_;
|
||||
} while (cur != signals_->sig_next_);
|
||||
for (signals_map_iter_t cur = signals_map_.begin()
|
||||
; cur != signals_map_.end() ; cur ++) {
|
||||
cur->second->dump_net(o, 4);
|
||||
}
|
||||
|
||||
// Dump specparams
|
||||
@@ -1157,6 +1265,18 @@ void NetExpr::dump(ostream&o) const
|
||||
o << "(?" << typeid(*this).name() << "?)";
|
||||
}
|
||||
|
||||
void NetEAccess::dump(ostream&o) const
|
||||
{
|
||||
o << nature_->name() << "." << nature_->access() << "(";
|
||||
assert(branch_);
|
||||
if (branch_->pin(0).is_linked())
|
||||
o << branch_->pin(0).nexus()->name();
|
||||
o << ", ";
|
||||
if (branch_->pin(1).is_linked())
|
||||
o << branch_->pin(1).nexus()->name();
|
||||
o << ")";
|
||||
}
|
||||
|
||||
void NetEBinary::dump(ostream&o) const
|
||||
{
|
||||
if (op_ == 'm' || op_ == 'M') {
|
||||
@@ -1397,4 +1517,6 @@ void Design::dump(ostream&o) const
|
||||
for (const NetProcTop*idx = procs_ ; idx ; idx = idx->next_)
|
||||
idx->dump(o, 0);
|
||||
|
||||
for (const NetAnalogTop*idx = aprocs_ ; idx ; idx = idx->next_)
|
||||
idx->dump(o, 0);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
|
||||
Developer Quick Start for Icarus Verilog
|
||||
|
||||
The documentation for getting, building and installing Icarus Verilog
|
||||
is kept and maintained at the iverilog documentation wiki at
|
||||
<http://iverilog.wikia.com>. See the Installation Guide for getting
|
||||
the current source from the git repository (and how to use the git
|
||||
repository) and see the Developer Guide for instructions on
|
||||
participating in the Icarus Verilog development process. That
|
||||
information will not be repeated here.
|
||||
|
||||
What this documentation *will* cover is the gross structure of the
|
||||
Icarus Verilog compiler source. This will help orient you to the
|
||||
source code itself, so that you can find the global parts where you
|
||||
can look for even better detail.
|
||||
|
||||
|
||||
* Compiler Components
|
||||
|
||||
- The compiler driver (driver/)
|
||||
|
||||
This is the binary that is installed as "iverilog". This program takes
|
||||
the command line arguments and assembles invocations of all the other
|
||||
subcommands to perform the steps of compilation.
|
||||
|
||||
- The preprocessor (ivlpp/)
|
||||
|
||||
This implements the Verilog pre-processor. In Icarus Verilog, the
|
||||
compiler directives `define, `include, `ifdef and etc. are implemented
|
||||
in an external program. The ivlpp/ directory contains the source for
|
||||
this program.
|
||||
|
||||
- The core compiler (this directory)
|
||||
|
||||
The "ivl" program is the core that does all the Verilog compiler
|
||||
processing that is not handled elsewhere. This is the main core of the
|
||||
Icarus Verilog compiler, not the runtime. See below for more details
|
||||
on the core itself.
|
||||
|
||||
- The loadable code generators (tgt-*/)
|
||||
|
||||
This core compiler, after it is finished with parsing and semantic
|
||||
analysis, uses loadable code generators to emit code for supported
|
||||
targets. The tgt-*/ directories contains the source for the target
|
||||
code generators that are bundled with Icarus Verilog. The tgt-vvp/
|
||||
directory in particular contains the code generator for the vvp
|
||||
runtime.
|
||||
|
||||
|
||||
* Runtime Components
|
||||
|
||||
- The vvp runtime (vvp/)
|
||||
|
||||
This program implements the runtime environment for Icarus
|
||||
Verilog. It implements the "vvp" command described in the user
|
||||
documentation. See the vvp/ subdirectory for further developer
|
||||
documentation.
|
||||
|
||||
- The system tasks implementations (vpi/)
|
||||
|
||||
The standard Verilog system tasks are implemented using VPI (PLI-2)
|
||||
and the source is in this subdirectory.
|
||||
|
||||
- The PLI-1 compatibility library (libveriuser/)
|
||||
|
||||
The Icarus Verilog support for the deprecated PLI-1 is in this
|
||||
subdirectory. The vvp runtime does not directly support the
|
||||
PLI-1. Instead, the libveriuser library emulates it using the builtin
|
||||
PLI-2 support.
|
||||
|
||||
- The Cadence PLI module compatibility module (cadpli/)
|
||||
|
||||
It is possible in some specialized situations to load and execute
|
||||
PLI-1 code written for Verilog-XL. This directory contains the source
|
||||
for the module that provides the Cadence PLI interface.
|
||||
|
||||
|
||||
* The Core Compiler
|
||||
|
||||
The "ivl" binary is the core compiler that does the heavy lifting of
|
||||
compiling the Verilog source (including libraries) and generating the
|
||||
output. This is the most complex component of the Icarus Verilog
|
||||
compilation system.
|
||||
|
||||
The process in the abstract starts with the Verilog lexical analysis
|
||||
and parsing to generate an internal "pform". The pform is then
|
||||
translated by elaboration into the "netlist" form. The netlist is
|
||||
processed by some functors (which include some optimizations and
|
||||
optional synthesis) then is translated into the ivl_target internal
|
||||
form. And finally, the ivl_target form is passed via the ivl_target.h
|
||||
API to the code generators.
|
||||
|
||||
- Lexical Analysis
|
||||
|
||||
Lexical analysis and parsing use the tools "flex", "gperf", and
|
||||
"bison". The "flex" input file "lexor.lex" recognizes the tokens in
|
||||
the input stream. This is called "lexical analysis". The lexical
|
||||
analyzer also does some processing of compiler directives that are not
|
||||
otherwise taken care of by the external preprocessor. The lexical
|
||||
analyzer uses a table of keywords that is generated using the "gperf"
|
||||
program and the input file "lexor_keywords.gperf". This table allows
|
||||
the lexical analyzer to efficiently check input words with the rather
|
||||
large set of potential keywords.
|
||||
|
||||
- Parsing
|
||||
|
||||
The parser input file "parse.y" is passed to the "bison" program to
|
||||
generate the parser. The parser uses the functions in parse*.h,
|
||||
parse*.cc, pform.h, and pform*.cc to generate the pform from the
|
||||
stream of input tokens. The pform is what compiler writers call a
|
||||
"decorated parse tree".
|
||||
|
||||
The pform itself is described by the classes in the header files
|
||||
"PScope.h", "Module.h", "PGenerate.h", "Statement.h", and
|
||||
"PExpr.h". The implementations of the classes in those header files
|
||||
are in the similarly named C++ files.
|
||||
|
||||
- Elaboration
|
||||
|
||||
Elaboration transforms the pform to the netlist form. Elaboration is
|
||||
conceptually divided into several major steps: Scope elaboration,
|
||||
parameter overrides and defparam propagation, signal elaboration, and
|
||||
statement and expression elaboration.
|
||||
|
||||
The elaboration of scopes and parameter overrides and defparam
|
||||
propagation are conceptually separate, but are in practice
|
||||
intermingled. The elaboration of scopes scans the pform to find and
|
||||
instantiate all the scopes of the design. New scopes are created by
|
||||
instantiation of modules (starting with the root instances) by user
|
||||
defined tasks and functions, named blocks, and generate schemes. The
|
||||
elaborate_scope methods implement scope elaboration, and the
|
||||
elab_scope.cc source file has the implementations of those
|
||||
methods.
|
||||
|
||||
The elaborate.cc source file contains the initial calls to the
|
||||
elaborate_scope for the root scopes to get the process started. In
|
||||
particular, see the "elaborate" function near the bottom of the
|
||||
elaborate.cc source file. The calls to Design::make_root_scope create
|
||||
the initial root scopes, and the creation and enqueue of the
|
||||
elaborate_root_scope_t work items primes the scope elaboration work
|
||||
list.
|
||||
|
||||
Intermingled in the work list are defparms work items that call the
|
||||
Design::run_defparams and Design::evaluate_parameters methods that
|
||||
override and evaluate parameters. The override and evaluation of
|
||||
parameters must be intermingled with the elaboration of scopes because
|
||||
the exact values of parameters may impact the scopes created (imagine
|
||||
generate schemes and instance arrays) and the created scopes in turn
|
||||
create new parameters that need override and evaluation.
|
||||
+6
-6
@@ -19,8 +19,8 @@
|
||||
|
||||
# include "discipline.h"
|
||||
|
||||
nature_t::nature_t(perm_string name, perm_string access)
|
||||
: name_(name), access_(access)
|
||||
nature_t::nature_t(perm_string name__, perm_string access__)
|
||||
: name_(name__), access_(access__)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -28,12 +28,12 @@ nature_t::~nature_t()
|
||||
{
|
||||
}
|
||||
|
||||
discipline_t::discipline_t(perm_string name, ddomain_t domain,
|
||||
nature_t*pot, nature_t*flow)
|
||||
: name_(name), domain_(domain), potential_(pot), flow_(flow)
|
||||
ivl_discipline_s::ivl_discipline_s(perm_string name__, ivl_dis_domain_t domain__,
|
||||
nature_t*pot, nature_t*flow__)
|
||||
: name_(name__), domain_(domain__), potential_(pot), flow_(flow__)
|
||||
{
|
||||
}
|
||||
|
||||
discipline_t::~discipline_t()
|
||||
ivl_discipline_s::~ivl_discipline_s()
|
||||
{
|
||||
}
|
||||
|
||||
+13
-11
@@ -28,10 +28,10 @@
|
||||
# include "StringHeap.h"
|
||||
# include <iostream>
|
||||
# include <map>
|
||||
# include "ivl_target.h"
|
||||
# include "LineInfo.h"
|
||||
|
||||
typedef enum { DD_NONE, DD_DISCRETE, DD_CONTINUOUS } ddomain_t;
|
||||
extern std::ostream& operator << (std::ostream&, ddomain_t);
|
||||
extern std::ostream& operator << (std::ostream&, ivl_dis_domain_t);
|
||||
|
||||
class nature_t : public LineInfo {
|
||||
public:
|
||||
@@ -47,29 +47,31 @@ class nature_t : public LineInfo {
|
||||
perm_string access_;
|
||||
};
|
||||
|
||||
class discipline_t : public LineInfo {
|
||||
class ivl_discipline_s : public LineInfo {
|
||||
public:
|
||||
explicit discipline_t (perm_string name, ddomain_t dom,
|
||||
nature_t*pot, nature_t*flow);
|
||||
~discipline_t();
|
||||
explicit ivl_discipline_s (perm_string name, ivl_dis_domain_t dom,
|
||||
nature_t*pot, nature_t*flow);
|
||||
~ivl_discipline_s();
|
||||
|
||||
perm_string name() const { return name_; }
|
||||
ddomain_t domain() const { return domain_; }
|
||||
ivl_dis_domain_t domain() const { return domain_; }
|
||||
const nature_t*potential() const { return potential_; }
|
||||
const nature_t*flow() const { return flow_; }
|
||||
|
||||
private:
|
||||
perm_string name_;
|
||||
ddomain_t domain_;
|
||||
ivl_dis_domain_t domain_;
|
||||
nature_t*potential_;
|
||||
nature_t*flow_;
|
||||
|
||||
private: // not implemented
|
||||
discipline_t(const discipline_t&);
|
||||
discipline_t& operator = (const discipline_t&);
|
||||
ivl_discipline_s(const ivl_discipline_s&);
|
||||
ivl_discipline_s& operator = (const ivl_discipline_s&);
|
||||
};
|
||||
|
||||
extern map<perm_string,nature_t*> natures;
|
||||
extern map<perm_string,discipline_t*> disciplines;
|
||||
extern map<perm_string,ivl_discipline_t> disciplines;
|
||||
// Map access function name to the nature that it accesses.
|
||||
extern map<perm_string,nature_t*> access_function_nature;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -20,6 +20,8 @@ SHELL = /bin/sh
|
||||
|
||||
VERSION = 0.9.devel
|
||||
|
||||
suffix = @install_suffix@
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
srcdir = @srcdir@
|
||||
@@ -27,6 +29,8 @@ datarootdir = @datarootdir@
|
||||
|
||||
VPATH = $(srcdir)
|
||||
|
||||
suffix = @install_suffix@
|
||||
|
||||
bindir = $(exec_prefix)/bin
|
||||
libdir = $(exec_prefix)/lib
|
||||
includedir = $(prefix)/include
|
||||
@@ -65,6 +69,7 @@ main.o: main.c config.h
|
||||
|
||||
config.h: config.h.in
|
||||
sed -e 's;@IVLCC@;@CC@;' -e 's;@IVLCXX@;@CXX@;' \
|
||||
-e 's;@SUFFIX@;$(suffix);g' \
|
||||
-e 's;@IVLCFLAGS@;@CXXFLAGS@;' \
|
||||
-e 's;@SHARED@;@shared@;' $< > $@
|
||||
|
||||
@@ -73,13 +78,13 @@ res.o: res.rc
|
||||
windres -i res.rc -o res.o
|
||||
#
|
||||
|
||||
install: all installdirs $(bindir)/iverilog-vpi@EXEEXT@
|
||||
install: all installdirs $(bindir)/iverilog-vpi$(suffix)@EXEEXT@
|
||||
|
||||
$(bindir)/iverilog-vpi@EXEEXT@: ./iverilog-vpi@EXEEXT@
|
||||
$(INSTALL_PROGRAM) ./iverilog-vpi@EXEEXT@ $(bindir)/iverilog-vpi@EXEEXT@
|
||||
$(bindir)/iverilog-vpi$(suffix)@EXEEXT@: ./iverilog-vpi@EXEEXT@
|
||||
$(INSTALL_PROGRAM) ./iverilog-vpi@EXEEXT@ $(bindir)/iverilog-vpi$(suffix)@EXEEXT@
|
||||
|
||||
installdirs: ../mkinstalldirs
|
||||
$(srcdir)/../mkinstalldirs $(bindir)
|
||||
|
||||
uninstall:
|
||||
rm -f $(bindir)/iverilog-vpi@EXEEXT@
|
||||
rm -f $(bindir)/iverilog-vpi$(suffix)@EXEEXT@
|
||||
|
||||
@@ -5,4 +5,5 @@
|
||||
#define IVERILOG_VPI_CXX "@IVLCXX@"
|
||||
#define IVERILOG_VPI_CFLAGS " @IVLCFLAGS@"
|
||||
#define IVERILOG_VPI_LDFLAGS "@SHARED@"
|
||||
#define IVERILOG_VPI_LDLIBS "-lveriuser -lvpi"
|
||||
#define IVERILOG_VPI_LDLIBS "-lveriuser@SUFFIX@ -lvpi@SUFFIX@"
|
||||
#define IVERILOG_SUFFIX "@SUFFIX@"
|
||||
|
||||
+8
-8
@@ -87,9 +87,9 @@ static void myExit(int exitVal)
|
||||
|
||||
static void usage()
|
||||
{
|
||||
fprintf(stderr,"usage: iverilog-vpi [src and obj files]...\n");
|
||||
fprintf(stderr," or iverilog-vpi -mingw=dir\n");
|
||||
fprintf(stderr," or iverilog-vpi -ivl=dir\n");
|
||||
fprintf(stderr,"usage: iverilog-vpi" IVERILOG_SUFFIX " [src and obj files]...\n");
|
||||
fprintf(stderr," or iverilog-vpi" IVERILOG_SUFFIX " -mingw=dir\n");
|
||||
fprintf(stderr," or iverilog-vpi" IVERILOG_SUFFIX " -ivl=dir\n");
|
||||
myExit(1);
|
||||
}
|
||||
|
||||
@@ -384,7 +384,7 @@ static int parse(int argc, char *argv[])
|
||||
/* Check for the --install-dir option */
|
||||
else if (stricmp("--install-dir", argv[idx]) == 0) {
|
||||
setup_ivl_environment();
|
||||
printf("%s\\\\lib\\\\ivl\\\\.\n", gstr.pIVL);
|
||||
printf("%s\\\\lib\\\\ivl" IVERILOG_SUFFIX "\\\\.\n", gstr.pIVL);
|
||||
myExit(0);
|
||||
}
|
||||
/* This is different than iverilog-vpi.sh, we don't
|
||||
@@ -444,14 +444,14 @@ static void checkIvlDir(char *root)
|
||||
initDynString(&path);
|
||||
assign(&path,gstr.pIVL);
|
||||
appendBackSlash(&path);
|
||||
append(&path,"bin\\vvp.exe");
|
||||
append(&path,"bin\\vvp" IVERILOG_SUFFIX ".exe");
|
||||
|
||||
irv = _stat(path,&stat_buf);
|
||||
deInitDynString(path);
|
||||
|
||||
if (irv) {
|
||||
fprintf(stderr,"error: %s does not appear to be the valid root directory of\n",root);
|
||||
fprintf(stderr," Icarus Verilog. Use the -ivl option of iverilog-vpi.exe to\n");
|
||||
fprintf(stderr," Icarus Verilog. Use the -ivl option of iverilog-vpi" IVERILOG_SUFFIX " to\n");
|
||||
fprintf(stderr," point to the Icarus Verilog root directory. For a Windows\n");
|
||||
fprintf(stderr," command shell the option would be something like -ivl=c:\\iverilog\n");
|
||||
fprintf(stderr," For a Cygwin shell the option would be something like\n");
|
||||
@@ -503,7 +503,7 @@ static void setup_ivl_environment()
|
||||
SetRegistryKey(IVL_REGKEY_IVL,gstr.pIVL);
|
||||
} else if (!GetRegistryKey(IVL_REGKEY_IVL,&gstr.pIVL)) {
|
||||
fprintf(stderr,"error: can not locate the Icarus Verilog root directory, use the -ivl option\n");
|
||||
fprintf(stderr," of iverilog-vpi.exe to point to the Icarus Verilog root directory.\n");
|
||||
fprintf(stderr," of iverilog-vpi" IVERILOG_SUFFIX " to point to the Icarus Verilog root directory.\n");
|
||||
fprintf(stderr," For a Windows command shell the option would be something like\n");
|
||||
fprintf(stderr," -ivl=c:\\iverilog For a Cygwin shell the option would be something\n");
|
||||
fprintf(stderr," like -ivl=c:\\\\iverilog\n");
|
||||
@@ -516,7 +516,7 @@ static void setup_ivl_environment()
|
||||
append(&gstr.pCFLAGS,gstr.pIVL);
|
||||
appendBackSlash(&gstr.pCFLAGS);
|
||||
append(&gstr.pCFLAGS, "\\");
|
||||
append(&gstr.pCFLAGS,"include");
|
||||
append(&gstr.pCFLAGS,"include" IVERILOG_SUFFIX);
|
||||
|
||||
/* Build up the LDFLAGS option string */
|
||||
assign(&gstr.pLDLIBS,"-L");
|
||||
|
||||
+17
-15
@@ -20,6 +20,8 @@ SHELL = /bin/sh
|
||||
|
||||
VERSION = 0.9.devel
|
||||
|
||||
suffix = @install_suffix@
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
srcdir = @srcdir@
|
||||
@@ -68,7 +70,7 @@ cfparse.h cfparse.c: cfparse.y
|
||||
|
||||
|
||||
main.o: main.c globals.h ../version.h
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) -c -DIVL_ROOT='"@libdir@/ivl"' -DIVL_INC='"@includedir@"' -DIVL_LIB='"@libdir@"' -DDLLIB='"@DLLIB@"' $(srcdir)/main.c
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) -c -DIVL_ROOT='"@libdir@/ivl$(suffix)"' -DIVL_INC='"@includedir@"' -DIVL_LIB='"@libdir@"' -DDLLIB='"@DLLIB@"' $(srcdir)/main.c
|
||||
|
||||
build_string.o: build_string.c globals.h
|
||||
cflexor.o: cflexor.c cfparse.h cfparse_misc.h globals.h
|
||||
@@ -82,35 +84,35 @@ iverilog.pdf: iverilog.ps
|
||||
|
||||
ifeq (@MINGW32@,yes)
|
||||
ifeq ($(MAN),none)
|
||||
INSTALL_DOC = $(mandir)/man1/iverilog.1
|
||||
INSTALL_DOC = $(mandir)/man1/iverilog$(suffix).1
|
||||
else
|
||||
ifeq ($(PS2PDF),none)
|
||||
INSTALL_DOC = $(mandir)/man1/iverilog.1
|
||||
INSTALL_DOC = $(mandir)/man1/iverilog$(suffix).1
|
||||
else
|
||||
INSTALL_DOC = $(prefix)/iverilog.pdf $(mandir)/man1/iverilog.1
|
||||
INSTALL_DOC = $(prefix)/iverilog$(suffix).pdf $(mandir)/man1/iverilog$(suffix).1
|
||||
all: iverilog.pdf
|
||||
endif
|
||||
endif
|
||||
INSTALL_DOCDIR = $(mandir)/man1
|
||||
else
|
||||
INSTALL_DOC = $(mandir)/man1/iverilog.1
|
||||
INSTALL_DOC = $(mandir)/man1/iverilog$(suffix).1
|
||||
INSTALL_DOCDIR = $(mandir)/man1
|
||||
endif
|
||||
|
||||
install: all installdirs $(bindir)/iverilog@EXEEXT@ $(INSTALL_DOC)
|
||||
install: all installdirs $(bindir)/iverilog$(suffix)@EXEEXT@ $(INSTALL_DOC)
|
||||
|
||||
$(bindir)/iverilog@EXEEXT@: ./iverilog@EXEEXT@
|
||||
$(INSTALL_PROGRAM) ./iverilog@EXEEXT@ $(bindir)/iverilog@EXEEXT@
|
||||
$(bindir)/iverilog$(suffix)@EXEEXT@: ./iverilog@EXEEXT@
|
||||
$(INSTALL_PROGRAM) ./iverilog@EXEEXT@ $(DESTDIR)$(bindir)/iverilog$(suffix)@EXEEXT@
|
||||
|
||||
$(mandir)/man1/iverilog.1: $(srcdir)/iverilog.man
|
||||
$(INSTALL_DATA) $(srcdir)/iverilog.man $(mandir)/man1/iverilog.1
|
||||
$(mandir)/man1/iverilog$(suffix).1: $(srcdir)/iverilog.man
|
||||
$(INSTALL_DATA) $(srcdir)/iverilog.man $(DESTDIR)$(mandir)/man1/iverilog$(suffix).1
|
||||
|
||||
$(prefix)/iverilog.pdf: iverilog.pdf
|
||||
$(INSTALL_DATA) iverilog.pdf $(prefix)/iverilog.pdf
|
||||
$(prefix)/iverilog$(suffix).pdf: iverilog.pdf
|
||||
$(INSTALL_DATA) iverilog.pdf $(prefix)/iverilog$(suffix).pdf
|
||||
|
||||
installdirs: ../mkinstalldirs
|
||||
$(srcdir)/../mkinstalldirs $(bindir) $(INSTALL_DOCDIR)
|
||||
$(srcdir)/../mkinstalldirs $(DESTDIR)$(bindir) $(DESTDIR)$(INSTALL_DOCDIR)
|
||||
|
||||
uninstall:
|
||||
rm -f $(bindir)/iverilog@EXEEXT@
|
||||
rm -f $(mandir)/man1/iverilog.1 $(prefix)/iverilog.pdf
|
||||
rm -f $(DESTDIR)$(bindir)/iverilog$(suffix)@EXEEXT@
|
||||
rm -f $(DESTDIR)$(mandir)/man1/iverilog$(suffix).1 $(DESTDIR)$(prefix)/iverilog$(suffix).pdf
|
||||
|
||||
+1
-1
@@ -149,7 +149,7 @@ int cmdfile_stack_ptr = 0;
|
||||
cflval.text = trim_trailing_white(yytext, 0);
|
||||
BEGIN(0);
|
||||
return TOK_STRING; }
|
||||
|
||||
|
||||
/* Fallback match. */
|
||||
. { return yytext[0]; }
|
||||
|
||||
|
||||
+7
-11
@@ -14,7 +14,7 @@ iverilog - Icarus Verilog compiler
|
||||
\fIiverilog\fP is a compiler that translates Verilog source code into
|
||||
executable programs for simulation, or other netlist formats for
|
||||
further processing. The currently supported targets are \fIvvp\fP for
|
||||
simulation, and \fIxnf\fP and \fIfpga\fP for synthesis. Other target
|
||||
simulation, and \fIfpga\fP for synthesis. Other target
|
||||
types are added as code generators are implemented.
|
||||
|
||||
.SH OPTIONS
|
||||
@@ -212,17 +212,18 @@ This is the default. The vvp target generates code for the vvp
|
||||
runtime. The output is a complete program that simulates the design
|
||||
but must be run by the \fBvvp\fP command.
|
||||
.TP 8
|
||||
.B xnf
|
||||
This is the Xilinx Netlist Format used by many tools for placing
|
||||
devices in FPGAs or other programmable devices. This target is
|
||||
obsolete, use the \fBfpga\fP target instead.
|
||||
.TP 8
|
||||
.B fpga
|
||||
This is a synthesis target that supports a variety of fpga devices,
|
||||
mostly by EDIF format output. The Icarus Verilog fpga code generator
|
||||
can generate complete designs or EDIF macros that can in turn be
|
||||
imported into larger designs by other tools. The \fBfpga\fP target
|
||||
implies the synthesis \fB-S\fP flag.
|
||||
.TP 8
|
||||
.B vhdl
|
||||
This target produces a VHDL translation of the Verilog netlist. The
|
||||
output is a single file containing VHDL entities corresponding to
|
||||
the modules in the Verilog source code. Note that only a subset of
|
||||
the Verilog language is supported. See the wiki for more information.
|
||||
|
||||
.SH "WARNING TYPES"
|
||||
These are the types of warnings that can be selected by the \fB-W\fP
|
||||
@@ -412,11 +413,6 @@ To compile and run explicitly using the vvp runtime:
|
||||
|
||||
iverilog -ohello.vvp -tvvp hello.v
|
||||
|
||||
To compile hello.v to a file in XNF-format called hello.xnf
|
||||
|
||||
iverilog -txnf -ohello.xnf hello.v
|
||||
|
||||
|
||||
.SH "AUTHOR"
|
||||
.nf
|
||||
Steve Williams ([email protected])
|
||||
|
||||
+142
-77
@@ -51,6 +51,7 @@ const char HELP[] =
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
@@ -106,7 +107,7 @@ const char*npath = 0;
|
||||
const char*targ = "vvp";
|
||||
const char*depfile = 0;
|
||||
|
||||
const char*generation = "2x";
|
||||
const char*generation = "2005";
|
||||
const char*gen_specify = "specify";
|
||||
const char*gen_xtypes = "xtypes";
|
||||
const char*gen_icarus = "icarus-misc";
|
||||
@@ -259,18 +260,113 @@ static const char*my_tempfile(const char*str, FILE**fout)
|
||||
return pathbuf;
|
||||
}
|
||||
|
||||
static int t_version_only(void)
|
||||
{
|
||||
remove(source_path);
|
||||
free(source_path);
|
||||
|
||||
fflush(0);
|
||||
snprintf(tmp, sizeof tmp, "%s%civlpp -V", pbase, sep);
|
||||
system(tmp);
|
||||
|
||||
fflush(0);
|
||||
snprintf(tmp, sizeof tmp, "%s%civl -V -C%s -C%s", pbase, sep,
|
||||
iconfig_path, iconfig_common_path);
|
||||
system(tmp);
|
||||
|
||||
if ( ! getenv("IVERILOG_ICONFIG")) {
|
||||
remove(iconfig_path);
|
||||
free(iconfig_path);
|
||||
remove(defines_path);
|
||||
free(defines_path);
|
||||
remove(compiled_defines_path);
|
||||
free(compiled_defines_path);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void build_preprocess_command(int e_flag)
|
||||
{
|
||||
snprintf(tmp, sizeof tmp, "%s%civlpp %s%s -F%s -f%s -p%s ",
|
||||
pbase,sep, verbose_flag?" -v":"",
|
||||
e_flag?"":" -L", defines_path, source_path,
|
||||
compiled_defines_path);
|
||||
}
|
||||
|
||||
static int t_preprocess_only(void)
|
||||
{
|
||||
int rc;
|
||||
char*cmd;
|
||||
unsigned ncmd;
|
||||
|
||||
build_preprocess_command(1);
|
||||
|
||||
ncmd = strlen(tmp);
|
||||
cmd = malloc(ncmd+1);
|
||||
strcpy(cmd, tmp);
|
||||
|
||||
if (strcmp(opath,"-") != 0) {
|
||||
snprintf(tmp, sizeof tmp, " > %s", opath);
|
||||
cmd = realloc(cmd, ncmd+strlen(tmp)+1);
|
||||
strcpy(cmd+ncmd, tmp);
|
||||
ncmd += strlen(tmp);
|
||||
}
|
||||
|
||||
if (verbose_flag)
|
||||
printf("preprocess: %s\n", cmd);
|
||||
|
||||
rc = system(cmd);
|
||||
remove(source_path);
|
||||
free(source_path);
|
||||
|
||||
if ( ! getenv("IVERILOG_ICONFIG")) {
|
||||
remove(iconfig_path);
|
||||
free(iconfig_path);
|
||||
remove(defines_path);
|
||||
free(defines_path);
|
||||
remove(compiled_defines_path);
|
||||
free(compiled_defines_path);
|
||||
}
|
||||
|
||||
if (rc != 0) {
|
||||
if (WIFEXITED(rc)) {
|
||||
fprintf(stderr, "errors preprocessing Verilog program.\n");
|
||||
return WEXITSTATUS(rc);
|
||||
}
|
||||
|
||||
fprintf(stderr, "Command signaled: %s\n", cmd);
|
||||
free(cmd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
free(cmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the default target type. It looks up the bits that are
|
||||
* needed to run the command from the configuration file (which is
|
||||
* already parsed for us) so we can handle must of the generic cases.
|
||||
*/
|
||||
static int t_default(char*cmd, unsigned ncmd)
|
||||
static int t_compile()
|
||||
{
|
||||
unsigned rc;
|
||||
|
||||
/* Start by building the preprocess command line. */
|
||||
build_preprocess_command(0);
|
||||
|
||||
size_t ncmd = strlen(tmp);
|
||||
char*cmd = malloc(ncmd + 1);
|
||||
strcpy(cmd, tmp);
|
||||
|
||||
#ifdef __MINGW32__
|
||||
unsigned ncmd_start = ncmd;
|
||||
#else
|
||||
int rtn;
|
||||
#endif
|
||||
|
||||
/* Build the ivl command and pipe it to the preprocessor. */
|
||||
snprintf(tmp, sizeof tmp, " | %s/ivl", base);
|
||||
rc = strlen(tmp);
|
||||
cmd = realloc(cmd, ncmd+rc+1);
|
||||
@@ -323,28 +419,33 @@ static int t_default(char*cmd, unsigned ncmd)
|
||||
rc = system(cmd);
|
||||
if ( ! getenv("IVERILOG_ICONFIG")) {
|
||||
remove(source_path);
|
||||
free(source_path);
|
||||
remove(iconfig_path);
|
||||
free(iconfig_path);
|
||||
remove(defines_path);
|
||||
free(defines_path);
|
||||
remove(compiled_defines_path);
|
||||
free(compiled_defines_path);
|
||||
}
|
||||
#ifdef __MINGW32__ /* MinGW just returns the exit status, so return it! */
|
||||
free(cmd);
|
||||
return rc;
|
||||
#else
|
||||
|
||||
rtn = 0;
|
||||
if (rc != 0) {
|
||||
if (rc == 127) {
|
||||
fprintf(stderr, "Failed to execute: %s\n", cmd);
|
||||
return 1;
|
||||
rtn = 1;
|
||||
} else if (WIFEXITED(rc)) {
|
||||
rtn = WEXITSTATUS(rc);
|
||||
} else {
|
||||
fprintf(stderr, "Command signaled: %s\n", cmd);
|
||||
rtn = -1;
|
||||
}
|
||||
|
||||
if (WIFEXITED(rc))
|
||||
return WEXITSTATUS(rc);
|
||||
|
||||
fprintf(stderr, "Command signaled: %s\n", cmd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
free(cmd);
|
||||
return rtn;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -505,7 +606,7 @@ int process_generation(const char*name)
|
||||
" 2005 -- IEEE1364-2005\n"
|
||||
"Other generation flags:\n"
|
||||
" specify | no-specify\n"
|
||||
" verilog-ams | no-verinlog-ams\n"
|
||||
" verilog-ams | no-verilog-ams\n"
|
||||
" std-include | no-std-include\n"
|
||||
" xtypes | no-xtypes\n"
|
||||
" icarus-misc | no-icarus-misc\n"
|
||||
@@ -522,7 +623,7 @@ int process_generation(const char*name)
|
||||
void add_sft_file(const char *module)
|
||||
{
|
||||
char *file;
|
||||
|
||||
|
||||
file = (char *) malloc(strlen(base)+1+strlen(module)+4+1);
|
||||
sprintf(file, "%s%c%s.sft", base, sep, module);
|
||||
if (access(file, R_OK) == 0)
|
||||
@@ -532,8 +633,6 @@ void add_sft_file(const char *module)
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char*cmd;
|
||||
unsigned ncmd;
|
||||
int e_flag = 0;
|
||||
int version_flag = 0;
|
||||
int opt, idx, rc;
|
||||
@@ -653,7 +752,7 @@ int main(int argc, char **argv)
|
||||
case 'c':
|
||||
case 'f':
|
||||
add_cmd_file(optarg);
|
||||
break;
|
||||
break;
|
||||
case 'D':
|
||||
process_define(optarg);
|
||||
break;
|
||||
@@ -672,9 +771,9 @@ int main(int argc, char **argv)
|
||||
if (rc != 0)
|
||||
return -1;
|
||||
break;
|
||||
case 'h':
|
||||
fprintf(stderr, "%s\n", HELP);
|
||||
return 1;
|
||||
case 'h':
|
||||
fprintf(stderr, "%s\n", HELP);
|
||||
return 1;
|
||||
|
||||
case 'I':
|
||||
process_include_dir(optarg);
|
||||
@@ -747,9 +846,6 @@ int main(int argc, char **argv)
|
||||
printf("Icarus Verilog version " VERSION " (" VERSION_TAG ")\n\n");
|
||||
printf("Copyright 1998-2008 Stephen Williams\n");
|
||||
puts(NOTICE);
|
||||
|
||||
if (version_flag)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Make a common conf file path to reflect the target. */
|
||||
@@ -764,9 +860,18 @@ int main(int argc, char **argv)
|
||||
how to handle them. */
|
||||
fprintf(iconfig_file, "sys_func:%s%csystem.sft\n", base, sep);
|
||||
|
||||
/* If verilog-ams is enabled, then include the va_math module
|
||||
as well. */
|
||||
if (strcmp(gen_verilog_ams,"verilog-ams") == 0) {
|
||||
/* If verilog-2005 is enabled or icarus-misc or verilog-ams,
|
||||
* then include the v2005_math library. */
|
||||
if (strcmp(generation, "2005") == 0 ||
|
||||
strcmp(gen_icarus, "icarus-misc") == 0 ||
|
||||
strcmp(gen_verilog_ams, "verilog-ams") == 0) {
|
||||
fprintf(iconfig_file, "sys_func:%s%cv2005_math.sft\n", base, sep);
|
||||
fprintf(iconfig_file, "module:v2005_math\n");
|
||||
}
|
||||
/* If verilog-ams or icarus_misc is enabled, then include the
|
||||
* va_math module as well. */
|
||||
if (strcmp(gen_verilog_ams,"verilog-ams") == 0 ||
|
||||
strcmp(gen_icarus, "icarus-misc") == 0) {
|
||||
fprintf(iconfig_file, "sys_func:%s%cva_math.sft\n", base, sep);
|
||||
fprintf(iconfig_file, "module:va_math\n");
|
||||
}
|
||||
@@ -823,60 +928,11 @@ int main(int argc, char **argv)
|
||||
fclose(defines_file);
|
||||
defines_file = 0;
|
||||
|
||||
if (source_count == 0) {
|
||||
if (source_count == 0 && !version_flag) {
|
||||
fprintf(stderr, "%s: no source files.\n\n%s\n", argv[0], HELP);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* Start building the preprocess command line. */
|
||||
|
||||
sprintf(tmp, "%s%civlpp %s%s -F%s -f%s -p%s ", pbase,sep,
|
||||
verbose_flag?" -v":"",
|
||||
e_flag?"":" -L", defines_path, source_path,
|
||||
compiled_defines_path);
|
||||
|
||||
ncmd = strlen(tmp);
|
||||
cmd = malloc(ncmd + 1);
|
||||
strcpy(cmd, tmp);
|
||||
|
||||
/* If the -E flag was given on the command line, then all we
|
||||
do is run the preprocessor and put the output where the
|
||||
user wants it. */
|
||||
if (e_flag) {
|
||||
int rc;
|
||||
if (strcmp(opath,"-") != 0) {
|
||||
sprintf(tmp, " > %s", opath);
|
||||
cmd = realloc(cmd, ncmd+strlen(tmp)+1);
|
||||
strcpy(cmd+ncmd, tmp);
|
||||
ncmd += strlen(tmp);
|
||||
}
|
||||
|
||||
if (verbose_flag)
|
||||
printf("preprocess: %s\n", cmd);
|
||||
|
||||
rc = system(cmd);
|
||||
remove(source_path);
|
||||
fclose(iconfig_file);
|
||||
if ( ! getenv("IVERILOG_ICONFIG")) {
|
||||
remove(iconfig_path);
|
||||
remove(defines_path);
|
||||
remove(compiled_defines_path);
|
||||
}
|
||||
|
||||
if (rc != 0) {
|
||||
if (WIFEXITED(rc)) {
|
||||
fprintf(stderr, "errors preprocessing Verilog program.\n");
|
||||
return WEXITSTATUS(rc);
|
||||
}
|
||||
|
||||
fprintf(stderr, "Command signaled: %s\n", cmd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
fprintf(iconfig_file, "iwidth:%u\n", integer_width);
|
||||
|
||||
/* Write the preprocessor command needed to preprocess a
|
||||
@@ -888,7 +944,16 @@ int main(int argc, char **argv)
|
||||
/* Done writing to the iconfig file. Close it now. */
|
||||
fclose(iconfig_file);
|
||||
|
||||
return t_default(cmd, ncmd);
|
||||
/* If we're only here for the version output, then we're done. */
|
||||
if (version_flag)
|
||||
return t_version_only();
|
||||
|
||||
return 0;
|
||||
/* If the -E flag was given on the command line, then all we
|
||||
do is run the preprocessor and put the output where the
|
||||
user wants it. */
|
||||
if (e_flag)
|
||||
return t_preprocess_only();
|
||||
|
||||
/* Otherwise, this is a full compile. */
|
||||
return t_compile();
|
||||
}
|
||||
|
||||
+20
-2
@@ -21,6 +21,16 @@
|
||||
|
||||
# include "netlist.h"
|
||||
# include <cassert>
|
||||
# include <stdlib.h>
|
||||
# include "ivl_assert.h"
|
||||
|
||||
NetEAccess* NetEAccess::dup_expr() const
|
||||
{
|
||||
NetEAccess*tmp = new NetEAccess(branch_, nature_);
|
||||
ivl_assert(*this, tmp);
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetEBComp* NetEBComp::dup_expr() const
|
||||
{
|
||||
@@ -84,8 +94,8 @@ NetESFunc* NetESFunc::dup_expr() const
|
||||
|
||||
tmp->cast_signed(has_sign());
|
||||
for (unsigned idx = 0 ; idx < nparms() ; idx += 1) {
|
||||
assert(tmp->parm(idx));
|
||||
tmp->parm(idx, tmp->parm(idx)->dup_expr());
|
||||
assert(parm(idx));
|
||||
tmp->parm(idx, parm(idx)->dup_expr());
|
||||
}
|
||||
|
||||
tmp->set_line(*this);
|
||||
@@ -128,6 +138,14 @@ NetEUFunc* NetEUFunc::dup_expr() const
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetEUBits* NetEUBits::dup_expr() const
|
||||
{
|
||||
NetEUBits*tmp = new NetEUBits(op_, expr_->dup_expr());
|
||||
assert(tmp);
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetEUnary* NetEUnary::dup_expr() const
|
||||
{
|
||||
NetEUnary*tmp = new NetEUnary(op_, expr_->dup_expr());
|
||||
|
||||
+1
-2
@@ -115,7 +115,7 @@ NetNet* PEIdent::elaborate_anet(Design*des, NetScope*scope) const
|
||||
const NetExpr*par = 0;
|
||||
NetEvent* eve = 0;
|
||||
|
||||
symbol_search(des, scope, path_, sig, mem, par, eve);
|
||||
symbol_search(this, des, scope, path_, sig, mem, par, eve);
|
||||
|
||||
|
||||
if (mem != 0) {
|
||||
@@ -211,4 +211,3 @@ NetNet* PEIdent::elaborate_anet(Design*des, NetScope*scope) const
|
||||
* Check lvalue of procedural continuous assign (PR#29)
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
+1248
-307
File diff suppressed because it is too large
Load Diff
+72
-103
@@ -152,7 +152,7 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
||||
const NetExpr*par = 0;
|
||||
NetEvent* eve = 0;
|
||||
|
||||
symbol_search(des, scope, path_, reg, par, eve);
|
||||
symbol_search(this, des, scope, path_, reg, par, eve);
|
||||
if (reg == 0) {
|
||||
cerr << get_fileline() << ": error: Could not find variable ``"
|
||||
<< path_ << "'' in ``" << scope_path(scope) <<
|
||||
@@ -208,101 +208,18 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
||||
return 0;
|
||||
}
|
||||
|
||||
long msb, lsb;
|
||||
NetExpr*mux;
|
||||
|
||||
if (use_sel == index_component_t::SEL_BIT) {
|
||||
|
||||
const index_component_t&index_tail = name_tail.index.back();
|
||||
ivl_assert(*this, index_tail.msb != 0);
|
||||
ivl_assert(*this, index_tail.lsb == 0);
|
||||
|
||||
/* If there is only a single select expression, it is a
|
||||
bit select. Evaluate the constant value and treat it
|
||||
as a part select with a bit width of 1. If the
|
||||
expression it not constant, then return the
|
||||
expression as a mux. */
|
||||
|
||||
NetExpr*index_expr = elab_and_eval(des, scope, index_tail.msb, -1);
|
||||
|
||||
if (NetEConst*index_con = dynamic_cast<NetEConst*> (index_expr)) {
|
||||
msb = index_con->value().as_long();
|
||||
lsb = index_con->value().as_long();
|
||||
mux = 0;
|
||||
|
||||
} else {
|
||||
msb = 0;
|
||||
lsb = 0;
|
||||
mux = index_expr;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
/* No select expressions, so presume a part select the
|
||||
width of the register. */
|
||||
|
||||
msb = reg->msb();
|
||||
lsb = reg->lsb();
|
||||
mux = 0;
|
||||
NetAssign_*lv = new NetAssign_(reg);
|
||||
elaborate_lval_net_bit_(des, scope, lv);
|
||||
return lv;
|
||||
}
|
||||
|
||||
ivl_assert(*this, use_sel == index_component_t::SEL_NONE);
|
||||
|
||||
NetAssign_*lv;
|
||||
if (mux) {
|
||||
|
||||
/* If there is a non-constant bit select, make a
|
||||
NetAssign_ to the target reg and attach a
|
||||
bmux to select the target bit. */
|
||||
lv = new NetAssign_(reg);
|
||||
|
||||
/* Correct the mux for the range of the vector. */
|
||||
if (reg->msb() < reg->lsb())
|
||||
mux = make_sub_expr(reg->lsb(), mux);
|
||||
else if (reg->lsb() != 0)
|
||||
mux = make_add_expr(mux, - reg->lsb());
|
||||
|
||||
lv->set_part(mux, 1);
|
||||
|
||||
} else if (msb == reg->msb() && lsb == reg->lsb()) {
|
||||
|
||||
/* No bit select, and part select covers the entire
|
||||
vector. Simplest case. */
|
||||
lv = new NetAssign_(reg);
|
||||
|
||||
} else {
|
||||
|
||||
/* If the bit/part select is constant, then make the
|
||||
NetAssign_ only as wide as it needs to be and connect
|
||||
only to the selected bits of the reg. */
|
||||
unsigned loff = reg->sb_to_idx(lsb);
|
||||
unsigned moff = reg->sb_to_idx(msb);
|
||||
unsigned wid = moff - loff + 1;
|
||||
|
||||
if (moff < loff) {
|
||||
cerr << get_fileline() << ": error: part select "
|
||||
<< reg->name() << "[" << msb<<":"<<lsb<<"]"
|
||||
<< " is reversed." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If the part select extends beyond the extreme of the
|
||||
variable, then report an error. Note that loff is
|
||||
converted to normalized form so is relative the
|
||||
variable pins. */
|
||||
|
||||
if ((wid + loff) > reg->vector_width()) {
|
||||
cerr << get_fileline() << ": error: bit/part select "
|
||||
<< reg->name() << "[" << msb<<":"<<lsb<<"]"
|
||||
<< " is out of range." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
lv = new NetAssign_(reg);
|
||||
lv->set_part(new NetEConst(verinum(loff)), wid);
|
||||
}
|
||||
/* No select expressions. */
|
||||
|
||||
NetAssign_*lv = new NetAssign_(reg);
|
||||
|
||||
return lv;
|
||||
}
|
||||
@@ -374,10 +291,67 @@ NetAssign_* PEIdent::elaborate_lval_net_word_(Design*des,
|
||||
return lv;
|
||||
}
|
||||
|
||||
bool PEIdent::elaborate_lval_net_bit_(Design*des,
|
||||
NetScope*scope,
|
||||
NetAssign_*lv) const
|
||||
{
|
||||
const name_component_t&name_tail = path_.back();
|
||||
const index_component_t&index_tail = name_tail.index.back();
|
||||
ivl_assert(*this, index_tail.msb != 0);
|
||||
ivl_assert(*this, index_tail.lsb == 0);
|
||||
|
||||
NetNet*reg = lv->sig();
|
||||
|
||||
// Bit selects have a single select expression. Evaluate the
|
||||
// constant value and treat it as a part select with a bit
|
||||
// width of 1.
|
||||
NetExpr*mux = elab_and_eval(des, scope, index_tail.msb, -1);
|
||||
long lsb = 0;
|
||||
|
||||
if (NetEConst*index_con = dynamic_cast<NetEConst*> (mux)) {
|
||||
lsb = index_con->value().as_long();
|
||||
mux = 0;
|
||||
}
|
||||
|
||||
if (mux) {
|
||||
// Non-constant bit mux. Correct the mux for the range
|
||||
// of the vector, then set the l-value part select expression.
|
||||
if (reg->msb() < reg->lsb())
|
||||
mux = make_sub_expr(reg->lsb(), mux);
|
||||
else if (reg->lsb() != 0)
|
||||
mux = make_add_expr(mux, - reg->lsb());
|
||||
|
||||
lv->set_part(mux, 1);
|
||||
|
||||
} else if (lsb == reg->msb() && lsb == reg->lsb()) {
|
||||
// Constant bit mux that happens to select the only bit
|
||||
// of the l-value. Don't bother with any select at all.
|
||||
|
||||
} else {
|
||||
// Constant bit select that does something useful.
|
||||
long loff = reg->sb_to_idx(lsb);
|
||||
|
||||
if (loff < 0 || loff >= (long)reg->vector_width()) {
|
||||
cerr << get_fileline() << ": error: bit select "
|
||||
<< reg->name() << "[" <<lsb<<"]"
|
||||
<< " is out of range." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
lv->set_part(new NetEConst(verinum(loff)), 1);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PEIdent::elaborate_lval_net_part_(Design*des,
|
||||
NetScope*scope,
|
||||
NetAssign_*lv) const
|
||||
{
|
||||
// The range expressions of a part select must be
|
||||
// constant. The calculate_parts_ function calculates the
|
||||
// values into msb and lsb.
|
||||
long msb, lsb;
|
||||
bool flag = calculate_parts_(des, scope, msb, lsb);
|
||||
if (!flag)
|
||||
@@ -388,17 +362,14 @@ bool PEIdent::elaborate_lval_net_part_(Design*des,
|
||||
|
||||
if (msb == reg->msb() && lsb == reg->lsb()) {
|
||||
|
||||
/* No bit select, and part select covers the entire
|
||||
vector. Simplest case. */
|
||||
/* Part select covers the entire vector. Simplest case. */
|
||||
|
||||
} else {
|
||||
|
||||
/* If the bit/part select is constant, then make the
|
||||
NetAssign_ only as wide as it needs to be and connect
|
||||
only to the selected bits of the reg. */
|
||||
unsigned loff = reg->sb_to_idx(lsb);
|
||||
unsigned moff = reg->sb_to_idx(msb);
|
||||
unsigned wid = moff - loff + 1;
|
||||
/* Get the canonical offsets into the vector. */
|
||||
long loff = reg->sb_to_idx(lsb);
|
||||
long moff = reg->sb_to_idx(msb);
|
||||
long wid = moff - loff + 1;
|
||||
|
||||
if (moff < loff) {
|
||||
cerr << get_fileline() << ": error: part select "
|
||||
@@ -408,17 +379,15 @@ bool PEIdent::elaborate_lval_net_part_(Design*des,
|
||||
return false;
|
||||
}
|
||||
|
||||
/* If the part select extends beyond the extreme of the
|
||||
/* If the part select extends beyond the extremes of the
|
||||
variable, then report an error. Note that loff is
|
||||
converted to normalized form so is relative the
|
||||
variable pins. */
|
||||
|
||||
if ((wid + loff) > reg->vector_width()) {
|
||||
cerr << get_fileline() << ": error: bit/part select "
|
||||
if (loff < 0 || moff >= (signed)reg->vector_width()) {
|
||||
cerr << get_fileline() << ": warning: Part select "
|
||||
<< reg->name() << "[" << msb<<":"<<lsb<<"]"
|
||||
<< " is out of range." << endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
lv->set_part(new NetEConst(verinum(loff)), wid);
|
||||
|
||||
+52
-3097
File diff suppressed because it is too large
Load Diff
+174
-3
@@ -57,6 +57,52 @@ NetExpr*PEBinary::elaborate_pexpr (Design*des, NetScope*scope) const
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetExpr*PEBComp::elaborate_pexpr(Design*des, NetScope*scope) const
|
||||
{
|
||||
NetExpr*lp = left_->elaborate_pexpr(des, scope);
|
||||
NetExpr*rp = right_->elaborate_pexpr(des, scope);
|
||||
if ((lp == 0) || (rp == 0)) {
|
||||
delete lp;
|
||||
delete rp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
suppress_binary_operand_sign_if_needed_(lp, rp);
|
||||
|
||||
NetEBComp*tmp = new NetEBComp(op_, lp, rp);
|
||||
tmp->set_line(*this);
|
||||
bool flag = tmp->set_width(1);
|
||||
if (flag == false) {
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
"expression bit width of comparison != 1." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetExpr*PEBLogic::elaborate_pexpr(Design*des, NetScope*scope) const
|
||||
{
|
||||
NetExpr*lp = left_->elaborate_pexpr(des, scope);
|
||||
NetExpr*rp = right_->elaborate_pexpr(des, scope);
|
||||
if ((lp == 0) || (rp == 0)) {
|
||||
delete lp;
|
||||
delete rp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetEBLogic*tmp = new NetEBLogic(op_, lp, rp);
|
||||
tmp->set_line(*this);
|
||||
bool flag = tmp->set_width(1);
|
||||
if (flag == false) {
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
"expression bit width of comparison != 1." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Event though parameters are not generally sized, parameter
|
||||
* expressions can include concatenation expressions. This requires
|
||||
@@ -132,13 +178,13 @@ NetExpr*PEFNumber::elaborate_pexpr(Design*des, NetScope*scope) const
|
||||
*/
|
||||
NetExpr*PEIdent::elaborate_pexpr(Design*des, NetScope*scope) const
|
||||
{
|
||||
pform_name_t path = path_;
|
||||
pform_name_t oldpath = path_;
|
||||
name_component_t name_tail = path_.back();
|
||||
path.pop_back();
|
||||
oldpath.pop_back();
|
||||
|
||||
NetScope*pscope = scope;
|
||||
if (path_.size() > 0) {
|
||||
list<hname_t> tmp = eval_scope_path(des, scope, path);
|
||||
list<hname_t> tmp = eval_scope_path(des, scope, oldpath);
|
||||
pscope = des->find_scope(scope, tmp);
|
||||
}
|
||||
|
||||
@@ -267,3 +313,128 @@ NetExpr*PEUnary::elaborate_pexpr (Design*des, NetScope*scope) const
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetExpr* PECallFunction::elaborate_pexpr(Design*des, NetScope*scope) const
|
||||
{
|
||||
/* Only $clog2 and the builtin mathematical functions can
|
||||
* be a constant system function. */
|
||||
perm_string nm = peek_tail_name(path_);
|
||||
if (nm[0] == '$' && (generation_flag >= GN_VER2005 ||
|
||||
gn_icarus_misc_flag || gn_verilog_ams_flag)) {
|
||||
if (nm == "$clog2" ||
|
||||
nm == "$ln" ||
|
||||
nm == "$log10" ||
|
||||
nm == "$exp" ||
|
||||
nm == "$sqrt" ||
|
||||
nm == "$floor" ||
|
||||
nm == "$ceil" ||
|
||||
nm == "$sin" ||
|
||||
nm == "$cos" ||
|
||||
nm == "$tan" ||
|
||||
nm == "$asin" ||
|
||||
nm == "$acos" ||
|
||||
nm == "$atan" ||
|
||||
nm == "$sinh" ||
|
||||
nm == "$cosh" ||
|
||||
nm == "$tanh" ||
|
||||
nm == "$asinh" ||
|
||||
nm == "$acosh" ||
|
||||
nm == "$atanh") {
|
||||
if (parms_.size() != 1 || parms_[0] == 0) {
|
||||
cerr << get_fileline() << ": error: " << nm
|
||||
<< " takes a single argument." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
NetExpr*arg = parms_[0]->elaborate_pexpr(des, scope);
|
||||
if (arg == 0) return 0;
|
||||
NetESFunc*rtn;
|
||||
if (nm == "$clog2") {
|
||||
rtn = new NetESFunc(nm, IVL_VT_BOOL, integer_width, 1);
|
||||
} else {
|
||||
rtn = new NetESFunc(nm, IVL_VT_REAL, 1, 1);
|
||||
}
|
||||
rtn->set_line(*this);
|
||||
rtn->cast_signed(true);
|
||||
rtn->parm(0, arg);
|
||||
return rtn;
|
||||
}
|
||||
|
||||
if (nm == "$pow" ||
|
||||
nm == "$atan2" ||
|
||||
nm == "$hypot") {
|
||||
if (parms_.size() != 2 || parms_[0] == 0 || parms_[1] == 0) {
|
||||
cerr << get_fileline() << ": error: " << nm
|
||||
<< " takes two arguments." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
NetExpr*arg0 = parms_[0]->elaborate_pexpr(des, scope);
|
||||
NetExpr*arg1 = parms_[1]->elaborate_pexpr(des, scope);
|
||||
if (arg0 == 0 || arg1 == 0) return 0;
|
||||
NetESFunc*rtn = new NetESFunc(nm, IVL_VT_REAL, 1, 2);
|
||||
rtn->set_line(*this);
|
||||
rtn->cast_signed(true);
|
||||
rtn->parm(0, arg0);
|
||||
rtn->parm(1, arg1);
|
||||
return rtn;
|
||||
}
|
||||
|
||||
/* These are only available with verilog-ams or icarus-misc. */
|
||||
if ((gn_icarus_misc_flag || gn_verilog_ams_flag) &&
|
||||
(nm == "$log" || nm == "$abs")) {
|
||||
if (parms_.size() != 1 || parms_[0] == 0) {
|
||||
cerr << get_fileline() << ": error: " << nm
|
||||
<< " takes a single argument." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
NetExpr*arg = parms_[0]->elaborate_pexpr(des, scope);
|
||||
if (arg == 0) return 0;
|
||||
NetESFunc*rtn;
|
||||
if (nm == "$log") {
|
||||
rtn = new NetESFunc(nm, IVL_VT_REAL, 1, 1);
|
||||
} else {
|
||||
/* This can return either a real or an arbitrary
|
||||
* width vector, so set things to fail if this
|
||||
* does not get replaced with a constant during
|
||||
* elaboration. */
|
||||
rtn = new NetESFunc(nm, IVL_VT_NO_TYPE, 0, 1);
|
||||
}
|
||||
rtn->set_line(*this);
|
||||
rtn->cast_signed(true);
|
||||
rtn->parm(0, arg);
|
||||
return rtn;
|
||||
}
|
||||
if ((gn_icarus_misc_flag || gn_verilog_ams_flag) &&
|
||||
(nm == "$min" || nm == "$max")) {
|
||||
if (parms_.size() != 2 || parms_[0] == 0 || parms_[1] == 0) {
|
||||
cerr << get_fileline() << ": error: " << nm
|
||||
<< " takes two arguments." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
NetExpr*arg0 = parms_[0]->elaborate_pexpr(des, scope);
|
||||
NetExpr*arg1 = parms_[1]->elaborate_pexpr(des, scope);
|
||||
if (arg0 == 0 || arg1 == 0) return 0;
|
||||
/* See $log above for why this has no type or width. */
|
||||
NetESFunc*rtn = new NetESFunc(nm, IVL_VT_NO_TYPE, 0, 2);
|
||||
rtn->set_line(*this);
|
||||
rtn->cast_signed(true);
|
||||
rtn->parm(0, arg0);
|
||||
rtn->parm(1, arg1);
|
||||
return rtn;
|
||||
}
|
||||
|
||||
cerr << get_fileline() << ": error: this is not a constant "
|
||||
"system function (" << *this << ")." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Constant user function code goes here. */
|
||||
cerr << get_fileline() << ": sorry: constant user functions are not "
|
||||
"currently supported." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
+448
-159
@@ -40,20 +40,55 @@
|
||||
# include "PTask.h"
|
||||
# include "PWire.h"
|
||||
# include "Statement.h"
|
||||
# include "AStatement.h"
|
||||
# include "netlist.h"
|
||||
# include "util.h"
|
||||
# include <typeinfo>
|
||||
# include <assert.h>
|
||||
# include "ivl_assert.h"
|
||||
|
||||
void Module::elaborate_parm_item_(perm_string name, const param_expr_t&cur,
|
||||
Design*des, NetScope*scope)
|
||||
typedef map<perm_string,LexicalScope::param_expr_t>::const_iterator mparm_it_t;
|
||||
|
||||
static void collect_scope_parameters_(NetScope*scope,
|
||||
const map<perm_string,LexicalScope::param_expr_t>¶meters)
|
||||
{
|
||||
for (mparm_it_t cur = parameters.begin()
|
||||
; cur != parameters.end() ; cur ++) {
|
||||
|
||||
NetEParam*tmp = new NetEParam;
|
||||
tmp->set_line(*((*cur).second.expr));
|
||||
tmp->cast_signed( (*cur).second.signed_flag );
|
||||
|
||||
scope->set_parameter((*cur).first, tmp, (*cur).second.type,
|
||||
0, 0, false, 0, (*cur).second);
|
||||
}
|
||||
}
|
||||
|
||||
static void collect_scope_localparams_(NetScope*scope,
|
||||
const map<perm_string,LexicalScope::param_expr_t>&localparams)
|
||||
{
|
||||
for (mparm_it_t cur = localparams.begin()
|
||||
; cur != localparams.end() ; cur ++) {
|
||||
|
||||
NetEParam*tmp = new NetEParam;
|
||||
tmp->set_line(*((*cur).second.expr));
|
||||
if ((*cur).second.msb)
|
||||
tmp->cast_signed( (*cur).second.signed_flag );
|
||||
|
||||
scope->set_parameter((*cur).first, tmp, (*cur).second.type,
|
||||
0, 0, false, 0, (*cur).second);
|
||||
}
|
||||
}
|
||||
|
||||
static void elaborate_parm_item_(perm_string name,
|
||||
const LexicalScope::param_expr_t&cur,
|
||||
Design*des, NetScope*scope)
|
||||
{
|
||||
PExpr*ex = cur.expr;
|
||||
assert(ex);
|
||||
|
||||
NetExpr*val = ex->elaborate_pexpr(des, scope);
|
||||
if (val == 0) return;
|
||||
|
||||
NetExpr*msb = 0;
|
||||
NetExpr*lsb = 0;
|
||||
bool signed_flag = cur.signed_flag;
|
||||
@@ -71,21 +106,8 @@ void Module::elaborate_parm_item_(perm_string name, const param_expr_t&cur,
|
||||
assert(lsb);
|
||||
}
|
||||
|
||||
if (signed_flag) {
|
||||
/* If explicitly signed, then say so. */
|
||||
val->cast_signed(true);
|
||||
} else if (cur.msb) {
|
||||
/* If there is a range, then the signedness comes
|
||||
from the type and not the expression. */
|
||||
val->cast_signed(signed_flag);
|
||||
} else {
|
||||
/* otherwise, let the expression describe
|
||||
itself. */
|
||||
signed_flag = val->has_sign();
|
||||
}
|
||||
|
||||
NetScope::range_t*range_list = 0;
|
||||
for (Module::range_t*range = cur.range ; range ; range = range->next) {
|
||||
for (LexicalScope::range_t*range = cur.range ; range ; range = range->next) {
|
||||
NetScope::range_t*tmp = new NetScope::range_t;
|
||||
tmp->exclude_flag = range->exclude_flag;
|
||||
tmp->low_open_flag = range->low_open_flag;
|
||||
@@ -118,13 +140,186 @@ void Module::elaborate_parm_item_(perm_string name, const param_expr_t&cur,
|
||||
range_list = tmp;
|
||||
}
|
||||
|
||||
val = scope->set_parameter(name, val, cur.type, msb, lsb, signed_flag, range_list, cur);
|
||||
assert(val);
|
||||
/* Set the parameter expression to 0 if the evaluation failed. */
|
||||
if (val == 0) {
|
||||
val = scope->set_parameter(name, val, cur.type, msb, lsb,
|
||||
signed_flag, range_list, cur);
|
||||
delete val;
|
||||
return;
|
||||
}
|
||||
|
||||
if (signed_flag) {
|
||||
/* If explicitly signed, then say so. */
|
||||
val->cast_signed(true);
|
||||
} else if (cur.msb) {
|
||||
/* If there is a range, then the signedness comes
|
||||
from the type and not the expression. */
|
||||
val->cast_signed(signed_flag);
|
||||
} else {
|
||||
/* otherwise, let the expression describe
|
||||
itself. */
|
||||
signed_flag = val->has_sign();
|
||||
}
|
||||
|
||||
val = scope->set_parameter(name, val, cur.type, msb, lsb, signed_flag,
|
||||
range_list, cur);
|
||||
delete val;
|
||||
}
|
||||
|
||||
static void elaborate_scope_parameters_(Design*des, NetScope*scope,
|
||||
const map<perm_string,LexicalScope::param_expr_t>¶meters)
|
||||
{
|
||||
for (mparm_it_t cur = parameters.begin()
|
||||
; cur != parameters.end() ; cur ++) {
|
||||
|
||||
elaborate_parm_item_((*cur).first, (*cur).second, des, scope);
|
||||
}
|
||||
}
|
||||
|
||||
static void elaborate_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 ++) {
|
||||
|
||||
elaborate_parm_item_((*cur).first, (*cur).second, des, scope);
|
||||
}
|
||||
}
|
||||
|
||||
static void replace_scope_parameters_(NetScope*scope, const LineInfo&loc,
|
||||
const Module::replace_t&replacements)
|
||||
{
|
||||
for (Module::replace_t::const_iterator cur = replacements.begin()
|
||||
; cur != replacements.end() ; cur ++) {
|
||||
|
||||
NetExpr*val = (*cur).second;
|
||||
if (val == 0) {
|
||||
cerr << loc.get_fileline() << ": internal error: "
|
||||
<< "Missing expression in parameter replacement for "
|
||||
<< (*cur).first;
|
||||
}
|
||||
assert(val);
|
||||
if (debug_scopes) {
|
||||
cerr << loc.get_fileline() << ": debug: "
|
||||
<< "Replace " << (*cur).first
|
||||
<< " with expression " << *val
|
||||
<< " from " << val->get_fileline() << "." << endl;
|
||||
cerr << loc.get_fileline() << ": : "
|
||||
<< "Type=" << val->expr_type() << endl;
|
||||
}
|
||||
bool flag = scope->replace_parameter((*cur).first, val);
|
||||
if (! flag) {
|
||||
cerr << val->get_fileline() << ": warning: parameter "
|
||||
<< (*cur).first << " not found in "
|
||||
<< scope_path(scope) << "." << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void elaborate_scope_events_(Design*des, NetScope*scope,
|
||||
const map<perm_string,PEvent*>&events)
|
||||
{
|
||||
for (map<perm_string,PEvent*>::const_iterator et = events.begin()
|
||||
; et != events.end() ; et ++ ) {
|
||||
|
||||
(*et).second->elaborate_scope(des, scope);
|
||||
}
|
||||
}
|
||||
|
||||
static void elaborate_scope_tasks(Design*des, NetScope*scope,
|
||||
const LineInfo&loc,
|
||||
const map<perm_string,PTask*>&tasks)
|
||||
{
|
||||
typedef map<perm_string,PTask*>::const_iterator tasks_it_t;
|
||||
|
||||
for (tasks_it_t cur = tasks.begin()
|
||||
; cur != tasks.end() ; cur ++ ) {
|
||||
|
||||
hname_t use_name( (*cur).first );
|
||||
if (scope->child(use_name)) {
|
||||
cerr << loc.get_fileline() << ": error: task/scope name "
|
||||
<< use_name << " already used in this context."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
}
|
||||
NetScope*task_scope = new NetScope(scope, use_name,
|
||||
NetScope::TASK);
|
||||
task_scope->is_auto((*cur).second->is_auto());
|
||||
task_scope->set_line((*cur).second);
|
||||
|
||||
if (debug_scopes)
|
||||
cerr << cur->second->get_fileline() << ": debug: "
|
||||
<< "Elaborate task scope " << scope_path(task_scope) << endl;
|
||||
(*cur).second->elaborate_scope(des, task_scope);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void elaborate_scope_funcs(Design*des, NetScope*scope,
|
||||
const LineInfo&loc,
|
||||
const map<perm_string,PFunction*>&funcs)
|
||||
{
|
||||
typedef map<perm_string,PFunction*>::const_iterator funcs_it_t;
|
||||
|
||||
for (funcs_it_t cur = funcs.begin()
|
||||
; cur != funcs.end() ; cur ++ ) {
|
||||
|
||||
hname_t use_name( (*cur).first );
|
||||
if (scope->child(use_name)) {
|
||||
cerr << loc.get_fileline() << ": error: function/scope name "
|
||||
<< use_name << " already used in this context."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
}
|
||||
NetScope*func_scope = new NetScope(scope, use_name,
|
||||
NetScope::FUNC);
|
||||
func_scope->is_auto((*cur).second->is_auto());
|
||||
func_scope->set_line((*cur).second);
|
||||
|
||||
if (debug_scopes)
|
||||
cerr << cur->second->get_fileline() << ": debug: "
|
||||
<< "Elaborate function scope " << scope_path(func_scope) << endl;
|
||||
(*cur).second->elaborate_scope(des, func_scope);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class generate_schemes_work_item_t : public elaborator_work_item_t {
|
||||
public:
|
||||
generate_schemes_work_item_t(Design*des__, NetScope*scope, Module*mod)
|
||||
: elaborator_work_item_t(des__), scope_(scope), mod_(mod)
|
||||
{ }
|
||||
|
||||
void elaborate_runrun()
|
||||
{
|
||||
if (debug_scopes)
|
||||
cerr << mod_->get_fileline() << ": debug: "
|
||||
<< "Processing generate schemes for "
|
||||
<< scope_path(scope_) << endl;
|
||||
|
||||
// Generate schemes can create new scopes in the form of
|
||||
// generated code. Scan the generate schemes, and *generate*
|
||||
// new scopes, which is slightly different from simple
|
||||
// elaboration.
|
||||
typedef list<PGenerate*>::const_iterator generate_it_t;
|
||||
for (generate_it_t cur = mod_->generate_schemes.begin()
|
||||
; cur != mod_->generate_schemes.end() ; cur ++ ) {
|
||||
(*cur) -> generate_scope(des, scope_);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
// The scope_ is the scope that contains the generate scheme
|
||||
// we are to work on. the mod_ is the Module definition for
|
||||
// that scope, and contains the parsed generate schemes.
|
||||
NetScope*scope_;
|
||||
Module*mod_;
|
||||
};
|
||||
|
||||
bool Module::elaborate_scope(Design*des, NetScope*scope,
|
||||
const replace_t&replacements) const
|
||||
const replace_t&replacements)
|
||||
{
|
||||
if (debug_scopes) {
|
||||
cerr << get_fileline() << ": debug: Elaborate scope "
|
||||
@@ -142,81 +337,25 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
|
||||
// the pform and just place a NetEParam placeholder in the
|
||||
// place of the elaborated expression.
|
||||
|
||||
typedef map<perm_string,param_expr_t>::const_iterator mparm_it_t;
|
||||
typedef map<pform_name_t,PExpr*>::const_iterator pform_parm_it_t;
|
||||
// Scan the parameters in the module, and create stub parameter
|
||||
// entries in the scope for the parameter names.
|
||||
|
||||
collect_scope_parameters_(scope, parameters);
|
||||
|
||||
// This loop scans the parameters in the module, and creates
|
||||
// stub parameter entries in the scope for the parameter name.
|
||||
|
||||
for (mparm_it_t cur = parameters.begin()
|
||||
; cur != parameters.end() ; cur ++) {
|
||||
|
||||
NetEParam*tmp = new NetEParam;
|
||||
tmp->set_line(*((*cur).second.expr));
|
||||
tmp->cast_signed( (*cur).second.signed_flag );
|
||||
|
||||
scope->set_parameter((*cur).first, tmp, (*cur).second.type,
|
||||
0, 0, false, 0, (*cur).second);
|
||||
}
|
||||
|
||||
for (mparm_it_t cur = localparams.begin()
|
||||
; cur != localparams.end() ; cur ++) {
|
||||
|
||||
NetEParam*tmp = new NetEParam;
|
||||
tmp->set_line(*((*cur).second.expr));
|
||||
if ((*cur).second.msb)
|
||||
tmp->cast_signed( (*cur).second.signed_flag );
|
||||
|
||||
scope->set_parameter((*cur).first, tmp, (*cur).second.type,
|
||||
0, 0, false, 0, (*cur).second);
|
||||
}
|
||||
|
||||
collect_scope_localparams_(scope, localparams);
|
||||
|
||||
// Now scan the parameters again, this time elaborating them
|
||||
// for use as parameter values. This is after the previous
|
||||
// scan so that local parameter names can be used in the
|
||||
// r-value expressions.
|
||||
|
||||
for (mparm_it_t cur = parameters.begin()
|
||||
; cur != parameters.end() ; cur ++) {
|
||||
|
||||
elaborate_parm_item_((*cur).first, (*cur).second, des, scope);
|
||||
}
|
||||
elaborate_scope_parameters_(des, scope, parameters);
|
||||
|
||||
/* run parameter replacements that were collected from the
|
||||
containing scope and meant for me. */
|
||||
for (replace_t::const_iterator cur = replacements.begin()
|
||||
; cur != replacements.end() ; cur ++) {
|
||||
replace_scope_parameters_(scope, *this, replacements);
|
||||
|
||||
NetExpr*val = (*cur).second;
|
||||
if (val == 0) {
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<< "Missing expression in parameter replacement for "
|
||||
<< (*cur).first;
|
||||
}
|
||||
assert(val);
|
||||
if (debug_scopes) {
|
||||
cerr << get_fileline() << ": debug: "
|
||||
<< "Replace " << (*cur).first
|
||||
<< " with expression " << *val
|
||||
<< " from " << val->get_fileline() << "." << endl;
|
||||
cerr << get_fileline() << ": : "
|
||||
<< "Type=" << val->expr_type() << endl;
|
||||
}
|
||||
bool flag = scope->replace_parameter((*cur).first, val);
|
||||
if (! flag) {
|
||||
cerr << val->get_fileline() << ": warning: parameter "
|
||||
<< (*cur).first << " not found in "
|
||||
<< scope_path(scope) << "." << endl;
|
||||
}
|
||||
}
|
||||
|
||||
for (mparm_it_t cur = localparams.begin()
|
||||
; cur != localparams.end() ; cur ++) {
|
||||
|
||||
elaborate_parm_item_((*cur).first, (*cur).second, des, scope);
|
||||
}
|
||||
elaborate_scope_localparams_(des, scope, localparams);
|
||||
|
||||
// Run through the defparams for this module, elaborate the
|
||||
// expressions in this context and save the result is a table
|
||||
@@ -228,15 +367,17 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
|
||||
// here because the parameter receiving the assignment may be
|
||||
// in a scope not discovered by this pass.
|
||||
|
||||
for (pform_parm_it_t cur = defparms.begin()
|
||||
; cur != defparms.end() ; cur ++ ) {
|
||||
typedef list<Module::named_expr_t>::const_iterator defparms_iter_t;
|
||||
for (defparms_iter_t cur = defparms.begin()
|
||||
; cur != defparms.end() ; cur ++) {
|
||||
|
||||
PExpr*ex = (*cur).second;
|
||||
PExpr*ex = cur->second;
|
||||
assert(ex);
|
||||
|
||||
NetExpr*val = ex->elaborate_pexpr(des, scope);
|
||||
if (val == 0) continue;
|
||||
scope->defparams[(*cur).first] = val;
|
||||
|
||||
scope->defparams.push_back(make_pair(cur->first, val));
|
||||
}
|
||||
|
||||
// Evaluate the attributes. Evaluate them in the scope of the
|
||||
@@ -249,66 +390,29 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
|
||||
|
||||
delete[]attr;
|
||||
|
||||
// Generate schemes can create new scopes in the form of
|
||||
// generated code. Scan the generate schemes, and *generate*
|
||||
// new scopes, which is slightly different from simple
|
||||
// elaboration.
|
||||
|
||||
typedef list<PGenerate*>::const_iterator generate_it_t;
|
||||
for (generate_it_t cur = generate_schemes.begin()
|
||||
; cur != generate_schemes.end() ; cur ++ ) {
|
||||
(*cur) -> generate_scope(des, scope);
|
||||
}
|
||||
// Generate schemes need to have their scopes elaborated, but
|
||||
// we cannot do that until defparams are run, so push it off
|
||||
// into an elaborate work item.
|
||||
if (debug_scopes)
|
||||
cerr << get_fileline() << ": debug: "
|
||||
<< "Schedule generates within " << scope_path(scope)
|
||||
<< " for elaboration after defparams." << endl;
|
||||
|
||||
des->elaboration_work_list.push_back(new generate_schemes_work_item_t(des, scope, this));
|
||||
|
||||
// Tasks introduce new scopes, so scan the tasks in this
|
||||
// module. Create a scope for the task and pass that to the
|
||||
// elaborate_scope method of the PTask for detailed
|
||||
// processing.
|
||||
|
||||
typedef map<perm_string,PTask*>::const_iterator tasks_it_t;
|
||||
|
||||
for (tasks_it_t cur = tasks_.begin()
|
||||
; cur != tasks_.end() ; cur ++ ) {
|
||||
|
||||
hname_t use_name( (*cur).first );
|
||||
if (scope->child(use_name)) {
|
||||
cerr << get_fileline() << ": error: task/scope name "
|
||||
<< use_name << " already used in this context."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
}
|
||||
NetScope*task_scope = new NetScope(scope, use_name,
|
||||
NetScope::TASK);
|
||||
task_scope->set_line((*cur).second);
|
||||
(*cur).second->elaborate_scope(des, task_scope);
|
||||
}
|
||||
elaborate_scope_tasks(des, scope, *this, tasks);
|
||||
|
||||
|
||||
// Functions are very similar to tasks, at least from the
|
||||
// perspective of scopes. So handle them exactly the same
|
||||
// way.
|
||||
|
||||
typedef map<perm_string,PFunction*>::const_iterator funcs_it_t;
|
||||
|
||||
for (funcs_it_t cur = funcs_.begin()
|
||||
; cur != funcs_.end() ; cur ++ ) {
|
||||
|
||||
hname_t use_name( (*cur).first );
|
||||
if (scope->child(use_name)) {
|
||||
cerr << get_fileline() << ": error: function/scope name "
|
||||
<< use_name << " already used in this context."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
}
|
||||
NetScope*func_scope = new NetScope(scope, use_name,
|
||||
NetScope::FUNC);
|
||||
func_scope->set_line((*cur).second);
|
||||
(*cur).second->elaborate_scope(des, func_scope);
|
||||
}
|
||||
|
||||
elaborate_scope_funcs(des, scope, *this, funcs);
|
||||
|
||||
// Gates include modules, which might introduce new scopes, so
|
||||
// scan all of them to create those scopes.
|
||||
@@ -338,11 +442,7 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
|
||||
// elaboration, so do it now. This allows for normal
|
||||
// elaboration to reference these events.
|
||||
|
||||
for (map<perm_string,PEvent*>::const_iterator et = events.begin()
|
||||
; et != events.end() ; et ++ ) {
|
||||
|
||||
(*et).second->elaborate_scope(des, scope);
|
||||
}
|
||||
elaborate_scope_events_(des, scope, events);
|
||||
|
||||
return des->errors == 0;
|
||||
}
|
||||
@@ -361,7 +461,9 @@ bool PGenerate::generate_scope(Design*des, NetScope*container)
|
||||
|
||||
case GS_CASE:
|
||||
return generate_scope_case_(des, container);
|
||||
return true;
|
||||
|
||||
case GS_NBLOCK:
|
||||
return generate_scope_nblock_(des, container);
|
||||
|
||||
case GS_CASE_ITEM:
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
@@ -422,7 +524,12 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
|
||||
container->genvar_tmp_val = genvar;
|
||||
NetExpr*test_ex = elab_and_eval(des, container, loop_test, -1);
|
||||
NetEConst*test = dynamic_cast<NetEConst*>(test_ex);
|
||||
assert(test);
|
||||
if (test == 0) {
|
||||
cerr << get_fileline() << ": error: Cannot evaluate genvar"
|
||||
<< " conditional expression: " << *loop_test << endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
while (test->value().as_long()) {
|
||||
|
||||
// The actual name of the scope includes the genvar so
|
||||
@@ -469,7 +576,12 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
|
||||
// Calculate the step for the loop variable.
|
||||
NetExpr*step_ex = elab_and_eval(des, container, loop_step, -1);
|
||||
NetEConst*step = dynamic_cast<NetEConst*>(step_ex);
|
||||
assert(step);
|
||||
if (step == 0) {
|
||||
cerr << get_fileline() << ": error: Cannot evaluate genvar"
|
||||
<< " step expression: " << *loop_step << endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
if (debug_scopes)
|
||||
cerr << get_fileline() << ": debug: genvar step from "
|
||||
<< genvar << " to " << step->value().as_long() << endl;
|
||||
@@ -494,7 +606,12 @@ bool PGenerate::generate_scope_condit_(Design*des, NetScope*container, bool else
|
||||
{
|
||||
NetExpr*test_ex = elab_and_eval(des, container, loop_test, -1);
|
||||
NetEConst*test = dynamic_cast<NetEConst*> (test_ex);
|
||||
assert(test);
|
||||
if (test == 0) {
|
||||
cerr << get_fileline() << ": error: Cannot evaluate genvar"
|
||||
<< " conditional expression: " << *loop_test << endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the condition evaluates as false, then do not create the
|
||||
// scope.
|
||||
@@ -536,10 +653,12 @@ bool PGenerate::generate_scope_case_(Design*des, NetScope*container)
|
||||
{
|
||||
NetExpr*case_value_ex = elab_and_eval(des, container, loop_test, -1);
|
||||
NetEConst*case_value_co = dynamic_cast<NetEConst*>(case_value_ex);
|
||||
assert(case_value_co);
|
||||
|
||||
// The name of the scope to generate, whatever that item is.
|
||||
hname_t use_name (scope_name);
|
||||
if (case_value_co == 0) {
|
||||
cerr << get_fileline() << ": error: Cannot evaluate genvar case"
|
||||
<< " expression: " << *loop_test << endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (debug_scopes)
|
||||
cerr << get_fileline() << ": debug: Generate case "
|
||||
@@ -548,8 +667,8 @@ bool PGenerate::generate_scope_case_(Design*des, NetScope*container)
|
||||
PGenerate*default_item = 0;
|
||||
|
||||
typedef list<PGenerate*>::const_iterator generator_it_t;
|
||||
generator_it_t cur = generates.begin();
|
||||
while (cur != generates.end()) {
|
||||
generator_it_t cur = generate_schemes.begin();
|
||||
while (cur != generate_schemes.end()) {
|
||||
PGenerate*item = *cur;
|
||||
assert( item->scheme_type == PGenerate::GS_CASE_ITEM );
|
||||
|
||||
@@ -578,7 +697,7 @@ bool PGenerate::generate_scope_case_(Design*des, NetScope*container)
|
||||
delete case_value_co;
|
||||
case_value_co = 0;
|
||||
|
||||
PGenerate*item = (cur == generates.end())? default_item : *cur;
|
||||
PGenerate*item = (cur == generate_schemes.end())? default_item : *cur;
|
||||
if (item == 0) {
|
||||
cerr << get_fileline() << ": debug: "
|
||||
<< "No generate items found" << endl;
|
||||
@@ -590,6 +709,9 @@ bool PGenerate::generate_scope_case_(Design*des, NetScope*container)
|
||||
<< "Generate case matches item at "
|
||||
<< item->get_fileline() << endl;
|
||||
|
||||
// The name of the scope to generate, whatever that item is.
|
||||
hname_t use_name (item->scope_name);
|
||||
|
||||
NetScope*scope = new NetScope(container, use_name,
|
||||
NetScope::GENBLOCK);
|
||||
scope->set_line(get_file(), get_lineno());
|
||||
@@ -598,6 +720,29 @@ bool PGenerate::generate_scope_case_(Design*des, NetScope*container)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PGenerate::generate_scope_nblock_(Design*des, NetScope*container)
|
||||
{
|
||||
hname_t use_name (scope_name);
|
||||
if (container->child(use_name)) {
|
||||
cerr << get_fileline() << ": error: block/scope name "
|
||||
<< scope_name << " already used in this context."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
if (debug_scopes)
|
||||
cerr << get_fileline() << ": debug: Generate named block "
|
||||
<< ": Generate scope=" << use_name << endl;
|
||||
|
||||
NetScope*scope = new NetScope(container, use_name,
|
||||
NetScope::GENBLOCK);
|
||||
scope->set_line(get_file(), get_lineno());
|
||||
|
||||
elaborate_subscope_(des, scope);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PGenerate::elaborate_subscope_(Design*des, NetScope*scope)
|
||||
{
|
||||
// Scan the generated scope for nested generate schemes,
|
||||
@@ -605,11 +750,24 @@ void PGenerate::elaborate_subscope_(Design*des, NetScope*scope)
|
||||
// from simple elaboration.
|
||||
|
||||
typedef list<PGenerate*>::const_iterator generate_it_t;
|
||||
for (generate_it_t cur = generates.begin()
|
||||
; cur != generates.end() ; cur ++ ) {
|
||||
for (generate_it_t cur = generate_schemes.begin()
|
||||
; cur != generate_schemes.end() ; cur ++ ) {
|
||||
(*cur) -> generate_scope(des, scope);
|
||||
}
|
||||
|
||||
// Scan the localparams in this scope, and create stub parameter
|
||||
// entries in the scope for the parameter names.
|
||||
collect_scope_localparams_(scope, localparams);
|
||||
|
||||
// Now scan the localparams again, this time elaborating them
|
||||
// for use as parameter values.
|
||||
elaborate_scope_localparams_(des, scope, localparams);
|
||||
|
||||
// Scan through all the task and function declarations in this
|
||||
// scope.
|
||||
elaborate_scope_tasks(des, scope, *this, tasks);
|
||||
elaborate_scope_funcs(des, scope, *this, funcs);
|
||||
|
||||
// Scan the generated scope for gates that may create
|
||||
// their own scopes.
|
||||
typedef list<PGate*>::const_iterator pgate_list_it_t;
|
||||
@@ -618,10 +776,54 @@ void PGenerate::elaborate_subscope_(Design*des, NetScope*scope)
|
||||
(*cur) ->elaborate_scope(des, scope);
|
||||
}
|
||||
|
||||
typedef list<PProcess*>::const_iterator proc_it_t;
|
||||
for (proc_it_t cur = behaviors.begin()
|
||||
; cur != behaviors.end() ; cur ++ ) {
|
||||
(*cur) -> statement() -> elaborate_scope(des, scope);
|
||||
}
|
||||
|
||||
// Scan through all the named events in this scope.
|
||||
elaborate_scope_events_(des, scope, events);
|
||||
|
||||
// Save the scope that we created, for future use.
|
||||
scope_list_.push_back(scope);
|
||||
}
|
||||
|
||||
class delayed_elaborate_scope_mod_instances : public elaborator_work_item_t {
|
||||
|
||||
public:
|
||||
delayed_elaborate_scope_mod_instances(Design*des__,
|
||||
const PGModule*obj,
|
||||
Module*mod,
|
||||
NetScope*sc)
|
||||
: elaborator_work_item_t(des__), obj_(obj), mod_(mod), sc_(sc)
|
||||
{ }
|
||||
~delayed_elaborate_scope_mod_instances() { }
|
||||
|
||||
virtual void elaborate_runrun();
|
||||
|
||||
private:
|
||||
const PGModule*obj_;
|
||||
Module*mod_;
|
||||
NetScope*sc_;
|
||||
};
|
||||
|
||||
void delayed_elaborate_scope_mod_instances::elaborate_runrun()
|
||||
{
|
||||
if (debug_scopes)
|
||||
cerr << obj_->get_fileline() << ": debug: "
|
||||
<< "Resume scope elaboration of instances of "
|
||||
<< mod_->mod_name() << "." << endl;
|
||||
|
||||
obj_->elaborate_scope_mod_instances_(des, mod_, sc_);
|
||||
}
|
||||
|
||||
/*
|
||||
* Here we handle the elaborate scope of a module instance. The caller
|
||||
* has already figured out that this "gate" is a module, and has found
|
||||
* the module definition. The "sc" argument is the scope that will
|
||||
* contain this instance.
|
||||
*/
|
||||
void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
|
||||
{
|
||||
if (get_name() == "") {
|
||||
@@ -668,6 +870,36 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
|
||||
return;
|
||||
}
|
||||
|
||||
if (msb_ || lsb_) {
|
||||
// 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
|
||||
// elaboration until after defparams (above me) are
|
||||
// run. Do that by appending a work item to the
|
||||
// elaboration work list.
|
||||
if (debug_scopes)
|
||||
cerr << get_fileline() << ": debug: delay elaborate_scope"
|
||||
<< " of array of " << get_name()
|
||||
<< " in scope " << scope_path(sc) << "." << endl;
|
||||
|
||||
elaborator_work_item_t*tmp
|
||||
= new delayed_elaborate_scope_mod_instances(des, this, mod, sc);
|
||||
des->elaboration_work_list.push_back(tmp);
|
||||
|
||||
} else {
|
||||
// If there are no expressions that need to be evaluated
|
||||
// to elaborate the scope of this next instances, then
|
||||
// get right to it.
|
||||
elaborate_scope_mod_instances_(des, mod, sc);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This method is called to process a module instantiation after basic
|
||||
* sanity testing is already complete.
|
||||
*/
|
||||
void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*sc) const
|
||||
{
|
||||
NetExpr*mse = msb_ ? elab_and_eval(des, sc, msb_, -1) : 0;
|
||||
NetExpr*lse = lsb_ ? elab_and_eval(des, sc, lsb_, -1) : 0;
|
||||
NetEConst*msb = dynamic_cast<NetEConst*> (mse);
|
||||
@@ -755,16 +987,16 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
|
||||
assert(parms_ == 0);
|
||||
list<perm_string>::const_iterator cur
|
||||
= mod->param_names.begin();
|
||||
unsigned idx = 0;
|
||||
unsigned jdx = 0;
|
||||
for (;;) {
|
||||
if (idx >= overrides_->count())
|
||||
if (jdx >= overrides_->count())
|
||||
break;
|
||||
if (cur == mod->param_names.end())
|
||||
break;
|
||||
|
||||
replace[*cur] = (*overrides_)[idx];
|
||||
replace[*cur] = (*overrides_)[jdx];
|
||||
|
||||
idx += 1;
|
||||
jdx += 1;
|
||||
cur ++;
|
||||
}
|
||||
}
|
||||
@@ -773,8 +1005,8 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
|
||||
// so the mapping into the replace list is much easier.
|
||||
if (parms_) {
|
||||
assert(overrides_ == 0);
|
||||
for (unsigned idx = 0 ; idx < nparms_ ; idx += 1)
|
||||
replace[parms_[idx].name] = parms_[idx].parm;
|
||||
for (unsigned jdx = 0 ; jdx < nparms_ ; jdx += 1)
|
||||
replace[parms_[jdx].name] = parms_[jdx].parm;
|
||||
|
||||
}
|
||||
|
||||
@@ -834,6 +1066,25 @@ void PFunction::elaborate_scope(Design*des, NetScope*scope) const
|
||||
{
|
||||
assert(scope->type() == NetScope::FUNC);
|
||||
|
||||
// Scan the parameters in the function, and create stub parameter
|
||||
// entries in the scope for the parameter names.
|
||||
|
||||
collect_scope_parameters_(scope, parameters);
|
||||
|
||||
collect_scope_localparams_(scope, localparams);
|
||||
|
||||
// Now scan the parameters again, this time elaborating them
|
||||
// for use as parameter values. This is after the previous
|
||||
// scan so that local parameter names can be used in the
|
||||
// r-value expressions.
|
||||
|
||||
elaborate_scope_parameters_(des, scope, parameters);
|
||||
|
||||
elaborate_scope_localparams_(des, scope, localparams);
|
||||
|
||||
// Scan through all the named events in this scope.
|
||||
elaborate_scope_events_(des, scope, events);
|
||||
|
||||
if (statement_)
|
||||
statement_->elaborate_scope(des, scope);
|
||||
}
|
||||
@@ -842,6 +1093,25 @@ void PTask::elaborate_scope(Design*des, NetScope*scope) const
|
||||
{
|
||||
assert(scope->type() == NetScope::TASK);
|
||||
|
||||
// Scan the parameters in the task, and create stub parameter
|
||||
// entries in the scope for the parameter names.
|
||||
|
||||
collect_scope_parameters_(scope, parameters);
|
||||
|
||||
collect_scope_localparams_(scope, localparams);
|
||||
|
||||
// Now scan the parameters again, this time elaborating them
|
||||
// for use as parameter values. This is after the previous
|
||||
// scan so that local parameter names can be used in the
|
||||
// r-value expressions.
|
||||
|
||||
elaborate_scope_parameters_(des, scope, parameters);
|
||||
|
||||
elaborate_scope_localparams_(des, scope, localparams);
|
||||
|
||||
// Scan through all the named events in this scope.
|
||||
elaborate_scope_events_(des, scope, events);
|
||||
|
||||
if (statement_)
|
||||
statement_->elaborate_scope(des, scope);
|
||||
}
|
||||
@@ -878,11 +1148,30 @@ void PBlock::elaborate_scope(Design*des, NetScope*scope) const
|
||||
? NetScope::FORK_JOIN
|
||||
: NetScope::BEGIN_END);
|
||||
my_scope->set_line(get_file(), get_lineno());
|
||||
my_scope->is_auto(scope->is_auto());
|
||||
|
||||
// Scan the parameters in the scope, and create stub parameter
|
||||
// entries in the scope for the parameter names.
|
||||
|
||||
collect_scope_parameters_(my_scope, parameters);
|
||||
|
||||
collect_scope_localparams_(my_scope, localparams);
|
||||
|
||||
// Now scan the parameters again, this time elaborating them
|
||||
// for use as parameter values. This is after the previous
|
||||
// scan so that local parameter names can be used in the
|
||||
// r-value expressions.
|
||||
|
||||
elaborate_scope_parameters_(des, my_scope, parameters);
|
||||
|
||||
elaborate_scope_localparams_(des, my_scope, localparams);
|
||||
|
||||
// Scan through all the named events in this scope.
|
||||
elaborate_scope_events_(des, my_scope, events);
|
||||
}
|
||||
|
||||
for (unsigned idx = 0 ; idx < list_.count() ; idx += 1)
|
||||
list_[idx] -> elaborate_scope(des, my_scope);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+104
-61
@@ -108,13 +108,49 @@ bool PScope::elaborate_sig_wires_(Design*des, NetScope*scope) const
|
||||
return flag;
|
||||
}
|
||||
|
||||
static void elaborate_sig_funcs(Design*des, NetScope*scope,
|
||||
const map<perm_string,PFunction*>&funcs)
|
||||
{
|
||||
typedef map<perm_string,PFunction*>::const_iterator mfunc_it_t;
|
||||
|
||||
for (mfunc_it_t cur = funcs.begin()
|
||||
; cur != funcs.end() ; cur ++) {
|
||||
|
||||
hname_t use_name ( (*cur).first );
|
||||
NetScope*fscope = scope->child(use_name);
|
||||
if (scope == 0) {
|
||||
cerr << (*cur).second->get_fileline() << ": internal error: "
|
||||
<< "Child scope for function " << (*cur).first
|
||||
<< " missing in " << scope_path(scope) << "." << endl;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
(*cur).second->elaborate_sig(des, fscope);
|
||||
}
|
||||
}
|
||||
|
||||
static void elaborate_sig_tasks(Design*des, NetScope*scope,
|
||||
const map<perm_string,PTask*>&tasks)
|
||||
{
|
||||
typedef map<perm_string,PTask*>::const_iterator mtask_it_t;
|
||||
|
||||
for (mtask_it_t cur = tasks.begin()
|
||||
; cur != tasks.end() ; cur ++) {
|
||||
NetScope*tscope = scope->child( hname_t((*cur).first) );
|
||||
assert(tscope);
|
||||
(*cur).second->elaborate_sig(des, tscope);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Module::elaborate_sig(Design*des, NetScope*scope) const
|
||||
{
|
||||
bool flag = true;
|
||||
|
||||
// Scan all the ports of the module, and make sure that each
|
||||
// is connected to wires that have port declarations.
|
||||
for (unsigned idx = 0 ; idx < ports.count() ; idx += 1) {
|
||||
for (unsigned idx = 0 ; idx < ports.size() ; idx += 1) {
|
||||
Module::port_t*pp = ports[idx];
|
||||
if (pp == 0)
|
||||
continue;
|
||||
@@ -123,7 +159,7 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const
|
||||
// expression are all identifiers that should reference
|
||||
// wires within the scope.
|
||||
map<perm_string,PWire*>::const_iterator wt;
|
||||
for (unsigned cc = 0 ; cc < pp->expr.count() ; cc += 1) {
|
||||
for (unsigned cc = 0 ; cc < pp->expr.size() ; cc += 1) {
|
||||
pform_name_t port_path (pp->expr[cc]->path());
|
||||
// A concatenated wire of a port really should not
|
||||
// have any hierarchy.
|
||||
@@ -182,38 +218,12 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const
|
||||
flag &= (*gt)->elaborate_sig(des, scope);
|
||||
}
|
||||
|
||||
|
||||
typedef map<perm_string,PFunction*>::const_iterator mfunc_it_t;
|
||||
|
||||
for (mfunc_it_t cur = funcs_.begin()
|
||||
; cur != funcs_.end() ; cur ++) {
|
||||
|
||||
hname_t use_name ( (*cur).first );
|
||||
NetScope*fscope = scope->child(use_name);
|
||||
if (scope == 0) {
|
||||
cerr << (*cur).second->get_fileline() << ": internal error: "
|
||||
<< "Child scope for function " << (*cur).first
|
||||
<< " missing in " << scope_path(scope) << "." << endl;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
(*cur).second->elaborate_sig(des, fscope);
|
||||
}
|
||||
|
||||
|
||||
// After all the wires are elaborated, we are free to
|
||||
// elaborate the ports of the tasks defined within this
|
||||
// module. Run through them now.
|
||||
|
||||
typedef map<perm_string,PTask*>::const_iterator mtask_it_t;
|
||||
|
||||
for (mtask_it_t cur = tasks_.begin()
|
||||
; cur != tasks_.end() ; cur ++) {
|
||||
NetScope*tscope = scope->child( hname_t((*cur).first) );
|
||||
assert(tscope);
|
||||
(*cur).second->elaborate_sig(des, tscope);
|
||||
}
|
||||
elaborate_sig_funcs(des, scope, funcs);
|
||||
elaborate_sig_tasks(des, scope, tasks);
|
||||
|
||||
// initial and always blocks may contain begin-end and
|
||||
// fork-join blocks that can introduce scopes. Therefore, I
|
||||
@@ -256,7 +266,7 @@ bool PEIdent::elaborate_sig(Design*des, NetScope*scope) const
|
||||
if (error_implicit)
|
||||
return true;
|
||||
|
||||
symbol_search(des, scope, path_, sig, par, eve);
|
||||
symbol_search(this, des, scope, path_, sig, par, eve);
|
||||
|
||||
if (eve != 0)
|
||||
return false;
|
||||
@@ -351,11 +361,11 @@ bool PGModule::elaborate_sig_mod_(Design*des, NetScope*scope,
|
||||
continue;
|
||||
flag = tmp->elaborate_sig(des, scope) && flag;
|
||||
}
|
||||
|
||||
|
||||
|
||||
NetScope::scope_vec_t instance = scope->instance_arrays[get_name()];
|
||||
|
||||
for (unsigned idx = 0 ; idx < instance.count() ; idx += 1) {
|
||||
for (unsigned idx = 0 ; idx < instance.size() ; idx += 1) {
|
||||
// I know a priori that the elaborate_scope created the scope
|
||||
// already, so just look it up as a child of the current scope.
|
||||
NetScope*my_scope = instance[idx];
|
||||
@@ -415,8 +425,8 @@ bool PGenerate::elaborate_sig(Design*des, NetScope*container) const
|
||||
<< scope_path(container) << "." << endl;
|
||||
|
||||
typedef list<PGenerate*>::const_iterator generate_it_t;
|
||||
for (generate_it_t cur = generates.begin()
|
||||
; cur != generates.end() ; cur ++) {
|
||||
for (generate_it_t cur = generate_schemes.begin()
|
||||
; cur != generate_schemes.end() ; cur ++) {
|
||||
PGenerate*item = *cur;
|
||||
if (! item->scope_list_.empty()) {
|
||||
flag &= item->elaborate_sig(des, container);
|
||||
@@ -461,9 +471,12 @@ bool PGenerate::elaborate_sig_(Design*des, NetScope*scope) const
|
||||
cur->elaborate_sig(des, scope);
|
||||
}
|
||||
|
||||
elaborate_sig_funcs(des, scope, funcs);
|
||||
elaborate_sig_tasks(des, scope, tasks);
|
||||
|
||||
typedef list<PGenerate*>::const_iterator generate_it_t;
|
||||
for (generate_it_t cur = generates.begin()
|
||||
; cur != generates.end() ; cur ++ ) {
|
||||
for (generate_it_t cur = generate_schemes.begin()
|
||||
; cur != generate_schemes.end() ; cur ++ ) {
|
||||
(*cur) -> elaborate_sig(des, scope);
|
||||
}
|
||||
|
||||
@@ -576,9 +589,17 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
||||
break;
|
||||
|
||||
default:
|
||||
cerr << get_fileline() << ": internal error: I don't know how "
|
||||
<< "to deal with return type of function "
|
||||
<< scope->basename() << "." << endl;
|
||||
if (ports_) {
|
||||
cerr << get_fileline() << ": internal error: I don't know "
|
||||
<< "how to deal with return type of function "
|
||||
<< scope->basename() << "." << endl;
|
||||
} else {
|
||||
/* If we do not have any ports or a return type this
|
||||
* is probably a bad function definition. */
|
||||
cerr << get_fileline() << ": error: Bad definition for "
|
||||
<< "function " << scope->basename() << "?" << endl;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
svector<NetNet*>ports (ports_? ports_->count() : 0);
|
||||
@@ -792,16 +813,19 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
|
||||
if (port_set_ || net_set_) {
|
||||
long pmsb = 0, plsb = 0, nmsb = 0, nlsb = 0;
|
||||
bool bad_lsb = false, bad_msb = false;
|
||||
/* If they exist get the port definition MSB and LSB */
|
||||
if (port_set_ && port_msb_ != 0) {
|
||||
NetExpr*texpr = elab_and_eval(des, scope, port_msb_, -1);
|
||||
|
||||
if (! eval_as_long(pmsb, texpr)) {
|
||||
cerr << port_msb_->get_fileline() << ": error: "
|
||||
"Unable to evaluate MSB constant expression ``"
|
||||
<< *port_msb_ << "''." << endl;
|
||||
"Range expressions must be constant." << endl;
|
||||
cerr << port_msb_->get_fileline() << " : "
|
||||
"This MSB expression violates the rule: "
|
||||
<< *port_msb_ << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
bad_msb = true;
|
||||
}
|
||||
|
||||
delete texpr;
|
||||
@@ -810,10 +834,12 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
|
||||
if (! eval_as_long(plsb, texpr)) {
|
||||
cerr << port_lsb_->get_fileline() << ": error: "
|
||||
"Unable to evaluate LSB constant expression ``"
|
||||
<< *port_lsb_ << "''." << endl;
|
||||
"Range expressions must be constant." << endl;
|
||||
cerr << port_lsb_->get_fileline() << " : "
|
||||
"This LSB expression violates the rule: "
|
||||
<< *port_lsb_ << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
bad_lsb = true;
|
||||
}
|
||||
|
||||
delete texpr;
|
||||
@@ -825,15 +851,17 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
if (port_lsb_ == 0) assert(port_msb_ == 0);
|
||||
|
||||
/* If they exist get the net/etc. definition MSB and LSB */
|
||||
if (net_set_ && net_msb_ != 0) {
|
||||
if (net_set_ && net_msb_ != 0 && !bad_msb && !bad_lsb) {
|
||||
NetExpr*texpr = elab_and_eval(des, scope, net_msb_, -1);
|
||||
|
||||
if (! eval_as_long(nmsb, texpr)) {
|
||||
cerr << net_msb_->get_fileline() << ": error: "
|
||||
"Unable to evaluate MSB constant expression ``"
|
||||
<< *net_msb_ << "''." << endl;
|
||||
"Range expressions must be constant." << endl;
|
||||
cerr << net_msb_->get_fileline() << " : "
|
||||
"This MSB expression violates the rule: "
|
||||
<< *net_msb_ << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
bad_msb = true;
|
||||
}
|
||||
|
||||
delete texpr;
|
||||
@@ -842,10 +870,12 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
|
||||
if (! eval_as_long(nlsb, texpr)) {
|
||||
cerr << net_lsb_->get_fileline() << ": error: "
|
||||
"Unable to evaluate LSB constant expression ``"
|
||||
<< *net_lsb_ << "''." << endl;
|
||||
"Range expressions must be constant." << endl;
|
||||
cerr << net_lsb_->get_fileline() << " : "
|
||||
"This LSB expression violates the rule: "
|
||||
<< *net_lsb_ << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
bad_lsb = true;
|
||||
}
|
||||
|
||||
delete texpr;
|
||||
@@ -898,6 +928,10 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
}
|
||||
}
|
||||
|
||||
/* Attempt to recover from errors. */
|
||||
if (bad_lsb) nlsb = 0;
|
||||
if (bad_msb) nmsb = nlsb;
|
||||
|
||||
lsb = nlsb;
|
||||
msb = nmsb;
|
||||
if (nmsb > nlsb)
|
||||
@@ -942,16 +976,18 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
delete lexp;
|
||||
|
||||
if (!const_flag) {
|
||||
cerr << get_fileline() << ": internal error: The indices "
|
||||
cerr << get_fileline() << ": error: The indices "
|
||||
<< "are not constant for array ``"
|
||||
<< name_ << "''." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Attempt to recover from error, */
|
||||
array_s0 = 0;
|
||||
array_e0 = 0;
|
||||
} else {
|
||||
array_s0 = lval.as_long();
|
||||
array_e0 = rval.as_long();
|
||||
}
|
||||
array_dimensions = 1;
|
||||
array_s0 = lval.as_long();
|
||||
array_e0 = rval.as_long();
|
||||
}
|
||||
|
||||
/* If the net type is supply0 or supply1, replace it
|
||||
@@ -990,8 +1026,11 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: Create signal "
|
||||
<< wtype << " ["<<msb<<":"<<lsb<<"] " << name_
|
||||
<< " in scope " << scope_path(scope) << endl;
|
||||
<< wtype << " ["<<msb<<":"<<lsb<<"] " << name_;
|
||||
if (array_dimensions > 0) {
|
||||
cerr << " [" << array_s0 << ":" << array_e0 << "]" << endl;
|
||||
}
|
||||
cerr << " in scope " << scope_path(scope) << endl;
|
||||
}
|
||||
|
||||
|
||||
@@ -1016,6 +1055,10 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
sig->set_signed(get_signed());
|
||||
sig->set_isint(get_isint());
|
||||
|
||||
if (ivl_discipline_t dis = get_discipline()) {
|
||||
sig->set_discipline(dis);
|
||||
}
|
||||
|
||||
if (pull)
|
||||
connect(sig->pin(0), pull->pin(0));
|
||||
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (c) 2008 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# include "AStatement.h"
|
||||
|
||||
# include <cstdlib>
|
||||
# include <iostream>
|
||||
|
||||
+1173
-731
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (c) 2008 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# include "AStatement.h"
|
||||
# include "netlist.h"
|
||||
# include "netmisc.h"
|
||||
# include "util.h"
|
||||
|
||||
# include <typeinfo>
|
||||
|
||||
NetProc* AContrib::elaborate(Design*des, NetScope*scope) const
|
||||
{
|
||||
NetExpr*lval = elab_and_eval(des, scope, lval_, -1);
|
||||
NetExpr*rval = elab_and_eval(des, scope, rval_, -1);
|
||||
|
||||
NetContribution*st = new NetContribution(lval, rval);
|
||||
st->set_line(*this);
|
||||
return st;
|
||||
}
|
||||
|
||||
bool AProcess::elaborate(Design*des, NetScope*scope) const
|
||||
{
|
||||
NetProc*statement = statement_->elaborate(des, scope);
|
||||
if (statement == 0)
|
||||
return false;
|
||||
|
||||
NetAnalogTop*top = new NetAnalogTop(scope, type_, statement);
|
||||
|
||||
// Evaluate the attributes for this process, if there
|
||||
// are any. These attributes are to be attached to the
|
||||
// NetProcTop object.
|
||||
struct attrib_list_t*attrib_list = 0;
|
||||
unsigned attrib_list_n = 0;
|
||||
attrib_list = evaluate_attributes(attributes, attrib_list_n, des, scope);
|
||||
|
||||
for (unsigned adx = 0 ; adx < attrib_list_n ; adx += 1)
|
||||
top->attribute(attrib_list[adx].key,
|
||||
attrib_list[adx].val);
|
||||
|
||||
delete[]attrib_list;
|
||||
|
||||
top->set_line(*this);
|
||||
des->add_process(top);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -72,6 +72,16 @@ bool NetCaseCmp::emit_node(struct target_t*tgt) const
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetCastInt::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->lpm_cast_int(this);
|
||||
}
|
||||
|
||||
bool NetCastReal::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->lpm_cast_real(this);
|
||||
}
|
||||
|
||||
bool NetCLShift::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
tgt->lpm_clshift(this);
|
||||
@@ -180,16 +190,28 @@ bool NetProcTop::emit(struct target_t*tgt) const
|
||||
return tgt->process(this);
|
||||
}
|
||||
|
||||
bool NetAnalogTop::emit(struct target_t*tgt) const
|
||||
{
|
||||
cerr << get_fileline() << ": sorry: "
|
||||
<< "I don't know how to emit for analog processes." << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NetProc::emit_proc(struct target_t*tgt) const
|
||||
{
|
||||
cerr << "EMIT: Proc type? " << typeid(*this).name() << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NetAlloc::emit_proc(struct target_t*tgt) const
|
||||
{
|
||||
tgt->proc_alloc(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetAssign::emit_proc(struct target_t*tgt) const
|
||||
{
|
||||
tgt->proc_assign(this);
|
||||
return true;
|
||||
return tgt->proc_assign(this);
|
||||
}
|
||||
|
||||
bool NetAssignNB::emit_proc(struct target_t*tgt) const
|
||||
@@ -240,6 +262,12 @@ bool NetForever::emit_proc(struct target_t*tgt) const
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetFree::emit_proc(struct target_t*tgt) const
|
||||
{
|
||||
tgt->proc_free(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetPDelay::emit_proc(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->proc_delay(this);
|
||||
@@ -352,23 +380,20 @@ void NetScope::emit_scope(struct target_t*tgt) const
|
||||
for (NetScope*cur = sub_ ; cur ; cur = cur->sib_)
|
||||
cur->emit_scope(tgt);
|
||||
|
||||
if (signals_) {
|
||||
NetNet*cur = signals_->sig_next_;
|
||||
do {
|
||||
tgt->signal(cur);
|
||||
cur = cur->sig_next_;
|
||||
} while (cur != signals_->sig_next_);
|
||||
for (signals_map_iter_t cur = signals_map_.begin()
|
||||
; cur != signals_map_.end() ; cur ++) {
|
||||
tgt->signal(cur->second);
|
||||
}
|
||||
|
||||
/* Run the signals again, but this time to connect the
|
||||
delay paths. This is done as a second pass because
|
||||
the paths reference other signals that may be later
|
||||
in the list. We can do it here becase delay paths are
|
||||
always connected within the scope. */
|
||||
cur = signals_->sig_next_;
|
||||
do {
|
||||
tgt->signal_paths(cur);
|
||||
cur = cur->sig_next_;
|
||||
} while (cur != signals_->sig_next_);
|
||||
// Run the signals again, but this time to connect the
|
||||
// delay paths. This is done as a second pass because
|
||||
// the paths reference other signals that may be later
|
||||
// in the list. We can do it here because delay paths are
|
||||
// always connected within the scope.
|
||||
for (signals_map_iter_t cur = signals_map_.begin()
|
||||
; cur != signals_map_.end() ; cur ++) {
|
||||
|
||||
tgt->signal_paths(cur->second);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -438,6 +463,8 @@ int Design::emit(struct target_t*tgt) const
|
||||
bool proc_rc = true;
|
||||
for (const NetProcTop*idx = procs_ ; idx ; idx = idx->next_)
|
||||
proc_rc &= idx->emit(tgt);
|
||||
for (const NetAnalogTop*idx = aprocs_ ; idx ; idx = idx->next_)
|
||||
proc_rc &= idx->emit(tgt);
|
||||
|
||||
rc = tgt->end_design(this);
|
||||
|
||||
@@ -451,6 +478,11 @@ int Design::emit(struct target_t*tgt) const
|
||||
return rc;
|
||||
}
|
||||
|
||||
void NetEAccess::expr_scan(struct expr_scan_t*tgt) const
|
||||
{
|
||||
tgt->expr_access_func(this);
|
||||
}
|
||||
|
||||
void NetEBinary::expr_scan(struct expr_scan_t*tgt) const
|
||||
{
|
||||
tgt->expr_binary(this);
|
||||
@@ -526,17 +558,3 @@ void NetEUnary::expr_scan(struct expr_scan_t*tgt) const
|
||||
{
|
||||
tgt->expr_unary(this);
|
||||
}
|
||||
|
||||
int emit(const Design*des, const char*type)
|
||||
{
|
||||
for (unsigned idx = 0 ; target_table[idx] ; idx += 1) {
|
||||
const struct target*tgt = target_table[idx];
|
||||
if (strcmp(tgt->name, type) == 0)
|
||||
return des->emit(tgt->meth);
|
||||
|
||||
}
|
||||
|
||||
cerr << "error: Code generator type " << type
|
||||
<< " not found." << endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -185,7 +185,7 @@ verinum* PEIdent::eval_const(Design*des, NetScope*scope) const
|
||||
return new verinum(scope->genvar_tmp_val);
|
||||
}
|
||||
|
||||
symbol_search(des, scope, path_, net, expr, eve);
|
||||
symbol_search(this, des, scope, path_, net, expr, eve);
|
||||
|
||||
if (expr == 0)
|
||||
return 0;
|
||||
|
||||
+10
-6
@@ -53,14 +53,19 @@ 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;
|
||||
if (exp)
|
||||
verinum*tmp = 0;
|
||||
if (exp) {
|
||||
tmp = exp->eval_const(des, scope);
|
||||
else
|
||||
if (tmp == 0) {
|
||||
cerr << exp->get_fileline() << ": error: ``"
|
||||
<< *exp << "'' is not a constant expression."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
}
|
||||
if (tmp == 0)
|
||||
tmp = new verinum(1);
|
||||
|
||||
if (tmp == 0)
|
||||
cerr << "internal error: no result for " << *exp << endl;
|
||||
assert(tmp);
|
||||
|
||||
table[idx].val = *tmp;
|
||||
@@ -106,4 +111,3 @@ attrib_list_t* evaluate_attributes(const map<perm_string,PExpr*>&att,
|
||||
* of complex attributes attached to gates.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
+433
-54
@@ -22,6 +22,8 @@
|
||||
|
||||
# include <iostream>
|
||||
# include <cstdlib>
|
||||
# include <cstring>
|
||||
# include <math.h>
|
||||
|
||||
# include "netlist.h"
|
||||
# include "ivl_assert.h"
|
||||
@@ -131,6 +133,19 @@ NetExpr* NetEBAdd::eval_tree(int prune_to_width)
|
||||
verinum lval = lc->value();
|
||||
verinum rval = rc->value();
|
||||
|
||||
if (lval.len() < expr_width())
|
||||
lval = pad_to_width(lval, expr_width());
|
||||
if (rval.len() < expr_width())
|
||||
rval = pad_to_width(rval, expr_width());
|
||||
|
||||
if (se->expr_width() > this->expr_width()) {
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<< "expr_width()=" << expr_width()
|
||||
<< ", sub expr_width()=" << se->expr_width()
|
||||
<< ", sub expression=" << *se << endl;
|
||||
}
|
||||
ivl_assert(*this, se->expr_width() <= this->expr_width());
|
||||
|
||||
verinum val;
|
||||
if (op_ == se->op_) {
|
||||
/* (a + lval) + rval --> a + (rval+lval) */
|
||||
@@ -142,6 +157,15 @@ NetExpr* NetEBAdd::eval_tree(int prune_to_width)
|
||||
val = rval - lval;
|
||||
}
|
||||
|
||||
// Since we padded the operands above to be the minimum
|
||||
// width, the val should also be at least expr_width().
|
||||
ivl_assert(*this, val.len() >= expr_width());
|
||||
if (val.len() > expr_width()) {
|
||||
verinum tmp (val, expr_width());
|
||||
tmp.has_sign(val.has_sign());
|
||||
val = tmp;
|
||||
}
|
||||
|
||||
NetEConst*tmp = new NetEConst(val);
|
||||
left_ = se->left_->dup_expr();
|
||||
delete se;
|
||||
@@ -338,19 +362,15 @@ NetEConst* NetEBComp::eval_leeq_real_(NetExpr*le, NetExpr*ri, bool eq_flag)
|
||||
switch (le->expr_type()) {
|
||||
case IVL_VT_REAL:
|
||||
rtmp = dynamic_cast<NetECReal*> (le);
|
||||
if (rtmp == 0)
|
||||
return 0;
|
||||
|
||||
if (rtmp == 0) return 0;
|
||||
lv = rtmp->value().as_double();
|
||||
break;
|
||||
|
||||
case IVL_VT_LOGIC:
|
||||
case IVL_VT_BOOL:
|
||||
vtmp = dynamic_cast<NetEConst*> (le);
|
||||
if (vtmp == 0)
|
||||
return 0;
|
||||
|
||||
lv = vtmp->value().as_long();
|
||||
if (vtmp == 0) return 0;
|
||||
lv = vtmp->value().as_double();
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -359,23 +379,18 @@ NetEConst* NetEBComp::eval_leeq_real_(NetExpr*le, NetExpr*ri, bool eq_flag)
|
||||
assert(0);
|
||||
}
|
||||
|
||||
|
||||
switch (ri->expr_type()) {
|
||||
case IVL_VT_REAL:
|
||||
rtmp = dynamic_cast<NetECReal*> (ri);
|
||||
if (rtmp == 0)
|
||||
return 0;
|
||||
|
||||
if (rtmp == 0) return 0;
|
||||
rv = rtmp->value().as_double();
|
||||
break;
|
||||
|
||||
case IVL_VT_LOGIC:
|
||||
case IVL_VT_BOOL:
|
||||
vtmp = dynamic_cast<NetEConst*> (ri);
|
||||
if (vtmp == 0)
|
||||
return 0;
|
||||
|
||||
rv = vtmp->value().as_long();
|
||||
if (vtmp == 0) return 0;
|
||||
rv = vtmp->value().as_double();
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -479,19 +494,6 @@ NetEConst* NetEBComp::eval_gt_()
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/* Compare with a real value. Do it as double precision. */
|
||||
if (right_->expr_type() == IVL_VT_REAL) {
|
||||
NetECReal*tmp = dynamic_cast<NetECReal*>(right_);
|
||||
if (tmp == 0)
|
||||
return 0;
|
||||
|
||||
double rr = tmp->value().as_double();
|
||||
double ll = lv.has_sign()? lv.as_long() : lv.as_ulong();
|
||||
|
||||
verinum result ((ll > rr)? verinum::V1 : verinum::V0, 1, true);
|
||||
return new NetEConst(result);
|
||||
}
|
||||
|
||||
/* Now go on to the normal test of the values. */
|
||||
NetEConst*r = dynamic_cast<NetEConst*>(right_);
|
||||
if (r == 0) return 0;
|
||||
@@ -530,19 +532,6 @@ NetEConst* NetEBComp::eval_gteq_()
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/* Compare with a real value. Do it as double precision. */
|
||||
if (right_->expr_type() == IVL_VT_REAL) {
|
||||
NetECReal*tmp = dynamic_cast<NetECReal*>(right_);
|
||||
if (tmp == 0)
|
||||
return 0;
|
||||
|
||||
double rr = tmp->value().as_double();
|
||||
double ll = lv.has_sign()? lv.as_long() : lv.as_ulong();
|
||||
|
||||
verinum result ((ll >= rr)? verinum::V1 : verinum::V0, 1, true);
|
||||
return new NetEConst(result);
|
||||
}
|
||||
|
||||
/* Now go on to the normal test of the values. */
|
||||
NetEConst*r = dynamic_cast<NetEConst*>(right_);
|
||||
if (r == 0) return 0;
|
||||
@@ -561,8 +550,73 @@ NetEConst* NetEBComp::eval_gteq_()
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Evaluate <A>==<B> or <A>!=<B>. The equality operator checks all the
|
||||
* bits and returns true(false) if there are any bits in the vector
|
||||
* that are defined (0 or 1) and different. If all the defined bits
|
||||
* are equal, but there are are x/z bits, then the situation is
|
||||
* ambiguous so the result is x.
|
||||
*/
|
||||
NetEConst* NetEBComp::eval_eqeq_real_(NetExpr*le, NetExpr*ri, bool ne_flag)
|
||||
{
|
||||
NetEConst*vtmp;
|
||||
NetECReal*rtmp;
|
||||
double lv, rv;
|
||||
|
||||
switch (le->expr_type()) {
|
||||
case IVL_VT_REAL:
|
||||
rtmp = dynamic_cast<NetECReal*> (le);
|
||||
if (rtmp == 0) return 0;
|
||||
lv = rtmp->value().as_double();
|
||||
break;
|
||||
|
||||
case IVL_VT_LOGIC:
|
||||
case IVL_VT_BOOL:
|
||||
vtmp = dynamic_cast<NetEConst*> (le);
|
||||
if (vtmp == 0) return 0;
|
||||
lv = vtmp->value().as_double();
|
||||
break;
|
||||
|
||||
default:
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<< "Unexpected expression type? " << le->expr_type() << endl;
|
||||
assert(0);
|
||||
}
|
||||
|
||||
switch (ri->expr_type()) {
|
||||
case IVL_VT_REAL:
|
||||
rtmp = dynamic_cast<NetECReal*> (ri);
|
||||
if (rtmp == 0) return 0;
|
||||
rv = rtmp->value().as_double();
|
||||
break;
|
||||
|
||||
case IVL_VT_LOGIC:
|
||||
case IVL_VT_BOOL:
|
||||
vtmp = dynamic_cast<NetEConst*> (ri);
|
||||
if (vtmp == 0) return 0;
|
||||
rv = vtmp->value().as_double();
|
||||
break;
|
||||
|
||||
default:
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<< "Unexpected expression type? " << ri->expr_type() << endl;
|
||||
assert(0);
|
||||
}
|
||||
|
||||
verinum result(((lv == rv) ^ ne_flag) ? verinum::V1 : verinum::V0, 1);
|
||||
vtmp = new NetEConst(result);
|
||||
vtmp->set_line(*this);
|
||||
|
||||
return vtmp;
|
||||
}
|
||||
|
||||
NetEConst* NetEBComp::eval_eqeq_(bool ne_flag)
|
||||
{
|
||||
if (right_->expr_type() == IVL_VT_REAL)
|
||||
return eval_eqeq_real_(right_, left_, ne_flag);
|
||||
if (left_->expr_type() == IVL_VT_REAL)
|
||||
return eval_eqeq_real_(right_, left_, ne_flag);
|
||||
|
||||
NetEConst*l = dynamic_cast<NetEConst*>(left_);
|
||||
if (l == 0) return 0;
|
||||
NetEConst*r = dynamic_cast<NetEConst*>(right_);
|
||||
@@ -581,11 +635,14 @@ NetEConst* NetEBComp::eval_eqeq_(bool ne_flag)
|
||||
|
||||
for (unsigned idx = 0 ; idx < top ; idx += 1) {
|
||||
|
||||
bool x_bit_present = false;
|
||||
|
||||
switch (lv.get(idx)) {
|
||||
|
||||
case verinum::Vx:
|
||||
case verinum::Vz:
|
||||
res = verinum::Vx;
|
||||
x_bit_present = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -597,17 +654,20 @@ NetEConst* NetEBComp::eval_eqeq_(bool ne_flag)
|
||||
case verinum::Vx:
|
||||
case verinum::Vz:
|
||||
res = verinum::Vx;
|
||||
x_bit_present = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (res == verinum::Vx)
|
||||
break;
|
||||
if (x_bit_present)
|
||||
continue;
|
||||
|
||||
if (rv.get(idx) != lv.get(idx))
|
||||
if (rv.get(idx) != lv.get(idx)) {
|
||||
res = ne_res;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (res != verinum::Vx) {
|
||||
@@ -766,9 +826,9 @@ NetExpr* NetEBDiv::eval_tree(int prune_to_width)
|
||||
|
||||
verireal lval = lc->value();
|
||||
|
||||
if (NetECReal*rc = dynamic_cast<NetECReal*>(right_)) {
|
||||
if (NetECReal*rcr = dynamic_cast<NetECReal*>(right_)) {
|
||||
NetECReal*tmp = 0;
|
||||
verireal rval = rc->value();
|
||||
verireal rval = rcr->value();
|
||||
|
||||
switch (op_) {
|
||||
case '/':
|
||||
@@ -811,8 +871,10 @@ NetExpr* NetEBDiv::eval_tree(int prune_to_width)
|
||||
NetEConst*rc = dynamic_cast<NetEConst*>(right_);
|
||||
if (rc == 0) return 0;
|
||||
|
||||
verinum lval = lc->value();
|
||||
verinum rval = rc->value();
|
||||
// Make sure the expression is evaluated at the
|
||||
// expression width.
|
||||
verinum lval = pad_to_width(lc->value(), expr_width());
|
||||
verinum rval = pad_to_width(rc->value(), expr_width());
|
||||
|
||||
NetExpr*tmp = 0;
|
||||
switch (op_) {
|
||||
@@ -1153,6 +1215,11 @@ NetEConst* NetEConcat::eval_tree(int prune_to_width)
|
||||
val = verinum(val.as_string());
|
||||
}
|
||||
|
||||
// Normally, concatenations are unsigned. However, the
|
||||
// $signed() function works by marking the expression as
|
||||
// signed, so we really have to check.
|
||||
val.has_sign( this->has_sign() );
|
||||
|
||||
NetEConst*res = new NetEConst(val);
|
||||
res->set_width(val.len());
|
||||
return res;
|
||||
@@ -1339,7 +1406,7 @@ NetExpr* NetETernary::eval_tree(int prune_to_width)
|
||||
case C_0:
|
||||
eval_expr(false_val_);
|
||||
if (debug_eval_tree) {
|
||||
|
||||
|
||||
cerr << get_fileline() << ": debug: Evaluate ternary with "
|
||||
<< "constant condition value: ";
|
||||
print_ternary_cond(cond_);
|
||||
@@ -1537,6 +1604,7 @@ NetEConst* NetEUReduce::eval_tree(int prune_to_width)
|
||||
|
||||
verinum val = rval->value();
|
||||
verinum::V res;
|
||||
bool invert = false;
|
||||
|
||||
switch (op_) {
|
||||
|
||||
@@ -1565,6 +1633,8 @@ NetEConst* NetEUReduce::eval_tree(int prune_to_width)
|
||||
break;
|
||||
}
|
||||
|
||||
case 'A':
|
||||
invert = true;
|
||||
case '&': {
|
||||
res = verinum::V1;
|
||||
for (unsigned idx = 0 ; idx < val.len() ; idx += 1)
|
||||
@@ -1572,6 +1642,8 @@ NetEConst* NetEUReduce::eval_tree(int prune_to_width)
|
||||
break;
|
||||
}
|
||||
|
||||
case 'N':
|
||||
invert = true;
|
||||
case '|': {
|
||||
res = verinum::V0;
|
||||
for (unsigned idx = 0 ; idx < val.len() ; idx += 1)
|
||||
@@ -1579,6 +1651,8 @@ NetEConst* NetEUReduce::eval_tree(int prune_to_width)
|
||||
break;
|
||||
}
|
||||
|
||||
case 'X':
|
||||
invert = true;
|
||||
case '^': {
|
||||
/* Reduction XOR. */
|
||||
unsigned ones = 0, unknown = 0;
|
||||
@@ -1594,16 +1668,321 @@ NetEConst* NetEUReduce::eval_tree(int prune_to_width)
|
||||
break;
|
||||
}
|
||||
|
||||
if (unknown)
|
||||
return new NetEConst(verinum(verinum::Vx,1,true));
|
||||
if (ones%2)
|
||||
return new NetEConst(verinum(verinum::V1,1,true));
|
||||
return new NetEConst(verinum(verinum::V0,1,true));
|
||||
if (unknown) res = verinum::Vx;
|
||||
else if (ones%2) res = verinum::V1;
|
||||
else res = verinum::V0;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (invert) res = ~res;
|
||||
return new NetEConst(verinum(res, 1));
|
||||
}
|
||||
|
||||
NetExpr* evaluate_clog2(NetExpr*&arg_)
|
||||
{
|
||||
eval_expr(arg_);
|
||||
NetEConst*tmpi = dynamic_cast<NetEConst *>(arg_);
|
||||
NetECReal*tmpr = dynamic_cast<NetECReal *>(arg_);
|
||||
if (tmpi || tmpr) {
|
||||
verinum arg;
|
||||
if (tmpi) {
|
||||
arg = tmpi->value();
|
||||
} else {
|
||||
arg = verinum(tmpr->value().as_double(), true);
|
||||
}
|
||||
|
||||
/* If we have an x in the verinum we return 'bx. */
|
||||
if (!arg.is_defined()) {
|
||||
verinum tmp (verinum::Vx, integer_width);
|
||||
tmp.has_sign(true);
|
||||
NetEConst*rtn = new NetEConst(tmp);
|
||||
return rtn;
|
||||
}
|
||||
|
||||
bool is_neg = false;
|
||||
uint64_t res = 0;
|
||||
if (arg.is_negative()) {
|
||||
is_neg = true;
|
||||
// If the length is not defined, then work with
|
||||
// the trimmed version of the number.
|
||||
if (! arg.has_len())
|
||||
arg = trim_vnum(arg);
|
||||
}
|
||||
arg.has_sign(false); // $unsigned()
|
||||
|
||||
if (!arg.is_zero()) {
|
||||
arg = arg - verinum((uint64_t)1, 1);
|
||||
while (!arg.is_zero()) {
|
||||
res += 1;
|
||||
arg = arg >> 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_neg && res < integer_width)
|
||||
res = integer_width;
|
||||
|
||||
verinum tmp (res, integer_width);
|
||||
NetEConst*rtn = new NetEConst(tmp);
|
||||
return rtn;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetExpr* evaluate_math_one_arg(NetExpr*&arg_, const char*name)
|
||||
{
|
||||
eval_expr(arg_);
|
||||
NetEConst*tmpi = dynamic_cast<NetEConst *>(arg_);
|
||||
NetECReal*tmpr = dynamic_cast<NetECReal *>(arg_);
|
||||
if (tmpi || tmpr) {
|
||||
double arg;
|
||||
if (tmpi) {
|
||||
arg = tmpi->value().as_double();
|
||||
} else {
|
||||
arg = tmpr->value().as_double();
|
||||
}
|
||||
|
||||
if (strcmp(name, "$ln") == 0) {
|
||||
return new NetECReal(verireal(log(arg)));
|
||||
} else if (strcmp(name, "$log") == 0) {
|
||||
return new NetECReal(verireal(log10(arg)));
|
||||
} else if (strcmp(name, "$log10") == 0) {
|
||||
return new NetECReal(verireal(log10(arg)));
|
||||
} else if (strcmp(name, "$exp") == 0) {
|
||||
return new NetECReal(verireal(exp(arg)));
|
||||
} else if (strcmp(name, "$sqrt") == 0) {
|
||||
return new NetECReal(verireal(sqrt(arg)));
|
||||
} else if (strcmp(name, "$floor") == 0) {
|
||||
return new NetECReal(verireal(floor(arg)));
|
||||
} else if (strcmp(name, "$ceil") == 0) {
|
||||
return new NetECReal(verireal(ceil(arg)));
|
||||
} else if (strcmp(name, "$sin") == 0) {
|
||||
return new NetECReal(verireal(sin(arg)));
|
||||
} else if (strcmp(name, "$cos") == 0) {
|
||||
return new NetECReal(verireal(cos(arg)));
|
||||
} else if (strcmp(name, "$tan") == 0) {
|
||||
return new NetECReal(verireal(tan(arg)));
|
||||
} else if (strcmp(name, "$asin") == 0) {
|
||||
return new NetECReal(verireal(asin(arg)));
|
||||
} else if (strcmp(name, "$acos") == 0) {
|
||||
return new NetECReal(verireal(acos(arg)));
|
||||
} else if (strcmp(name, "$atan") == 0) {
|
||||
return new NetECReal(verireal(atan(arg)));
|
||||
} else if (strcmp(name, "$sinh") == 0) {
|
||||
return new NetECReal(verireal(sinh(arg)));
|
||||
} else if (strcmp(name, "$cosh") == 0) {
|
||||
return new NetECReal(verireal(cosh(arg)));
|
||||
} else if (strcmp(name, "$tanh") == 0) {
|
||||
return new NetECReal(verireal(tanh(arg)));
|
||||
} else if (strcmp(name, "$asinh") == 0) {
|
||||
return new NetECReal(verireal(asinh(arg)));
|
||||
} else if (strcmp(name, "$acosh") == 0) {
|
||||
return new NetECReal(verireal(acosh(arg)));
|
||||
} else if (strcmp(name, "$atanh") == 0) {
|
||||
return new NetECReal(verireal(atanh(arg)));
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetExpr* evaluate_math_two_args(NetExpr*&arg0_, NetExpr*&arg1_, const char*name)
|
||||
{
|
||||
eval_expr(arg0_);
|
||||
eval_expr(arg1_);
|
||||
NetEConst*tmpi0 = dynamic_cast<NetEConst *>(arg0_);
|
||||
NetECReal*tmpr0 = dynamic_cast<NetECReal *>(arg0_);
|
||||
NetEConst*tmpi1 = dynamic_cast<NetEConst *>(arg1_);
|
||||
NetECReal*tmpr1 = dynamic_cast<NetECReal *>(arg1_);
|
||||
if ((tmpi0 || tmpr0) && (tmpi1 || tmpr1)) {
|
||||
double arg0, arg1;
|
||||
if (tmpi0) {
|
||||
arg0 = tmpi0->value().as_double();
|
||||
} else {
|
||||
arg0 = tmpr0->value().as_double();
|
||||
}
|
||||
if (tmpi1) {
|
||||
arg1 = tmpi1->value().as_double();
|
||||
} else {
|
||||
arg1 = tmpr1->value().as_double();
|
||||
}
|
||||
|
||||
if (strcmp(name, "$pow") == 0) {
|
||||
return new NetECReal(verireal(pow(arg0, arg1)));
|
||||
} else if (strcmp(name, "$atan2") == 0) {
|
||||
return new NetECReal(verireal(atan2(arg0, arg1)));
|
||||
} else if (strcmp(name, "$hypot") == 0) {
|
||||
return new NetECReal(verireal(hypot(arg0, arg1)));
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetExpr* evaluate_abs(NetExpr*&arg_)
|
||||
{
|
||||
eval_expr(arg_);
|
||||
NetEConst*tmpi = dynamic_cast<NetEConst *>(arg_);
|
||||
if (tmpi) {
|
||||
verinum arg = tmpi->value();
|
||||
if (arg.is_negative()) {
|
||||
arg = v_not(arg) + verinum(1);
|
||||
}
|
||||
return new NetEConst(arg);
|
||||
}
|
||||
|
||||
NetECReal*tmpr = dynamic_cast<NetECReal *>(arg_);
|
||||
if (tmpr) {
|
||||
double arg = tmpr->value().as_double();
|
||||
return new NetECReal(verireal(fabs(arg)));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetExpr* evaluate_min_max(NetExpr*&arg0_, NetExpr*&arg1_, const char*name)
|
||||
{
|
||||
eval_expr(arg0_);
|
||||
eval_expr(arg1_);
|
||||
NetEConst*tmpi0 = dynamic_cast<NetEConst *>(arg0_);
|
||||
NetECReal*tmpr0 = dynamic_cast<NetECReal *>(arg0_);
|
||||
NetEConst*tmpi1 = dynamic_cast<NetEConst *>(arg1_);
|
||||
NetECReal*tmpr1 = dynamic_cast<NetECReal *>(arg1_);
|
||||
if (tmpi0 && tmpi1) {
|
||||
verinum arg0 = tmpi0->value();
|
||||
verinum arg1 = tmpi1->value();
|
||||
if (strcmp(name, "$min") == 0) {
|
||||
return new NetEConst( arg0 < arg1 ? arg0 : arg1);
|
||||
} else if (strcmp(name, "$max") == 0) {
|
||||
return new NetEConst( arg0 < arg1 ? arg1 : arg0);
|
||||
}
|
||||
}
|
||||
|
||||
if ((tmpi0 || tmpr0) && (tmpi1 || tmpr1)) {
|
||||
double arg0, arg1;
|
||||
if (tmpi0) {
|
||||
arg0 = tmpi0->value().as_double();
|
||||
} else {
|
||||
arg0 = tmpr0->value().as_double();
|
||||
}
|
||||
if (tmpi1) {
|
||||
arg1 = tmpi1->value().as_double();
|
||||
} else {
|
||||
arg1 = tmpr1->value().as_double();
|
||||
}
|
||||
if (strcmp(name, "$min") == 0) {
|
||||
return new NetECReal(verireal(arg0 < arg1 ? arg0 : arg1));
|
||||
} else if (strcmp(name, "$max") == 0) {
|
||||
return new NetECReal(verireal(arg0 < arg1 ? arg1 : arg0));
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetExpr* NetESFunc::eval_tree(int prune_to_width)
|
||||
{
|
||||
/* If we are not targeting at least Verilog-2005, Verilog-AMS
|
||||
* or using the Icarus misc flag then we do not support these
|
||||
* functions as constant. */
|
||||
if (generation_flag < GN_VER2005 &&
|
||||
!gn_icarus_misc_flag && !gn_verilog_ams_flag) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char*nm = name();
|
||||
NetExpr*rtn = 0;
|
||||
/* Only $clog2 and the builtin mathematical functions can
|
||||
* be a constant system function. */
|
||||
if (strcmp(nm, "$clog2") == 0 ||
|
||||
strcmp(nm, "$ln") == 0 ||
|
||||
strcmp(nm, "$log10") == 0 ||
|
||||
strcmp(nm, "$exp") == 0 ||
|
||||
strcmp(nm, "$sqrt") == 0 ||
|
||||
strcmp(nm, "$floor") == 0 ||
|
||||
strcmp(nm, "$ceil") == 0 ||
|
||||
strcmp(nm, "$sin") == 0 ||
|
||||
strcmp(nm, "$cos") == 0 ||
|
||||
strcmp(nm, "$tan") == 0 ||
|
||||
strcmp(nm, "$asin") == 0 ||
|
||||
strcmp(nm, "$acos") == 0 ||
|
||||
strcmp(nm, "$atan") == 0 ||
|
||||
strcmp(nm, "$sinh") == 0 ||
|
||||
strcmp(nm, "$cosh") == 0 ||
|
||||
strcmp(nm, "$tanh") == 0 ||
|
||||
strcmp(nm, "$asinh") == 0 ||
|
||||
strcmp(nm, "$acosh") == 0 ||
|
||||
strcmp(nm, "$atanh") == 0) {
|
||||
if (nparms() != 1 || parm(0) == 0) {
|
||||
cerr << get_fileline() << ": error: " << nm
|
||||
<< " takes a single argument." << endl;
|
||||
return 0;
|
||||
}
|
||||
NetExpr*arg = parm(0)->dup_expr();
|
||||
if (strcmp(nm, "$clog2") == 0) {
|
||||
rtn = evaluate_clog2(arg);
|
||||
} else {
|
||||
rtn = evaluate_math_one_arg(arg, nm);
|
||||
}
|
||||
delete arg;
|
||||
}
|
||||
|
||||
if (strcmp(nm, "$pow") == 0 ||
|
||||
strcmp(nm, "$atan2") == 0 ||
|
||||
strcmp(nm, "$hypot") == 0) {
|
||||
if (nparms() != 2 || parm(0) == 0 || parm(1) == 0) {
|
||||
cerr << get_fileline() << ": error: " << nm
|
||||
<< " takes two arguments." << endl;
|
||||
return 0;
|
||||
}
|
||||
NetExpr*arg0 = parm(0)->dup_expr();
|
||||
NetExpr*arg1 = parm(1)->dup_expr();
|
||||
rtn = evaluate_math_two_args(arg0, arg1, nm);
|
||||
delete arg0;
|
||||
delete arg1;
|
||||
}
|
||||
|
||||
if ((gn_icarus_misc_flag || gn_verilog_ams_flag) &&
|
||||
(strcmp(nm, "$log") == 0 || strcmp(nm, "$abs") == 0)) {
|
||||
if (nparms() != 1 || parm(0) == 0) {
|
||||
cerr << get_fileline() << ": error: " << nm
|
||||
<< " takes a single argument." << endl;
|
||||
return 0;
|
||||
}
|
||||
NetExpr*arg = parm(0)->dup_expr();
|
||||
if (strcmp(nm, "$log") == 0) {
|
||||
rtn = evaluate_math_one_arg(arg, nm);
|
||||
} else {
|
||||
rtn = evaluate_abs(arg);
|
||||
}
|
||||
delete arg;
|
||||
}
|
||||
|
||||
if ((gn_icarus_misc_flag || gn_verilog_ams_flag) &&
|
||||
(strcmp(nm, "$min") == 0 || strcmp(nm, "$max") == 0)) {
|
||||
if (nparms() != 2 || parm(0) == 0 || parm(1) == 0) {
|
||||
cerr << get_fileline() << ": error: " << nm
|
||||
<< " takes two arguments." << endl;
|
||||
return 0;
|
||||
}
|
||||
NetExpr*arg0 = parm(0)->dup_expr();
|
||||
NetExpr*arg1 = parm(1)->dup_expr();
|
||||
rtn = evaluate_min_max(arg0, arg1, nm);
|
||||
delete arg0;
|
||||
delete arg1;
|
||||
}
|
||||
|
||||
if (rtn != 0) {
|
||||
rtn->set_line(*this);
|
||||
if (debug_eval_tree) {
|
||||
cerr << get_fileline() << ": debug: Evaluate constant "
|
||||
<< nm << "." << endl;
|
||||
}
|
||||
}
|
||||
|
||||
return rtn;
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@
|
||||
*
|
||||
* The POST_MAP compiler directive causes the GSR manipulations
|
||||
* included in the test bench to be compiled in, to simulate the chip
|
||||
* startup. Other then that, the test bench runs the post-map design
|
||||
* startup. Other than that, the test bench runs the post-map design
|
||||
* the same way the pre-synthesis design works.
|
||||
*
|
||||
* Run this design with the command:
|
||||
|
||||
+360
-162
@@ -20,56 +20,56 @@
|
||||
# include "config.h"
|
||||
# include "compiler.h"
|
||||
|
||||
# include <cstdlib>
|
||||
# include <iostream>
|
||||
|
||||
# include "netlist.h"
|
||||
# include "netmisc.h"
|
||||
# include "ivl_assert.h"
|
||||
|
||||
NetNet* convert_to_real_const(Design*des, NetExpr*expr, NetExpr*obj)
|
||||
static NetNet* convert_to_real_const(Design*des, NetScope*scope, NetEConst*expr)
|
||||
{
|
||||
NetNet* sig;
|
||||
|
||||
if (NetEConst*tmp = dynamic_cast<NetEConst*>(expr)) {
|
||||
verireal vrl(tmp->value().as_double());
|
||||
NetECReal rlval(vrl);
|
||||
sig = rlval.synthesize(des);
|
||||
} else {
|
||||
cerr << obj->get_fileline() << ": sorry: Cannot convert "
|
||||
"bit based value (" << *expr << ") to real." << endl;
|
||||
des->errors += 1;
|
||||
sig = 0;
|
||||
}
|
||||
verireal vrl(expr->value().as_double());
|
||||
NetECReal rlval(vrl);
|
||||
NetNet* sig = rlval.synthesize(des, scope);
|
||||
|
||||
return sig;
|
||||
}
|
||||
|
||||
/* Note that lsig, rsig and real_args are references. */
|
||||
bool process_binary_args(Design*des, NetExpr*left, NetExpr*right,
|
||||
NetNet*&lsig, NetNet*&rsig, bool&real_args,
|
||||
NetExpr*obj)
|
||||
static bool process_binary_args(Design*des, NetScope*scope,
|
||||
NetExpr*left, NetExpr*right,
|
||||
NetNet*&lsig, NetNet*&rsig, bool&real_args,
|
||||
NetExpr*obj)
|
||||
{
|
||||
if (left->expr_type() == IVL_VT_REAL ||
|
||||
right->expr_type() == IVL_VT_REAL) {
|
||||
real_args = true;
|
||||
|
||||
/* Currently we will have a runtime assert if both expressions
|
||||
are not real, though we can convert constants. */
|
||||
/* Convert the arguments to real. Handle the special
|
||||
cases of constants, which can be converted more directly. */
|
||||
if (left->expr_type() == IVL_VT_REAL) {
|
||||
lsig = left->synthesize(des);
|
||||
lsig = left->synthesize(des, scope);
|
||||
} else if (NetEConst*tmpc = dynamic_cast<NetEConst*> (left)) {
|
||||
lsig = convert_to_real_const(des, scope, tmpc);
|
||||
} else {
|
||||
lsig = convert_to_real_const(des, left, obj);
|
||||
NetNet*tmp = left->synthesize(des, scope);
|
||||
lsig = cast_to_real(des, scope, tmp);
|
||||
}
|
||||
|
||||
if (right->expr_type() == IVL_VT_REAL) {
|
||||
rsig = right->synthesize(des);
|
||||
rsig = right->synthesize(des, scope);
|
||||
} else if (NetEConst*tmpc = dynamic_cast<NetEConst*> (right)) {
|
||||
rsig = convert_to_real_const(des, scope, tmpc);
|
||||
} else {
|
||||
rsig = convert_to_real_const(des, right, obj);
|
||||
NetNet*tmp = right->synthesize(des, scope);
|
||||
rsig = cast_to_real(des, scope, tmp);
|
||||
}
|
||||
|
||||
} else {
|
||||
real_args = false;
|
||||
lsig = left->synthesize(des);
|
||||
rsig = right->synthesize(des);
|
||||
lsig = left->synthesize(des, scope);
|
||||
rsig = right->synthesize(des, scope);
|
||||
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ bool process_binary_args(Design*des, NetExpr*left, NetExpr*right,
|
||||
else return false;
|
||||
}
|
||||
|
||||
NetNet* NetExpr::synthesize(Design*des)
|
||||
NetNet* NetExpr::synthesize(Design*des, NetScope*scope)
|
||||
{
|
||||
cerr << get_fileline() << ": internal error: cannot synthesize expression: "
|
||||
<< *this << endl;
|
||||
@@ -88,25 +88,35 @@ NetNet* NetExpr::synthesize(Design*des)
|
||||
/*
|
||||
* Make an LPM_ADD_SUB device from addition operators.
|
||||
*/
|
||||
NetNet* NetEBAdd::synthesize(Design*des)
|
||||
NetNet* NetEBAdd::synthesize(Design*des, NetScope*scope)
|
||||
{
|
||||
assert((op()=='+') || (op()=='-'));
|
||||
ivl_assert(*this, (op()=='+') || (op()=='-'));
|
||||
|
||||
NetNet *lsig=0, *rsig=0;
|
||||
bool real_args=false;
|
||||
if (process_binary_args(des, left_, right_, lsig, rsig,
|
||||
if (process_binary_args(des, scope, left_, right_, lsig, rsig,
|
||||
real_args, this)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(expr_width() >= lsig->vector_width());
|
||||
assert(expr_width() >= rsig->vector_width());
|
||||
ivl_assert(*this, expr_width() >= lsig->vector_width());
|
||||
ivl_assert(*this, expr_width() >= rsig->vector_width());
|
||||
|
||||
lsig = pad_to_width(des, lsig, expr_width());
|
||||
rsig = pad_to_width(des, rsig, expr_width());
|
||||
unsigned width;
|
||||
if (expr_type() == IVL_VT_REAL) {
|
||||
width = 1;
|
||||
if (lsig->data_type() != IVL_VT_REAL)
|
||||
lsig = cast_to_real(des, scope, lsig);
|
||||
if (rsig->data_type() != IVL_VT_REAL)
|
||||
rsig = cast_to_real(des, scope, rsig);
|
||||
|
||||
assert(lsig->vector_width() == rsig->vector_width());
|
||||
unsigned width=lsig->vector_width();
|
||||
} else {
|
||||
lsig = pad_to_width(des, lsig, expr_width());
|
||||
rsig = pad_to_width(des, rsig, expr_width());
|
||||
|
||||
assert(lsig->vector_width() == rsig->vector_width());
|
||||
width=lsig->vector_width();
|
||||
}
|
||||
|
||||
perm_string path = lsig->scope()->local_symbol();
|
||||
NetNet*osig = new NetNet(lsig->scope(), path, NetNet::IMPLICIT, width);
|
||||
@@ -138,10 +148,10 @@ NetNet* NetEBAdd::synthesize(Design*des)
|
||||
* signals, then just connect a single gate to each bit of the vector
|
||||
* of the expression.
|
||||
*/
|
||||
NetNet* NetEBBits::synthesize(Design*des)
|
||||
NetNet* NetEBBits::synthesize(Design*des, NetScope*scope)
|
||||
{
|
||||
NetNet*lsig = left_->synthesize(des);
|
||||
NetNet*rsig = right_->synthesize(des);
|
||||
NetNet*lsig = left_->synthesize(des, scope);
|
||||
NetNet*rsig = right_->synthesize(des, scope);
|
||||
|
||||
if (lsig == 0 || rsig == 0) return 0;
|
||||
|
||||
@@ -154,10 +164,7 @@ NetNet* NetEBBits::synthesize(Design*des)
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetScope*scope = lsig->scope();
|
||||
assert(scope);
|
||||
|
||||
unsigned width = lsig->vector_width();
|
||||
unsigned width = expr_width();
|
||||
if (rsig->vector_width() > width) width = rsig->vector_width();
|
||||
|
||||
lsig = pad_to_width(des, lsig, width);
|
||||
@@ -205,13 +212,13 @@ NetNet* NetEBBits::synthesize(Design*des)
|
||||
return osig;
|
||||
}
|
||||
|
||||
NetNet* NetEBComp::synthesize(Design*des)
|
||||
NetNet* NetEBComp::synthesize(Design*des, NetScope*scope)
|
||||
{
|
||||
|
||||
NetNet *lsig=0, *rsig=0;
|
||||
unsigned width;
|
||||
bool real_args=false;
|
||||
if (process_binary_args(des, left_, right_, lsig, rsig,
|
||||
if (process_binary_args(des, scope, left_, right_, lsig, rsig,
|
||||
real_args, this)) {
|
||||
return 0;
|
||||
}
|
||||
@@ -222,24 +229,58 @@ NetNet* NetEBComp::synthesize(Design*des)
|
||||
width = lsig->vector_width();
|
||||
if (rsig->vector_width() > width) width = rsig->vector_width();
|
||||
|
||||
lsig = pad_to_width(des, lsig, width);
|
||||
rsig = pad_to_width(des, rsig, width);
|
||||
if (lsig->get_signed())
|
||||
lsig = pad_to_width_signed(des, lsig, width);
|
||||
else
|
||||
lsig = pad_to_width(des, lsig, width);
|
||||
if (rsig->get_signed())
|
||||
rsig = pad_to_width_signed(des, rsig, width);
|
||||
else
|
||||
rsig = pad_to_width(des, rsig, width);
|
||||
}
|
||||
|
||||
NetScope*scope = lsig->scope();
|
||||
assert(scope);
|
||||
|
||||
NetNet*osig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, 1);
|
||||
osig->set_line(*this);
|
||||
osig->local_flag(true);
|
||||
osig->data_type(IVL_VT_LOGIC);
|
||||
|
||||
bool signed_compare = lsig->get_signed() && rsig->get_signed();
|
||||
// Test if the comparison is signed.
|
||||
//
|
||||
// Note 1: This is not the same as asking if the result is
|
||||
// signed. In fact, the result will typically be UNsigned. The
|
||||
// decision to make the comparison signed depends on the
|
||||
// operand expressions.
|
||||
//
|
||||
// Note 2: The operand expressions may be signed even if the
|
||||
// sig that comes out of synthesis is unsigned. The $signed()
|
||||
// function marks the expression but doesn't change the
|
||||
// underlying signals.
|
||||
bool signed_compare = left_->has_sign() && right_->has_sign();
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: Comparison (" << op_ << ")"
|
||||
<< " is " << (signed_compare? "signed" : "unsigned")
|
||||
<< endl;
|
||||
cerr << get_fileline() << ": : lsig is "
|
||||
<< (lsig->get_signed()? "signed" : "unsigned")
|
||||
<< " rsig is " << (rsig->get_signed()? "signed" : "unsigned")
|
||||
<< endl;
|
||||
}
|
||||
|
||||
if (op_ == 'E' || op_ == 'N') {
|
||||
NetCaseCmp*gate = new NetCaseCmp(scope, scope->local_symbol(),
|
||||
width, op_=='E'?true:false);
|
||||
gate->set_line(*this);
|
||||
connect(gate->pin(0), osig->pin(0));
|
||||
connect(gate->pin(1), lsig->pin(0));
|
||||
connect(gate->pin(2), rsig->pin(0));
|
||||
des->add_node(gate);
|
||||
return osig;
|
||||
}
|
||||
|
||||
/* Handle the special case of a single bit equality
|
||||
operation. Make an XNOR gate instead of a comparator. */
|
||||
if ((width == 1) && ((op_ == 'e') || (op_ == 'E')) && !real_args) {
|
||||
if ((width == 1) && (op_ == 'e') && !real_args) {
|
||||
NetLogic*gate = new NetLogic(scope, scope->local_symbol(),
|
||||
3, NetLogic::XNOR, 1);
|
||||
gate->set_line(*this);
|
||||
@@ -253,7 +294,7 @@ NetNet* NetEBComp::synthesize(Design*des)
|
||||
/* Handle the special case of a single bit inequality
|
||||
operation. This is similar to single bit equality, but uses
|
||||
an XOR instead of an XNOR gate. */
|
||||
if ((width == 1) && ((op_ == 'n') || (op_ == 'N')) && !real_args) {
|
||||
if ((width == 1) && (op_ == 'n') && !real_args) {
|
||||
NetLogic*gate = new NetLogic(scope, scope->local_symbol(),
|
||||
3, NetLogic::XOR, 1);
|
||||
gate->set_line(*this);
|
||||
@@ -321,12 +362,12 @@ NetNet* NetEBComp::synthesize(Design*des)
|
||||
return osig;
|
||||
}
|
||||
|
||||
NetNet* NetEBPow::synthesize(Design*des)
|
||||
NetNet* NetEBPow::synthesize(Design*des, NetScope*scope)
|
||||
{
|
||||
NetNet *lsig=0, *rsig=0;
|
||||
unsigned width;
|
||||
bool real_args=false;
|
||||
if (process_binary_args(des, left_, right_, lsig, rsig,
|
||||
if (process_binary_args(des, scope, left_, right_, lsig, rsig,
|
||||
real_args, this)) {
|
||||
return 0;
|
||||
}
|
||||
@@ -334,9 +375,6 @@ NetNet* NetEBPow::synthesize(Design*des)
|
||||
if (real_args) width = 1;
|
||||
else width = expr_width();
|
||||
|
||||
NetScope*scope = lsig->scope();
|
||||
assert(scope);
|
||||
|
||||
NetPow*powr = new NetPow(scope, scope->local_symbol(), width,
|
||||
lsig->vector_width(),
|
||||
rsig->vector_width());
|
||||
@@ -359,12 +397,12 @@ NetNet* NetEBPow::synthesize(Design*des)
|
||||
return osig;
|
||||
}
|
||||
|
||||
NetNet* NetEBMult::synthesize(Design*des)
|
||||
NetNet* NetEBMult::synthesize(Design*des, NetScope*scope)
|
||||
{
|
||||
NetNet *lsig=0, *rsig=0;
|
||||
unsigned width;
|
||||
bool real_args=false;
|
||||
if (process_binary_args(des, left_, right_, lsig, rsig,
|
||||
if (process_binary_args(des, scope, left_, right_, lsig, rsig,
|
||||
real_args, this)) {
|
||||
return 0;
|
||||
}
|
||||
@@ -372,9 +410,6 @@ NetNet* NetEBMult::synthesize(Design*des)
|
||||
if (real_args) width = 1;
|
||||
else width = expr_width();
|
||||
|
||||
NetScope*scope = lsig->scope();
|
||||
assert(scope);
|
||||
|
||||
NetMult*mult = new NetMult(scope, scope->local_symbol(),
|
||||
width,
|
||||
lsig->vector_width(),
|
||||
@@ -398,12 +433,12 @@ NetNet* NetEBMult::synthesize(Design*des)
|
||||
return osig;
|
||||
}
|
||||
|
||||
NetNet* NetEBDiv::synthesize(Design*des)
|
||||
NetNet* NetEBDiv::synthesize(Design*des, NetScope*scope)
|
||||
{
|
||||
NetNet *lsig=0, *rsig=0;
|
||||
unsigned width;
|
||||
bool real_args=false;
|
||||
if (process_binary_args(des, left_, right_, lsig, rsig,
|
||||
if (process_binary_args(des, scope, left_, right_, lsig, rsig,
|
||||
real_args, this)) {
|
||||
return 0;
|
||||
}
|
||||
@@ -411,12 +446,11 @@ NetNet* NetEBDiv::synthesize(Design*des)
|
||||
if (real_args) width = 1;
|
||||
else width = expr_width();
|
||||
|
||||
NetScope*scope = lsig->scope();
|
||||
|
||||
NetNet*osig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, width);
|
||||
osig->set_line(*this);
|
||||
osig->data_type(lsig->data_type());
|
||||
osig->set_signed(has_sign());
|
||||
osig->local_flag(true);
|
||||
|
||||
switch (op()) {
|
||||
@@ -427,6 +461,7 @@ NetNet* NetEBDiv::synthesize(Design*des)
|
||||
lsig->vector_width(),
|
||||
rsig->vector_width());
|
||||
div->set_line(*this);
|
||||
div->set_signed(has_sign());
|
||||
des->add_node(div);
|
||||
|
||||
connect(div->pin_DataA(), lsig->pin(0));
|
||||
@@ -449,6 +484,7 @@ NetNet* NetEBDiv::synthesize(Design*des)
|
||||
lsig->vector_width(),
|
||||
rsig->vector_width());
|
||||
div->set_line(*this);
|
||||
div->set_signed(has_sign());
|
||||
des->add_node(div);
|
||||
|
||||
connect(div->pin_DataA(), lsig->pin(0));
|
||||
@@ -459,7 +495,7 @@ NetNet* NetEBDiv::synthesize(Design*des)
|
||||
|
||||
default: {
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<< "NetEBDiv has unexpeced op() code: "
|
||||
<< "NetEBDiv has unexpected op() code: "
|
||||
<< op() << endl;
|
||||
des->errors += 1;
|
||||
|
||||
@@ -471,10 +507,10 @@ NetNet* NetEBDiv::synthesize(Design*des)
|
||||
return osig;
|
||||
}
|
||||
|
||||
NetNet* NetEBLogic::synthesize(Design*des)
|
||||
NetNet* NetEBLogic::synthesize(Design*des, NetScope*scope)
|
||||
{
|
||||
NetNet*lsig = left_->synthesize(des);
|
||||
NetNet*rsig = right_->synthesize(des);
|
||||
NetNet*lsig = left_->synthesize(des, scope);
|
||||
NetNet*rsig = right_->synthesize(des, scope);
|
||||
|
||||
if (lsig == 0 || rsig == 0) return 0;
|
||||
|
||||
@@ -487,9 +523,6 @@ NetNet* NetEBLogic::synthesize(Design*des)
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetScope*scope = lsig->scope();
|
||||
assert(scope);
|
||||
|
||||
NetNet*osig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, 1);
|
||||
osig->data_type(expr_type());
|
||||
@@ -551,11 +584,11 @@ NetNet* NetEBLogic::synthesize(Design*des)
|
||||
return osig;
|
||||
}
|
||||
|
||||
NetNet* NetEBShift::synthesize(Design*des)
|
||||
NetNet* NetEBShift::synthesize(Design*des, NetScope*scope)
|
||||
{
|
||||
eval_expr(right_);
|
||||
|
||||
NetNet*lsig = left_->synthesize(des);
|
||||
NetNet*lsig = left_->synthesize(des, scope);
|
||||
|
||||
if (lsig == 0) return 0;
|
||||
|
||||
@@ -568,10 +601,8 @@ NetNet* NetEBShift::synthesize(Design*des)
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool right_flag = op_ == 'r' || op_ == 'R';
|
||||
bool signed_flag = op_ == 'R';
|
||||
|
||||
NetScope*scope = lsig->scope();
|
||||
const bool right_flag = op_ == 'r' || op_ == 'R';
|
||||
const bool signed_flag = op_ == 'R';
|
||||
|
||||
/* Detect the special case where the shift amount is
|
||||
constant. Evaluate the shift amount, and simply reconnect
|
||||
@@ -580,7 +611,7 @@ NetNet* NetEBShift::synthesize(Design*des)
|
||||
verinum shift_v = rcon->value();
|
||||
long shift = shift_v.as_long();
|
||||
|
||||
if (op() == 'r')
|
||||
if (right_flag)
|
||||
shift = 0-shift;
|
||||
|
||||
if (shift == 0)
|
||||
@@ -593,34 +624,13 @@ NetNet* NetEBShift::synthesize(Design*des)
|
||||
|
||||
// ushift is the amount of pad created by the shift.
|
||||
unsigned long ushift = shift>=0? shift : -shift;
|
||||
if (ushift > osig->vector_width())
|
||||
ushift = osig->vector_width();
|
||||
ivl_assert(*this, ushift < osig->vector_width());
|
||||
|
||||
// part_width is the bits of the vector that survive the shift.
|
||||
unsigned long part_width = osig->vector_width() - ushift;
|
||||
|
||||
verinum znum (verinum::V0, ushift, true);
|
||||
NetConst*zcon = new NetConst(scope, scope->local_symbol(),
|
||||
znum);
|
||||
des->add_node(zcon);
|
||||
|
||||
/* Detect the special case that the shift is the size of
|
||||
the whole expression. Simply connect the pad to the
|
||||
osig and escape. */
|
||||
if (ushift >= osig->vector_width()) {
|
||||
connect(zcon->pin(0), osig->pin(0));
|
||||
return osig;
|
||||
}
|
||||
|
||||
NetNet*zsig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, znum.len());
|
||||
zsig->data_type(osig->data_type());
|
||||
zsig->local_flag(true);
|
||||
zsig->set_line(*this);
|
||||
connect(zcon->pin(0), zsig->pin(0));
|
||||
|
||||
/* Create a part select to reduce the width of the lsig
|
||||
to the amount left by the shift. */
|
||||
// Create a part select to reduce the width of the lsig
|
||||
// to the amount left by the shift.
|
||||
NetPartSelect*psel = new NetPartSelect(lsig, shift<0? ushift : 0,
|
||||
part_width,
|
||||
NetPartSelect::VP);
|
||||
@@ -633,6 +643,34 @@ NetNet* NetEBShift::synthesize(Design*des)
|
||||
psig->set_line(*this);
|
||||
connect(psig->pin(0), psel->pin(0));
|
||||
|
||||
// Handle the special case of a signed right shift. In
|
||||
// this case, use the NetSignExtend device to pad the
|
||||
// result to the desired width.
|
||||
if (signed_flag && right_flag) {
|
||||
NetSignExtend*pad = new NetSignExtend(scope, scope->local_symbol(),
|
||||
osig->vector_width());
|
||||
des->add_node(pad);
|
||||
pad->set_line(*this);
|
||||
|
||||
connect(pad->pin(1), psig->pin(0));
|
||||
connect(pad->pin(0), osig->pin(0));
|
||||
return osig;
|
||||
}
|
||||
|
||||
// Other cases are handled by zero-extending on the
|
||||
// proper end.
|
||||
verinum znum (verinum::V0, ushift, true);
|
||||
NetConst*zcon = new NetConst(scope, scope->local_symbol(),
|
||||
znum);
|
||||
des->add_node(zcon);
|
||||
|
||||
NetNet*zsig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, znum.len());
|
||||
zsig->data_type(osig->data_type());
|
||||
zsig->local_flag(true);
|
||||
zsig->set_line(*this);
|
||||
connect(zcon->pin(0), zsig->pin(0));
|
||||
|
||||
NetConcat*ccat = new NetConcat(scope, scope->local_symbol(),
|
||||
osig->vector_width(), 2);
|
||||
ccat->set_line(*this);
|
||||
@@ -652,7 +690,7 @@ NetNet* NetEBShift::synthesize(Design*des)
|
||||
return osig;
|
||||
}
|
||||
|
||||
NetNet*rsig = right_->synthesize(des);
|
||||
NetNet*rsig = right_->synthesize(des, scope);
|
||||
|
||||
if (rsig == 0) return 0;
|
||||
|
||||
@@ -678,13 +716,13 @@ NetNet* NetEBShift::synthesize(Design*des)
|
||||
return osig;
|
||||
}
|
||||
|
||||
NetNet* NetEConcat::synthesize(Design*des)
|
||||
NetNet* NetEConcat::synthesize(Design*des, NetScope*scope)
|
||||
{
|
||||
/* First, synthesize the operands. */
|
||||
NetNet**tmp = new NetNet*[parms_.count()];
|
||||
bool flag = true;
|
||||
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) {
|
||||
tmp[idx] = parms_[idx]->synthesize(des);
|
||||
tmp[idx] = parms_[idx]->synthesize(des, scope);
|
||||
if (tmp[idx] == 0)
|
||||
flag = false;
|
||||
}
|
||||
@@ -692,9 +730,7 @@ NetNet* NetEConcat::synthesize(Design*des)
|
||||
if (flag == false)
|
||||
return 0;
|
||||
|
||||
assert(tmp[0]);
|
||||
NetScope*scope = tmp[0]->scope();
|
||||
assert(scope);
|
||||
ivl_assert(*this, tmp[0]);
|
||||
|
||||
/* Make a NetNet object to carry the output vector. */
|
||||
perm_string path = scope->local_symbol();
|
||||
@@ -712,7 +748,9 @@ NetNet* NetEConcat::synthesize(Design*des)
|
||||
unsigned cur_pin = 1;
|
||||
for (unsigned rpt = 0; rpt < repeat(); rpt += 1) {
|
||||
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) {
|
||||
connect(concat->pin(cur_pin), tmp[parms_.count()-idx-1]->pin(0));
|
||||
unsigned concat_item = parms_.count()-idx-1;
|
||||
ivl_assert(*this, tmp[concat_item]);
|
||||
connect(concat->pin(cur_pin), tmp[concat_item]->pin(0));
|
||||
cur_pin += 1;
|
||||
}
|
||||
}
|
||||
@@ -721,17 +759,14 @@ NetNet* NetEConcat::synthesize(Design*des)
|
||||
return osig;
|
||||
}
|
||||
|
||||
NetNet* NetEConst::synthesize(Design*des)
|
||||
NetNet* NetEConst::synthesize(Design*des, NetScope*scope)
|
||||
{
|
||||
NetScope*scope = des->find_root_scope();
|
||||
assert(scope);
|
||||
|
||||
perm_string path = scope->local_symbol();
|
||||
unsigned width=expr_width();
|
||||
|
||||
NetNet*osig = new NetNet(scope, path, NetNet::IMPLICIT, width-1,0);
|
||||
NetNet*osig = new NetNet(scope, path, NetNet::IMPLICIT, width);
|
||||
osig->local_flag(true);
|
||||
osig->data_type(IVL_VT_LOGIC);
|
||||
osig->data_type(expr_type());
|
||||
osig->set_signed(has_sign());
|
||||
NetConst*con = new NetConst(scope, scope->local_symbol(), value());
|
||||
connect(osig->pin(0), con->pin(0));
|
||||
@@ -743,11 +778,8 @@ NetNet* NetEConst::synthesize(Design*des)
|
||||
/*
|
||||
* Create a NetLiteral object to represent real valued constants.
|
||||
*/
|
||||
NetNet* NetECReal::synthesize(Design*des)
|
||||
NetNet* NetECReal::synthesize(Design*des, NetScope*scope)
|
||||
{
|
||||
NetScope*scope = des->find_root_scope();
|
||||
assert(scope);
|
||||
|
||||
perm_string path = scope->local_symbol();
|
||||
|
||||
NetNet*osig = new NetNet(scope, path, NetNet::WIRE, 1);
|
||||
@@ -768,9 +800,9 @@ NetNet* NetECReal::synthesize(Design*des)
|
||||
* The bitwise unary logic operator (there is only one) is turned
|
||||
* into discrete gates just as easily as the binary ones above.
|
||||
*/
|
||||
NetNet* NetEUBits::synthesize(Design*des)
|
||||
NetNet* NetEUBits::synthesize(Design*des, NetScope*scope)
|
||||
{
|
||||
NetNet*isig = expr_->synthesize(des);
|
||||
NetNet*isig = expr_->synthesize(des, scope);
|
||||
|
||||
if (isig == 0) return 0;
|
||||
|
||||
@@ -782,9 +814,6 @@ NetNet* NetEUBits::synthesize(Design*des)
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetScope*scope = isig->scope();
|
||||
assert(scope);
|
||||
|
||||
unsigned width = isig->vector_width();
|
||||
NetNet*osig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, width);
|
||||
@@ -810,13 +839,56 @@ NetNet* NetEUBits::synthesize(Design*des)
|
||||
return osig;
|
||||
}
|
||||
|
||||
NetNet* NetEUReduce::synthesize(Design*des)
|
||||
NetNet* NetEUnary::synthesize(Design*des, NetScope*scope)
|
||||
{
|
||||
NetNet*isig = expr_->synthesize(des);
|
||||
if (op_ == '+')
|
||||
return expr_->synthesize(des, scope);
|
||||
|
||||
if (op_ == '-') {
|
||||
NetNet*sig = expr_->synthesize(des, scope);
|
||||
sig = sub_net_from(des, scope, 0, sig);
|
||||
return sig;
|
||||
}
|
||||
|
||||
if (op_ == 'm') {
|
||||
NetNet*sub = expr_->synthesize(des, scope);
|
||||
if (expr_->has_sign() == false)
|
||||
return sub;
|
||||
|
||||
NetNet*sig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, sub->vector_width());
|
||||
sig->set_line(*this);
|
||||
sig->local_flag(true);
|
||||
sig->data_type(sub->data_type());
|
||||
|
||||
NetAbs*tmp = new NetAbs(scope, scope->local_symbol(), sub->vector_width());
|
||||
des->add_node(tmp);
|
||||
tmp->set_line(*this);
|
||||
|
||||
connect(tmp->pin(1), sub->pin(0));
|
||||
connect(tmp->pin(0), sig->pin(0));
|
||||
return sig;
|
||||
}
|
||||
|
||||
cerr << get_fileline() << ": iternal error: "
|
||||
<< "NetEUnary::synthesize cannot handle op_=" << op_ << endl;
|
||||
des->errors += 1;
|
||||
return expr_->synthesize(des, scope);
|
||||
}
|
||||
|
||||
NetNet* NetEUReduce::synthesize(Design*des, NetScope*scope)
|
||||
{
|
||||
NetNet*isig = expr_->synthesize(des, scope);
|
||||
|
||||
if (isig == 0) return 0;
|
||||
|
||||
if (isig->data_type() == IVL_VT_REAL) {
|
||||
if (op() == '!') {
|
||||
cerr << get_fileline() << ": sorry: ! is currently "
|
||||
"unsupported for real values." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
cerr << get_fileline() << ": error: reduction operator ("
|
||||
<< human_readable_op(op_)
|
||||
<< ") may not have a REAL operand." << endl;
|
||||
@@ -824,9 +896,6 @@ NetNet* NetEUReduce::synthesize(Design*des)
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetScope*scope = isig->scope();
|
||||
assert(scope);
|
||||
|
||||
NetNet*osig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, 1);
|
||||
osig->data_type(expr_type());
|
||||
@@ -849,7 +918,7 @@ NetNet* NetEUReduce::synthesize(Design*des)
|
||||
rtype = NetUReduce::XOR;
|
||||
break;
|
||||
case 'A':
|
||||
rtype = NetUReduce::XNOR;
|
||||
rtype = NetUReduce::NAND;
|
||||
break;
|
||||
case 'X':
|
||||
rtype = NetUReduce::XNOR;
|
||||
@@ -871,22 +940,101 @@ NetNet* NetEUReduce::synthesize(Design*des)
|
||||
return osig;
|
||||
}
|
||||
|
||||
NetNet* NetESelect::synthesize(Design *des)
|
||||
/*
|
||||
* Turn a part/bit select expression into gates.
|
||||
* We know some things about the expression that elaboration enforces
|
||||
* for us:
|
||||
*
|
||||
* - Expression elaboration already converted the offset expression into
|
||||
* canonical form, so we don't have to worry about that here.
|
||||
*/
|
||||
NetNet* NetESelect::synthesize(Design *des, NetScope*scope)
|
||||
{
|
||||
|
||||
NetNet*sub = expr_->synthesize(des);
|
||||
NetNet*sub = expr_->synthesize(des, scope);
|
||||
|
||||
if (sub == 0) return 0;
|
||||
|
||||
NetScope*scope = sub->scope();
|
||||
|
||||
NetNet*off = 0;
|
||||
|
||||
// Detect the special case that there is a base expression and
|
||||
// it is constant. In this case we can generate fixed part selects.
|
||||
if (NetEConst*base_const = dynamic_cast<NetEConst*>(base_)) {
|
||||
verinum base_tmp = base_const->value();
|
||||
ivl_assert(*this, base_tmp.is_defined());
|
||||
|
||||
long base_val = base_tmp.as_long();
|
||||
unsigned select_width = expr_width();
|
||||
|
||||
// Any below X bits?
|
||||
NetNet*below = 0;
|
||||
if (base_val < 0) {
|
||||
unsigned below_width = abs(base_val);
|
||||
base_val = 0;
|
||||
ivl_assert(*this, below_width < select_width);
|
||||
select_width -= below_width;
|
||||
|
||||
below = make_const_x(des, scope, below_width);
|
||||
below->set_line(*this);
|
||||
}
|
||||
|
||||
// Any above bits?
|
||||
NetNet*above = 0;
|
||||
if ((unsigned)base_val+select_width > sub->vector_width()) {
|
||||
select_width = sub->vector_width() - base_val;
|
||||
unsigned above_width = expr_width() - select_width;
|
||||
|
||||
above = make_const_x(des, scope, above_width);
|
||||
above->set_line(*this);
|
||||
}
|
||||
|
||||
// Make the make part select.
|
||||
NetPartSelect*sel = new NetPartSelect(sub, base_val, select_width,
|
||||
NetPartSelect::VP);
|
||||
des->add_node(sel);
|
||||
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, select_width);
|
||||
tmp->data_type(sub->data_type());
|
||||
tmp->local_flag(true);
|
||||
tmp->set_line(*this);
|
||||
connect(sel->pin(0), tmp->pin(0));
|
||||
|
||||
unsigned concat_count = 1;
|
||||
if (above)
|
||||
concat_count += 1;
|
||||
if (below)
|
||||
concat_count += 1;
|
||||
if (concat_count > 1) {
|
||||
NetConcat*cat = new NetConcat(scope, scope->local_symbol(),
|
||||
expr_width(), concat_count);
|
||||
cat->set_line(*this);
|
||||
des->add_node(cat);
|
||||
if (below) {
|
||||
connect(cat->pin(1), below->pin(0));
|
||||
connect(cat->pin(2), tmp->pin(0));
|
||||
} else {
|
||||
connect(cat->pin(1), tmp->pin(0));
|
||||
}
|
||||
if (above) {
|
||||
connect(cat->pin(concat_count), above->pin(0));
|
||||
}
|
||||
|
||||
tmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, expr_width());
|
||||
tmp->data_type(sub->data_type());
|
||||
tmp->local_flag(true);
|
||||
tmp->set_line(*this);
|
||||
connect(cat->pin(0), tmp->pin(0));
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
// This handles the case that the NetESelect exists to do an
|
||||
// actual part/bit select. Generate a NetPartSelect object to
|
||||
// do the work, and replace "sub" with the selected output.
|
||||
if (base_ != 0) {
|
||||
off = base_->synthesize(des);
|
||||
off = base_->synthesize(des, scope);
|
||||
|
||||
NetPartSelect*sel = new NetPartSelect(sub, off, expr_width());
|
||||
sel->set_line(*this);
|
||||
@@ -967,21 +1115,26 @@ NetNet* NetESelect::synthesize(Design *des)
|
||||
* expressions to the B and A inputs. This way, when the select input
|
||||
* is one, the B input, which is the true expression, is selected.
|
||||
*/
|
||||
NetNet* NetETernary::synthesize(Design *des)
|
||||
NetNet* NetETernary::synthesize(Design *des, NetScope*scope)
|
||||
{
|
||||
NetNet*csig = cond_->synthesize(des),
|
||||
*tsig = true_val_->synthesize(des),
|
||||
*fsig = false_val_->synthesize(des);
|
||||
NetNet*csig = cond_->synthesize(des, scope),
|
||||
*tsig = true_val_->synthesize(des, scope),
|
||||
*fsig = false_val_->synthesize(des, scope);
|
||||
|
||||
if (csig == 0 || tsig == 0 || fsig == 0) return 0;
|
||||
|
||||
if (tsig->data_type() != fsig->data_type()) {
|
||||
cerr << get_fileline() << ": error: True and False clauses of "
|
||||
"ternary expression have different types." << endl;
|
||||
if (! NetETernary::test_operand_compat(tsig->data_type(),fsig->data_type())) {
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<< " True and False clauses of ternary expression "
|
||||
<< " have incompatible types." << endl;
|
||||
cerr << get_fileline() << ": : True clause is: "
|
||||
<< tsig->data_type() << endl;
|
||||
<< tsig->data_type()
|
||||
<< " (" << true_val_->expr_type() << "): "
|
||||
<< *true_val_ << endl;
|
||||
cerr << get_fileline() << ": : False clause is: "
|
||||
<< fsig->data_type() << endl;
|
||||
<< fsig->data_type()
|
||||
<< " (" << false_val_->expr_type() << "): "
|
||||
<< *false_val_ << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
} else if (tsig->data_type() == IVL_VT_NO_TYPE) {
|
||||
@@ -993,7 +1146,7 @@ NetNet* NetETernary::synthesize(Design *des)
|
||||
|
||||
perm_string path = csig->scope()->local_symbol();
|
||||
|
||||
assert(csig->vector_width() == 1);
|
||||
ivl_assert(*this, csig->vector_width() == 1);
|
||||
|
||||
unsigned width=expr_width();
|
||||
NetNet*osig = new NetNet(csig->scope(), path, NetNet::IMPLICIT, width);
|
||||
@@ -1025,26 +1178,25 @@ NetNet* NetETernary::synthesize(Design *des)
|
||||
* a bit more work needs to be done. Return a temporary that represents
|
||||
* the selected word.
|
||||
*/
|
||||
NetNet* NetESignal::synthesize(Design*des)
|
||||
NetNet* NetESignal::synthesize(Design*des, NetScope*scope)
|
||||
{
|
||||
if (word_ == 0)
|
||||
return net_;
|
||||
|
||||
NetScope*scope = net_->scope();
|
||||
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, net_->vector_width());
|
||||
tmp->set_line(*this);
|
||||
tmp->local_flag(true);
|
||||
tmp->data_type(net_->data_type());
|
||||
|
||||
// For NetExpr objects, the word index is already converted to
|
||||
// a canonical (lsb==0) address. Just use the index directly.
|
||||
|
||||
if (NetEConst*index_co = dynamic_cast<NetEConst*> (word_)) {
|
||||
|
||||
long index = index_co->value().as_long();
|
||||
|
||||
assert(net_->array_index_is_valid(index));
|
||||
index = net_->array_index_to_address(index);
|
||||
|
||||
connect(tmp->pin(0), net_->pin(index));
|
||||
|
||||
} else {
|
||||
unsigned selwid = word_->expr_width();
|
||||
|
||||
@@ -1053,7 +1205,7 @@ NetNet* NetESignal::synthesize(Design*des)
|
||||
mux->set_line(*this);
|
||||
des->add_node(mux);
|
||||
|
||||
NetNet*index_net = word_->synthesize(des);
|
||||
NetNet*index_net = word_->synthesize(des, scope);
|
||||
connect(mux->pin_Address(), index_net->pin(0));
|
||||
|
||||
connect(tmp->pin(0), mux->pin_Result());
|
||||
@@ -1061,22 +1213,68 @@ NetNet* NetESignal::synthesize(Design*des)
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetNet* NetESFunc::synthesize(Design*des)
|
||||
NetNet* NetESFunc::synthesize(Design*des, NetScope*scope)
|
||||
{
|
||||
cerr << get_fileline() << ": sorry: cannot synthesize system function: "
|
||||
<< *this << " in this context" << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
|
||||
const struct sfunc_return_type*def = lookup_sys_func(name_);
|
||||
|
||||
/* We cannot use the default value for system functions in a
|
||||
* continuous assignment since the function name is NULL. */
|
||||
if (def == 0 || def->name == 0) {
|
||||
cerr << get_fileline() << ": error: System function "
|
||||
<< name_ << " not defined in system "
|
||||
"table or SFT file(s)." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: Net system function "
|
||||
<< name_ << " returns " << def->type << endl;
|
||||
}
|
||||
|
||||
NetSysFunc*net = new NetSysFunc(scope, scope->local_symbol(),
|
||||
def, 1+nparms_);
|
||||
net->set_line(*this);
|
||||
des->add_node(net);
|
||||
|
||||
NetNet*osig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, def->wid);
|
||||
osig->local_flag(true);
|
||||
osig->set_signed(def->type==IVL_VT_REAL? true : false);
|
||||
osig->data_type(def->type);
|
||||
osig->set_line(*this);
|
||||
|
||||
connect(net->pin(0), osig->pin(0));
|
||||
|
||||
unsigned errors = 0;
|
||||
for (unsigned idx = 0 ; idx < nparms_ ; idx += 1) {
|
||||
NetNet*tmp = parms_[idx]->synthesize(des, scope);
|
||||
if (tmp == 0) {
|
||||
cerr << get_fileline() << ": error: Unable to elaborate "
|
||||
<< "argument " << idx << " of call to " << name_ <<
|
||||
"." << endl;
|
||||
errors += 1;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
connect(net->pin(1+idx), tmp->pin(0));
|
||||
}
|
||||
|
||||
if (errors > 0) return 0;
|
||||
|
||||
return osig;
|
||||
}
|
||||
|
||||
NetNet* NetEUFunc::synthesize(Design*des)
|
||||
NetNet* NetEUFunc::synthesize(Design*des, NetScope*scope)
|
||||
{
|
||||
svector<NetNet*> eparms (parms_.count());
|
||||
|
||||
/* Synthesize the arguments. */
|
||||
bool errors = false;
|
||||
for (unsigned idx = 0; idx < eparms.count(); idx += 1) {
|
||||
NetNet*tmp = parms_[idx]->synthesize(des);
|
||||
NetNet*tmp = parms_[idx]->synthesize(des, scope);
|
||||
if (tmp == 0) {
|
||||
cerr << get_fileline() << ": error: Unable to synthesize "
|
||||
"port " << idx << " of call to "
|
||||
@@ -1103,7 +1301,7 @@ NetNet* NetEUFunc::synthesize(Design*des)
|
||||
/* Connect the pins to the arguments. */
|
||||
NetFuncDef*def = func_->func_def();
|
||||
for (unsigned idx = 0; idx < eparms.count(); idx += 1) {
|
||||
NetNet*tmp = pad_to_width(des, eparms[idx],
|
||||
NetNet*tmp = pad_to_width(des, eparms[idx],
|
||||
def->port(idx)->vector_width());
|
||||
connect(net->pin(idx+1), tmp->pin(0));
|
||||
}
|
||||
|
||||
+5
-13
@@ -111,20 +111,12 @@ void NetScope::run_functor(Design*des, functor_t*fun)
|
||||
|
||||
// apply to signals. Each iteration, allow for the possibility
|
||||
// that the current signal deletes itself.
|
||||
if (signals_) {
|
||||
unsigned count = 0;
|
||||
NetNet*cur = signals_->sig_next_;
|
||||
do {
|
||||
count += 1;
|
||||
cur = cur->sig_next_;
|
||||
} while (cur != signals_->sig_next_);
|
||||
|
||||
cur = signals_->sig_next_;
|
||||
for (unsigned idx = 0 ; idx < count ; idx += 1) {
|
||||
NetNet*tmp = cur->sig_next_;
|
||||
fun->signal(des, cur);
|
||||
cur = tmp;
|
||||
}
|
||||
signals_map_iter_t cur = signals_map_.begin();
|
||||
while (cur != signals_map_.end()) {
|
||||
signals_map_iter_t tmp = cur;
|
||||
cur ++;
|
||||
fun->signal(des, tmp->second);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
-3
@@ -17,17 +17,18 @@
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: iverilog-vpi.sh,v 1.17 2007/02/06 05:07:31 steve Exp $"
|
||||
|
||||
# These are the variables used for compiling files
|
||||
CC=@IVCC@
|
||||
CXX=@IVCXX@
|
||||
CFLAGS="@PIC@ @IVCFLAGS@ -I@INCLUDEDIR@"
|
||||
|
||||
SUFFIX=@SUFFIX@
|
||||
|
||||
# These are used for linking...
|
||||
LD=$CC
|
||||
LDFLAGS="@SHARED@ -L@LIBDIR@"
|
||||
LDLIBS="-lveriuser -lvpi"
|
||||
LDLIBS="-lveriuser$SUFFIX -lvpi$SUFFIX"
|
||||
|
||||
CCSRC=
|
||||
CXSRC=
|
||||
@@ -101,7 +102,7 @@ do
|
||||
;;
|
||||
|
||||
--install-dir)
|
||||
echo "@LIBDIR@/ivl"
|
||||
echo "@LIBDIR@/ivl$SUFFIX"
|
||||
exit
|
||||
;;
|
||||
esac
|
||||
|
||||
@@ -15,6 +15,9 @@ ivl_const_signed
|
||||
ivl_const_type
|
||||
ivl_const_width
|
||||
|
||||
ivl_discipline_domain
|
||||
ivl_discipline_name
|
||||
|
||||
ivl_event_any
|
||||
ivl_event_basename
|
||||
ivl_event_name
|
||||
@@ -143,6 +146,7 @@ ivl_scope_def_lineno
|
||||
ivl_scope_event
|
||||
ivl_scope_events
|
||||
ivl_scope_file
|
||||
ivl_scope_is_auto
|
||||
ivl_scope_lineno
|
||||
ivl_scope_logs
|
||||
ivl_scope_log
|
||||
@@ -171,6 +175,7 @@ ivl_signal_attr_val
|
||||
ivl_signal_basename
|
||||
ivl_signal_data_type
|
||||
ivl_signal_dimensions
|
||||
ivl_signal_discipline
|
||||
ivl_signal_file
|
||||
ivl_signal_integer
|
||||
ivl_signal_lineno
|
||||
@@ -191,6 +196,8 @@ ivl_path_source
|
||||
|
||||
ivl_process_attr_cnt
|
||||
ivl_process_attr_val
|
||||
ivl_process_file
|
||||
ivl_process_lineno
|
||||
ivl_process_scope
|
||||
ivl_process_stmt
|
||||
ivl_process_type
|
||||
|
||||
+55
-5
@@ -151,6 +151,7 @@ _BEGIN_DECL
|
||||
typedef struct ivl_array_s *ivl_array_t;
|
||||
typedef struct ivl_delaypath_s*ivl_delaypath_t;
|
||||
typedef struct ivl_design_s *ivl_design_t;
|
||||
typedef struct ivl_discipline_s*ivl_discipline_t;
|
||||
typedef struct ivl_event_s *ivl_event_t;
|
||||
typedef struct ivl_expr_s *ivl_expr_t;
|
||||
typedef struct ivl_island_s *ivl_island_t;
|
||||
@@ -159,6 +160,7 @@ typedef struct ivl_lval_s *ivl_lval_t;
|
||||
typedef struct ivl_net_const_s*ivl_net_const_t;
|
||||
typedef struct ivl_net_logic_s*ivl_net_logic_t;
|
||||
typedef struct ivl_udp_s *ivl_udp_t;
|
||||
typedef struct ivl_nature_s *ivl_nature_t;
|
||||
typedef struct ivl_net_probe_s*ivl_net_probe_t;
|
||||
typedef struct ivl_nexus_s *ivl_nexus_t;
|
||||
typedef struct ivl_nexus_ptr_s*ivl_nexus_ptr_t;
|
||||
@@ -176,6 +178,12 @@ typedef struct ivl_statement_s*ivl_statement_t;
|
||||
* changes and additions to the enumerations.
|
||||
*/
|
||||
|
||||
typedef enum ivl_dis_domain_e {
|
||||
IVL_DIS_NONE = 0,
|
||||
IVL_DIS_DISCRETE = 1,
|
||||
IVL_DIS_CONTINUOUS = 2
|
||||
} ivl_dis_domain_t;
|
||||
|
||||
typedef enum ivl_drive_e {
|
||||
IVL_DR_HiZ = 0,
|
||||
IVL_DR_SMALL = 1,
|
||||
@@ -193,6 +201,7 @@ typedef enum ivl_drive_e {
|
||||
typedef enum ivl_expr_type_e {
|
||||
IVL_EX_NONE = 0,
|
||||
IVL_EX_ARRAY = 18,
|
||||
IVL_EX_BACCESS= 19,
|
||||
IVL_EX_BINARY = 2,
|
||||
IVL_EX_CONCAT = 3,
|
||||
IVL_EX_EVENT = 17,
|
||||
@@ -254,6 +263,8 @@ typedef enum ivl_lpm_type_e {
|
||||
IVL_LPM_ABS = 32,
|
||||
IVL_LPM_ADD = 0,
|
||||
IVL_LPM_ARRAY = 30,
|
||||
IVL_LPM_CAST_INT = 34,
|
||||
IVL_LPM_CAST_REAL = 33,
|
||||
IVL_LPM_CONCAT = 16,
|
||||
IVL_LPM_CMP_EEQ= 18, /* Case EQ (===) */
|
||||
IVL_LPM_CMP_EQ = 10,
|
||||
@@ -340,6 +351,7 @@ typedef enum ivl_signal_type_e {
|
||||
typedef enum ivl_statement_type_e {
|
||||
IVL_ST_NONE = 0,
|
||||
IVL_ST_NOOP = 1,
|
||||
IVL_ST_ALLOC = 25,
|
||||
IVL_ST_ASSIGN = 2,
|
||||
IVL_ST_ASSIGN_NB = 3,
|
||||
IVL_ST_BLOCK = 4,
|
||||
@@ -356,6 +368,7 @@ typedef enum ivl_statement_type_e {
|
||||
IVL_ST_FORCE = 14,
|
||||
IVL_ST_FOREVER = 15,
|
||||
IVL_ST_FORK = 16,
|
||||
IVL_ST_FREE = 26,
|
||||
IVL_ST_RELEASE = 17,
|
||||
IVL_ST_REPEAT = 18,
|
||||
IVL_ST_STASK = 19,
|
||||
@@ -499,7 +512,8 @@ extern ivl_net_const_t ivl_design_const(ivl_design_t, unsigned idx);
|
||||
* ivl_const_bits
|
||||
* This returns a pointer to an array of constant characters,
|
||||
* each byte a '0', '1', 'x' or 'z'. The array is *not* nul
|
||||
* terminated.
|
||||
* terminated. This value is only value if ivl_const_type is
|
||||
* IVL_VT_LOGIC or IVL_VT_BOOL. It returns nil otherwise.
|
||||
*
|
||||
* ivl_const_nex
|
||||
* Return the ivl_nexus_t of the output for the constant.
|
||||
@@ -537,6 +551,28 @@ extern double ivl_const_real(ivl_net_const_t net);
|
||||
/* extern ivl_nexus_t ivl_const_pin(ivl_net_const_t net, unsigned idx); */
|
||||
/* extern unsigned ivl_const_pins(ivl_net_const_t net); */
|
||||
|
||||
/* DISCIPLINES
|
||||
*
|
||||
* Disciplines are Verilog-AMS construct. A discipline is a collection
|
||||
* of attributes that can be attached to a signal.
|
||||
*
|
||||
* FUNCTION SUMMARY
|
||||
*
|
||||
* ivl_discipline_name
|
||||
* This is the name of the discipline in the Verilog-AMS source.
|
||||
*
|
||||
* ivl_discipline_domain
|
||||
* This is the domain: continuous or discrete.
|
||||
*
|
||||
* SEMANTIC NOTES
|
||||
*
|
||||
* The discipline domain will not be IVL_DIS_NONE. The "none" domain
|
||||
* is a place-holder internally for incomplete parsing, and is also
|
||||
* available for code generaters to use.
|
||||
*/
|
||||
extern const char*ivl_discipline_name(ivl_discipline_t net);
|
||||
extern ivl_dis_domain_t ivl_discipline_domain(ivl_discipline_t net);
|
||||
|
||||
/* EVENTS
|
||||
*
|
||||
* Events are a unification of named events and implicit events
|
||||
@@ -986,8 +1022,9 @@ extern unsigned ivl_lpm_lineno(ivl_lpm_t net);
|
||||
* more than the width of the output, although the possibility of
|
||||
* overflow exists at run time.
|
||||
*
|
||||
* Multiply may be signed. If so, the output should be sign extended
|
||||
* to fill in its result.
|
||||
* The inputs are always treated as unsigned. If the expression is
|
||||
* supposed to be signed, elaboration will generate the necessary sign
|
||||
* extension, so the target need not (must not) consider signedness.
|
||||
*
|
||||
* - Power (IVL_LPM_POW)
|
||||
* The power takes two inputs and generates an output. Unlike other
|
||||
@@ -1251,7 +1288,7 @@ extern const char*ivl_lpm_string(ivl_lpm_t net);
|
||||
*/
|
||||
|
||||
extern unsigned ivl_lval_width(ivl_lval_t net);
|
||||
extern ivl_expr_t ivl_lval_mux(ivl_lval_t net); // XXXX Obsolete?
|
||||
extern ivl_expr_t ivl_lval_mux(ivl_lval_t net); /* XXXX Obsolete? */
|
||||
extern ivl_expr_t ivl_lval_idx(ivl_lval_t net);
|
||||
extern ivl_expr_t ivl_lval_part_off(ivl_lval_t net);
|
||||
extern ivl_signal_t ivl_lval_sig(ivl_lval_t net);
|
||||
@@ -1445,6 +1482,9 @@ extern unsigned ivl_parameter_lineno(ivl_parameter_t net);
|
||||
* ivl_scope_lineno
|
||||
* Returns the instantiation file and line for this scope.
|
||||
*
|
||||
* ivl_scope_is_auto
|
||||
* Is the task or function declared to be automatic?
|
||||
*
|
||||
* ivl_scope_var
|
||||
* ivl_scope_vars
|
||||
* REMOVED
|
||||
@@ -1521,6 +1561,7 @@ extern unsigned ivl_scope_def_lineno(ivl_scope_t net);
|
||||
extern unsigned ivl_scope_events(ivl_scope_t net);
|
||||
extern ivl_event_t ivl_scope_event(ivl_scope_t net, unsigned idx);
|
||||
extern const char* ivl_scope_file(ivl_scope_t net);
|
||||
extern unsigned ivl_scope_is_auto(ivl_scope_t net);
|
||||
extern unsigned ivl_scope_lineno(ivl_scope_t net);
|
||||
extern unsigned ivl_scope_logs(ivl_scope_t net);
|
||||
extern ivl_net_logic_t ivl_scope_log(ivl_scope_t net, unsigned idx);
|
||||
@@ -1573,6 +1614,10 @@ extern int ivl_scope_time_units(ivl_scope_t net);
|
||||
* The signal may be an array (of vectors) in which case this
|
||||
* function returns >0, the number of dimensions of the array.
|
||||
*
|
||||
* ivl_signal_discipline
|
||||
* If the signal has been declared with a domain (Verilog-AMS) then
|
||||
* this function wil return a non-nil ivl_discipline_t.
|
||||
*
|
||||
* ivl_signal_msb
|
||||
* ivl_signal_lsb
|
||||
* ivl_signal_width
|
||||
@@ -1640,6 +1685,7 @@ extern ivl_nexus_t ivl_signal_nex(ivl_signal_t net, unsigned word);
|
||||
extern int ivl_signal_array_base(ivl_signal_t net);
|
||||
extern unsigned ivl_signal_array_count(ivl_signal_t net);
|
||||
extern unsigned ivl_signal_dimensions(ivl_signal_t net);
|
||||
extern ivl_discipline_t ivl_signal_discipline(ivl_signal_t net);
|
||||
extern int ivl_signal_msb(ivl_signal_t net);
|
||||
extern int ivl_signal_lsb(ivl_signal_t net);
|
||||
extern unsigned ivl_signal_width(ivl_signal_t net);
|
||||
@@ -1693,6 +1739,9 @@ extern ivl_statement_t ivl_process_stmt(ivl_process_t net);
|
||||
extern unsigned ivl_process_attr_cnt(ivl_process_t net);
|
||||
extern ivl_attribute_t ivl_process_attr_val(ivl_process_t net, unsigned idx);
|
||||
|
||||
extern const char* ivl_process_file(ivl_process_t net);
|
||||
extern unsigned ivl_process_lineno(ivl_process_t net);
|
||||
|
||||
/*
|
||||
* These functions manage statements of various type. This includes
|
||||
* all the different kinds of statements (as enumerated in
|
||||
@@ -1917,7 +1966,7 @@ extern unsigned ivl_switch_lineno(ivl_switch_t net);
|
||||
#endif
|
||||
|
||||
extern DLLEXPORT int target_design(ivl_design_t des);
|
||||
|
||||
extern DLLEXPORT const char* target_query(const char*key);
|
||||
|
||||
/* target_design
|
||||
|
||||
@@ -1935,6 +1984,7 @@ extern DLLEXPORT int target_design(ivl_design_t des);
|
||||
ivl core. This function is how the target module is invoked. */
|
||||
|
||||
typedef int (*target_design_f)(ivl_design_t des);
|
||||
typedef const char* (*target_query_f) (const char*key);
|
||||
|
||||
|
||||
_END_DECL
|
||||
|
||||
+8
-6
@@ -25,6 +25,8 @@ SHELL = /bin/sh
|
||||
|
||||
VERSION = 0.0
|
||||
|
||||
suffix = @install_suffix@
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
srcdir = @srcdir@
|
||||
@@ -40,7 +42,7 @@ INSTALL = @INSTALL@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
|
||||
CPPFLAGS = @ident_support@ -I. -I.. -I$(srcdir)/.. -I$(srcdir) @CPPFLAGS@ @DEFS@
|
||||
CPPFLAGS = @ident_support@ -I. -I.. -I$(srcdir)/.. -I$(srcdir) -DVERSION='"$(VERSION)"' @CPPFLAGS@ @DEFS@
|
||||
CFLAGS = -Wall @CFLAGS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
|
||||
@@ -60,16 +62,16 @@ ivlpp@EXEEXT@: $O
|
||||
lexor.c: lexor.lex
|
||||
flex -olexor.c $(srcdir)/lexor.lex
|
||||
|
||||
install: all installdirs $(libdir)/ivl/ivlpp@EXEEXT@
|
||||
install: all installdirs $(libdir)/ivl$(suffix)/ivlpp@EXEEXT@
|
||||
|
||||
$(libdir)/ivl/ivlpp@EXEEXT@: ivlpp@EXEEXT@
|
||||
$(INSTALL_PROGRAM) ./ivlpp@EXEEXT@ $(libdir)/ivl/ivlpp@EXEEXT@
|
||||
$(libdir)/ivl$(suffix)/ivlpp@EXEEXT@: ivlpp@EXEEXT@
|
||||
$(INSTALL_PROGRAM) ./ivlpp@EXEEXT@ $(DESTDIR)$(libdir)/ivl$(suffix)/ivlpp@EXEEXT@
|
||||
|
||||
installdirs: ../mkinstalldirs
|
||||
$(srcdir)/../mkinstalldirs $(libdir)/ivl
|
||||
$(srcdir)/../mkinstalldirs $(DESTDIR)$(libdir)/ivl$(suffix)
|
||||
|
||||
uninstall:
|
||||
rm -f $(libdir)/ivl/ivlpp@EXEEXT@
|
||||
rm -f $(DESTDIR)$(libdir)/ivl$(suffix)/ivlpp@EXEEXT@
|
||||
|
||||
lexor.o: lexor.c globals.h
|
||||
main.o: main.c globals.h
|
||||
|
||||
+3
-1
@@ -1,7 +1,7 @@
|
||||
#ifndef __globals_H
|
||||
#define __globals_H
|
||||
/*
|
||||
* Copyright (c) 1999-2007 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2008 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
|
||||
@@ -22,9 +22,11 @@
|
||||
# include <stdio.h>
|
||||
|
||||
extern void reset_lexor(FILE*out, char*paths[]);
|
||||
extern void destroy_lexor();
|
||||
extern void load_precompiled_defines(FILE*src);
|
||||
extern void define_macro(const char*name, const char*value, int keyword,
|
||||
int argc);
|
||||
extern void free_macros();
|
||||
extern void dump_precompiled_defines(FILE*out);
|
||||
|
||||
/* These variables contain the include directories to be searched when
|
||||
|
||||
+74
-12
@@ -78,6 +78,9 @@ struct include_stack_t
|
||||
YY_BUFFER_STATE yybs;
|
||||
|
||||
struct include_stack_t* next;
|
||||
|
||||
/* A single line comment can be associated with this include. */
|
||||
char* comment;
|
||||
};
|
||||
|
||||
static void emit_pathline(struct include_stack_t* isp);
|
||||
@@ -115,7 +118,7 @@ static void ifdef_enter(void)
|
||||
struct ifdef_stack_t*cur;
|
||||
|
||||
cur = (struct ifdef_stack_t*) calloc(1, sizeof(struct ifdef_stack_t));
|
||||
cur->path = strdup(istack->path);
|
||||
if (istack->path) cur->path = strdup(istack->path);
|
||||
cur->lineno = istack->lineno;
|
||||
cur->next = ifdef_stack;
|
||||
|
||||
@@ -131,8 +134,10 @@ static void ifdef_leave(void)
|
||||
cur = ifdef_stack;
|
||||
ifdef_stack = cur->next;
|
||||
|
||||
if (strcmp(istack->path,cur->path) != 0)
|
||||
{
|
||||
/* If either path is from a non-file context e.g.(macro expansion)
|
||||
* we assume that the non-file part is from this file. */
|
||||
if (istack->path != NULL && cur->path != NULL &&
|
||||
strcmp(istack->path,cur->path) != 0) {
|
||||
fprintf
|
||||
(
|
||||
stderr,
|
||||
@@ -293,9 +298,10 @@ keywords (include|define|undef|ifdef|ifndef|else|elseif|endif)
|
||||
|
||||
/* Catch single-line comments that share the line with an include
|
||||
* directive. And while I'm at it, I might as well preserve the
|
||||
* comment in the output stream.
|
||||
* comment in the output stream. This will be printed after the
|
||||
* file has been included.
|
||||
*/
|
||||
<PPINCLUDE>"//"[^\r\n]* { ECHO; }
|
||||
<PPINCLUDE>"//"[^\r\n]* { standby->comment = strdup(yytext); }
|
||||
|
||||
/* These finish the include directive (EOF or EOL) so I revert the
|
||||
* lexor state and execute the inclusion.
|
||||
@@ -696,7 +702,7 @@ static int is_defined(const char*name)
|
||||
* These variables are also used for storing the actual arguments when
|
||||
* a macro is instantiated.
|
||||
*/
|
||||
#define MAX_DEF_ARG 256 // allows argument IDs to be stored in a single char
|
||||
#define MAX_DEF_ARG 256 /* allows argument IDs to be stored in a single char */
|
||||
|
||||
#define DEF_BUF_CHUNK 256
|
||||
|
||||
@@ -705,14 +711,14 @@ static int def_buf_size = 0;
|
||||
static int def_buf_free = 0;
|
||||
|
||||
static int def_argc = 0;
|
||||
static int def_argo[MAX_DEF_ARG]; // offset of first character in arg
|
||||
static int def_argl[MAX_DEF_ARG]; // length of arg string.
|
||||
static int def_argo[MAX_DEF_ARG]; /* offset of first character in arg */
|
||||
static int def_argl[MAX_DEF_ARG]; /* length of arg string. */
|
||||
|
||||
/*
|
||||
* Return a pointer to the start of argument 'arg'. Returned pointers
|
||||
* may go stale after a call to def_buf_grow_to_fit.
|
||||
*/
|
||||
static inline char* def_argv(int arg)
|
||||
static /* inline */ char* def_argv(int arg)
|
||||
{
|
||||
return def_buf + def_argo[arg];
|
||||
}
|
||||
@@ -827,6 +833,21 @@ void define_macro(const char* name, const char* value, int keyword, int argc)
|
||||
}
|
||||
}
|
||||
|
||||
static void free_macro(struct define_t* def)
|
||||
{
|
||||
if (def == 0) return;
|
||||
free_macro(def->left);
|
||||
free_macro(def->right);
|
||||
free(def->name);
|
||||
free(def->value);
|
||||
free(def);
|
||||
}
|
||||
|
||||
void free_macros()
|
||||
{
|
||||
free_macro(def_table);
|
||||
}
|
||||
|
||||
/*
|
||||
* The do_define function accumulates the defined value in these
|
||||
* variables. When the define is over, the def_finish() function
|
||||
@@ -856,6 +877,7 @@ static int define_continue_flag = 0;
|
||||
static char *find_arg(char*ptr, char*head, char*arg)
|
||||
{
|
||||
char *cp = ptr;
|
||||
size_t len = strlen(arg);
|
||||
|
||||
while (1) {
|
||||
/* Look for a candidate match, just return if none is found. */
|
||||
@@ -866,7 +888,8 @@ static char *find_arg(char*ptr, char*head, char*arg)
|
||||
* match is not in the middle of another identifier.
|
||||
*/
|
||||
if (cp != head &&
|
||||
(isalnum(*(cp-1)) || *(cp-1) == '_' || *(cp-1) == '$')) {
|
||||
(isalnum(*(cp-1)) || *(cp-1) == '_' || *(cp-1) == '$' ||
|
||||
isalnum(*(cp+len)) || *(cp+len) == '_' || *(cp+len) == '$')) {
|
||||
cp++;
|
||||
continue;
|
||||
}
|
||||
@@ -941,7 +964,7 @@ static void do_define()
|
||||
}
|
||||
|
||||
/* Detect the continuation sequence. If I find it, remove it
|
||||
* and the white space that preceeds it, then replace all that
|
||||
* and the white space that precedes it, then replace all that
|
||||
* with a single newline.
|
||||
*/
|
||||
if ((cp > yytext) && (cp[-1] == '\\'))
|
||||
@@ -1414,6 +1437,7 @@ static void include_filename()
|
||||
standby->path = strdup(yytext+1);
|
||||
standby->path[strlen(standby->path)-1] = 0;
|
||||
standby->lineno = 0;
|
||||
standby->comment = NULL;
|
||||
}
|
||||
|
||||
static void do_include()
|
||||
@@ -1453,6 +1477,8 @@ static void do_include()
|
||||
|
||||
if ((standby->file = fopen(path, "r")))
|
||||
{
|
||||
/* Free the original path before we overwrite it. */
|
||||
free(standby->path);
|
||||
standby->path = strdup(path);
|
||||
goto code_that_switches_buffers;
|
||||
}
|
||||
@@ -1464,11 +1490,14 @@ static void do_include()
|
||||
|
||||
code_that_switches_buffers:
|
||||
|
||||
/* Clear the current files path from the search list. */
|
||||
include_dir[0] = 0;
|
||||
|
||||
if(depend_file)
|
||||
fprintf(depend_file, "%s\n", standby->path);
|
||||
|
||||
if (line_direct_flag)
|
||||
fprintf(yyout, "\n`line %u \"%s\" 1\n", istack->lineno+1, standby->path);
|
||||
fprintf(yyout, "\n`line 1 \"%s\" 1\n", standby->path);
|
||||
|
||||
standby->next = istack;
|
||||
standby->stringify_flag = 0;
|
||||
@@ -1526,6 +1555,17 @@ static int load_next_input()
|
||||
/* Delete the current input buffers, and free the cell. */
|
||||
yy_delete_buffer(YY_CURRENT_BUFFER);
|
||||
|
||||
/* If there was a comment for this include print it before we
|
||||
* return to the previous input stream. This technically belongs
|
||||
* to the previous stream, but it should not create any problems
|
||||
* since it is only a comment.
|
||||
*/
|
||||
if (isp->comment) {
|
||||
fprintf(yyout, "%s\n", isp->comment);
|
||||
free(isp->comment);
|
||||
isp->comment = NULL;
|
||||
}
|
||||
|
||||
if (isp->file)
|
||||
{
|
||||
free(isp->path);
|
||||
@@ -1584,6 +1624,12 @@ static int load_next_input()
|
||||
if(depend_file)
|
||||
fprintf(depend_file, "%s\n", istack->path);
|
||||
|
||||
/* This works around an issue in flex yyrestart() where it
|
||||
* uses yyin to create a new buffer when one does not exist.
|
||||
* I would have assumed that it would use the file argument.
|
||||
* The problem is that we have deleted the buffer and freed
|
||||
* yyin (isp->file) above. */
|
||||
yyin = 0;
|
||||
yyrestart(istack->file);
|
||||
return 1;
|
||||
}
|
||||
@@ -1716,6 +1762,7 @@ void reset_lexor(FILE* out, char* paths[])
|
||||
isp->ebs = 0;
|
||||
isp->lineno = 0;
|
||||
isp->stringify_flag = 0;
|
||||
isp->comment = NULL;
|
||||
|
||||
if (isp->file == 0)
|
||||
{
|
||||
@@ -1746,6 +1793,7 @@ void reset_lexor(FILE* out, char* paths[])
|
||||
isp->next = 0;
|
||||
isp->lineno = 0;
|
||||
isp->stringify_flag = 0;
|
||||
isp->comment = NULL;
|
||||
|
||||
if (tail)
|
||||
tail->next = isp;
|
||||
@@ -1755,3 +1803,17 @@ void reset_lexor(FILE* out, char* paths[])
|
||||
tail = isp;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Modern version of flex (>=2.5.9) can clean up the scanner data.
|
||||
*/
|
||||
void destroy_lexor()
|
||||
{
|
||||
# ifdef FLEX_SCANNER
|
||||
# if YY_FLEX_MAJOR_VERSION >= 2 && YY_FLEX_MINOR_VERSION >= 5
|
||||
# if defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9
|
||||
yylex_destroy();
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
}
|
||||
|
||||
+33
-9
@@ -17,7 +17,8 @@ const char COPYRIGHT[] =
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
# include "config.h"
|
||||
# include "config.h"
|
||||
# include "version.h"
|
||||
|
||||
const char NOTICE[] =
|
||||
" This program is free software; you can redistribute it and/or modify\n"
|
||||
@@ -35,8 +36,6 @@ const char NOTICE[] =
|
||||
" Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA\n"
|
||||
;
|
||||
|
||||
const char VERSION[] = "$Name: $ $State: Exp $";
|
||||
|
||||
# include <stdio.h>
|
||||
# include <stdlib.h>
|
||||
#ifdef HAVE_MALLOC_H
|
||||
@@ -103,6 +102,8 @@ static int flist_read_flags(const char*path)
|
||||
char*cp = line_buf + strspn(line_buf, " \t\r\b\f");
|
||||
/* Remove trailing white space. */
|
||||
char*tail = cp + strlen(cp);
|
||||
char*arg;
|
||||
|
||||
while (tail > cp) {
|
||||
if (! isspace(tail[-1]))
|
||||
break;
|
||||
@@ -118,7 +119,7 @@ static int flist_read_flags(const char*path)
|
||||
continue;
|
||||
|
||||
/* The arg points to the argument to the keyword. */
|
||||
char*arg = strchr(cp, ':');
|
||||
arg = strchr(cp, ':');
|
||||
if (arg) *arg++ = 0;
|
||||
|
||||
if (strcmp(cp,"D") == 0) {
|
||||
@@ -188,12 +189,14 @@ static int flist_read_names(const char*path)
|
||||
add_source_file(cp);
|
||||
}
|
||||
|
||||
fclose(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char*argv[])
|
||||
{
|
||||
int opt, idx;
|
||||
unsigned lp;
|
||||
const char*flist_path = 0;
|
||||
unsigned flag_errors = 0;
|
||||
char*out_path = 0;
|
||||
@@ -229,7 +232,7 @@ int main(int argc, char*argv[])
|
||||
include_dir[0] = 0; /* 0 is reserved for the current files path. */
|
||||
include_dir[1] = strdup(".");
|
||||
|
||||
while ((opt=getopt(argc, argv, "F:f:K:Lo:p:P:v")) != EOF) switch (opt) {
|
||||
while ((opt=getopt(argc, argv, "F:f:K:Lo:p:P:vV")) != EOF) switch (opt) {
|
||||
|
||||
case 'F':
|
||||
flist_read_flags(optarg);
|
||||
@@ -282,14 +285,21 @@ int main(int argc, char*argv[])
|
||||
fclose(src);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case 'v':
|
||||
fprintf(stderr, "Icarus Verilog Preprocessor version %s\n",
|
||||
VERSION);
|
||||
fprintf(stderr, "Icarus Verilog Preprocessor version "
|
||||
VERSION " (" VERSION_TAG ")\n\n");
|
||||
fprintf(stderr, "%s\n", COPYRIGHT);
|
||||
fputs(NOTICE, stderr);
|
||||
break;
|
||||
|
||||
case 'V':
|
||||
fprintf(stdout, "Icarus Verilog Preprocessor version "
|
||||
VERSION " (" VERSION_TAG ")\n\n");
|
||||
fprintf(stdout, "%s\n", COPYRIGHT);
|
||||
fputs(NOTICE, stdout);
|
||||
return 0;
|
||||
|
||||
default:
|
||||
flag_errors += 1;
|
||||
break;
|
||||
@@ -304,7 +314,8 @@ int main(int argc, char*argv[])
|
||||
" -o<fil> - Send the output to <fil>\n"
|
||||
" -p<fil> - Write precompiled defines to <fil>\n"
|
||||
" -P<fil> - Read precompiled defines from <fil>\n"
|
||||
" -v - Print version information\n",
|
||||
" -v - Verbose\n"
|
||||
" -V - Print version information and quit\n",
|
||||
argv[0]);
|
||||
return flag_errors;
|
||||
}
|
||||
@@ -359,6 +370,7 @@ int main(int argc, char*argv[])
|
||||
start scanning. */
|
||||
reset_lexor(out, source_list);
|
||||
if (yylex()) return -1;
|
||||
destroy_lexor();
|
||||
|
||||
if(depend_file) {
|
||||
fclose(depend_file);
|
||||
@@ -369,5 +381,17 @@ int main(int argc, char*argv[])
|
||||
fclose(precomp_out);
|
||||
}
|
||||
|
||||
/* Free the source and include directory lists. */
|
||||
for (lp = 0; lp < source_cnt; lp += 1) {
|
||||
free(source_list[lp]);
|
||||
}
|
||||
free(source_list);
|
||||
for (lp = 0; lp < include_cnt; lp += 1) {
|
||||
free(include_dir[lp]);
|
||||
}
|
||||
free(include_dir);
|
||||
|
||||
free_macros();
|
||||
|
||||
return error_count;
|
||||
}
|
||||
|
||||
@@ -87,6 +87,7 @@ static void process_timescale(const char*txt);
|
||||
static list<int> keyword_mask_stack;
|
||||
|
||||
static int comment_enter;
|
||||
static bool in_module = false;
|
||||
%}
|
||||
|
||||
%x CCOMMENT
|
||||
@@ -123,8 +124,8 @@ S [afpnumkKMGT]
|
||||
/* The contents of C-style comments are ignored, like white space. */
|
||||
|
||||
"/*" { comment_enter = YY_START; BEGIN(CCOMMENT); }
|
||||
<CCOMMENT>. { yymore(); }
|
||||
<CCOMMENT>\n { yylloc.first_line += 1; yymore(); }
|
||||
<CCOMMENT>. { ; }
|
||||
<CCOMMENT>\n { yylloc.first_line += 1; }
|
||||
<CCOMMENT>"*/" { BEGIN(comment_enter); }
|
||||
|
||||
|
||||
@@ -227,6 +228,15 @@ S [afpnumkKMGT]
|
||||
BEGIN(EDGES);
|
||||
break;
|
||||
|
||||
case K_module:
|
||||
case K_macromodule:
|
||||
in_module = true;
|
||||
break;
|
||||
|
||||
case K_endmodule:
|
||||
in_module = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
yylval.text = 0;
|
||||
break;
|
||||
@@ -237,7 +247,7 @@ S [afpnumkKMGT]
|
||||
value instead. */
|
||||
if (rc == IDENTIFIER && gn_verilog_ams_flag) {
|
||||
perm_string tmp = lex_strings.make(yylval.text);
|
||||
map<perm_string,discipline_t*>::iterator cur = disciplines.find(tmp);
|
||||
map<perm_string,ivl_discipline_t>::iterator cur = disciplines.find(tmp);
|
||||
if (cur != disciplines.end()) {
|
||||
yylval.discipline = (*cur).second;
|
||||
rc = DISCIPLINE_IDENTIFIER;
|
||||
@@ -343,6 +353,12 @@ S [afpnumkKMGT]
|
||||
^{W}?`timescale { BEGIN(PPTIMESCALE); }
|
||||
<PPTIMESCALE>.* { process_timescale(yytext); }
|
||||
<PPTIMESCALE>\n {
|
||||
if (in_module) {
|
||||
cerr << yylloc.text << ":" << yylloc.first_line << ": error: "
|
||||
"`timescale directive can not be inside a module "
|
||||
"definition." << endl;
|
||||
error_count += 1;
|
||||
}
|
||||
yylloc.first_line += 1;
|
||||
BEGIN(0); }
|
||||
|
||||
@@ -439,7 +455,7 @@ S [afpnumkKMGT]
|
||||
|
||||
} else {
|
||||
cerr << yylloc.text << ":" << yylloc.first_line
|
||||
<< " error: Net type " << yytext
|
||||
<< ": error: Net type " << yytext
|
||||
<< " is not a valid (and supported)"
|
||||
<< " default net type." << endl;
|
||||
net_type = NetNet::WIRE;
|
||||
@@ -457,37 +473,37 @@ S [afpnumkKMGT]
|
||||
|
||||
^{W}?`define{W}?.* {
|
||||
cerr << yylloc.text << ":" << yylloc.first_line <<
|
||||
": `define not supported. Use an external preprocessor."
|
||||
": warning: `define not supported. Use an external preprocessor."
|
||||
<< endl;
|
||||
}
|
||||
|
||||
^{W}?`else{W}?.* {
|
||||
cerr << yylloc.text << ":" << yylloc.first_line <<
|
||||
": `else not supported. Use an external preprocessor."
|
||||
": warning: `else not supported. Use an external preprocessor."
|
||||
<< endl;
|
||||
}
|
||||
|
||||
^{W}?`endif{W}?.* {
|
||||
cerr << yylloc.text << ":" << yylloc.first_line <<
|
||||
": `endif not supported. Use an external preprocessor."
|
||||
": warning: `endif not supported. Use an external preprocessor."
|
||||
<< endl;
|
||||
}
|
||||
|
||||
^{W}?`ifdef{W}?.* {
|
||||
cerr << yylloc.text << ":" << yylloc.first_line <<
|
||||
": `ifdef not supported. Use an external preprocessor."
|
||||
": warning: `ifdef not supported. Use an external preprocessor."
|
||||
<< endl;
|
||||
}
|
||||
|
||||
^`include{W}?.* {
|
||||
cerr << yylloc.text << ":" << yylloc.first_line <<
|
||||
": `include not supported. Use an external preprocessor."
|
||||
": warning: `include not supported. Use an external preprocessor."
|
||||
<< endl;
|
||||
}
|
||||
|
||||
^`undef{W}?.* {
|
||||
cerr << yylloc.text << ":" << yylloc.first_line <<
|
||||
": `undef not supported. Use an external preprocessor."
|
||||
": warning: `undef not supported. Use an external preprocessor."
|
||||
<< endl;
|
||||
}
|
||||
|
||||
@@ -843,7 +859,7 @@ static verinum*make_unsized_dec(const char*ptr)
|
||||
if (ptr[0] == '\'') {
|
||||
/* The number has decorations of the form 'sd<digits>,
|
||||
possibly with space between the d and the <digits>.
|
||||
Also, the 's' is optional, and markes the number as
|
||||
Also, the 's' is optional, and marks the number as
|
||||
signed. */
|
||||
ptr += 1;
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ assign, GN_KEYWORDS_1364_1995, K_assign
|
||||
atan, GN_KEYWORDS_VAMS_2_3, K_atan
|
||||
atan2, GN_KEYWORDS_VAMS_2_3, K_atan2
|
||||
atanh, GN_KEYWORDS_VAMS_2_3, K_atanh
|
||||
automatic, GN_KEYWORDS_1364_2001, K_automatic
|
||||
begin, GN_KEYWORDS_1364_1995, K_begin
|
||||
bool, GN_KEYWORDS_ICARUS, K_bool
|
||||
buf, GN_KEYWORDS_1364_1995, K_buf
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
|
||||
suffix = @install_suffix@
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
@@ -86,15 +87,15 @@ clean:
|
||||
distclean: clean
|
||||
rm -f Makefile config.status config.log config.cache config.h
|
||||
|
||||
install:: all installdirs $(libdir)/libveriuser.a $(INSTALL32)
|
||||
install:: all installdirs $(libdir)/libveriuser$(suffix).a $(INSTALL32)
|
||||
|
||||
$(libdir)/libveriuser.a: ./libveriuser.a
|
||||
$(INSTALL_DATA) ./libveriuser.a $(libdir)/libveriuser.a
|
||||
$(libdir)/libveriuser$(suffix).a: ./libveriuser.a
|
||||
$(INSTALL_DATA) ./libveriuser.a $(DESTDIR)$(libdir)/libveriuser$(suffix).a
|
||||
|
||||
installdirs: mkinstalldirs
|
||||
$(srcdir)/mkinstalldirs $(includedir) $(libdir)
|
||||
$(srcdir)/mkinstalldirs $(DESTDIR)$(includedir) $(DESTDIR)$(libdir)
|
||||
|
||||
uninstall::
|
||||
rm -f $(libdir)/libveriuser.a
|
||||
rm -f $(DESTDIR)$(libdir)/libveriuser$(suffix).a
|
||||
|
||||
-include $(patsubst %.o, dep/%.d, $O)
|
||||
|
||||
@@ -99,7 +99,7 @@ PLI_INT32 acc_fetch_fulltype(handle obj)
|
||||
return accTopModule;
|
||||
else
|
||||
return accModuleInstance;
|
||||
// FIXME accCellInstance
|
||||
/* FIXME accCellInstance */
|
||||
|
||||
case vpiNamedEvent: return accNamedEvent;
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ handle acc_next(PLI_INT32 *type, handle scope, handle prev)
|
||||
* rescan all the items up to the previous one, then return
|
||||
* the next one.
|
||||
*/
|
||||
iter = vpi_iterate(vpiScope, scope); // ICARUS extension
|
||||
iter = vpi_iterate(vpiScope, scope); /* ICARUS extension */
|
||||
if (prev) {
|
||||
while ((hand = vpi_scan(iter))) {
|
||||
if (hand == prev) break;
|
||||
|
||||
@@ -35,7 +35,7 @@ int acc_object_of_type(handle object, PLI_INT32 type)
|
||||
|
||||
if (pli_trace) {
|
||||
fprintf(pli_trace, "acc_object_of_type(%p \"%s\", %d)",
|
||||
object, vpi_get_str(vpiName, object), type);
|
||||
object, vpi_get_str(vpiName, object), type);
|
||||
fflush(pli_trace);
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,8 @@ AC_PROG_RANLIB
|
||||
AC_EXEEXT
|
||||
AX_CPP_IDENT
|
||||
|
||||
AX_ENABLE_SUFFIX
|
||||
|
||||
AC_CHECK_HEADERS(malloc.h)
|
||||
|
||||
AC_CHECK_SIZEOF(unsigned long long)
|
||||
|
||||
@@ -366,7 +366,7 @@ PLI_INT32 tf_isetrealdelay(double dly, void*obj)
|
||||
s_cb_data cb;
|
||||
s_vpi_time ti = {vpiSimTime};
|
||||
|
||||
// Scale delay to SimTime
|
||||
/* Scale delay to SimTime */
|
||||
ivl_u64_t delay = ((dly
|
||||
* pow(10, tf_gettimeprecision() - tf_gettimeunit()))
|
||||
+ 0.5);
|
||||
|
||||
+5
-4
@@ -60,8 +60,9 @@ bool Nexus::drivers_constant() const
|
||||
|
||||
if (cur_dir == Link::PASSIVE) {
|
||||
|
||||
const NetObj*obj = cur->get_obj();
|
||||
if (obj->scope()->parent() != 0)
|
||||
const NetPins*obj = cur->get_obj();
|
||||
const NetObj*as_obj = dynamic_cast<const NetObj*>(obj);
|
||||
if (as_obj == 0 || as_obj->scope()->parent() != 0)
|
||||
continue;
|
||||
|
||||
sig = dynamic_cast<const NetNet*>(cur->get_obj());
|
||||
@@ -80,8 +81,8 @@ bool Nexus::drivers_constant() const
|
||||
|
||||
/* If there is a supply net, then this nexus will have a
|
||||
constant value independent of any drivers. */
|
||||
if (const NetNet*sig = dynamic_cast<const NetNet*>(cur->get_obj()))
|
||||
switch (sig->type()) {
|
||||
if (const NetNet*s = dynamic_cast<const NetNet*>(cur->get_obj()))
|
||||
switch (s->type()) {
|
||||
case NetNet::SUPPLY0:
|
||||
driven_ = V0;
|
||||
return true;
|
||||
|
||||
@@ -20,6 +20,7 @@ const char COPYRIGHT[] =
|
||||
*/
|
||||
|
||||
# include "config.h"
|
||||
# include "version.h"
|
||||
|
||||
const char NOTICE[] =
|
||||
" This program is free software; you can redistribute it and/or modify\n"
|
||||
@@ -54,10 +55,12 @@ const char NOTICE[] =
|
||||
#endif
|
||||
# include "pform.h"
|
||||
# include "parse_api.h"
|
||||
# include "PGenerate.h"
|
||||
# include "netlist.h"
|
||||
# include "target.h"
|
||||
# include "compiler.h"
|
||||
# include "discipline.h"
|
||||
# include "t-dll.h"
|
||||
|
||||
#if defined(__MINGW32__) && !defined(HAVE_GETOPT_H)
|
||||
extern "C" int getopt(int argc, char*argv[], const char*fmt);
|
||||
@@ -74,12 +77,8 @@ extern "C" const char*optarg;
|
||||
/* Count errors detected in flag processing. */
|
||||
unsigned flag_errors = 0;
|
||||
|
||||
const char VERSION[] = "$Name: $";
|
||||
|
||||
const char*basedir = ".";
|
||||
|
||||
const char*target = "null";
|
||||
|
||||
/*
|
||||
* These are the language support control flags. These support which
|
||||
* language features (the generation) to support. The generation_flag
|
||||
@@ -125,6 +124,7 @@ bool debug_eval_tree = false;
|
||||
bool debug_elaborate = false;
|
||||
bool debug_synth2 = false;
|
||||
bool debug_optimizer = false;
|
||||
bool debug_automatic = false;
|
||||
|
||||
/*
|
||||
* Verbose messages enabled.
|
||||
@@ -160,9 +160,6 @@ extern void synth(Design*des);
|
||||
extern void synth2(Design*des);
|
||||
extern void syn_rules(Design*des);
|
||||
extern void nodangle(Design*des);
|
||||
#ifdef WITH_T_XNF
|
||||
extern void xnfio(Design*des);
|
||||
#endif
|
||||
|
||||
typedef void (*net_func)(Design*);
|
||||
static struct net_func_map {
|
||||
@@ -174,9 +171,6 @@ static struct net_func_map {
|
||||
{ "synth", &synth },
|
||||
{ "synth2", &synth2 },
|
||||
{ "syn-rules", &syn_rules },
|
||||
#ifdef WITH_T_XNF
|
||||
{ "xnfio", &xnfio },
|
||||
#endif
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
@@ -235,16 +229,16 @@ static void process_generation_flag(const char*gen)
|
||||
|
||||
} else if (strcmp(gen,"specify") == 0) {
|
||||
gn_specify_blocks_flag = true;
|
||||
|
||||
|
||||
} else if (strcmp(gen,"no-specify") == 0) {
|
||||
gn_specify_blocks_flag = false;
|
||||
|
||||
|
||||
} else if (strcmp(gen,"verilog-ams") == 0) {
|
||||
gn_verilog_ams_flag = true;
|
||||
|
||||
|
||||
} else if (strcmp(gen,"no-verilog-ams") == 0) {
|
||||
gn_verilog_ams_flag = false;
|
||||
|
||||
|
||||
} else if (strcmp(gen,"io-range-error") == 0) {
|
||||
gn_io_range_error_flag = true;
|
||||
|
||||
@@ -272,6 +266,9 @@ static void parm_to_flagmap(const string&flag)
|
||||
flags[key] = value;
|
||||
}
|
||||
|
||||
static void find_module_mention(map<perm_string,bool>&check_map, Module*m);
|
||||
static void find_module_mention(map<perm_string,bool>&check_map, PGenerate*s);
|
||||
|
||||
/*
|
||||
* Read the contents of a config file. This file is a temporary
|
||||
* configuration file made by the compiler driver to carry the bulky
|
||||
@@ -295,7 +292,7 @@ static void parm_to_flagmap(const string&flag)
|
||||
* -T:<min/typ/max>
|
||||
* Select which expression to use.
|
||||
*
|
||||
* -t:<target>
|
||||
* -t:<target> (obsolete)
|
||||
* Usually, "-t:dll"
|
||||
*
|
||||
* basedir:<path>
|
||||
@@ -396,6 +393,8 @@ static void read_iconfig_file(const char*ipath)
|
||||
} else if (strcmp(cp,"optimizer") == 0) {
|
||||
debug_optimizer = true;
|
||||
cerr << "debug: Enable optimizer debug" << endl;
|
||||
} else if (strcmp(cp,"automatic") == 0) {
|
||||
debug_automatic = true;
|
||||
} else {
|
||||
}
|
||||
|
||||
@@ -485,7 +484,7 @@ static void read_iconfig_file(const char*ipath)
|
||||
library_suff.push_back(strdup(cp));
|
||||
|
||||
} else if (strcmp(buf,"-t") == 0) {
|
||||
target = strdup(cp);
|
||||
// NO LONGER USED
|
||||
|
||||
} else if (strcmp(buf,"-T") == 0) {
|
||||
if (strcmp(cp,"min") == 0) {
|
||||
@@ -535,6 +534,7 @@ int main(int argc, char*argv[])
|
||||
{
|
||||
bool help_flag = false;
|
||||
bool times_flag = false;
|
||||
bool version_flag = false;
|
||||
|
||||
const char* net_path = 0;
|
||||
const char* pf_path = 0;
|
||||
@@ -578,10 +578,8 @@ int main(int argc, char*argv[])
|
||||
# endif
|
||||
break;
|
||||
case 'V':
|
||||
cout << "Icarus Verilog version " << VERSION << endl;
|
||||
cout << COPYRIGHT << endl;
|
||||
cout << endl << NOTICE << endl;
|
||||
return 0;
|
||||
version_flag = true;
|
||||
break;
|
||||
default:
|
||||
flag_errors += 1;
|
||||
break;
|
||||
@@ -590,8 +588,20 @@ int main(int argc, char*argv[])
|
||||
if (flag_errors)
|
||||
return flag_errors;
|
||||
|
||||
if (version_flag) {
|
||||
cout << "\n\nIcarus Verilog Parser/Elaborator version "
|
||||
<< VERSION << " (" << VERSION_TAG << ")" << endl;
|
||||
cout << COPYRIGHT << endl;
|
||||
cout << endl << NOTICE << endl;
|
||||
|
||||
dll_target_obj.test_version(flags["DLL"]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (help_flag) {
|
||||
cout << "Icarus Verilog version " << VERSION << endl <<
|
||||
cout << "Icarus Verilog Parser/Elaborator version "
|
||||
<< VERSION << " (" << VERSION_TAG << ")" << endl <<
|
||||
"usage: ivl <options> <file>\n"
|
||||
"options:\n"
|
||||
"\t-C <name> Config file from driver.\n"
|
||||
@@ -695,7 +705,7 @@ int main(int argc, char*argv[])
|
||||
pform_dump(out, (*cur).second);
|
||||
}
|
||||
out << "PFORM DUMP DISCIPLINES:" << endl;
|
||||
for (map<perm_string,discipline_t*>::iterator cur = disciplines.begin()
|
||||
for (map<perm_string,ivl_discipline_t>::iterator cur = disciplines.begin()
|
||||
; cur != disciplines.end() ; cur ++ ) {
|
||||
pform_dump(out, (*cur).second);
|
||||
}
|
||||
@@ -729,15 +739,7 @@ int main(int argc, char*argv[])
|
||||
for (mod = pform_modules.begin()
|
||||
; mod != pform_modules.end()
|
||||
; mod++) {
|
||||
list<PGate*> gates = (*mod).second->get_gates();
|
||||
list<PGate*>::const_iterator gate;
|
||||
for (gate = gates.begin(); gate != gates.end(); gate++) {
|
||||
PGModule *mod = dynamic_cast<PGModule*>(*gate);
|
||||
if (mod) {
|
||||
// Note that this module has been instantiated
|
||||
mentioned_p[mod->get_type()] = true;
|
||||
}
|
||||
}
|
||||
find_module_mention(mentioned_p, mod->second);
|
||||
}
|
||||
|
||||
for (mod = pform_modules.begin()
|
||||
@@ -854,20 +856,21 @@ int main(int argc, char*argv[])
|
||||
}
|
||||
|
||||
if (verbose_flag) {
|
||||
cout << "CODE GENERATION -t "<<target<< endl;
|
||||
cout << "CODE GENERATION" << endl;
|
||||
}
|
||||
|
||||
int emit_rc;
|
||||
emit_rc = emit(des, target);
|
||||
if (emit_rc > 0) {
|
||||
cerr << "error: Code generation had "
|
||||
<< emit_rc << " errors."
|
||||
<< endl;
|
||||
return 1;
|
||||
}
|
||||
if (emit_rc < 0) {
|
||||
cerr << "error: Code generator failure: " << emit_rc << endl;
|
||||
return -1;
|
||||
if (int emit_rc = des->emit(&dll_target_obj)) {
|
||||
if (emit_rc > 0) {
|
||||
cerr << "error: Code generation had "
|
||||
<< emit_rc << " errors."
|
||||
<< endl;
|
||||
return 1;
|
||||
}
|
||||
if (emit_rc < 0) {
|
||||
cerr << "error: Code generator failure: " << emit_rc << endl;
|
||||
return -1;
|
||||
}
|
||||
assert(emit_rc);
|
||||
}
|
||||
|
||||
if (verbose_flag) {
|
||||
@@ -907,3 +910,40 @@ int main(int argc, char*argv[])
|
||||
|
||||
return des? des->errors : 1;
|
||||
}
|
||||
|
||||
static void find_module_mention(map<perm_string,bool>&check_map, Module*mod)
|
||||
{
|
||||
list<PGate*> gates = mod->get_gates();
|
||||
list<PGate*>::const_iterator gate;
|
||||
for (gate = gates.begin(); gate != gates.end(); gate++) {
|
||||
PGModule*tmp = dynamic_cast<PGModule*>(*gate);
|
||||
if (tmp) {
|
||||
// Note that this module has been instantiated
|
||||
check_map[tmp->get_type()] = true;
|
||||
}
|
||||
}
|
||||
|
||||
list<PGenerate*>::const_iterator cur;
|
||||
for (cur = mod->generate_schemes.begin()
|
||||
; cur != mod->generate_schemes.end() ; cur ++) {
|
||||
find_module_mention(check_map, *cur);
|
||||
}
|
||||
}
|
||||
|
||||
static void find_module_mention(map<perm_string,bool>&check_map, PGenerate*schm)
|
||||
{
|
||||
list<PGate*>::const_iterator gate;
|
||||
for (gate = schm->gates.begin(); gate != schm->gates.end(); gate++) {
|
||||
PGModule*tmp = dynamic_cast<PGModule*>(*gate);
|
||||
if (tmp) {
|
||||
// Note that this module has been instantiated
|
||||
check_map[tmp->get_type()] = true;
|
||||
}
|
||||
}
|
||||
|
||||
list<PGenerate*>::const_iterator cur;
|
||||
for (cur = schm->generate_schemes.begin()
|
||||
; cur != schm->generate_schemes.end() ; cur ++) {
|
||||
find_module_mention(check_map, *cur);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) 2008 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# include <typeinfo>
|
||||
# include <cstdlib>
|
||||
# include <climits>
|
||||
# include "compiler.h"
|
||||
# include "netlist.h"
|
||||
# include "netmisc.h"
|
||||
# include "ivl_assert.h"
|
||||
|
||||
NetContribution::NetContribution(NetExpr*l, NetExpr*r)
|
||||
: lval_(l), rval_(r)
|
||||
{
|
||||
}
|
||||
|
||||
NetContribution::~NetContribution()
|
||||
{
|
||||
}
|
||||
+26
-36
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2008 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
|
||||
@@ -16,9 +16,6 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: net_assign.cc,v 1.22 2007/01/16 05:44:15 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
@@ -84,6 +81,11 @@ unsigned NetAssign_::lwidth() const
|
||||
return lwid_;
|
||||
}
|
||||
|
||||
ivl_variable_type_t NetAssign_::expr_type() const
|
||||
{
|
||||
return sig_->data_type();
|
||||
}
|
||||
|
||||
perm_string NetAssign_::name() const
|
||||
{
|
||||
if (sig_) {
|
||||
@@ -212,15 +214,34 @@ NetAssign::~NetAssign()
|
||||
{
|
||||
}
|
||||
|
||||
NetAssignNB::NetAssignNB(NetAssign_*lv, NetExpr*rv)
|
||||
NetAssignNB::NetAssignNB(NetAssign_*lv, NetExpr*rv, NetEvWait*ev, NetExpr*cnt)
|
||||
: NetAssignBase(lv, rv)
|
||||
{
|
||||
event_ = ev;
|
||||
count_ = cnt;
|
||||
}
|
||||
|
||||
NetAssignNB::~NetAssignNB()
|
||||
{
|
||||
}
|
||||
|
||||
unsigned NetAssignNB::nevents() const
|
||||
{
|
||||
if (event_) return event_->nevents();
|
||||
return 0;
|
||||
}
|
||||
|
||||
const NetEvent*NetAssignNB::event(unsigned idx) const
|
||||
{
|
||||
if (event_) return event_->event(idx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const NetExpr*NetAssignNB::get_count() const
|
||||
{
|
||||
return count_;
|
||||
}
|
||||
|
||||
NetCAssign::NetCAssign(NetAssign_*lv, NetExpr*rv)
|
||||
: NetAssignBase(lv, rv)
|
||||
{
|
||||
@@ -256,34 +277,3 @@ NetRelease::NetRelease(NetAssign_*l)
|
||||
NetRelease::~NetRelease()
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: net_assign.cc,v $
|
||||
* Revision 1.22 2007/01/16 05:44:15 steve
|
||||
* Major rework of array handling. Memories are replaced with the
|
||||
* more general concept of arrays. The NetMemory and NetEMemory
|
||||
* classes are removed from the ivl core program, and the IVL_LPM_RAM
|
||||
* lpm type is removed from the ivl_target API.
|
||||
*
|
||||
* Revision 1.21 2006/02/02 02:43:58 steve
|
||||
* Allow part selects of memory words in l-values.
|
||||
*
|
||||
* Revision 1.20 2005/07/11 16:56:50 steve
|
||||
* Remove NetVariable and ivl_variable_t structures.
|
||||
*
|
||||
* Revision 1.19 2004/12/11 02:31:26 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.18 2004/08/28 15:08:31 steve
|
||||
* Do not change reg to wire in NetAssign_ unless synthesizing.
|
||||
*
|
||||
* Revision 1.17 2004/02/18 17:11:56 steve
|
||||
* Use perm_strings for named langiage items.
|
||||
*
|
||||
* Revision 1.16 2003/01/26 21:15:58 steve
|
||||
* Rework expression parsing and elaboration to
|
||||
* accommodate real/realtime values and expressions.
|
||||
*/
|
||||
|
||||
|
||||
+128
-14
@@ -20,6 +20,7 @@
|
||||
# include "config.h"
|
||||
|
||||
# include <iostream>
|
||||
# include <set>
|
||||
# include <cstdlib>
|
||||
|
||||
/*
|
||||
@@ -35,7 +36,7 @@
|
||||
# include "ivl_assert.h"
|
||||
|
||||
Design:: Design()
|
||||
: errors(0), nodes_(0), procs_(0), lcounter_(0)
|
||||
: errors(0), nodes_(0), procs_(0), aprocs_(0), lcounter_(0)
|
||||
{
|
||||
procs_idx_ = 0;
|
||||
des_precision_ = 0;
|
||||
@@ -208,10 +209,12 @@ void NetScope::run_defparams(Design*des)
|
||||
}
|
||||
}
|
||||
|
||||
map<pform_name_t,NetExpr*>::const_iterator pp;
|
||||
for (pp = defparams.begin() ; pp != defparams.end() ; pp ++ ) {
|
||||
NetExpr*val = (*pp).second;
|
||||
pform_name_t path = (*pp).first;
|
||||
while (! defparams.empty()) {
|
||||
pair<pform_name_t,NetExpr*> pp = defparams.front();
|
||||
defparams.pop_front();
|
||||
|
||||
pform_name_t path = pp.first;
|
||||
NetExpr*val = pp.second;
|
||||
|
||||
perm_string perm_name = peek_tail_name(path);
|
||||
path.pop_back();
|
||||
@@ -222,11 +225,20 @@ void NetScope::run_defparams(Design*des)
|
||||
is the current scope. */
|
||||
NetScope*targ_scope = des->find_scope(this, eval_path);
|
||||
if (targ_scope == 0) {
|
||||
cerr << val->get_fileline() << ": warning: scope of " <<
|
||||
path << "." << perm_name << " not found." << endl;
|
||||
|
||||
// Push the defparam onto a list for retry
|
||||
// later. It is possible for the scope lookup to
|
||||
// fail if the scope being defparam'd into is
|
||||
// generated by an index array for generate.
|
||||
eval_path.push_back(hname_t(perm_name));
|
||||
defparams_later.push_back(make_pair(eval_path,val));
|
||||
continue;
|
||||
}
|
||||
|
||||
// Once placed in the parameter map, the expression may
|
||||
// be deleted when evaluated, so give it a copy of this
|
||||
// expression, not the original.
|
||||
val = val->dup_expr();
|
||||
bool flag = targ_scope->replace_parameter(perm_name, val);
|
||||
if (! flag) {
|
||||
cerr << val->get_fileline() << ": warning: parameter "
|
||||
@@ -235,6 +247,66 @@ void NetScope::run_defparams(Design*des)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// If some of the defparams didn't find a scope in the name,
|
||||
// then try again later. It may be that the target scope is
|
||||
// created later by generate scheme or instance array.
|
||||
if (! defparams_later.empty())
|
||||
des->defparams_later.insert(this);
|
||||
}
|
||||
|
||||
void NetScope::run_defparams_later(Design*des)
|
||||
{
|
||||
set<NetScope*> target_scopes;
|
||||
list<pair<list<hname_t>,NetExpr*> > defparams_even_later;
|
||||
|
||||
while (! defparams_later.empty()) {
|
||||
pair<list<hname_t>,NetExpr*> cur = defparams_later.front();
|
||||
defparams_later.pop_front();
|
||||
|
||||
list<hname_t>eval_path = cur.first;
|
||||
perm_string name = eval_path.back().peek_name();
|
||||
eval_path.pop_back();
|
||||
|
||||
NetExpr*val = cur.second;
|
||||
|
||||
NetScope*targ_scope = des->find_scope(this, eval_path);
|
||||
if (targ_scope == 0) {
|
||||
// If a scope in the target path is not found,
|
||||
// then push this defparam for handling even
|
||||
// later. Maybe a later generate scheme or
|
||||
// instance array will create the scope.
|
||||
defparams_even_later.push_back(cur);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Once placed in the parameter map, the expression may
|
||||
// be deleted when evaluated, so give it a copy of this
|
||||
// expression, not the original.
|
||||
val = val->dup_expr();
|
||||
bool flag = targ_scope->replace_parameter(name, val);
|
||||
if (! flag) {
|
||||
cerr << val->get_fileline() << ": warning: parameter "
|
||||
<< name << " not found in "
|
||||
<< scope_path(targ_scope) << "." << endl;
|
||||
}
|
||||
|
||||
// We'll need to re-evaluate parameters in this scope
|
||||
target_scopes.insert(targ_scope);
|
||||
}
|
||||
|
||||
// All the scopes that this defparam set touched should have
|
||||
// their parameters re-evaluated.
|
||||
for (set<NetScope*>::iterator cur = target_scopes.begin()
|
||||
; cur != target_scopes.end() ; cur ++ )
|
||||
(*cur)->evaluate_parameters(des);
|
||||
|
||||
// If there are some scopes that still have missing scopes,
|
||||
// then sav them back into the defparams_later list for a
|
||||
// later pass.
|
||||
defparams_later = defparams_even_later;
|
||||
if (! defparams_later.empty())
|
||||
des->defparams_later.insert(this);
|
||||
}
|
||||
|
||||
void Design::evaluate_parameters()
|
||||
@@ -285,11 +357,11 @@ void NetScope::evaluate_parameter_logic_(Design*des, param_ref_t cur)
|
||||
|
||||
/* Evaluate the parameter expression, if necessary. */
|
||||
NetExpr*expr = (*cur).second.expr;
|
||||
assert(expr);
|
||||
if (expr == NULL) return; // This is an invalid parameter so return.
|
||||
|
||||
eval_expr(expr);
|
||||
|
||||
/* The eval_expr may delete any replace the expr pointer, so the
|
||||
/* The eval_expr may delete and replace the expr pointer, so the
|
||||
second.expr value cannot be relied on. Might as well replace
|
||||
it now with the expression that we evaluated. */
|
||||
(*cur).second.expr = expr;
|
||||
@@ -335,6 +407,14 @@ void NetScope::evaluate_parameter_logic_(Design*des, param_ref_t cur)
|
||||
unsigned long wid = (msb >= lsb)? msb - lsb : lsb - msb;
|
||||
wid += 1;
|
||||
|
||||
/* If we have a real value convert it to an integer. */
|
||||
if(NetECReal*tmp = dynamic_cast<NetECReal*>(expr)) {
|
||||
verinum nval(tmp->value().as_long64());
|
||||
expr = new NetEConst(nval);
|
||||
expr->set_line(*((*cur).second.expr));
|
||||
(*cur).second.expr = expr;
|
||||
}
|
||||
|
||||
NetEConst*val = dynamic_cast<NetEConst*>(expr);
|
||||
assert(val);
|
||||
|
||||
@@ -348,7 +428,7 @@ void NetScope::evaluate_parameter_logic_(Design*des, param_ref_t cur)
|
||||
tmp.has_sign ( (*cur).second.signed_flag );
|
||||
delete val;
|
||||
val = new NetEConst(tmp);
|
||||
expr = val;
|
||||
(*cur).second.expr = expr = val;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -500,12 +580,15 @@ void NetScope::evaluate_parameter_real_(Design*des, param_ref_t cur)
|
||||
|
||||
void NetScope::evaluate_parameters(Design*des)
|
||||
{
|
||||
NetScope*cur = sub_;
|
||||
while (cur) {
|
||||
cur->evaluate_parameters(des);
|
||||
cur = cur->sib_;
|
||||
NetScope*curs = sub_;
|
||||
while (curs) {
|
||||
curs->evaluate_parameters(des);
|
||||
curs = curs->sib_;
|
||||
}
|
||||
|
||||
if (debug_scopes)
|
||||
cerr << ":0" << ": debug: "
|
||||
<< "Evaluate parameters in " << scope_path(this) << endl;
|
||||
|
||||
// Evaluate the parameter values. The parameter expressions
|
||||
// have already been elaborated and replaced by the scope
|
||||
@@ -540,6 +623,32 @@ void NetScope::evaluate_parameters(Design*des)
|
||||
|
||||
}
|
||||
|
||||
void Design::residual_defparams()
|
||||
{
|
||||
for (list<NetScope*>::const_iterator scope = root_scopes_.begin();
|
||||
scope != root_scopes_.end(); scope++)
|
||||
(*scope)->residual_defparams(this);
|
||||
}
|
||||
|
||||
void NetScope::residual_defparams(Design*des)
|
||||
{
|
||||
// Clean out the list of defparams that never managed to match
|
||||
// a scope. Print a warning for each.
|
||||
while (! defparams_later.empty()) {
|
||||
pair<list<hname_t>,NetExpr*> cur = defparams_later.front();
|
||||
defparams_later.pop_front();
|
||||
|
||||
cerr << cur.second->get_fileline() << ": warning: "
|
||||
<< "Scope of " << cur.first << " not found." << endl;
|
||||
}
|
||||
|
||||
NetScope*cur = sub_;
|
||||
while (cur) {
|
||||
cur->residual_defparams(des);
|
||||
cur = cur->sib_;
|
||||
}
|
||||
}
|
||||
|
||||
const char* Design::get_flag(const string&key) const
|
||||
{
|
||||
map<string,const char*>::const_iterator tmp = flags_.find(key);
|
||||
@@ -655,6 +764,11 @@ void Design::add_process(NetProcTop*pro)
|
||||
procs_ = pro;
|
||||
}
|
||||
|
||||
void Design::add_process(NetAnalogTop*pro)
|
||||
{
|
||||
pro->next_ = aprocs_;
|
||||
aprocs_ = pro;
|
||||
}
|
||||
void Design::delete_process(NetProcTop*top)
|
||||
{
|
||||
assert(top);
|
||||
|
||||
+7
-3
@@ -173,6 +173,12 @@ void NetEvent::find_similar_event(list<NetEvent*>&event_list)
|
||||
if (tmp == this)
|
||||
continue;
|
||||
|
||||
/* For automatic tasks, the VVP runtime holds state for events
|
||||
in the automatically allocated context. This means we can't
|
||||
merge similar events in different automatic tasks. */
|
||||
if (scope()->is_auto() && (tmp->scope() != scope()))
|
||||
continue;
|
||||
|
||||
if ((*idx).second != probe_count)
|
||||
continue;
|
||||
|
||||
@@ -251,7 +257,6 @@ NetEvProbe::NetEvProbe(NetScope*s, perm_string n, NetEvent*tgt,
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < p ; idx += 1) {
|
||||
pin(idx).set_dir(Link::INPUT);
|
||||
pin(idx).set_name(perm_string::literal("P"), idx);
|
||||
}
|
||||
|
||||
enext_ = event_->probes_;
|
||||
@@ -299,7 +304,7 @@ void NetEvProbe::find_similar_probes(list<NetEvProbe*>&plist)
|
||||
Nexus*nex = pin(0).nexus();
|
||||
|
||||
for (Link*lcur = nex->first_nlink(); lcur; lcur = lcur->next_nlink()) {
|
||||
NetObj*obj = lcur->get_obj();
|
||||
NetPins*obj = lcur->get_obj();
|
||||
if (obj->pin_count() != pin_count())
|
||||
continue;
|
||||
|
||||
@@ -554,4 +559,3 @@ NetProc* NetEvWait::statement()
|
||||
* Simulate named event trigger and waits.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
+65
-40
@@ -35,8 +35,8 @@ ivl_variable_type_t NetExpr::expr_type() const
|
||||
* Create an add/sub node from the two operands. Make a best guess of
|
||||
* the
|
||||
*/
|
||||
NetEBAdd::NetEBAdd(char op, NetExpr*l, NetExpr*r, bool lossless_flag)
|
||||
: NetEBinary(op, l, r)
|
||||
NetEBAdd::NetEBAdd(char op__, NetExpr*l, NetExpr*r, bool lossless_flag)
|
||||
: NetEBinary(op__, l, r)
|
||||
{
|
||||
NetEConst* tmp;
|
||||
|
||||
@@ -56,42 +56,54 @@ NetEBAdd::NetEBAdd(char op, NetExpr*l, NetExpr*r, bool lossless_flag)
|
||||
&& (! tmp->has_width())
|
||||
&& (tmp->expr_width() > l->expr_width() || integer_width > l->expr_width()) ) {
|
||||
|
||||
unsigned target_width = l->expr_width() + 1;
|
||||
verinum tmp_v = trim_vnum(tmp->value());
|
||||
unsigned target_width = l->expr_width();
|
||||
if (target_width < tmp_v.len())
|
||||
target_width = tmp_v.len();
|
||||
if (lossless_flag)
|
||||
target_width += 1;
|
||||
if (target_width < integer_width)
|
||||
target_width = integer_width;
|
||||
|
||||
r->set_width(target_width);
|
||||
|
||||
/* Note: This constant value will not gain a defined
|
||||
width from this. Make sure. */
|
||||
assert(! r->has_width() );
|
||||
|
||||
expr_width(target_width);
|
||||
|
||||
} else if ( (tmp = dynamic_cast<NetEConst*>(l))
|
||||
&& (! tmp->has_width())
|
||||
&& (tmp->expr_width() > r->expr_width() || integer_width > r->expr_width()) ) {
|
||||
|
||||
unsigned target_width = r->expr_width() + 1;
|
||||
verinum tmp_v = trim_vnum(tmp->value());
|
||||
unsigned target_width = r->expr_width();
|
||||
if (target_width < tmp_v.len())
|
||||
target_width = tmp_v.len();
|
||||
if (lossless_flag)
|
||||
target_width += 1;
|
||||
if (target_width < integer_width)
|
||||
target_width = integer_width;
|
||||
|
||||
l->set_width(target_width);
|
||||
|
||||
/* Note: This constant value will not gain a defined
|
||||
width from this. Make sure. */
|
||||
assert(! l->has_width() );
|
||||
|
||||
}
|
||||
expr_width(target_width);
|
||||
|
||||
unsigned pad_width = lossless_flag? 1 : 0;
|
||||
cast_signed(l->has_sign() && r->has_sign());
|
||||
|
||||
/* Now that we have the operand sizes the way we like, or as
|
||||
good as we are going to get them, set the size of myself. */
|
||||
if (r->expr_width() > l->expr_width()) {
|
||||
|
||||
expr_width(r->expr_width() + pad_width);
|
||||
} else if (r->expr_width() > l->expr_width()) {
|
||||
unsigned loss_pad = lossless_flag? 1 : 0;
|
||||
expr_width(r->expr_width() + loss_pad);
|
||||
|
||||
} else {
|
||||
expr_width(l->expr_width() + pad_width);
|
||||
unsigned loss_pad = lossless_flag? 1 : 0;
|
||||
expr_width(l->expr_width() + loss_pad);
|
||||
}
|
||||
|
||||
cast_signed(l->has_sign() && r->has_sign());
|
||||
}
|
||||
|
||||
NetEBAdd::~NetEBAdd()
|
||||
@@ -124,9 +136,12 @@ ivl_variable_type_t NetEBAdd::expr_type() const
|
||||
* expression. Otherwise, the netlist will have to allow the
|
||||
* expressions to have different widths.
|
||||
*/
|
||||
NetEBComp::NetEBComp(char op, NetExpr*l, NetExpr*r)
|
||||
: NetEBinary(op, l, r)
|
||||
NetEBComp::NetEBComp(char op__, NetExpr*l, NetExpr*r)
|
||||
: NetEBinary(op__, l, r)
|
||||
{
|
||||
// The output of compare is always unsigned.
|
||||
cast_signed_base_(false);
|
||||
|
||||
if (NetEConst*tmp = dynamic_cast<NetEConst*>(r)) do {
|
||||
|
||||
if (tmp->has_width())
|
||||
@@ -185,8 +200,8 @@ ivl_variable_type_t NetEBComp::expr_type() const
|
||||
return IVL_VT_BOOL;
|
||||
}
|
||||
|
||||
NetEBDiv::NetEBDiv(char op, NetExpr*l, NetExpr*r)
|
||||
: NetEBinary(op, l, r)
|
||||
NetEBDiv::NetEBDiv(char op__, NetExpr*l, NetExpr*r)
|
||||
: NetEBinary(op__, l, r)
|
||||
{
|
||||
unsigned w = l->expr_width();
|
||||
if (r->expr_width() > w)
|
||||
@@ -218,8 +233,8 @@ ivl_variable_type_t NetEBDiv::expr_type() const
|
||||
return IVL_VT_LOGIC;
|
||||
}
|
||||
|
||||
NetEBMinMax::NetEBMinMax(char op, NetExpr*l, NetExpr*r)
|
||||
: NetEBinary(op, l, r)
|
||||
NetEBMinMax::NetEBMinMax(char op__, NetExpr*l, NetExpr*r)
|
||||
: NetEBinary(op__, l, r)
|
||||
{
|
||||
expr_width( max(l->expr_width(), r->expr_width()) );
|
||||
cast_signed(l->has_sign() || r->has_sign());
|
||||
@@ -239,18 +254,18 @@ ivl_variable_type_t NetEBMinMax::expr_type() const
|
||||
return IVL_VT_LOGIC;
|
||||
}
|
||||
|
||||
NetEBMult::NetEBMult(char op, NetExpr*l, NetExpr*r)
|
||||
: NetEBinary(op, l, r)
|
||||
NetEBMult::NetEBMult(char op__, NetExpr*l, NetExpr*r)
|
||||
: NetEBinary(op__, l, r)
|
||||
{
|
||||
expr_width(l->expr_width() + r->expr_width());
|
||||
cast_signed(l->has_sign() && r->has_sign());
|
||||
if (expr_type() == IVL_VT_REAL)
|
||||
expr_width(1);
|
||||
else
|
||||
expr_width(l->expr_width() + r->expr_width());
|
||||
|
||||
/* If it turns out that this is not a signed expression, then
|
||||
cast the signedness out of the operands as well. */
|
||||
if (! has_sign()) {
|
||||
l->cast_signed(false);
|
||||
r->cast_signed(false);
|
||||
}
|
||||
if (expr_type() == IVL_VT_REAL)
|
||||
cast_signed(true);
|
||||
else
|
||||
cast_signed(l->has_sign() && r->has_sign());
|
||||
}
|
||||
|
||||
NetEBMult::~NetEBMult()
|
||||
@@ -275,10 +290,10 @@ ivl_variable_type_t NetEBMult::expr_type() const
|
||||
return IVL_VT_LOGIC;
|
||||
}
|
||||
|
||||
NetEBPow::NetEBPow(char op, NetExpr*l, NetExpr*r)
|
||||
: NetEBinary(op, l, r)
|
||||
NetEBPow::NetEBPow(char op__, NetExpr*l, NetExpr*r)
|
||||
: NetEBinary(op__, l, r)
|
||||
{
|
||||
assert(op == 'p');
|
||||
assert(op__ == 'p');
|
||||
/* This is incorrect! a * (2^b - 1) is close. */
|
||||
expr_width(l->expr_width()+r->expr_width());
|
||||
cast_signed(l->has_sign() || r->has_sign());
|
||||
@@ -302,21 +317,17 @@ ivl_variable_type_t NetEBPow::expr_type() const
|
||||
return IVL_VT_REAL;
|
||||
if (left_->expr_type() == IVL_VT_REAL)
|
||||
return IVL_VT_REAL;
|
||||
if (left_->has_sign())
|
||||
return IVL_VT_REAL;
|
||||
if (right_->has_sign())
|
||||
return IVL_VT_REAL;
|
||||
|
||||
return IVL_VT_LOGIC;
|
||||
}
|
||||
|
||||
NetEBShift::NetEBShift(char op, NetExpr*l, NetExpr*r)
|
||||
: NetEBinary(op, l, r)
|
||||
NetEBShift::NetEBShift(char op__, NetExpr*l, NetExpr*r)
|
||||
: NetEBinary(op__, l, r)
|
||||
{
|
||||
expr_width(l->expr_width());
|
||||
|
||||
// The >>> is signed if the left operand is signed.
|
||||
if (op == 'R') cast_signed(l->has_sign());
|
||||
if (op__ == 'R') cast_signed(l->has_sign());
|
||||
}
|
||||
|
||||
NetEBShift::~NetEBShift()
|
||||
@@ -588,3 +599,17 @@ ivl_variable_type_t NetESFunc::expr_type() const
|
||||
{
|
||||
return type_;
|
||||
}
|
||||
|
||||
NetEAccess::NetEAccess(NetBranch*br, nature_t*nat)
|
||||
: branch_(br), nature_(nat)
|
||||
{
|
||||
}
|
||||
|
||||
NetEAccess::~NetEAccess()
|
||||
{
|
||||
}
|
||||
|
||||
ivl_variable_type_t NetEAccess::expr_type() const
|
||||
{
|
||||
return IVL_VT_REAL;
|
||||
}
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2004 Stephen Williams (steve@picturel.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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: net_force.cc,v 1.13 2004/12/11 02:31:26 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
# include "compiler.h"
|
||||
|
||||
/*
|
||||
* This file contains implementation of the NetForce, NetRelease,
|
||||
* NetCAssign and NetDeassign classes. These are similar or related in
|
||||
* that they handle the procedural continuous assign and force
|
||||
* statements.
|
||||
*/
|
||||
|
||||
# include "netlist.h"
|
||||
# include <assert.h>
|
||||
|
||||
|
||||
/*
|
||||
* $Log: net_force.cc,v $
|
||||
* Revision 1.13 2004/12/11 02:31:26 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.12 2004/02/18 17:11:56 steve
|
||||
* Use perm_strings for named langiage items.
|
||||
*
|
||||
* Revision 1.11 2003/03/06 00:28:41 steve
|
||||
* All NetObj objects have lex_string base names.
|
||||
*
|
||||
* Revision 1.10 2003/01/27 05:09:17 steve
|
||||
* Spelling fixes.
|
||||
*
|
||||
* Revision 1.9 2002/08/19 00:06:12 steve
|
||||
* Allow release to handle removal of target net.
|
||||
*
|
||||
* Revision 1.8 2002/08/12 01:34:59 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.7 2002/01/19 19:02:08 steve
|
||||
* Pass back target errors processing conditionals.
|
||||
*
|
||||
* Revision 1.6 2001/11/14 03:28:49 steve
|
||||
* DLL target support for force and release.
|
||||
*
|
||||
* Revision 1.5 2001/10/31 05:24:52 steve
|
||||
* ivl_target support for assign/deassign.
|
||||
*
|
||||
* Revision 1.4 2001/10/28 01:14:53 steve
|
||||
* NetObj constructor finally requires a scope.
|
||||
*
|
||||
* Revision 1.3 2001/07/25 03:10:49 steve
|
||||
* Create a config.h.in file to hold all the config
|
||||
* junk, and support gcc 3.0. (Stephan Boettcher)
|
||||
*
|
||||
* Revision 1.2 2000/05/12 01:22:41 steve
|
||||
* NetCAssign needs to incr_eref its lval to lock it down.
|
||||
*
|
||||
* Revision 1.1 2000/05/11 23:37:27 steve
|
||||
* Add support for procedural continuous assignment.
|
||||
*
|
||||
*/
|
||||
|
||||
+10
-14
@@ -34,12 +34,10 @@ NetUserFunc::NetUserFunc(NetScope*s, perm_string n, NetScope*d)
|
||||
def_(d)
|
||||
{
|
||||
pin(0).set_dir(Link::OUTPUT);
|
||||
pin(0).set_name(def_->basename(), 0);
|
||||
|
||||
for (unsigned idx = 1 ; idx < pin_count() ; idx += 1) {
|
||||
|
||||
pin(idx).set_dir(Link::INPUT);
|
||||
pin(idx).set_name(perm_string::literal("D"), idx-1);
|
||||
pin(idx).drive0(Link::HIGHZ);
|
||||
pin(idx).drive1(Link::HIGHZ);
|
||||
}
|
||||
@@ -51,36 +49,36 @@ NetUserFunc::~NetUserFunc()
|
||||
|
||||
ivl_variable_type_t NetUserFunc::data_type(unsigned port) const
|
||||
{
|
||||
NetFuncDef*def = def_->func_def();
|
||||
NetFuncDef*fdef = def_->func_def();
|
||||
|
||||
/* Port 0 is the return port. */
|
||||
if (port == 0) {
|
||||
const NetNet*sig = def->return_sig();
|
||||
const NetNet*sig = fdef->return_sig();
|
||||
assert(sig);
|
||||
return sig->data_type();
|
||||
}
|
||||
|
||||
port -= 1;
|
||||
assert(port < def->port_count());
|
||||
const NetNet*port_sig = def->port(port);
|
||||
assert(port < fdef->port_count());
|
||||
const NetNet*port_sig = fdef->port(port);
|
||||
|
||||
return port_sig->data_type();
|
||||
}
|
||||
|
||||
unsigned NetUserFunc::port_width(unsigned port) const
|
||||
{
|
||||
NetFuncDef*def = def_->func_def();
|
||||
NetFuncDef*fdef = def_->func_def();
|
||||
|
||||
/* Port 0 is the return port. */
|
||||
if (port == 0) {
|
||||
const NetNet*sig = def->return_sig();
|
||||
const NetNet*sig = fdef->return_sig();
|
||||
assert(sig);
|
||||
return sig->vector_width();
|
||||
}
|
||||
|
||||
port -= 1;
|
||||
assert(port < def->port_count());
|
||||
const NetNet*port_sig = def->port(port);
|
||||
assert(port < fdef->port_count());
|
||||
const NetNet*port_sig = fdef->port(port);
|
||||
|
||||
return port_sig->vector_width();
|
||||
}
|
||||
@@ -104,7 +102,7 @@ bool PECallFunction::check_call_matches_definition_(Design*des, NetScope*dscope)
|
||||
1 nil pointer. This is how the parser tells me of no
|
||||
parameter. In other words, ``func()'' is 1 nil parameter. */
|
||||
|
||||
unsigned parms_count = parms_.count();
|
||||
unsigned parms_count = parms_.size();
|
||||
if ((parms_count == 1) && (parms_[0] == 0))
|
||||
parms_count = 0;
|
||||
|
||||
@@ -135,13 +133,11 @@ NetSysFunc::NetSysFunc(NetScope*s, perm_string n,
|
||||
{
|
||||
def_ = def;
|
||||
|
||||
pin(0).set_dir(Link::OUTPUT);
|
||||
pin(0).set_name(perm_string::literal("Q"), 0);
|
||||
pin(0).set_dir(Link::OUTPUT); // Q
|
||||
|
||||
for (unsigned idx = 1 ; idx < pin_count() ; idx += 1) {
|
||||
|
||||
pin(idx).set_dir(Link::INPUT);
|
||||
pin(idx).set_name(perm_string::literal("D"), idx-1);
|
||||
pin(idx).drive0(Link::HIGHZ);
|
||||
pin(idx).drive1(Link::HIGHZ);
|
||||
}
|
||||
|
||||
+82
-34
@@ -64,7 +64,7 @@ void connect(Link&l, Link&r)
|
||||
|
||||
Link::Link()
|
||||
: dir_(PASSIVE), drive0_(STRONG), drive1_(STRONG), init_(verinum::Vx),
|
||||
inst_(0), next_(0), nexus_(0)
|
||||
next_(0), nexus_(0)
|
||||
{
|
||||
(new Nexus()) -> relink(this);
|
||||
}
|
||||
@@ -103,6 +103,11 @@ void Link::drivers_delays(NetExpr*rise, NetExpr*fall, NetExpr*decay)
|
||||
nexus_->drivers_delays(rise, fall, decay);
|
||||
}
|
||||
|
||||
void Link::drivers_drive(strength_t drive0__, strength_t drive1__)
|
||||
{
|
||||
nexus_->drivers_drive(drive0__, drive1__);
|
||||
}
|
||||
|
||||
void Link::drive0(Link::strength_t str)
|
||||
{
|
||||
drive0_ = str;
|
||||
@@ -134,16 +139,16 @@ verinum::V Link::get_init() const
|
||||
}
|
||||
|
||||
|
||||
void Link::cur_link(NetObj*&net, unsigned &pin)
|
||||
void Link::cur_link(NetPins*&net, unsigned &pin)
|
||||
{
|
||||
net = node_;
|
||||
pin = pin_;
|
||||
net = get_obj();
|
||||
pin = get_pin();
|
||||
}
|
||||
|
||||
void Link::cur_link(const NetObj*&net, unsigned &pin) const
|
||||
void Link::cur_link(const NetPins*&net, unsigned &pin) const
|
||||
{
|
||||
net = node_;
|
||||
pin = pin_;
|
||||
net = get_obj();
|
||||
pin = get_pin();
|
||||
}
|
||||
|
||||
void Link::unlink()
|
||||
@@ -186,35 +191,30 @@ const Link* Link::next_nlink() const
|
||||
return next_;
|
||||
}
|
||||
|
||||
const NetObj*Link::get_obj() const
|
||||
const NetPins*Link::get_obj() const
|
||||
{
|
||||
return node_;
|
||||
if (pin_zero_)
|
||||
return node_;
|
||||
const Link*tmp = this - pin_;
|
||||
assert(tmp->pin_zero_);
|
||||
return tmp->node_;
|
||||
}
|
||||
|
||||
NetObj*Link::get_obj()
|
||||
NetPins*Link::get_obj()
|
||||
{
|
||||
return node_;
|
||||
if (pin_zero_)
|
||||
return node_;
|
||||
Link*tmp = this - pin_;
|
||||
assert(tmp->pin_zero_);
|
||||
return tmp->node_;
|
||||
}
|
||||
|
||||
unsigned Link::get_pin() const
|
||||
{
|
||||
return pin_;
|
||||
}
|
||||
|
||||
void Link::set_name(perm_string n, unsigned i)
|
||||
{
|
||||
name_ = n;
|
||||
inst_ = i;
|
||||
}
|
||||
|
||||
perm_string Link::get_name() const
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
|
||||
unsigned Link::get_inst() const
|
||||
{
|
||||
return inst_;
|
||||
if (pin_zero_)
|
||||
return 0;
|
||||
else
|
||||
return pin_;
|
||||
}
|
||||
|
||||
Nexus::Nexus()
|
||||
@@ -247,19 +247,68 @@ verinum::V Nexus::get_init() const
|
||||
return verinum::Vz;
|
||||
}
|
||||
|
||||
bool Nexus::drivers_present() const
|
||||
{
|
||||
assert(list_);
|
||||
for (Link*cur = list_ ; cur ; cur = cur->next_) {
|
||||
if (cur->get_dir() == Link::OUTPUT)
|
||||
return true;
|
||||
|
||||
if (cur->get_dir() == Link::INPUT)
|
||||
continue;
|
||||
|
||||
// Must be PASSIVE, so if it is some kind of net, see if
|
||||
// it is the sort that might drive the nexus.
|
||||
const NetPins*obj;
|
||||
unsigned pin;
|
||||
cur->cur_link(obj, pin);
|
||||
if (const NetNet*net = dynamic_cast<const NetNet*>(obj))
|
||||
switch (net->type()) {
|
||||
case NetNet::SUPPLY0:
|
||||
case NetNet::SUPPLY1:
|
||||
case NetNet::TRI0:
|
||||
case NetNet::TRI1:
|
||||
case NetNet::WAND:
|
||||
case NetNet::WOR:
|
||||
case NetNet::TRIAND:
|
||||
case NetNet::TRIOR:
|
||||
case NetNet::REG:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Nexus::drivers_delays(NetExpr*rise, NetExpr*fall, NetExpr*decay)
|
||||
{
|
||||
for (Link*cur = list_ ; cur ; cur = cur->next_) {
|
||||
if (cur->get_dir() != Link::OUTPUT)
|
||||
continue;
|
||||
|
||||
NetObj*obj = cur->get_obj();
|
||||
NetObj*obj = dynamic_cast<NetObj*>(cur->get_obj());
|
||||
if (obj == 0)
|
||||
continue;
|
||||
|
||||
obj->rise_time(rise);
|
||||
obj->fall_time(fall);
|
||||
obj->decay_time(decay);
|
||||
}
|
||||
}
|
||||
|
||||
void Nexus::drivers_drive(Link::strength_t drive0, Link::strength_t drive1)
|
||||
{
|
||||
for (Link*cur = list_ ; cur ; cur = cur->next_) {
|
||||
if (cur->get_dir() != Link::OUTPUT)
|
||||
continue;
|
||||
|
||||
cur->drive0(drive0);
|
||||
cur->drive1(drive1);
|
||||
}
|
||||
}
|
||||
|
||||
void Nexus::unlink(Link*that)
|
||||
{
|
||||
if (name_) {
|
||||
@@ -397,12 +446,11 @@ const char* Nexus::name() const
|
||||
|
||||
if (sig == 0) {
|
||||
const Link*lnk = first_nlink();
|
||||
const NetObj*obj = lnk->get_obj();
|
||||
const NetObj*obj = dynamic_cast<const NetObj*>(lnk->get_obj());
|
||||
pin = lnk->get_pin();
|
||||
cerr << "internal error: No signal for nexus of " <<
|
||||
obj->name() << " pin " << pin << "(" <<
|
||||
lnk->get_name() << "<" << lnk->get_inst() << ">)"
|
||||
" type=" << typeid(*obj).name() << "?" << endl;
|
||||
cerr << "internal error: No signal for nexus of "
|
||||
<< obj->name() << " pin " << pin
|
||||
<< " type=" << typeid(*obj).name() << "?" << endl;
|
||||
|
||||
}
|
||||
assert(sig);
|
||||
|
||||
+14
-32
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2005 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2008 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
|
||||
@@ -16,9 +16,6 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: net_modulo.cc,v 1.9 2005/09/15 22:54:47 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
@@ -40,12 +37,9 @@ NetModulo::NetModulo(NetScope*s, perm_string n, unsigned wr,
|
||||
: NetNode(s, n, 3),
|
||||
width_r_(wr), width_a_(wa), width_b_(wb)
|
||||
{
|
||||
pin(0).set_dir(Link::OUTPUT);
|
||||
pin(0).set_name(perm_string::literal("Result"), 0);
|
||||
pin(1).set_dir(Link::INPUT);
|
||||
pin(1).set_name(perm_string::literal("DataA"), 0);
|
||||
pin(2).set_dir(Link::INPUT);
|
||||
pin(2).set_name(perm_string::literal("DataB"), 0);
|
||||
pin(0).set_dir(Link::OUTPUT); // Result
|
||||
pin(1).set_dir(Link::INPUT); // DataA
|
||||
pin(2).set_dir(Link::INPUT); // DataB
|
||||
}
|
||||
|
||||
NetModulo::~NetModulo()
|
||||
@@ -72,6 +66,16 @@ Link& NetModulo::pin_Result()
|
||||
return pin(0);
|
||||
}
|
||||
|
||||
void NetModulo::set_signed(bool flag)
|
||||
{
|
||||
signed_flag_ = flag;
|
||||
}
|
||||
|
||||
bool NetModulo::get_signed() const
|
||||
{
|
||||
return signed_flag_;
|
||||
}
|
||||
|
||||
const Link& NetModulo::pin_Result() const
|
||||
{
|
||||
return pin(0);
|
||||
@@ -96,25 +100,3 @@ const Link& NetModulo::pin_DataB() const
|
||||
{
|
||||
return pin(2);
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: net_modulo.cc,v $
|
||||
* Revision 1.9 2005/09/15 22:54:47 steve
|
||||
* Fix bug configuring NetModulo pins.
|
||||
*
|
||||
* Revision 1.8 2005/03/12 06:43:35 steve
|
||||
* Update support for LPM_MOD.
|
||||
*
|
||||
* Revision 1.7 2004/02/18 17:11:56 steve
|
||||
* Use perm_strings for named langiage items.
|
||||
*
|
||||
* Revision 1.6 2003/03/06 00:28:41 steve
|
||||
* All NetObj objects have lex_string base names.
|
||||
*
|
||||
* Revision 1.5 2002/08/12 01:34:59 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.4 2002/08/11 23:47:04 steve
|
||||
* Add missing Log and Ident strings.
|
||||
*
|
||||
*/
|
||||
|
||||
+15
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002-2007 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2002-2008 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
|
||||
@@ -53,8 +53,13 @@ NexusSet* NetEBinary::nex_input(bool rem_out)
|
||||
|
||||
NexusSet* NetEConcat::nex_input(bool rem_out)
|
||||
{
|
||||
if (parms_[0] == NULL) return NULL;
|
||||
NexusSet*result = parms_[0]->nex_input(rem_out);
|
||||
for (unsigned idx = 1 ; idx < parms_.count() ; idx += 1) {
|
||||
if (parms_[idx] == NULL) {
|
||||
delete result;
|
||||
return NULL;
|
||||
}
|
||||
NexusSet*tmp = parms_[idx]->nex_input(rem_out);
|
||||
result->add(*tmp);
|
||||
delete tmp;
|
||||
@@ -62,6 +67,11 @@ NexusSet* NetEConcat::nex_input(bool rem_out)
|
||||
return result;
|
||||
}
|
||||
|
||||
NexusSet* NetEAccess::nex_input(bool rem_out)
|
||||
{
|
||||
return new NexusSet;
|
||||
}
|
||||
|
||||
/*
|
||||
* A constant has not inputs, so always return an empty set.
|
||||
*/
|
||||
@@ -98,6 +108,10 @@ NexusSet* NetESelect::nex_input(bool rem_out)
|
||||
{
|
||||
NexusSet*result = base_? base_->nex_input(rem_out) : new NexusSet();
|
||||
NexusSet*tmp = expr_->nex_input(rem_out);
|
||||
if (tmp == NULL) {
|
||||
delete result;
|
||||
return NULL;
|
||||
}
|
||||
result->add(*tmp);
|
||||
delete tmp;
|
||||
return result;
|
||||
@@ -381,4 +395,3 @@ NexusSet* NetWhile::nex_input(bool rem_out)
|
||||
delete tmp;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
+12
-34
@@ -38,9 +38,9 @@
|
||||
NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t)
|
||||
: type_(t), up_(up), sib_(0), sub_(0)
|
||||
{
|
||||
signals_ = 0;
|
||||
events_ = 0;
|
||||
lcounter_ = 0;
|
||||
is_auto_ = false;
|
||||
|
||||
if (up) {
|
||||
default_nettype_ = up->default_nettype();
|
||||
@@ -106,7 +106,7 @@ void NetScope::set_line(perm_string file, perm_string def_file,
|
||||
}
|
||||
|
||||
NetExpr* NetScope::set_parameter(perm_string key, NetExpr*expr,
|
||||
ivl_variable_type_t type,
|
||||
ivl_variable_type_t type__,
|
||||
NetExpr*msb, NetExpr*lsb, bool signed_flag,
|
||||
NetScope::range_t*range_list,
|
||||
const LineInfo&file_line)
|
||||
@@ -114,7 +114,7 @@ NetExpr* NetScope::set_parameter(perm_string key, NetExpr*expr,
|
||||
param_expr_t&ref = parameters[key];
|
||||
NetExpr* res = ref.expr;
|
||||
ref.expr = expr;
|
||||
ref.type = type;
|
||||
ref.type = type__;
|
||||
ref.msb = msb;
|
||||
ref.lsb = lsb;
|
||||
ref.signed_flag = signed_flag;
|
||||
@@ -122,7 +122,7 @@ NetExpr* NetScope::set_parameter(perm_string key, NetExpr*expr,
|
||||
ref.range = range_list;
|
||||
ref.set_line(file_line);
|
||||
|
||||
ivl_assert(file_line, type != IVL_VT_NO_TYPE);
|
||||
ivl_assert(file_line, type__ != IVL_VT_NO_TYPE);
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -166,7 +166,7 @@ bool NetScope::replace_parameter(perm_string key, NetExpr*expr)
|
||||
|
||||
/*
|
||||
* This is not really complete (msb, lsb, sign). It is currently only
|
||||
* used to add a genver to the local parameter list.
|
||||
* used to add a genvar to the local parameter list.
|
||||
*/
|
||||
NetExpr* NetScope::set_localparam(perm_string key, NetExpr*expr,
|
||||
const LineInfo&file_line)
|
||||
@@ -261,6 +261,7 @@ NetFuncDef* NetScope::func_def()
|
||||
assert( type_ == FUNC );
|
||||
return func_;
|
||||
}
|
||||
|
||||
bool NetScope::in_func()
|
||||
{
|
||||
return (type_ == FUNC) ? true : false;
|
||||
@@ -275,7 +276,7 @@ const NetFuncDef* NetScope::func_def() const
|
||||
void NetScope::set_module_name(perm_string n)
|
||||
{
|
||||
assert(type_ == MODULE);
|
||||
module_name_ = n; /* NOTE: n mus have been permallocated. */
|
||||
module_name_ = n; /* NOTE: n must have been permallocated. */
|
||||
}
|
||||
|
||||
perm_string NetScope::module_name() const
|
||||
@@ -358,30 +359,13 @@ NetEvent* NetScope::find_event(perm_string name)
|
||||
|
||||
void NetScope::add_signal(NetNet*net)
|
||||
{
|
||||
if (signals_ == 0) {
|
||||
net->sig_next_ = net;
|
||||
net->sig_prev_ = net;
|
||||
} else {
|
||||
net->sig_next_ = signals_->sig_next_;
|
||||
net->sig_prev_ = signals_;
|
||||
net->sig_next_->sig_prev_ = net;
|
||||
net->sig_prev_->sig_next_ = net;
|
||||
}
|
||||
signals_ = net;
|
||||
signals_map_[net->name()]=net;
|
||||
}
|
||||
|
||||
void NetScope::rem_signal(NetNet*net)
|
||||
{
|
||||
assert(net->scope() == this);
|
||||
if (signals_ == net)
|
||||
signals_ = net->sig_prev_;
|
||||
|
||||
if (signals_ == net) {
|
||||
signals_ = 0;
|
||||
} else {
|
||||
net->sig_prev_->sig_next_ = net->sig_next_;
|
||||
net->sig_next_->sig_prev_ = net->sig_prev_;
|
||||
}
|
||||
signals_map_.erase(net->name());
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -391,16 +375,10 @@ void NetScope::rem_signal(NetNet*net)
|
||||
*/
|
||||
NetNet* NetScope::find_signal(perm_string key)
|
||||
{
|
||||
if (signals_ == 0)
|
||||
if (signals_map_.find(key)!=signals_map_.end())
|
||||
return signals_map_[key];
|
||||
else
|
||||
return 0;
|
||||
|
||||
NetNet*cur = signals_;
|
||||
do {
|
||||
if (cur->name() == key)
|
||||
return cur;
|
||||
cur = cur->sig_prev_;
|
||||
} while (cur != signals_);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+18
-15
@@ -42,22 +42,21 @@ static bool has_enable(ivl_switch_type_t tt)
|
||||
}
|
||||
}
|
||||
|
||||
NetTran::NetTran(NetScope*scope, perm_string n, ivl_switch_type_t tt)
|
||||
: NetNode(scope, n, has_enable(tt)? 3 : 2), type_(tt)
|
||||
NetTran::NetTran(NetScope*scope__, perm_string n, ivl_switch_type_t tt)
|
||||
: NetNode(scope__, n, has_enable(tt)? 3 : 2), type_(tt)
|
||||
{
|
||||
pin(0).set_dir(Link::PASSIVE); pin(0).set_name(perm_string::literal("A"), 0);
|
||||
pin(1).set_dir(Link::PASSIVE); pin(1).set_name(perm_string::literal("B"), 0);
|
||||
pin(0).set_dir(Link::PASSIVE);
|
||||
pin(1).set_dir(Link::PASSIVE);
|
||||
if (pin_count() == 3) {
|
||||
pin(2).set_dir(Link::INPUT);
|
||||
pin(2).set_name(perm_string::literal("E"), 0);
|
||||
pin(2).set_dir(Link::INPUT); // Enable
|
||||
}
|
||||
}
|
||||
|
||||
NetTran::NetTran(NetScope*scope, perm_string n, unsigned wid, unsigned part, unsigned off)
|
||||
: NetNode(scope, n, 2), type_(IVL_SW_TRAN_VP), wid_(wid), part_(part), off_(off)
|
||||
NetTran::NetTran(NetScope*scope__, perm_string n, unsigned wid, unsigned part, unsigned off)
|
||||
: NetNode(scope__, n, 2), type_(IVL_SW_TRAN_VP), wid_(wid), part_(part), off_(off)
|
||||
{
|
||||
pin(0).set_dir(Link::PASSIVE); pin(0).set_name(perm_string::literal("A"), 0);
|
||||
pin(1).set_dir(Link::PASSIVE); pin(1).set_name(perm_string::literal("B"), 0);
|
||||
pin(0).set_dir(Link::PASSIVE);
|
||||
pin(1).set_dir(Link::PASSIVE);
|
||||
}
|
||||
|
||||
NetTran::~NetTran()
|
||||
@@ -100,8 +99,12 @@ void join_island(NetObj*obj)
|
||||
Nexus*nex = obj->pin(idx).nexus();
|
||||
for (Link*cur = nex->first_nlink() ; cur ; cur = cur->next_nlink()) {
|
||||
unsigned pin;
|
||||
NetObj*tmp;
|
||||
cur->cur_link(tmp, pin);
|
||||
NetPins*tmp_pins;
|
||||
cur->cur_link(tmp_pins, pin);
|
||||
|
||||
NetObj*tmp = dynamic_cast<NetObj*> (tmp_pins);
|
||||
if (tmp == 0)
|
||||
continue;
|
||||
|
||||
// Skip self.
|
||||
if (tmp == obj)
|
||||
@@ -114,7 +117,7 @@ void join_island(NetObj*obj)
|
||||
|
||||
// If that is an uncommitted branch, then save
|
||||
// it. When I finally choose an island for self,
|
||||
// these branches will be scanned so tha they join
|
||||
// these branches will be scanned so that they join
|
||||
// this island as well.
|
||||
if (tmp_branch->island == 0) {
|
||||
uncommitted_neighbors.push_back(tmp);
|
||||
@@ -128,7 +131,7 @@ void join_island(NetObj*obj)
|
||||
if (branch->island == 0) {
|
||||
if (debug_elaborate)
|
||||
cerr << obj->get_fileline() << ": debug: "
|
||||
<< "Join brach to existing island." << endl;
|
||||
<< "Join branch to existing island." << endl;
|
||||
branch->island = tmp_branch->island;
|
||||
|
||||
} else if (branch->island != tmp_branch->island) {
|
||||
@@ -139,7 +142,7 @@ void join_island(NetObj*obj)
|
||||
}
|
||||
}
|
||||
|
||||
// If after all that we did not find an idland to join, then
|
||||
// If after all that we did not find an island to join, then
|
||||
// start the island not and join it.
|
||||
if (branch->island == 0) {
|
||||
branch->island = new ivl_island_s;
|
||||
|
||||
@@ -30,10 +30,8 @@ NetUDP::NetUDP(NetScope*s, perm_string n, unsigned pins, PUdp *u)
|
||||
: NetNode(s, n, pins), udp(u)
|
||||
{
|
||||
pin(0).set_dir(Link::OUTPUT);
|
||||
pin(0).set_name(perm_string::literal("O"), 0);
|
||||
for (unsigned idx = 1 ; idx < pins ; idx += 1) {
|
||||
pin(idx).set_dir(Link::INPUT);
|
||||
pin(idx).set_name(perm_string::literal("I"), idx-1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+259
-249
@@ -23,6 +23,7 @@
|
||||
|
||||
# include <typeinfo>
|
||||
# include <cstdlib>
|
||||
# include <climits>
|
||||
# include "compiler.h"
|
||||
# include "netlist.h"
|
||||
# include "netmisc.h"
|
||||
@@ -91,7 +92,7 @@ unsigned count_inputs(const Link&pin)
|
||||
const Nexus*nex = pin.nexus();
|
||||
for (const Link*clnk = nex->first_nlink()
|
||||
; clnk ; clnk = clnk->next_nlink()) {
|
||||
const NetObj*cur;
|
||||
const NetPins*cur;
|
||||
unsigned cpin;
|
||||
clnk->cur_link(cur, cpin);
|
||||
if (cur->pin(cpin).get_dir() == Link::INPUT)
|
||||
@@ -108,7 +109,7 @@ unsigned count_outputs(const Link&pin)
|
||||
const Nexus*nex = pin.nexus();
|
||||
for (const Link*clnk = nex->first_nlink()
|
||||
; clnk ; clnk = clnk->next_nlink()) {
|
||||
const NetObj*cur;
|
||||
const NetPins*cur;
|
||||
unsigned cpin;
|
||||
clnk->cur_link(cur, cpin);
|
||||
if (cur->pin(cpin).get_dir() == Link::OUTPUT)
|
||||
@@ -125,7 +126,7 @@ unsigned count_signals(const Link&pin)
|
||||
const Nexus*nex = pin.nexus();
|
||||
for (const Link*clnk = nex->first_nlink()
|
||||
; clnk ; clnk = clnk->next_nlink()) {
|
||||
const NetObj*cur;
|
||||
const NetPins*cur;
|
||||
unsigned cpin;
|
||||
clnk->cur_link(cur, cpin);
|
||||
if (dynamic_cast<const NetNet*>(cur))
|
||||
@@ -142,7 +143,7 @@ const NetNet* find_link_signal(const NetObj*net, unsigned pin, unsigned&bidx)
|
||||
for (const Link*clnk = nex->first_nlink()
|
||||
; clnk ; clnk = clnk->next_nlink()) {
|
||||
|
||||
const NetObj*cur;
|
||||
const NetPins*cur;
|
||||
unsigned cpin;
|
||||
clnk->cur_link(cur, cpin);
|
||||
|
||||
@@ -171,19 +172,53 @@ Link* find_next_output(Link*lnk)
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetObj::NetObj(NetScope*s, perm_string n, unsigned np)
|
||||
: scope_(s), name_(n), npins_(np), delay1_(0), delay2_(0), delay3_(0)
|
||||
NetPins::NetPins(unsigned npins)
|
||||
: npins_(npins)
|
||||
{
|
||||
pins_ = new Link[npins_];
|
||||
for (unsigned idx = 0 ; idx < npins_ ; idx += 1) {
|
||||
pins_[idx].node_ = this;
|
||||
pins_[idx].pin_ = idx;
|
||||
pins_[0].pin_zero_ = true;
|
||||
pins_[0].node_ = this;
|
||||
|
||||
for (unsigned idx = 1 ; idx < npins_ ; idx += 1) {
|
||||
pins_[idx].pin_zero_ = false;
|
||||
pins_[idx].pin_ = idx;
|
||||
}
|
||||
}
|
||||
|
||||
NetPins::~NetPins()
|
||||
{
|
||||
delete[]pins_;
|
||||
}
|
||||
|
||||
Link& NetPins::pin(unsigned idx)
|
||||
{
|
||||
if (idx >= npins_) {
|
||||
cerr << get_fileline() << ": internal error: pin("<<idx<<")"
|
||||
<< " out of bounds("<<npins_<<")" << endl;
|
||||
cerr << get_fileline() << ": : typeid="
|
||||
<< typeid(*this).name() << endl;
|
||||
}
|
||||
|
||||
assert(idx < npins_);
|
||||
assert(idx == 0? pins_[0].pin_zero_ : pins_[idx].pin_==idx);
|
||||
|
||||
return pins_[idx];
|
||||
}
|
||||
|
||||
const Link& NetPins::pin(unsigned idx) const
|
||||
{
|
||||
assert(idx < npins_);
|
||||
assert(idx == 0? pins_[0].pin_zero_ : pins_[idx].pin_==idx);
|
||||
return pins_[idx];
|
||||
}
|
||||
|
||||
NetObj::NetObj(NetScope*s, perm_string n, unsigned np)
|
||||
: NetPins(np), scope_(s), name_(n), delay1_(0), delay2_(0), delay3_(0)
|
||||
{
|
||||
}
|
||||
|
||||
NetObj::~NetObj()
|
||||
{
|
||||
delete[]pins_;
|
||||
}
|
||||
|
||||
NetScope* NetObj::scope()
|
||||
@@ -196,25 +231,6 @@ const NetScope* NetObj::scope() const
|
||||
return scope_;
|
||||
}
|
||||
|
||||
Link& NetObj::pin(unsigned idx)
|
||||
{
|
||||
if (idx >= npins_) {
|
||||
cerr << get_fileline() << ": internal error: pin("<<idx<<")"
|
||||
<< " out of bounds("<<npins_<<")" << endl;
|
||||
cerr << get_fileline() << ": : typeid="
|
||||
<< typeid(*this).name() << endl;
|
||||
}
|
||||
|
||||
assert(idx < npins_);
|
||||
return pins_[idx];
|
||||
}
|
||||
|
||||
const Link& NetObj::pin(unsigned idx) const
|
||||
{
|
||||
assert(idx < npins_);
|
||||
return pins_[idx];
|
||||
}
|
||||
|
||||
NetNode::NetNode(NetScope*s, perm_string n, unsigned npins)
|
||||
: NetObj(s, n, npins), node_next_(0), node_prev_(0), design_(0)
|
||||
{
|
||||
@@ -226,8 +242,19 @@ NetNode::~NetNode()
|
||||
design_->del_node(this);
|
||||
}
|
||||
|
||||
NetBus::NetBus(NetScope*s, unsigned pin_count)
|
||||
: NetObj(s, perm_string::literal(""), pin_count)
|
||||
NetBranch::NetBranch(ivl_discipline_t dis)
|
||||
: NetPins(2), discipline_(dis)
|
||||
{
|
||||
pin(0).set_dir(Link::PASSIVE);
|
||||
pin(1).set_dir(Link::PASSIVE);
|
||||
}
|
||||
|
||||
NetBranch::~NetBranch()
|
||||
{
|
||||
}
|
||||
|
||||
NetBus::NetBus(NetScope*s, unsigned pin_count__)
|
||||
: NetObj(s, perm_string::literal(""), pin_count__)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -244,13 +271,11 @@ NetDelaySrc::NetDelaySrc(NetScope*s, perm_string n, unsigned npins,
|
||||
posedge_ = false;
|
||||
negedge_ = false;
|
||||
for (unsigned idx = 0 ; idx < npins ; idx += 1) {
|
||||
pin(idx).set_name(perm_string::literal("I"), idx);
|
||||
pin(idx).set_dir(Link::INPUT);
|
||||
}
|
||||
|
||||
if (condit_src) {
|
||||
condit_flag_ = true;
|
||||
pin(npins).set_name(perm_string::literal("COND"), 0);
|
||||
pin(npins).set_dir(Link::INPUT);
|
||||
}
|
||||
}
|
||||
@@ -402,9 +427,10 @@ const Link& NetDelaySrc::condit_pin() const
|
||||
}
|
||||
|
||||
NetNet::NetNet(NetScope*s, perm_string n, Type t, unsigned npins)
|
||||
: NetObj(s, n, 1), sig_next_(0), sig_prev_(0),
|
||||
: NetObj(s, n, 1),
|
||||
type_(t), port_type_(NOT_A_PORT), data_type_(IVL_VT_NO_TYPE),
|
||||
signed_(false), isint_(false), msb_(npins-1), lsb_(0), dimensions_(0),
|
||||
signed_(false), isint_(false), discipline_(0), msb_(npins-1), lsb_(0),
|
||||
dimensions_(0),
|
||||
s0_(0), e0_(0), local_flag_(false), eref_count_(0), lref_count_(0)
|
||||
{
|
||||
assert(s);
|
||||
@@ -432,7 +458,6 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t, unsigned npins)
|
||||
break;
|
||||
}
|
||||
|
||||
pin(0).set_name(perm_string::literal("P"), 0);
|
||||
pin(0).set_dir(dir);
|
||||
pin(0).set_init(init_value);
|
||||
|
||||
@@ -441,10 +466,9 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t, unsigned npins)
|
||||
|
||||
NetNet::NetNet(NetScope*s, perm_string n, Type t,
|
||||
long ms, long ls)
|
||||
: NetObj(s, n, 1),
|
||||
sig_next_(0), sig_prev_(0), type_(t),
|
||||
: NetObj(s, n, 1), type_(t),
|
||||
port_type_(NOT_A_PORT), data_type_(IVL_VT_NO_TYPE), signed_(false),
|
||||
isint_(false), msb_(ms), lsb_(ls), dimensions_(0), s0_(0), e0_(0),
|
||||
isint_(false), discipline_(0), msb_(ms), lsb_(ls), dimensions_(0), s0_(0), e0_(0),
|
||||
local_flag_(false), eref_count_(0), lref_count_(0)
|
||||
{
|
||||
assert(s);
|
||||
@@ -471,7 +495,6 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t,
|
||||
}
|
||||
|
||||
for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) {
|
||||
pin(idx).set_name(perm_string::literal("P"), idx);
|
||||
pin(idx).set_dir(dir);
|
||||
pin(idx).set_init(init_value);
|
||||
}
|
||||
@@ -490,9 +513,9 @@ static unsigned calculate_count(long s, long e)
|
||||
NetNet::NetNet(NetScope*s, perm_string n, Type t,
|
||||
long ms, long ls, long array_s, long array_e)
|
||||
: NetObj(s, n, calculate_count(array_s, array_e)),
|
||||
sig_next_(0), sig_prev_(0), type_(t), port_type_(NOT_A_PORT),
|
||||
type_(t), port_type_(NOT_A_PORT),
|
||||
data_type_(IVL_VT_NO_TYPE), signed_(false), isint_(false),
|
||||
msb_(ms), lsb_(ls), dimensions_(1), s0_(array_s), e0_(array_e),
|
||||
discipline_(0), msb_(ms), lsb_(ls), dimensions_(1), s0_(array_s), e0_(array_e),
|
||||
local_flag_(false), eref_count_(0), lref_count_(0)
|
||||
{
|
||||
assert(s);
|
||||
@@ -519,7 +542,6 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t,
|
||||
}
|
||||
|
||||
for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) {
|
||||
pin(idx).set_name(perm_string::literal("P"), idx);
|
||||
pin(idx).set_dir(dir);
|
||||
pin(idx).set_init(init_value);
|
||||
}
|
||||
@@ -604,7 +626,10 @@ void NetNet::data_type(ivl_variable_type_t t)
|
||||
|
||||
bool NetNet::get_signed() const
|
||||
{
|
||||
return signed_;
|
||||
if (data_type_ == IVL_VT_REAL)
|
||||
return true;
|
||||
else
|
||||
return signed_;
|
||||
}
|
||||
|
||||
void NetNet::set_signed(bool flag)
|
||||
@@ -622,6 +647,17 @@ void NetNet::set_isint(bool flag)
|
||||
isint_ = flag;
|
||||
}
|
||||
|
||||
ivl_discipline_t NetNet::get_discipline() const
|
||||
{
|
||||
return discipline_;
|
||||
}
|
||||
|
||||
void NetNet::set_discipline(ivl_discipline_t dis)
|
||||
{
|
||||
ivl_assert(*this, discipline_ == 0);
|
||||
discipline_ = dis;
|
||||
}
|
||||
|
||||
long NetNet::lsb() const
|
||||
{
|
||||
return lsb_;
|
||||
@@ -745,9 +781,9 @@ const NetDelaySrc* NetNet::delay_path(unsigned idx) const
|
||||
}
|
||||
|
||||
NetPartSelect::NetPartSelect(NetNet*sig, unsigned off, unsigned wid,
|
||||
NetPartSelect::dir_t dir)
|
||||
NetPartSelect::dir_t dir__)
|
||||
: NetNode(sig->scope(), sig->scope()->local_symbol(), 2),
|
||||
off_(off), wid_(wid), dir_(dir)
|
||||
off_(off), wid_(wid), dir_(dir__)
|
||||
{
|
||||
connect(pin(1), sig->pin(0));
|
||||
set_line(*sig);
|
||||
@@ -762,8 +798,6 @@ NetPartSelect::NetPartSelect(NetNet*sig, unsigned off, unsigned wid,
|
||||
pin(1).set_dir(Link::OUTPUT);
|
||||
break;
|
||||
}
|
||||
pin(0).set_name(perm_string::literal("Part"), 0);
|
||||
pin(1).set_name(perm_string::literal("Vect"), 0);
|
||||
}
|
||||
|
||||
NetPartSelect::NetPartSelect(NetNet*sig, NetNet*sel,
|
||||
@@ -785,10 +819,6 @@ NetPartSelect::NetPartSelect(NetNet*sig, NetNet*sel,
|
||||
break;
|
||||
}
|
||||
pin(2).set_dir(Link::INPUT);
|
||||
|
||||
pin(0).set_name(perm_string::literal("Part"), 0);
|
||||
pin(1).set_name(perm_string::literal("Vect"), 0);
|
||||
pin(2).set_name(perm_string::literal("Select"), 0);
|
||||
}
|
||||
|
||||
NetPartSelect::~NetPartSelect()
|
||||
@@ -819,7 +849,7 @@ NetProc::~NetProc()
|
||||
{
|
||||
}
|
||||
|
||||
NetProcTop::NetProcTop(NetScope*s, Type t, NetProc*st)
|
||||
NetProcTop::NetProcTop(NetScope*s, ivl_process_type_t t, NetProc*st)
|
||||
: type_(t), statement_(st), scope_(s)
|
||||
{
|
||||
}
|
||||
@@ -844,19 +874,41 @@ NetScope* NetProcTop::scope()
|
||||
return scope_;
|
||||
}
|
||||
|
||||
NetAnalogTop::NetAnalogTop(NetScope*scope, ivl_process_type_t t, NetProc*st)
|
||||
: type_(t), statement_(st), scope_(scope)
|
||||
{
|
||||
next_ = 0;
|
||||
}
|
||||
|
||||
NetAnalogTop::~NetAnalogTop()
|
||||
{
|
||||
}
|
||||
|
||||
const NetScope* NetProcTop::scope() const
|
||||
{
|
||||
return scope_;
|
||||
}
|
||||
|
||||
NetConcat::NetConcat(NetScope*scope, perm_string n, unsigned wid, unsigned cnt)
|
||||
: NetNode(scope, n, cnt+1), width_(wid)
|
||||
NetCastInt::NetCastInt(NetScope*scope__, perm_string n, unsigned width__)
|
||||
: NetNode(scope__, n, 2), width_(width__)
|
||||
{
|
||||
pin(0).set_dir(Link::OUTPUT);
|
||||
pin(1).set_dir(Link::INPUT);
|
||||
}
|
||||
|
||||
NetCastReal::NetCastReal(NetScope*scope__, perm_string n, bool signed_flag__)
|
||||
: NetNode(scope__, n, 2), signed_flag_(signed_flag__)
|
||||
{
|
||||
pin(0).set_dir(Link::OUTPUT);
|
||||
pin(1).set_dir(Link::INPUT);
|
||||
}
|
||||
|
||||
NetConcat::NetConcat(NetScope*scope__, perm_string n, unsigned wid, unsigned cnt)
|
||||
: NetNode(scope__, n, cnt+1), width_(wid)
|
||||
{
|
||||
pin(0).set_dir(Link::OUTPUT);
|
||||
pin(0).set_name(perm_string::literal("O"), 0);
|
||||
for (unsigned idx = 1 ; idx < cnt+1 ; idx += 1) {
|
||||
pin(idx).set_dir(Link::INPUT);
|
||||
pin(idx).set_name(perm_string::literal("I"), idx-1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -869,14 +921,12 @@ unsigned NetConcat::width() const
|
||||
return width_;
|
||||
}
|
||||
|
||||
NetReplicate::NetReplicate(NetScope*scope, perm_string n,
|
||||
NetReplicate::NetReplicate(NetScope*scope__, perm_string n,
|
||||
unsigned wid, unsigned rpt)
|
||||
: NetNode(scope, n, 2), width_(wid), repeat_(rpt)
|
||||
: NetNode(scope__, n, 2), width_(wid), repeat_(rpt)
|
||||
{
|
||||
pin(0).set_dir(Link::OUTPUT);
|
||||
pin(0).set_name(perm_string::literal("O"), 0);
|
||||
pin(1).set_dir(Link::INPUT);
|
||||
pin(1).set_name(perm_string::literal("I"), 0);
|
||||
}
|
||||
|
||||
NetReplicate::~NetReplicate()
|
||||
@@ -907,25 +957,17 @@ unsigned NetReplicate::repeat() const
|
||||
* ...
|
||||
*/
|
||||
|
||||
NetFF::NetFF(NetScope*s, perm_string n, unsigned width)
|
||||
: NetNode(s, n, 8), width_(width)
|
||||
NetFF::NetFF(NetScope*s, perm_string n, unsigned width__)
|
||||
: NetNode(s, n, 8), width_(width__)
|
||||
{
|
||||
pin_Clock().set_dir(Link::INPUT);
|
||||
pin_Clock().set_name(perm_string::literal("Clock"), 0);
|
||||
pin_Enable().set_dir(Link::INPUT);
|
||||
pin_Enable().set_name(perm_string::literal("Enable"), 0);
|
||||
pin_Aset().set_dir(Link::INPUT);
|
||||
pin_Aset().set_name(perm_string::literal("Aset"), 0);
|
||||
pin_Aclr().set_dir(Link::INPUT);
|
||||
pin_Aclr().set_name(perm_string::literal("Aclr"), 0);
|
||||
pin_Sset().set_dir(Link::INPUT);
|
||||
pin_Sset().set_name(perm_string::literal("Sset"), 0);
|
||||
pin_Sclr().set_dir(Link::INPUT);
|
||||
pin_Sclr().set_name(perm_string::literal("Sclr"), 0);
|
||||
pin_Data().set_dir(Link::INPUT);
|
||||
pin_Data().set_name(perm_string::literal("Data"), 0);
|
||||
pin_Q().set_dir(Link::OUTPUT);
|
||||
pin_Q().set_name(perm_string::literal("Q"), 0);
|
||||
}
|
||||
|
||||
NetFF::~NetFF()
|
||||
@@ -1042,9 +1084,7 @@ NetAbs::NetAbs(NetScope*s, perm_string n, unsigned w)
|
||||
: NetNode(s, n, 2), width_(w)
|
||||
{
|
||||
pin(0).set_dir(Link::OUTPUT);
|
||||
pin(0).set_name(perm_string::literal("Result"), 0);
|
||||
pin(1).set_dir(Link::INPUT);
|
||||
pin(1).set_name(perm_string::literal("DataA"), 0);
|
||||
}
|
||||
|
||||
NetAbs::~NetAbs()
|
||||
@@ -1059,37 +1099,18 @@ unsigned NetAbs::width() const
|
||||
/*
|
||||
* The NetAddSub class represents an LPM_ADD_SUB device. The pinout is
|
||||
* assigned like so:
|
||||
* 0 -- Add_Sub
|
||||
* 1 -- Aclr
|
||||
* 2 -- Clock
|
||||
* 3 -- Cin
|
||||
* 4 -- Cout
|
||||
* 5 -- Overflow
|
||||
* 6 -- DataA (normally a vector)
|
||||
* 7 -- DataB (normally a vector)
|
||||
* 8 -- Result (normally a vector)
|
||||
* 0 -- Cout
|
||||
* 1 -- DataA (normally a vector)
|
||||
* 2 -- DataB (normally a vector)
|
||||
* 3 -- Result (normally a vector)
|
||||
*/
|
||||
NetAddSub::NetAddSub(NetScope*s, perm_string n, unsigned w)
|
||||
: NetNode(s, n, 9), width_(w)
|
||||
: NetNode(s, n, 4), width_(w)
|
||||
{
|
||||
pin(0).set_dir(Link::INPUT);
|
||||
pin(0).set_name(perm_string::literal("Add_Sub"), 0);
|
||||
pin(1).set_dir(Link::INPUT);
|
||||
pin(1).set_name(perm_string::literal("Aclr"), 0);
|
||||
pin(2).set_dir(Link::INPUT);
|
||||
pin(2).set_name(perm_string::literal("Clock"), 0);
|
||||
pin(3).set_dir(Link::INPUT);
|
||||
pin(3).set_name(perm_string::literal("Cin"), 0);
|
||||
pin(4).set_dir(Link::OUTPUT);
|
||||
pin(4).set_name(perm_string::literal("Cout"), 0);
|
||||
pin(5).set_dir(Link::OUTPUT);
|
||||
pin(5).set_name(perm_string::literal("Overflow"), 0);
|
||||
pin(6).set_dir(Link::INPUT);
|
||||
pin(6).set_name(perm_string::literal("DataA"), 0);
|
||||
pin(7).set_dir(Link::INPUT);
|
||||
pin(7).set_name(perm_string::literal("DataB"), 0);
|
||||
pin(8).set_dir(Link::OUTPUT);
|
||||
pin(8).set_name(perm_string::literal("Result"), 0);
|
||||
pin(0).set_dir(Link::OUTPUT); // Cout
|
||||
pin(1).set_dir(Link::INPUT); // DataA
|
||||
pin(2).set_dir(Link::INPUT); // DataB
|
||||
pin(3).set_dir(Link::OUTPUT); // Result
|
||||
}
|
||||
|
||||
NetAddSub::~NetAddSub()
|
||||
@@ -1103,55 +1124,53 @@ unsigned NetAddSub::width()const
|
||||
|
||||
Link& NetAddSub::pin_Cout()
|
||||
{
|
||||
return pin(4);
|
||||
return pin(0);
|
||||
}
|
||||
|
||||
const Link& NetAddSub::pin_Cout() const
|
||||
{
|
||||
return pin(4);
|
||||
return pin(0);
|
||||
}
|
||||
|
||||
Link& NetAddSub::pin_DataA()
|
||||
{
|
||||
return pin(6);
|
||||
return pin(1);
|
||||
}
|
||||
|
||||
const Link& NetAddSub::pin_DataA() const
|
||||
{
|
||||
return pin(6);
|
||||
return pin(1);
|
||||
}
|
||||
|
||||
Link& NetAddSub::pin_DataB()
|
||||
{
|
||||
return pin(7);
|
||||
return pin(2);
|
||||
}
|
||||
|
||||
const Link& NetAddSub::pin_DataB() const
|
||||
{
|
||||
return pin(7);
|
||||
return pin(2);
|
||||
}
|
||||
|
||||
Link& NetAddSub::pin_Result()
|
||||
{
|
||||
return pin(8);
|
||||
return pin(3);
|
||||
}
|
||||
|
||||
const Link& NetAddSub::pin_Result() const
|
||||
{
|
||||
return pin(8);
|
||||
return pin(3);
|
||||
}
|
||||
|
||||
NetArrayDq::NetArrayDq(NetScope*s, perm_string n, NetNet*mem, unsigned awid)
|
||||
NetArrayDq::NetArrayDq(NetScope*s, perm_string n, NetNet*mem__, unsigned awid)
|
||||
: NetNode(s, n, 2),
|
||||
mem_(mem), awidth_(awid)
|
||||
mem_(mem__), awidth_(awid)
|
||||
{
|
||||
pin(0).set_dir(Link::OUTPUT);
|
||||
pin(0).set_name(perm_string::literal("Result"), 0);
|
||||
pin(1).set_dir(Link::INPUT);
|
||||
pin(1).set_name(perm_string::literal("Address"), 0);
|
||||
pin(0).set_dir(Link::OUTPUT); // Result
|
||||
pin(1).set_dir(Link::INPUT); // Address
|
||||
// Increment the expression reference count for the target
|
||||
// memory so that it is not deleted underneath me.
|
||||
mem->incr_eref();
|
||||
mem_->incr_eref();
|
||||
}
|
||||
|
||||
NetArrayDq::~NetArrayDq()
|
||||
@@ -1200,18 +1219,15 @@ const Link& NetArrayDq::pin_Address() const
|
||||
* 2 -- Distance
|
||||
*/
|
||||
NetCLShift::NetCLShift(NetScope*s, perm_string n,
|
||||
unsigned width, unsigned width_dist,
|
||||
bool right_flag, bool signed_flag)
|
||||
unsigned width__, unsigned width_dist__,
|
||||
bool right_flag__, bool signed_flag__)
|
||||
: NetNode(s, n, 3),
|
||||
width_(width), width_dist_(width_dist),
|
||||
right_flag_(right_flag), signed_flag_(signed_flag)
|
||||
width_(width__), width_dist_(width_dist__),
|
||||
right_flag_(right_flag__), signed_flag_(signed_flag__)
|
||||
{
|
||||
pin(0).set_dir(Link::OUTPUT);
|
||||
pin(0).set_name(perm_string::literal("Result"), 0);
|
||||
pin(1).set_dir(Link::INPUT);
|
||||
pin(1).set_name(perm_string::literal("Data"), 0);
|
||||
pin(2).set_dir(Link::INPUT);
|
||||
pin(2).set_name(perm_string::literal("Distance"), 0);
|
||||
pin(0).set_dir(Link::OUTPUT); // Result
|
||||
pin(1).set_dir(Link::INPUT); // Data
|
||||
pin(2).set_dir(Link::INPUT); // Distance
|
||||
}
|
||||
|
||||
NetCLShift::~NetCLShift()
|
||||
@@ -1269,29 +1285,17 @@ const Link& NetCLShift::pin_Distance() const
|
||||
}
|
||||
|
||||
NetCompare::NetCompare(NetScope*s, perm_string n, unsigned wi)
|
||||
: NetNode(s, n, 10), width_(wi)
|
||||
: NetNode(s, n, 8), width_(wi)
|
||||
{
|
||||
signed_flag_ = false;
|
||||
pin(0).set_dir(Link::INPUT); pin(0).set_name(
|
||||
perm_string::literal("Aclr"));
|
||||
pin(1).set_dir(Link::INPUT); pin(1).set_name(
|
||||
perm_string::literal("Clock"));
|
||||
pin(2).set_dir(Link::OUTPUT); pin(2).set_name(
|
||||
perm_string::literal("AGB"));
|
||||
pin(3).set_dir(Link::OUTPUT); pin(3).set_name(
|
||||
perm_string::literal("AGEB"));
|
||||
pin(4).set_dir(Link::OUTPUT); pin(4).set_name(
|
||||
perm_string::literal("AEB"));
|
||||
pin(5).set_dir(Link::OUTPUT); pin(5).set_name(
|
||||
perm_string::literal("ANEB"));
|
||||
pin(6).set_dir(Link::OUTPUT); pin(6).set_name(
|
||||
perm_string::literal("ALB"));
|
||||
pin(7).set_dir(Link::OUTPUT); pin(7).set_name(
|
||||
perm_string::literal("ALEB"));
|
||||
pin(8).set_dir(Link::INPUT);
|
||||
pin(8).set_name(perm_string::literal("DataA"));
|
||||
pin(9).set_dir(Link::INPUT);
|
||||
pin(9).set_name(perm_string::literal("DataB"));
|
||||
pin(0).set_dir(Link::OUTPUT); // AGB
|
||||
pin(1).set_dir(Link::OUTPUT); // AGEB
|
||||
pin(2).set_dir(Link::OUTPUT); // AEB
|
||||
pin(3).set_dir(Link::OUTPUT); // ANEB
|
||||
pin(4).set_dir(Link::OUTPUT); // ALB
|
||||
pin(5).set_dir(Link::OUTPUT); // ALEB
|
||||
pin(6).set_dir(Link::INPUT); // DataA
|
||||
pin(7).set_dir(Link::INPUT); // DataB
|
||||
}
|
||||
|
||||
NetCompare::~NetCompare()
|
||||
@@ -1313,104 +1317,85 @@ void NetCompare::set_signed(bool flag)
|
||||
signed_flag_ = flag;
|
||||
}
|
||||
|
||||
Link& NetCompare::pin_Aclr()
|
||||
{
|
||||
return pin(0);
|
||||
}
|
||||
|
||||
const Link& NetCompare::pin_Aclr() const
|
||||
{
|
||||
return pin(0);
|
||||
}
|
||||
|
||||
Link& NetCompare::pin_Clock()
|
||||
{
|
||||
return pin(1);
|
||||
}
|
||||
|
||||
const Link& NetCompare::pin_Clock() const
|
||||
{
|
||||
return pin(1);
|
||||
}
|
||||
|
||||
Link& NetCompare::pin_AGB()
|
||||
{
|
||||
return pin(2);
|
||||
return pin(0);
|
||||
}
|
||||
|
||||
const Link& NetCompare::pin_AGB() const
|
||||
{
|
||||
return pin(2);
|
||||
return pin(0);
|
||||
}
|
||||
|
||||
Link& NetCompare::pin_AGEB()
|
||||
{
|
||||
return pin(3);
|
||||
return pin(1);
|
||||
}
|
||||
|
||||
const Link& NetCompare::pin_AGEB() const
|
||||
{
|
||||
return pin(3);
|
||||
return pin(1);
|
||||
}
|
||||
|
||||
Link& NetCompare::pin_AEB()
|
||||
{
|
||||
return pin(4);
|
||||
return pin(2);
|
||||
}
|
||||
|
||||
const Link& NetCompare::pin_AEB() const
|
||||
{
|
||||
return pin(4);
|
||||
return pin(2);
|
||||
}
|
||||
|
||||
Link& NetCompare::pin_ANEB()
|
||||
{
|
||||
return pin(5);
|
||||
return pin(3);
|
||||
}
|
||||
|
||||
const Link& NetCompare::pin_ANEB() const
|
||||
{
|
||||
return pin(5);
|
||||
return pin(3);
|
||||
}
|
||||
|
||||
Link& NetCompare::pin_ALB()
|
||||
{
|
||||
return pin(6);
|
||||
return pin(4);
|
||||
}
|
||||
|
||||
const Link& NetCompare::pin_ALB() const
|
||||
{
|
||||
return pin(6);
|
||||
return pin(4);
|
||||
}
|
||||
|
||||
Link& NetCompare::pin_ALEB()
|
||||
{
|
||||
return pin(7);
|
||||
return pin(5);
|
||||
}
|
||||
|
||||
const Link& NetCompare::pin_ALEB() const
|
||||
{
|
||||
return pin(7);
|
||||
return pin(5);
|
||||
}
|
||||
|
||||
Link& NetCompare::pin_DataA()
|
||||
{
|
||||
return pin(8);
|
||||
return pin(6);
|
||||
}
|
||||
|
||||
const Link& NetCompare::pin_DataA() const
|
||||
{
|
||||
return pin(8);
|
||||
return pin(6);
|
||||
}
|
||||
|
||||
Link& NetCompare::pin_DataB()
|
||||
{
|
||||
return pin(9);
|
||||
return pin(7);
|
||||
}
|
||||
|
||||
const Link& NetCompare::pin_DataB() const
|
||||
{
|
||||
return pin(9);
|
||||
return pin(7);
|
||||
}
|
||||
|
||||
NetDivide::NetDivide(NetScope*sc, perm_string n, unsigned wr,
|
||||
@@ -1418,12 +1403,9 @@ NetDivide::NetDivide(NetScope*sc, perm_string n, unsigned wr,
|
||||
: NetNode(sc, n, 3),
|
||||
width_r_(wr), width_a_(wa), width_b_(wb), signed_flag_(false)
|
||||
{
|
||||
pin(0).set_dir(Link::OUTPUT);
|
||||
pin(0).set_name(perm_string::literal("Result"), 0);
|
||||
pin(1).set_dir(Link::INPUT);
|
||||
pin(1).set_name(perm_string::literal("DataA"), 0);
|
||||
pin(2).set_dir(Link::INPUT);
|
||||
pin(2).set_name(perm_string::literal("DataB"), 0);
|
||||
pin(0).set_dir(Link::OUTPUT); // Result
|
||||
pin(1).set_dir(Link::INPUT); // DataA
|
||||
pin(2).set_dir(Link::INPUT); // DataB
|
||||
}
|
||||
|
||||
NetDivide::~NetDivide()
|
||||
@@ -1489,13 +1471,17 @@ NetLiteral::NetLiteral(NetScope*sc, perm_string n, const verireal&val)
|
||||
: NetNode(sc, n, 1), real_(val)
|
||||
{
|
||||
pin(0).set_dir(Link::OUTPUT);
|
||||
pin(0).set_name(perm_string::literal("O"), 0);
|
||||
}
|
||||
|
||||
NetLiteral::~NetLiteral()
|
||||
{
|
||||
}
|
||||
|
||||
ivl_variable_type_t NetLiteral::data_type() const
|
||||
{
|
||||
return IVL_VT_REAL;
|
||||
}
|
||||
|
||||
const verireal& NetLiteral::value_real() const
|
||||
{
|
||||
return real_;
|
||||
@@ -1506,12 +1492,9 @@ NetMult::NetMult(NetScope*sc, perm_string n, unsigned wr,
|
||||
: NetNode(sc, n, 3),
|
||||
signed_(false), width_r_(wr), width_a_(wa), width_b_(wb)
|
||||
{
|
||||
pin(0).set_dir(Link::OUTPUT);
|
||||
pin(0).set_name(perm_string::literal("Result"), 0);
|
||||
pin(1).set_dir(Link::INPUT);
|
||||
pin(1).set_name(perm_string::literal("DataA"), 0);
|
||||
pin(2).set_dir(Link::INPUT);
|
||||
pin(2).set_name(perm_string::literal("DataB"), 0);
|
||||
pin(0).set_dir(Link::OUTPUT); // Result
|
||||
pin(1).set_dir(Link::INPUT); // DataA
|
||||
pin(2).set_dir(Link::INPUT); // DataB
|
||||
}
|
||||
|
||||
NetMult::~NetMult()
|
||||
@@ -1578,12 +1561,9 @@ NetPow::NetPow(NetScope*sc, perm_string n, unsigned wr,
|
||||
: NetNode(sc, n, 3),
|
||||
signed_(false), width_r_(wr), width_a_(wa), width_b_(wb)
|
||||
{
|
||||
pin(0).set_dir(Link::OUTPUT);
|
||||
pin(0).set_name(perm_string::literal("Result"), 0);
|
||||
pin(1).set_dir(Link::INPUT);
|
||||
pin(1).set_name(perm_string::literal("DataA"), 0);
|
||||
pin(2).set_dir(Link::INPUT);
|
||||
pin(2).set_name(perm_string::literal("DataB"), 0);
|
||||
pin(0).set_dir(Link::OUTPUT); // Result
|
||||
pin(1).set_dir(Link::INPUT); // DataA
|
||||
pin(2).set_dir(Link::INPUT); // DataB
|
||||
}
|
||||
|
||||
NetPow::~NetPow()
|
||||
@@ -1658,14 +1638,11 @@ NetMux::NetMux(NetScope*s, perm_string n,
|
||||
: NetNode(s, n, 2+si),
|
||||
width_(wi), size_(si), swidth_(sw)
|
||||
{
|
||||
pin(0).set_dir(Link::OUTPUT);
|
||||
pin(0).set_name(perm_string::literal("Q"), 0);
|
||||
pin(1).set_dir(Link::INPUT);
|
||||
pin(1).set_name(perm_string::literal("Sel"), 0);
|
||||
pin(0).set_dir(Link::OUTPUT); // Q
|
||||
pin(1).set_dir(Link::INPUT); // Sel
|
||||
|
||||
for (unsigned idx = 0 ; idx < size_ ; idx += 1) {
|
||||
pin_Data(idx).set_dir(Link::INPUT);
|
||||
pin_Data(idx).set_name(perm_string::literal("D"), idx);
|
||||
pin_Data(idx).set_dir(Link::INPUT); // Data[idx]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1725,8 +1702,6 @@ NetSignExtend::NetSignExtend(NetScope*s, perm_string n, unsigned w)
|
||||
{
|
||||
pin(0).set_dir(Link::OUTPUT);
|
||||
pin(1).set_dir(Link::INPUT);
|
||||
pin(0).set_name(perm_string::literal("O"), 0);
|
||||
pin(1).set_name(perm_string::literal("I"), 0);
|
||||
}
|
||||
|
||||
NetSignExtend::~NetSignExtend()
|
||||
@@ -1743,8 +1718,6 @@ NetBUFZ::NetBUFZ(NetScope*s, perm_string n, unsigned w)
|
||||
{
|
||||
pin(0).set_dir(Link::OUTPUT);
|
||||
pin(1).set_dir(Link::INPUT);
|
||||
pin(0).set_name(perm_string::literal("O"), 0);
|
||||
pin(1).set_name(perm_string::literal("I"), 0);
|
||||
}
|
||||
|
||||
NetBUFZ::~NetBUFZ()
|
||||
@@ -1756,12 +1729,12 @@ unsigned NetBUFZ::width() const
|
||||
return width_;
|
||||
}
|
||||
|
||||
NetCaseCmp::NetCaseCmp(NetScope*s, perm_string n, unsigned wid, bool eeq)
|
||||
: NetNode(s, n, 3), width_(wid), eeq_(eeq)
|
||||
NetCaseCmp::NetCaseCmp(NetScope*s, perm_string n, unsigned wid, bool eeq__)
|
||||
: NetNode(s, n, 3), width_(wid), eeq_(eeq__)
|
||||
{
|
||||
pin(0).set_dir(Link::OUTPUT); pin(0).set_name(perm_string::literal("O"),0);
|
||||
pin(1).set_dir(Link::INPUT); pin(1).set_name(perm_string::literal("I"),0);
|
||||
pin(2).set_dir(Link::INPUT); pin(2).set_name(perm_string::literal("I"),1);
|
||||
pin(0).set_dir(Link::OUTPUT);
|
||||
pin(1).set_dir(Link::INPUT);
|
||||
pin(2).set_dir(Link::INPUT);
|
||||
}
|
||||
|
||||
NetCaseCmp::~NetCaseCmp()
|
||||
@@ -1820,7 +1793,6 @@ NetConst::NetConst(NetScope*s, perm_string n, verinum::V v)
|
||||
: NetNode(s, n, 1), width_(1)
|
||||
{
|
||||
pin(0).set_dir(Link::OUTPUT);
|
||||
pin(0).set_name(perm_string::literal("O"), 0);
|
||||
value_ = new verinum::V[1];
|
||||
value_[0] = v;
|
||||
}
|
||||
@@ -1829,7 +1801,6 @@ NetConst::NetConst(NetScope*s, perm_string n, const verinum&val)
|
||||
: NetNode(s, n, 1), width_(val.len())
|
||||
{
|
||||
pin(0).set_dir(Link::OUTPUT);
|
||||
pin(0).set_name(perm_string::literal("O"), 0);
|
||||
value_ = new verinum::V[width_];
|
||||
for (unsigned idx = 0 ; idx < width_ ; idx += 1) {
|
||||
value_[idx] = val.get(idx);
|
||||
@@ -1860,12 +1831,7 @@ NetFuncDef::NetFuncDef(NetScope*s, NetNet*result, const svector<NetNet*>&po)
|
||||
NetFuncDef::~NetFuncDef()
|
||||
{
|
||||
}
|
||||
#if 0
|
||||
const string NetFuncDef::name() const
|
||||
{
|
||||
return scope_->name();
|
||||
}
|
||||
#endif
|
||||
|
||||
const NetScope* NetFuncDef::scope() const
|
||||
{
|
||||
return scope_;
|
||||
@@ -1989,17 +1955,50 @@ NetUTask::NetUTask(NetScope*def)
|
||||
NetUTask::~NetUTask()
|
||||
{
|
||||
}
|
||||
#if 0
|
||||
const string NetUTask::name() const
|
||||
{
|
||||
return task_->name();
|
||||
}
|
||||
#endif
|
||||
|
||||
const NetScope* NetUTask::task() const
|
||||
{
|
||||
return task_;
|
||||
}
|
||||
|
||||
NetAlloc::NetAlloc(NetScope*scope__)
|
||||
: scope_(scope__)
|
||||
{
|
||||
}
|
||||
|
||||
NetAlloc::~NetAlloc()
|
||||
{
|
||||
}
|
||||
#if 0
|
||||
const string NetAlloc::name() const
|
||||
{
|
||||
return scope_->name();
|
||||
}
|
||||
#endif
|
||||
const NetScope* NetAlloc::scope() const
|
||||
{
|
||||
return scope_;
|
||||
}
|
||||
|
||||
NetFree::NetFree(NetScope*scope__)
|
||||
: scope_(scope__)
|
||||
{
|
||||
}
|
||||
|
||||
NetFree::~NetFree()
|
||||
{
|
||||
}
|
||||
#if 0
|
||||
const string NetFree::name() const
|
||||
{
|
||||
return scope_->name();
|
||||
}
|
||||
#endif
|
||||
const NetScope* NetFree::scope() const
|
||||
{
|
||||
return scope_;
|
||||
}
|
||||
|
||||
NetExpr::NetExpr(unsigned w)
|
||||
: width_(w), signed_flag_(false)
|
||||
{
|
||||
@@ -2019,6 +2018,13 @@ void NetExpr::cast_signed(bool flag)
|
||||
signed_flag_ = flag;
|
||||
}
|
||||
|
||||
void NetExpr::expr_width(unsigned w)
|
||||
{
|
||||
// Catch underflow wrap errors.
|
||||
ivl_assert(*this, w < (UINT_MAX - 256));
|
||||
width_ = w;
|
||||
}
|
||||
|
||||
bool NetExpr::has_width() const
|
||||
{
|
||||
return true;
|
||||
@@ -2031,8 +2037,8 @@ bool NetExpr::has_width() const
|
||||
* be. However, if we don't, our default will be the width of the
|
||||
* largest operand.
|
||||
*/
|
||||
NetEBBits::NetEBBits(char op, NetExpr*l, NetExpr*r)
|
||||
: NetEBinary(op, l, r)
|
||||
NetEBBits::NetEBBits(char op__, NetExpr*l, NetExpr*r)
|
||||
: NetEBinary(op__, l, r)
|
||||
{
|
||||
if (r->expr_width() > l->expr_width())
|
||||
expr_width(r->expr_width());
|
||||
@@ -2051,9 +2057,12 @@ NetEBBits* NetEBBits::dup_expr() const
|
||||
return result;
|
||||
}
|
||||
|
||||
NetEBinary::NetEBinary(char op, NetExpr*l, NetExpr*r)
|
||||
: op_(op), left_(l), right_(r)
|
||||
NetEBinary::NetEBinary(char op__, NetExpr*l, NetExpr*r)
|
||||
: op_(op__), left_(l), right_(r)
|
||||
{
|
||||
// Binary expressions of all sorts are signed if both the
|
||||
// arguments are signed.
|
||||
cast_signed_base_( left_->has_sign() && right_->has_sign());
|
||||
}
|
||||
|
||||
NetEBinary::~NetEBinary()
|
||||
@@ -2073,8 +2082,8 @@ NetEBinary* NetEBinary::dup_expr() const
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetEBLogic::NetEBLogic(char op, NetExpr*l, NetExpr*r)
|
||||
: NetEBinary(op, l, r)
|
||||
NetEBLogic::NetEBLogic(char op__, NetExpr*l, NetExpr*r)
|
||||
: NetEBinary(op__, l, r)
|
||||
{
|
||||
expr_width(1);
|
||||
}
|
||||
@@ -2272,6 +2281,8 @@ const NetExpr* NetETernary::false_expr() const
|
||||
|
||||
ivl_variable_type_t NetETernary::expr_type() const
|
||||
{
|
||||
ivl_assert(*this, true_val_);
|
||||
ivl_assert(*this, false_val_);
|
||||
ivl_variable_type_t tru = true_val_->expr_type();
|
||||
ivl_variable_type_t fal = false_val_->expr_type();
|
||||
if (tru == IVL_VT_LOGIC && fal == IVL_VT_BOOL)
|
||||
@@ -2293,8 +2304,8 @@ ivl_variable_type_t NetETernary::expr_type() const
|
||||
return tru;
|
||||
}
|
||||
|
||||
NetEUnary::NetEUnary(char op, NetExpr*ex)
|
||||
: NetExpr(ex->expr_width()), op_(op), expr_(ex)
|
||||
NetEUnary::NetEUnary(char op__, NetExpr*ex)
|
||||
: NetExpr(ex->expr_width()), op_(op__), expr_(ex)
|
||||
{
|
||||
switch (op_) {
|
||||
case '!':
|
||||
@@ -2322,8 +2333,8 @@ ivl_variable_type_t NetEUnary::expr_type() const
|
||||
return expr_->expr_type();
|
||||
}
|
||||
|
||||
NetEUBits::NetEUBits(char op, NetExpr*ex)
|
||||
: NetEUnary(op, ex)
|
||||
NetEUBits::NetEUBits(char op__, NetExpr*ex)
|
||||
: NetEUnary(op__, ex)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -2336,8 +2347,8 @@ ivl_variable_type_t NetEUBits::expr_type() const
|
||||
return expr_->expr_type();
|
||||
}
|
||||
|
||||
NetEUReduce::NetEUReduce(char op, NetExpr*ex)
|
||||
: NetEUnary(op, ex)
|
||||
NetEUReduce::NetEUReduce(char op__, NetExpr*ex)
|
||||
: NetEUnary(op__, ex)
|
||||
{
|
||||
expr_width(1);
|
||||
}
|
||||
@@ -2356,10 +2367,8 @@ NetLogic::NetLogic(NetScope*s, perm_string n, unsigned pins,
|
||||
: NetNode(s, n, pins), type_(t), width_(wid)
|
||||
{
|
||||
pin(0).set_dir(Link::OUTPUT);
|
||||
pin(0).set_name(perm_string::literal("O"), 0);
|
||||
for (unsigned idx = 1 ; idx < pins ; idx += 1) {
|
||||
pin(idx).set_dir(Link::INPUT);
|
||||
pin(idx).set_name(perm_string::literal("I"), idx-1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2373,14 +2382,12 @@ unsigned NetLogic::width() const
|
||||
return width_;
|
||||
}
|
||||
|
||||
NetUReduce::NetUReduce(NetScope*scope, perm_string n,
|
||||
NetUReduce::NetUReduce(NetScope*scope__, perm_string n,
|
||||
NetUReduce::TYPE t, unsigned wid)
|
||||
: NetNode(scope, n, 2), type_(t), width_(wid)
|
||||
: NetNode(scope__, n, 2), type_(t), width_(wid)
|
||||
{
|
||||
pin(0).set_dir(Link::OUTPUT);
|
||||
pin(0).set_name(perm_string::literal("O"));
|
||||
pin(1).set_dir(Link::INPUT);
|
||||
pin(1).set_name(perm_string::literal("I"));
|
||||
}
|
||||
|
||||
NetUReduce::TYPE NetUReduce::type() const
|
||||
@@ -2552,6 +2559,7 @@ DelayType NetBlock::delay_type() const
|
||||
for (const NetProc*cur = proc_first(); cur; cur = proc_next(cur)) {
|
||||
DelayType dt = cur->delay_type();
|
||||
if (dt > result) result = dt;
|
||||
if (dt == DEFINITE_DELAY) break;
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -2586,7 +2594,9 @@ DelayType NetCondit::delay_type() const
|
||||
if (else_) {
|
||||
result = combine_delays(if_->delay_type(), else_->delay_type());
|
||||
} else {
|
||||
result = if_->delay_type();
|
||||
/* Because of the indeterminate conditional value the
|
||||
* best we can have for this case is a possible delay. */
|
||||
result = combine_delays(if_->delay_type(), NO_DELAY);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
@@ -29,6 +29,8 @@
|
||||
# include <map>
|
||||
# include <list>
|
||||
# include <vector>
|
||||
# include <set>
|
||||
# include <utility>
|
||||
# include "ivl_target.h"
|
||||
# include "pform_types.h"
|
||||
# include "config.h"
|
||||
@@ -66,6 +68,7 @@ class NetTaskDef;
|
||||
class NetEvTrig;
|
||||
class NetEvWait;
|
||||
|
||||
class nature_t;
|
||||
|
||||
struct target;
|
||||
struct functor_t;
|
||||
@@ -74,6 +77,24 @@ ostream& operator << (ostream&o, ivl_variable_type_t val);
|
||||
|
||||
extern void join_island(NetObj*obj);
|
||||
|
||||
class NetPins : public LineInfo {
|
||||
|
||||
public:
|
||||
explicit NetPins(unsigned npins);
|
||||
virtual ~NetPins();
|
||||
|
||||
unsigned pin_count() const { return npins_; }
|
||||
|
||||
Link&pin(unsigned idx);
|
||||
const Link&pin(unsigned idx) const;
|
||||
|
||||
void dump_node_pins(ostream&, unsigned, const char**pin_names =0) const;
|
||||
|
||||
private:
|
||||
Link*pins_;
|
||||
const unsigned npins_;
|
||||
};
|
||||
|
||||
/* =========
|
||||
* A NetObj is anything that has any kind of behavior in the
|
||||
* netlist. Nodes can be gates, registers, etc. and are linked
|
||||
@@ -94,7 +115,7 @@ extern void join_island(NetObj*obj);
|
||||
* interpretation of the rise/fall/decay times is typically left to
|
||||
* the target to properly interpret.
|
||||
*/
|
||||
class NetObj : public Attrib, public virtual LineInfo {
|
||||
class NetObj : public NetPins, public Attrib {
|
||||
|
||||
public:
|
||||
public:
|
||||
@@ -108,8 +129,6 @@ class NetObj : public Attrib, public virtual LineInfo {
|
||||
|
||||
perm_string name() const { return name_; }
|
||||
|
||||
unsigned pin_count() const { return npins_; }
|
||||
|
||||
const NetExpr* rise_time() const { return delay1_; }
|
||||
const NetExpr* fall_time() const { return delay2_; }
|
||||
const NetExpr* decay_time() const { return delay3_; }
|
||||
@@ -118,17 +137,11 @@ class NetObj : public Attrib, public virtual LineInfo {
|
||||
void fall_time(const NetExpr* d) { delay2_ = d; }
|
||||
void decay_time(const NetExpr* d) { delay3_ = d; }
|
||||
|
||||
Link&pin(unsigned idx);
|
||||
const Link&pin(unsigned idx) const;
|
||||
|
||||
void dump_node_pins(ostream&, unsigned) const;
|
||||
void dump_obj_attr(ostream&, unsigned) const;
|
||||
|
||||
private:
|
||||
NetScope*scope_;
|
||||
perm_string name_;
|
||||
Link*pins_;
|
||||
const unsigned npins_;
|
||||
const NetExpr* delay1_;
|
||||
const NetExpr* delay2_;
|
||||
const NetExpr* delay3_;
|
||||
@@ -148,11 +161,31 @@ class IslandBranch {
|
||||
struct ivl_island_s* island;
|
||||
};
|
||||
|
||||
/*
|
||||
* A NetBranch is a construct of Verilog-A that is a branch between
|
||||
* two nodes. The branch has exactly 2 pins and a discipline.
|
||||
*
|
||||
* pin(0) is the source of flow through a branch and the plus side of
|
||||
* potential. Pin(1) is the sink of flow and the minus (or ground) of
|
||||
* potential.
|
||||
*/
|
||||
class NetBranch : public NetPins {
|
||||
|
||||
public:
|
||||
explicit NetBranch(ivl_discipline_t dis);
|
||||
explicit NetBranch(ivl_discipline_t dis, perm_string name);
|
||||
~NetBranch();
|
||||
|
||||
private:
|
||||
ivl_discipline_t discipline_;
|
||||
perm_string name_;
|
||||
};
|
||||
|
||||
class Link {
|
||||
|
||||
friend void connect(Link&, Link&);
|
||||
friend void connect(Nexus*, Link&);
|
||||
friend class NetObj;
|
||||
friend class NetPins;
|
||||
friend class Nexus;
|
||||
|
||||
public:
|
||||
@@ -160,9 +193,11 @@ class Link {
|
||||
|
||||
enum strength_t { HIGHZ, WEAK, PULL, STRONG, SUPPLY };
|
||||
|
||||
private: // Only NetPins can create/delete Link objects
|
||||
Link();
|
||||
~Link();
|
||||
|
||||
public:
|
||||
// Manipulate the link direction.
|
||||
void set_dir(DIR d);
|
||||
DIR get_dir() const;
|
||||
@@ -176,6 +211,10 @@ class Link {
|
||||
void drive0(strength_t);
|
||||
void drive1(strength_t);
|
||||
|
||||
// This sets the drives for all drivers of this link, and not
|
||||
// just the current link.
|
||||
void drivers_drive(strength_t d0, strength_t d1);
|
||||
|
||||
strength_t drive0() const;
|
||||
strength_t drive1() const;
|
||||
|
||||
@@ -186,8 +225,8 @@ class Link {
|
||||
void set_init(verinum::V val);
|
||||
verinum::V get_init() const;
|
||||
|
||||
void cur_link(NetObj*&net, unsigned &pin);
|
||||
void cur_link(const NetObj*&net, unsigned &pin) const;
|
||||
void cur_link(NetPins*&net, unsigned &pin);
|
||||
void cur_link(const NetPins*&net, unsigned &pin) const;
|
||||
|
||||
// Get a pointer to the nexus that represents all the links
|
||||
// connected to me.
|
||||
@@ -214,32 +253,23 @@ class Link {
|
||||
|
||||
// Return information about the object that this link is
|
||||
// a part of.
|
||||
const NetObj*get_obj() const;
|
||||
NetObj*get_obj();
|
||||
const NetPins*get_obj() const;
|
||||
NetPins*get_obj();
|
||||
unsigned get_pin() const;
|
||||
|
||||
// A link of an object (sometimes called a "pin") has a
|
||||
// name. It is convenient for the name to have a string and an
|
||||
// integer part.
|
||||
void set_name(perm_string, unsigned inst =0);
|
||||
perm_string get_name() const;
|
||||
unsigned get_inst() const;
|
||||
|
||||
private:
|
||||
// The NetNode manages these. They point back to the
|
||||
// NetNode so that following the links can get me here.
|
||||
NetObj *node_;
|
||||
unsigned pin_;
|
||||
union {
|
||||
NetPins *node_;
|
||||
unsigned pin_;
|
||||
};
|
||||
|
||||
DIR dir_;
|
||||
strength_t drive0_, drive1_;
|
||||
verinum::V init_;
|
||||
|
||||
// These members name the pin of the link. If the name
|
||||
// has width, then the inst_ member is the index of the
|
||||
// pin.
|
||||
perm_string name_;
|
||||
unsigned inst_;
|
||||
bool pin_zero_ : 1;
|
||||
DIR dir_ : 2;
|
||||
strength_t drive0_ : 3;
|
||||
strength_t drive1_ : 3;
|
||||
verinum::V init_ : 2;
|
||||
|
||||
private:
|
||||
Link *next_;
|
||||
@@ -278,6 +308,7 @@ class Nexus {
|
||||
verinum::V get_init() const;
|
||||
|
||||
void drivers_delays(NetExpr*rise, NetExpr*fall, NetExpr*decay);
|
||||
void drivers_drive(Link::strength_t d0, Link::strength_t d1);
|
||||
|
||||
Link*first_nlink();
|
||||
const Link* first_nlink()const;
|
||||
@@ -288,6 +319,10 @@ class Nexus {
|
||||
|
||||
NetNet* pick_any_net();
|
||||
|
||||
/* This method returns true if there are any drivers
|
||||
(including variables) attached to this nexus. */
|
||||
bool drivers_present() const;
|
||||
|
||||
/* This method returns true if all the possible drivers of
|
||||
this nexus are constant. It will also return true if there
|
||||
are no drivers at all. */
|
||||
@@ -518,6 +553,10 @@ class NetNet : public NetObj {
|
||||
bool get_isint() const;
|
||||
void set_isint(bool);
|
||||
|
||||
/* Attach a discipline to the net. */
|
||||
ivl_discipline_t get_discipline() const;
|
||||
void set_discipline(ivl_discipline_t dis);
|
||||
|
||||
/* These methods return the msb and lsb indices for the most
|
||||
significant and least significant bits. These are signed
|
||||
longs, and may be different from pin numbers. For example,
|
||||
@@ -574,17 +613,13 @@ class NetNet : public NetObj {
|
||||
|
||||
virtual void dump_net(ostream&, unsigned) const;
|
||||
|
||||
private:
|
||||
// The NetScope class uses this for listing signals.
|
||||
friend class NetScope;
|
||||
NetNet*sig_next_, *sig_prev_;
|
||||
|
||||
private:
|
||||
Type type_;
|
||||
PortType port_type_;
|
||||
ivl_variable_type_t data_type_;
|
||||
bool signed_;
|
||||
bool isint_; // original type of integer
|
||||
ivl_discipline_t discipline_;
|
||||
|
||||
long msb_, lsb_;
|
||||
const unsigned dimensions_;
|
||||
@@ -686,6 +721,9 @@ class NetScope : public Attrib {
|
||||
unsigned get_def_lineno() const { return def_lineno_; };
|
||||
|
||||
bool in_func();
|
||||
/* Is the task or function automatic. */
|
||||
void is_auto(bool is_auto__) { is_auto_ = is_auto__; };
|
||||
bool is_auto() const { return is_auto_; };
|
||||
|
||||
const NetTaskDef* task_def() const;
|
||||
const NetFuncDef* func_def() const;
|
||||
@@ -718,8 +756,13 @@ class NetScope : public Attrib {
|
||||
const hname_t& fullname() const { return name_; }
|
||||
|
||||
void run_defparams(class Design*);
|
||||
void run_defparams_later(class Design*);
|
||||
|
||||
void evaluate_parameters(class Design*);
|
||||
|
||||
// Look for defparams that never matched, and print warnings.
|
||||
void residual_defparams(class Design*);
|
||||
|
||||
/* This method generates a non-hierarchical name that is
|
||||
guaranteed to be unique within this scope. */
|
||||
perm_string local_symbol();
|
||||
@@ -737,7 +780,8 @@ class NetScope : public Attrib {
|
||||
assignments from the scope pass to the parameter evaluation
|
||||
step. After that, it is not used. */
|
||||
|
||||
map<pform_name_t,NetExpr*>defparams;
|
||||
list<pair<pform_name_t,NetExpr*> > defparams;
|
||||
list<pair<list<hname_t>,NetExpr*> > defparams_later;
|
||||
|
||||
public:
|
||||
struct range_t {
|
||||
@@ -785,7 +829,7 @@ class NetScope : public Attrib {
|
||||
|
||||
/* Module instance arrays are collected here for access during
|
||||
the multiple elaboration passes. */
|
||||
typedef svector<NetScope*> scope_vec_t;
|
||||
typedef vector<NetScope*> scope_vec_t;
|
||||
map<perm_string, scope_vec_t>instance_arrays;
|
||||
|
||||
/* Loop generate uses this as scratch space during
|
||||
@@ -811,7 +855,8 @@ class NetScope : public Attrib {
|
||||
NetNet::Type default_nettype_;
|
||||
|
||||
NetEvent *events_;
|
||||
NetNet *signals_;
|
||||
typedef std::map<perm_string,NetNet*>::const_iterator signals_map_iter_t;
|
||||
std::map <perm_string,NetNet*> signals_map_;
|
||||
perm_string module_name_;
|
||||
union {
|
||||
NetTaskDef*task_;
|
||||
@@ -823,11 +868,12 @@ class NetScope : public Attrib {
|
||||
NetScope*sub_;
|
||||
|
||||
unsigned lcounter_;
|
||||
bool is_auto_;
|
||||
};
|
||||
|
||||
/*
|
||||
* This class implements the LPM_ABS component. The node has a single
|
||||
* input, a signe expression, that it converts to the absolute
|
||||
* input, a signed expression, that it converts to the absolute
|
||||
* value. The gate is simple: pin(0) is the output and pin(1) is the input.
|
||||
*/
|
||||
class NetAbs : public NetNode {
|
||||
@@ -861,13 +907,7 @@ class NetAddSub : public NetNode {
|
||||
// operands and results).
|
||||
unsigned width() const;
|
||||
|
||||
Link& pin_Aclr();
|
||||
Link& pin_Add_Sub();
|
||||
Link& pin_Clock();
|
||||
Link& pin_Cin();
|
||||
Link& pin_Cout();
|
||||
Link& pin_Overflow();
|
||||
|
||||
Link& pin_DataA();
|
||||
Link& pin_DataB();
|
||||
Link& pin_Result();
|
||||
@@ -916,6 +956,44 @@ class NetArrayDq : public NetNode {
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
* Convert an IVL_VT_REAL input to a logical value with the
|
||||
* given width. The input is pin(1) and the output is pin(0).
|
||||
*/
|
||||
class NetCastInt : public NetNode {
|
||||
|
||||
public:
|
||||
NetCastInt(NetScope*s, perm_string n, unsigned width);
|
||||
|
||||
unsigned width() const { return width_; }
|
||||
|
||||
virtual void dump_node(ostream&, unsigned ind) const;
|
||||
virtual bool emit_node(struct target_t*) const;
|
||||
|
||||
private:
|
||||
unsigned width_;
|
||||
};
|
||||
|
||||
/*
|
||||
* Convert an input to IVL_VT_REAL. The input is pin(1), which can be
|
||||
* any vector type (VT_BOOL or VT_LOGIC) and the output is pin(0),
|
||||
* which is IVL_VT_REAL. The conversion interprets the input as an
|
||||
* unsigned value unless the signed_flag is true.
|
||||
*/
|
||||
class NetCastReal : public NetNode {
|
||||
|
||||
public:
|
||||
NetCastReal(NetScope*s, perm_string n, bool signed_flag);
|
||||
|
||||
bool signed_flag() const { return signed_flag_; }
|
||||
|
||||
virtual void dump_node(ostream&, unsigned ind) const;
|
||||
virtual bool emit_node(struct target_t*) const;
|
||||
|
||||
private:
|
||||
bool signed_flag_;
|
||||
};
|
||||
|
||||
/*
|
||||
* This type represents the LPM_CLSHIFT device.
|
||||
*/
|
||||
@@ -957,6 +1035,9 @@ class NetCLShift : public NetNode {
|
||||
* inputs is narrower then the other, it is up to the generator to
|
||||
* make sure all the data pins are properly driven.
|
||||
*
|
||||
* The signed() property is true if the comparison is to be done to
|
||||
* signed arguments. The result is always UNsigned.
|
||||
*
|
||||
* NOTE: This is not the same as the device used to support case
|
||||
* compare. Case comparisons handle Vx and Vz values, whereas this
|
||||
* device need not.
|
||||
@@ -972,8 +1053,6 @@ class NetCompare : public NetNode {
|
||||
bool get_signed() const;
|
||||
void set_signed(bool);
|
||||
|
||||
Link& pin_Aclr();
|
||||
Link& pin_Clock();
|
||||
Link& pin_AGB();
|
||||
Link& pin_AGEB();
|
||||
Link& pin_AEB();
|
||||
@@ -984,8 +1063,6 @@ class NetCompare : public NetNode {
|
||||
Link& pin_DataA();
|
||||
Link& pin_DataB();
|
||||
|
||||
const Link& pin_Aclr() const;
|
||||
const Link& pin_Clock() const;
|
||||
const Link& pin_AGB() const;
|
||||
const Link& pin_AGEB() const;
|
||||
const Link& pin_AEB() const;
|
||||
@@ -1100,6 +1177,9 @@ class NetModulo : public NetNode {
|
||||
unsigned width_a() const;
|
||||
unsigned width_b() const;
|
||||
|
||||
void set_signed(bool);
|
||||
bool get_signed() const;
|
||||
|
||||
Link& pin_DataA();
|
||||
Link& pin_DataB();
|
||||
Link& pin_Result();
|
||||
@@ -1116,6 +1196,8 @@ class NetModulo : public NetNode {
|
||||
unsigned width_r_;
|
||||
unsigned width_a_;
|
||||
unsigned width_b_;
|
||||
|
||||
bool signed_flag_;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -1379,7 +1461,7 @@ class NetSysFunc : public NetNode {
|
||||
class NetTran : public NetNode, public IslandBranch {
|
||||
|
||||
public:
|
||||
// Tran devices other then TRAN_VP
|
||||
// Tran devices other than TRAN_VP
|
||||
NetTran(NetScope*scope, perm_string n, ivl_switch_type_t type);
|
||||
// Create a TRAN_VP
|
||||
NetTran(NetScope*scope, perm_string n, unsigned wid,
|
||||
@@ -1485,12 +1567,20 @@ class NetExpr : public LineInfo {
|
||||
virtual NexusSet* nex_input(bool rem_out = true) =0;
|
||||
|
||||
// Return a version of myself that is structural. This is used
|
||||
// for converting expressions to gates.
|
||||
virtual NetNet*synthesize(Design*);
|
||||
// for converting expressions to gates. The arguments are:
|
||||
//
|
||||
// des, scope: The context where this work is done
|
||||
//
|
||||
// rise/fall/decay: Attach these delays to the driver for the
|
||||
// expression output.
|
||||
//
|
||||
// drive0/drive1: Attach these strengths tp the driver for
|
||||
// the expression output.
|
||||
virtual NetNet*synthesize(Design*des, NetScope*scope);
|
||||
|
||||
|
||||
protected:
|
||||
void expr_width(unsigned w) { width_ = w; }
|
||||
void expr_width(unsigned w);
|
||||
void cast_signed_base_(bool flag) {signed_flag_ = flag; }
|
||||
|
||||
private:
|
||||
@@ -1524,7 +1614,7 @@ class NetEConst : public NetExpr {
|
||||
virtual void dump(ostream&) const;
|
||||
|
||||
virtual NetEConst* dup_expr() const;
|
||||
virtual NetNet*synthesize(Design*);
|
||||
virtual NetNet*synthesize(Design*, NetScope*scope);
|
||||
virtual NexusSet* nex_input(bool rem_out = true);
|
||||
|
||||
private:
|
||||
@@ -1541,7 +1631,7 @@ class NetEConstParam : public NetEConst {
|
||||
perm_string name() const;
|
||||
const NetScope*scope() const;
|
||||
|
||||
virtual bool set_width(unsigned w, bool last_chance);
|
||||
virtual bool set_width(unsigned w, bool last_chance =false);
|
||||
virtual void expr_scan(struct expr_scan_t*) const;
|
||||
virtual void dump(ostream&) const;
|
||||
|
||||
@@ -1577,7 +1667,7 @@ class NetECReal : public NetExpr {
|
||||
virtual void dump(ostream&) const;
|
||||
|
||||
virtual NetECReal* dup_expr() const;
|
||||
virtual NetNet*synthesize(Design*);
|
||||
virtual NetNet*synthesize(Design*, NetScope*scope);
|
||||
virtual NexusSet* nex_input(bool rem_out = true);
|
||||
|
||||
private:
|
||||
@@ -1995,6 +2085,23 @@ class NetProc : public virtual LineInfo {
|
||||
NetProc& operator= (const NetProc&);
|
||||
};
|
||||
|
||||
class NetAlloc : public NetProc {
|
||||
|
||||
public:
|
||||
NetAlloc(NetScope*);
|
||||
~NetAlloc();
|
||||
|
||||
const string name() const;
|
||||
|
||||
const NetScope* scope() const;
|
||||
|
||||
virtual bool emit_proc(struct target_t*) const;
|
||||
virtual void dump(ostream&, unsigned ind) const;
|
||||
|
||||
private:
|
||||
NetScope*scope_;
|
||||
};
|
||||
|
||||
/*
|
||||
* Procedural assignment is broken into a suite of classes. These
|
||||
* classes represent the various aspects of the assignment statement
|
||||
@@ -2048,6 +2155,7 @@ class NetAssign_ {
|
||||
// method accounts for the presence of the mux, so it is not
|
||||
// necessarily the same as the pin_count().
|
||||
unsigned lwidth() const;
|
||||
ivl_variable_type_t expr_type() const;
|
||||
|
||||
// Get the name of the underlying object.
|
||||
perm_string name() const;
|
||||
@@ -2139,7 +2247,8 @@ class NetAssign : public NetAssignBase {
|
||||
|
||||
class NetAssignNB : public NetAssignBase {
|
||||
public:
|
||||
explicit NetAssignNB(NetAssign_*lv, NetExpr*rv);
|
||||
explicit NetAssignNB(NetAssign_*lv, NetExpr*rv, NetEvWait*ev,
|
||||
NetExpr*cnt);
|
||||
~NetAssignNB();
|
||||
|
||||
|
||||
@@ -2147,7 +2256,13 @@ class NetAssignNB : public NetAssignBase {
|
||||
virtual int match_proc(struct proc_match_t*);
|
||||
virtual void dump(ostream&, unsigned ind) const;
|
||||
|
||||
unsigned nevents() const;
|
||||
const NetEvent*event(unsigned) const;
|
||||
const NetExpr* get_count() const;
|
||||
|
||||
private:
|
||||
NetEvWait*event_;
|
||||
NetExpr*count_;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -2319,6 +2434,24 @@ class NetCondit : public NetProc {
|
||||
NetProc*else_;
|
||||
};
|
||||
|
||||
/*
|
||||
* This represents the analog contribution statement. The l-val is a
|
||||
* branch expression, and the r-value is an arbitrary expression that
|
||||
* may include branches and real values.
|
||||
*/
|
||||
class NetContribution : public NetProc {
|
||||
|
||||
public:
|
||||
explicit NetContribution(NetExpr*lval, NetExpr*rval);
|
||||
~NetContribution();
|
||||
|
||||
virtual void dump(ostream&, unsigned ind) const;
|
||||
|
||||
private:
|
||||
NetExpr*lval_;
|
||||
NetExpr*rval_;
|
||||
};
|
||||
|
||||
/*
|
||||
* The procedural deassign statement (the opposite of assign) releases
|
||||
* any assign expressions attached to the bits of the reg. The
|
||||
@@ -2529,6 +2662,8 @@ class NetEvWait : public NetProc {
|
||||
const svector<NetEvProbe*>&events);
|
||||
|
||||
virtual void dump(ostream&, unsigned ind) const;
|
||||
// This will ignore any statement.
|
||||
virtual void dump_inline(ostream&) const;
|
||||
virtual DelayType delay_type() const;
|
||||
|
||||
private:
|
||||
@@ -2538,6 +2673,8 @@ class NetEvWait : public NetProc {
|
||||
NetEvent**events_;
|
||||
};
|
||||
|
||||
ostream& operator << (ostream&out, const NetEvWait&obj);
|
||||
|
||||
class NetEvProbe : public NetNode {
|
||||
|
||||
friend class NetEvent;
|
||||
@@ -2603,6 +2740,23 @@ class NetForever : public NetProc {
|
||||
NetProc*statement_;
|
||||
};
|
||||
|
||||
class NetFree : public NetProc {
|
||||
|
||||
public:
|
||||
NetFree(NetScope*);
|
||||
~NetFree();
|
||||
|
||||
const string name() const;
|
||||
|
||||
const NetScope* scope() const;
|
||||
|
||||
virtual bool emit_proc(struct target_t*) const;
|
||||
virtual void dump(ostream&, unsigned ind) const;
|
||||
|
||||
private:
|
||||
NetScope*scope_;
|
||||
};
|
||||
|
||||
/*
|
||||
* A function definition is elaborated just like a task, though by now
|
||||
* it is certain that the first parameter (a phantom parameter) is the
|
||||
@@ -2814,7 +2968,7 @@ class NetEUFunc : public NetExpr {
|
||||
virtual void expr_scan(struct expr_scan_t*) const;
|
||||
virtual NetEUFunc*dup_expr() const;
|
||||
virtual NexusSet* nex_input(bool rem_out = true);
|
||||
virtual NetNet* synthesize(Design*des);
|
||||
virtual NetNet* synthesize(Design*des, NetScope*scope);
|
||||
|
||||
private:
|
||||
NetScope*scope_;
|
||||
@@ -2827,6 +2981,27 @@ class NetEUFunc : public NetExpr {
|
||||
NetEUFunc& operator= (const NetEUFunc&);
|
||||
};
|
||||
|
||||
/*
|
||||
* A call to a nature access function for a branch.
|
||||
*/
|
||||
class NetEAccess : public NetExpr {
|
||||
|
||||
public:
|
||||
explicit NetEAccess(NetBranch*br, nature_t*nat);
|
||||
~NetEAccess();
|
||||
|
||||
virtual ivl_variable_type_t expr_type() const;
|
||||
virtual void dump(ostream&) const;
|
||||
|
||||
virtual void expr_scan(struct expr_scan_t*) const;
|
||||
virtual NetEAccess*dup_expr() const;
|
||||
virtual NexusSet* nex_input(bool rem_out = true);
|
||||
|
||||
private:
|
||||
NetBranch*branch_;
|
||||
nature_t*nature_;
|
||||
};
|
||||
|
||||
/*
|
||||
* A call to a user defined task is elaborated into this object. This
|
||||
* contains a pointer to the elaborated task definition, but is a
|
||||
@@ -2887,12 +3062,10 @@ class NetWhile : public NetProc {
|
||||
class NetProcTop : public LineInfo, public Attrib {
|
||||
|
||||
public:
|
||||
enum Type { KINITIAL, KALWAYS };
|
||||
|
||||
NetProcTop(NetScope*s, Type t, class NetProc*st);
|
||||
NetProcTop(NetScope*s, ivl_process_type_t t, class NetProc*st);
|
||||
~NetProcTop();
|
||||
|
||||
Type type() const { return type_; }
|
||||
ivl_process_type_t type() const { return type_; }
|
||||
NetProc*statement();
|
||||
const NetProc*statement() const;
|
||||
|
||||
@@ -2917,7 +3090,7 @@ class NetProcTop : public LineInfo, public Attrib {
|
||||
bool emit(struct target_t*tgt) const;
|
||||
|
||||
private:
|
||||
const Type type_;
|
||||
const ivl_process_type_t type_;
|
||||
NetProc*const statement_;
|
||||
|
||||
NetScope*scope_;
|
||||
@@ -2925,6 +3098,32 @@ class NetProcTop : public LineInfo, public Attrib {
|
||||
NetProcTop*next_;
|
||||
};
|
||||
|
||||
class NetAnalogTop : public LineInfo, public Attrib {
|
||||
|
||||
public:
|
||||
NetAnalogTop(NetScope*scope, ivl_process_type_t t, NetProc*st);
|
||||
~NetAnalogTop();
|
||||
|
||||
ivl_process_type_t type() const { return type_; }
|
||||
|
||||
NetProc*statement();
|
||||
const NetProc*statement() const;
|
||||
|
||||
NetScope*scope();
|
||||
const NetScope*scope() const;
|
||||
|
||||
void dump(ostream&, unsigned ind) const;
|
||||
bool emit(struct target_t*tgt) const;
|
||||
|
||||
private:
|
||||
const ivl_process_type_t type_;
|
||||
NetProc* statement_;
|
||||
|
||||
NetScope*scope_;
|
||||
friend class Design;
|
||||
NetAnalogTop*next_;
|
||||
};
|
||||
|
||||
/*
|
||||
* This class represents a binary operator, with the left and right
|
||||
* operands and a single character for the operator. The operator
|
||||
@@ -3008,7 +3207,7 @@ class NetEBAdd : public NetEBinary {
|
||||
virtual bool set_width(unsigned w, bool last_chance);
|
||||
virtual NetEBAdd* dup_expr() const;
|
||||
virtual NetExpr* eval_tree(int prune_to_width = -1);
|
||||
virtual NetNet* synthesize(Design*);
|
||||
virtual NetNet* synthesize(Design*, NetScope*scope);
|
||||
|
||||
private:
|
||||
NetECReal* eval_tree_real_();
|
||||
@@ -3030,7 +3229,7 @@ class NetEBDiv : public NetEBinary {
|
||||
virtual bool set_width(unsigned w, bool last_chance);
|
||||
virtual NetEBDiv* dup_expr() const;
|
||||
virtual NetExpr* eval_tree(int prune_to_width = -1);
|
||||
virtual NetNet* synthesize(Design*);
|
||||
virtual NetNet* synthesize(Design*, NetScope*scope);
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -3057,7 +3256,7 @@ class NetEBBits : public NetEBinary {
|
||||
virtual NetEBBits* dup_expr() const;
|
||||
virtual NetEConst* eval_tree(int prune_to_width = -1);
|
||||
|
||||
virtual NetNet* synthesize(Design*);
|
||||
virtual NetNet* synthesize(Design*, NetScope*scope);
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -3080,7 +3279,7 @@ class NetEBComp : public NetEBinary {
|
||||
NetEBComp(char op, NetExpr*l, NetExpr*r);
|
||||
~NetEBComp();
|
||||
|
||||
virtual bool set_width(unsigned w, bool last_chance);
|
||||
virtual bool set_width(unsigned w, bool last_chance =false);
|
||||
|
||||
/* A compare expression has a definite width. */
|
||||
virtual bool has_width() const;
|
||||
@@ -3088,12 +3287,13 @@ class NetEBComp : public NetEBinary {
|
||||
virtual NetEBComp* dup_expr() const;
|
||||
virtual NetEConst* eval_tree(int prune_to_width = -1);
|
||||
|
||||
virtual NetNet* synthesize(Design*);
|
||||
virtual NetNet* synthesize(Design*, NetScope*scope);
|
||||
|
||||
private:
|
||||
NetEConst* must_be_leeq_(NetExpr*le, const verinum&rv, bool eq_flag);
|
||||
|
||||
NetEConst*eval_eqeq_(bool ne_flag);
|
||||
NetEConst*eval_eqeq_real_(NetExpr*le, NetExpr*ri, bool ne_flag);
|
||||
NetEConst*eval_less_();
|
||||
NetEConst*eval_leeq_();
|
||||
NetEConst*eval_leeq_real_(NetExpr*le, NetExpr*ri, bool eq_flag);
|
||||
@@ -3116,10 +3316,10 @@ class NetEBLogic : public NetEBinary {
|
||||
NetEBLogic(char op, NetExpr*l, NetExpr*r);
|
||||
~NetEBLogic();
|
||||
|
||||
virtual bool set_width(unsigned w, bool last_chance);
|
||||
virtual bool set_width(unsigned w, bool last_chance =false);
|
||||
virtual NetEBLogic* dup_expr() const;
|
||||
virtual NetEConst* eval_tree(int prune_to_width = -1);
|
||||
virtual NetNet* synthesize(Design*);
|
||||
virtual NetNet* synthesize(Design*, NetScope*scope);
|
||||
|
||||
private:
|
||||
};
|
||||
@@ -3157,7 +3357,7 @@ class NetEBMult : public NetEBinary {
|
||||
virtual bool set_width(unsigned w, bool last_chance);
|
||||
virtual NetEBMult* dup_expr() const;
|
||||
virtual NetExpr* eval_tree(int prune_to_width = -1);
|
||||
virtual NetNet* synthesize(Design*);
|
||||
virtual NetNet* synthesize(Design*, NetScope*scope);
|
||||
|
||||
private:
|
||||
|
||||
@@ -3179,7 +3379,7 @@ class NetEBPow : public NetEBinary {
|
||||
virtual bool set_width(unsigned w, bool last_chance);
|
||||
virtual NetEBPow* dup_expr() const;
|
||||
virtual NetExpr* eval_tree(int prune_to_width = -1);
|
||||
virtual NetNet* synthesize(Design*);
|
||||
virtual NetNet* synthesize(Design*, NetScope*scope);
|
||||
|
||||
private:
|
||||
|
||||
@@ -3211,7 +3411,7 @@ class NetEBShift : public NetEBinary {
|
||||
virtual NetEBShift* dup_expr() const;
|
||||
virtual NetEConst* eval_tree(int prune_to_width = -1);
|
||||
|
||||
virtual NetNet* synthesize(Design*);
|
||||
virtual NetNet* synthesize(Design*, NetScope*scope);
|
||||
|
||||
private:
|
||||
};
|
||||
@@ -3245,7 +3445,7 @@ class NetEConcat : public NetExpr {
|
||||
virtual bool set_width(unsigned w, bool last_chance =false);
|
||||
virtual NetEConcat* dup_expr() const;
|
||||
virtual NetEConst* eval_tree(int prune_to_width = -1);
|
||||
virtual NetNet*synthesize(Design*);
|
||||
virtual NetNet*synthesize(Design*, NetScope*scope);
|
||||
virtual void expr_scan(struct expr_scan_t*) const;
|
||||
virtual void dump(ostream&) const;
|
||||
|
||||
@@ -3321,7 +3521,7 @@ class NetESelect : public NetExpr {
|
||||
virtual void expr_scan(struct expr_scan_t*) const;
|
||||
virtual NetEConst* eval_tree(int prune_to_width = -1);
|
||||
virtual NetESelect* dup_expr() const;
|
||||
virtual NetNet*synthesize(Design*des);
|
||||
virtual NetNet*synthesize(Design*des, NetScope*scope);
|
||||
virtual void dump(ostream&) const;
|
||||
|
||||
private:
|
||||
@@ -3392,6 +3592,8 @@ class NetESFunc : public NetExpr {
|
||||
NetExpr* parm(unsigned idx);
|
||||
const NetExpr* parm(unsigned idx) const;
|
||||
|
||||
virtual NetExpr* eval_tree(int prune_to_width = -1);
|
||||
|
||||
virtual ivl_variable_type_t expr_type() const;
|
||||
virtual NexusSet* nex_input(bool rem_out = true);
|
||||
virtual bool set_width(unsigned, bool last_chance);
|
||||
@@ -3399,7 +3601,7 @@ class NetESFunc : public NetExpr {
|
||||
|
||||
virtual void expr_scan(struct expr_scan_t*) const;
|
||||
virtual NetESFunc*dup_expr() const;
|
||||
virtual NetNet*synthesize(Design*);
|
||||
virtual NetNet*synthesize(Design*, NetScope*scope);
|
||||
|
||||
private:
|
||||
const char* name_;
|
||||
@@ -3436,7 +3638,10 @@ class NetETernary : public NetExpr {
|
||||
virtual NexusSet* nex_input(bool rem_out = true);
|
||||
virtual void expr_scan(struct expr_scan_t*) const;
|
||||
virtual void dump(ostream&) const;
|
||||
virtual NetNet*synthesize(Design*);
|
||||
virtual NetNet*synthesize(Design*, NetScope*scope);
|
||||
|
||||
public:
|
||||
static bool test_operand_compat(ivl_variable_type_t tru, ivl_variable_type_t fal);
|
||||
|
||||
private:
|
||||
NetExpr*cond_;
|
||||
@@ -3473,6 +3678,7 @@ class NetEUnary : public NetExpr {
|
||||
|
||||
virtual NetEUnary* dup_expr() const;
|
||||
virtual NetExpr* eval_tree(int prune_to_width = -1);
|
||||
virtual NetNet* synthesize(Design*, NetScope*scope);
|
||||
|
||||
virtual ivl_variable_type_t expr_type() const;
|
||||
virtual NexusSet* nex_input(bool rem_out = true);
|
||||
@@ -3493,8 +3699,9 @@ class NetEUBits : public NetEUnary {
|
||||
NetEUBits(char op, NetExpr*ex);
|
||||
~NetEUBits();
|
||||
|
||||
virtual NetNet* synthesize(Design*);
|
||||
virtual NetNet* synthesize(Design*, NetScope*scope);
|
||||
|
||||
virtual NetEUBits* dup_expr() const;
|
||||
virtual NetExpr* eval_tree(int prune_to_width = -1);
|
||||
virtual ivl_variable_type_t expr_type() const;
|
||||
};
|
||||
@@ -3506,7 +3713,7 @@ class NetEUReduce : public NetEUnary {
|
||||
~NetEUReduce();
|
||||
|
||||
virtual bool set_width(unsigned w, bool last_chance);
|
||||
virtual NetNet* synthesize(Design*);
|
||||
virtual NetNet* synthesize(Design*, NetScope*scope);
|
||||
virtual NetEUReduce* dup_expr() const;
|
||||
virtual NetEConst* eval_tree(int prune_to_width = -1);
|
||||
virtual ivl_variable_type_t expr_type() const;
|
||||
@@ -3533,7 +3740,7 @@ class NetESignal : public NetExpr {
|
||||
virtual bool set_width(unsigned, bool last_chance);
|
||||
|
||||
virtual NetESignal* dup_expr() const;
|
||||
NetNet* synthesize(Design*des);
|
||||
NetNet* synthesize(Design*des, NetScope*scope);
|
||||
NexusSet* nex_input(bool rem_out = true);
|
||||
|
||||
// This is the expression for selecting an array word, if this
|
||||
@@ -3560,6 +3767,18 @@ class NetESignal : public NetExpr {
|
||||
NetExpr*word_;
|
||||
};
|
||||
|
||||
/*
|
||||
* The Design object keeps a list of work items for processing
|
||||
* elaboration. This is the type of those work items.
|
||||
*/
|
||||
struct elaborator_work_item_t {
|
||||
explicit elaborator_work_item_t(Design*d)
|
||||
: des(d) { }
|
||||
virtual ~elaborator_work_item_t() { }
|
||||
virtual void elaborate_runrun() =0;
|
||||
protected:
|
||||
Design*des;
|
||||
};
|
||||
|
||||
/*
|
||||
* This class contains an entire design. It includes processes and a
|
||||
@@ -3609,10 +3828,23 @@ class Design {
|
||||
NetScope* find_scope(NetScope*, const std::list<hname_t>&path,
|
||||
NetScope::TYPE type = NetScope::MODULE) const;
|
||||
|
||||
/* These members help manage elaboration of scopes. When we
|
||||
get to a point in scope elaboration where we want to put
|
||||
off a scope elaboration, an object of scope_elaboration_t
|
||||
is pushed onto the scope_elaborations list. The scope
|
||||
elaborator will go through this list elaborating scopes
|
||||
until the list is empty. */
|
||||
list<elaborator_work_item_t*>elaboration_work_list;
|
||||
void run_elaboration_work(void);
|
||||
|
||||
set<NetScope*> defparams_later;
|
||||
|
||||
// PARAMETERS
|
||||
|
||||
void run_defparams();
|
||||
void evaluate_parameters();
|
||||
// Look for defparams that never matched, and print warnings.
|
||||
void residual_defparams();
|
||||
|
||||
/* This method locates a signal, starting at a given
|
||||
scope. The name parameter may be partially hierarchical, so
|
||||
@@ -3633,7 +3865,9 @@ class Design {
|
||||
|
||||
// PROCESSES
|
||||
void add_process(NetProcTop*);
|
||||
void add_process(NetAnalogTop*);
|
||||
void delete_process(NetProcTop*);
|
||||
bool check_always_delay() const;
|
||||
|
||||
// Iterate over the design...
|
||||
void dump(ostream&) const;
|
||||
@@ -3663,6 +3897,8 @@ class Design {
|
||||
NetProcTop*procs_;
|
||||
NetProcTop*procs_idx_;
|
||||
|
||||
NetAnalogTop*aprocs_;
|
||||
|
||||
map<string,const char*> flags_;
|
||||
|
||||
int des_precision_;
|
||||
|
||||
+170
-39
@@ -76,6 +76,86 @@ NetNet* add_to_net(Design*des, NetNet*sig, long val)
|
||||
#endif
|
||||
}
|
||||
|
||||
NetNet* sub_net_from(Design*des, NetScope*scope, long val, NetNet*sig)
|
||||
{
|
||||
NetNet*zero_net = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, sig->vector_width());
|
||||
zero_net->data_type(sig->data_type());
|
||||
zero_net->local_flag(true);
|
||||
|
||||
if (sig->data_type() == IVL_VT_REAL) {
|
||||
verireal zero (val);
|
||||
NetLiteral*zero_obj = new NetLiteral(scope, scope->local_symbol(), zero);
|
||||
des->add_node(zero_obj);
|
||||
|
||||
connect(zero_net->pin(0), zero_obj->pin(0));
|
||||
|
||||
} else {
|
||||
verinum zero ((int64_t)val);
|
||||
zero = pad_to_width(zero, sig->vector_width());
|
||||
NetConst*zero_obj = new NetConst(scope, scope->local_symbol(), zero);
|
||||
des->add_node(zero_obj);
|
||||
|
||||
connect(zero_net->pin(0), zero_obj->pin(0));
|
||||
}
|
||||
|
||||
NetAddSub*adder = new NetAddSub(scope, scope->local_symbol(), sig->vector_width());
|
||||
des->add_node(adder);
|
||||
adder->attribute(perm_string::literal("LPM_Direction"), verinum("SUB"));
|
||||
|
||||
connect(zero_net->pin(0), adder->pin_DataA());
|
||||
connect(adder->pin_DataB(), sig->pin(0));
|
||||
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, sig->vector_width());
|
||||
tmp->data_type(sig->data_type());
|
||||
tmp->local_flag(true);
|
||||
|
||||
connect(adder->pin_Result(), tmp->pin(0));
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetNet* cast_to_int(Design*des, NetScope*scope, NetNet*src, unsigned wid)
|
||||
{
|
||||
if (src->data_type() != IVL_VT_REAL)
|
||||
return src;
|
||||
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(), NetNet::WIRE, wid);
|
||||
tmp->data_type(IVL_VT_LOGIC);
|
||||
tmp->set_line(*src);
|
||||
tmp->local_flag(true);
|
||||
|
||||
NetCastInt*cast = new NetCastInt(scope, scope->local_symbol(), wid);
|
||||
cast->set_line(*src);
|
||||
des->add_node(cast);
|
||||
|
||||
connect(cast->pin(0), tmp->pin(0));
|
||||
connect(cast->pin(1), src->pin(0));
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetNet* cast_to_real(Design*des, NetScope*scope, NetNet*src)
|
||||
{
|
||||
if (src->data_type() == IVL_VT_REAL)
|
||||
return src;
|
||||
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(), NetNet::WIRE);
|
||||
tmp->data_type(IVL_VT_REAL);
|
||||
tmp->set_line(*src);
|
||||
tmp->local_flag(true);
|
||||
|
||||
NetCastReal*cast = new NetCastReal(scope, scope->local_symbol(), src->get_signed());
|
||||
cast->set_line(*src);
|
||||
des->add_node(cast);
|
||||
|
||||
connect(cast->pin(0), tmp->pin(0));
|
||||
connect(cast->pin(1), src->pin(0));
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a signed constant to an existing expression. Generate a new
|
||||
* NetEBAdd node that has the input expression and an expression made
|
||||
@@ -130,6 +210,27 @@ NetEConst* make_const_x(unsigned long wid)
|
||||
return resx;
|
||||
}
|
||||
|
||||
NetEConst* make_const_0(unsigned long wid)
|
||||
{
|
||||
verinum xxx (verinum::V0, wid);
|
||||
NetEConst*resx = new NetEConst(xxx);
|
||||
return resx;
|
||||
}
|
||||
|
||||
NetNet* make_const_x(Design*des, NetScope*scope, unsigned long wid)
|
||||
{
|
||||
verinum xxx (verinum::Vx, wid);
|
||||
NetConst*res = new NetConst(scope, scope->local_symbol(), xxx);
|
||||
des->add_node(res);
|
||||
|
||||
NetNet*sig = new NetNet(scope, scope->local_symbol(), NetNet::WIRE, wid);
|
||||
sig->local_flag(true);
|
||||
sig->data_type(IVL_VT_LOGIC);
|
||||
|
||||
connect(sig->pin(0), res->pin(0));
|
||||
return sig;
|
||||
}
|
||||
|
||||
NetExpr* condition_reduce(NetExpr*expr)
|
||||
{
|
||||
if (expr->expr_width() == 1)
|
||||
@@ -204,6 +305,57 @@ bool eval_as_double(double&value, NetExpr*expr)
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* At the parser level, a name component is a name with a collection
|
||||
* of expressions. For example foo[N] is the name "foo" and the index
|
||||
* expression "N". This function takes as input the name component and
|
||||
* returns the path component name. It will evaluate the index
|
||||
* expression if it is present.
|
||||
*/
|
||||
hname_t eval_path_component(Design*des, NetScope*scope,
|
||||
const name_component_t&comp)
|
||||
{
|
||||
// No index expression, so the path component is an undecorated
|
||||
// name, for example "foo".
|
||||
if (comp.index.empty())
|
||||
return hname_t(comp.name);
|
||||
|
||||
// The parser will assure that path components will have only
|
||||
// one index. For example, foo[N] is one index, foo[n][m] is two.
|
||||
assert(comp.index.size() == 1);
|
||||
|
||||
const index_component_t&index = comp.index.front();
|
||||
|
||||
// The parser will assure that path components will have only
|
||||
// bit select index expressions. For example, "foo[n]" is OK,
|
||||
// but "foo[n:m]" is not.
|
||||
assert(index.sel == index_component_t::SEL_BIT);
|
||||
|
||||
// Evaluate the bit select to get a number.
|
||||
NetExpr*tmp = elab_and_eval(des, scope, index.msb, -1);
|
||||
ivl_assert(*index.msb, tmp);
|
||||
|
||||
// Now we should have a constant value for the bit select
|
||||
// expression, and we can use it to make the final hname_t
|
||||
// value, for example "foo[5]".
|
||||
if (NetEConst*ctmp = dynamic_cast<NetEConst*>(tmp)) {
|
||||
hname_t res(comp.name, ctmp->value().as_long());
|
||||
delete ctmp;
|
||||
return res;
|
||||
}
|
||||
|
||||
// Darn, the expression doesn't evaluate to a constant. That's
|
||||
// an error to be reported. And make up a fake index value to
|
||||
// return to the caller.
|
||||
cerr << index.msb->get_fileline() << ": error: "
|
||||
<< "Scope index expression is not constant: "
|
||||
<< *index.msb << endl;
|
||||
des->errors += 1;
|
||||
|
||||
delete tmp;
|
||||
return hname_t (comp.name, 0);
|
||||
}
|
||||
|
||||
std::list<hname_t> eval_scope_path(Design*des, NetScope*scope,
|
||||
const pform_name_t&path)
|
||||
{
|
||||
@@ -213,30 +365,7 @@ std::list<hname_t> eval_scope_path(Design*des, NetScope*scope,
|
||||
|
||||
for (pform_path_it cur = path.begin() ; cur != path.end(); cur++) {
|
||||
const name_component_t&comp = *cur;
|
||||
if (comp.index.empty()) {
|
||||
res.push_back(hname_t(comp.name));
|
||||
continue;
|
||||
}
|
||||
|
||||
assert(comp.index.size() == 1);
|
||||
const index_component_t&index = comp.index.front();
|
||||
assert(index.sel == index_component_t::SEL_BIT);
|
||||
|
||||
NetExpr*tmp = elab_and_eval(des, scope, index.msb, -1);
|
||||
ivl_assert(*index.msb, tmp);
|
||||
|
||||
if (NetEConst*ctmp = dynamic_cast<NetEConst*>(tmp)) {
|
||||
res.push_back(hname_t(comp.name, ctmp->value().as_long()));
|
||||
delete ctmp;
|
||||
continue;
|
||||
} else {
|
||||
cerr << index.msb->get_fileline() << ": error: "
|
||||
<< "Scope index expression is not constant: "
|
||||
<< *index.msb << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
return res;
|
||||
res.push_back( eval_path_component(des,scope,comp) );
|
||||
}
|
||||
|
||||
return res;
|
||||
@@ -249,26 +378,28 @@ const char *human_readable_op(const char op)
|
||||
{
|
||||
const char *type;
|
||||
switch (op) {
|
||||
case '~': type = "~"; break; // Negation
|
||||
case '~': type = "~"; break; // Negation
|
||||
|
||||
case '^': type = "^"; break; // XOR
|
||||
case 'X': type = "~^"; break; // XNOR
|
||||
case '&': type = "&"; break; // Bitwise AND
|
||||
case 'A': type = "~&"; break; // NAND (~&)
|
||||
case '|': type = "|"; break; // Bitwise OR
|
||||
case 'O': type = "~|"; break; // NOR
|
||||
case '^': type = "^"; break; // XOR
|
||||
case 'X': type = "~^"; break; // XNOR
|
||||
case '&': type = "&"; break; // Bitwise AND
|
||||
case 'A': type = "~&"; break; // NAND (~&)
|
||||
case '|': type = "|"; break; // Bitwise OR
|
||||
case 'O': type = "~|"; break; // NOR
|
||||
|
||||
case 'a': type = "&&"; break; // Logical AND
|
||||
case 'o': type = "||"; break; // Logical OR
|
||||
case '!': type = "!"; break; // Logical NOT
|
||||
case 'a': type = "&&"; break; // Logical AND
|
||||
case 'o': type = "||"; break; // Logical OR
|
||||
|
||||
case 'E': type = "==="; break; // Case equality
|
||||
case 'N': type = "!=="; break; // Case inequality
|
||||
case 'E': type = "==="; break; // Case equality
|
||||
case 'N': type = "!=="; break; // Case inequality
|
||||
|
||||
case 'l': type = "<<(<)"; break; // Left shifts
|
||||
case 'r': type = ">>"; break; // Logical right shift
|
||||
case 'R': type = ">>>"; break; // Arithmetic right shift
|
||||
case 'l': type = "<<(<)"; break; // Left shifts
|
||||
case 'r': type = ">>"; break; // Logical right shift
|
||||
case 'R': type = ">>>"; break; // Arithmetic right shift
|
||||
|
||||
default: assert(0);
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
@@ -36,21 +36,25 @@
|
||||
* ex2 is the lsb expression for the range. If there is no range, then
|
||||
* these values are set to 0.
|
||||
*/
|
||||
extern NetScope* symbol_search(Design*des,
|
||||
NetScope*start, pform_name_t path,
|
||||
extern NetScope* symbol_search(const LineInfo*li,
|
||||
Design*des,
|
||||
NetScope*start,
|
||||
pform_name_t path,
|
||||
NetNet*&net, /* net/reg */
|
||||
const NetExpr*&par,/* parameter */
|
||||
NetEvent*&eve, /* named event */
|
||||
const NetExpr*&ex1, const NetExpr*&ex2);
|
||||
|
||||
inline NetScope* symbol_search(Design*des,
|
||||
NetScope*start, const pform_name_t&path,
|
||||
inline NetScope* symbol_search(const LineInfo*li,
|
||||
Design*des,
|
||||
NetScope*start,
|
||||
const pform_name_t&path,
|
||||
NetNet*&net, /* net/reg */
|
||||
const NetExpr*&par,/* parameter */
|
||||
NetEvent*&eve /* named event */)
|
||||
{
|
||||
const NetExpr*ex1, *ex2;
|
||||
return symbol_search(des, start, path, net, par, eve, ex1, ex2);
|
||||
return symbol_search(li, des, start, path, net, par, eve, ex1, ex2);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -64,6 +68,13 @@ extern NetNet*pad_to_width(Design*des, NetNet*n, unsigned w);
|
||||
|
||||
extern NetNet*pad_to_width_signed(Design*des, NetNet*n, unsigned w);
|
||||
|
||||
/*
|
||||
* Generate the nodes necessary to cast an expression (a net) to a
|
||||
* real value.
|
||||
*/
|
||||
extern NetNet*cast_to_int(Design*des, NetScope*scope, NetNet*src, unsigned wid);
|
||||
extern NetNet*cast_to_real(Design*des, NetScope*scope, NetNet*src);
|
||||
|
||||
/*
|
||||
* Take the input expression and return a variation that assures that
|
||||
* the expression is 1-bit wide and logical. This reflects the needs
|
||||
@@ -84,6 +95,7 @@ extern NetNet*crop_to_width(Design*des, NetNet*n, unsigned w);
|
||||
* return a new NetNet value that is the output of an addition.
|
||||
*/
|
||||
extern NetNet*add_to_net(Design*des, NetNet*sig, long val);
|
||||
extern NetNet*sub_net_from(Design*des, NetScope*scope, long val, NetNet*sig);
|
||||
|
||||
/*
|
||||
* These functions make various sorts of expressions, given operands
|
||||
@@ -106,6 +118,12 @@ extern NetExpr*make_sub_expr(long val, NetExpr*expr);
|
||||
* Make a NetEConst object that contains only X bits.
|
||||
*/
|
||||
extern NetEConst*make_const_x(unsigned long wid);
|
||||
extern NetEConst*make_const_0(unsigned long wid);
|
||||
|
||||
/*
|
||||
* Make A const net
|
||||
*/
|
||||
extern NetNet* make_const_x(Design*des, NetScope*scope, unsigned long wid);
|
||||
|
||||
/*
|
||||
* In some cases the lval is accessible as a pointer to the head of
|
||||
@@ -123,14 +141,27 @@ extern unsigned count_lval_width(const class NetAssign_*first);
|
||||
* The expr_width is the width of the context where the expression is
|
||||
* being elaborated, or -1 if the expression is self-determined width.
|
||||
*
|
||||
* Also, the prune_width is the maximum width of the result, and it
|
||||
* passed to the eval_tree method of the expression to limit constant
|
||||
* results if possible.
|
||||
* The prune_width is the maximum width of the result, and is passed
|
||||
* to the eval_tree method of the expression to limit constant
|
||||
* results. The evaluation will prune any constant result down to the
|
||||
* prune_width (if >0) so should only be used at the point where it is
|
||||
* bound to the destination.
|
||||
*/
|
||||
class PExpr;
|
||||
extern NetExpr* elab_and_eval(Design*des, NetScope*scope,
|
||||
const PExpr*pe, int expr_wid,
|
||||
int prune_width =-1);
|
||||
|
||||
/*
|
||||
* This function elaborates an expression as if it is for the r-value
|
||||
* of an assignment, The data_type_lv and expr_wid_lv are the type and
|
||||
* with of the l-value, and the expr is the expression to
|
||||
* elaborate. The result is the NetExpr elaborated and evaluated.
|
||||
* (See elab_expr.cc)
|
||||
*/
|
||||
extern NetExpr* elaborate_rval_expr(Design*des, NetScope*scope,
|
||||
ivl_variable_type_t data_type_lv,
|
||||
int expr_wid_lv, PExpr*expr);
|
||||
/*
|
||||
* This procedure elaborates an expression and if the elaboration is
|
||||
* successful the original expression is replaced with the new one.
|
||||
@@ -145,9 +176,26 @@ void eval_expr(NetExpr*&expr, int prune_width =-1);
|
||||
bool eval_as_long(long&value, NetExpr*expr);
|
||||
bool eval_as_double(double&value, NetExpr*expr);
|
||||
|
||||
/*
|
||||
* Evaluate the component of a scope path to get an hname_t value. Do
|
||||
* the evaluation in the context of the given scope.
|
||||
*/
|
||||
extern hname_t eval_path_component(Design*des, NetScope*scope,
|
||||
const name_component_t&comp);
|
||||
|
||||
/*
|
||||
* Evaluate an entire scope path in the context of the given scope.
|
||||
*/
|
||||
extern std::list<hname_t> eval_scope_path(Design*des, NetScope*scope,
|
||||
const pform_name_t&path);
|
||||
|
||||
/*
|
||||
* Return true if the data type is a type that is normally available
|
||||
* in vector for. IVL_VT_BOOL and IVL_VT_LOGIC are vectorable,
|
||||
* IVL_VT_REAL is not.
|
||||
*/
|
||||
extern bool type_is_vectorable(ivl_variable_type_t type);
|
||||
|
||||
/*
|
||||
* Return a human readable version of the operator.
|
||||
*/
|
||||
|
||||
+82
-55
@@ -37,14 +37,18 @@ class nodangle_f : public functor_t {
|
||||
void event(Design*des, NetEvent*ev);
|
||||
void signal(Design*des, NetNet*sig);
|
||||
|
||||
unsigned count_;
|
||||
unsigned iteration;
|
||||
unsigned stotal, etotal;
|
||||
bool scontinue, econtinue;
|
||||
bool scomplete, ecomplete;
|
||||
};
|
||||
|
||||
void nodangle_f::event(Design*des, NetEvent*ev)
|
||||
{
|
||||
if (ecomplete) return;
|
||||
|
||||
/* If there are no references to this event, then go right
|
||||
ahead and delete in. There is no use looking further at
|
||||
ahead and delete it. There is no use looking further at
|
||||
it. */
|
||||
if ((ev->nwait() + ev->ntrig() + ev->nexpr()) == 0) {
|
||||
delete ev;
|
||||
@@ -52,58 +56,79 @@ void nodangle_f::event(Design*des, NetEvent*ev)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Try to remove duplicate probes from the event. */
|
||||
for (unsigned idx = 0 ; idx < ev->nprobe() ; idx += 1) {
|
||||
unsigned jdx = idx + 1;
|
||||
while (jdx < ev->nprobe()) {
|
||||
NetEvProbe*ip = ev->probe(idx);
|
||||
NetEvProbe*jp = ev->probe(jdx);
|
||||
if (iteration == 0) {
|
||||
/* Try to remove duplicate probes from the event. This
|
||||
is done as a separate initial pass to ensure similar
|
||||
events are detected as soon as possible in subsequent
|
||||
iterations. */
|
||||
for (unsigned idx = 0 ; idx < ev->nprobe() ; idx += 1) {
|
||||
unsigned jdx = idx + 1;
|
||||
while (jdx < ev->nprobe()) {
|
||||
NetEvProbe*ip = ev->probe(idx);
|
||||
NetEvProbe*jp = ev->probe(jdx);
|
||||
|
||||
if (ip->edge() != jp->edge()) {
|
||||
jdx += 1;
|
||||
continue;
|
||||
}
|
||||
if (ip->edge() != jp->edge()) {
|
||||
jdx += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
bool fully_connected = true;
|
||||
for (unsigned jpin = 0; jpin < jp->pin_count(); jpin += 1) {
|
||||
unsigned ipin = 0;
|
||||
bool connected_flag = false;
|
||||
for (ipin = 0 ; ipin < ip->pin_count(); ipin += 1)
|
||||
if (connected(ip->pin(ipin), jp->pin(jpin))) {
|
||||
connected_flag = true;
|
||||
break;
|
||||
}
|
||||
bool fully_connected = true;
|
||||
for (unsigned jpin = 0; jpin < jp->pin_count(); jpin += 1) {
|
||||
unsigned ipin = 0;
|
||||
bool connected_flag = false;
|
||||
for (ipin = 0 ; ipin < ip->pin_count(); ipin += 1)
|
||||
if (connected(ip->pin(ipin), jp->pin(jpin))) {
|
||||
connected_flag = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!connected_flag) {
|
||||
fully_connected = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!connected_flag) {
|
||||
fully_connected = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (fully_connected) {
|
||||
delete jp;
|
||||
} else {
|
||||
jdx += 1;
|
||||
}
|
||||
}
|
||||
if (fully_connected) {
|
||||
delete jp;
|
||||
} else {
|
||||
jdx += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
econtinue = true;
|
||||
} else {
|
||||
/* Postpone examining events in an automatic scope until the
|
||||
third (optional) pass. This will mean similar events are
|
||||
biased towards being stored in static scopes. */
|
||||
if (ev->scope()->is_auto()) {
|
||||
if (iteration == 1) {
|
||||
econtinue = true;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (iteration == 2) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Try to find all the events that are similar to me, and
|
||||
replace their references with references to me. */
|
||||
list<NetEvent*> match;
|
||||
ev->find_similar_event(match);
|
||||
for (list<NetEvent*>::iterator idx = match.begin()
|
||||
; idx != match.end() ; idx ++) {
|
||||
|
||||
NetEvent*tmp = *idx;
|
||||
assert(tmp != ev);
|
||||
tmp ->replace_event(ev);
|
||||
}
|
||||
}
|
||||
|
||||
/* Try to find all the events that are similar to me, and
|
||||
replace their references with references to me. */
|
||||
list<NetEvent*> match;
|
||||
ev->find_similar_event(match);
|
||||
for (list<NetEvent*>::iterator idx = match.begin()
|
||||
; idx != match.end() ; idx ++) {
|
||||
|
||||
NetEvent*tmp = *idx;
|
||||
assert(tmp != ev);
|
||||
tmp ->replace_event(ev);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void nodangle_f::signal(Design*des, NetNet*sig)
|
||||
{
|
||||
if (scomplete) return;
|
||||
|
||||
/* Cannot delete signals referenced in an expression
|
||||
or an l-value. */
|
||||
if (sig->get_refs() > 0)
|
||||
@@ -174,7 +199,7 @@ void nodangle_f::signal(Design*des, NetNet*sig)
|
||||
/* If every pin is connected to another significant signal,
|
||||
then I can delete this one. */
|
||||
if (significant_flags == sig->pin_count()) {
|
||||
count_ += 1;
|
||||
scontinue = true;
|
||||
delete sig;
|
||||
stotal += 1;
|
||||
}
|
||||
@@ -183,23 +208,26 @@ void nodangle_f::signal(Design*des, NetNet*sig)
|
||||
void nodangle(Design*des)
|
||||
{
|
||||
nodangle_f fun;
|
||||
unsigned count_iterations = 0;
|
||||
fun.iteration = 0;
|
||||
fun.stotal = 0;
|
||||
fun.etotal = 0;
|
||||
|
||||
fun.scomplete = false;
|
||||
fun.ecomplete = false;
|
||||
do {
|
||||
fun.count_ = 0;
|
||||
fun.scontinue = false;
|
||||
fun.econtinue = false;
|
||||
des->functor(&fun);
|
||||
count_iterations += 1;
|
||||
fun.iteration += 1;
|
||||
fun.scomplete = !fun.scontinue;
|
||||
fun.ecomplete = !fun.econtinue;
|
||||
|
||||
if (verbose_flag) {
|
||||
cout << " ... " << count_iterations << " iterations"
|
||||
cout << " ... " << fun.iteration << " iterations"
|
||||
<< " deleted " << fun.stotal << " dangling signals"
|
||||
<< " and " << fun.etotal << " events."
|
||||
<< " (count=" << fun.count_ << ")" << endl;
|
||||
<< " and " << fun.etotal << " events." << endl;
|
||||
}
|
||||
|
||||
} while (fun.count_ > 0);
|
||||
} while (fun.scontinue || fun.econtinue);
|
||||
|
||||
}
|
||||
|
||||
@@ -285,4 +313,3 @@ void nodangle(Design*des)
|
||||
* symbols generated by elaboration and other steps.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
@@ -88,6 +88,7 @@ NetNet*pad_to_width(Design*des, NetNet*net, unsigned wid)
|
||||
tmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, wid);
|
||||
tmp->data_type( net->data_type() );
|
||||
tmp->set_line(*net);
|
||||
tmp->local_flag(true);
|
||||
connect(cc->pin(0), tmp->pin(0));
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user