mirror of
https://github.com/steveicarus/iverilog.git
synced 2026-08-23 06:16:47 +02:00
Compare commits
1070
Commits
version0_1
...
s20010902
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
298a352cbd | ||
|
|
356552faad | ||
|
|
5e1e79b3c4 | ||
|
|
2996d2eb19 | ||
|
|
16023cbbd6 | ||
|
|
77927972e5 | ||
|
|
d762a320dc | ||
|
|
a9e54e7553 | ||
|
|
8b8a3d83e0 | ||
|
|
3fbbd4080a | ||
|
|
e79a371f76 | ||
|
|
c507379f09 | ||
|
|
47031767fa | ||
|
|
af5e68448c | ||
|
|
c1c88f87c6 | ||
|
|
a9b5c9c037 | ||
|
|
03b428b6cb | ||
|
|
271a835305 | ||
|
|
a3c3019a04 | ||
|
|
f063bf833f | ||
|
|
2002c03cef | ||
|
|
b8be5e80cd | ||
|
|
c29e11ed36 | ||
|
|
e35ed6e91c | ||
|
|
794ce68a6c | ||
|
|
31aa85ce7d | ||
|
|
15c2b0317d | ||
|
|
820d8b9edc | ||
|
|
a3a0f5f432 | ||
|
|
a98b5023a8 | ||
|
|
645c8913f1 | ||
|
|
066284d5c2 | ||
|
|
2802601c44 | ||
|
|
962a77c6b8 | ||
|
|
ca801574e3 | ||
|
|
606c1d38bb | ||
|
|
147ee59940 | ||
|
|
2e3fc89831 | ||
|
|
82bccd335d | ||
|
|
bfc05e2d71 | ||
|
|
c8135595be | ||
|
|
d5658d4180 | ||
|
|
8356e6a51f | ||
|
|
fbf55b9df4 | ||
|
|
176e6d09ca | ||
|
|
b72d1c297d | ||
|
|
f5b9c26735 | ||
|
|
d8141252e9 | ||
|
|
ed86dee65d | ||
|
|
f535cd3077 | ||
|
|
537757a7b9 | ||
|
|
4fb354776e | ||
|
|
1583b1e84a | ||
|
|
45ff04ecb6 | ||
|
|
ef08e43cf2 | ||
|
|
e17f7f5146 | ||
|
|
8654412844 | ||
|
|
140533db50 | ||
|
|
00cacae2a3 | ||
|
|
7e0b0d7328 | ||
|
|
1be77d68ce | ||
|
|
c5a5a11b7f | ||
|
|
becc7cb56a | ||
|
|
629a02cccf | ||
|
|
f28b97ebfd | ||
|
|
c5234e95cd | ||
|
|
b825f8d2b2 | ||
|
|
eb08253ed0 | ||
|
|
7b79fd98e5 | ||
|
|
6d5fcf5853 | ||
|
|
bc284ee6d8 | ||
|
|
260b4166c1 | ||
|
|
b59cc5ff6d | ||
|
|
5c89fb71ae | ||
|
|
3baa8c0445 | ||
|
|
ce589da58a | ||
|
|
0bb9359c05 | ||
|
|
54140dadcf | ||
|
|
60c22aefeb | ||
|
|
69a2331791 | ||
|
|
29cfd8ccfe | ||
|
|
bf67f386de | ||
|
|
a2f07011c1 | ||
|
|
0bd6cf7b6f | ||
|
|
cd8e491028 | ||
|
|
e773ccfe49 | ||
|
|
83de770387 | ||
|
|
b3a8098506 | ||
|
|
05407f488f | ||
|
|
85d53ebbf4 | ||
|
|
e4139f4819 | ||
|
|
45c935af45 | ||
|
|
cfbfd9ec1d | ||
|
|
ae209a144f | ||
|
|
64837efac5 | ||
|
|
8d73df2b04 | ||
|
|
59117c2e42 | ||
|
|
e23dd57c9d | ||
|
|
0e20be774e | ||
|
|
c3ae00ae49 | ||
|
|
a7328ecce1 | ||
|
|
15a952a143 | ||
|
|
3154f07817 | ||
|
|
4e700bffb8 | ||
|
|
7b2d4c9ef6 | ||
|
|
da828a218f | ||
|
|
13ef84bc35 | ||
|
|
c7b36322f6 | ||
|
|
8cc89a3a1f | ||
|
|
b8c5aff0cb | ||
|
|
fb0c387b12 | ||
|
|
1628045b55 | ||
|
|
608e5a4dbb | ||
|
|
30787fd49e | ||
|
|
1e231c3338 | ||
|
|
370549a19a | ||
|
|
39c39f0162 | ||
|
|
bcaa122fb9 | ||
|
|
96403de903 | ||
|
|
ab5cad18de | ||
|
|
b1c548a981 | ||
|
|
039769dbaf | ||
|
|
a76d6dc352 | ||
|
|
7eab75ded1 | ||
|
|
ef9c7c4a30 | ||
|
|
4c54e070ed | ||
|
|
80c609853a | ||
|
|
eeabc7234c | ||
|
|
79b740284a | ||
|
|
ab7b353ace | ||
|
|
3b82a15521 | ||
|
|
97d972ebb3 | ||
|
|
5f5081827d | ||
|
|
6b7b4e700a | ||
|
|
baac893d22 | ||
|
|
d680e594ed | ||
|
|
42adc49e57 | ||
|
|
4a2168b352 | ||
|
|
44d4660fe8 | ||
|
|
45d4117c02 | ||
|
|
ae837a6347 | ||
|
|
426fc18d10 | ||
|
|
2531ed89cd | ||
|
|
566d5c9a93 | ||
|
|
a033c331b6 | ||
|
|
066b534307 | ||
|
|
64cabd8074 | ||
|
|
a0db52c69f | ||
|
|
7bbedd1b55 | ||
|
|
0340256b4c | ||
|
|
c4bd8b1463 | ||
|
|
a2d465804f | ||
|
|
3c5d32637c | ||
|
|
c93cb71162 | ||
|
|
c3960f8e6a | ||
|
|
96d04bb5a0 | ||
|
|
1f1bfd0eab | ||
|
|
8cdf51f913 | ||
|
|
1f3eedcfd7 | ||
|
|
541f269c20 | ||
|
|
68a7ddefd3 | ||
|
|
3961c68928 | ||
|
|
832b795826 | ||
|
|
7a6be47603 | ||
|
|
81536481cc | ||
|
|
6e703c5744 | ||
|
|
82e8e51736 | ||
|
|
905529081d | ||
|
|
4159c98c58 | ||
|
|
e40efec4bd | ||
|
|
e418625457 | ||
|
|
4b82d26f5e | ||
|
|
63a02d1c0a | ||
|
|
bf42772995 | ||
|
|
b75221e9bf | ||
|
|
1e9a54d134 | ||
|
|
ff0b59ff6b | ||
|
|
b3a5a0e5ab | ||
|
|
e002b1c1c4 | ||
|
|
7009dc8d9b | ||
|
|
e28b7f06c5 | ||
|
|
b6e1d63cb0 | ||
|
|
5a279dbdc8 | ||
|
|
3ad3a2ab57 | ||
|
|
5361efe8ed | ||
|
|
2f2657b765 | ||
|
|
19a7f3faeb | ||
|
|
f480943649 | ||
|
|
f3019ff5a0 | ||
|
|
33ee5c26b0 | ||
|
|
1e9184f0f9 | ||
|
|
19251f7a79 | ||
|
|
b79da2c4d6 | ||
|
|
e68ba4c73a | ||
|
|
39ffe91230 | ||
|
|
150fc6f3ee | ||
|
|
a7411eb00d | ||
|
|
660fd7c1d4 | ||
|
|
53772db66d | ||
|
|
93dd08bdf5 | ||
|
|
176d707e0a | ||
|
|
34dade1b65 | ||
|
|
4e815f8565 | ||
|
|
e69a3ed934 | ||
|
|
77d63aba74 | ||
|
|
de8c725890 | ||
|
|
d4b2958e50 | ||
|
|
8669b372e0 | ||
|
|
61991e6367 | ||
|
|
bdcb813727 | ||
|
|
e6f1510a40 | ||
|
|
224af78463 | ||
|
|
983bf5cbab | ||
|
|
96bcf6eac4 | ||
|
|
0872ad34cf | ||
|
|
5aee3b866a | ||
|
|
3ce86f5664 | ||
|
|
23e5394fb4 | ||
|
|
be7ac7a2ca | ||
|
|
a616cfd0c2 | ||
|
|
e85b669307 | ||
|
|
bc6dfeb4a9 | ||
|
|
bf96986c38 | ||
|
|
26cfbb2b7b | ||
|
|
35fc2a609d | ||
|
|
f05b13c630 | ||
|
|
4d8954be4c | ||
|
|
1d0a9871c2 | ||
|
|
2292751fc3 | ||
|
|
a6524e47e2 | ||
|
|
02b9aa9163 | ||
|
|
754adce4a4 | ||
|
|
f3fdf70b56 | ||
|
|
38db6fde0c | ||
|
|
4f804577f9 | ||
|
|
44a182d92c | ||
|
|
91d65d0e4e | ||
|
|
a88f030b52 | ||
|
|
4537de8120 | ||
|
|
100bdedac3 | ||
|
|
914ad85e63 | ||
|
|
b3c2ad0a65 | ||
|
|
2e12635494 | ||
|
|
4325b787c0 | ||
|
|
4e3c702cc7 | ||
|
|
213cb1b08a | ||
|
|
b7569f4d70 | ||
|
|
e328cf9fed | ||
|
|
78af3dbdc0 | ||
|
|
372674b4c0 | ||
|
|
8d0f7e1594 | ||
|
|
558fea33fb | ||
|
|
de5930f7d8 | ||
|
|
e09a14aa44 | ||
|
|
d45c7c58df | ||
|
|
b5e0f46229 | ||
|
|
12229e4826 | ||
|
|
8f88525819 | ||
|
|
a225fe304d | ||
|
|
0f9eb13245 | ||
|
|
06437b7fba | ||
|
|
ba910c0fac | ||
|
|
28278d3c09 | ||
|
|
2bf7653ab9 | ||
|
|
cb39b3b65c | ||
|
|
3e3757bde7 | ||
|
|
8b4befd4fc | ||
|
|
972e9c866b | ||
|
|
f758010f01 | ||
|
|
8057faccc1 | ||
|
|
3f952a2fd2 | ||
|
|
eb71c70c99 | ||
|
|
2a44cf70b1 | ||
|
|
431b16639d | ||
|
|
014e68b62f | ||
|
|
31291f5d8a | ||
|
|
a52b34cb64 | ||
|
|
3ca55bf327 | ||
|
|
9bb2cee686 | ||
|
|
4f3bdd9f38 | ||
|
|
efe41c2435 | ||
|
|
f855cb19b8 | ||
|
|
861ed55879 | ||
|
|
35e0dcdd3d | ||
|
|
a72a8607e6 | ||
|
|
904747acf5 | ||
|
|
4d40a336c0 | ||
|
|
32e9c8049a | ||
|
|
bb24624979 | ||
|
|
506bc87e82 | ||
|
|
986885bd70 | ||
|
|
73c4893ef7 | ||
|
|
62c9f39297 | ||
|
|
8b5f62a5e5 | ||
|
|
aec5841c7f | ||
|
|
c997c090a1 | ||
|
|
0ab60cd3c3 | ||
|
|
ae23a8f6bf | ||
|
|
46e868d313 | ||
|
|
8dfa322b8b | ||
|
|
2f2f08b02f | ||
|
|
102fd24dd2 | ||
|
|
66cf3ec8fa | ||
|
|
57b0d9691e | ||
|
|
7c6f496765 | ||
|
|
67e72ce77e | ||
|
|
c97692d715 | ||
|
|
66f83f3b08 | ||
|
|
3765bdd3ac | ||
|
|
39bcdfb7b4 | ||
|
|
57cd770650 | ||
|
|
3194b0c53a | ||
|
|
9e8005f7b7 | ||
|
|
41ce198a1f | ||
|
|
05e30ed43b | ||
|
|
09cd582cc5 | ||
|
|
235781ce08 | ||
|
|
70aeb980d8 | ||
|
|
d0d6189874 | ||
|
|
8205d0fcc9 | ||
|
|
60d068a33e | ||
|
|
e1a4b457c2 | ||
|
|
86e18226eb | ||
|
|
7fa2975c24 | ||
|
|
d39190243b | ||
|
|
0550287658 | ||
|
|
82947a9343 | ||
|
|
b7fb806611 | ||
|
|
6a236061de | ||
|
|
898639d7bf | ||
|
|
6322400b83 | ||
|
|
9b7341889d | ||
|
|
0653f859bc | ||
|
|
48ff66cbce | ||
|
|
1b2a6f8bed | ||
|
|
c6cf665c4a | ||
|
|
19c84ff9a2 | ||
|
|
15398a8f58 | ||
|
|
9d2e22576e | ||
|
|
3ffb3c7011 | ||
|
|
cac4c8d5ce | ||
|
|
f40d006c26 | ||
|
|
e6c36597eb | ||
|
|
141808b787 | ||
|
|
003f103408 | ||
|
|
ce66498c88 | ||
|
|
bf30a0bc07 | ||
|
|
f8e6d782e1 | ||
|
|
7a8135c703 | ||
|
|
311e1ce9ee | ||
|
|
9bce21ddb7 | ||
|
|
c4e438d4ba | ||
|
|
a2da2d59df | ||
|
|
56a4236576 | ||
|
|
2443c655f2 | ||
|
|
ae1d5227de | ||
|
|
5769bbe15e | ||
|
|
6dbf7333c8 | ||
|
|
4352ce6753 | ||
|
|
29a50a52ca | ||
|
|
d25690cc8e | ||
|
|
e29ecdc234 | ||
|
|
0f6eea7024 | ||
|
|
97dd559fca | ||
|
|
a4c722b195 | ||
|
|
b3a3b888d8 | ||
|
|
2f1d258acb | ||
|
|
7aa9bc9892 | ||
|
|
4a058632b2 | ||
|
|
6a72b4c10e | ||
|
|
00d44222dd | ||
|
|
b36b6d0ca0 | ||
|
|
386958f9a0 | ||
|
|
f6eb581aff | ||
|
|
966f7a4bff | ||
|
|
2cb76cabef | ||
|
|
609d5fe727 | ||
|
|
522d0ec864 | ||
|
|
ad8565f8a6 | ||
|
|
b0c003dc34 | ||
|
|
a4e528f0c3 | ||
|
|
c8d9ade58c | ||
|
|
61e3eed49c | ||
|
|
afb8e285db | ||
|
|
79ce94b585 | ||
|
|
f7f5ccce05 | ||
|
|
25d25ff7fe | ||
|
|
31b0037299 | ||
|
|
16f514739f | ||
|
|
604ce0db09 | ||
|
|
a71dbd3987 | ||
|
|
417186b06f | ||
|
|
ac91dc38b8 | ||
|
|
6d0be3de3a | ||
|
|
2d4f33a0dd | ||
|
|
c6088c8820 | ||
|
|
5134636932 | ||
|
|
5d051ffbde | ||
|
|
97985bba64 | ||
|
|
9ec5fa972e | ||
|
|
9e04ef4abd | ||
|
|
68dc83b322 | ||
|
|
97e9b62080 | ||
|
|
4072021ba4 | ||
|
|
c901945871 | ||
|
|
95281e5d82 | ||
|
|
2858c2f09b | ||
|
|
034cdae445 | ||
|
|
e71ea8c9de | ||
|
|
b2a136e07e | ||
|
|
c2dc3fe5c3 | ||
|
|
548ff4f89a | ||
|
|
b3c24adb11 | ||
|
|
e81d0d9f23 | ||
|
|
715d140d85 | ||
|
|
fa46de1021 | ||
|
|
aa31884d3b | ||
|
|
aacce5ef1b | ||
|
|
565088160e | ||
|
|
b24011b84b | ||
|
|
2b8d9abd3e | ||
|
|
e24facfaf6 | ||
|
|
27e717839a | ||
|
|
52c7108782 | ||
|
|
90ed3dd124 | ||
|
|
8118203766 | ||
|
|
e8518c5056 | ||
|
|
f02d4574f9 | ||
|
|
f1ff1149f7 | ||
|
|
034a38ea36 | ||
|
|
f8c3b84f68 | ||
|
|
d8ef63efd1 | ||
|
|
a240be73e7 | ||
|
|
1563643c92 | ||
|
|
5b89249f10 | ||
|
|
bf70673380 | ||
|
|
6779f01f3a | ||
|
|
66f7ef97da | ||
|
|
e03859b834 | ||
|
|
f2c1902984 | ||
|
|
32f3881344 | ||
|
|
264e629c74 | ||
|
|
8969ab03d7 | ||
|
|
952ebe8516 | ||
|
|
f355cf334c | ||
|
|
01c5321208 | ||
|
|
970ba895c9 | ||
|
|
cbc3be0304 | ||
|
|
cb65ee5e00 | ||
|
|
debe707097 | ||
|
|
79b60da54c | ||
|
|
84c7795d16 | ||
|
|
410a93b52c | ||
|
|
78355b6038 | ||
|
|
59b69c6dd1 | ||
|
|
d3bff8a451 | ||
|
|
43ddd97426 | ||
|
|
4399042b8d | ||
|
|
2b0aaec8ab | ||
|
|
7d7ccd4f08 | ||
|
|
93463b6ff5 | ||
|
|
4b0c56c3a8 | ||
|
|
1bae567728 | ||
|
|
7d7beeecc1 | ||
|
|
f5d0211864 | ||
|
|
1f4232187c | ||
|
|
f45ba008d8 | ||
|
|
ac629b313c | ||
|
|
563065053e | ||
|
|
2b903f5d0e | ||
|
|
7ef3b44ab1 | ||
|
|
8376553349 | ||
|
|
3885f17d0f | ||
|
|
4b0e5bd173 | ||
|
|
d78c7392c2 | ||
|
|
cf3f1b38c3 | ||
|
|
2fbc0af1ea | ||
|
|
94a1d59817 | ||
|
|
57d1bfaf29 | ||
|
|
d6701803d1 | ||
|
|
9e624ac833 | ||
|
|
0175c727ee | ||
|
|
90250baf0f | ||
|
|
cc22ae833a | ||
|
|
6c4b5cf2c2 | ||
|
|
88a2ca2168 | ||
|
|
41242735ed | ||
|
|
ab11943496 | ||
|
|
d9f0065f93 | ||
|
|
53dfdacce8 | ||
|
|
4e44515078 | ||
|
|
2b11f78d63 | ||
|
|
a4de0af79d | ||
|
|
145ac49233 | ||
|
|
6479319fea | ||
|
|
f224ed3a90 | ||
|
|
5f292e546d | ||
|
|
65020bc6de | ||
|
|
6adb50e860 | ||
|
|
1ea417dc30 | ||
|
|
a00924089d | ||
|
|
66716f5101 | ||
|
|
219df169a3 | ||
|
|
b712c3f5ca | ||
|
|
02fc59fbdf | ||
|
|
4e7a5d55d0 | ||
|
|
5fb7f9ca91 | ||
|
|
246f2d5884 | ||
|
|
5276752276 | ||
|
|
6bf599e839 | ||
|
|
fff32b1b54 | ||
|
|
a64a4d7a9b | ||
|
|
9eb6f9dbb9 | ||
|
|
430e46d718 | ||
|
|
cd9a30707b | ||
|
|
ad0853d666 | ||
|
|
cc18d065aa | ||
|
|
14c67a5389 | ||
|
|
68e672e61a | ||
|
|
2703456ad4 | ||
|
|
8ee00ec562 | ||
|
|
8bfae1e641 | ||
|
|
8befc6f7c4 | ||
|
|
d5ec89813d | ||
|
|
ac7ae1ba6f | ||
|
|
120a211e68 | ||
|
|
b6a18098c7 | ||
|
|
112936d661 | ||
|
|
4d09c43ecf | ||
|
|
2a6f8634f6 | ||
|
|
5803e8c42c | ||
|
|
eda3c63f72 | ||
|
|
365b149ec1 | ||
|
|
e68c26bb87 | ||
|
|
4e7f8766fa | ||
|
|
fe209a6996 | ||
|
|
f4671a3082 | ||
|
|
c9881c115a | ||
|
|
0a3bda87d6 | ||
|
|
8ae4e25720 | ||
|
|
44131d4b16 | ||
|
|
d5eb3a2bad | ||
|
|
086348035e | ||
|
|
05b5b91a84 | ||
|
|
bcbd5b2c5c | ||
|
|
8c680d158a | ||
|
|
8fe6324aec | ||
|
|
15a426cc73 | ||
|
|
770dfe5eaa | ||
|
|
5144725b8f | ||
|
|
189f55b894 | ||
|
|
e836bc951d | ||
|
|
f0718b1345 | ||
|
|
9cb91ce9aa | ||
|
|
4abf4b0a9a | ||
|
|
7d622fc6ab | ||
|
|
3e73ec3e0f | ||
|
|
36a1b37789 | ||
|
|
e34ef2a2b9 | ||
|
|
fd0f618529 | ||
|
|
a010dd1cc0 | ||
|
|
5dbea64759 | ||
|
|
084a464cf1 | ||
|
|
c0f951c146 | ||
|
|
9ddd0491f7 | ||
|
|
245472ca63 | ||
|
|
371f43e227 | ||
|
|
9fe0d9b120 | ||
|
|
16c50ad810 | ||
|
|
a4da2c7ed5 | ||
|
|
40da501cec | ||
|
|
f6507cba43 | ||
|
|
e027247a0e | ||
|
|
789e862ca4 | ||
|
|
a6b83ac5da | ||
|
|
3b9a60414e | ||
|
|
4f638882c9 | ||
|
|
4faec154f0 | ||
|
|
ff53b60c66 | ||
|
|
a2a40869b0 | ||
|
|
b714f57797 | ||
|
|
d0ec7e2c02 | ||
|
|
d16d29c591 | ||
|
|
e310532434 | ||
|
|
4eed86d519 | ||
|
|
ef49fc127f | ||
|
|
e6151db172 | ||
|
|
28af357c8a | ||
|
|
a5c69b50e5 | ||
|
|
02f876ac69 | ||
|
|
ea921efced | ||
|
|
4bf3e37af3 | ||
|
|
291ab97422 | ||
|
|
12db3340cc | ||
|
|
e33fb3ce51 | ||
|
|
92424eea10 | ||
|
|
4ca0bffc7f | ||
|
|
c86da66b77 | ||
|
|
f7d62b96aa | ||
|
|
482323843e | ||
|
|
f4443a7dfa | ||
|
|
1f07ba52b6 | ||
|
|
ec0d12b738 | ||
|
|
457d193238 | ||
|
|
e05b9a4769 | ||
|
|
2750977e4a | ||
|
|
ff5846100c | ||
|
|
da926fa08b | ||
|
|
fc6978e4de | ||
|
|
11e6440162 | ||
|
|
f74368dec2 | ||
|
|
4b264a4c58 | ||
|
|
0ca9b2736b | ||
|
|
28bc621f11 | ||
|
|
197ed46b26 | ||
|
|
b05aadfd94 | ||
|
|
a8da692540 | ||
|
|
1d6f48914f | ||
|
|
1046c86c84 | ||
|
|
47ce0f3c46 | ||
|
|
2dd1d070ec | ||
|
|
f4ed0e35af | ||
|
|
61ad0b23c8 | ||
|
|
5415dd70c5 | ||
|
|
ff514aab72 | ||
|
|
d7788b88b7 | ||
|
|
a1cfabafb8 | ||
|
|
35769ef541 | ||
|
|
80d3342178 | ||
|
|
4d27b947bc | ||
|
|
3591e06c4e | ||
|
|
88c8547486 | ||
|
|
d92ac5772c | ||
|
|
f2997d7767 | ||
|
|
7df9943679 | ||
|
|
f3dfff7d76 | ||
|
|
23a5bd072d | ||
|
|
d6efae4bdd | ||
|
|
10fbb2a1bb | ||
|
|
5b65f15df4 | ||
|
|
72229abda6 | ||
|
|
427de3ab0b | ||
|
|
6962841546 | ||
|
|
bb414303a0 | ||
|
|
431228e881 | ||
|
|
07d7008853 | ||
|
|
7545db5e26 | ||
|
|
ad4931e813 | ||
|
|
f915efaf15 | ||
|
|
df660bab0c | ||
|
|
26350fdcf5 | ||
|
|
0e7ca326ce | ||
|
|
88b479a82b | ||
|
|
e08314eaf5 | ||
|
|
b8fe10d27d | ||
|
|
1cc7b6d4d7 | ||
|
|
bb9eb2cd1d | ||
|
|
add2ae16fa | ||
|
|
ecf71efc84 | ||
|
|
e10679633d | ||
|
|
f5fae7f271 | ||
|
|
90ae46476c | ||
|
|
2dedd6c067 | ||
|
|
7ee46bc621 | ||
|
|
368e5b72be | ||
|
|
f526d235d1 | ||
|
|
06f5482631 | ||
|
|
52b649cd5e | ||
|
|
588966320f | ||
|
|
5ce28c193a | ||
|
|
c9bcda147e | ||
|
|
4819d54d51 | ||
|
|
8fe887ffe1 | ||
|
|
76e2c509d7 | ||
|
|
6f69773c57 | ||
|
|
8ba1facb66 | ||
|
|
20d07a7366 | ||
|
|
02bee9358c | ||
|
|
41f3ba65a1 | ||
|
|
ce19190eae | ||
|
|
d7fcd66826 | ||
|
|
9680de25cd | ||
|
|
aac5fc246a | ||
|
|
887654b7c5 | ||
|
|
07aa86f0fa | ||
|
|
2f668421a3 | ||
|
|
bb777f317b | ||
|
|
b34a451cbc | ||
|
|
c12e0f5416 | ||
|
|
40028f263f | ||
|
|
21e0e8a8a1 | ||
|
|
700bcfda70 | ||
|
|
fff759de20 | ||
|
|
79b1c51e68 | ||
|
|
8b581cef46 | ||
|
|
d6b43519a8 | ||
|
|
cbe20e8bcf | ||
|
|
e8bb53e2ea | ||
|
|
2be1c115ff | ||
|
|
36cc374ec9 | ||
|
|
043bd2876b | ||
|
|
57ced29227 | ||
|
|
80c69d565b | ||
|
|
3a2eff2265 | ||
|
|
48ff3590bc | ||
|
|
9067c91656 | ||
|
|
13c1378666 | ||
|
|
39cf6bd164 | ||
|
|
ea53f2b54f | ||
|
|
effc84c46d | ||
|
|
89d7176734 | ||
|
|
f8478a4408 | ||
|
|
8978bbd5e6 | ||
|
|
063d56ffc1 | ||
|
|
67472379b4 | ||
|
|
7e9a7ed0cb | ||
|
|
db1b53c1e7 | ||
|
|
68c6c48a18 | ||
|
|
3c94635f99 | ||
|
|
8a69c54886 | ||
|
|
b6ce313e91 | ||
|
|
3ae76a8638 | ||
|
|
d86b37d90f | ||
|
|
e27934a577 | ||
|
|
ddcba9d91f | ||
|
|
44438c9678 | ||
|
|
4cf75adf94 | ||
|
|
49570b8cd9 | ||
|
|
24e46723b0 | ||
|
|
e95d0c3b87 | ||
|
|
ece3f5e0a2 | ||
|
|
115d24a292 | ||
|
|
ac81f6a201 | ||
|
|
ff32325d07 | ||
|
|
eb781a7441 | ||
|
|
8876cda37f | ||
|
|
df113f962b | ||
|
|
d0fc6d515d | ||
|
|
3cb666dd2f | ||
|
|
a59bbdeb4f | ||
|
|
9abd84952b | ||
|
|
3ae4d2cf91 | ||
|
|
534521f88b | ||
|
|
566aad9e15 | ||
|
|
248baa26e1 | ||
|
|
91a462e38c | ||
|
|
d58533fd7b | ||
|
|
dab45178a7 | ||
|
|
e01137ced3 | ||
|
|
b5a36fef70 | ||
|
|
2e3e9ecf37 | ||
|
|
60c2046be6 | ||
|
|
1325a3e2b6 | ||
|
|
d677f226f3 | ||
|
|
eb93e3d2f5 | ||
|
|
7cccbda275 | ||
|
|
931ec257f0 | ||
|
|
b6562d3ed9 | ||
|
|
0243fca8dc | ||
|
|
30a81731dd | ||
|
|
3aa250b16b | ||
|
|
39c71ef68a | ||
|
|
4494a7a4f3 | ||
|
|
739365abe5 | ||
|
|
880b712140 | ||
|
|
08e6bf2e27 | ||
|
|
5f7c298a21 | ||
|
|
34399cf297 | ||
|
|
cb7b1b6c94 | ||
|
|
53489e6abe | ||
|
|
4f75d04a42 | ||
|
|
81dab9c572 | ||
|
|
286cef19fb | ||
|
|
741b17245d | ||
|
|
2a08824ae9 | ||
|
|
42e4ff47c8 | ||
|
|
8dd2fc7095 | ||
|
|
c07cc005bd | ||
|
|
79ca317c1d | ||
|
|
b8946d4cb3 | ||
|
|
8902645fa7 | ||
|
|
9c12fcffe4 | ||
|
|
9b59001cf9 | ||
|
|
18eb34921f | ||
|
|
cdb3eb7e6b | ||
|
|
e152b91226 | ||
|
|
056a3f7220 | ||
|
|
888360dd3b | ||
|
|
337eee7dcb | ||
|
|
de76c77820 | ||
|
|
642e1bccd9 | ||
|
|
1562784a48 | ||
|
|
042724612e | ||
|
|
62d83e962a | ||
|
|
583868e74e | ||
|
|
e52ada617e | ||
|
|
f3384c7da5 | ||
|
|
d94acc1c5c | ||
|
|
4febf5801b | ||
|
|
e52243a82d | ||
|
|
db8cc7d98d | ||
|
|
bec4a205ec | ||
|
|
a2d3a5aab0 | ||
|
|
9bc3a8f241 | ||
|
|
8f64656984 | ||
|
|
6f3153d703 | ||
|
|
80878e2e53 | ||
|
|
66ae567b25 | ||
|
|
413d852012 | ||
|
|
8b03550a1e | ||
|
|
6329549938 | ||
|
|
6f9cc57e70 | ||
|
|
3d85c66b02 | ||
|
|
fcbbbfe3d6 | ||
|
|
ea8bc7f419 | ||
|
|
161fa9c4e7 | ||
|
|
c2b134e7d6 | ||
|
|
9c1dc92d74 | ||
|
|
a674df662f | ||
|
|
c1c0168893 | ||
|
|
9c65596b1a | ||
|
|
503ed3276f | ||
|
|
14d87e3e11 | ||
|
|
fd09bc3e3e | ||
|
|
e0dcdf6b72 | ||
|
|
0c62321402 | ||
|
|
1bde1b862d | ||
|
|
8fc2dc2cd1 | ||
|
|
092b1bded5 | ||
|
|
b93415e8f1 | ||
|
|
28df01b880 | ||
|
|
2f419f0e08 | ||
|
|
d9eed14972 | ||
|
|
cc3d4c8231 | ||
|
|
38b4de87ad | ||
|
|
0f13af2ea1 | ||
|
|
a96fa80ccc | ||
|
|
085c31d671 | ||
|
|
3676d66408 | ||
|
|
addedf7231 | ||
|
|
562e4c28d2 | ||
|
|
1e0e1a2b64 | ||
|
|
ea96c3ef66 | ||
|
|
cca036c4a8 | ||
|
|
3c9902d93e | ||
|
|
e5511fd0a7 | ||
|
|
afdb76c929 | ||
|
|
b44abcd481 | ||
|
|
c3282bfa6c | ||
|
|
367db72c99 | ||
|
|
4f0b0cb8ce | ||
|
|
d68339a96a | ||
|
|
6021c7b192 | ||
|
|
d4bab8709b | ||
|
|
2f59918c74 | ||
|
|
de1a7a0933 | ||
|
|
e9742c662b | ||
|
|
e81ce68e8c | ||
|
|
c98e4b25b3 | ||
|
|
c4d8ded269 | ||
|
|
35a2690d75 | ||
|
|
ca6631fdda | ||
|
|
b28f258463 | ||
|
|
b90cda1f3f | ||
|
|
ca2fd41bb6 | ||
|
|
43643ba98f | ||
|
|
f847b9cfeb | ||
|
|
fbe475ef7d | ||
|
|
f95b082339 | ||
|
|
0a70a8a954 | ||
|
|
ed5e587cf1 | ||
|
|
1db70a0c46 | ||
|
|
69612ceb73 | ||
|
|
8d8f1e2401 | ||
|
|
b175e4aef7 | ||
|
|
8a4937bada | ||
|
|
b5b15a5990 | ||
|
|
3aef1be0e7 | ||
|
|
77361fb8a0 | ||
|
|
3a9be680a4 | ||
|
|
acfb5c177d | ||
|
|
2b40c7ce11 | ||
|
|
08e9a114a2 | ||
|
|
1f7090135b | ||
|
|
1412eb2697 | ||
|
|
dab5999621 | ||
|
|
906c7b4783 | ||
|
|
e78af393de | ||
|
|
72c8897d13 | ||
|
|
9ca1791b43 | ||
|
|
6e8fe39cc7 | ||
|
|
6446add9cd | ||
|
|
ebacf88b14 | ||
|
|
a8114ae122 | ||
|
|
44838f8973 | ||
|
|
ad8811282b | ||
|
|
181b776f0c | ||
|
|
c0d51dd2eb | ||
|
|
99a891b8a1 | ||
|
|
23725cf42c | ||
|
|
9a36dcd33d | ||
|
|
d539b0b5fe | ||
|
|
37e65614a0 | ||
|
|
88d3ad51b0 | ||
|
|
2094a2f466 | ||
|
|
74c43032b3 | ||
|
|
4f07c43976 | ||
|
|
726f7b8b11 | ||
|
|
5624a66bbb | ||
|
|
7484feceb5 | ||
|
|
d033509359 | ||
|
|
62c6422724 | ||
|
|
df0808d5bb | ||
|
|
4493e968da | ||
|
|
59bbc27268 | ||
|
|
b1fd927acb | ||
|
|
b0d0cdbd7d | ||
|
|
8dbd64121f | ||
|
|
72b3508911 | ||
|
|
8d16ee9dd5 | ||
|
|
cad5df1e9f | ||
|
|
e9b06f1022 | ||
|
|
7307deb3a9 | ||
|
|
f6959ba09e | ||
|
|
2693a8cd7d | ||
|
|
30e8289239 | ||
|
|
b62a7ace5c | ||
|
|
67bdd433a9 | ||
|
|
6150be2324 | ||
|
|
694ff934af | ||
|
|
2dd010dc04 | ||
|
|
26dcecebdb | ||
|
|
d97ab9be23 | ||
|
|
995f7e89d1 | ||
|
|
995f61ace4 | ||
|
|
b9d19d3358 | ||
|
|
ffc3a42405 | ||
|
|
8a10511105 | ||
|
|
9f84deeb56 | ||
|
|
dcaea50b8f | ||
|
|
c790ccca5a | ||
|
|
edc40f1792 | ||
|
|
eb9ed665f3 | ||
|
|
d4370a0878 | ||
|
|
a9e11d6546 | ||
|
|
649ce73047 | ||
|
|
3265f3f63a | ||
|
|
c3da6febbd | ||
|
|
c5b64b4ad4 | ||
|
|
44d30ad127 | ||
|
|
94270ff988 | ||
|
|
2deb379c06 | ||
|
|
09e0d668a6 | ||
|
|
80bd855329 | ||
|
|
567de6ba39 | ||
|
|
48de739506 | ||
|
|
3adaf23aab | ||
|
|
e71413123e | ||
|
|
51e96a2d8b | ||
|
|
38fd245767 | ||
|
|
20712d3fcc | ||
|
|
8cbf4f815e | ||
|
|
5ea3610d4a | ||
|
|
9deb7f6ba5 | ||
|
|
7ab6ff77ad | ||
|
|
2563e2b717 | ||
|
|
2e05f7f7ec | ||
|
|
01c5147079 | ||
|
|
71a506a28a | ||
|
|
6eef54595f | ||
|
|
79f772200a | ||
|
|
78ab1a7bba | ||
|
|
61822d48aa | ||
|
|
e7efc2709a | ||
|
|
0fbca815b4 | ||
|
|
1698a19cf6 | ||
|
|
7b5b5c2f39 | ||
|
|
2a68121685 | ||
|
|
380d5620e6 | ||
|
|
aae17041ef | ||
|
|
1d7cf5bb8c | ||
|
|
8696a4363a | ||
|
|
59c240bc9b | ||
|
|
d751b05cec | ||
|
|
843af31958 | ||
|
|
5aea537ab9 | ||
|
|
b734ecf02f | ||
|
|
5b52c384d6 | ||
|
|
2cba0a50f3 | ||
|
|
b354cf68b8 | ||
|
|
a9264d71c6 | ||
|
|
e0873f6c14 | ||
|
|
b8ddbcf62b | ||
|
|
bd09bed662 | ||
|
|
1ee4015aa8 | ||
|
|
a8d787bd66 | ||
|
|
e77bcf6910 | ||
|
|
2bc8f79e0f | ||
|
|
e58be1b128 | ||
|
|
ee180f6cf0 | ||
|
|
ce0b97a8f0 | ||
|
|
cf8d17a6ab | ||
|
|
e6bd088984 | ||
|
|
9b3c3b6e7a | ||
|
|
dc5bd8ea59 | ||
|
|
121b6c2ecb | ||
|
|
57d28e4f86 | ||
|
|
d84b72609d | ||
|
|
ef98be1192 | ||
|
|
3b9dedbc86 | ||
|
|
aa8908c52f | ||
|
|
3d1ffced57 | ||
|
|
f37f69f160 | ||
|
|
fac3bde2c8 | ||
|
|
9125a4c451 | ||
|
|
bed47a4ab4 | ||
|
|
2de887c2ff | ||
|
|
fdf2c1b0d0 | ||
|
|
7f78b9bf56 | ||
|
|
d6f53b2582 | ||
|
|
848110bc33 | ||
|
|
eb4cdc5026 | ||
|
|
3d673c1f02 | ||
|
|
a48b4c4f8d | ||
|
|
ba7fdb580d | ||
|
|
9e5ff89ef3 | ||
|
|
0d5e4b40d0 | ||
|
|
142b9e667d | ||
|
|
f3b76d958d | ||
|
|
87d6df5204 | ||
|
|
c7193fa6fe | ||
|
|
645c24289e | ||
|
|
e52a5be16e | ||
|
|
7e37b61a05 | ||
|
|
cbd353fbb8 | ||
|
|
4c274223cf | ||
|
|
65e4e9f428 | ||
|
|
e6820ed169 | ||
|
|
c3cb0f2371 | ||
|
|
31f1ceea9f | ||
|
|
94afe54741 | ||
|
|
080f161c37 | ||
|
|
5ce35e3e60 | ||
|
|
6d0edcf58a | ||
|
|
7033836e01 | ||
|
|
b7409d98ff | ||
|
|
b6d1bb1fa7 | ||
|
|
4558a7d8d0 | ||
|
|
22c2625ace | ||
|
|
4de8ba489d | ||
|
|
65ae92859c | ||
|
|
d355270c2d | ||
|
|
ced7cc6d60 | ||
|
|
d54cc14ca2 | ||
|
|
98a57f4fac | ||
|
|
40ca71b10b | ||
|
|
e7e58cdd71 | ||
|
|
1dcf9de34c | ||
|
|
fcb1d8dc72 | ||
|
|
5fa7e1c31b | ||
|
|
6e3c258edb | ||
|
|
6be5421c8a | ||
|
|
76655ce2bb | ||
|
|
3e1738dcec | ||
|
|
ec8dec74a6 | ||
|
|
838d25890b | ||
|
|
4a6d3a5104 | ||
|
|
b688cdbc40 | ||
|
|
09de918198 | ||
|
|
3e2bb85f58 |
+8
-1
@@ -1,12 +1,19 @@
|
||||
lexor_keyword.cc
|
||||
parse.h
|
||||
parse.cc
|
||||
parse.cc.output
|
||||
syn-rules.cc
|
||||
syn-rules.cc.output
|
||||
lexor.cc
|
||||
ivl
|
||||
ivl.exp
|
||||
dep
|
||||
configure
|
||||
Makefile
|
||||
verilog
|
||||
check
|
||||
check.cc
|
||||
config.status
|
||||
config.log
|
||||
config.cache
|
||||
config.h
|
||||
dosify
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright (c) 2000 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
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: Attrib.cc,v 1.2 2001/07/25 03:10:48 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# include "Attrib.h"
|
||||
# include <assert.h>
|
||||
|
||||
Attrib::Attrib()
|
||||
{
|
||||
nlist_ = 0;
|
||||
list_ = 0;
|
||||
}
|
||||
|
||||
Attrib::~Attrib()
|
||||
{
|
||||
delete[] list_;
|
||||
}
|
||||
|
||||
void Attrib::set_attributes(const map<string,string>&attr)
|
||||
{
|
||||
assert(list_ == 0);
|
||||
|
||||
nlist_ = attr.size();
|
||||
list_ = new cell_[nlist_];
|
||||
|
||||
map<string,string>::const_iterator idx;
|
||||
unsigned jdx;
|
||||
for (idx = attr.begin(), jdx = 0 ; idx != attr.end() ; idx ++, jdx++) {
|
||||
struct cell_*tmp = list_ + jdx;
|
||||
tmp->key = (*idx).first;
|
||||
tmp->val = (*idx).second;
|
||||
}
|
||||
}
|
||||
|
||||
string Attrib::attribute(const string&key) const
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < nlist_ ; idx += 1) {
|
||||
|
||||
if (key == list_[idx].key)
|
||||
return list_[idx].val;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
void Attrib::attribute(const string&key, const string&value)
|
||||
{
|
||||
unsigned idx;
|
||||
|
||||
for (idx = 0 ; idx < nlist_ ; idx += 1) {
|
||||
if (key == list_[idx].key) {
|
||||
list_[idx].val = value;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
struct cell_*tmp = new struct cell_[nlist_+1];
|
||||
for (idx = 0 ; idx < nlist_ ; idx += 1)
|
||||
tmp[idx] = list_[idx];
|
||||
|
||||
tmp[nlist_].key = key;
|
||||
tmp[nlist_].val = value;
|
||||
|
||||
nlist_ += 1;
|
||||
delete[]list_;
|
||||
list_ = tmp;
|
||||
}
|
||||
|
||||
bool Attrib::has_compat_attributes(const Attrib&that) const
|
||||
{
|
||||
unsigned idx;
|
||||
|
||||
for (idx = 0 ; idx < that.nlist_ ; idx += 1) {
|
||||
|
||||
string tmp = attribute(that.list_[idx].key);
|
||||
if (tmp != that.list_[idx].val)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned Attrib::size() const
|
||||
{
|
||||
return nlist_;
|
||||
}
|
||||
|
||||
string Attrib::key(unsigned idx) const
|
||||
{
|
||||
assert(idx < nlist_);
|
||||
return list_[idx].key;
|
||||
}
|
||||
|
||||
string Attrib::value(unsigned idx) const
|
||||
{
|
||||
assert(idx < nlist_);
|
||||
return list_[idx].val;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* $Log: Attrib.cc,v $
|
||||
* Revision 1.2 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.1 2000/12/04 17:37:03 steve
|
||||
* Add Attrib class for holding NetObj attributes.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
#ifndef __Attrib_H
|
||||
#define __Attrib_H
|
||||
/*
|
||||
* Copyright (c) 2000 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
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: Attrib.h,v 1.1 2000/12/04 17:37:03 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <string>
|
||||
# include <map>
|
||||
|
||||
/*
|
||||
* This class keeps a map of key/value pairs. The map can be set from
|
||||
* an STL map, or by setting individual mappings.
|
||||
*/
|
||||
class Attrib {
|
||||
|
||||
public:
|
||||
Attrib();
|
||||
~Attrib();
|
||||
|
||||
void set_attributes(const map<string,string>&attr);
|
||||
string attribute(const string&key) const;
|
||||
void attribute(const string&key, const string&value);
|
||||
bool has_compat_attributes(const Attrib&that) const;
|
||||
|
||||
|
||||
/* Provide a means of iterating over the entries in the map. */
|
||||
unsigned size() const;
|
||||
string key(unsigned idx) const;
|
||||
string value(unsigned idx) const;
|
||||
|
||||
private:
|
||||
struct cell_ {
|
||||
string key;
|
||||
string val;
|
||||
};
|
||||
|
||||
unsigned nlist_;
|
||||
struct cell_*list_;
|
||||
|
||||
private: // not implemented
|
||||
Attrib(const Attrib&);
|
||||
Attrib& operator= (const Attrib&);
|
||||
};
|
||||
|
||||
/*
|
||||
* $Log: Attrib.h,v $
|
||||
* Revision 1.1 2000/12/04 17:37:03 steve
|
||||
* Add Attrib class for holding NetObj attributes.
|
||||
*
|
||||
*/
|
||||
#endif
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (c) 2000 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
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: LineInfo.cc,v 1.2 2001/07/25 03:10:48 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# include "LineInfo.h"
|
||||
# include <cstdio>
|
||||
|
||||
LineInfo::~LineInfo()
|
||||
{
|
||||
}
|
||||
|
||||
string LineInfo::get_line() const
|
||||
{
|
||||
char buf[8];
|
||||
sprintf(buf, "%u", lineno_);
|
||||
return string(file_? file_ : "") + ":" + buf;
|
||||
}
|
||||
|
||||
void LineInfo::set_line(const LineInfo&that)
|
||||
{
|
||||
file_ = that.file_;
|
||||
lineno_ = that.lineno_;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: LineInfo.cc,v $
|
||||
* Revision 1.2 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.1 2000/11/30 17:31:42 steve
|
||||
* Change LineInfo to store const C strings.
|
||||
*
|
||||
*/
|
||||
|
||||
+23
-35
@@ -18,59 +18,47 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: LineInfo.h,v 1.3 1999/02/15 02:06:15 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: LineInfo.h,v 1.5 2000/11/30 17:31:42 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <cstdio>
|
||||
# include <string>
|
||||
|
||||
/*
|
||||
* This class holds line information for an internal object.
|
||||
*
|
||||
* Note that the file names are C-style strings that are allocated by
|
||||
* the lexor (which parses the line directives) and are never
|
||||
* deallocated. We can therefore safely store the pointer and never
|
||||
* delete the string, even if LineInfo objects are destroyed.
|
||||
*/
|
||||
|
||||
class LineInfo {
|
||||
public:
|
||||
LineInfo() : lineno_(0) { }
|
||||
LineInfo() : file_(0), lineno_(0) { }
|
||||
~LineInfo();
|
||||
|
||||
string get_line() const
|
||||
{ char buf[8];
|
||||
sprintf(buf, "%u", lineno_);
|
||||
return file_ + ":" + buf;
|
||||
}
|
||||
string get_line() const;
|
||||
|
||||
void set_line(const LineInfo&that)
|
||||
{ file_ = that.file_;
|
||||
lineno_ = that.lineno_;
|
||||
}
|
||||
void set_line(const LineInfo&that);
|
||||
|
||||
void set_file(const string&f) { file_ = f; }
|
||||
void set_file(const char*f) { file_ = f; }
|
||||
void set_lineno(unsigned n) { lineno_ = n; }
|
||||
|
||||
private:
|
||||
string file_;
|
||||
const char* file_;
|
||||
unsigned lineno_;
|
||||
};
|
||||
|
||||
/*
|
||||
* $Log: LineInfo.h,v $
|
||||
* Revision 1.5 2000/11/30 17:31:42 steve
|
||||
* Change LineInfo to store const C strings.
|
||||
*
|
||||
* Revision 1.4 2000/02/23 02:56:53 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.3 1999/02/15 02:06:15 steve
|
||||
* Elaborate gate ranges.
|
||||
*
|
||||
* Revision 1.2 1999/02/01 00:26:48 steve
|
||||
* Carry some line info to the netlist,
|
||||
* Dump line numbers for processes.
|
||||
* Elaborate prints errors about port vector
|
||||
* width mismatch
|
||||
* Emit better handles null statements.
|
||||
*
|
||||
* Revision 1.1 1999/01/25 05:45:56 steve
|
||||
* Add the LineInfo class to carry the source file
|
||||
* location of things. PGate, Statement and PProcess.
|
||||
*
|
||||
* elaborate handles module parameter mismatches,
|
||||
* missing or incorrect lvalues for procedural
|
||||
* assignment, and errors are propogated to the
|
||||
* top of the elaboration call tree.
|
||||
*
|
||||
* Attach line numbers to processes, gates and
|
||||
* assignment statements.
|
||||
*
|
||||
*/
|
||||
#endif
|
||||
|
||||
+153
-50
@@ -3,9 +3,7 @@
|
||||
# and/or modify it in source code form under the terms of the GNU
|
||||
# Library General Public License as published by the Free Software
|
||||
# Foundation; either version 2 of the License, or (at your option)
|
||||
# any later version. In order to redistribute the software in
|
||||
# binary form, you will need a Picture Elements Binary Software
|
||||
# License.
|
||||
# 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
|
||||
@@ -18,126 +16,231 @@
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.30 1999/11/29 17:02:21 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.103 2001/08/10 00:40:00 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
|
||||
VERSION = 0.0
|
||||
VERSION = 0.5
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
srcdir = @srcdir@
|
||||
|
||||
SUBDIRS = @subdirs@
|
||||
|
||||
VPATH = $(srcdir)
|
||||
|
||||
bindir = $(exec_prefix)/bin
|
||||
libdir = $(exec_prefix)/lib
|
||||
mandir = @mandir@
|
||||
bindir = @bindir@
|
||||
libdir = @libdir@
|
||||
includedir = $(prefix)/include
|
||||
|
||||
dllib=@DLLIB@
|
||||
rdynamic=@rdynamic@
|
||||
|
||||
CC = @CC@
|
||||
CXX = @CXX@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
STRIP = @STRIP@
|
||||
|
||||
CPPFLAGS = @CPPFLAGS@ @DEFS@
|
||||
CXXFLAGS = @CXXFLAGS@ -I$(srcdir)
|
||||
CXXFLAGS = @CXXFLAGS@ -I. -I$(srcdir)
|
||||
PICFLAGS = @PICFLAG@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
|
||||
all: ivl verilog
|
||||
cd vpi ; $(MAKE) all
|
||||
# The TARGETS variable lists the target modules that can be build and
|
||||
# installed. Some of them depend on external things, so are only
|
||||
# compiled if the prerequisites are installed.
|
||||
TARGETS = tgt-null
|
||||
ifeq ('@HAVE_IPAL@','yes')
|
||||
TARGETS += tgt-pal
|
||||
endif
|
||||
|
||||
|
||||
all: ivl@EXEEXT@ libvpi.a
|
||||
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) all); done
|
||||
cd vvm ; $(MAKE) all
|
||||
cd vpi ; $(MAKE) all
|
||||
cd ivlpp ; $(MAKE) all
|
||||
cd driver ; $(MAKE) all
|
||||
cd tgt-verilog ; $(MAKE) all
|
||||
cd tgt-stub ; $(MAKE) all
|
||||
for tgt in $(TARGETS); do (cd $$tgt ; $(MAKE) all); done
|
||||
|
||||
# In the windows world, the installer will need a dosify program to
|
||||
# dosify text files.
|
||||
ifeq (@WIN32@,yes)
|
||||
all: dosify.exe
|
||||
dosify.exe: dosify.c
|
||||
$(CC) -o dosify.exe dosify.c
|
||||
endif
|
||||
|
||||
# This rule rules the compiler in the trivial hello.vl program to make
|
||||
# sure the basics were compiled properly.
|
||||
check: all
|
||||
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) check); done
|
||||
driver/iverilog -Ccheck.conf -ocheck -tvvm-check -B./ivlpp examples/hello.vl
|
||||
$(CXX) -o check $(rdynamic) -fno-exceptions -I$(srcdir) -I$(srcdir)/vvm -I$(srcdir)/vpip -Lvvm -Lvpip check.cc -lvvm -lvpip $(dllib)
|
||||
./check | grep 'Hello, World'
|
||||
|
||||
clean:
|
||||
rm -f *.o parse.cc parse.cc.output parse.h dep/*.d lexor.cc verilog
|
||||
cd vpi ; $(MAKE) clean
|
||||
rm -f *.o parse.cc parse.cc.output parse.h dep/*.d lexor.cc lexor_keyword.cc ivl@EXEEXT@ libivl.a libvpi.a
|
||||
cd vvm ; $(MAKE) clean
|
||||
cd vpi ; $(MAKE) clean
|
||||
cd driver ; $(MAKE) clean
|
||||
cd ivlpp ; $(MAKE) clean
|
||||
cd tgt-verilog ; $(MAKE) clean
|
||||
cd tgt-stub ; $(MAKE) clean
|
||||
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) clean); done
|
||||
for tgt in $(TARGETS); do (cd $$tgt ; $(MAKE) clean); done
|
||||
|
||||
distclean: clean
|
||||
rm -f vpi/Makefile
|
||||
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) distclean); done
|
||||
for tgt in $(TARGETS); do (cd $$tgt ; $(MAKE) distclean); done
|
||||
rm -f vvm/Makefile
|
||||
rm -f vpi/Makefile
|
||||
rm -f ivlpp/Makefile
|
||||
rm -f driver/Makefile
|
||||
rm -f config.status config.cache config.log
|
||||
rm -f Makefile
|
||||
|
||||
TT = t-null.o t-verilog.o t-vvm.o t-xnf.o
|
||||
FF = nobufz.o nodangle.o propinit.o sigfold.o synth.o xnfio.o xnfsyn.o
|
||||
TT = t-dll.o t-dll-api.o t-dll-expr.o t-dll-proc.o t-vvm.o t-xnf.o
|
||||
FF = nodangle.o synth.o syn-rules.o xnfio.o
|
||||
|
||||
O = main.o cprop.o design_dump.o dup_expr.o elaborate.o elab_expr.o \
|
||||
elab_net.o emit.o eval.o eval_tree.o expr_synth.o functor.o \
|
||||
lexor.o lexor_keyword.o mangle.o netlist.o pad_to_width.o \
|
||||
elab_lval.o elab_net.o elab_anet.o elab_pexpr.o elab_scope.o \
|
||||
elab_sig.o emit.o eval.o eval_rconst.o \
|
||||
eval_tree.o expr_synth.o functor.o lexor.o lexor_keyword.o link_const.o \
|
||||
mangle.o netlist.o netmisc.o net_assign.o \
|
||||
net_design.o net_event.o net_force.o net_link.o net_modulo.o net_proc.o \
|
||||
net_scope.o net_udp.o pad_to_width.o \
|
||||
parse.o parse_misc.o pform.o pform_dump.o \
|
||||
set_width.o \
|
||||
verinum.o verireal.o target.o targets.o Module.o PDelays.o PExpr.o PGate.o \
|
||||
verinum.o verireal.o target.o targets.o util.o \
|
||||
Attrib.o LineInfo.o Module.o PDelays.o PEvent.o \
|
||||
PExpr.o PGate.o \
|
||||
PTask.o PFunction.o PWire.o Statement.o \
|
||||
$(FF) $(TT)
|
||||
|
||||
Makefile: Makefile.in config.status
|
||||
Makefile: Makefile.in config.h.in config.status
|
||||
./config.status
|
||||
|
||||
# Make the actual verilog program from the script template. This
|
||||
# simply invloves editing the substitution strings in the script into
|
||||
# the configured copy.
|
||||
tmp1 = bindir
|
||||
tmp2 = libdir
|
||||
tmp3 = includedir
|
||||
tmp4 = CXX
|
||||
verilog: $(srcdir)/verilog.sh
|
||||
sed -e 's;@$(tmp1)@;@bindir@;' \
|
||||
-e 's;@$(tmp2)@;@libdir@;' \
|
||||
-e 's;@$(tmp3)@;@includedir@;' \
|
||||
-e 's;@$(tmp4)@;@CXX@;' < $< > $@
|
||||
|
||||
ivl: $O
|
||||
$(CXX) $(CXXFLAGS) -o ivl $O
|
||||
libvpi.a: vpithunk.o
|
||||
rm -f $@
|
||||
ar cvq $@ vpithunk.o
|
||||
|
||||
%.o dep/%.d: %.cc
|
||||
# The vpithunk.c file (that makes up the libvpi.a library) needs to
|
||||
# be make with PIC flags, because shared objects load it.
|
||||
vpithunk.o: vpithunk.c
|
||||
@[ -d dep ] || mkdir dep
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) $(PICFLAGS) -MD -c $< -o $*.o
|
||||
mv $*.d dep/$*.d
|
||||
|
||||
|
||||
ifeq (@WIN32@,yes)
|
||||
ivl@EXEEXT@: $O ivl.def
|
||||
dlltool --dllname ivl@EXEEXT@ --def ivl.def \
|
||||
--output-lib libivl.a --output-exp ivl.exp
|
||||
# $(CXX) -o ivl@EXEEXT@ -Wl,--base-file,ivl.base ivl.exp $O $(dllib)
|
||||
# dlltool --dllname ivl@EXEEXT@ --base-file ivl.base \
|
||||
# --output-exp ivl.exp --def ivl.def
|
||||
$(CXX) -o ivl@EXEEXT@ ivl.exp $O $(dllib) @EXTRALIBS@
|
||||
else
|
||||
ivl@EXEEXT@: $O
|
||||
$(CXX) $(CXXFLAGS) $(rdynamic) $(LDFLAGS) -o ivl@EXEEXT@ $O $(dllib)
|
||||
endif
|
||||
|
||||
|
||||
%.o: %.cc
|
||||
@[ -d dep ] || mkdir dep
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -MD -c $< -o $*.o
|
||||
mv $*.d dep/$*.d
|
||||
|
||||
|
||||
lexor.o dep/lexor.d: lexor.cc parse.h
|
||||
lexor.o: lexor.cc parse.h
|
||||
|
||||
parse.o dep/parse.d: parse.cc
|
||||
parse.o: parse.cc
|
||||
|
||||
parse.h parse.cc: $(srcdir)/parse.y
|
||||
bison --verbose -t -p VL -d $(srcdir)/parse.y -o parse.cc
|
||||
bison --verbose -t -p VL -d -o parse.cc $(srcdir)/parse.y
|
||||
mv parse.cc.h parse.h
|
||||
|
||||
syn-rules.cc: $(srcdir)/syn-rules.y
|
||||
bison --verbose -p syn_ -o syn-rules.cc $(srcdir)/syn-rules.y
|
||||
|
||||
lexor.cc: $(srcdir)/lexor.lex
|
||||
flex -PVL -s -olexor.cc $(srcdir)/lexor.lex
|
||||
|
||||
install: all installdirs $(bindir)/verilog $(bindir)/ivl $(mandir)/man1/verilog.1
|
||||
cd vpi ; $(MAKE) install
|
||||
lexor_keyword.o: lexor_keyword.cc
|
||||
|
||||
lexor_keyword.cc: lexor_keyword.gperf
|
||||
gperf -o -i 7 -C -k 1-3,$$ -L ANSI-C -H keyword_hash -N check_identifier -t $(srcdir)/lexor_keyword.gperf > lexor_keyword.cc || (rm -f lexor_keyword.cc ; false)
|
||||
|
||||
ifeq (@WIN32@,yes)
|
||||
WIN32_INSTALL = $(prefix)/hello.vl $(prefix)/sqrt.vl $(prefix)/QUICK_START.txt
|
||||
endif
|
||||
|
||||
install: all installdirs $(libdir)/ivl/ivl@EXEEXT@ $(libdir)/ivl/iverilog.conf $(includedir)/ivl_target.h $(includedir)/vpi_user.h $(libdir)/libvpi.a $(WIN32_INSTALL)
|
||||
cd vvm ; $(MAKE) install
|
||||
cd vpi ; $(MAKE) install
|
||||
cd ivlpp ; $(MAKE) install
|
||||
cd driver ; $(MAKE) install
|
||||
for tgt in $(SUBDIRS); do (cd $$tgt ; $(MAKE) install); done
|
||||
for tgt in $(TARGETS); do (cd $$tgt ; $(MAKE) install); done
|
||||
|
||||
$(bindir)/verilog: ./verilog
|
||||
$(INSTALL_PROGRAM) ./verilog $(bindir)/verilog
|
||||
$(libdir)/libvpi.a : ./libvpi.a
|
||||
$(INSTALL_DATA) libvpi.a $(libdir)/libvpi.a
|
||||
|
||||
$(bindir)/ivl: ivl
|
||||
$(INSTALL_PROGRAM) ./ivl $(bindir)/ivl
|
||||
$(STRIP) $(bindir)/ivl
|
||||
$(libdir)/ivl/ivl@EXEEXT@: ./ivl@EXEEXT@
|
||||
$(INSTALL_PROGRAM) ./ivl@EXEEXT@ $(libdir)/ivl/ivl@EXEEXT@
|
||||
$(STRIP) $(libdir)/ivl/ivl@EXEEXT@
|
||||
|
||||
$(mandir)/man1/verilog.1: $(srcdir)/verilog.1
|
||||
$(INSTALL_DATA) $(srcdir)/verilog.1 $(mandir)/man1/verilog.1
|
||||
$(libdir)/ivl/iverilog.conf: $(srcdir)/iverilog.conf
|
||||
$(INSTALL_DATA) $(srcdir)/iverilog.conf $(libdir)/ivl/iverilog.conf
|
||||
|
||||
$(includedir)/ivl_target.h: $(srcdir)/ivl_target.h
|
||||
$(INSTALL_DATA) $(srcdir)/ivl_target.h $(includedir)/ivl_target.h
|
||||
|
||||
$(includedir)/vpi_user.h: $(srcdir)/vpi_user.h
|
||||
$(INSTALL_DATA) $(srcdir)/vpi_user.h $(includedir)/vpi_user.h
|
||||
|
||||
# In windows installations, put a few examples and the quick_start
|
||||
# into the destination directory.
|
||||
ifeq (@WIN32@,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)/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 $(bindir) $(mandir)/man1
|
||||
$(srcdir)/mkinstalldirs $(bindir) $(includedir) $(libdir)/ivl
|
||||
|
||||
|
||||
uninstall:
|
||||
rm -f $(bindir)/ivl
|
||||
rm -f $(libdir)/ivl/ivl@EXEEXT@
|
||||
rm -f $(bindir)/verilog
|
||||
rm -f $(mandir)/man1/verilog.1
|
||||
rm -f $(bindir)/gverilog@EXEEXT@
|
||||
rm -f $(includedir)/ivl_target.h
|
||||
rm -f $(includedir)/vpi_user.h
|
||||
cd driver ; $(MAKE) uninstall
|
||||
cd vpi ; $(MAKE) uninstall
|
||||
cd vvm ; $(MAKE) uninstall
|
||||
cd ivlpp ; $(MAKE) uninstall
|
||||
for tgt in $(SUBDIRS); do (cd $$tgt ; $(MAKE) uninstall); done
|
||||
for tgt in $(TARGETS); do (cd $$tgt ; $(MAKE) uninstall); done
|
||||
|
||||
|
||||
-include $(patsubst %.o, dep/%.d, $O)
|
||||
-include $(patsubst %.o, dep/%.d, vpithunk.o)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2000 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,26 +16,23 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: Module.cc,v 1.7 1999/09/17 02:06:25 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: Module.cc,v 1.15 2001/07/25 03:10:48 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# include "Module.h"
|
||||
# include "PGate.h"
|
||||
# include "PWire.h"
|
||||
# include <assert.h>
|
||||
|
||||
Module::Module(const string&name, const svector<Module::port_t*>*pp)
|
||||
: name_(name)
|
||||
{
|
||||
if (pp) {
|
||||
if (pp)
|
||||
ports_ = *pp;
|
||||
for (unsigned idx = 0 ; idx < ports_.count() ; idx += 1) {
|
||||
port_t*cur = ports_[idx];
|
||||
if (cur == 0)
|
||||
continue;
|
||||
for (unsigned jdx = 0 ; jdx < cur->wires.count() ; jdx += 1)
|
||||
add_wire(cur->wires[jdx]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Module::add_gate(PGate*gate)
|
||||
@@ -53,9 +50,14 @@ void Module::add_function(const string &name, PFunction *func)
|
||||
funcs_[name] = func;
|
||||
}
|
||||
|
||||
void Module::add_wire(PWire*wire)
|
||||
PWire* Module::add_wire(PWire*wire)
|
||||
{
|
||||
wires_.push_back(wire);
|
||||
PWire*&ep = wires_[wire->name()];
|
||||
if (ep) return ep;
|
||||
|
||||
assert(ep == 0);
|
||||
ep = wire;
|
||||
return wire;
|
||||
}
|
||||
|
||||
void Module::add_behavior(PProcess*b)
|
||||
@@ -68,10 +70,20 @@ unsigned Module::port_count() const
|
||||
return ports_.count();
|
||||
}
|
||||
|
||||
const svector<PWire*>& Module::get_port(unsigned idx) const
|
||||
/*
|
||||
* Return the array of PEIdent object that are at this port of the
|
||||
* module. If the port is internally unconnected, return an empty
|
||||
* array.
|
||||
*/
|
||||
const svector<PEIdent*>& Module::get_port(unsigned idx) const
|
||||
{
|
||||
assert(idx < ports_.count());
|
||||
return ports_[idx]->wires;
|
||||
static svector<PEIdent*> zero;
|
||||
|
||||
if (ports_[idx])
|
||||
return ports_[idx]->expr;
|
||||
else
|
||||
return zero;
|
||||
}
|
||||
|
||||
unsigned Module::find_port(const string&name) const
|
||||
@@ -85,22 +97,73 @@ unsigned Module::find_port(const string&name) const
|
||||
}
|
||||
|
||||
|
||||
PWire* Module::get_wire(const string&name)
|
||||
PWire* Module::get_wire(const string&name) const
|
||||
{
|
||||
for (list<PWire*>::iterator cur = wires_.begin()
|
||||
; cur != wires_.end()
|
||||
map<string,PWire*>::const_iterator obj = wires_.find(name);
|
||||
if (obj == wires_.end())
|
||||
return 0;
|
||||
else
|
||||
return (*obj).second;
|
||||
}
|
||||
|
||||
PGate* Module::get_gate(const string&name)
|
||||
{
|
||||
for (list<PGate*>::iterator cur = gates_.begin()
|
||||
; cur != gates_.end()
|
||||
; cur ++ ) {
|
||||
|
||||
if ((*cur)->name() == name)
|
||||
if ((*cur)->get_name() == name)
|
||||
return *cur;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const map<string,PWire*>& Module::get_wires() const
|
||||
{
|
||||
return wires_;
|
||||
}
|
||||
|
||||
const list<PGate*>& Module::get_gates() const
|
||||
{
|
||||
return gates_;
|
||||
}
|
||||
|
||||
const list<PProcess*>& Module::get_behaviors() const
|
||||
{
|
||||
return behaviors_;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* $Log: Module.cc,v $
|
||||
* Revision 1.15 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.14 2000/11/15 20:31:05 steve
|
||||
* Fix warning about temporaries.
|
||||
*
|
||||
* Revision 1.13 2000/11/05 06:05:59 steve
|
||||
* Handle connectsion to internally unconnected modules (PR#38)
|
||||
*
|
||||
* Revision 1.12 2000/05/16 04:05:15 steve
|
||||
* Module ports are really special PEIdent
|
||||
* expressions, because a name can be used
|
||||
* many places in the port list.
|
||||
*
|
||||
* Revision 1.11 2000/03/12 17:09:40 steve
|
||||
* Support localparam.
|
||||
*
|
||||
* Revision 1.10 2000/02/23 02:56:53 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.9 2000/01/09 20:37:57 steve
|
||||
* Careful with wires connected to multiple ports.
|
||||
*
|
||||
* Revision 1.8 1999/12/11 05:45:41 steve
|
||||
* Fix support for attaching attributes to primitive gates.
|
||||
*
|
||||
* Revision 1.7 1999/09/17 02:06:25 steve
|
||||
* Handle unconnected module ports.
|
||||
*
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __Module_H
|
||||
#define __Module_H
|
||||
/*
|
||||
* Copyright (c) 1998 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2000 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,15 +18,18 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: Module.h,v 1.10 1999/11/27 19:07:57 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: Module.h,v 1.21 2000/11/05 06:05:59 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <list>
|
||||
# include <map>
|
||||
# include "svector.h"
|
||||
# include "named.h"
|
||||
# include <string>
|
||||
class PEvent;
|
||||
class PExpr;
|
||||
class PEIdent;
|
||||
class PGate;
|
||||
class PTask;
|
||||
class PFunction;
|
||||
@@ -51,9 +54,7 @@ class Module {
|
||||
public:
|
||||
struct port_t {
|
||||
string name;
|
||||
svector<PWire*>wires;
|
||||
|
||||
port_t(int c=0) : wires(c) { }
|
||||
svector<PEIdent*> expr;
|
||||
};
|
||||
|
||||
public:
|
||||
@@ -64,6 +65,13 @@ class Module {
|
||||
module is elaborated. During parsing, I put the parameters
|
||||
into this map. */
|
||||
map<string,PExpr*>parameters;
|
||||
map<string,PExpr*>localparams;
|
||||
|
||||
/* The module also has defparam assignments which don't create
|
||||
new parameters within the module, but may be used to set
|
||||
values within this module (when instantiated) or in other
|
||||
instantiated modules. */
|
||||
map<string,PExpr*>defparms;
|
||||
|
||||
/* Parameters may be overridden at instantiation time;
|
||||
the overrides do not contain explicit parameter names,
|
||||
@@ -73,34 +81,54 @@ class Module {
|
||||
a parameter-index to its name. */
|
||||
list<string> param_names;
|
||||
|
||||
/* Keep a table of named events declared in the module. */
|
||||
map<string,PEvent*>events;
|
||||
|
||||
/* These are the timescale for this module. The default is
|
||||
set by the `timescale directive. */
|
||||
int time_unit, time_precision;
|
||||
|
||||
const string&get_name() const { return name_; }
|
||||
|
||||
void add_gate(PGate*gate);
|
||||
void add_wire(PWire*wire);
|
||||
|
||||
// The add_wire method adds a wire by name, but only if the
|
||||
// wire name doesn't already exist. Either way, the result is
|
||||
// the existing wire or the pointer passed in.
|
||||
PWire* add_wire(PWire*wire);
|
||||
|
||||
void add_behavior(PProcess*behave);
|
||||
void add_task(const string&name, PTask*def);
|
||||
void add_function(const string&name, PFunction*def);
|
||||
|
||||
unsigned port_count() const;
|
||||
const svector<PWire*>& get_port(unsigned idx) const;
|
||||
const svector<PEIdent*>& get_port(unsigned idx) const;
|
||||
unsigned find_port(const string&) const;
|
||||
|
||||
// Find a wire by name. This is used for connecting gates to
|
||||
// existing wires, etc.
|
||||
PWire* get_wire(const string&name);
|
||||
PWire* get_wire(const string&name) const;
|
||||
PGate* get_gate(const string&name);
|
||||
|
||||
const list<PWire*>& get_wires() const { return wires_; }
|
||||
const list<PGate*>& get_gates() const { return gates_; }
|
||||
const list<PProcess*>& get_behaviors() const { return behaviors_; }
|
||||
const map<string,PWire*>& get_wires() const;
|
||||
const list<PGate*>& get_gates() const;
|
||||
const list<PProcess*>& get_behaviors() const;
|
||||
|
||||
void dump(ostream&out) const;
|
||||
bool elaborate(Design*, NetScope*scope, svector<PExpr*>*overrides_) const;
|
||||
bool elaborate(Design*, NetScope*scope) const;
|
||||
|
||||
bool elaborate_scope(Design*, NetScope*scope) const;
|
||||
|
||||
bool elaborate_sig(Design*, NetScope*scope) const;
|
||||
|
||||
private:
|
||||
const string name_;
|
||||
|
||||
/* This is an array of port descriptors, which is in turn a
|
||||
named array of PEident pointers. */
|
||||
svector<port_t*> ports_;
|
||||
list<PWire*> wires_;
|
||||
|
||||
map<string,PWire*> wires_;
|
||||
list<PGate*> gates_;
|
||||
list<PProcess*> behaviors_;
|
||||
map<string,PTask*> tasks_;
|
||||
@@ -114,6 +142,45 @@ class Module {
|
||||
|
||||
/*
|
||||
* $Log: Module.h,v $
|
||||
* Revision 1.21 2000/11/05 06:05:59 steve
|
||||
* Handle connectsion to internally unconnected modules (PR#38)
|
||||
*
|
||||
* Revision 1.20 2000/07/22 22:09:03 steve
|
||||
* Parse and elaborate timescale to scopes.
|
||||
*
|
||||
* Revision 1.19 2000/05/16 04:05:15 steve
|
||||
* Module ports are really special PEIdent
|
||||
* expressions, because a name can be used
|
||||
* many places in the port list.
|
||||
*
|
||||
* Revision 1.18 2000/05/02 16:27:38 steve
|
||||
* Move signal elaboration to a seperate pass.
|
||||
*
|
||||
* Revision 1.17 2000/04/01 19:31:57 steve
|
||||
* Named events as far as the pform.
|
||||
*
|
||||
* Revision 1.16 2000/03/12 17:09:40 steve
|
||||
* Support localparam.
|
||||
*
|
||||
* Revision 1.15 2000/03/08 04:36:53 steve
|
||||
* Redesign the implementation of scopes and parameters.
|
||||
* I now generate the scopes and notice the parameters
|
||||
* in a separate pass over the pform. Once the scopes
|
||||
* are generated, I can process overrides and evalutate
|
||||
* paremeters before elaboration begins.
|
||||
*
|
||||
* Revision 1.14 2000/02/23 02:56:53 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.13 2000/01/09 20:37:57 steve
|
||||
* Careful with wires connected to multiple ports.
|
||||
*
|
||||
* Revision 1.12 2000/01/09 05:50:48 steve
|
||||
* Support named parameter override lists.
|
||||
*
|
||||
* Revision 1.11 1999/12/11 05:45:41 steve
|
||||
* Fix support for attaching attributes to primitive gates.
|
||||
*
|
||||
* Revision 1.10 1999/11/27 19:07:57 steve
|
||||
* Support the creation of scopes.
|
||||
*
|
||||
|
||||
+65
-19
@@ -16,10 +16,14 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: PDelays.cc,v 1.1 1999/09/04 19:11:46 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: PDelays.cc,v 1.5 2001/07/25 03:10:48 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# include <iostream>
|
||||
|
||||
# include "PDelays.h"
|
||||
# include "PExpr.h"
|
||||
# include "verinum.h"
|
||||
@@ -52,30 +56,56 @@ void PDelays::set_delays(const svector<PExpr*>*del)
|
||||
delay_[idx] = (*del)[idx];
|
||||
}
|
||||
|
||||
void PDelays::eval_delays(Design*des, const string&path,
|
||||
unsigned long&rise_time,
|
||||
unsigned long&fall_time,
|
||||
unsigned long&decay_time) const
|
||||
static unsigned long calculate_val(Design*des, const NetScope*scope,
|
||||
const PExpr*expr)
|
||||
{
|
||||
verinum*dv;
|
||||
assert(expr);
|
||||
unsigned long val;
|
||||
|
||||
int shift = scope->time_unit() - des->get_precision();
|
||||
|
||||
if (verireal*dr = expr->eval_rconst(des, scope)) {
|
||||
val = dr->as_long(shift);
|
||||
delete dr;
|
||||
|
||||
} else {
|
||||
verinum*dv = expr->eval_const(des, scope->name());
|
||||
if (dv == 0) {
|
||||
cerr << expr->get_line() << ": sorry: non-constant "
|
||||
<< "delays not supported here: " << *expr << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(dv);
|
||||
val = dv->as_ulong();
|
||||
val = des->scale_to_precision(val, scope);
|
||||
delete dv;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
void PDelays::eval_delays(Design*des, const string&path,
|
||||
unsigned long&rise_time,
|
||||
unsigned long&fall_time,
|
||||
unsigned long&decay_time) const
|
||||
{
|
||||
NetScope*scope = des->find_scope(path);
|
||||
assert(scope);
|
||||
|
||||
int shift = scope->time_unit() - des->get_precision();
|
||||
|
||||
|
||||
if (delay_[0]) {
|
||||
dv = delay_[0]->eval_const(des, path);
|
||||
assert(dv);
|
||||
rise_time = dv->as_ulong();
|
||||
delete dv;
|
||||
rise_time = calculate_val(des, scope, delay_[0]);
|
||||
|
||||
if (delay_[1]) {
|
||||
dv = delay_[1]->eval_const(des, path);
|
||||
assert(dv);
|
||||
fall_time = dv->as_ulong();
|
||||
delete dv;
|
||||
fall_time = calculate_val(des, scope, delay_[1]);
|
||||
|
||||
if (delay_[2]) {
|
||||
dv = delay_[2]->eval_const(des, path);
|
||||
assert(dv);
|
||||
decay_time = dv->as_ulong();
|
||||
delete dv;
|
||||
decay_time = calculate_val(des, scope, delay_[2]);
|
||||
|
||||
} else {
|
||||
if (rise_time < fall_time)
|
||||
decay_time = rise_time;
|
||||
@@ -96,6 +126,22 @@ void PDelays::eval_delays(Design*des, const string&path,
|
||||
|
||||
/*
|
||||
* $Log: PDelays.cc,v $
|
||||
* Revision 1.5 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.4 2001/01/20 02:15:50 steve
|
||||
* apologize for not supporting non-constant delays.
|
||||
*
|
||||
* Revision 1.3 2001/01/14 23:04:55 steve
|
||||
* Generalize the evaluation of floating point delays, and
|
||||
* get it working with delay assignment statements.
|
||||
*
|
||||
* Allow parameters to be referenced by hierarchical name.
|
||||
*
|
||||
* Revision 1.2 2000/02/23 02:56:53 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.1 1999/09/04 19:11:46 steve
|
||||
* Add support for delayed non-blocking assignments.
|
||||
*
|
||||
|
||||
@@ -18,15 +18,21 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: PDelays.h,v 1.1 1999/09/04 19:11:46 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: PDelays.h,v 1.3 2001/01/16 02:44:17 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "svector.h"
|
||||
# include <string>
|
||||
|
||||
#ifdef HAVE_IOSFWD
|
||||
# include <iosfwd>
|
||||
#else
|
||||
class ostream;
|
||||
#endif
|
||||
|
||||
class Design;
|
||||
class PExpr;
|
||||
class ostream;
|
||||
|
||||
/*
|
||||
* Various PForm objects can carry delays. These delays include rise,
|
||||
@@ -60,6 +66,12 @@ ostream& operator << (ostream&o, const PDelays&);
|
||||
|
||||
/*
|
||||
* $Log: PDelays.h,v $
|
||||
* Revision 1.3 2001/01/16 02:44:17 steve
|
||||
* Use the iosfwd header if available.
|
||||
*
|
||||
* Revision 1.2 2000/02/23 02:56:53 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.1 1999/09/04 19:11:46 steve
|
||||
* Add support for delayed non-blocking assignments.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) 200Stephen 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
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: PEvent.cc,v 1.2 2001/07/25 03:10:48 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# include "PEvent.h"
|
||||
|
||||
PEvent::PEvent(const string&n)
|
||||
: name_(n)
|
||||
{
|
||||
}
|
||||
|
||||
PEvent::~PEvent()
|
||||
{
|
||||
}
|
||||
|
||||
string PEvent::name() const
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: PEvent.cc,v $
|
||||
* Revision 1.2 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.1 2000/04/01 19:31:57 steve
|
||||
* Named events as far as the pform.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
#ifndef __PEvent_H
|
||||
#define __PEvent_H
|
||||
/*
|
||||
* Copyright (c) 2000 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
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: PEvent.h,v 1.4 2001/01/16 02:44:18 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "LineInfo.h"
|
||||
# include <string>
|
||||
|
||||
class Design;
|
||||
class NetScope;
|
||||
|
||||
/*
|
||||
* The PEvent class represents event objects. These are things that
|
||||
* are declared in Verilog as ``event foo;''
|
||||
*/
|
||||
class PEvent : public LineInfo {
|
||||
|
||||
public:
|
||||
explicit PEvent(const string&name);
|
||||
~PEvent();
|
||||
|
||||
string name() const;
|
||||
|
||||
void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
|
||||
private:
|
||||
string name_;
|
||||
|
||||
private: // not implemented
|
||||
PEvent(const PEvent&);
|
||||
PEvent& operator= (const PEvent&);
|
||||
};
|
||||
|
||||
/*
|
||||
* $Log: PEvent.h,v $
|
||||
* Revision 1.4 2001/01/16 02:44:18 steve
|
||||
* Use the iosfwd header if available.
|
||||
*
|
||||
* Revision 1.3 2000/04/09 17:44:30 steve
|
||||
* Catch event declarations during scope elaborate.
|
||||
*
|
||||
* Revision 1.2 2000/04/04 03:20:15 steve
|
||||
* Simulate named event trigger and waits.
|
||||
*
|
||||
* Revision 1.1 2000/04/01 19:31:57 steve
|
||||
* Named events as far as the pform.
|
||||
*
|
||||
*/
|
||||
#endif
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998 Stephen Williams <[email protected]>
|
||||
* Copyright (c) 1998-1999 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,14 +16,22 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: PExpr.cc,v 1.11 1999/10/31 04:11:27 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: PExpr.cc,v 1.24 2001/07/25 03:10:48 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# include <iostream>
|
||||
|
||||
# include "PExpr.h"
|
||||
# include "Module.h"
|
||||
# include <typeinfo>
|
||||
|
||||
PExpr::PExpr()
|
||||
{
|
||||
}
|
||||
|
||||
PExpr::~PExpr()
|
||||
{
|
||||
}
|
||||
@@ -41,16 +49,18 @@ bool PExpr::is_constant(Module*) const
|
||||
NetNet* PExpr::elaborate_net(Design*des, const string&path, unsigned,
|
||||
unsigned long,
|
||||
unsigned long,
|
||||
unsigned long) const
|
||||
unsigned long,
|
||||
Link::strength_t,
|
||||
Link::strength_t) const
|
||||
{
|
||||
cerr << "Don't know how to elaborate `" << *this
|
||||
<< "' as gates." << endl;
|
||||
cerr << get_line() << ": error: Unable to elaborate `"
|
||||
<< *this << "' as gates." << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetNet* PExpr::elaborate_lnet(Design*des, const string&path) const
|
||||
{
|
||||
cerr << get_line() << ": expression not valid in assign l-value: "
|
||||
cerr << get_line() << ": error: expression not valid in assign l-value: "
|
||||
<< *this << endl;
|
||||
return 0;
|
||||
}
|
||||
@@ -60,15 +70,25 @@ bool PEBinary::is_constant(Module*mod) const
|
||||
return left_->is_constant(mod) && right_->is_constant(mod);
|
||||
}
|
||||
|
||||
PECallFunction::PECallFunction(const string &n, const svector<PExpr *> &parms)
|
||||
PECallFunction::PECallFunction(const char*n, const svector<PExpr *> &parms)
|
||||
: name_(n), parms_(parms)
|
||||
{
|
||||
}
|
||||
|
||||
PECallFunction::PECallFunction(const char*n)
|
||||
: name_(n)
|
||||
{
|
||||
}
|
||||
|
||||
PECallFunction::~PECallFunction()
|
||||
{
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -83,14 +103,91 @@ PEConcat::~PEConcat()
|
||||
delete repeat_;
|
||||
}
|
||||
|
||||
PEEvent::PEEvent(PEEvent::edge_t t, PExpr*e)
|
||||
: type_(t), expr_(e)
|
||||
{
|
||||
}
|
||||
|
||||
PEEvent::~PEEvent()
|
||||
{
|
||||
}
|
||||
|
||||
PEEvent::edge_t PEEvent::type() const
|
||||
{
|
||||
return type_;
|
||||
}
|
||||
|
||||
PExpr* PEEvent::expr() const
|
||||
{
|
||||
return expr_;
|
||||
}
|
||||
|
||||
PEFNumber::PEFNumber(verireal*v)
|
||||
: value_(v)
|
||||
{
|
||||
}
|
||||
|
||||
PEFNumber::~PEFNumber()
|
||||
{
|
||||
delete value_;
|
||||
}
|
||||
|
||||
const verireal& PEFNumber::value() const
|
||||
{
|
||||
return *value_;
|
||||
}
|
||||
|
||||
bool PEFNumber::is_constant(Module*) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
PEIdent::PEIdent(const string&s)
|
||||
: text_(s), msb_(0), lsb_(0), idx_(0)
|
||||
{
|
||||
}
|
||||
|
||||
PEIdent::~PEIdent()
|
||||
{
|
||||
}
|
||||
|
||||
string PEIdent::name() const
|
||||
{
|
||||
return text_;
|
||||
}
|
||||
|
||||
/*
|
||||
* An identifier can be in a constant expresion if (and only if) it is
|
||||
* a parameter.
|
||||
*/
|
||||
bool PEIdent::is_constant(Module*mod) const
|
||||
{
|
||||
map<string,PExpr*>::const_iterator cur = mod->parameters.find(text_);
|
||||
return cur != mod->parameters.end();
|
||||
map<string,PExpr*>::const_iterator cur;
|
||||
if (mod == 0) return false;
|
||||
|
||||
cur = mod->parameters.find(text_);
|
||||
if (cur != mod->parameters.end()) return true;
|
||||
|
||||
cur = mod->localparams.find(text_);
|
||||
if (cur != mod->localparams.end()) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
PENumber::PENumber(verinum*vp)
|
||||
: value_(vp)
|
||||
{
|
||||
assert(vp);
|
||||
}
|
||||
|
||||
PENumber::~PENumber()
|
||||
{
|
||||
delete value_;
|
||||
}
|
||||
|
||||
const verinum& PENumber::value() const
|
||||
{
|
||||
return *value_;
|
||||
}
|
||||
|
||||
bool PENumber::is_the_same(const PExpr*that) const
|
||||
@@ -107,6 +204,20 @@ bool PENumber::is_constant(Module*) const
|
||||
return true;
|
||||
}
|
||||
|
||||
PEString::PEString(const string&s)
|
||||
: text_(s)
|
||||
{
|
||||
}
|
||||
|
||||
PEString::~PEString()
|
||||
{
|
||||
}
|
||||
|
||||
string PEString::value() const
|
||||
{
|
||||
return text_;
|
||||
}
|
||||
|
||||
bool PEString::is_constant(Module*) const
|
||||
{
|
||||
return true;
|
||||
@@ -121,13 +232,88 @@ PETernary::~PETernary()
|
||||
{
|
||||
}
|
||||
|
||||
bool PETernary::is_constant(Module*) const
|
||||
bool PETernary::is_constant(Module*m) const
|
||||
{
|
||||
return false;
|
||||
return expr_->is_constant(m)
|
||||
&& tru_->is_constant(m)
|
||||
&& fal_->is_constant(m);
|
||||
}
|
||||
|
||||
PEUnary::PEUnary(char op, PExpr*ex)
|
||||
: op_(op), expr_(ex)
|
||||
{
|
||||
}
|
||||
|
||||
PEUnary::~PEUnary()
|
||||
{
|
||||
}
|
||||
|
||||
bool PEUnary::is_constant(Module*m) const
|
||||
{
|
||||
return expr_->is_constant(m);
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: PExpr.cc,v $
|
||||
* Revision 1.24 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.23 2001/01/14 23:04:55 steve
|
||||
* Generalize the evaluation of floating point delays, and
|
||||
* get it working with delay assignment statements.
|
||||
*
|
||||
* Allow parameters to be referenced by hierarchical name.
|
||||
*
|
||||
* Revision 1.22 2001/01/12 04:31:27 steve
|
||||
* Handle error idents in constants not in any scope (PR#97)
|
||||
*
|
||||
* Revision 1.21 2000/12/16 19:03:30 steve
|
||||
* Evaluate <= and ?: in parameter expressions (PR#81)
|
||||
*
|
||||
* Revision 1.20 2000/12/10 22:01:35 steve
|
||||
* Support decimal constants in behavioral delays.
|
||||
*
|
||||
* Revision 1.19 2000/06/30 15:50:20 steve
|
||||
* Allow unary operators in constant expressions.
|
||||
*
|
||||
* Revision 1.18 2000/05/07 04:37:55 steve
|
||||
* Carry strength values from Verilog source to the
|
||||
* pform and netlist for gates.
|
||||
*
|
||||
* Change vvm constants to use the driver_t to drive
|
||||
* a constant value. This works better if there are
|
||||
* multiple drivers on a signal.
|
||||
*
|
||||
* Revision 1.17 2000/05/04 03:37:58 steve
|
||||
* Add infrastructure for system functions, move
|
||||
* $time to that structure and add $random.
|
||||
*
|
||||
* Revision 1.16 2000/04/12 04:23:57 steve
|
||||
* Named events really should be expressed with PEIdent
|
||||
* objects in the pform,
|
||||
*
|
||||
* Handle named events within the mix of net events
|
||||
* and edges. As a unified lot they get caught together.
|
||||
* wait statements are broken into more complex statements
|
||||
* that include a conditional.
|
||||
*
|
||||
* Do not generate NetPEvent or NetNEvent objects in
|
||||
* elaboration. NetEvent, NetEvWait and NetEvProbe
|
||||
* take over those functions in the netlist.
|
||||
*
|
||||
* Revision 1.15 2000/04/01 19:31:57 steve
|
||||
* Named events as far as the pform.
|
||||
*
|
||||
* Revision 1.14 2000/03/12 18:22:11 steve
|
||||
* Binary and unary operators in parameter expressions.
|
||||
*
|
||||
* Revision 1.13 2000/02/23 02:56:53 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.12 1999/12/31 17:38:37 steve
|
||||
* Standardize some of the error messages.
|
||||
*
|
||||
* Revision 1.11 1999/10/31 04:11:27 steve
|
||||
* Add to netlist links pin name and instance number,
|
||||
* and arrange in vvm for pin connections by name
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __PExpr_H
|
||||
#define __PExpr_H
|
||||
/*
|
||||
* Copyright (c) 1998-1999 Stephen Williams <[email protected]>
|
||||
* Copyright (c) 1998-2000 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,8 +18,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: PExpr.h,v 1.25 1999/11/21 00:13:08 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: PExpr.h,v 1.48 2001/01/14 23:04:55 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <string>
|
||||
@@ -32,6 +32,7 @@ class Design;
|
||||
class Module;
|
||||
class NetNet;
|
||||
class NetExpr;
|
||||
class NetScope;
|
||||
|
||||
/*
|
||||
* The PExpr class hierarchy supports the description of
|
||||
@@ -43,13 +44,21 @@ class NetExpr;
|
||||
*/
|
||||
|
||||
class PExpr : public LineInfo {
|
||||
|
||||
public:
|
||||
PExpr();
|
||||
virtual ~PExpr();
|
||||
|
||||
virtual void dump(ostream&) const;
|
||||
|
||||
// Procedural elaboration of the expression.
|
||||
virtual NetExpr*elaborate_expr(Design*des, const string&path) const;
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope) const;
|
||||
|
||||
// Elaborate expressions that are the r-value of parameter
|
||||
// assignments. This elaboration follows the restrictions of
|
||||
// constant expressions and supports later overriding and
|
||||
// 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.
|
||||
@@ -57,17 +66,33 @@ class PExpr : public LineInfo {
|
||||
unsigned lwidth,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay) const;
|
||||
unsigned long decay,
|
||||
Link::strength_t drive0 =Link::STRONG,
|
||||
Link::strength_t drive1 =Link::STRONG)
|
||||
const;
|
||||
|
||||
// This method elaborates the expression as NetNet objects. It
|
||||
// only allows regs suitable for procedural continuous assignments.
|
||||
virtual NetNet* elaborate_anet(Design*des, NetScope*scope) const;
|
||||
|
||||
// This method elaborates the expression as gates, but
|
||||
// restricted for use as l-values of continuous assignments.
|
||||
virtual NetNet* elaborate_lnet(Design*des, const string&path) const;
|
||||
|
||||
// Expressions that can be in the l-value of procedural
|
||||
// assignments can be elaborated with this method.
|
||||
virtual NetAssign_* elaborate_lval(Design*des, NetScope*scope) const;
|
||||
|
||||
// This attempts to evaluate a constant expression, and return
|
||||
// a verinum as a result. If the expression cannot be
|
||||
// evaluated, return 0.
|
||||
virtual verinum* eval_const(const Design*des, const string&path) const;
|
||||
|
||||
// This attempts to evaluate a constant expression as a
|
||||
// decimal floating point. This is used when calculating delay
|
||||
// constants.
|
||||
virtual verireal* eval_rconst(const Design*, const NetScope*) const;
|
||||
|
||||
// This method returns true if that expression is the same as
|
||||
// this expression. This method is used for comparing
|
||||
// expressions that must be structurally "identical".
|
||||
@@ -79,6 +104,9 @@ class PExpr : public LineInfo {
|
||||
// of expresions.
|
||||
virtual bool is_constant(Module*) const;
|
||||
|
||||
private: // not implemented
|
||||
PExpr(const PExpr&);
|
||||
PExpr& operator= (const PExpr&);
|
||||
};
|
||||
|
||||
ostream& operator << (ostream&, const PExpr&);
|
||||
@@ -86,18 +114,26 @@ ostream& operator << (ostream&, const PExpr&);
|
||||
class PEConcat : public PExpr {
|
||||
|
||||
public:
|
||||
PEConcat(const svector<PExpr*>&p, PExpr*r =0)
|
||||
: parms_(p), repeat_(r) { }
|
||||
PEConcat(const svector<PExpr*>&p, PExpr*r =0);
|
||||
~PEConcat();
|
||||
|
||||
virtual void dump(ostream&) const;
|
||||
|
||||
// Concatenated Regs can be on the left of procedural
|
||||
// continuous assignments.
|
||||
virtual NetNet* elaborate_anet(Design*des, NetScope*scope) const;
|
||||
|
||||
virtual NetNet* elaborate_lnet(Design*des, const string&path) const;
|
||||
virtual NetNet* elaborate_net(Design*des, const string&path,
|
||||
unsigned width,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay) const;
|
||||
virtual NetExpr*elaborate_expr(Design*des, const string&path) const;
|
||||
unsigned long decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*) const;
|
||||
virtual NetEConcat*elaborate_pexpr(Design*des, NetScope*) const;
|
||||
virtual NetAssign_* elaborate_lval(Design*des, NetScope*scope) const;
|
||||
virtual bool is_constant(Module*) const;
|
||||
|
||||
private:
|
||||
@@ -105,48 +141,101 @@ class PEConcat : public PExpr {
|
||||
PExpr*repeat_;
|
||||
};
|
||||
|
||||
/*
|
||||
* Event expressions are expressions that can be combined with the
|
||||
* event "or" operator. These include "posedge foo" and similar, and
|
||||
* also include named events. "edge" events are associated with an
|
||||
* expression, whereas named events simply have a name, which
|
||||
* represents an event variable.
|
||||
*/
|
||||
class PEEvent : public PExpr {
|
||||
|
||||
public:
|
||||
PEEvent(NetNEvent::Type t, PExpr*e)
|
||||
: type_(t), expr_(e)
|
||||
{ }
|
||||
enum edge_t {ANYEDGE, POSEDGE, NEGEDGE, POSITIVE};
|
||||
|
||||
NetNEvent::Type type() const { return type_; }
|
||||
PExpr* expr() const { return expr_; }
|
||||
// Use this constructor to create events based on edges or levels.
|
||||
PEEvent(edge_t t, PExpr*e);
|
||||
|
||||
~PEEvent();
|
||||
|
||||
edge_t type() const;
|
||||
PExpr* expr() const;
|
||||
|
||||
virtual void dump(ostream&) const;
|
||||
|
||||
private:
|
||||
edge_t type_;
|
||||
PExpr *expr_;
|
||||
};
|
||||
|
||||
/*
|
||||
* This holds a floating point constant in the source.
|
||||
*/
|
||||
class PEFNumber : public PExpr {
|
||||
|
||||
public:
|
||||
explicit PEFNumber(verireal*vp);
|
||||
~PEFNumber();
|
||||
|
||||
const verireal& value() const;
|
||||
|
||||
/* The eval_const method as applied to a floating point number
|
||||
gets the *integer* value of the number. This accounts for
|
||||
any rounding that is needed to get the value. */
|
||||
virtual verinum* eval_const(const Design*des, const string&path) const;
|
||||
|
||||
/* This method returns the full floating point value. */
|
||||
virtual verireal* eval_rconst(const Design*, const NetScope*) const;
|
||||
|
||||
/* A PEFNumber is a constant, so this returns true. */
|
||||
virtual bool is_constant(Module*) const;
|
||||
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*) const;
|
||||
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
|
||||
virtual void dump(ostream&) const;
|
||||
|
||||
private:
|
||||
NetNEvent::Type type_;
|
||||
PExpr*expr_;
|
||||
verireal*value_;
|
||||
};
|
||||
|
||||
class PEIdent : public PExpr {
|
||||
|
||||
public:
|
||||
explicit PEIdent(const string&s)
|
||||
: text_(s), msb_(0), lsb_(0), idx_(0) { }
|
||||
explicit PEIdent(const string&s);
|
||||
~PEIdent();
|
||||
|
||||
virtual void dump(ostream&) const;
|
||||
|
||||
// Regs can be on the left of procedural continuous assignments
|
||||
virtual NetNet* elaborate_anet(Design*des, NetScope*scope) const;
|
||||
|
||||
// Identifiers are allowed (with restrictions) is assign l-values.
|
||||
virtual NetNet* elaborate_lnet(Design*des, const string&path) const;
|
||||
|
||||
// Identifiers are also allowed as procedural assignment l-values.
|
||||
virtual NetAssign_* elaborate_lval(Design*des, NetScope*scope) const;
|
||||
|
||||
// Structural r-values are OK.
|
||||
virtual NetNet* elaborate_net(Design*des, const string&path,
|
||||
unsigned lwidth,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay) const;
|
||||
unsigned long decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
|
||||
virtual NetExpr*elaborate_expr(Design*des, const string&path) const;
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*) const;
|
||||
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
|
||||
// Elaborate the PEIdent as a port to a module. This method
|
||||
// only applies to Ident expressions.
|
||||
NetNet* elaborate_port(Design*des, NetScope*sc) const;
|
||||
|
||||
virtual bool is_constant(Module*) const;
|
||||
verinum* eval_const(const Design*des, const string&path) const;
|
||||
|
||||
// XXXX
|
||||
string name() const { return text_; }
|
||||
string name() const;
|
||||
|
||||
private:
|
||||
string text_;
|
||||
@@ -170,19 +259,21 @@ class PEIdent : public PExpr {
|
||||
class PENumber : public PExpr {
|
||||
|
||||
public:
|
||||
explicit PENumber(verinum*vp)
|
||||
: value_(vp) { assert(vp); }
|
||||
~PENumber() { delete value_; }
|
||||
explicit PENumber(verinum*vp);
|
||||
~PENumber();
|
||||
|
||||
const verinum& value() const { return *value_; }
|
||||
const verinum& value() const;
|
||||
|
||||
virtual void dump(ostream&) const;
|
||||
virtual NetNet* elaborate_net(Design*des, const string&path,
|
||||
unsigned lwidth,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay) const;
|
||||
virtual NetExpr*elaborate_expr(Design*des, const string&path) const;
|
||||
unsigned long decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
virtual NetEConst*elaborate_expr(Design*des, NetScope*) const;
|
||||
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
virtual verinum* eval_const(const Design*des, const string&path) const;
|
||||
|
||||
virtual bool is_the_same(const PExpr*that) const;
|
||||
@@ -195,12 +286,13 @@ class PENumber : public PExpr {
|
||||
class PEString : public PExpr {
|
||||
|
||||
public:
|
||||
explicit PEString(const string&s)
|
||||
: text_(s) { }
|
||||
explicit PEString(const string&s);
|
||||
~PEString();
|
||||
|
||||
string value() const { return text_; }
|
||||
string value() const;
|
||||
virtual void dump(ostream&) const;
|
||||
virtual NetExpr*elaborate_expr(Design*des, const string&path) const;
|
||||
virtual NetEConst*elaborate_expr(Design*des, NetScope*) const;
|
||||
virtual NetEConst*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
|
||||
virtual bool is_constant(Module*) const;
|
||||
|
||||
@@ -211,16 +303,22 @@ class PEString : public PExpr {
|
||||
class PEUnary : public PExpr {
|
||||
|
||||
public:
|
||||
explicit PEUnary(char op, PExpr*ex)
|
||||
: op_(op), expr_(ex) { }
|
||||
explicit PEUnary(char op, PExpr*ex);
|
||||
~PEUnary();
|
||||
|
||||
virtual void dump(ostream&out) const;
|
||||
virtual NetNet* elaborate_net(Design*des, const string&path,
|
||||
unsigned width,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay) const;
|
||||
virtual NetExpr*elaborate_expr(Design*des, const string&path) const;
|
||||
unsigned long decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
virtual NetEUnary*elaborate_expr(Design*des, NetScope*) const;
|
||||
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
virtual verinum* eval_const(const Design*des, const string&path) const;
|
||||
|
||||
virtual bool is_constant(Module*) const;
|
||||
|
||||
private:
|
||||
char op_;
|
||||
@@ -240,8 +338,11 @@ class PEBinary : public PExpr {
|
||||
unsigned width,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay) const;
|
||||
virtual NetExpr*elaborate_expr(Design*des, const string&path) const;
|
||||
unsigned long decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
virtual NetEBinary*elaborate_expr(Design*des, NetScope*) const;
|
||||
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
virtual verinum* eval_const(const Design*des, const string&path) const;
|
||||
|
||||
private:
|
||||
@@ -249,16 +350,43 @@ class PEBinary : public PExpr {
|
||||
PExpr*left_;
|
||||
PExpr*right_;
|
||||
|
||||
NetEBinary*elaborate_expr_base_(Design*, NetExpr*lp, NetExpr*rp) const;
|
||||
|
||||
NetNet* elaborate_net_add_(Design*des, const string&path,
|
||||
unsigned lwidth,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay) const;
|
||||
NetNet* elaborate_net_bit_(Design*des, const string&path,
|
||||
unsigned lwidth,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay) const;
|
||||
NetNet* elaborate_net_cmp_(Design*des, const string&path,
|
||||
unsigned lwidth,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay) const;
|
||||
NetNet* elaborate_net_div_(Design*des, const string&path,
|
||||
unsigned lwidth,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay) const;
|
||||
NetNet* elaborate_net_mod_(Design*des, const string&path,
|
||||
unsigned lwidth,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay) const;
|
||||
NetNet* elaborate_net_log_(Design*des, const string&path,
|
||||
unsigned lwidth,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay) const;
|
||||
NetNet* elaborate_net_mul_(Design*des, const string&path,
|
||||
unsigned lwidth,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay) const;
|
||||
NetNet* elaborate_net_shift_(Design*des, const string&path,
|
||||
unsigned lwidth,
|
||||
unsigned long rise,
|
||||
@@ -281,10 +409,13 @@ class PETernary : public PExpr {
|
||||
virtual void dump(ostream&out) const;
|
||||
virtual NetNet* elaborate_net(Design*des, const string&path,
|
||||
unsigned width,
|
||||
unsigned long rise =0,
|
||||
unsigned long fall =0,
|
||||
unsigned long decay =0) const;
|
||||
virtual NetExpr*elaborate_expr(Design*des, const string&path) const;
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
virtual NetETernary*elaborate_expr(Design*des, NetScope*) const;
|
||||
virtual NetETernary*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
virtual verinum* eval_const(const Design*des, const string&path) const;
|
||||
|
||||
private:
|
||||
@@ -294,25 +425,121 @@ class PETernary : public PExpr {
|
||||
};
|
||||
|
||||
/*
|
||||
* This class represents a parsed call to a function.
|
||||
* This class represents a parsed call to a function, including calls
|
||||
* to system functions.
|
||||
*/
|
||||
class PECallFunction : public PExpr {
|
||||
public:
|
||||
explicit PECallFunction(const string &n, const svector<PExpr *> &parms);
|
||||
explicit PECallFunction(const char*n, const svector<PExpr *> &parms);
|
||||
explicit PECallFunction(const char*n);
|
||||
~PECallFunction();
|
||||
|
||||
virtual void dump(ostream &) const;
|
||||
virtual NetExpr*elaborate_expr(Design*des, const string&path) const;
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope) const;
|
||||
|
||||
private:
|
||||
string name_;
|
||||
svector<PExpr *> parms_;
|
||||
|
||||
NetESFunc* elaborate_sfunc_(Design*des, const string&path) const;
|
||||
NetExpr* elaborate_sfunc_(Design*des, NetScope*scope) const;
|
||||
};
|
||||
|
||||
/*
|
||||
* $Log: PExpr.h,v $
|
||||
* Revision 1.48 2001/01/14 23:04:55 steve
|
||||
* Generalize the evaluation of floating point delays, and
|
||||
* get it working with delay assignment statements.
|
||||
*
|
||||
* Allow parameters to be referenced by hierarchical name.
|
||||
*
|
||||
* Revision 1.47 2000/12/16 19:03:30 steve
|
||||
* Evaluate <= and ?: in parameter expressions (PR#81)
|
||||
*
|
||||
* Revision 1.46 2000/12/10 22:01:35 steve
|
||||
* Support decimal constants in behavioral delays.
|
||||
*
|
||||
* Revision 1.45 2000/12/06 06:31:09 steve
|
||||
* Check lvalue of procedural continuous assign (PR#29)
|
||||
*
|
||||
* Revision 1.44 2000/09/17 21:26:15 steve
|
||||
* Add support for modulus (Eric Aardoom)
|
||||
*
|
||||
* Revision 1.43 2000/09/09 15:21:26 steve
|
||||
* move lval elaboration to PExpr virtual methods.
|
||||
*
|
||||
* Revision 1.42 2000/09/07 22:38:13 steve
|
||||
* Support unary + and - in constants.
|
||||
*
|
||||
* Revision 1.41 2000/06/30 15:50:20 steve
|
||||
* Allow unary operators in constant expressions.
|
||||
*
|
||||
* Revision 1.40 2000/06/13 05:22:16 steve
|
||||
* Support concatenation in parameter expressions.
|
||||
*
|
||||
* Revision 1.39 2000/06/01 02:31:39 steve
|
||||
* Parameters can be strings.
|
||||
*
|
||||
* Revision 1.38 2000/05/16 04:05:15 steve
|
||||
* Module ports are really special PEIdent
|
||||
* expressions, because a name can be used
|
||||
* many places in the port list.
|
||||
*
|
||||
* Revision 1.37 2000/05/07 04:37:56 steve
|
||||
* Carry strength values from Verilog source to the
|
||||
* pform and netlist for gates.
|
||||
*
|
||||
* Change vvm constants to use the driver_t to drive
|
||||
* a constant value. This works better if there are
|
||||
* multiple drivers on a signal.
|
||||
*
|
||||
* Revision 1.36 2000/05/04 03:37:58 steve
|
||||
* Add infrastructure for system functions, move
|
||||
* $time to that structure and add $random.
|
||||
*
|
||||
* Revision 1.35 2000/04/12 04:23:57 steve
|
||||
* Named events really should be expressed with PEIdent
|
||||
* objects in the pform,
|
||||
*
|
||||
* Handle named events within the mix of net events
|
||||
* and edges. As a unified lot they get caught together.
|
||||
* wait statements are broken into more complex statements
|
||||
* that include a conditional.
|
||||
*
|
||||
* Do not generate NetPEvent or NetNEvent objects in
|
||||
* elaboration. NetEvent, NetEvWait and NetEvProbe
|
||||
* take over those functions in the netlist.
|
||||
*
|
||||
* Revision 1.34 2000/04/01 21:40:22 steve
|
||||
* Add support for integer division.
|
||||
*
|
||||
* Revision 1.33 2000/04/01 19:31:57 steve
|
||||
* Named events as far as the pform.
|
||||
*
|
||||
* Revision 1.32 2000/03/12 18:22:11 steve
|
||||
* Binary and unary operators in parameter expressions.
|
||||
*
|
||||
* Revision 1.31 2000/03/12 04:35:22 steve
|
||||
* Allow parameter identifiers in parameter expressions.
|
||||
*
|
||||
* Revision 1.30 2000/03/08 04:36:53 steve
|
||||
* Redesign the implementation of scopes and parameters.
|
||||
* I now generate the scopes and notice the parameters
|
||||
* in a separate pass over the pform. Once the scopes
|
||||
* are generated, I can process overrides and evalutate
|
||||
* paremeters before elaboration begins.
|
||||
*
|
||||
* Revision 1.29 2000/02/23 02:56:53 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.28 2000/02/16 03:58:27 steve
|
||||
* Fix up width matching in structural bitwise operators.
|
||||
*
|
||||
* Revision 1.27 2000/01/13 03:35:35 steve
|
||||
* Multiplication all the way to simulation.
|
||||
*
|
||||
* Revision 1.26 1999/12/16 03:46:39 steve
|
||||
* Structural logical or.
|
||||
*
|
||||
* Revision 1.25 1999/11/21 00:13:08 steve
|
||||
* Support memories in continuous assignments.
|
||||
*
|
||||
|
||||
+29
-4
@@ -16,14 +16,16 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: PFunction.cc,v 1.2 1999/08/25 22:22:41 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: PFunction.cc,v 1.5 2001/07/25 03:10:48 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
#include "PTask.h"
|
||||
|
||||
PFunction::PFunction(svector<PWire*>*p, Statement*s)
|
||||
: out_(0), ports_(p), statement_(s)
|
||||
PFunction::PFunction()
|
||||
: out_(0), ports_(0), statement_(0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -31,6 +33,19 @@ PFunction::~PFunction()
|
||||
{
|
||||
}
|
||||
|
||||
void PFunction::set_ports(svector<PWire *>*p)
|
||||
{
|
||||
assert(ports_ == 0);
|
||||
ports_ = p;
|
||||
}
|
||||
|
||||
void PFunction::set_statement(Statement*s)
|
||||
{
|
||||
assert(s != 0);
|
||||
assert(statement_ == 0);
|
||||
statement_ = s;
|
||||
}
|
||||
|
||||
void PFunction::set_output(PWire*o)
|
||||
{
|
||||
assert(out_ == 0);
|
||||
@@ -39,6 +54,16 @@ void PFunction::set_output(PWire*o)
|
||||
|
||||
/*
|
||||
* $Log: PFunction.cc,v $
|
||||
* Revision 1.5 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.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/08/25 22:22:41 steve
|
||||
* elaborate some aspects of functions.
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1999-2000 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,10 +16,12 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: PGate.cc,v 1.5 1999/09/14 01:50:35 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: PGate.cc,v 1.10 2001/07/25 03:10:48 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# include "PGate.h"
|
||||
# include "PExpr.h"
|
||||
# include "verinum.h"
|
||||
@@ -31,6 +33,8 @@ PGate::PGate(const string&name,
|
||||
: name_(name), pins_(pins)
|
||||
{
|
||||
if (del) delay_.set_delays(del);
|
||||
str0_ = STRONG;
|
||||
str1_ = STRONG;
|
||||
}
|
||||
|
||||
PGate::PGate(const string&name,
|
||||
@@ -39,17 +43,45 @@ PGate::PGate(const string&name,
|
||||
: name_(name), pins_(pins)
|
||||
{
|
||||
if (del) delay_.set_delay(del);
|
||||
str0_ = STRONG;
|
||||
str1_ = STRONG;
|
||||
}
|
||||
|
||||
PGate::PGate(const string&name, svector<PExpr*>*pins)
|
||||
: name_(name), pins_(pins)
|
||||
{
|
||||
str0_ = STRONG;
|
||||
str1_ = STRONG;
|
||||
}
|
||||
|
||||
PGate::~PGate()
|
||||
{
|
||||
}
|
||||
|
||||
PGate::strength_t PGate::strength0() const
|
||||
{
|
||||
return str0_;
|
||||
}
|
||||
|
||||
void PGate::strength0(PGate::strength_t s)
|
||||
{
|
||||
str0_ = s;
|
||||
}
|
||||
|
||||
PGate::strength_t PGate::strength1() const
|
||||
{
|
||||
return str1_;
|
||||
}
|
||||
|
||||
void PGate::strength1(PGate::strength_t s)
|
||||
{
|
||||
str1_ = s;
|
||||
}
|
||||
|
||||
void PGate::elaborate_scope(Design*, NetScope*) const
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* This method is used during elaboration to calculate the
|
||||
* rise/fall/decay times for the gate. These values were set in pform
|
||||
@@ -110,8 +142,64 @@ void PGBuiltin::set_range(PExpr*msb, PExpr*lsb)
|
||||
lsb_ = lsb;
|
||||
}
|
||||
|
||||
PGModule::PGModule(const string&type, const string&name, svector<PExpr*>*pins)
|
||||
: PGate(name, pins), type_(type), overrides_(0), pins_(0),
|
||||
npins_(0), parms_(0), nparms_(0), msb_(0), lsb_(0)
|
||||
{
|
||||
}
|
||||
|
||||
PGModule::PGModule(const string&type, const string&name,
|
||||
named<PExpr*>*pins, unsigned npins)
|
||||
: PGate(name, 0), type_(type), overrides_(0), pins_(pins),
|
||||
npins_(npins), parms_(0), nparms_(0), msb_(0), lsb_(0)
|
||||
{
|
||||
}
|
||||
|
||||
void PGModule::set_parameters(svector<PExpr*>*o)
|
||||
{
|
||||
assert(overrides_ == 0);
|
||||
overrides_ = o;
|
||||
}
|
||||
|
||||
void PGModule::set_parameters(named<PExpr*>*pa, unsigned npa)
|
||||
{
|
||||
assert(parms_ == 0);
|
||||
assert(overrides_ == 0);
|
||||
parms_ = pa;
|
||||
nparms_ = npa;
|
||||
}
|
||||
|
||||
void PGModule::set_range(PExpr*msb, PExpr*lsb)
|
||||
{
|
||||
assert(msb_ == 0);
|
||||
assert(lsb_ == 0);
|
||||
|
||||
msb_ = msb;
|
||||
lsb_ = lsb;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: PGate.cc,v $
|
||||
* Revision 1.10 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.9 2000/05/06 15:41:56 steve
|
||||
* Carry assignment strength to pform.
|
||||
*
|
||||
* Revision 1.8 2000/03/08 04:36:53 steve
|
||||
* Redesign the implementation of scopes and parameters.
|
||||
* I now generate the scopes and notice the parameters
|
||||
* in a separate pass over the pform. Once the scopes
|
||||
* are generated, I can process overrides and evalutate
|
||||
* paremeters before elaboration begins.
|
||||
*
|
||||
* Revision 1.7 2000/02/23 02:56:53 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.6 2000/02/18 05:15:02 steve
|
||||
* Catch module instantiation arrays.
|
||||
*
|
||||
* Revision 1.5 1999/09/14 01:50:35 steve
|
||||
* Handle gates without delays.
|
||||
*
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __PGate_H
|
||||
#define __PGate_H
|
||||
/*
|
||||
* Copyright (c) 1998-1999 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2000 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,16 +18,20 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: PGate.h,v 1.10 1999/09/04 19:11:46 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: PGate.h,v 1.19 2001/04/22 23:09:45 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "svector.h"
|
||||
# include "named.h"
|
||||
# include "LineInfo.h"
|
||||
# include "PDelays.h"
|
||||
# include <map>
|
||||
# include <string>
|
||||
class PExpr;
|
||||
class PUdp;
|
||||
class Design;
|
||||
class NetScope;
|
||||
class Module;
|
||||
|
||||
/*
|
||||
@@ -38,10 +42,17 @@ class Module;
|
||||
* This pins of a gate are connected to expressions. The elaboration
|
||||
* step will need to convert expressions to a network of gates in
|
||||
* order to elaborate expression inputs, but that can easily be done.
|
||||
*
|
||||
* The PGate base class also carries the strength0 and strength1
|
||||
* strengths for those gates where the driver[s] can be described by a
|
||||
* single strength pair. There is a strength of the 0 drive, and a
|
||||
* strength of the 1 drive.
|
||||
*/
|
||||
class PGate : public LineInfo {
|
||||
|
||||
public:
|
||||
enum strength_t { HIGHZ, WEAK, PULL, STRONG, SUPPLY };
|
||||
|
||||
explicit PGate(const string&name, svector<PExpr*>*pins,
|
||||
const svector<PExpr*>*del);
|
||||
|
||||
@@ -62,8 +73,18 @@ class PGate : public LineInfo {
|
||||
unsigned pin_count() const { return pins_? pins_->count() : 0; }
|
||||
const PExpr*pin(unsigned idx) const { return (*pins_)[idx]; }
|
||||
|
||||
strength_t strength0() const;
|
||||
strength_t strength1() const;
|
||||
|
||||
void strength0(strength_t);
|
||||
void strength1(strength_t);
|
||||
|
||||
map<string,string> attributes;
|
||||
|
||||
virtual void dump(ostream&out) const;
|
||||
virtual void elaborate(Design*des, const string&path) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*sc) const;
|
||||
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
|
||||
|
||||
protected:
|
||||
const svector<PExpr*>* get_pins() const { return pins_; }
|
||||
@@ -76,6 +97,8 @@ class PGate : public LineInfo {
|
||||
PDelays delay_;
|
||||
svector<PExpr*>*pins_;
|
||||
|
||||
strength_t str0_, str1_;
|
||||
|
||||
private: // not implemented
|
||||
PGate(const PGate&);
|
||||
PGate& operator= (const PGate&);
|
||||
@@ -151,35 +174,81 @@ class PGModule : public PGate {
|
||||
// If the binding of ports is by position, this constructor
|
||||
// builds everything all at once.
|
||||
explicit PGModule(const string&type, const string&name,
|
||||
svector<PExpr*>*overrides, svector<PExpr*>*pins)
|
||||
: PGate(name, pins), type_(type), overrides_(overrides), pins_(0), npins_(0) { }
|
||||
svector<PExpr*>*pins);
|
||||
|
||||
// If the binding of ports is by name, this constructor takes
|
||||
// the bindings and stores them for later elaboration.
|
||||
struct bind_t {
|
||||
string name;
|
||||
PExpr* parm;
|
||||
};
|
||||
explicit PGModule(const string&type, const string&name,
|
||||
svector<PExpr*>*overrides, bind_t*pins, unsigned npins)
|
||||
: PGate(name, 0), type_(type), overrides_(overrides), pins_(pins), npins_(npins) { }
|
||||
named<PExpr*>*pins, unsigned npins);
|
||||
|
||||
|
||||
// Parameter overrides can come as an ordered list, or a set
|
||||
// of named expressions.
|
||||
void set_parameters(svector<PExpr*>*o);
|
||||
void set_parameters(named<PExpr*>*pa, unsigned npa);
|
||||
|
||||
// Modules can be instantiated in ranges. The parser uses this
|
||||
// method to pass the range to the pform.
|
||||
void set_range(PExpr*msb, PExpr*lsb);
|
||||
|
||||
virtual void dump(ostream&out) const;
|
||||
virtual void elaborate(Design*, const string&path) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*sc) const;
|
||||
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
|
||||
|
||||
private:
|
||||
string type_;
|
||||
svector<PExpr*>*overrides_;
|
||||
bind_t*pins_;
|
||||
named<PExpr*>*pins_;
|
||||
unsigned npins_;
|
||||
|
||||
// These members support parameter override by name
|
||||
named<PExpr*>*parms_;
|
||||
unsigned nparms_;
|
||||
|
||||
// Arrays of modules are give if these are set.
|
||||
PExpr*msb_;
|
||||
PExpr*lsb_;
|
||||
|
||||
void elaborate_mod_(Design*, Module*mod, const string&path) const;
|
||||
void elaborate_udp_(Design*, PUdp *udp, const string&path) const;
|
||||
void elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const;
|
||||
bool elaborate_sig_mod_(Design*des, NetScope*scope, Module*mod) const;
|
||||
};
|
||||
|
||||
/*
|
||||
* $Log: PGate.h,v $
|
||||
* Revision 1.19 2001/04/22 23:09:45 steve
|
||||
* More UDP consolidation from Stephan Boettcher.
|
||||
*
|
||||
* Revision 1.18 2000/05/06 15:41:56 steve
|
||||
* Carry assignment strength to pform.
|
||||
*
|
||||
* Revision 1.17 2000/05/02 16:27:38 steve
|
||||
* Move signal elaboration to a seperate pass.
|
||||
*
|
||||
* Revision 1.16 2000/03/29 04:37:10 steve
|
||||
* New and improved combinational primitives.
|
||||
*
|
||||
* Revision 1.15 2000/03/08 04:36:53 steve
|
||||
* Redesign the implementation of scopes and parameters.
|
||||
* I now generate the scopes and notice the parameters
|
||||
* in a separate pass over the pform. Once the scopes
|
||||
* are generated, I can process overrides and evalutate
|
||||
* paremeters before elaboration begins.
|
||||
*
|
||||
* Revision 1.14 2000/02/23 02:56:53 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.13 2000/02/18 05:15:02 steve
|
||||
* Catch module instantiation arrays.
|
||||
*
|
||||
* Revision 1.12 2000/01/09 05:50:48 steve
|
||||
* Support named parameter override lists.
|
||||
*
|
||||
* Revision 1.11 1999/12/11 05:45:41 steve
|
||||
* Fix support for attaching attributes to primitive gates.
|
||||
*
|
||||
* Revision 1.10 1999/09/04 19:11:46 steve
|
||||
* Add support for delayed non-blocking assignments.
|
||||
*
|
||||
|
||||
@@ -16,14 +16,16 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: PTask.cc,v 1.2 1999/07/24 02:11:19 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: PTask.cc,v 1.6 2001/07/25 03:10:48 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# include "PTask.h"
|
||||
|
||||
PTask::PTask(svector<PWire*>*p, Statement*s)
|
||||
: ports_(p), statement_(s)
|
||||
PTask::PTask()
|
||||
: ports_(0), statement_(0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -31,8 +33,34 @@ PTask::~PTask()
|
||||
{
|
||||
}
|
||||
|
||||
void PTask::set_ports(svector<PWire*>*p)
|
||||
{
|
||||
assert(ports_ == 0);
|
||||
ports_ = p;
|
||||
}
|
||||
|
||||
void PTask::set_statement(Statement*s)
|
||||
{
|
||||
assert(statement_ == 0);
|
||||
statement_ = s;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* $Log: PTask.cc,v $
|
||||
* 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.
|
||||
*
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __PTask_H
|
||||
#define __PTask_H
|
||||
/*
|
||||
* Copyright (c) 1999 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1999-2000 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,14 +18,15 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: PTask.h,v 1.6 1999/09/30 21:28:34 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: PTask.h,v 1.10 2001/01/13 22:20:08 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "LineInfo.h"
|
||||
# include "svector.h"
|
||||
# include <string>
|
||||
class Design;
|
||||
class NetScope;
|
||||
class PWire;
|
||||
class Statement;
|
||||
|
||||
@@ -35,11 +36,23 @@ class Statement;
|
||||
class PTask : public LineInfo {
|
||||
|
||||
public:
|
||||
explicit PTask(svector<PWire*>*p, Statement*s);
|
||||
explicit PTask();
|
||||
~PTask();
|
||||
|
||||
void elaborate_1(Design*des, const string&path) const;
|
||||
void elaborate_2(Design*des, const string&path) const;
|
||||
void set_ports(svector<PWire *>*p);
|
||||
void set_statement(Statement *s);
|
||||
|
||||
// Tasks introduce scope, to need to be handled during the
|
||||
// scope elaboration pass. The scope passed is my scope,
|
||||
// created by the containing scope. I fill it in with stuff if
|
||||
// I need to.
|
||||
void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
|
||||
// Bind the ports to the regs that are the ports.
|
||||
void elaborate_sig(Design*des, NetScope*scope) const;
|
||||
|
||||
// Elaborate the statement to finish off the task definition.
|
||||
void elaborate(Design*des, const string&path) const;
|
||||
|
||||
void dump(ostream&, unsigned) const;
|
||||
|
||||
@@ -60,14 +73,20 @@ class PTask : public LineInfo {
|
||||
class PFunction : public LineInfo {
|
||||
|
||||
public:
|
||||
explicit PFunction(svector<PWire *>*p, Statement *s);
|
||||
explicit PFunction();
|
||||
~PFunction();
|
||||
|
||||
void set_ports(svector<PWire *>*p);
|
||||
void set_statement(Statement *s);
|
||||
void set_output(PWire*);
|
||||
|
||||
/* Functions are elaborated in 2 passes. */
|
||||
void elaborate_1(Design *des, const string &path) const;
|
||||
void elaborate_2(Design *des, const string &path) const;
|
||||
void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
|
||||
/* elaborate the ports and return value. */
|
||||
void elaborate_sig(Design *des, NetScope*) const;
|
||||
|
||||
/* Elaborate the behavioral statement. */
|
||||
void elaborate(Design *des, NetScope*) const;
|
||||
|
||||
void dump(ostream&, unsigned) const;
|
||||
|
||||
@@ -79,6 +98,26 @@ class PFunction : public LineInfo {
|
||||
|
||||
/*
|
||||
* $Log: PTask.h,v $
|
||||
* Revision 1.10 2001/01/13 22:20:08 steve
|
||||
* Parse parameters within nested scopes.
|
||||
*
|
||||
* Revision 1.9 2000/07/30 18:25:43 steve
|
||||
* Rearrange task and function elaboration so that the
|
||||
* NetTaskDef and NetFuncDef functions are created during
|
||||
* signal enaboration, and carry these objects in the
|
||||
* NetScope class instead of the extra, useless map in
|
||||
* the Design class.
|
||||
*
|
||||
* Revision 1.8 2000/03/08 04:36:53 steve
|
||||
* Redesign the implementation of scopes and parameters.
|
||||
* I now generate the scopes and notice the parameters
|
||||
* in a separate pass over the pform. Once the scopes
|
||||
* are generated, I can process overrides and evalutate
|
||||
* paremeters before elaboration begins.
|
||||
*
|
||||
* Revision 1.7 2000/02/23 02:56:53 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.6 1999/09/30 21:28:34 steve
|
||||
* Handle mutual reference of tasks by elaborating
|
||||
* task definitions in two passes, like functions.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __PUdp_H
|
||||
#define __PUdp_H
|
||||
/*
|
||||
* Copyright (c) 1998 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2000 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,8 +18,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: PUdp.h,v 1.3 1999/06/15 03:44:53 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: PUdp.h,v 1.5 2001/04/22 23:09:45 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <map>
|
||||
@@ -72,8 +72,8 @@ class PUdp {
|
||||
|
||||
void dump(ostream&out) const;
|
||||
|
||||
private:
|
||||
const string name_;
|
||||
private:
|
||||
|
||||
private: // Not implemented
|
||||
PUdp(const PUdp&);
|
||||
@@ -82,6 +82,12 @@ class PUdp {
|
||||
|
||||
/*
|
||||
* $Log: PUdp.h,v $
|
||||
* Revision 1.5 2001/04/22 23:09:45 steve
|
||||
* More UDP consolidation from Stephan Boettcher.
|
||||
*
|
||||
* Revision 1.4 2000/02/23 02:56:53 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.3 1999/06/15 03:44:53 steve
|
||||
* Get rid of the STL vector template.
|
||||
*
|
||||
|
||||
@@ -16,15 +16,17 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: PWire.cc,v 1.2 1999/09/10 05:02:09 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: PWire.cc,v 1.6 2001/07/25 03:10:48 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# include "PWire.h"
|
||||
# include <assert.h>
|
||||
|
||||
PWire::PWire(const string&n, NetNet::Type t, NetNet::PortType pt)
|
||||
: name_(n), type_(t), port_type_(pt), lidx_(0), ridx_(0)
|
||||
: name_(n), type_(t), port_type_(pt), signed_(false), lidx_(0), ridx_(0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -43,11 +45,9 @@ bool PWire::set_wire_type(NetNet::Type t)
|
||||
return true;
|
||||
case NetNet::IMPLICIT_REG:
|
||||
if (t == NetNet::REG) { type_ = t; return true; }
|
||||
if (t == NetNet::INTEGER) {type_ = t; return true; }
|
||||
return false;
|
||||
case NetNet::REG:
|
||||
if (t == NetNet::REG) return true;
|
||||
if (t == NetNet::INTEGER) {type_ = t; return true; }
|
||||
return false;
|
||||
default:
|
||||
if (type_ != t)
|
||||
@@ -83,6 +83,16 @@ bool PWire::set_port_type(NetNet::PortType pt)
|
||||
}
|
||||
}
|
||||
|
||||
void PWire::set_signed(bool flag)
|
||||
{
|
||||
signed_ = flag;
|
||||
}
|
||||
|
||||
bool PWire::get_signed() const
|
||||
{
|
||||
return signed_;
|
||||
}
|
||||
|
||||
void PWire::set_range(PExpr*m, PExpr*l)
|
||||
{
|
||||
msb_ = svector<PExpr*>(msb_,m);
|
||||
@@ -93,13 +103,27 @@ void PWire::set_memory_idx(PExpr*ldx, PExpr*rdx)
|
||||
{
|
||||
assert(lidx_ == 0);
|
||||
assert(ridx_ == 0);
|
||||
assert((type_ == NetNet::REG) || (type_ == NetNet::INTEGER));
|
||||
assert(type_ == NetNet::REG);
|
||||
lidx_ = ldx;
|
||||
ridx_ = rdx;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: PWire.cc,v $
|
||||
* 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/01/06 02:29:35 steve
|
||||
* Support arrays of integers.
|
||||
*
|
||||
* Revision 1.4 2000/12/11 00:31:43 steve
|
||||
* Add support for signed reg variables,
|
||||
* simulate in t-vvm signed comparisons.
|
||||
*
|
||||
* Revision 1.3 2000/02/23 02:56:54 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.2 1999/09/10 05:02:09 steve
|
||||
* Handle integers at task parameters.
|
||||
*
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __PWire_H
|
||||
#define __PWire_H
|
||||
/*
|
||||
* Copyright (c) 1998 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2000 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,15 +18,21 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: PWire.h,v 1.6 1999/11/27 19:07:57 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: PWire.h,v 1.10 2001/01/16 02:44:18 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
# include "LineInfo.h"
|
||||
# include <map>
|
||||
# include <map>
|
||||
# include "svector.h"
|
||||
|
||||
#ifdef HAVE_IOSFWD
|
||||
# include <iosfwd>
|
||||
#else
|
||||
class ostream;
|
||||
#endif
|
||||
|
||||
class PExpr;
|
||||
class Design;
|
||||
|
||||
@@ -49,6 +55,9 @@ class PWire : public LineInfo {
|
||||
NetNet::PortType get_port_type() const;
|
||||
bool set_port_type(NetNet::PortType);
|
||||
|
||||
void set_signed(bool flag);
|
||||
bool get_signed() const;
|
||||
|
||||
void set_range(PExpr*msb, PExpr*lsb);
|
||||
|
||||
void set_memory_idx(PExpr*ldx, PExpr*rdx);
|
||||
@@ -58,12 +67,13 @@ class PWire : public LineInfo {
|
||||
// Write myself to the specified stream.
|
||||
void dump(ostream&out) const;
|
||||
|
||||
void elaborate(Design*, NetScope*scope) const;
|
||||
void elaborate_sig(Design*, NetScope*scope) const;
|
||||
|
||||
private:
|
||||
string name_;
|
||||
NetNet::Type type_;
|
||||
NetNet::PortType port_type_;
|
||||
bool signed_;
|
||||
|
||||
// These members hold expressions for the bit width of the
|
||||
// wire. If they do not exist, the wire is 1 bit wide.
|
||||
@@ -82,6 +92,19 @@ class PWire : public LineInfo {
|
||||
|
||||
/*
|
||||
* $Log: PWire.h,v $
|
||||
* Revision 1.10 2001/01/16 02:44:18 steve
|
||||
* Use the iosfwd header if available.
|
||||
*
|
||||
* Revision 1.9 2000/12/11 00:31:43 steve
|
||||
* Add support for signed reg variables,
|
||||
* simulate in t-vvm signed comparisons.
|
||||
*
|
||||
* Revision 1.8 2000/05/02 16:27:38 steve
|
||||
* Move signal elaboration to a seperate pass.
|
||||
*
|
||||
* Revision 1.7 2000/02/23 02:56:54 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.6 1999/11/27 19:07:57 steve
|
||||
* Support the creation of scopes.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
|
||||
* Getting Started with Icarus Verilog
|
||||
|
||||
Icarus Verilog is a Verilog compiler. It is suitable for use as a
|
||||
simulator, and, to some degree, synthesizer. Icarus Verilog runs under
|
||||
Linux and a variety of UNIX systems, as well as Windows as a command
|
||||
line tool, so the instructions are generally applicable to all
|
||||
environments. Note that this is only a quick start. For more detailed
|
||||
documentation, see the manual page for the iverilog command.
|
||||
|
||||
|
||||
* Hello, World!
|
||||
|
||||
The first thing you want to do as a user is learn how to compile and
|
||||
execute even the most trivial design. For the purposes of simulation,
|
||||
we use as our example *the* most trivial simulation:
|
||||
|
||||
module main;
|
||||
|
||||
initial
|
||||
begin
|
||||
$display("Hello, World");
|
||||
$finish ;
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
By a text editor (or copy hello.vl from the Icarus Verilog examples
|
||||
directory) arrange for this program to be in a text file, "hello.vl".
|
||||
Next, compile this program with a command like this:
|
||||
|
||||
% iverilog -o hello hello.vl
|
||||
|
||||
The results of this compile are placed into the file "hello", as the
|
||||
"-o" flag tells the compiler where to place the compiled result. Next,
|
||||
execute the compiled program like so:
|
||||
|
||||
% vvp hello
|
||||
Hello, World
|
||||
|
||||
And there it is, the program has been executed. So what happened? The
|
||||
first step, the "iverilog" command, read and interpreted the source
|
||||
file, then generated a compiled result. The compiled form may be
|
||||
selected by command line switches, but the default form is the VVP
|
||||
format, which is actually run by the "vvp" command.
|
||||
|
||||
The "iverilog" and "vvp" commands are the only commands that users
|
||||
use to invoke Icarus Verilog. What the compiler actually does is
|
||||
controlled by command line switches. In our little example, we asked
|
||||
the compiler to compile the source program to the default vvp form,
|
||||
which is in turn executed by the vvp program.
|
||||
|
||||
|
||||
* Windows Install
|
||||
|
||||
The easiest way to install under Windows is to get a precompiled
|
||||
installer for the version you wish to install. Icarus Verilog is
|
||||
distributed for Windows users as a self-installing .exe. Just execute
|
||||
the installer and follow the instructions. During the install, take
|
||||
note of the directory where the program is installed: for example,
|
||||
C:\iverilog is a good place to install.
|
||||
|
||||
Once the binary is installed, you need to add the bin directory to
|
||||
your execution path. The executables you need are in C:\iverilog\bin,
|
||||
where the "C:\iverilog" part is actually the root of where you
|
||||
installed the package. The programs are in the bin subdirectory. Put
|
||||
this directory in your PATH environment variable, and the above
|
||||
commands become accessible to you at the command line prompt, or even
|
||||
in batch files.
|
||||
|
||||
|
||||
* Linux Install
|
||||
|
||||
Under Linux, the install is even easier. For RedHat and Mandrake based
|
||||
systems, there is the appropriate RPM file. Just install the package
|
||||
with the "rpm -U <file>" command. Debian users should get Icarus
|
||||
Verilog packages from the main Debian software site.
|
||||
|
||||
|
||||
* Install From Source
|
||||
|
||||
In this case, see the readme and other documentation that comes with
|
||||
the source.
|
||||
+275
-160
@@ -1,23 +1,28 @@
|
||||
THE ICARUS VERILOG COMPILATION SYSTEM
|
||||
September 18, 1999
|
||||
September 17, 2000
|
||||
|
||||
|
||||
1.0 What is ICARUS Verilog?
|
||||
|
||||
Icarus Verilog is intended to compile ALL of the Verilog HDL as described
|
||||
in the IEEE-1364 standard. Of course, it's not quite there yet. It does
|
||||
currently handle a mix of structural and behavioral constructs. For a
|
||||
view of the current state of Icarus Verilog, see its home page at
|
||||
<http://www.icarus.com/eda/verilog>.
|
||||
Icarus Verilog is intended to compile ALL of the Verilog HDL as
|
||||
described in the IEEE-1364 standard. Of course, it's not quite there
|
||||
yet. It does currently handle a mix of structural and behavioral
|
||||
constructs. For a view of the current state of Icarus Verilog, see its
|
||||
home page at <http://www.icarus.com/eda/verilog>.
|
||||
|
||||
IVL 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 written in C++ called VVM
|
||||
and an XNF (Xilinx Netlist Format) generator. See "vvm.txt" and
|
||||
"xnf.txt" for further details on these back-end processors. In the
|
||||
future, backends are expected for EDIF/LPM, structural Verilog, etc.
|
||||
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 written in
|
||||
C++ called VVM, another faster simulator called VVP and an XNF (Xilinx
|
||||
Netlist Format) generator. See "vvm.txt" and "xnf.txt" for further
|
||||
details on these back-end processors. In the future, backends are
|
||||
expected for EDIF/LPM, structural Verilog, VHDL, etc.
|
||||
|
||||
2.0 Building/Installing IVL From Source
|
||||
For instructions on how to run Icarus Verilog, see the ``iverilog''
|
||||
man page.
|
||||
|
||||
|
||||
2.0 Building/Installing Icarus Verilog From Source
|
||||
|
||||
If you are starting from source, the build process is designed to be
|
||||
as simple as practical. Someone basically familiar with the target
|
||||
@@ -31,16 +36,27 @@ You need the following software to compile Icarus Verilog from source
|
||||
on a UNIX-like system:
|
||||
|
||||
- GNU Make
|
||||
The Makefiles use some GNU extensions to, so a basic POSIX
|
||||
The Makefiles use some GNU extensions, so a basic POSIX
|
||||
make will not work. Linux systems typically come with a
|
||||
satisfactory make.
|
||||
satisfactory make. BSD based systems (i.e. NetBSD, FreeBSD)
|
||||
typically have GNU make as the gmake program.
|
||||
|
||||
- ISO C++ Compiler
|
||||
The ivl program is written in C++ and makes use of templates
|
||||
and some of the standard C++ library. egcs compilers with
|
||||
the associated libstdc++ are known to work.
|
||||
The ivl and ivlpp programs are written in C++ and make use
|
||||
of templates and some of the standard C++ library. egcs and
|
||||
recent gcc compilers with the associated libstdc++ are known
|
||||
to work. MSVC++ 5 and 6 are known to definitely *not* work.
|
||||
|
||||
- bison
|
||||
- bison and flex
|
||||
|
||||
- gperf 2.7
|
||||
The lexical analyzer doesn't recognize keywords directly,
|
||||
but instead matches symbols and looks them up in a hash
|
||||
table in order to get the proper lexical code. The gperf
|
||||
program generates the lookup table.
|
||||
|
||||
A version problem with this program is the most common cause
|
||||
of difficulty. See the Icarus Verilog FAQ.
|
||||
|
||||
2.2 Compilation
|
||||
|
||||
@@ -51,16 +67,48 @@ with the commands:
|
||||
./configure
|
||||
make
|
||||
|
||||
2.3 Installation
|
||||
Normally, this command automatically figures out every thing 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
|
||||
libaries 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,
|
||||
/usr/local/share/ivl, etc.
|
||||
|
||||
I recommend that if you are configuring for precompiled
|
||||
binaries, use --prefix=/usr. On Solaris systems, it is
|
||||
common to use --prefix=/opt.
|
||||
|
||||
2.3 (Optional) Testing
|
||||
|
||||
To run a simple test before installation, execute
|
||||
|
||||
make check
|
||||
|
||||
The commands printed by this run might help you in running Icarus
|
||||
Verilog on your own verilog sources before the package is installed
|
||||
by root.
|
||||
|
||||
2.4 Installation
|
||||
|
||||
Now install the files in an appropriate place. (The makefiles by
|
||||
default install in /usr/local unless you specify a different prefix
|
||||
with the --prefix=<path> flag to the configure command.) Do this as
|
||||
root.
|
||||
with the --prefix=<path> flag to the configure command.) You may need
|
||||
to do this as root to gain access to installation directories.
|
||||
|
||||
make install
|
||||
|
||||
3.0 How IVL Works
|
||||
2.5 Uninstallation
|
||||
|
||||
The generated Makefiles also include the uninstall target. This should
|
||||
remove all the files that ``make install'' creates.
|
||||
|
||||
3.0 How Icarus Verilog Works
|
||||
|
||||
This tool includes a parser which reads in Verilog (plus extensions)
|
||||
and generates an internal netlist. The netlist is passed to various
|
||||
@@ -86,8 +134,8 @@ step. There may be dangling references, and it is not yet clear which
|
||||
module is the root.
|
||||
|
||||
One can see a human readable version of the final PFORM by using the
|
||||
``-P <path>'' flag to the compiler. This will cause ivl to dump the
|
||||
PFORM into the file named <path>.
|
||||
``-P <path>'' flag to the compiler. This will cause iverilog to dump
|
||||
the PFORM into the file named <path>.
|
||||
|
||||
3.3 Elaboration
|
||||
|
||||
@@ -95,7 +143,8 @@ This phase takes the pform and generates a netlist. The driver selects
|
||||
(by user request or lucky guess) the root module to elaborate,
|
||||
resolves references and expands the instantiations to form the design
|
||||
netlist. (See netlist.txt.) Final semantic checks are performed during
|
||||
elaboration, and some simple optimizations are performed.
|
||||
elaboration, and some simple optimizations are performed. The netlist
|
||||
includes all the behavioral descriptions, as well as gates and wires.
|
||||
|
||||
The elaborate() function performs the elaboration.
|
||||
|
||||
@@ -104,6 +153,31 @@ optimized netlist by using the ``-N <path>'' flag to the compiler. If
|
||||
elaboration succeeds, the final netlist (i.e. after optimizations but
|
||||
before code generation) will be dumped into the file named <path>.
|
||||
|
||||
Elaboration is actually performed it two steps: scopes and parameters
|
||||
first, followed by the structural and behavioral elaboration.
|
||||
|
||||
3.3.1 Scope Elaboration
|
||||
|
||||
This pass scans through the pform looking for scopes and parameters. A
|
||||
tree of NetScope objects is built up and placed in the Design object,
|
||||
with the root module represented by the root NetScope object. The
|
||||
elab_scope.cc and elab_pexpr.cc files contain most of the code for
|
||||
handling this phase.
|
||||
|
||||
The tail of the elaborate_scope behavior (after the pform is
|
||||
traversed) includes a scan of the NetScope tree to locate defparam
|
||||
assignments that were collected during scope elaboration. This is when
|
||||
the defparam overrides are applied to the parameters.
|
||||
|
||||
3.3.2 Netlist Elaboration
|
||||
|
||||
After the scopes and parameters are generated and the NetScope tree
|
||||
fully formed, the elaboration runs through the pform again, this time
|
||||
generating the structural and behavioral netlist. Parameters are
|
||||
elaborated and evaluated by now so all the constants of code
|
||||
generation are now known locally, so the netlist can be generated by
|
||||
simply passing through the pform.
|
||||
|
||||
3.4 Optimization
|
||||
|
||||
This is actually a collection of processing steps that perform
|
||||
@@ -114,7 +188,7 @@ some useful transformations would be,
|
||||
- combinational reduction
|
||||
- Constant propagation
|
||||
|
||||
The actual functions performed are specified on the command line by
|
||||
The actual functions performed are specified on the ivl command line by
|
||||
the -F flags (See below).
|
||||
|
||||
3.5 Code Generation
|
||||
@@ -127,76 +201,10 @@ The emit() method of the Design class performs this step. It runs
|
||||
through the design elements, calling target functions as need arises
|
||||
to generate actual output.
|
||||
|
||||
The target code generator to used is given by the -t flag on the
|
||||
The user selects the target code generator with the -t flag on the
|
||||
command line.
|
||||
|
||||
4.0 Running Verilog
|
||||
|
||||
The preferred way to invoke the compiler with the verilog(1)
|
||||
command. This program invokes the preprocessor (ivlpp) and the
|
||||
compiler (ivl) with the proper command line options to get the job
|
||||
done in a friendly way. See the verilog(1) man page for usage details.
|
||||
|
||||
4.1 Running IVL Directly
|
||||
|
||||
The ivl command is the compiler driver, that invokes the parser,
|
||||
optimization functions and the code generator.
|
||||
|
||||
Usage: ivl <options>... file
|
||||
ivl -h
|
||||
|
||||
-F <name>
|
||||
Use this flag to request an optimization function be applied
|
||||
to the netlist before it is sent to the target output
|
||||
stage. Any number of -F options may be given, to specify a
|
||||
variety of processing steps. The steps will be applied in
|
||||
order, with the output of one uses as the input to the next.
|
||||
|
||||
The function is specified by name. Use the "ivl -h" command to
|
||||
get a list of configured function names.
|
||||
|
||||
-f <assign>
|
||||
Use this flag to set a parameter value. The format of the
|
||||
assignment is <key>=<value> where key is any string up to the
|
||||
first '=', and <value> is the rest of the option. If the '='
|
||||
is omitted, then the key is assigned the empty string.
|
||||
|
||||
The useful keys are defined by the functions and the target in
|
||||
use. These assignments are specifically useful for passing
|
||||
target specific information to the target back-end, or
|
||||
options/parameters to optimization functions, if any are defined.
|
||||
|
||||
-N <file>
|
||||
Dump the elaborated netlist to the named file. The netlist is
|
||||
the folly elaborated netlist, after all the function modules
|
||||
are applied and right before the output generator is
|
||||
called. This is an aid for debugging the compiler, and the
|
||||
output generator in particular.
|
||||
|
||||
-o <file>
|
||||
Normally, the generated result is sent to standard
|
||||
output. Use the -o flag to specify an output file for the
|
||||
generated result.
|
||||
|
||||
-P <file>
|
||||
Write the PForm of the parsed input to the specified file.
|
||||
The pform is the compiler's understanding of the input after
|
||||
parsing and before elaboration. This is an aid for debugging
|
||||
the compiler.
|
||||
|
||||
-s <module>
|
||||
Normally, ivl will elaborate the only module in the source
|
||||
file. If there are multiple modules, use this option to select
|
||||
the module to be used as the top-level module.
|
||||
|
||||
-t <name>
|
||||
Select the output format for the compiled result. Use the
|
||||
"ivl -h" command to get a list of configured targets.
|
||||
|
||||
-v
|
||||
Print version and copyright information for ivl.
|
||||
|
||||
ATTRIBUTES
|
||||
3.6 ATTRIBUTES
|
||||
|
||||
The parser accepts as an extension to Verilog the $attribute module
|
||||
item. The syntax of the $attribute item is:
|
||||
@@ -221,14 +229,105 @@ names a primitive earlier in the compilation unit and the statement is
|
||||
placed in global scope, instead of within a module. The semicolon is
|
||||
not part of a type attribute.
|
||||
|
||||
Currently, type attributes are only supported for UDP types.
|
||||
|
||||
Note that attributes are also occasionally used for communication
|
||||
between processing steps. Processing steps that are aware of others
|
||||
may place attributes on netlist objects to communicate information to
|
||||
later steps.
|
||||
|
||||
4.1 EXAMPLES
|
||||
4.0 Running iverilog
|
||||
|
||||
The preferred way to invoke the compiler is with the iverilog(1)
|
||||
command. This program invokes the preprocessor (ivlpp) and the
|
||||
compiler (ivl) with the proper command line options to get the job
|
||||
done in a friendly way. See the iverilog(1) man page for usage details.
|
||||
|
||||
4.1 Running IVL Directly (not recommended)
|
||||
|
||||
NOTE: The preferred method of running Icarus Verilog is the
|
||||
iverilog command described above. The instructions below may
|
||||
change at any time without notice.
|
||||
|
||||
The ivl command is the compiler driver, that invokes the parser,
|
||||
optimization functions and the code generator, but not the preprocessor.
|
||||
|
||||
Usage: ivl <options>... file
|
||||
ivl -h
|
||||
ivl -V
|
||||
|
||||
-F <name>
|
||||
Use this flag to request an optimization function be applied
|
||||
to the netlist before it is sent to the target output
|
||||
stage. Any number of -F options may be given, to specify a
|
||||
variety of processing steps. The steps will be applied in
|
||||
order, with the output of one uses as the input to the next.
|
||||
|
||||
The function is specified by name. Use the "ivl -h" command to
|
||||
get a list of configured function names.
|
||||
|
||||
-h
|
||||
Print usage information, and exit.
|
||||
|
||||
-m <module>
|
||||
Cause a named VPI module to be included in the module
|
||||
list. This parameter appends the named module to the end of
|
||||
the VPI_MODULE_LIST. This is an ordered list of modules to be
|
||||
loaded into the simulation at runtime.
|
||||
|
||||
This list can also be set with -fVPI_MODULE_LIST=<list> which
|
||||
sets the list completely. Then, -m after this will append
|
||||
module names to the list sp specified. The default list
|
||||
includes "system".
|
||||
|
||||
-N <file>
|
||||
Dump the elaborated netlist to the named file. The netlist is
|
||||
the folly elaborated netlist, after all the function modules
|
||||
are applied and right before the output generator is
|
||||
called. This is an aid for debugging the compiler, and the
|
||||
output generator in particular.
|
||||
|
||||
-o <file>
|
||||
Normally, the generated result is sent to standard
|
||||
output. Use the -o flag to specify an output file for the
|
||||
generated result.
|
||||
|
||||
-P <file>
|
||||
Write the PForm of the parsed input to the specified file.
|
||||
The pform is the compiler's understanding of the input after
|
||||
parsing and before elaboration. This is an aid for debugging
|
||||
the compiler.
|
||||
|
||||
-p <assign>
|
||||
Use this flag to set a parameter value. The format of the
|
||||
assignment is <key>=<value> where key is any string up to the
|
||||
first '=', and <value> is the rest of the option. If the '='
|
||||
is omitted, then the key is assigned the empty string.
|
||||
|
||||
The useful keys are defined by the functions and the target in
|
||||
use. These assignments are specifically useful for passing
|
||||
target specific information to the target back-end, or
|
||||
options/parameters to optimization functions, if any are defined.
|
||||
|
||||
-s <module>
|
||||
Normally, ivl will elaborate the only module in the source
|
||||
file. If there are multiple modules, use this option to select
|
||||
the module to be used as the top-level module.
|
||||
|
||||
-T [min|typ|max]
|
||||
Normally, ivl will select typ values from min:type:max
|
||||
expressions and print a warning. This flag tells the compiler
|
||||
exactly which value to choose, and suppresses the warning.
|
||||
|
||||
-t <name>
|
||||
Select the output format for the compiled result. Use the
|
||||
"ivl -h" command to get a list of configured targets.
|
||||
|
||||
-v Print progress indications, and (if supported by the system)
|
||||
executions times in ivl precessing steps.
|
||||
|
||||
-V
|
||||
Print version and copyright information for ivl, and exit.
|
||||
|
||||
4.2 EXAMPLES
|
||||
|
||||
Example: Compiling "hello.vl"
|
||||
|
||||
@@ -245,45 +344,32 @@ endmodule
|
||||
|
||||
--------------------------------------------------------------
|
||||
|
||||
Insure that "verilog" is on your search path, and the vpi library
|
||||
Insure that "iverilog" is on your search path, and the vpi library
|
||||
is available.
|
||||
|
||||
For csh -
|
||||
To compile the program:
|
||||
|
||||
setenv PATH /usr/local/bin:$PATH
|
||||
setenv VPI_MODULE_PATH /usr/local/lib/ivl
|
||||
|
||||
verilog hello.vl
|
||||
iverilog hello.vl
|
||||
|
||||
(The above presumes that /usr/local/include and /usr/local/lib are
|
||||
part of the compiler search path, which is usually the case for gcc.)
|
||||
|
||||
To run the program
|
||||
To run the program:
|
||||
|
||||
./hello
|
||||
./a.out
|
||||
|
||||
You can use the "-o" switch to name the output command to be generated
|
||||
by the compiler. See the iverilog(1) man page.
|
||||
|
||||
5.0 Unsupported Constructs
|
||||
|
||||
IVL is in development - as such it still only supports a (growing) subset
|
||||
of verilog. Below is a description of some of the currently unsupported
|
||||
verilog features. This list is not exhaustive, and does not account
|
||||
for errors in the compiler. See the Icarus Verilog web page for the
|
||||
current state of support for Verilog.
|
||||
|
||||
- Min/Typ/Max expressions: Example: a = (1 : 6 : 14);
|
||||
|
||||
- Memories work, but only in procedural code.
|
||||
|
||||
reg [1:0] b [2:0], bar;
|
||||
wire [1:0] foo;
|
||||
always foo = b[i]; // sorry
|
||||
always @(i) bar = b[i]; // OK
|
||||
|
||||
- `timescale directive
|
||||
|
||||
- force/release/assign/deassign procedural assignments not
|
||||
supported.
|
||||
Icarus Verilog is in development - as such it still only supports a
|
||||
(growing) subset of Verilog. Below is a description of some of the
|
||||
currently unsupported verilog features. This list is not exhaustive,
|
||||
and does not account for errors in the compiler. See the Icarus
|
||||
Verilog web page for the current state of support for Verilog, and in
|
||||
particular, browse the bug report database for reported unsupported
|
||||
constructs.
|
||||
|
||||
- block disable not supported, i.e.:
|
||||
|
||||
@@ -293,62 +379,44 @@ current state of support for Verilog.
|
||||
[...]
|
||||
end
|
||||
|
||||
- fork/join is not supported in vvm runtime
|
||||
|
||||
- Structural shift operators are in general not supported.
|
||||
Procedural expressions are OK. Constant expressions are OK.
|
||||
|
||||
assign foo = a << b; // sorry
|
||||
always @(a or b) foo = a << b; // OK
|
||||
parameter foo = a << b; // OK
|
||||
|
||||
- Functions in structural contexts are not supported.
|
||||
|
||||
assign foo = user_function(a,b); // sorry
|
||||
always @(a or b) foo = user_function(a,b); // OK
|
||||
|
||||
- multiplicative operators (*, /, %) are not supported.
|
||||
- real data types not supported. This includes real and
|
||||
realtime. However, floating point constants in delay expressions
|
||||
are supported so that `timescale works properly.
|
||||
|
||||
assign foo = a * b; // sorry
|
||||
always @(a or b) foo = a * b; // sorry
|
||||
- System functions are supported, but the compiler presumes that
|
||||
they return 32 bits. This is the typical case.
|
||||
|
||||
- event data type is not supported.
|
||||
- Specify blocks are parsed but ignored in general.
|
||||
|
||||
- real data type not supported.
|
||||
|
||||
- system functions are not supported. (User defined functions are
|
||||
supported, and system tasks are supported.)
|
||||
|
||||
assign foo = $some_function(a,b); // sorry
|
||||
always @(a or b) foo = $some_function(a,b); // sorry
|
||||
|
||||
- non-constant delay expressions, i.e.:
|
||||
|
||||
reg [7:0] del;
|
||||
always #(reg) $display($time,,"del = %d", del); // sorry
|
||||
|
||||
- drive strengths are parsed, bug ignored.
|
||||
|
||||
Specify blocks are parsed but ignored in general.
|
||||
- trireg is not supported. tri0 and tri1 are supported.
|
||||
|
||||
|
||||
6.0 CREDITS
|
||||
|
||||
Except where otherwise noted, ivl and ivlpp are Copyright Stephen
|
||||
Williams. The proper notices are in the head of each file. However,
|
||||
I have received aid in the form of fixes, Verilog guidance, and
|
||||
especially testing from many people, including (in alphabetical order):
|
||||
Except where otherwise noted, Icarus Verilog, ivl and ivlpp are
|
||||
Copyright Stephen Williams. The proper notices are in the head of each
|
||||
file. However, I have early on received aid in the form of fixes,
|
||||
Verilog guidance, and especially testing from many people, including
|
||||
(in alphabetical order):
|
||||
|
||||
Eric Aardoom <[email protected]>
|
||||
Stephan I. Boettcher <[email protected]>
|
||||
Ed Carter <[email protected]>
|
||||
Larry Doolittle <[email protected]>
|
||||
Guy Hutchison <[email protected]>
|
||||
Ales Hvezda <[email protected]>
|
||||
James Lee <jml@seva.com>
|
||||
Venkat Iyer <venkat@comit.com>
|
||||
Yasuhisa Kato <[email protected]>
|
||||
James Lee <[email protected]>
|
||||
Peter Monta <[email protected]>
|
||||
Daniel H. Nelsen <[email protected]>
|
||||
Stefan Petersen <[email protected]>
|
||||
Jason Schonberg <schon@mips.com>
|
||||
Jason Schonberg <schonm@yahoo.com>
|
||||
Stuart Sutherland <[email protected]>
|
||||
Stephen Tell <[email protected]>
|
||||
Stefan Theide <[email protected]>
|
||||
@@ -357,3 +425,50 @@ especially testing from many people, including (in alphabetical order):
|
||||
and others. Testers in particular include a larger community of people
|
||||
interested in a GPL Verilog for Linux. Special thanks to Steve Wilson
|
||||
for collecting and organizing the test suite code for all those testers.
|
||||
|
||||
|
||||
6.1 PORT MAINTAINERS
|
||||
|
||||
This is a list of people who have created ports and precompiled
|
||||
packages for various operating systems. These folks have graciously
|
||||
taken on the task of building Icarus Verilog on their systems and
|
||||
bundled it into neat packages.(+) If you want to be added to the list (or
|
||||
removed from the list) send e-mail to me.
|
||||
|
||||
FreeBSD/{Intel,alpha}
|
||||
Ying-Chieh Liao <[email protected]>
|
||||
|
||||
Linux/{alpha,Intel} (RPMS)
|
||||
Stephen Williams <[email protected]>
|
||||
|
||||
Linux/* (.debs)
|
||||
Hamish Moffatt <[email protected]>
|
||||
|
||||
Macintosh -- MacO/S
|
||||
Yasuhisa Kato <[email protected]>
|
||||
|
||||
NetBSD/*
|
||||
Dan McMahill <[email protected]>
|
||||
|
||||
Solaris/SPARC packages (.pkg)
|
||||
Dan McMahill <[email protected]>
|
||||
|
||||
Cygwin32/*
|
||||
Venkat Iyer <[email protected]>
|
||||
|
||||
Mingw32
|
||||
Venkat Iyer <[email protected]>
|
||||
|
||||
(+) These are not the only systems where Icarus Verilog has been run,
|
||||
just the systems where precompiled binaries are publicly available.
|
||||
|
||||
|
||||
6.2 TEST SUITE MANAGER
|
||||
|
||||
Steve Wilson <[email protected]> or <[email protected]> has taken on
|
||||
the large task of managing the test suite. He has maintained the
|
||||
regression test scripts, the driver list, received submissions from
|
||||
myself and others, and has written a great many tests on his own. Any
|
||||
compiler writer, for any language, will tell you that the test suite
|
||||
is at least as important as the compiler code itself.
|
||||
|
||||
|
||||
+134
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-1999 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,10 +16,12 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: Statement.cc,v 1.16 1999/09/29 18:36:02 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: Statement.cc,v 1.23 2001/07/25 03:10:48 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# include "Statement.h"
|
||||
# include "PExpr.h"
|
||||
|
||||
@@ -122,6 +124,22 @@ PCase::~PCase()
|
||||
delete[]items_;
|
||||
}
|
||||
|
||||
PCAssign::PCAssign(PExpr*l, PExpr*r)
|
||||
: lval_(l), expr_(r)
|
||||
{
|
||||
}
|
||||
|
||||
PCAssign::~PCAssign()
|
||||
{
|
||||
delete lval_;
|
||||
delete expr_;
|
||||
}
|
||||
|
||||
PCondit::PCondit(PExpr*ex, Statement*i, Statement*e)
|
||||
: expr_(ex), if_(i), else_(e)
|
||||
{
|
||||
}
|
||||
|
||||
PCondit::~PCondit()
|
||||
{
|
||||
delete expr_;
|
||||
@@ -129,6 +147,68 @@ PCondit::~PCondit()
|
||||
delete else_;
|
||||
}
|
||||
|
||||
PDeassign::PDeassign(PExpr*l)
|
||||
: lval_(l)
|
||||
{
|
||||
}
|
||||
|
||||
PDeassign::~PDeassign()
|
||||
{
|
||||
delete lval_;
|
||||
}
|
||||
|
||||
|
||||
PDelayStatement::PDelayStatement(PExpr*d, Statement*st)
|
||||
: delay_(d), statement_(st)
|
||||
{
|
||||
}
|
||||
|
||||
PDelayStatement::~PDelayStatement()
|
||||
{
|
||||
}
|
||||
|
||||
PDisable::PDisable(const string&sc)
|
||||
: scope_(sc)
|
||||
{
|
||||
}
|
||||
|
||||
PDisable::~PDisable()
|
||||
{
|
||||
}
|
||||
|
||||
PEventStatement::PEventStatement(const svector<PEEvent*>&ee)
|
||||
: expr_(ee), statement_(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
PEventStatement::PEventStatement(PEEvent*ee)
|
||||
: expr_(1), statement_(0)
|
||||
{
|
||||
expr_[0] = ee;
|
||||
}
|
||||
|
||||
PEventStatement::~PEventStatement()
|
||||
{
|
||||
// delete the events and the statement?
|
||||
}
|
||||
|
||||
void PEventStatement::set_statement(Statement*st)
|
||||
{
|
||||
statement_ = st;
|
||||
}
|
||||
|
||||
PForce::PForce(PExpr*l, PExpr*r)
|
||||
: lval_(l), expr_(r)
|
||||
{
|
||||
}
|
||||
|
||||
PForce::~PForce()
|
||||
{
|
||||
delete lval_;
|
||||
delete expr_;
|
||||
}
|
||||
|
||||
PForever::PForever(Statement*s)
|
||||
: statement_(s)
|
||||
{
|
||||
@@ -144,6 +224,16 @@ PProcess::~PProcess()
|
||||
delete statement_;
|
||||
}
|
||||
|
||||
PRelease::PRelease(PExpr*l)
|
||||
: lval_(l)
|
||||
{
|
||||
}
|
||||
|
||||
PRelease::~PRelease()
|
||||
{
|
||||
delete lval_;
|
||||
}
|
||||
|
||||
PRepeat::PRepeat(PExpr*e, Statement*s)
|
||||
: expr_(e), statement_(s)
|
||||
{
|
||||
@@ -155,6 +245,15 @@ PRepeat::~PRepeat()
|
||||
delete statement_;
|
||||
}
|
||||
|
||||
PTrigger::PTrigger(const string&e)
|
||||
: event_(e)
|
||||
{
|
||||
}
|
||||
|
||||
PTrigger::~PTrigger()
|
||||
{
|
||||
}
|
||||
|
||||
PWhile::~PWhile()
|
||||
{
|
||||
delete cond_;
|
||||
@@ -163,6 +262,38 @@ PWhile::~PWhile()
|
||||
|
||||
/*
|
||||
* $Log: Statement.cc,v $
|
||||
* 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)
|
||||
*
|
||||
* Revision 1.22 2000/07/26 05:08:07 steve
|
||||
* Parse disable statements to pform.
|
||||
*
|
||||
* Revision 1.21 2000/05/11 23:37:26 steve
|
||||
* Add support for procedural continuous assignment.
|
||||
*
|
||||
* Revision 1.20 2000/04/22 04:20:19 steve
|
||||
* Add support for force assignment.
|
||||
*
|
||||
* Revision 1.19 2000/04/12 04:23:57 steve
|
||||
* Named events really should be expressed with PEIdent
|
||||
* objects in the pform,
|
||||
*
|
||||
* Handle named events within the mix of net events
|
||||
* and edges. As a unified lot they get caught together.
|
||||
* wait statements are broken into more complex statements
|
||||
* that include a conditional.
|
||||
*
|
||||
* Do not generate NetPEvent or NetNEvent objects in
|
||||
* elaboration. NetEvent, NetEvWait and NetEvProbe
|
||||
* take over those functions in the netlist.
|
||||
*
|
||||
* Revision 1.18 2000/04/01 19:31:57 steve
|
||||
* Named events as far as the pform.
|
||||
*
|
||||
* Revision 1.17 2000/02/23 02:56:54 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.16 1999/09/29 18:36:02 steve
|
||||
* Full case support
|
||||
*
|
||||
|
||||
+158
-15
@@ -1,7 +1,7 @@
|
||||
#ifndef __Statement_H
|
||||
#define __Statement_H
|
||||
/*
|
||||
* Copyright (c) 1998 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2000 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,8 +18,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: Statement.h,v 1.20 1999/09/29 18:36:02 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: Statement.h,v 1.29 2000/09/09 15:21:26 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <string>
|
||||
@@ -30,6 +30,11 @@
|
||||
class PExpr;
|
||||
class Statement;
|
||||
class PEventStatement;
|
||||
class Design;
|
||||
class NetAssign_;
|
||||
class NetCAssign;
|
||||
class NetDeassign;
|
||||
class NetScope;
|
||||
|
||||
/*
|
||||
* The PProcess is the root of a behavioral process. Each process gets
|
||||
@@ -70,6 +75,7 @@ class Statement : public LineInfo {
|
||||
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual NetProc* elaborate(Design*des, const string&path) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -88,9 +94,7 @@ class PAssign_ : public Statement {
|
||||
const PExpr* rval() const { return rval_; }
|
||||
|
||||
protected:
|
||||
NetNet*elaborate_lval(Design*, const string&path,
|
||||
unsigned&lsb, unsigned&msb,
|
||||
NetExpr*&mux) const;
|
||||
NetAssign_* elaborate_lval(Design*, NetScope*scope) const;
|
||||
|
||||
PDelays delay_;
|
||||
PEventStatement*event_;
|
||||
@@ -155,6 +159,7 @@ class PBlock : public Statement {
|
||||
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual NetProc* elaborate(Design*des, const string&path) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
|
||||
private:
|
||||
string name_;
|
||||
@@ -204,6 +209,7 @@ class PCase : public Statement {
|
||||
~PCase();
|
||||
|
||||
virtual NetProc* elaborate(Design*des, const string&path) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
@@ -217,14 +223,28 @@ class PCase : public Statement {
|
||||
PCase& operator= (const PCase&);
|
||||
};
|
||||
|
||||
class PCAssign : public Statement {
|
||||
|
||||
public:
|
||||
explicit PCAssign(PExpr*l, PExpr*r);
|
||||
~PCAssign();
|
||||
|
||||
virtual NetCAssign* elaborate(Design*des, const string&path) const;
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
PExpr*lval_;
|
||||
PExpr*expr_;
|
||||
};
|
||||
|
||||
class PCondit : public Statement {
|
||||
|
||||
public:
|
||||
PCondit(PExpr*ex, Statement*i, Statement*e)
|
||||
: expr_(ex), if_(i), else_(e) { }
|
||||
PCondit(PExpr*ex, Statement*i, Statement*e);
|
||||
~PCondit();
|
||||
|
||||
virtual NetProc* elaborate(Design*des, const string&path) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
@@ -237,34 +257,72 @@ class PCondit : public Statement {
|
||||
PCondit& operator= (const PCondit&);
|
||||
};
|
||||
|
||||
class PDeassign : public Statement {
|
||||
|
||||
public:
|
||||
explicit PDeassign(PExpr*l);
|
||||
~PDeassign();
|
||||
|
||||
virtual NetDeassign* elaborate(Design*des, const string&path) const;
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
PExpr*lval_;
|
||||
};
|
||||
|
||||
class PDelayStatement : public Statement {
|
||||
|
||||
public:
|
||||
PDelayStatement(PExpr*d, Statement*st)
|
||||
: delay_(d), statement_(st) { }
|
||||
PDelayStatement(PExpr*d, Statement*st);
|
||||
~PDelayStatement();
|
||||
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual NetProc* elaborate(Design*des, const string&path) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
|
||||
private:
|
||||
PExpr*delay_;
|
||||
Statement*statement_;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* This represends the parsing of a disable <scope> statement.
|
||||
*/
|
||||
class PDisable : public Statement {
|
||||
|
||||
public:
|
||||
explicit PDisable(const string&sc);
|
||||
~PDisable();
|
||||
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual NetProc* elaborate(Design*des, const string&path) const;
|
||||
|
||||
private:
|
||||
string scope_;
|
||||
};
|
||||
|
||||
/*
|
||||
* The event statement represents the event delay in behavioral
|
||||
* code. It comes from such things as:
|
||||
*
|
||||
* @name <statement>;
|
||||
* @(expr) <statement>;
|
||||
*/
|
||||
class PEventStatement : public Statement {
|
||||
|
||||
public:
|
||||
|
||||
PEventStatement(const svector<PEEvent*>&ee)
|
||||
: expr_(ee), statement_(0) { }
|
||||
explicit PEventStatement(const svector<PEEvent*>&ee);
|
||||
explicit PEventStatement(PEEvent*ee);
|
||||
|
||||
PEventStatement(PEEvent*ee)
|
||||
: expr_(1), statement_(0) { expr_[0] = ee; }
|
||||
~PEventStatement();
|
||||
|
||||
void set_statement(Statement*st) { statement_ = st; }
|
||||
void set_statement(Statement*st);
|
||||
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual NetProc* elaborate(Design*des, const string&path) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
|
||||
// This method is used to elaborate, but attach a previously
|
||||
// elaborated statement to the event.
|
||||
@@ -275,12 +333,27 @@ class PEventStatement : public Statement {
|
||||
Statement*statement_;
|
||||
};
|
||||
|
||||
class PForce : public Statement {
|
||||
|
||||
public:
|
||||
explicit PForce(PExpr*l, PExpr*r);
|
||||
~PForce();
|
||||
|
||||
virtual NetProc* elaborate(Design*des, const string&path) const;
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
PExpr*lval_;
|
||||
PExpr*expr_;
|
||||
};
|
||||
|
||||
class PForever : public Statement {
|
||||
public:
|
||||
explicit PForever(Statement*s);
|
||||
~PForever();
|
||||
|
||||
virtual NetProc* elaborate(Design*des, const string&path) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
@@ -297,6 +370,7 @@ class PForStatement : public Statement {
|
||||
{ }
|
||||
|
||||
virtual NetProc* elaborate(Design*des, const string&path) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
@@ -323,6 +397,7 @@ class PRepeat : public Statement {
|
||||
~PRepeat();
|
||||
|
||||
virtual NetProc* elaborate(Design*des, const string&path) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
@@ -330,6 +405,36 @@ class PRepeat : public Statement {
|
||||
Statement*statement_;
|
||||
};
|
||||
|
||||
class PRelease : public Statement {
|
||||
|
||||
public:
|
||||
explicit PRelease(PExpr*l);
|
||||
~PRelease();
|
||||
|
||||
virtual NetProc* elaborate(Design*des, const string&path) const;
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
PExpr*lval_;
|
||||
};
|
||||
|
||||
/*
|
||||
* The PTrigger statement sends a trigger to a named event. Take the
|
||||
* name here.
|
||||
*/
|
||||
class PTrigger : public Statement {
|
||||
|
||||
public:
|
||||
explicit PTrigger(const string&ev);
|
||||
~PTrigger();
|
||||
|
||||
virtual NetProc* elaborate(Design*des, const string&path) const;
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
string event_;
|
||||
};
|
||||
|
||||
class PWhile : public Statement {
|
||||
|
||||
public:
|
||||
@@ -338,6 +443,7 @@ class PWhile : public Statement {
|
||||
~PWhile();
|
||||
|
||||
virtual NetProc* elaborate(Design*des, const string&path) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
@@ -347,6 +453,43 @@ class PWhile : public Statement {
|
||||
|
||||
/*
|
||||
* $Log: Statement.h,v $
|
||||
* Revision 1.29 2000/09/09 15:21:26 steve
|
||||
* move lval elaboration to PExpr virtual methods.
|
||||
*
|
||||
* Revision 1.28 2000/09/03 17:58:35 steve
|
||||
* Change elaborate_lval to return NetAssign_ objects.
|
||||
*
|
||||
* Revision 1.27 2000/07/26 05:08:07 steve
|
||||
* Parse disable statements to pform.
|
||||
*
|
||||
* Revision 1.26 2000/05/11 23:37:26 steve
|
||||
* Add support for procedural continuous assignment.
|
||||
*
|
||||
* Revision 1.25 2000/04/22 04:20:19 steve
|
||||
* Add support for force assignment.
|
||||
*
|
||||
* Revision 1.24 2000/04/12 04:23:57 steve
|
||||
* Named events really should be expressed with PEIdent
|
||||
* objects in the pform,
|
||||
*
|
||||
* Handle named events within the mix of net events
|
||||
* and edges. As a unified lot they get caught together.
|
||||
* wait statements are broken into more complex statements
|
||||
* that include a conditional.
|
||||
*
|
||||
* Do not generate NetPEvent or NetNEvent objects in
|
||||
* elaboration. NetEvent, NetEvWait and NetEvProbe
|
||||
* take over those functions in the netlist.
|
||||
*
|
||||
* Revision 1.23 2000/04/01 19:31:57 steve
|
||||
* Named events as far as the pform.
|
||||
*
|
||||
* Revision 1.22 2000/03/11 03:25:51 steve
|
||||
* Locate scopes in statements.
|
||||
*
|
||||
* Revision 1.21 2000/02/23 02:56:54 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.20 1999/09/29 18:36:02 steve
|
||||
* Full case support
|
||||
*
|
||||
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
#!/bin/sh
|
||||
|
||||
#
|
||||
# This shell script exists to run autoconf on source distributions
|
||||
# that are pulled from CVS. The configure scripts are not included
|
||||
# in CVS, and there are several configure.in files, so it is easiest
|
||||
# to just run this script to autoconf wherever needed.
|
||||
#
|
||||
echo "Autoconf in root..."
|
||||
autoconf
|
||||
|
||||
for dir in vpip vvp tgt-vvp tgt-fpga
|
||||
do
|
||||
echo "Autoconf in $dir..."
|
||||
( cd $dir ; autoconf )
|
||||
done
|
||||
@@ -0,0 +1,6 @@
|
||||
|
||||
# The make check target uses this to check the compilation of the
|
||||
# compiler.
|
||||
|
||||
[-tvvm-check]
|
||||
<ivl>./ivl %W %[s-s%s] %[N-N%N] %[T-T%T] -tvvm -Fcprop -Fnodangle -fVPI_MODULE_PATH=vpi %f %m -o%o.cc -- -
|
||||
+49
-3
@@ -1,7 +1,7 @@
|
||||
#ifndef __compiler_H
|
||||
#define __compiler_H
|
||||
/*
|
||||
* Copyright (c) 1999 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1999-2000 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,8 +18,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: compiler.h,v 1.1 1999/06/06 20:42:48 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: compiler.h,v 1.5 2000/10/31 17:49:02 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -33,8 +33,54 @@
|
||||
# define INTEGER_WIDTH 32
|
||||
#endif
|
||||
|
||||
/* The TIME_WIDTH is the width of time variables. */
|
||||
#ifndef TIME_WIDTH
|
||||
# define TIME_WIDTH 64
|
||||
#endif
|
||||
|
||||
/*
|
||||
* When doing dynamic linking, we need a uniform way to identify the
|
||||
* symbol. Some compilers put leading _, some trailing _. The
|
||||
* configure script figures out which is the local convention and
|
||||
* defines NEED_LU and NEED_TU as required.
|
||||
*/
|
||||
#ifdef NEED_LU
|
||||
#define LU "_"
|
||||
#else
|
||||
#define LU ""
|
||||
#endif
|
||||
|
||||
#ifdef NEED_TU
|
||||
#define TU "_"
|
||||
#else
|
||||
#define TU ""
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* These are flags to enable various sorts of warnings. By default all
|
||||
* the warnings are of, the -W<list> parameter arranges for each to be
|
||||
* enabled.
|
||||
*/
|
||||
|
||||
/* Implicit definitions of wires. */
|
||||
extern bool warn_implicit;
|
||||
|
||||
/*
|
||||
* $Log: compiler.h,v $
|
||||
* Revision 1.5 2000/10/31 17:49:02 steve
|
||||
* Support time variables.
|
||||
*
|
||||
* Revision 1.4 2000/08/20 04:13:56 steve
|
||||
* Add ivl_target support for logic gates, and
|
||||
* make the interface more accessible.
|
||||
*
|
||||
* Revision 1.3 2000/03/17 21:50:25 steve
|
||||
* Switch to control warnings.
|
||||
*
|
||||
* Revision 1.2 2000/02/23 02:56:54 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.1 1999/06/06 20:42:48 steve
|
||||
* Make compiler width a compile time constant.
|
||||
*
|
||||
|
||||
Vendored
+411
-140
@@ -1,6 +1,7 @@
|
||||
#! /bin/sh
|
||||
# Attempt to guess a canonical system name.
|
||||
# Copyright (C) 1992, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
|
||||
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000
|
||||
# Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by
|
||||
@@ -22,7 +23,7 @@
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
# Written by Per Bothner <[email protected]>.
|
||||
# The master version of this file is at the FSF in /home/gd/gnu/lib.
|
||||
# Please send patches to <[email protected]>.
|
||||
#
|
||||
# This script attempts to guess a canonical system name similar to
|
||||
# config.sub. If it succeeds, it prints the system name on stdout, and
|
||||
@@ -35,6 +36,20 @@
|
||||
# (but try to keep the structure clean).
|
||||
#
|
||||
|
||||
# Use $HOST_CC if defined. $CC may point to a cross-compiler
|
||||
if test x"$CC_FOR_BUILD" = x; then
|
||||
if test x"$HOST_CC" != x; then
|
||||
CC_FOR_BUILD="$HOST_CC"
|
||||
else
|
||||
if test x"$CC" != x; then
|
||||
CC_FOR_BUILD="$CC"
|
||||
else
|
||||
CC_FOR_BUILD=cc
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
|
||||
# ([email protected] 8/24/94.)
|
||||
if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
|
||||
@@ -46,11 +61,49 @@ UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
|
||||
UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
|
||||
UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
|
||||
|
||||
trap 'rm -f dummy.c dummy.o dummy; exit 1' 1 2 15
|
||||
dummy=dummy-$$
|
||||
trap 'rm -f $dummy.c $dummy.o $dummy; exit 1' 1 2 15
|
||||
|
||||
# Note: order is significant - the case branches are not exclusive.
|
||||
|
||||
case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
||||
*:NetBSD:*:*)
|
||||
# Netbsd (nbsd) targets should (where applicable) match one or
|
||||
# more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
|
||||
# *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
|
||||
# switched to ELF, *-*-netbsd* would select the old
|
||||
# object file format. This provides both forward
|
||||
# compatibility and a consistent mechanism for selecting the
|
||||
# object file format.
|
||||
# Determine the machine/vendor (is the vendor relevant).
|
||||
case "${UNAME_MACHINE}" in
|
||||
amiga) machine=m68k-cbm ;;
|
||||
arm32) machine=arm-unknown ;;
|
||||
atari*) machine=m68k-atari ;;
|
||||
sun3*) machine=m68k-sun ;;
|
||||
mac68k) machine=m68k-apple ;;
|
||||
macppc) machine=powerpc-apple ;;
|
||||
hp3[0-9][05]) machine=m68k-hp ;;
|
||||
ibmrt|romp-ibm) machine=romp-ibm ;;
|
||||
*) machine=${UNAME_MACHINE}-unknown ;;
|
||||
esac
|
||||
# The Operating System including object format.
|
||||
if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
|
||||
| grep __ELF__ >/dev/null
|
||||
then
|
||||
# Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
|
||||
# Return netbsd for either. FIX?
|
||||
os=netbsd
|
||||
else
|
||||
os=netbsdelf
|
||||
fi
|
||||
# The OS release
|
||||
release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
|
||||
# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
|
||||
# contains redundant information, the shorter form:
|
||||
# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
|
||||
echo "${machine}-${os}${release}"
|
||||
exit 0 ;;
|
||||
alpha:OSF1:*:*)
|
||||
if test $UNAME_RELEASE = "V4.0"; then
|
||||
UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
|
||||
@@ -59,46 +112,62 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
||||
# A Tn.n version is a released field test version.
|
||||
# A Xn.n version is an unreleased experimental baselevel.
|
||||
# 1.2 uses "1.2" for uname -r.
|
||||
cat <<EOF >dummy.s
|
||||
cat <<EOF >$dummy.s
|
||||
.data
|
||||
\$Lformat:
|
||||
.byte 37,100,45,37,120,10,0 # "%d-%x\n"
|
||||
|
||||
.text
|
||||
.globl main
|
||||
.align 4
|
||||
.ent main
|
||||
main:
|
||||
.frame \$30,0,\$26,0
|
||||
.prologue 0
|
||||
.long 0x47e03d80 # implver $0
|
||||
lda \$2,259
|
||||
.long 0x47e20c21 # amask $2,$1
|
||||
srl \$1,8,\$2
|
||||
sll \$2,2,\$2
|
||||
sll \$0,3,\$0
|
||||
addl \$1,\$0,\$0
|
||||
addl \$2,\$0,\$0
|
||||
ret \$31,(\$26),1
|
||||
.frame \$30,16,\$26,0
|
||||
ldgp \$29,0(\$27)
|
||||
.prologue 1
|
||||
.long 0x47e03d80 # implver \$0
|
||||
lda \$2,-1
|
||||
.long 0x47e20c21 # amask \$2,\$1
|
||||
lda \$16,\$Lformat
|
||||
mov \$0,\$17
|
||||
not \$1,\$18
|
||||
jsr \$26,printf
|
||||
ldgp \$29,0(\$26)
|
||||
mov 0,\$16
|
||||
jsr \$26,exit
|
||||
.end main
|
||||
EOF
|
||||
${CC-cc} dummy.s -o dummy 2>/dev/null
|
||||
$CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null
|
||||
if test "$?" = 0 ; then
|
||||
./dummy
|
||||
case "$?" in
|
||||
7)
|
||||
case `./$dummy` in
|
||||
0-0)
|
||||
UNAME_MACHINE="alpha"
|
||||
;;
|
||||
15)
|
||||
1-0)
|
||||
UNAME_MACHINE="alphaev5"
|
||||
;;
|
||||
14)
|
||||
1-1)
|
||||
UNAME_MACHINE="alphaev56"
|
||||
;;
|
||||
10)
|
||||
1-101)
|
||||
UNAME_MACHINE="alphapca56"
|
||||
;;
|
||||
16)
|
||||
2-303)
|
||||
UNAME_MACHINE="alphaev6"
|
||||
;;
|
||||
2-307)
|
||||
UNAME_MACHINE="alphaev67"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
rm -f dummy.s dummy
|
||||
echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr [[A-Z]] [[a-z]]`
|
||||
rm -f $dummy.s $dummy
|
||||
echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
|
||||
exit 0 ;;
|
||||
Alpha\ *:Windows_NT*:*)
|
||||
# How do we know it's Interix rather than the generic POSIX subsystem?
|
||||
# Should we change UNAME_MACHINE based on the output of uname instead
|
||||
# of the specific Alpha model?
|
||||
echo alpha-pc-interix
|
||||
exit 0 ;;
|
||||
21064:Windows_NT:50:3)
|
||||
echo alpha-dec-winnt3.5
|
||||
@@ -106,12 +175,12 @@ EOF
|
||||
Amiga*:UNIX_System_V:4.0:*)
|
||||
echo m68k-cbm-sysv4
|
||||
exit 0;;
|
||||
amiga:NetBSD:*:*)
|
||||
echo m68k-cbm-netbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
amiga:OpenBSD:*:*)
|
||||
echo m68k-unknown-openbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
*:[Aa]miga[Oo][Ss]:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-amigaos
|
||||
exit 0 ;;
|
||||
arc64:OpenBSD:*:*)
|
||||
echo mips64el-unknown-openbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
@@ -130,16 +199,16 @@ EOF
|
||||
wgrisc:OpenBSD:*:*)
|
||||
echo mipsel-unknown-openbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
*:OS/390:*:*)
|
||||
echo i370-ibm-openedition
|
||||
exit 0 ;;
|
||||
arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
|
||||
echo arm-acorn-riscix${UNAME_RELEASE}
|
||||
exit 0;;
|
||||
arm32:NetBSD:*:*)
|
||||
echo arm-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
|
||||
exit 0 ;;
|
||||
SR2?01:HI-UX/MPP:*:*)
|
||||
echo hppa1.1-hitachi-hiuxmpp
|
||||
exit 0;;
|
||||
Pyramid*:OSx*:*:*|MIS*:OSx*:*:*)
|
||||
Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
|
||||
# [email protected] (Earle F. Ake) contributed MIS and NILE.
|
||||
if test "`(/bin/universe) 2>/dev/null`" = att ; then
|
||||
echo pyramid-pyramid-sysv3
|
||||
@@ -147,9 +216,12 @@ EOF
|
||||
echo pyramid-pyramid-bsd
|
||||
fi
|
||||
exit 0 ;;
|
||||
NILE:*:*:dcosx)
|
||||
NILE*:*:*:dcosx)
|
||||
echo pyramid-pyramid-svr4
|
||||
exit 0 ;;
|
||||
sun4H:SunOS:5.*:*)
|
||||
echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
|
||||
exit 0 ;;
|
||||
sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
|
||||
echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
|
||||
exit 0 ;;
|
||||
@@ -189,21 +261,38 @@ EOF
|
||||
aushp:SunOS:*:*)
|
||||
echo sparc-auspex-sunos${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
atari*:NetBSD:*:*)
|
||||
echo m68k-atari-netbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
atari*:OpenBSD:*:*)
|
||||
echo m68k-unknown-openbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
sun3*:NetBSD:*:*)
|
||||
echo m68k-sun-netbsd${UNAME_RELEASE}
|
||||
# The situation for MiNT is a little confusing. The machine name
|
||||
# can be virtually everything (everything which is not
|
||||
# "atarist" or "atariste" at least should have a processor
|
||||
# > m68000). The system name ranges from "MiNT" over "FreeMiNT"
|
||||
# to the lowercase version "mint" (or "freemint"). Finally
|
||||
# the system name "TOS" denotes a system which is actually not
|
||||
# MiNT. But MiNT is downward compatible to TOS, so this should
|
||||
# be no problem.
|
||||
atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
|
||||
echo m68k-atari-mint${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
|
||||
echo m68k-atari-mint${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
*falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
|
||||
echo m68k-atari-mint${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
|
||||
echo m68k-milan-mint${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
|
||||
echo m68k-hades-mint${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
*:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
|
||||
echo m68k-unknown-mint${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
sun3*:OpenBSD:*:*)
|
||||
echo m68k-unknown-openbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
mac68k:NetBSD:*:*)
|
||||
echo m68k-apple-netbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
mac68k:OpenBSD:*:*)
|
||||
echo m68k-unknown-openbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
@@ -225,12 +314,17 @@ EOF
|
||||
VAX*:ULTRIX*:*:*)
|
||||
echo vax-dec-ultrix${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
2020:CLIX:*:*)
|
||||
2020:CLIX:*:* | 2430:CLIX:*:*)
|
||||
echo clipper-intergraph-clix${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
mips:*:*:UMIPS | mips:*:*:RISCos)
|
||||
sed 's/^ //' << EOF >dummy.c
|
||||
int main (argc, argv) int argc; char **argv; {
|
||||
sed 's/^ //' << EOF >$dummy.c
|
||||
#ifdef __cplusplus
|
||||
#include <stdio.h> /* for printf() prototype */
|
||||
int main (int argc, char *argv[]) {
|
||||
#else
|
||||
int main (argc, argv) int argc; char *argv[]; {
|
||||
#endif
|
||||
#if defined (host_mips) && defined (MIPSEB)
|
||||
#if defined (SYSTYPE_SYSV)
|
||||
printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
|
||||
@@ -245,10 +339,10 @@ EOF
|
||||
exit (-1);
|
||||
}
|
||||
EOF
|
||||
${CC-cc} dummy.c -o dummy \
|
||||
&& ./dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
|
||||
&& rm dummy.c dummy && exit 0
|
||||
rm -f dummy.c dummy
|
||||
$CC_FOR_BUILD $dummy.c -o $dummy \
|
||||
&& ./$dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
|
||||
&& rm $dummy.c $dummy && exit 0
|
||||
rm -f $dummy.c $dummy
|
||||
echo mips-mips-riscos${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
Night_Hawk:Power_UNIX:*:*)
|
||||
@@ -266,15 +360,18 @@ EOF
|
||||
AViiON:dgux:*:*)
|
||||
# DG/UX returns AViiON for all architectures
|
||||
UNAME_PROCESSOR=`/usr/bin/uname -p`
|
||||
if [ $UNAME_PROCESSOR = mc88100 -o $UNAME_PROCESSOR = mc88110 ] ; then
|
||||
if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx \
|
||||
-o ${TARGET_BINARY_INTERFACE}x = x ] ; then
|
||||
if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
|
||||
then
|
||||
if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
|
||||
[ ${TARGET_BINARY_INTERFACE}x = x ]
|
||||
then
|
||||
echo m88k-dg-dgux${UNAME_RELEASE}
|
||||
else
|
||||
else
|
||||
echo m88k-dg-dguxbcs${UNAME_RELEASE}
|
||||
fi
|
||||
else
|
||||
echo i586-dg-dgux${UNAME_RELEASE}
|
||||
fi
|
||||
else echo i586-dg-dgux${UNAME_RELEASE}
|
||||
fi
|
||||
exit 0 ;;
|
||||
M88*:DolphinOS:*:*) # DolphinOS (SVR3)
|
||||
echo m88k-dolphin-sysv3
|
||||
@@ -300,7 +397,7 @@ EOF
|
||||
exit 0 ;;
|
||||
*:AIX:2:3)
|
||||
if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
|
||||
sed 's/^ //' << EOF >dummy.c
|
||||
sed 's/^ //' << EOF >$dummy.c
|
||||
#include <sys/systemcfg.h>
|
||||
|
||||
main()
|
||||
@@ -311,8 +408,8 @@ EOF
|
||||
exit(0);
|
||||
}
|
||||
EOF
|
||||
${CC-cc} dummy.c -o dummy && ./dummy && rm dummy.c dummy && exit 0
|
||||
rm -f dummy.c dummy
|
||||
$CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm $dummy.c $dummy && exit 0
|
||||
rm -f $dummy.c $dummy
|
||||
echo rs6000-ibm-aix3.2.5
|
||||
elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
|
||||
echo rs6000-ibm-aix3.2.4
|
||||
@@ -321,7 +418,8 @@ EOF
|
||||
fi
|
||||
exit 0 ;;
|
||||
*:AIX:*:4)
|
||||
if /usr/sbin/lsattr -EHl proc0 | grep POWER >/dev/null 2>&1; then
|
||||
IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | head -1 | awk '{ print $1 }'`
|
||||
if /usr/sbin/lsattr -EHl ${IBM_CPU_ID} | grep POWER >/dev/null 2>&1; then
|
||||
IBM_ARCH=rs6000
|
||||
else
|
||||
IBM_ARCH=powerpc
|
||||
@@ -339,7 +437,7 @@ EOF
|
||||
ibmrt:4.4BSD:*|romp-ibm:BSD:*)
|
||||
echo romp-ibm-bsd4.4
|
||||
exit 0 ;;
|
||||
ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC NetBSD and
|
||||
ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
|
||||
echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
|
||||
exit 0 ;; # report: romp-ibm BSD 4.3
|
||||
*:BOSX:*:*)
|
||||
@@ -354,18 +452,52 @@ EOF
|
||||
hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
|
||||
echo m68k-hp-bsd4.4
|
||||
exit 0 ;;
|
||||
9000/[3478]??:HP-UX:*:*)
|
||||
9000/[34678]??:HP-UX:*:*)
|
||||
case "${UNAME_MACHINE}" in
|
||||
9000/31? ) HP_ARCH=m68000 ;;
|
||||
9000/[34]?? ) HP_ARCH=m68k ;;
|
||||
9000/7?? | 9000/8?[1679] ) HP_ARCH=hppa1.1 ;;
|
||||
9000/8?? ) HP_ARCH=hppa1.0 ;;
|
||||
9000/[678][0-9][0-9])
|
||||
sed 's/^ //' << EOF >$dummy.c
|
||||
|
||||
#define _HPUX_SOURCE
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int main ()
|
||||
{
|
||||
#if defined(_SC_KERNEL_BITS)
|
||||
long bits = sysconf(_SC_KERNEL_BITS);
|
||||
#endif
|
||||
long cpu = sysconf (_SC_CPU_VERSION);
|
||||
|
||||
switch (cpu)
|
||||
{
|
||||
case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
|
||||
case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
|
||||
case CPU_PA_RISC2_0:
|
||||
#if defined(_SC_KERNEL_BITS)
|
||||
switch (bits)
|
||||
{
|
||||
case 64: puts ("hppa2.0w"); break;
|
||||
case 32: puts ("hppa2.0n"); break;
|
||||
default: puts ("hppa2.0"); break;
|
||||
} break;
|
||||
#else /* !defined(_SC_KERNEL_BITS) */
|
||||
puts ("hppa2.0"); break;
|
||||
#endif
|
||||
default: puts ("hppa1.0"); break;
|
||||
}
|
||||
exit (0);
|
||||
}
|
||||
EOF
|
||||
(CCOPTS= $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null ) && HP_ARCH=`./$dummy`
|
||||
rm -f $dummy.c $dummy
|
||||
esac
|
||||
HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
|
||||
echo ${HP_ARCH}-hp-hpux${HPUX_REV}
|
||||
exit 0 ;;
|
||||
3050*:HI-UX:*:*)
|
||||
sed 's/^ //' << EOF >dummy.c
|
||||
sed 's/^ //' << EOF >$dummy.c
|
||||
#include <unistd.h>
|
||||
int
|
||||
main ()
|
||||
@@ -390,8 +522,8 @@ EOF
|
||||
exit (0);
|
||||
}
|
||||
EOF
|
||||
${CC-cc} dummy.c -o dummy && ./dummy && rm dummy.c dummy && exit 0
|
||||
rm -f dummy.c dummy
|
||||
$CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm $dummy.c $dummy && exit 0
|
||||
rm -f $dummy.c $dummy
|
||||
echo unknown-hitachi-hiuxwe2
|
||||
exit 0 ;;
|
||||
9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
|
||||
@@ -400,6 +532,9 @@ EOF
|
||||
9000/8??:4.3bsd:*:*)
|
||||
echo hppa1.0-hp-bsd
|
||||
exit 0 ;;
|
||||
*9??*:MPE/iX:*:*)
|
||||
echo hppa1.0-hp-mpeix
|
||||
exit 0 ;;
|
||||
hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
|
||||
echo hppa1.1-hp-osf
|
||||
exit 0 ;;
|
||||
@@ -416,6 +551,9 @@ EOF
|
||||
parisc*:Lites*:*:*)
|
||||
echo hppa1.1-hp-lites
|
||||
exit 0 ;;
|
||||
hppa*:OpenBSD:*:*)
|
||||
echo hppa-unknown-openbsd
|
||||
exit 0 ;;
|
||||
C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
|
||||
echo c1-convex-bsd
|
||||
exit 0 ;;
|
||||
@@ -446,45 +584,60 @@ EOF
|
||||
-e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/
|
||||
exit 0 ;;
|
||||
CRAY*TS:*:*:*)
|
||||
echo t90-cray-unicos${UNAME_RELEASE}
|
||||
echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
|
||||
exit 0 ;;
|
||||
CRAY*T3E:*:*:*)
|
||||
echo alpha-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
|
||||
exit 0 ;;
|
||||
CRAY*SV1:*:*:*)
|
||||
echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
|
||||
exit 0 ;;
|
||||
CRAY-2:*:*:*)
|
||||
echo cray2-cray-unicos
|
||||
exit 0 ;;
|
||||
F300:UNIX_System_V:*:*)
|
||||
FUJITSU_SYS=`uname -p | tr [A-Z] [a-z] | sed -e 's/\///'`
|
||||
FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
|
||||
FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
|
||||
echo "f300-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
|
||||
exit 0 ;;
|
||||
F301:UNIX_System_V:*:*)
|
||||
echo f301-fujitsu-uxpv`echo $UNAME_RELEASE | sed 's/ .*//'`
|
||||
exit 0 ;;
|
||||
hp3[0-9][05]:NetBSD:*:*)
|
||||
echo m68k-hp-netbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
hp300:OpenBSD:*:*)
|
||||
echo m68k-unknown-openbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
i?86:BSD/386:*:* | *:BSD/OS:*:*)
|
||||
i?86:BSD/386:*:* | i?86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
|
||||
echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
sparc*:BSD/OS:*:*)
|
||||
echo sparc-unknown-bsdi${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
*:BSD/OS:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
*:FreeBSD:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
|
||||
exit 0 ;;
|
||||
*:NetBSD:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
|
||||
exit 0 ;;
|
||||
*:OpenBSD:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-openbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
|
||||
exit 0 ;;
|
||||
i*:CYGWIN*:*)
|
||||
echo i386-pc-cygwin32
|
||||
echo ${UNAME_MACHINE}-pc-cygwin
|
||||
exit 0 ;;
|
||||
i*:MINGW*:*)
|
||||
echo i386-pc-mingw32
|
||||
echo ${UNAME_MACHINE}-pc-mingw32
|
||||
exit 0 ;;
|
||||
i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
|
||||
# How do we know it's Interix rather than the generic POSIX subsystem?
|
||||
# It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
|
||||
# UNAME_MACHINE based on the output of uname instead of i386?
|
||||
echo i386-pc-interix
|
||||
exit 0 ;;
|
||||
i*:UWIN*:*)
|
||||
echo ${UNAME_MACHINE}-pc-uwin
|
||||
exit 0 ;;
|
||||
p*:CYGWIN*:*)
|
||||
echo powerpcle-unknown-cygwin32
|
||||
echo powerpcle-unknown-cygwin
|
||||
exit 0 ;;
|
||||
prep*:SunOS:5.*:*)
|
||||
echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
|
||||
@@ -493,9 +646,11 @@ EOF
|
||||
echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
|
||||
exit 0 ;;
|
||||
*:Linux:*:*)
|
||||
|
||||
# The BFD linker knows what the default object file format is, so
|
||||
# first see if it will tell us.
|
||||
ld_help_string=`ld --help 2>&1`
|
||||
# first see if it will tell us. cd to the root directory to prevent
|
||||
# problems with other programs or directories called `ld' in the path.
|
||||
ld_help_string=`cd /; ld --help 2>&1`
|
||||
ld_supported_emulations=`echo $ld_help_string \
|
||||
| sed -ne '/supported emulations:/!d
|
||||
s/[ ][ ]*/ /g
|
||||
@@ -503,13 +658,45 @@ EOF
|
||||
s/ .*//
|
||||
p'`
|
||||
case "$ld_supported_emulations" in
|
||||
i?86linux) echo "${UNAME_MACHINE}-pc-linux-gnuaout" ; exit 0 ;;
|
||||
i?86coff) echo "${UNAME_MACHINE}-pc-linux-gnucoff" ; exit 0 ;;
|
||||
sparclinux) echo "${UNAME_MACHINE}-unknown-linux-gnuaout" ; exit 0 ;;
|
||||
m68klinux) echo "${UNAME_MACHINE}-unknown-linux-gnuaout" ; exit 0 ;;
|
||||
elf32ppc)
|
||||
*ia64)
|
||||
echo "${UNAME_MACHINE}-unknown-linux"
|
||||
exit 0
|
||||
;;
|
||||
i?86linux)
|
||||
echo "${UNAME_MACHINE}-pc-linux-gnuaout"
|
||||
exit 0
|
||||
;;
|
||||
elf_i?86)
|
||||
echo "${UNAME_MACHINE}-pc-linux"
|
||||
exit 0
|
||||
;;
|
||||
i?86coff)
|
||||
echo "${UNAME_MACHINE}-pc-linux-gnucoff"
|
||||
exit 0
|
||||
;;
|
||||
sparclinux)
|
||||
echo "${UNAME_MACHINE}-unknown-linux-gnuaout"
|
||||
exit 0
|
||||
;;
|
||||
armlinux)
|
||||
echo "${UNAME_MACHINE}-unknown-linux-gnuaout"
|
||||
exit 0
|
||||
;;
|
||||
elf32arm*)
|
||||
echo "${UNAME_MACHINE}-unknown-linux-gnuoldld"
|
||||
exit 0
|
||||
;;
|
||||
armelf_linux*)
|
||||
echo "${UNAME_MACHINE}-unknown-linux-gnu"
|
||||
exit 0
|
||||
;;
|
||||
m68klinux)
|
||||
echo "${UNAME_MACHINE}-unknown-linux-gnuaout"
|
||||
exit 0
|
||||
;;
|
||||
elf32ppc | elf32ppclinux)
|
||||
# Determine Lib Version
|
||||
cat >dummy.c <<EOF
|
||||
cat >$dummy.c <<EOF
|
||||
#include <features.h>
|
||||
#if defined(__GLIBC__)
|
||||
extern char __libc_version[];
|
||||
@@ -528,71 +715,85 @@ main(argc, argv)
|
||||
}
|
||||
EOF
|
||||
LIBC=""
|
||||
${CC-cc} dummy.c -o dummy 2>/dev/null
|
||||
$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null
|
||||
if test "$?" = 0 ; then
|
||||
./dummy | grep 1\.99 > /dev/null
|
||||
./$dummy | grep 1\.99 > /dev/null
|
||||
if test "$?" = 0 ; then
|
||||
LIBC="libc1"
|
||||
fi
|
||||
fi
|
||||
rm -f dummy.c dummy
|
||||
echo powerpc-unknown-linux-gnu${LIBC} ; exit 0 ;;
|
||||
fi
|
||||
rm -f $dummy.c $dummy
|
||||
echo powerpc-unknown-linux-gnu${LIBC}
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
|
||||
if test "${UNAME_MACHINE}" = "alpha" ; then
|
||||
sed 's/^ //' <<EOF >dummy.s
|
||||
.globl main
|
||||
.ent main
|
||||
main:
|
||||
.frame \$30,0,\$26,0
|
||||
.prologue 0
|
||||
.long 0x47e03d80 # implver $0
|
||||
lda \$2,259
|
||||
.long 0x47e20c21 # amask $2,$1
|
||||
srl \$1,8,\$2
|
||||
sll \$2,2,\$2
|
||||
sll \$0,3,\$0
|
||||
addl \$1,\$0,\$0
|
||||
addl \$2,\$0,\$0
|
||||
ret \$31,(\$26),1
|
||||
.end main
|
||||
cat <<EOF >$dummy.s
|
||||
.data
|
||||
\$Lformat:
|
||||
.byte 37,100,45,37,120,10,0 # "%d-%x\n"
|
||||
|
||||
.text
|
||||
.globl main
|
||||
.align 4
|
||||
.ent main
|
||||
main:
|
||||
.frame \$30,16,\$26,0
|
||||
ldgp \$29,0(\$27)
|
||||
.prologue 1
|
||||
.long 0x47e03d80 # implver \$0
|
||||
lda \$2,-1
|
||||
.long 0x47e20c21 # amask \$2,\$1
|
||||
lda \$16,\$Lformat
|
||||
mov \$0,\$17
|
||||
not \$1,\$18
|
||||
jsr \$26,printf
|
||||
ldgp \$29,0(\$26)
|
||||
mov 0,\$16
|
||||
jsr \$26,exit
|
||||
.end main
|
||||
EOF
|
||||
LIBC=""
|
||||
${CC-cc} dummy.s -o dummy 2>/dev/null
|
||||
$CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null
|
||||
if test "$?" = 0 ; then
|
||||
./dummy
|
||||
case "$?" in
|
||||
7)
|
||||
case `./$dummy` in
|
||||
0-0)
|
||||
UNAME_MACHINE="alpha"
|
||||
;;
|
||||
15)
|
||||
1-0)
|
||||
UNAME_MACHINE="alphaev5"
|
||||
;;
|
||||
14)
|
||||
1-1)
|
||||
UNAME_MACHINE="alphaev56"
|
||||
;;
|
||||
10)
|
||||
1-101)
|
||||
UNAME_MACHINE="alphapca56"
|
||||
;;
|
||||
16)
|
||||
2-303)
|
||||
UNAME_MACHINE="alphaev6"
|
||||
;;
|
||||
esac
|
||||
2-307)
|
||||
UNAME_MACHINE="alphaev67"
|
||||
;;
|
||||
esac
|
||||
|
||||
objdump --private-headers dummy | \
|
||||
objdump --private-headers $dummy | \
|
||||
grep ld.so.1 > /dev/null
|
||||
if test "$?" = 0 ; then
|
||||
LIBC="libc1"
|
||||
fi
|
||||
fi
|
||||
rm -f dummy.s dummy
|
||||
fi
|
||||
rm -f $dummy.s $dummy
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} ; exit 0
|
||||
elif test "${UNAME_MACHINE}" = "mips" ; then
|
||||
cat >dummy.c <<EOF
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
cat >$dummy.c <<EOF
|
||||
#ifdef __cplusplus
|
||||
#include <stdio.h> /* for printf() prototype */
|
||||
int main (int argc, char *argv[]) {
|
||||
#else
|
||||
int main (argc, argv) int argc; char *argv[]; {
|
||||
#endif
|
||||
#ifdef __MIPSEB__
|
||||
printf ("%s-unknown-linux-gnu\n", argv[1]);
|
||||
#endif
|
||||
@@ -602,8 +803,10 @@ main(argc, argv)
|
||||
return 0;
|
||||
}
|
||||
EOF
|
||||
${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy "${UNAME_MACHINE}" && rm dummy.c dummy && exit 0
|
||||
rm -f dummy.c dummy
|
||||
$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm $dummy.c $dummy && exit 0
|
||||
rm -f $dummy.c $dummy
|
||||
elif test "${UNAME_MACHINE}" = "s390"; then
|
||||
echo s390-ibm-linux && exit 0
|
||||
else
|
||||
# Either a pre-BFD a.out linker (linux-gnuoldld)
|
||||
# or one that does not give us useful --help.
|
||||
@@ -622,12 +825,14 @@ EOF
|
||||
;;
|
||||
esac
|
||||
# Determine whether the default compiler is a.out or elf
|
||||
cat >dummy.c <<EOF
|
||||
cat >$dummy.c <<EOF
|
||||
#include <features.h>
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
#ifdef __cplusplus
|
||||
#include <stdio.h> /* for printf() prototype */
|
||||
int main (int argc, char *argv[]) {
|
||||
#else
|
||||
int main (argc, argv) int argc; char *argv[]; {
|
||||
#endif
|
||||
#ifdef __ELF__
|
||||
# ifdef __GLIBC__
|
||||
# if __GLIBC__ >= 2
|
||||
@@ -644,8 +849,8 @@ main(argc, argv)
|
||||
return 0;
|
||||
}
|
||||
EOF
|
||||
${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy "${UNAME_MACHINE}" && rm dummy.c dummy && exit 0
|
||||
rm -f dummy.c dummy
|
||||
$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm $dummy.c $dummy && exit 0
|
||||
rm -f $dummy.c $dummy
|
||||
fi ;;
|
||||
# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. earlier versions
|
||||
# are messed up and put the nodename in both sysname and nodename.
|
||||
@@ -661,10 +866,20 @@ EOF
|
||||
echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
|
||||
exit 0 ;;
|
||||
i?86:*:4.*:* | i?86:SYSTEM_V:4.*:*)
|
||||
UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
|
||||
if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
|
||||
echo ${UNAME_MACHINE}-univel-sysv${UNAME_RELEASE}
|
||||
echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
|
||||
else
|
||||
echo ${UNAME_MACHINE}-pc-sysv${UNAME_RELEASE}
|
||||
echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
|
||||
fi
|
||||
exit 0 ;;
|
||||
i?86:*:5:7*)
|
||||
# Fixed at (any) Pentium or better
|
||||
UNAME_MACHINE=i586
|
||||
if [ ${UNAME_SYSTEM} = "UnixWare" ] ; then
|
||||
echo ${UNAME_MACHINE}-sco-sysv${UNAME_RELEASE}uw${UNAME_VERSION}
|
||||
else
|
||||
echo ${UNAME_MACHINE}-pc-sysv${UNAME_RELEASE}
|
||||
fi
|
||||
exit 0 ;;
|
||||
i?86:*:3.2:*)
|
||||
@@ -676,12 +891,20 @@ EOF
|
||||
(/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486
|
||||
(/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \
|
||||
&& UNAME_MACHINE=i586
|
||||
(/bin/uname -X|egrep '^Machine.*Pent ?II' >/dev/null) \
|
||||
&& UNAME_MACHINE=i686
|
||||
(/bin/uname -X|egrep '^Machine.*Pentium Pro' >/dev/null) \
|
||||
&& UNAME_MACHINE=i686
|
||||
echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
|
||||
else
|
||||
echo ${UNAME_MACHINE}-pc-sysv32
|
||||
fi
|
||||
exit 0 ;;
|
||||
i?86:*DOS:*:*)
|
||||
echo ${UNAME_MACHINE}-pc-msdosdjgpp
|
||||
exit 0 ;;
|
||||
pc:*:*:*)
|
||||
# Left here for compatibility:
|
||||
# uname -m prints for DJGPP always 'pc', but it prints nothing about
|
||||
# the processor, so we play safe by assuming i386.
|
||||
echo i386-pc-msdosdjgpp
|
||||
@@ -722,7 +945,7 @@ EOF
|
||||
mc68030:UNIX_System_V:4.*:*)
|
||||
echo m68k-atari-sysv4
|
||||
exit 0 ;;
|
||||
i?86:LynxOS:2.*:*)
|
||||
i?86:LynxOS:2.*:* | i?86:LynxOS:3.[01]*:*)
|
||||
echo i386-unknown-lynxos${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
TSUNAMI:LynxOS:2.*:*)
|
||||
@@ -734,6 +957,9 @@ EOF
|
||||
SM[BE]S:UNIX_SV:*:*)
|
||||
echo mips-dde-sysv${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
RM*:ReliantUNIX-*:*:*)
|
||||
echo mips-sni-sysv4
|
||||
exit 0 ;;
|
||||
RM*:SINIX-*:*:*)
|
||||
echo mips-sni-sysv4
|
||||
exit 0 ;;
|
||||
@@ -764,19 +990,61 @@ EOF
|
||||
news*:NEWS-OS:*:6*)
|
||||
echo mips-sony-newsos6
|
||||
exit 0 ;;
|
||||
R3000:*System_V*:*:* | R4000:UNIX_SYSV:*:*)
|
||||
R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
|
||||
if [ -d /usr/nec ]; then
|
||||
echo mips-nec-sysv${UNAME_RELEASE}
|
||||
else
|
||||
echo mips-unknown-sysv${UNAME_RELEASE}
|
||||
fi
|
||||
exit 0 ;;
|
||||
BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
|
||||
echo powerpc-be-beos
|
||||
exit 0 ;;
|
||||
BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
|
||||
echo powerpc-apple-beos
|
||||
exit 0 ;;
|
||||
BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
|
||||
echo i586-pc-beos
|
||||
exit 0 ;;
|
||||
SX-4:SUPER-UX:*:*)
|
||||
echo sx4-nec-superux${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
SX-5:SUPER-UX:*:*)
|
||||
echo sx5-nec-superux${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
Power*:Rhapsody:*:*)
|
||||
echo powerpc-apple-rhapsody${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
*:Rhapsody:*:*)
|
||||
echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
*:Darwin:*:*)
|
||||
echo `uname -p`-apple-darwin${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
*:procnto*:*:* | *:QNX:[0123456789]*:*)
|
||||
if test "${UNAME_MACHINE}" = "x86pc"; then
|
||||
UNAME_MACHINE=pc
|
||||
fi
|
||||
echo `uname -p`-${UNAME_MACHINE}-nto-qnx
|
||||
exit 0 ;;
|
||||
*:QNX:*:4*)
|
||||
echo i386-pc-qnx
|
||||
exit 0 ;;
|
||||
NSR-W:NONSTOP_KERNEL:*:*)
|
||||
echo nsr-tandem-nsk${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
BS2000:POSIX*:*:*)
|
||||
echo bs2000-siemens-sysv
|
||||
exit 0 ;;
|
||||
DS/*:UNIX_System_V:*:*)
|
||||
echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
esac
|
||||
|
||||
#echo '(No uname command or uname output not recognized.)' 1>&2
|
||||
#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
|
||||
|
||||
cat >dummy.c <<EOF
|
||||
cat >$dummy.c <<EOF
|
||||
#ifdef _SEQUENT_
|
||||
# include <sys/types.h>
|
||||
# include <sys/utsname.h>
|
||||
@@ -814,7 +1082,10 @@ main ()
|
||||
#endif
|
||||
int version;
|
||||
version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
|
||||
printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
|
||||
if (version < 4)
|
||||
printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
|
||||
else
|
||||
printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
|
||||
exit (0);
|
||||
#endif
|
||||
|
||||
@@ -874,8 +1145,8 @@ main ()
|
||||
}
|
||||
EOF
|
||||
|
||||
${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy && rm dummy.c dummy && exit 0
|
||||
rm -f dummy.c dummy
|
||||
$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy && rm $dummy.c $dummy && exit 0
|
||||
rm -f $dummy.c $dummy
|
||||
|
||||
# Apollos put the system type in the environment.
|
||||
|
||||
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
#ifndef __config_H /* -*- c++ -*- */
|
||||
#define __config_H
|
||||
/*
|
||||
* Copyright (c) 2001 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
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: config.h.in,v 1.1 2001/07/25 03:10:48 steve Exp $"
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus)
|
||||
# if !defined(__GNUC__)
|
||||
using namespace std;
|
||||
# elif (__GNUC__ == 3)
|
||||
using namespace std;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
# undef NEED_LU
|
||||
# undef NEED_TU
|
||||
# undef WLU
|
||||
# undef WTU
|
||||
# undef HAVE_TIMES
|
||||
# undef HAVE_IOSFWD
|
||||
# undef HAVE_GETOPT_H
|
||||
# undef HAVE_DLFCN_H
|
||||
# undef HAVE_DL_H
|
||||
# undef HAVE_FCHMOD
|
||||
# undef HAVE_LIBREADLINE
|
||||
|
||||
/*
|
||||
* $Log: config.h.in,v $
|
||||
* Revision 1.1 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)
|
||||
*
|
||||
*/
|
||||
#endif // __config_H
|
||||
Vendored
+236
-146
@@ -1,6 +1,8 @@
|
||||
#! /bin/sh
|
||||
# Configuration validation subroutine script, version 1.1.
|
||||
# Copyright (C) 1991, 92, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
|
||||
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000
|
||||
# Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is (in principle) common to ALL GNU software.
|
||||
# The presence of a machine in this file suggests that SOME GNU software
|
||||
# can handle that machine. It does not imply ALL GNU software can.
|
||||
@@ -25,6 +27,9 @@
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
# Written by Per Bothner <[email protected]>.
|
||||
# Please send patches to <[email protected]>.
|
||||
#
|
||||
# Configuration subroutine to validate and canonicalize a configuration type.
|
||||
# Supply the specified configuration type as an argument.
|
||||
# If it is invalid, we print an error message on stderr and exit with code 1.
|
||||
@@ -68,7 +73,7 @@ esac
|
||||
# Here we must recognize all the valid KERNEL-OS combinations.
|
||||
maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
|
||||
case $maybe_os in
|
||||
linux-gnu*)
|
||||
nto-qnx* | linux-gnu*)
|
||||
os=-$maybe_os
|
||||
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
|
||||
;;
|
||||
@@ -98,21 +103,21 @@ case $os in
|
||||
os=
|
||||
basic_machine=$1
|
||||
;;
|
||||
-sim | -cisco | -oki | -wec | -winbond ) # CYGNUS LOCAL
|
||||
-sim | -cisco | -oki | -wec | -winbond)
|
||||
os=
|
||||
basic_machine=$1
|
||||
;;
|
||||
-scout) # CYGNUS LOCAL
|
||||
-scout)
|
||||
;;
|
||||
-wrs) # CYGNUS LOCAL
|
||||
os=vxworks
|
||||
-wrs)
|
||||
os=-vxworks
|
||||
basic_machine=$1
|
||||
;;
|
||||
-hiux*)
|
||||
os=-hiuxwe2
|
||||
;;
|
||||
-sco5)
|
||||
os=sco3.2v5
|
||||
os=-sco3.2v5
|
||||
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
|
||||
;;
|
||||
-sco4)
|
||||
@@ -131,6 +136,9 @@ case $os in
|
||||
os=-sco3.2v2
|
||||
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
|
||||
;;
|
||||
-udk*)
|
||||
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
|
||||
;;
|
||||
-isc)
|
||||
os=-isc2.2
|
||||
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
|
||||
@@ -153,44 +161,40 @@ case $os in
|
||||
-psos*)
|
||||
os=-psos
|
||||
;;
|
||||
-mint | -mint[0-9]*)
|
||||
basic_machine=m68k-atari
|
||||
os=-mint
|
||||
;;
|
||||
esac
|
||||
|
||||
# Decode aliases for certain CPU-COMPANY combinations.
|
||||
case $basic_machine in
|
||||
# Recognize the basic CPU types without company name.
|
||||
# Some are omitted here because they have special meanings below.
|
||||
tahoe | i860 | m32r | m68k | m68000 | m88k | ns32k | arc | arm \
|
||||
| arme[lb] | pyramid | mn10200 | mn10300 \
|
||||
| tron | a29k | 580 | i960 | h8300 | hppa | hppa1.0 | hppa1.1 \
|
||||
| alpha | alphaev5 | alphaev56 | we32k | ns16k | clipper \
|
||||
| i370 | sh | powerpc | powerpcle | 1750a | dsp16xx | pdp11 \
|
||||
| mips64 | mipsel | mips64el | mips64orion | mips64orionel \
|
||||
| mipstx39 | mipstx39el \
|
||||
| sparc | sparclet | sparclite | sparc64 | v850)
|
||||
tahoe | i860 | ia64 | m32r | m68k | m68000 | m88k | ns32k | arc | arm \
|
||||
| arme[lb] | pyramid | mn10200 | mn10300 | tron | a29k \
|
||||
| 580 | i960 | h8300 \
|
||||
| x86 | ppcbe | mipsbe | mipsle | shbe | shle | armbe | armle \
|
||||
| hppa | hppa1.0 | hppa1.1 | hppa2.0 | hppa2.0w | hppa2.0n \
|
||||
| hppa64 \
|
||||
| alpha | alphaev[4-8] | alphaev56 | alphapca5[67] \
|
||||
| alphaev6[78] \
|
||||
| we32k | ns16k | clipper | i370 | sh | powerpc | powerpcle \
|
||||
| 1750a | dsp16xx | pdp11 | mips16 | mips64 | mipsel | mips64el \
|
||||
| mips64orion | mips64orionel | mipstx39 | mipstx39el \
|
||||
| mips64vr4300 | mips64vr4300el | mips64vr4100 | mips64vr4100el \
|
||||
| mips64vr5000 | miprs64vr5000el | mcore \
|
||||
| sparc | sparclet | sparclite | sparc64 | sparcv9 | v850 | c4x \
|
||||
| thumb | d10v | fr30 | avr)
|
||||
basic_machine=$basic_machine-unknown
|
||||
;;
|
||||
m88110 | m680[01234]0 | m683?2 | m68360 | z8k | v70 | h8500 | w65) # CYGNUS LOCAL
|
||||
basic_machine=$basic_machine-unknown
|
||||
;;
|
||||
mips64vr4300 | mips64vr4300el) # CYGNUS LOCAL jsmith/vr4300
|
||||
basic_machine=$basic_machine-unknown
|
||||
;;
|
||||
mips64vr4100 | mips64vr4100el) # CYGNUS LOCAL jsmith/vr4100
|
||||
basic_machine=$basic_machine-unknown
|
||||
;;
|
||||
mips64vr5000 | mips64vr5000el) # CYGNUS LOCAL ian/vr5000
|
||||
basic_machine=$basic_machine-unknown
|
||||
;;
|
||||
mips16) # CYGNUS LOCAL krk/mips16
|
||||
basic_machine=$basic_machine-unknown
|
||||
;;
|
||||
d10v) # CYGNUS LOCAL meissner/d10v
|
||||
basic_machine=$basic_machine-unknown
|
||||
m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | z8k | v70 | h8500 | w65 | pj | pjl)
|
||||
;;
|
||||
|
||||
# We use `pc' rather than `unknown'
|
||||
# because (1) that's what they normally are, and
|
||||
# (2) the word "unknown" tends to confuse beginning users.
|
||||
i[3456]86)
|
||||
i[34567]86)
|
||||
basic_machine=$basic_machine-pc
|
||||
;;
|
||||
# Object if more than one company name word.
|
||||
@@ -199,30 +203,32 @@ case $basic_machine in
|
||||
exit 1
|
||||
;;
|
||||
# Recognize the basic CPU types with company name.
|
||||
vax-* | tahoe-* | i[3456]86-* | i860-* | m32r-* | m68k-* | m68000-* \
|
||||
# FIXME: clean up the formatting here.
|
||||
vax-* | tahoe-* | i[34567]86-* | i860-* | ia64-* | m32r-* | m68k-* | m68000-* \
|
||||
| m88k-* | sparc-* | ns32k-* | fx80-* | arc-* | arm-* | c[123]* \
|
||||
| mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* \
|
||||
| power-* | none-* | 580-* | cray2-* | h8300-* | i960-* \
|
||||
| xmp-* | ymp-* | hppa-* | hppa1.0-* | hppa1.1-* \
|
||||
| alpha-* | alphaev5-* | alphaev56-* | we32k-* | cydra-* \
|
||||
| ns16k-* | pn-* | np1-* | xps100-* | clipper-* | orion-* \
|
||||
| power-* | none-* | 580-* | cray2-* | h8300-* | h8500-* | i960-* \
|
||||
| xmp-* | ymp-* \
|
||||
| x86-* | ppcbe-* | mipsbe-* | mipsle-* | shbe-* | shle-* | armbe-* | armle-* \
|
||||
| hppa-* | hppa1.0-* | hppa1.1-* | hppa2.0-* | hppa2.0w-* \
|
||||
| hppa2.0n-* | hppa64-* \
|
||||
| alpha-* | alphaev[4-8]-* | alphaev56-* | alphapca5[67]-* \
|
||||
| alphaev6[78]-* \
|
||||
| we32k-* | cydra-* | ns16k-* | pn-* | np1-* | xps100-* \
|
||||
| clipper-* | orion-* \
|
||||
| sparclite-* | pdp11-* | sh-* | powerpc-* | powerpcle-* \
|
||||
| sparc64-* | mips64-* | mipsel-* \
|
||||
| sparc64-* | sparcv9-* | sparc86x-* | mips16-* | mips64-* | mipsel-* \
|
||||
| mips64el-* | mips64orion-* | mips64orionel-* \
|
||||
| mipstx39-* | mipstx39el-* \
|
||||
| f301-*)
|
||||
;;
|
||||
m88110-* | m680[01234]0-* | m683?2-* | m68360-* | z8k-* | h8500-* | d10v-*) # CYGNUS LOCAL
|
||||
;;
|
||||
mips64vr4300-* | mips64vr4300el-*) # CYGNUS LOCAL jsmith/vr4300
|
||||
;;
|
||||
mips64vr4100-* | mips64vr4100el-*) # CYGNUS LOCAL jsmith/vr4100
|
||||
;;
|
||||
mips16-*) # CYGNUS LOCAL krk/mips16
|
||||
| mips64vr4100-* | mips64vr4100el-* | mips64vr4300-* | mips64vr4300el-* \
|
||||
| mipstx39-* | mipstx39el-* | mcore-* \
|
||||
| f301-* | armv*-* | s390-* | sv1-* | t3e-* \
|
||||
| m88110-* | m680[01234]0-* | m683?2-* | m68360-* | z8k-* | d10v-* \
|
||||
| thumb-* | v850-* | d30v-* | tic30-* | c30-* | fr30-* \
|
||||
| bs2000-*)
|
||||
;;
|
||||
# Recognize the various machine names and aliases which stand
|
||||
# for a CPU type and a company and sometimes even an OS.
|
||||
386bsd) # CYGNUS LOCAL
|
||||
386bsd)
|
||||
basic_machine=i386-unknown
|
||||
os=-bsd
|
||||
;;
|
||||
@@ -232,11 +238,11 @@ case $basic_machine in
|
||||
3b*)
|
||||
basic_machine=we32k-att
|
||||
;;
|
||||
a29khif) # CYGNUS LOCAL
|
||||
a29khif)
|
||||
basic_machine=a29k-amd
|
||||
os=-udi
|
||||
;;
|
||||
adobe68k) # CYGNUS LOCAL
|
||||
adobe68k)
|
||||
basic_machine=m68010-adobe
|
||||
os=-scout
|
||||
;;
|
||||
@@ -269,7 +275,7 @@ case $basic_machine in
|
||||
basic_machine=m68k-apollo
|
||||
os=-sysv
|
||||
;;
|
||||
apollo68bsd) # CYGNUS LOCAL
|
||||
apollo68bsd)
|
||||
basic_machine=m68k-apollo
|
||||
os=-bsd
|
||||
;;
|
||||
@@ -349,7 +355,7 @@ case $basic_machine in
|
||||
encore | umax | mmax)
|
||||
basic_machine=ns32k-encore
|
||||
;;
|
||||
es1800 | OSE68k | ose68k | ose | OSE) # CYGNUS LOCAL
|
||||
es1800 | OSE68k | ose68k | ose | OSE)
|
||||
basic_machine=m68k-ericsson
|
||||
os=-ose
|
||||
;;
|
||||
@@ -371,11 +377,11 @@ case $basic_machine in
|
||||
basic_machine=h8300-hitachi
|
||||
os=-hms
|
||||
;;
|
||||
h8300xray) # CYGNUS LOCAL
|
||||
h8300xray)
|
||||
basic_machine=h8300-hitachi
|
||||
os=-xray
|
||||
;;
|
||||
h8500hms) # CYGNUS LOCAL
|
||||
h8500hms)
|
||||
basic_machine=h8500-hitachi
|
||||
os=-hms
|
||||
;;
|
||||
@@ -394,29 +400,30 @@ case $basic_machine in
|
||||
basic_machine=m68k-hp
|
||||
os=-hpux
|
||||
;;
|
||||
w89k-*) # CYGNUS LOCAL
|
||||
basic_machine=hppa1.1-winbond
|
||||
os=-proelf
|
||||
;;
|
||||
op50n-*) # CYGNUS LOCAL
|
||||
basic_machine=hppa1.1-oki
|
||||
os=-proelf
|
||||
;;
|
||||
op60c-*) # CYGNUS LOCAL
|
||||
basic_machine=hppa1.1-oki
|
||||
os=-proelf
|
||||
;;
|
||||
hppro) # CYGNUS LOCAL
|
||||
basic_machine=hppa1.1-hp
|
||||
os=-proelf
|
||||
;;
|
||||
hp3k9[0-9][0-9] | hp9[0-9][0-9])
|
||||
basic_machine=hppa1.0-hp
|
||||
;;
|
||||
hp9k2[0-9][0-9] | hp9k31[0-9])
|
||||
basic_machine=m68000-hp
|
||||
;;
|
||||
hp9k3[2-9][0-9])
|
||||
basic_machine=m68k-hp
|
||||
;;
|
||||
hp9k7[0-9][0-9] | hp7[0-9][0-9] | hp9k8[0-9]7 | hp8[0-9]7)
|
||||
hp9k6[0-9][0-9] | hp6[0-9][0-9])
|
||||
basic_machine=hppa1.0-hp
|
||||
;;
|
||||
hp9k7[0-79][0-9] | hp7[0-79][0-9])
|
||||
basic_machine=hppa1.1-hp
|
||||
;;
|
||||
hp9k78[0-9] | hp78[0-9])
|
||||
# FIXME: really hppa2.0-hp
|
||||
basic_machine=hppa1.1-hp
|
||||
;;
|
||||
hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
|
||||
# FIXME: really hppa2.0-hp
|
||||
basic_machine=hppa1.1-hp
|
||||
;;
|
||||
hp9k8[0-9][13679] | hp8[0-9][13679])
|
||||
basic_machine=hppa1.1-hp
|
||||
;;
|
||||
hp9k8[0-9][0-9] | hp8[0-9][0-9])
|
||||
@@ -425,43 +432,50 @@ case $basic_machine in
|
||||
hppa-next)
|
||||
os=-nextstep3
|
||||
;;
|
||||
hppaosf) # CYGNUS LOCAL
|
||||
hppaosf)
|
||||
basic_machine=hppa1.1-hp
|
||||
os=-osf
|
||||
;;
|
||||
hppro)
|
||||
basic_machine=hppa1.1-hp
|
||||
os=-proelf
|
||||
;;
|
||||
i370-ibm* | ibm*)
|
||||
basic_machine=i370-ibm
|
||||
os=-mvs
|
||||
;;
|
||||
# I'm not sure what "Sysv32" means. Should this be sysv3.2?
|
||||
i[3456]86v32)
|
||||
i[34567]86v32)
|
||||
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
|
||||
os=-sysv32
|
||||
;;
|
||||
i[3456]86v4*)
|
||||
i[34567]86v4*)
|
||||
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
|
||||
os=-sysv4
|
||||
;;
|
||||
i[3456]86v)
|
||||
i[34567]86v)
|
||||
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
|
||||
os=-sysv
|
||||
;;
|
||||
i[3456]86sol2)
|
||||
i[34567]86sol2)
|
||||
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
|
||||
os=-solaris2
|
||||
;;
|
||||
i386mach) # CYGNUS LOCAL
|
||||
i386mach)
|
||||
basic_machine=i386-mach
|
||||
os=-mach
|
||||
;;
|
||||
i386-vsta | vsta) # CYGNUS LOCAL
|
||||
i386-vsta | vsta)
|
||||
basic_machine=i386-unknown
|
||||
os=-vsta
|
||||
;;
|
||||
i386-go32 | go32) # CYGNUS LOCAL
|
||||
i386-go32 | go32)
|
||||
basic_machine=i386-unknown
|
||||
os=-go32
|
||||
;;
|
||||
i386-mingw32 | mingw32)
|
||||
basic_machine=i386-unknown
|
||||
os=-mingw32
|
||||
;;
|
||||
iris | iris4d)
|
||||
basic_machine=mips-sgi
|
||||
case $os in
|
||||
@@ -490,6 +504,10 @@ case $basic_machine in
|
||||
miniframe)
|
||||
basic_machine=m68000-convergent
|
||||
;;
|
||||
*mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
|
||||
basic_machine=m68k-atari
|
||||
os=-mint
|
||||
;;
|
||||
mipsel*-linux*)
|
||||
basic_machine=mipsel-unknown
|
||||
os=-linux-gnu
|
||||
@@ -504,22 +522,34 @@ case $basic_machine in
|
||||
mips3*)
|
||||
basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
|
||||
;;
|
||||
monitor) # CYGNUS LOCAL
|
||||
mmix*)
|
||||
basic_machine=mmix-knuth
|
||||
os=-mmixware
|
||||
;;
|
||||
monitor)
|
||||
basic_machine=m68k-rom68k
|
||||
os=-coff
|
||||
;;
|
||||
msdos) # CYGNUS LOCAL
|
||||
basic_machine=i386-unknown
|
||||
msdos)
|
||||
basic_machine=i386-unknown
|
||||
os=-msdos
|
||||
;;
|
||||
mvs)
|
||||
basic_machine=i370-ibm
|
||||
os=-mvs
|
||||
;;
|
||||
ncr3000)
|
||||
basic_machine=i486-ncr
|
||||
os=-sysv4
|
||||
;;
|
||||
netbsd386)
|
||||
basic_machine=i386-unknown # CYGNUS LOCAL
|
||||
basic_machine=i386-unknown
|
||||
os=-netbsd
|
||||
;;
|
||||
netwinder)
|
||||
basic_machine=armv4l-rebel
|
||||
os=-linux
|
||||
;;
|
||||
news | news700 | news800 | news900)
|
||||
basic_machine=m68k-sony
|
||||
os=-newsos
|
||||
@@ -532,7 +562,7 @@ case $basic_machine in
|
||||
basic_machine=mips-sony
|
||||
os=-newsos
|
||||
;;
|
||||
necv70) # CYGNUS LOCAL
|
||||
necv70)
|
||||
basic_machine=v70-nec
|
||||
os=-sysv
|
||||
;;
|
||||
@@ -561,18 +591,25 @@ case $basic_machine in
|
||||
basic_machine=i960-intel
|
||||
os=-nindy
|
||||
;;
|
||||
mon960) # CYGNUS LOCAL
|
||||
mon960)
|
||||
basic_machine=i960-intel
|
||||
os=-mon960
|
||||
;;
|
||||
np1)
|
||||
basic_machine=np1-gould
|
||||
;;
|
||||
OSE68000 | ose68000) # CYGNUS LOCAL
|
||||
nsr-tandem)
|
||||
basic_machine=nsr-tandem
|
||||
;;
|
||||
op50n-* | op60c-*)
|
||||
basic_machine=hppa1.1-oki
|
||||
os=-proelf
|
||||
;;
|
||||
OSE68000 | ose68000)
|
||||
basic_machine=m68000-ericsson
|
||||
os=-ose
|
||||
;;
|
||||
os68k) # CYGNUS LOCAL
|
||||
os68k)
|
||||
basic_machine=m68k-none
|
||||
os=-os68k
|
||||
;;
|
||||
@@ -593,25 +630,23 @@ case $basic_machine in
|
||||
pc532 | pc532-*)
|
||||
basic_machine=ns32k-pc532
|
||||
;;
|
||||
pentium | p5)
|
||||
basic_machine=i586-intel
|
||||
pentium | p5 | k5 | k6 | nexen)
|
||||
basic_machine=i586-pc
|
||||
;;
|
||||
pentiumpro | p6)
|
||||
basic_machine=i686-intel
|
||||
pentiumpro | p6 | 6x86)
|
||||
basic_machine=i686-pc
|
||||
;;
|
||||
pentium-* | p5-*)
|
||||
pentiumii | pentium2)
|
||||
basic_machine=i786-pc
|
||||
;;
|
||||
pentium-* | p5-* | k5-* | k6-* | nexen-*)
|
||||
basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
pentiumpro-* | p6-*)
|
||||
pentiumpro-* | p6-* | 6x86-*)
|
||||
basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
k5)
|
||||
# We don't have specific support for AMD's K5 yet, so just call it a Pentium
|
||||
basic_machine=i586-amd
|
||||
;;
|
||||
nexen)
|
||||
# We don't have specific support for Nexgen yet, so just call it a Pentium
|
||||
basic_machine=i586-nexgen
|
||||
pentiumii-* | pentium2-*)
|
||||
basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
pn)
|
||||
basic_machine=pn-gould
|
||||
@@ -631,7 +666,7 @@ case $basic_machine in
|
||||
ps2)
|
||||
basic_machine=i386-ibm
|
||||
;;
|
||||
rom68k) # CYGNUS LOCAL
|
||||
rom68k)
|
||||
basic_machine=m68k-rom68k
|
||||
os=-coff
|
||||
;;
|
||||
@@ -641,7 +676,7 @@ case $basic_machine in
|
||||
rtpc | rtpc-*)
|
||||
basic_machine=romp-ibm
|
||||
;;
|
||||
sa29200) # CYGNUS LOCAL
|
||||
sa29200)
|
||||
basic_machine=a29k-amd
|
||||
os=-udi
|
||||
;;
|
||||
@@ -652,7 +687,7 @@ case $basic_machine in
|
||||
basic_machine=sh-hitachi
|
||||
os=-hms
|
||||
;;
|
||||
sparclite-wrs) # CYGNUS LOCAL
|
||||
sparclite-wrs)
|
||||
basic_machine=sparclite-wrs
|
||||
os=-vxworks
|
||||
;;
|
||||
@@ -663,10 +698,10 @@ case $basic_machine in
|
||||
spur)
|
||||
basic_machine=spur-unknown
|
||||
;;
|
||||
st2000) # CYGNUS LOCAL
|
||||
st2000)
|
||||
basic_machine=m68k-tandem
|
||||
;;
|
||||
stratus) # CYGNUS LOCAL
|
||||
stratus)
|
||||
basic_machine=i860-stratus
|
||||
os=-sysv4
|
||||
;;
|
||||
@@ -710,10 +745,18 @@ case $basic_machine in
|
||||
sun386 | sun386i | roadrunner)
|
||||
basic_machine=i386-sun
|
||||
;;
|
||||
sv1)
|
||||
basic_machine=sv1-cray
|
||||
os=-unicos
|
||||
;;
|
||||
symmetry)
|
||||
basic_machine=i386-sequent
|
||||
os=-dynix
|
||||
;;
|
||||
t3e)
|
||||
basic_machine=t3e-cray
|
||||
os=-unicos
|
||||
;;
|
||||
tx39)
|
||||
basic_machine=mipstx39-unknown
|
||||
;;
|
||||
@@ -731,7 +774,7 @@ case $basic_machine in
|
||||
basic_machine=a29k-nyu
|
||||
os=-sym1
|
||||
;;
|
||||
v810 | necv810) # CYGNUS LOCAL
|
||||
v810 | necv810)
|
||||
basic_machine=v810-nec
|
||||
os=-none
|
||||
;;
|
||||
@@ -758,9 +801,13 @@ case $basic_machine in
|
||||
basic_machine=a29k-wrs
|
||||
os=-vxworks
|
||||
;;
|
||||
w65*) # CYGNUS LOCAL
|
||||
basic_machine=w65-wdc
|
||||
os=-none
|
||||
w65*)
|
||||
basic_machine=w65-wdc
|
||||
os=-none
|
||||
;;
|
||||
w89k-*)
|
||||
basic_machine=hppa1.1-winbond
|
||||
os=-proelf
|
||||
;;
|
||||
xmp)
|
||||
basic_machine=xmp-cray
|
||||
@@ -769,7 +816,7 @@ case $basic_machine in
|
||||
xps | xps100)
|
||||
basic_machine=xps100-honeywell
|
||||
;;
|
||||
z8k-*-coff) # CYGNUS LOCAL
|
||||
z8k-*-coff)
|
||||
basic_machine=z8k-unknown
|
||||
os=-sim
|
||||
;;
|
||||
@@ -780,13 +827,13 @@ case $basic_machine in
|
||||
|
||||
# Here we handle the default manufacturer of certain CPU types. It is in
|
||||
# some cases the only manufacturer, in others, it is the most popular.
|
||||
w89k) # CYGNUS LOCAL
|
||||
w89k)
|
||||
basic_machine=hppa1.1-winbond
|
||||
;;
|
||||
op50n) # CYGNUS LOCAL
|
||||
op50n)
|
||||
basic_machine=hppa1.1-oki
|
||||
;;
|
||||
op60c) # CYGNUS LOCAL
|
||||
op60c)
|
||||
basic_machine=hppa1.1-oki
|
||||
;;
|
||||
mips)
|
||||
@@ -811,7 +858,7 @@ case $basic_machine in
|
||||
we32k)
|
||||
basic_machine=we32k-att
|
||||
;;
|
||||
sparc)
|
||||
sparc | sparcv9)
|
||||
basic_machine=sparc-sun
|
||||
;;
|
||||
cydra)
|
||||
@@ -823,12 +870,16 @@ case $basic_machine in
|
||||
orion105)
|
||||
basic_machine=clipper-highlevel
|
||||
;;
|
||||
mac | mpw | mac-mpw) # CYGNUS LOCAL
|
||||
mac | mpw | mac-mpw)
|
||||
basic_machine=m68k-apple
|
||||
;;
|
||||
pmac | pmac-mpw) # CYGNUS LOCAL
|
||||
pmac | pmac-mpw)
|
||||
basic_machine=powerpc-apple
|
||||
;;
|
||||
c4x*)
|
||||
basic_machine=c4x-none
|
||||
os=-coff
|
||||
;;
|
||||
*)
|
||||
echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
|
||||
exit 1
|
||||
@@ -861,9 +912,12 @@ case $os in
|
||||
-solaris)
|
||||
os=-solaris2
|
||||
;;
|
||||
-unixware* | svr4*)
|
||||
-svr4*)
|
||||
os=-sysv4
|
||||
;;
|
||||
-unixware*)
|
||||
os=-sysv4.2uw
|
||||
;;
|
||||
-gnu/linux*)
|
||||
os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
|
||||
;;
|
||||
@@ -879,22 +933,34 @@ case $os in
|
||||
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
|
||||
| -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
|
||||
| -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \
|
||||
| -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* \
|
||||
| -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
|
||||
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
|
||||
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
|
||||
| -cygwin32* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
|
||||
| -mingw32* | -linux-gnu* | -uxpv*)
|
||||
| -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
|
||||
| -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \
|
||||
| -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \
|
||||
| -openstep* | -oskit*)
|
||||
# Remember, each alternative MUST END IN *, to match a version number.
|
||||
;;
|
||||
# CYGNUS LOCAL
|
||||
-qnx*)
|
||||
case $basic_machine in
|
||||
x86-* | i[34567]86-*)
|
||||
;;
|
||||
*)
|
||||
os=-nto$os
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
-nto*)
|
||||
os=-nto-qnx
|
||||
;;
|
||||
-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
|
||||
| -windows* | -osx | -abug | -netware* | -os9* | -beos* \
|
||||
| -macos* | -mpw* | -magic* | -mon960* | -lnews* )
|
||||
| -windows* | -osx | -abug | -netware* | -os9* | -beos* \
|
||||
| -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
|
||||
;;
|
||||
-mac*)
|
||||
os=`echo $os | sed -e 's|mac|macos|'`
|
||||
;;
|
||||
# END CYGNUS LOCAL
|
||||
-linux*)
|
||||
os=`echo $os | sed -e 's|linux|linux-gnu|'`
|
||||
;;
|
||||
@@ -904,6 +970,12 @@ case $os in
|
||||
-sunos6*)
|
||||
os=`echo $os | sed -e 's|sunos6|solaris3|'`
|
||||
;;
|
||||
-opened*)
|
||||
os=-openedition
|
||||
;;
|
||||
-wince*)
|
||||
os=-wince
|
||||
;;
|
||||
-osfrose*)
|
||||
os=-osfrose
|
||||
;;
|
||||
@@ -919,7 +991,7 @@ case $os in
|
||||
-acis*)
|
||||
os=-aos
|
||||
;;
|
||||
-386bsd) # CYGNUS LOCAL
|
||||
-386bsd)
|
||||
os=-bsd
|
||||
;;
|
||||
-ctix* | -uts*)
|
||||
@@ -928,6 +1000,9 @@ case $os in
|
||||
-ns2 )
|
||||
os=-nextstep2
|
||||
;;
|
||||
-nsk)
|
||||
os=-nsk
|
||||
;;
|
||||
# Preserve the version number of sinix5.
|
||||
-sinix5.*)
|
||||
os=`echo $os | sed -e 's|sinix|sysv|'`
|
||||
@@ -953,15 +1028,18 @@ case $os in
|
||||
# This must come after -sysvr4.
|
||||
-sysv*)
|
||||
;;
|
||||
-ose*) # CYGNUS LOCAL
|
||||
-ose*)
|
||||
os=-ose
|
||||
;;
|
||||
-es1800*) # CYGNUS LOCAL
|
||||
-es1800*)
|
||||
os=-ose
|
||||
;;
|
||||
-xenix)
|
||||
os=-xenix
|
||||
;;
|
||||
-*mint | -*MiNT)
|
||||
os=-mint
|
||||
;;
|
||||
-none)
|
||||
;;
|
||||
*)
|
||||
@@ -987,6 +1065,9 @@ case $basic_machine in
|
||||
*-acorn)
|
||||
os=-riscix1.2
|
||||
;;
|
||||
arm*-rebel)
|
||||
os=-linux
|
||||
;;
|
||||
arm*-semi)
|
||||
os=-aout
|
||||
;;
|
||||
@@ -1008,34 +1089,34 @@ case $basic_machine in
|
||||
# default.
|
||||
# os=-sunos4
|
||||
;;
|
||||
m68*-cisco) # CYGNUS LOCAL
|
||||
m68*-cisco)
|
||||
os=-aout
|
||||
;;
|
||||
mips*-cisco) # CYGNUS LOCAL
|
||||
mips*-cisco)
|
||||
os=-elf
|
||||
;;
|
||||
mips*-*)
|
||||
os=-elf
|
||||
;;
|
||||
mips*-*) # CYGNUS LOCAL
|
||||
os=-elf
|
||||
;;
|
||||
*-tti) # must be before sparc entry or we get the wrong os.
|
||||
os=-sysv3
|
||||
;;
|
||||
sparc-* | *-sun)
|
||||
os=-sunos4.1.1
|
||||
;;
|
||||
*-be) # CYGNUS LOCAL
|
||||
*-be)
|
||||
os=-beos
|
||||
;;
|
||||
*-ibm)
|
||||
os=-aix
|
||||
;;
|
||||
*-wec) # CYGNUS LOCAL
|
||||
*-wec)
|
||||
os=-proelf
|
||||
;;
|
||||
*-winbond) # CYGNUS LOCAL
|
||||
*-winbond)
|
||||
os=-proelf
|
||||
;;
|
||||
*-oki) # CYGNUS LOCAL
|
||||
*-oki)
|
||||
os=-proelf
|
||||
;;
|
||||
*-hp)
|
||||
@@ -1101,15 +1182,18 @@ case $basic_machine in
|
||||
f301-fujitsu)
|
||||
os=-uxpv
|
||||
;;
|
||||
*-rom68k) # CYGNUS LOCAL
|
||||
*-rom68k)
|
||||
os=-coff
|
||||
;;
|
||||
*-*bug) # CYGNUS LOCAL
|
||||
*-*bug)
|
||||
os=-coff
|
||||
;;
|
||||
*-apple) # CYGNUS LOCAL
|
||||
*-apple)
|
||||
os=-macos
|
||||
;;
|
||||
*-atari*)
|
||||
os=-mint
|
||||
;;
|
||||
*)
|
||||
os=-none
|
||||
;;
|
||||
@@ -1131,12 +1215,15 @@ case $basic_machine in
|
||||
-aix*)
|
||||
vendor=ibm
|
||||
;;
|
||||
-beos*) # CYGNUS LOCAL
|
||||
-beos*)
|
||||
vendor=be
|
||||
;;
|
||||
-hpux*)
|
||||
vendor=hp
|
||||
;;
|
||||
-mpeix*)
|
||||
vendor=hp
|
||||
;;
|
||||
-hiux*)
|
||||
vendor=hitachi
|
||||
;;
|
||||
@@ -1152,7 +1239,7 @@ case $basic_machine in
|
||||
-genix*)
|
||||
vendor=ns
|
||||
;;
|
||||
-mvs*)
|
||||
-mvs* | -opened*)
|
||||
vendor=ibm
|
||||
;;
|
||||
-ptx*)
|
||||
@@ -1164,12 +1251,15 @@ case $basic_machine in
|
||||
-aux*)
|
||||
vendor=apple
|
||||
;;
|
||||
-hms*) # CYGNUS LOCAL
|
||||
-hms*)
|
||||
vendor=hitachi
|
||||
;;
|
||||
-mpw* | -macos*) # CYGNUS LOCAL
|
||||
-mpw* | -macos*)
|
||||
vendor=apple
|
||||
;;
|
||||
-*mint | -*MiNT)
|
||||
vendor=atari
|
||||
;;
|
||||
esac
|
||||
basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
|
||||
;;
|
||||
|
||||
+198
-2
@@ -1,11 +1,207 @@
|
||||
dnl Process this file with autoconf to produce a configure script.
|
||||
AC_INIT(netlist.h)
|
||||
AC_CONFIG_HEADER(config.h)
|
||||
|
||||
dnl Checks for programs.
|
||||
AC_PROG_CC
|
||||
AC_PROG_CXX
|
||||
AC_CHECK_TOOL(STRIP, strip, true)
|
||||
AC_CHECK_HEADERS(getopt.h)
|
||||
AC_CHECK_PROGS(XGPERF,gperf,none)
|
||||
if test "$XGPERF" = "none"
|
||||
then
|
||||
echo "*** Error: No suitable gperf found. ***"
|
||||
echo " Please install the 'gperf' package."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
AC_LANG_CPLUSPLUS
|
||||
|
||||
AC_CHECK_HEADERS(getopt.h iosfwd sys/wait.h)
|
||||
|
||||
AC_MSG_CHECKING(for sys/times)
|
||||
AC_TRY_LINK(
|
||||
#include <unistd.h>
|
||||
#include <sys/times.h>
|
||||
,{clock_t a = times(0)/sysconf(_SC_CLK_TCK);},
|
||||
do_times=yes
|
||||
AC_DEFINE(HAVE_TIMES,1),
|
||||
do_times=no
|
||||
)
|
||||
AC_MSG_RESULT($do_times)
|
||||
|
||||
AC_CHECK_HEADER(ipal.h, HAVE_IPAL=yes, HAVE_IPAL=)
|
||||
AC_ARG_WITH(ipal,enable PAL target,
|
||||
if test "$with_ipal" = no; then
|
||||
echo Disabling ipal support
|
||||
HAVE_IPAL=
|
||||
fi
|
||||
)
|
||||
AC_SUBST(HAVE_IPAL)
|
||||
|
||||
# --
|
||||
# Look for a dl library to use. First look for the standard dlopen
|
||||
# functions, and failing that look for the HP specific shl_load function.
|
||||
|
||||
AC_CHECK_HEADERS(dlfcn.h dl.h, break)
|
||||
|
||||
DLLIB=''
|
||||
AC_CHECK_LIB(dl,dlopen,[DLLIB=-ldl])
|
||||
if test -z "$DLLIB" ; then
|
||||
AC_CHECK_LIB(dld,shl_load,[DLLIB=-ldld])
|
||||
fi
|
||||
AC_SUBST(DLLIB)
|
||||
|
||||
AC_PROG_INSTALL
|
||||
|
||||
AC_OUTPUT(Makefile vpi/Makefile ivlpp/Makefile vvm/Makefile)
|
||||
AC_LANG_C
|
||||
|
||||
AC_CANONICAL_HOST
|
||||
# $host
|
||||
|
||||
|
||||
#######################
|
||||
## test for underscores. The vpi module loader in vvm needs to know this
|
||||
## in order to know the name of the start symbol for the .vpi module.
|
||||
#######################
|
||||
|
||||
AC_CYGWIN
|
||||
AC_EXEEXT
|
||||
AC_MINGW32
|
||||
|
||||
|
||||
WIN32=no
|
||||
AC_MSG_CHECKING("Checking for windows")
|
||||
if test "$CYGWIN" = "yes" -o "$MINGW32" = "yes"
|
||||
then
|
||||
WIN32=yes
|
||||
fi
|
||||
AC_SUBST(WIN32)
|
||||
AC_MSG_RESULT($WIN32)
|
||||
AC_SUBST(EXEEXT)
|
||||
|
||||
|
||||
AC_MSG_CHECKING("for leading and/or trailing underscores")
|
||||
cat << EOF > underscore.c
|
||||
void underscore(void){}
|
||||
EOF
|
||||
$CC -shared -c underscore.c > /dev/null 2>&1
|
||||
|
||||
CC_LEADING_UNDERSCORE=no
|
||||
CC_TRAILING_UNDERSCORE=no
|
||||
|
||||
output=`nm underscore.o|grep _underscore 2>&1`
|
||||
if test ! -z "$output" -a -z "$CYGWIN" -a -z "$MINGW32"; then
|
||||
CC_LEADING_UNDERSCORE=yes
|
||||
AC_DEFINE(NEED_LU)
|
||||
fi
|
||||
|
||||
|
||||
|
||||
output=`nm underscore.o|grep underscore_ 2>&1`
|
||||
if test ! -z "$output"; then
|
||||
CC_TRAILING_UNDERSCORE=yes
|
||||
AC_DEFINE(NEED_TU)
|
||||
fi
|
||||
|
||||
if test "$CC_LEADING_UNDERSCORE" = yes; then
|
||||
AC_DEFINE(WLU)
|
||||
fi
|
||||
if test "$CC_TRAILING_UNDERSCORE" = yes; then
|
||||
AC_DEFINE(WTU)
|
||||
fi
|
||||
|
||||
rm underscore.c underscore.o
|
||||
|
||||
AC_MSG_RESULT("$CC_LEADING_UNDERSCORE $CC_TRAILING_UNDERSCORE")
|
||||
|
||||
#######################
|
||||
## end of test for underscores
|
||||
#######################
|
||||
|
||||
# The -fPIC flag is used to tell the compiler to make position
|
||||
# independent code. It is needed when making shared objects.
|
||||
|
||||
AC_MSG_CHECKING("for flag to make position independent code")
|
||||
PICFLAG=-fPIC
|
||||
case "${host}" in
|
||||
|
||||
*-*-cygwin*)
|
||||
PICFLAG=
|
||||
;;
|
||||
|
||||
*-*-hpux*)
|
||||
PICFLAG=+z
|
||||
;;
|
||||
|
||||
esac
|
||||
AC_SUBST(PICFLAG)
|
||||
AC_MSG_RESULT($PICFLAG)
|
||||
|
||||
|
||||
# mingw needs to link with libiberty.a
|
||||
|
||||
AC_MSG_CHECKING("for extra libs needed")
|
||||
EXTRALIBS=
|
||||
case "${host}" in
|
||||
*-*-cygwin*)
|
||||
if test $ac_cv_mingw32 = yes; then
|
||||
EXTRALIBS="-liberty"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
AC_SUBST(EXTRALIBS)
|
||||
AC_MSG_RESULT($EXTRALIBS)
|
||||
|
||||
|
||||
# The -rdynamic flag is used by iverilog when compiling the target,
|
||||
# to know how to export symbols of the main program to loadable modules
|
||||
# that are brought in by -ldl
|
||||
AC_MSG_CHECKING("for -rdynamic compiler flag")
|
||||
|
||||
rdynamic=-rdynamic
|
||||
case "${host}" in
|
||||
|
||||
*-*-netbsd*)
|
||||
rdynamic="-Wl,--export-dynamic"
|
||||
;;
|
||||
|
||||
*-*-solaris*)
|
||||
rdynamic=""
|
||||
;;
|
||||
|
||||
*-*-cygwin*)
|
||||
rdynamic=""
|
||||
;;
|
||||
|
||||
*-*-hpux*)
|
||||
rdynamic="-E"
|
||||
;;
|
||||
esac
|
||||
AC_SUBST(rdynamic)
|
||||
AC_MSG_RESULT($rdynamic)
|
||||
|
||||
AC_MSG_CHECKING("for shared library link flag")
|
||||
shared=-shared
|
||||
case "${host}" in
|
||||
|
||||
*-*-cygwin*)
|
||||
shared="-mdll -Wl,--enable-auto-image-base"
|
||||
if test $ac_cv_mingw32 = yes; then
|
||||
shared="-shared -Wl,--enable-auto-image-base"
|
||||
fi
|
||||
;;
|
||||
|
||||
*-*-hpux*)
|
||||
shared="-b"
|
||||
;;
|
||||
|
||||
esac
|
||||
|
||||
AC_SUBST(shared)
|
||||
|
||||
AC_MSG_RESULT($shared)
|
||||
|
||||
|
||||
AC_CONFIG_SUBDIRS(vpip vvp tgt-vvp tgt-fpga)
|
||||
|
||||
AC_OUTPUT(Makefile vpi/Makefile ivlpp/Makefile vvm/Makefile driver/Makefile tgt-null/Makefile tgt-stub/Makefile tgt-verilog/Makefile tgt-pal/Makefile)
|
||||
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
|
||||
This file describes the build procedure under cygwin32 (Windows 95/98/NT/2K)
|
||||
----------------------------------------------------------------------------
|
||||
To build using cygwin:
|
||||
|
||||
Prerequisites:
|
||||
|
||||
o Latest net release (1.1.4) of cygwin (sources.redhat.com/cygwin)
|
||||
o autoconf version 2.13 (or later) from cygutils (cygutils.netpedia.net)
|
||||
o cvs (1.10.8 or later) also from cygutils
|
||||
|
||||
Procedure:
|
||||
o Get the source code - see the main icarus verilog page for how to
|
||||
do this
|
||||
o cd to the verilog directory
|
||||
o autoconf
|
||||
o ./configure
|
||||
o make
|
||||
o make install
|
||||
|
||||
That's all that's needed. But there're two common problems during
|
||||
the make phase. All steps are in the verilog directory.
|
||||
|
||||
1.
|
||||
|
||||
If gcc dies saying virtual memory exhausted while compiling parse.c
|
||||
then recompile with -O1 or without -O flag and do these steps to
|
||||
continue
|
||||
o make CXXFLAGS='' parse.o
|
||||
o make
|
||||
|
||||
2.
|
||||
|
||||
If gcc dies in the vpi directory while compiling vpi_systask.c with the
|
||||
error, conflicting types for `_cygwin_dll_entry', then fix the line in
|
||||
/usr/include/cygwin/cygwin_dll.h. Change the line:
|
||||
|
||||
int WINAPI _cygwin_dll_entry (HANDLE h, DWORD reason, void *ptr); \
|
||||
to
|
||||
int WINAPI _cygwin_dll_entry (HINSTANCE h, DWORD reason, void *ptr); \
|
||||
|
||||
Note the change from HANDLE to HINSTANCE. Then do
|
||||
o make
|
||||
|
||||
To build your own extensions - just include vpi_user.h and link with
|
||||
a command like this:
|
||||
|
||||
$(CC) -shared -o <dllname> <objects> -Wl,--enable-auto-image-base -L../vvm -lvvm -lvpip
|
||||
|
||||
- Venkat Iyer <[email protected]>
|
||||
|
||||
|
||||
|
||||
+500
-482
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (c) 2001 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
|
||||
*
|
||||
* $Id: dosify.c,v 1.1 2001/08/03 17:06:47 steve Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is a simple program to make a dosified copy of the
|
||||
* original. That is, it converts unix style line ends to DOS
|
||||
* style. This is useful for installing text files.
|
||||
*
|
||||
* The exact substitution is to replace \n with \r\n. If the line
|
||||
* already ends with \r\n then it is not changed to \r\r\n.
|
||||
*/
|
||||
|
||||
# include <stdio.h>
|
||||
|
||||
int main(int argc, char*argv[])
|
||||
{
|
||||
FILE*ifile;
|
||||
FILE*ofile;
|
||||
int ch, pr;
|
||||
|
||||
if (argc != 3) {
|
||||
fprintf(stderr, "Usage: %s <input> <output>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
ifile = fopen(argv[1], "rb");
|
||||
if (ifile == 0) {
|
||||
fprintf(stderr, "Unable to open %s for input.\n", argv[1]);
|
||||
return 2;
|
||||
}
|
||||
|
||||
ofile = fopen(argv[2], "wb");
|
||||
if (ofile == 0) {
|
||||
fprintf(stderr, "Unable to open %s for output.\n", argv[2]);
|
||||
return 2;
|
||||
}
|
||||
|
||||
pr = 0;
|
||||
while ((ch = fgetc(ifile)) != EOF) {
|
||||
|
||||
if ((ch == '\n') && (pr != '\r'))
|
||||
fputc('\r', ofile);
|
||||
|
||||
fputc(ch, ofile);
|
||||
pr = ch;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: dosify.c,v $
|
||||
* Revision 1.1 2001/08/03 17:06:47 steve
|
||||
* Add install of examples for Windows.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
Makefile
|
||||
parse.c
|
||||
parse.h
|
||||
parse.output
|
||||
lexor.c
|
||||
iverilog
|
||||
@@ -0,0 +1,91 @@
|
||||
#
|
||||
# This source code is free software; you can redistribute it
|
||||
# and/or modify it in source code form under the terms of the GNU
|
||||
# Library General Public License as published by the Free Software
|
||||
# Foundation; either version 2 of the License, or (at your option)
|
||||
# any later version. In order to redistribute the software in
|
||||
# binary form, you will need a Picture Elements Binary Software
|
||||
# License.
|
||||
#
|
||||
# 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 Library General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Library 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
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.6 2001/08/10 00:39:42 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
|
||||
VERSION = 0.0
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
srcdir = @srcdir@
|
||||
|
||||
VPATH = $(srcdir)
|
||||
|
||||
bindir = $(exec_prefix)/bin
|
||||
libdir = $(exec_prefix)/lib
|
||||
includedir = $(prefix)/include
|
||||
mandir = @mandir@
|
||||
|
||||
dllib=@DLLIB@
|
||||
rdynamic=@rdynamic@
|
||||
|
||||
CC = @CC@
|
||||
CXX = @CXX@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
|
||||
CPPFLAGS = @CPPFLAGS@ @DEFS@
|
||||
CFLAGS = @CFLAGS@ -I. -I$(srcdir)/..
|
||||
CXXFLAGS = @CXXFLAGS@ -I. -I$(srcdir)/..
|
||||
LDFLAGS = @LDFLAGS@
|
||||
|
||||
all: iverilog@EXEEXT@
|
||||
|
||||
clean:
|
||||
rm -f *.o lexor.c parse.c parse.h parse.output
|
||||
|
||||
O = main.o build_string.o lexor.o parse.o
|
||||
|
||||
iverilog@EXEEXT@: $O
|
||||
$(CC) $(LDFLAGS) $O -o iverilog@EXEEXT@ @EXTRALIBS@
|
||||
|
||||
lexor.c: lexor.lex
|
||||
flex -s -olexor.c $(srcdir)/lexor.lex
|
||||
|
||||
parse.h parse.c: parse.y
|
||||
bison --verbose -t -d -o parse.c $(srcdir)/parse.y
|
||||
|
||||
|
||||
main.o: main.c globals.h
|
||||
$(CC) $(CFLAGS) -c -DCXX='"@CXX@"' -DIVL_ROOT='"@libdir@/ivl"' -DIVL_INC='"@includedir@"' -DIVL_LIB='"@libdir@"' -DRDYNAMIC=\"$(rdynamic)\" -DDLLIB='"@DLLIB@"' -DEXEEXT='"@EXEEXT@"' $(srcdir)/main.c
|
||||
|
||||
build_string.o: build_string.c globals.h
|
||||
lexor.o: lexor.c parse.h globals.h
|
||||
parse.o: parse.c globals.h
|
||||
|
||||
|
||||
install: all installdirs $(bindir)/iverilog@EXEEXT@ $(mandir)/man1/iverilog.1
|
||||
|
||||
$(bindir)/iverilog@EXEEXT@: ./iverilog@EXEEXT@
|
||||
$(INSTALL_PROGRAM) ./iverilog@EXEEXT@ $(bindir)/iverilog@EXEEXT@
|
||||
|
||||
$(mandir)/man1/iverilog.1: $(srcdir)/iverilog.man
|
||||
$(INSTALL_DATA) $(srcdir)/iverilog.man $(mandir)/man1/iverilog.1
|
||||
|
||||
installdirs: ../mkinstalldirs
|
||||
$(srcdir)/../mkinstalldirs $(bindir) $(mandir)/man1
|
||||
|
||||
uninstall:
|
||||
rm -f $(bindir)/iverilog@EXEEXT@
|
||||
rm -f $(mandir)/man1/iverilog.1
|
||||
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
* Copyright (c) 2000 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
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: build_string.c,v 1.4 2001/07/25 03:10:50 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# include "globals.h"
|
||||
# include <string.h>
|
||||
# include <assert.h>
|
||||
|
||||
int build_string(char*output, size_t olen, const char*pattern)
|
||||
{
|
||||
char tmp_buf[1024];
|
||||
|
||||
char*output_save = output;
|
||||
while (*pattern) {
|
||||
|
||||
if (*pattern == '%') {
|
||||
pattern += 1;
|
||||
switch (*pattern) {
|
||||
case 0:
|
||||
break;
|
||||
|
||||
case '%':
|
||||
*output++ = '%';
|
||||
break;
|
||||
|
||||
case '[': {
|
||||
const char*tail;
|
||||
pattern += 1;
|
||||
assert(*pattern);
|
||||
tail = strchr(pattern+1, ']');
|
||||
assert(tail);
|
||||
strncpy(tmp_buf, pattern+1, tail-pattern-1);
|
||||
tmp_buf[tail-pattern-1] = 0;
|
||||
|
||||
if (((*pattern == 's') && start)
|
||||
|| ((*pattern == 'v') && verbose_flag)
|
||||
|| ((*pattern == 'N') && npath)
|
||||
|| ((*pattern == 'T') && mtm)) {
|
||||
int rc = build_string(output, olen,
|
||||
tmp_buf);
|
||||
output += rc;
|
||||
olen -= rc;
|
||||
}
|
||||
pattern = tail;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'B':
|
||||
strcpy(output, base);
|
||||
output += strlen(base);
|
||||
olen -= strlen(base);
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
if (f_list) {
|
||||
strcpy(output, f_list);
|
||||
output += strlen(f_list);
|
||||
olen -= strlen(f_list);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
if (mod_list) {
|
||||
strcpy(output, mod_list);
|
||||
output += strlen(mod_list);
|
||||
olen -= strlen(mod_list);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'N':
|
||||
if (npath) {
|
||||
strcpy(output, npath);
|
||||
output += strlen(npath);
|
||||
olen -= strlen(npath);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
strcpy(output, opath);
|
||||
output += strlen(opath);
|
||||
olen -= strlen(opath);
|
||||
break;
|
||||
|
||||
case 's':
|
||||
if (start) {
|
||||
strcpy(output, start);
|
||||
output += strlen(start);
|
||||
olen -= strlen(start);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'T':
|
||||
if (mtm) {
|
||||
strcpy(output, mtm);
|
||||
output += strlen(mtm);
|
||||
olen -= strlen(mtm);
|
||||
}
|
||||
break;
|
||||
|
||||
case 't':
|
||||
strcpy(output, targ);
|
||||
output += strlen(targ);
|
||||
olen -= strlen(targ);
|
||||
break;
|
||||
|
||||
case 'W':
|
||||
strcpy(output, warning_flags);
|
||||
output += strlen(warning_flags);
|
||||
olen -= strlen(warning_flags);
|
||||
break;
|
||||
|
||||
}
|
||||
pattern += 1;
|
||||
|
||||
} else {
|
||||
*output++ = *pattern++;
|
||||
olen -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
*output = 0;
|
||||
return output-output_save;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: build_string.c,v $
|
||||
* Revision 1.4 2001/07/25 03:10:50 steve
|
||||
* Create a config.h.in file to hold all the config
|
||||
* junk, and support gcc 3.0. (Stephan Boettcher)
|
||||
*
|
||||
* Revision 1.3 2001/07/03 04:09:25 steve
|
||||
* Generate verbuse status messages (Stephan Boettcher)
|
||||
*
|
||||
* Revision 1.2 2000/10/28 03:45:47 steve
|
||||
* Use the conf file to generate the vvm ivl string.
|
||||
*
|
||||
* Revision 1.1 2000/10/08 22:36:56 steve
|
||||
* iverilog with an iverilog.conf configuration file.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
#ifndef __globals_H
|
||||
#define __globals_H
|
||||
/*
|
||||
* Copyright (c) 2000 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
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: globals.h,v 1.4 2001/07/03 04:09:25 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <stddef.h>
|
||||
|
||||
/* This is the base (i.e. -B<value>) of the Icarus Verilog files. */
|
||||
extern const char*base;
|
||||
|
||||
/* This is a list of all the -f<key>=<value> options from the
|
||||
command line, concatenated together. */
|
||||
extern char*f_list;
|
||||
|
||||
extern char*mod_list;
|
||||
|
||||
/* This is the optional -Tmin|typ|max setting. */
|
||||
extern const char*mtm;
|
||||
|
||||
/* Ths is the optional -N<path> value, if one was supplied. */
|
||||
extern const char*npath;
|
||||
|
||||
/* This is the name of the output file that the user selected. */
|
||||
extern const char*opath;
|
||||
|
||||
/* This pointer is set if there was a -s<value> parameter. */
|
||||
extern const char*start;
|
||||
|
||||
/* This flag is true if the -S flag was used on the command line. */
|
||||
extern int synth_flag;
|
||||
|
||||
/* This is the name of the selected target. */
|
||||
extern const char*targ;
|
||||
|
||||
/* -v */
|
||||
extern int verbose_flag;
|
||||
|
||||
extern char warning_flags[];
|
||||
|
||||
extern const char*lookup_pattern(const char*key);
|
||||
|
||||
extern int build_string(char*out, size_t olen, const char*pattern);
|
||||
|
||||
/*
|
||||
* $Log: globals.h,v $
|
||||
* Revision 1.4 2001/07/03 04:09:25 steve
|
||||
* Generate verbuse status messages (Stephan Boettcher)
|
||||
*
|
||||
* Revision 1.3 2000/11/09 21:58:00 steve
|
||||
* Remember to include the -S condition.
|
||||
*
|
||||
* Revision 1.2 2000/10/28 03:45:47 steve
|
||||
* Use the conf file to generate the vvm ivl string.
|
||||
*
|
||||
* Revision 1.1 2000/10/08 22:36:56 steve
|
||||
* iverilog with an iverilog.conf configuration file.
|
||||
*
|
||||
*/
|
||||
#endif
|
||||
@@ -0,0 +1,202 @@
|
||||
.TH iverilog 1 "$Date: 2001/08/31 17:28:10 $" Version "$Date: 2001/08/31 17:28:10 $"
|
||||
.SH NAME
|
||||
iverilog - Icarus Verilog compiler
|
||||
|
||||
.SH SYNOPSIS
|
||||
.B iverilog
|
||||
[-ESv] [-Cpath] [-ccmdfile] [-Dmacro[=defn]] [-pflag=value] [-Iincludepath] [-mmodule] [-Nfile] [-ooutputfilename] [-stopmodule] [-ttype] [-Tmin/typ/max] [-Wclass] sourcefile
|
||||
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
\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 \fIvvm\fP (for
|
||||
executable simulation) and \fIvvp\fP for simulation, and \fIxnf\fP for
|
||||
synthesis. Other target types are added as code generators are
|
||||
implemented.
|
||||
|
||||
.SH OPTIONS
|
||||
.l
|
||||
\fIiverilog\fP accepts the following options:
|
||||
.TP 8
|
||||
.B -B\fIbase\fP
|
||||
The \fIiverilog\fP program uses external programs to preprocess and
|
||||
compile the verilog source. Normally, the path used to locate these
|
||||
tools is built into the \fIiverilog\fP program. However, the \fB-B\fP
|
||||
switch allows the user to select a different set of programs. The path
|
||||
given is used to locate \fIivlpp\fP, \fIivl\fP and the VPI modules.
|
||||
.TP 8
|
||||
.B -c\fIfile\fP
|
||||
This flag specifies an input file that contains a list of Verilog
|
||||
source files. This is similar to the \fIcommand file\fP of other
|
||||
Verilog simulators, in that it is a file that contains the file names
|
||||
instead of taking them on the command line. The command file may
|
||||
contain C-style comments (/*-*/) or shell-style comments (# to the end
|
||||
of the line.)
|
||||
.TP 8
|
||||
.B -C\fIpath\fP
|
||||
This flag selects the driver configuration file to use. Normally, the
|
||||
iverilog program will read its configuration file from
|
||||
/usr/lib/ivl/iverilog.conf (or the install path configured at compile
|
||||
time) but the user can specify the path to a different configuration
|
||||
file. This is useful when testing new configuration files. See the
|
||||
installed configuration file for a summary of the file format.
|
||||
.TP 8
|
||||
.B -D\fImacro\fP
|
||||
Defines macro \fImacro\fP with the string `1' as its definition. This
|
||||
form is normally only used to trigger ifdef conditionals in the
|
||||
Verilog source.
|
||||
.TP 8
|
||||
.B -D\fImacro=defn\fP
|
||||
Defines macro \fImacro\fP as \fIdefn\fP.
|
||||
.TP 8
|
||||
.B -E
|
||||
Preprocess the Verilog source, but do not compile it. The output file
|
||||
is the Verilog input, but with file inclusions and macro references
|
||||
expanded and removed. This is useful, for example, to preprocess
|
||||
verilog source for use by other compilers.
|
||||
.TP 8
|
||||
.B -I\fIincludedir\fP
|
||||
Append directory \fIincludepdir\fP to list of directories searched
|
||||
for Verilog include files. The \fB-I\fP switch may be used many times
|
||||
to specify several directories to search, the directories are searched
|
||||
in the order they appear on the command line.
|
||||
.TP 8
|
||||
.B -m\fImodule\fP
|
||||
Add this module to the list of VPI modules to be loaded by the
|
||||
simulation. Many modules can be specified, and all will be loaded, in
|
||||
the order specified. The system module is implicit and always included.
|
||||
.TP 8
|
||||
.B -N\fIpath\fP
|
||||
This is used for debugging the compiler proper. Dump the final netlist
|
||||
form of the design to the specified file. It otherwise does not affect
|
||||
operation of the compiler. The dump happens after the design is
|
||||
elaborated and optimized.
|
||||
.TP 8
|
||||
.B -o \fIfilename\fP
|
||||
Place output in the file \fIfilename\fP. If no output file name is
|
||||
specified, \fIiverilog\fP uses the default name \fBa.out\fP.
|
||||
.TP 8
|
||||
.B -p\fIflag=value\fP
|
||||
Assign a value to a target specific flag. The \fB-p\fP switch may be
|
||||
used as often as necessary to specify all the desired flags. The flags
|
||||
that are used depend on the target that is selected, and are described
|
||||
in target specific documentation. Flags that are not used are ignored.
|
||||
.TP 8
|
||||
.B -S
|
||||
Synthesize. Normally, if the target can accept behavioral
|
||||
descriptions the compiler will leave processes in behavioral
|
||||
form. The \fB-S\fP switch causes the compiler to perform synthesis
|
||||
even if it is not necessary for the target. If the target type is a
|
||||
netlist format, the \fB-S\fP switch is unnecessary and has no effect.
|
||||
.TP 8
|
||||
.B -s \fItopmodule\fP
|
||||
Specify the top level module to elaborate. Icarus Verilog will by default
|
||||
choose the only module that has no ports. However, this simplistic
|
||||
heuristic is often not sufficient, and sometimes not what is wanted
|
||||
anyhow.
|
||||
.TP 8
|
||||
.B -T\fImin|typ|max\fP
|
||||
Use this switch to select min, typ or max times from min:typ:max
|
||||
expressions. Normally, the compiler will simply use the typ value from
|
||||
these expressions (with a warning) but this switch will tell the
|
||||
compiler explicitly which value to use. This will suppress the
|
||||
warning that the compiler is making a choice.
|
||||
.TP 8
|
||||
.B -t\fItarget\fP
|
||||
Use this switch to specify the target output format. See the
|
||||
\fBTARGETS\fP section below for a list of valid output formats.
|
||||
.TP 8
|
||||
.B -v
|
||||
Turn on verbose messages. This will print the command lines that are
|
||||
executed to perform the actual compilation, along with version
|
||||
information from the various components.
|
||||
.TP 8
|
||||
.B -W\fIclass\fP
|
||||
Turn on different classes of warnings. See the \fBWARNING TYPES\fP
|
||||
section below for desctriptions of the different warning groups. If
|
||||
multiple \fB-W\fP switches are used, the warning set is the union of
|
||||
all the requested classes.
|
||||
|
||||
.SH TARGETS
|
||||
|
||||
The Icarus Verilog compiler supports a variety of targets, for
|
||||
different purposes, and the \fB-t\fP switch is used to select the
|
||||
desired target.
|
||||
|
||||
.TP 8
|
||||
.B null
|
||||
The null target causes no code to be generated. It is useful for
|
||||
checking the syntax of the Verilog source.
|
||||
.TP 8
|
||||
.B vvm
|
||||
The target is an executable program that uses the vvm simulation
|
||||
runtime. The compiler actually generates C++ code, then compiles and
|
||||
links that code to make the output executable.
|
||||
.TP 8
|
||||
.B vvp
|
||||
This is the default. The vvp target generates code for the vvp
|
||||
runtime. The output is a complete program that simulates the design
|
||||
(like with vvm) but must be run by the \fivvp\fP command. This target
|
||||
is much faster then the \fBvvm\fP target, but not quite as complete.
|
||||
.TP 8
|
||||
.B xnf
|
||||
This is the Xilinx Netlist Format used by many tools for placing
|
||||
devices in FPGAs or other programmable devices. The Icarus Verilog XNF
|
||||
code generator can generate complete designs or XNF macros that can be
|
||||
imported into larger designs by other tools.
|
||||
.TP 8
|
||||
.B fpga
|
||||
This is a variant of the XNF code generator that supports a wider
|
||||
variety of target devices. It is intented as a future replacement for
|
||||
the existing \fBxnf\fP target, but for now is still experimental.
|
||||
|
||||
.SH "WARNING TYPES"
|
||||
These are the types of warnings that can be selected by the \fB-W\fP
|
||||
switch.
|
||||
|
||||
.TP 8
|
||||
.B all
|
||||
This enables all supported warning categories.
|
||||
|
||||
.TP 8
|
||||
.B implicit
|
||||
This enables warnings for creation of implicit declarations. For
|
||||
example, if a scaler wire X is used but not declared in the Verilog
|
||||
source, this will print a warning at its first use.
|
||||
|
||||
.SH EXAMPLES
|
||||
These examples assume that you have a Verilog source file called hello.v in
|
||||
the current directory
|
||||
|
||||
To compile hello.v to an executable file called a.out:
|
||||
|
||||
iverilog hello.v
|
||||
|
||||
To compile hello.v to an executable file called hello:
|
||||
|
||||
iverilog -o hello hello.v
|
||||
|
||||
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])
|
||||
|
||||
.SH SEE ALSO
|
||||
vvp(1),
|
||||
.BR "<http://www.icarus.com/eda/verilog/>"
|
||||
|
||||
.SH COPYRIGHT
|
||||
.nf
|
||||
Copyright \(co 2000 Stephen Williams
|
||||
|
||||
This document can be freely redistributed according to the terms of the
|
||||
GNU General Public License version 2.0
|
||||
@@ -0,0 +1,80 @@
|
||||
|
||||
%{
|
||||
/*
|
||||
* Copyright (c) 2000 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
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: lexor.lex,v 1.5 2001/07/25 03:10:50 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# include <string.h>
|
||||
# include "parse.h"
|
||||
|
||||
%}
|
||||
|
||||
%x CTOKENS
|
||||
%x PATTERN
|
||||
|
||||
%%
|
||||
|
||||
"#".* { /* eat comments */; }
|
||||
|
||||
"\n" { /* eat line-ends */; }
|
||||
"\r" { /* eat line-ends */; }
|
||||
|
||||
"[" { BEGIN(CTOKENS); return '['; }
|
||||
|
||||
<CTOKENS>"]" { BEGIN(0); return ']'; }
|
||||
|
||||
<CTOKENS>[ \t\b]+ { /* skip white space */; }
|
||||
|
||||
<CTOKENS>"-S" { return CT_S; }
|
||||
|
||||
<CTOKENS>"-t"[a-zA-Z0-9\-_]+ {
|
||||
yylval.text = strdup(yytext+2);
|
||||
return CT_t; }
|
||||
|
||||
"<"[^>]*">" {
|
||||
BEGIN(PATTERN);
|
||||
yylval.text = strdup(yytext);
|
||||
return PATTERN_NAME; }
|
||||
|
||||
<PATTERN>.* {
|
||||
BEGIN(0);
|
||||
/* Trim off a trailing \r. This is an issue in the DOS world. */
|
||||
if (yytext[strlen(yytext)-1] == '\r')
|
||||
yytext[strlen(yytext)-1] = 0;
|
||||
|
||||
yylval.text = strdup(yytext);
|
||||
return PATTERN_TEXT; }
|
||||
|
||||
. { fprintf(stderr, "driver lexor: Unmatched character: %c\n", yytext[0]); }
|
||||
|
||||
%%
|
||||
|
||||
void reset_lexor(FILE*fd)
|
||||
{
|
||||
yyrestart(fd);
|
||||
}
|
||||
|
||||
int yywrap()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
+690
@@ -0,0 +1,690 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2001 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
|
||||
*/
|
||||
#ident "$Id: main.c,v 1.21 2001/07/25 03:10:50 steve Exp $"
|
||||
|
||||
# include "config.h"
|
||||
|
||||
const char HELP[] =
|
||||
"Usage: iverilog [-ESv] [-B base] [-C path] [-c cmdfile]\n"
|
||||
" [-D macro[=defn]] [-I includedir] [-m module]\n"
|
||||
" [-N file] [-o filename] [-p flag=value]\n"
|
||||
" [-s topmodule] [-t target] [-T min|typ|max]\n"
|
||||
" [-W class] source_file(s)\n"
|
||||
"See man page for details.";
|
||||
|
||||
#define MAXSIZE 4096
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#ifdef HAVE_SYS_WAIT_H
|
||||
#include <sys/wait.h>
|
||||
#endif
|
||||
|
||||
#ifdef __MINGW32__
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_GETOPT_H
|
||||
#include <getopt.h>
|
||||
#endif
|
||||
|
||||
#if defined(__MINGW32__) && !defined(HAVE_GETOPT_H)
|
||||
extern int getopt(int argc, char*argv[], const char*fmt);
|
||||
extern int optind;
|
||||
extern const char*optarg;
|
||||
#endif
|
||||
|
||||
#if !defined(WIFEXITED)
|
||||
# define WIFEXITED(rc) ((rc&0x7f) == 0)
|
||||
#endif
|
||||
|
||||
#if !defined(WEXITSTATUS)
|
||||
# define WEXITSTATUS(rc) (rc>>8)
|
||||
#endif
|
||||
|
||||
#ifndef IVL_ROOT
|
||||
# define IVL_ROOT "."
|
||||
#endif
|
||||
|
||||
#ifndef RDYNAMIC
|
||||
# define RDYNAMIC "-rdynamic"
|
||||
#endif
|
||||
|
||||
# include "globals.h"
|
||||
|
||||
#ifdef __MINGW32__
|
||||
const char sep = '\\';
|
||||
#else
|
||||
const char sep = '/';
|
||||
#endif
|
||||
|
||||
const char*base = 0;
|
||||
const char*mtm = 0;
|
||||
const char*opath = "a.out" EXEEXT;
|
||||
const char*npath = 0;
|
||||
const char*targ = "vvp";
|
||||
const char*start = 0;
|
||||
|
||||
char warning_flags[16] = "";
|
||||
|
||||
char*inc_list = 0;
|
||||
char*def_list = 0;
|
||||
char*mod_list = 0;
|
||||
char*command_filename = 0;
|
||||
|
||||
char*f_list = 0;
|
||||
|
||||
int synth_flag = 0;
|
||||
int verbose_flag = 0;
|
||||
int command_file = 0;
|
||||
int inside_c_comment = 0;
|
||||
|
||||
FILE *fp;
|
||||
|
||||
char line[MAXSIZE];
|
||||
char tmp[MAXSIZE];
|
||||
|
||||
static char ivl_root[MAXSIZE];
|
||||
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
int rc;
|
||||
const char*pattern;
|
||||
|
||||
pattern = lookup_pattern("<ivl>");
|
||||
if (pattern == 0) {
|
||||
fprintf(stderr, "No such target: %s\n", targ);
|
||||
return -1;
|
||||
}
|
||||
|
||||
tmp[0] = ' ';
|
||||
tmp[1] = '|';
|
||||
tmp[2] = ' ';
|
||||
rc = build_string(tmp+3, sizeof tmp - 3, pattern);
|
||||
cmd = realloc(cmd, ncmd+3+rc+1);
|
||||
#ifdef __MINGW32__
|
||||
{
|
||||
char *t;
|
||||
for (t = tmp; *t; t++)
|
||||
{
|
||||
if (*t == '/') *t = '\\';
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
strcpy(cmd+ncmd, tmp);
|
||||
|
||||
|
||||
if (verbose_flag)
|
||||
printf("translate: %s\n", cmd);
|
||||
|
||||
|
||||
rc = system(cmd);
|
||||
if (rc != 0) {
|
||||
if (WIFEXITED(rc))
|
||||
return WEXITSTATUS(rc);
|
||||
|
||||
fprintf(stderr, "Command signaled: %s\n", cmd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function handles the vvm target. After preprocessing, run the
|
||||
* ivl translator to get C++, then run g++ to make an executable
|
||||
* program out of that.
|
||||
*/
|
||||
static int t_vvm(char*cmd, unsigned ncmd)
|
||||
{
|
||||
int rc;
|
||||
|
||||
const char*pattern = lookup_pattern("<ivl>");
|
||||
if (pattern == 0) {
|
||||
fprintf(stderr, "No such target: %s\n", targ);
|
||||
return -1;
|
||||
}
|
||||
|
||||
tmp[0] = ' ';
|
||||
tmp[1] = '|';
|
||||
tmp[2] = ' ';
|
||||
rc = build_string(tmp+3, sizeof tmp - 3, pattern);
|
||||
cmd = realloc(cmd, ncmd+3+rc+1);
|
||||
|
||||
#ifdef __MINGW32__
|
||||
{
|
||||
char *t;
|
||||
for (t = tmp; *t; t++)
|
||||
{
|
||||
if (*t == '/') *t = '\\';
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
strcpy(cmd+ncmd, tmp);
|
||||
|
||||
|
||||
if (verbose_flag)
|
||||
printf("translate: %s\n", cmd);
|
||||
|
||||
rc = system(cmd);
|
||||
if (rc != 0) {
|
||||
if (WIFEXITED(rc)) {
|
||||
fprintf(stderr, "errors translating Verilog program.\n");
|
||||
return WEXITSTATUS(rc);
|
||||
} else {
|
||||
fprintf(stderr, "Command signaled: %s\n", cmd);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(__MINGW32__)
|
||||
/* In the Windows world, the path to headers and libraries
|
||||
for vvm is relative the ivl_root, which is in something like:
|
||||
|
||||
d:\iverilog\lib\ivl <-- ivl_root
|
||||
d:\iverilog\include <-- vvm headers
|
||||
d:\iverilog\lib <-- vvm libraries
|
||||
|
||||
So we make up all the ugly references that are the g++
|
||||
command line to compile a .cc file generated by vvm. */
|
||||
sprintf(tmp, "%s " RDYNAMIC " -s -fno-exceptions -o %s "
|
||||
"-I%s\\..\\..\\include -L%s\\.. %s.cc -lvvm -lvpip %s",
|
||||
CXX, opath, ivl_root, ivl_root, opath, DLLIB);
|
||||
#else
|
||||
/* In the UNIX universe, life is easy. The configure script
|
||||
has figured everything out and wrote it into the Makefile,
|
||||
which passes it on as the IVL_INC and IVL_LIB defines. */
|
||||
sprintf(tmp, "%s " RDYNAMIC " -s -fno-exceptions -o %s -I%s "
|
||||
"-L%s %s.cc -lvvm -lvpip %s", CXX, opath, IVL_INC,
|
||||
IVL_LIB, opath, DLLIB);
|
||||
#endif
|
||||
if (verbose_flag)
|
||||
printf("compile: %s\n", tmp);
|
||||
|
||||
rc = system(tmp);
|
||||
if (rc != 0) {
|
||||
if (WIFEXITED(rc)) {
|
||||
fprintf(stderr, "errors compiling translated program.\n");
|
||||
return WEXITSTATUS(rc);
|
||||
} else {
|
||||
fprintf(stderr, "Command signaled: %s\n", tmp);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
sprintf(tmp, "%s.cc", opath);
|
||||
unlink(tmp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int t_xnf(char*cmd, unsigned ncmd)
|
||||
{
|
||||
int rc;
|
||||
|
||||
sprintf(tmp, " | %s%civl %s -o %s -txnf -Fcprop -Fsynth -Fsyn-rules "
|
||||
"-Fnodangle -Fxnfio", base, sep,warning_flags, opath);
|
||||
|
||||
rc = strlen(tmp);
|
||||
cmd = realloc(cmd, ncmd+rc+1);
|
||||
#ifdef __MINGW32__
|
||||
{
|
||||
char *t;
|
||||
for (t = tmp; *t; t++)
|
||||
{
|
||||
if (*t == '/') *t = '\\';
|
||||
}
|
||||
}
|
||||
#endif
|
||||
strcpy(cmd+ncmd, tmp);
|
||||
ncmd += rc;
|
||||
|
||||
if (f_list) {
|
||||
rc = strlen(f_list);
|
||||
cmd = realloc(cmd, ncmd+rc+1);
|
||||
strcpy(cmd+ncmd, f_list);
|
||||
ncmd += rc;
|
||||
}
|
||||
|
||||
if (mtm) {
|
||||
sprintf(tmp, " -T%s", mtm);
|
||||
rc = strlen(tmp);
|
||||
cmd = realloc(cmd, ncmd+rc+1);
|
||||
strcpy(cmd+ncmd, tmp);
|
||||
ncmd += rc;
|
||||
}
|
||||
|
||||
if (npath) {
|
||||
sprintf(tmp, " -N%s", npath);
|
||||
rc = strlen(tmp);
|
||||
cmd = realloc(cmd, ncmd+rc+1);
|
||||
strcpy(cmd+ncmd, tmp);
|
||||
ncmd += rc;
|
||||
}
|
||||
|
||||
if (start) {
|
||||
sprintf(tmp, " -s%s", start);
|
||||
rc = strlen(tmp);
|
||||
cmd = realloc(cmd, ncmd+rc+1);
|
||||
strcpy(cmd+ncmd, tmp);
|
||||
ncmd += rc;
|
||||
}
|
||||
sprintf(tmp, " -- -");
|
||||
rc = strlen(tmp);
|
||||
cmd = realloc(cmd, ncmd+rc+1);
|
||||
strcpy(cmd+ncmd, tmp);
|
||||
ncmd += rc;
|
||||
|
||||
if (verbose_flag)
|
||||
printf("translate: %s\n", cmd);
|
||||
|
||||
rc = system(cmd);
|
||||
if (rc != 0) {
|
||||
if (WIFEXITED(rc)) {
|
||||
fprintf(stderr, "errors translating Verilog program.\n");
|
||||
return WEXITSTATUS(rc);
|
||||
}
|
||||
|
||||
fprintf(stderr, "Command signaled: %s\n", cmd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void process_warning_switch(const char*name)
|
||||
{
|
||||
if (warning_flags[0] == 0)
|
||||
strcpy(warning_flags, "-W");
|
||||
|
||||
if (strcmp(name,"all") == 0) {
|
||||
strcat(warning_flags, "i");
|
||||
|
||||
} else if (strcmp(name,"implicit") == 0) {
|
||||
if (! strchr(warning_flags+2, 'i'))
|
||||
strcat(warning_flags, "i");
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const char*config_path = 0;
|
||||
char*cmd;
|
||||
unsigned ncmd;
|
||||
int e_flag = 0;
|
||||
int opt, idx;
|
||||
char*cp;
|
||||
|
||||
#ifdef __MINGW32__
|
||||
{ char * s;
|
||||
char basepath[1024];
|
||||
GetModuleFileName(NULL,basepath,1024);
|
||||
|
||||
/* Calculate the ivl_root from the path to the command. This
|
||||
is necessary because of the installation process in
|
||||
Windows. Mostly, it is those darn drive letters, but oh
|
||||
well. We know the command path is formed like this:
|
||||
|
||||
D:\iverilog\bin\iverilog.exe
|
||||
|
||||
The IVL_ROOT in a Windows installation is the path:
|
||||
|
||||
D:\iverilog\lib\ivl
|
||||
|
||||
so we chop the file name and the last directory by
|
||||
turning the last two \ characters to null. Then we append
|
||||
the lib\ivl to finish. */
|
||||
|
||||
strncpy(ivl_root, basepath, MAXSIZE);
|
||||
s = strrchr(ivl_root, sep);
|
||||
if (s) *s = 0;
|
||||
s = strrchr(ivl_root, sep);
|
||||
if (s) *s = 0;
|
||||
strcat(ivl_root, "\\lib\\ivl");
|
||||
|
||||
base = ivl_root;
|
||||
}
|
||||
#else
|
||||
/* In a UNIX environment, the IVL_ROOT from the Makefile is
|
||||
dependable. It points to the $prefix/lib/ivl directory,
|
||||
where the sub-parts are installed. */
|
||||
strcpy(ivl_root, IVL_ROOT);
|
||||
base = ivl_root;
|
||||
#endif
|
||||
|
||||
while ((opt = getopt(argc, argv, "B:C:c:D:Ef:hI:m:N::o:p:Ss:T:t:vW:")) != EOF) {
|
||||
|
||||
switch (opt) {
|
||||
case 'B':
|
||||
base = optarg;
|
||||
break;
|
||||
case 'C':
|
||||
config_path = optarg;
|
||||
break;
|
||||
case 'c':
|
||||
command_filename = malloc(strlen(optarg)+1);
|
||||
strcat(command_filename, optarg);
|
||||
break;
|
||||
case 'D':
|
||||
if (def_list == 0) {
|
||||
def_list = malloc(strlen(" -D")+strlen(optarg)+1);
|
||||
strcpy(def_list, " -D");
|
||||
strcat(def_list, optarg);
|
||||
} else {
|
||||
def_list = realloc(def_list, strlen(def_list)
|
||||
+ strlen(" -D")
|
||||
+ strlen(optarg) + 1);
|
||||
strcat(def_list, " -D");
|
||||
strcat(def_list, optarg);
|
||||
}
|
||||
break;
|
||||
case 'E':
|
||||
e_flag = 1;
|
||||
break;
|
||||
case 'f':
|
||||
fprintf(stderr, "warning: The -f flag is moved to -p\n");
|
||||
case 'p':
|
||||
if (f_list == 0) {
|
||||
f_list = malloc(strlen(" -p")+strlen(optarg)+1);
|
||||
strcpy(f_list, " -p");
|
||||
strcat(f_list, optarg);
|
||||
} else {
|
||||
f_list = realloc(f_list, strlen(f_list) +
|
||||
strlen(" -p") +
|
||||
strlen(optarg) + 1);
|
||||
strcat(f_list, " -p");
|
||||
strcat(f_list, optarg);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
fprintf(stderr, "%s\n", HELP);
|
||||
return 1;
|
||||
|
||||
case 'I':
|
||||
if (inc_list == 0) {
|
||||
inc_list = malloc(strlen(" -I")+strlen(optarg)+1);
|
||||
strcpy(inc_list, " -I");
|
||||
strcat(inc_list, optarg);
|
||||
} else {
|
||||
inc_list = realloc(inc_list, strlen(inc_list)
|
||||
+ strlen(" -I")
|
||||
+ strlen(optarg) + 1);
|
||||
strcat(inc_list, " -I");
|
||||
strcat(inc_list, optarg);
|
||||
}
|
||||
break;
|
||||
case 'm':
|
||||
if (mod_list == 0) {
|
||||
mod_list = malloc(strlen(" -m")+strlen(optarg)+1);
|
||||
strcpy(mod_list, " -m");
|
||||
strcat(mod_list, optarg);
|
||||
} else {
|
||||
mod_list = realloc(mod_list, strlen(mod_list)
|
||||
+ strlen(" -m")
|
||||
+ strlen(optarg) + 1);
|
||||
strcat(mod_list, " -m");
|
||||
strcat(mod_list, optarg);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'N':
|
||||
npath = optarg;
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
opath = optarg;
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
synth_flag = 1;
|
||||
break;
|
||||
case 's':
|
||||
start = optarg;
|
||||
break;
|
||||
case 'T':
|
||||
if (strcmp(optarg,"min") == 0) {
|
||||
mtm = "min";
|
||||
} else if (strcmp(optarg,"typ") == 0) {
|
||||
mtm = "typ";
|
||||
} else if (strcmp(optarg,"max") == 0) {
|
||||
mtm = "max";
|
||||
} else {
|
||||
fprintf(stderr, "%s: invalid -T%s argument\n",
|
||||
argv[0], optarg);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case 't':
|
||||
targ = optarg;
|
||||
break;
|
||||
case 'v':
|
||||
verbose_flag = 1;
|
||||
break;
|
||||
case 'W':
|
||||
process_warning_switch(optarg);
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if ((optind == argc) && !command_filename) {
|
||||
fprintf(stderr, "%s: No input files.\n", argv[0]);
|
||||
fprintf(stderr, "%s\n", HELP);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Load the iverilog.conf file to get our substitution
|
||||
strings. */
|
||||
|
||||
{ char path[1024];
|
||||
FILE*fd;
|
||||
if (config_path) {
|
||||
strcpy(path, config_path);
|
||||
} else {
|
||||
sprintf(path, "%s%civerilog.conf", base,sep);
|
||||
}
|
||||
fd = fopen(path, "r");
|
||||
if (fd == 0) {
|
||||
fprintf(stderr, "Config file \"%s\" not found\n",path);
|
||||
return 1;
|
||||
}
|
||||
reset_lexor(fd);
|
||||
yyparse();
|
||||
}
|
||||
|
||||
/* Start building the preprocess command line. */
|
||||
|
||||
sprintf(tmp, "%s%civlpp %s%s", base,sep,
|
||||
verbose_flag?" -v":"",
|
||||
e_flag?"":" -L");
|
||||
|
||||
ncmd = strlen(tmp);
|
||||
cmd = malloc(ncmd + 1);
|
||||
strcpy(cmd, tmp);
|
||||
|
||||
if (inc_list) {
|
||||
cmd = realloc(cmd, ncmd + strlen(inc_list) + 1);
|
||||
strcat(cmd, inc_list);
|
||||
ncmd += strlen(inc_list);
|
||||
}
|
||||
|
||||
if (def_list) {
|
||||
cmd = realloc(cmd, ncmd + strlen(def_list) + 1);
|
||||
strcat(cmd, def_list);
|
||||
ncmd += strlen(def_list);
|
||||
}
|
||||
|
||||
/* If user supplied a command file, retain its contents -- this
|
||||
process supersedes command line source files. */
|
||||
|
||||
if (command_filename != 0) {
|
||||
if (( fp = fopen(command_filename, "r")) == NULL ) {
|
||||
fprintf(stderr, "%s: Can't open %s\n",
|
||||
argv[0], command_filename);
|
||||
return 1;
|
||||
|
||||
} else {
|
||||
/* Process file and skip over commented-out lines.
|
||||
Skips over c-like comment as well as '//' or
|
||||
'#' lines. */
|
||||
|
||||
sprintf(tmp, "");
|
||||
while (fgets(line, MAXSIZE, fp) != NULL) {
|
||||
if ( strstr(line, "*/") != NULL ) {
|
||||
inside_c_comment = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (inside_c_comment || (strstr(line, "/*") != NULL)) {
|
||||
inside_c_comment = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( (line[0] != '/' || line[1] != '/')
|
||||
&& line[0] != '#' ) {
|
||||
strcat (tmp, " ");
|
||||
strncat (tmp, line, (strlen(line)-1));
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
cmd = realloc(cmd, ncmd+strlen(tmp)+1);
|
||||
strcpy(cmd+ncmd, tmp);
|
||||
ncmd += strlen(tmp);
|
||||
|
||||
} else {
|
||||
|
||||
/* Add all verilog source files to the preprocess
|
||||
command line. */
|
||||
|
||||
for (idx = optind ; idx < argc ; idx += 1) {
|
||||
sprintf(tmp, " %s", argv[idx]);
|
||||
cmd = realloc(cmd, ncmd+strlen(tmp)+1);
|
||||
strcpy(cmd+ncmd, tmp);
|
||||
ncmd += strlen(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);
|
||||
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;
|
||||
}
|
||||
|
||||
if (strcmp(targ,"vvm") == 0)
|
||||
return t_vvm(cmd, ncmd);
|
||||
else if (strcmp(targ,"xnf") == 0)
|
||||
return t_xnf(cmd, ncmd);
|
||||
else {
|
||||
return t_default(cmd, ncmd);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: main.c,v $
|
||||
* Revision 1.21 2001/07/25 03:10:50 steve
|
||||
* Create a config.h.in file to hold all the config
|
||||
* junk, and support gcc 3.0. (Stephan Boettcher)
|
||||
*
|
||||
* Revision 1.20 2001/06/30 21:53:42 steve
|
||||
* Make the vvp target the default.
|
||||
*
|
||||
* Revision 1.19 2001/06/30 04:23:02 steve
|
||||
* Get include and lib paths right for mingw and vvm.
|
||||
*
|
||||
* Revision 1.18 2001/06/30 00:59:24 steve
|
||||
* Redo the ivl_root calculator for mingw.
|
||||
*
|
||||
* Revision 1.17 2001/06/27 02:22:26 steve
|
||||
* Get include and lib paths from Makefile.
|
||||
*
|
||||
* Revision 1.16 2001/06/20 02:25:40 steve
|
||||
* Edit ivl_install_dir only on mingw
|
||||
*
|
||||
* Revision 1.15 2001/06/15 05:14:21 steve
|
||||
* Fix library path calculation on non Windows systems
|
||||
* to include the install directories. (Brendan Simon)
|
||||
*
|
||||
* Revision 1.14 2001/06/12 03:53:10 steve
|
||||
* Change the VPI call process so that loaded .vpi modules
|
||||
* use a function table instead of implicit binding.
|
||||
*
|
||||
* Revision 1.13 2001/05/20 18:22:02 steve
|
||||
* Fix WIFEXITED macro.
|
||||
*
|
||||
* Revision 1.12 2001/05/20 18:06:57 steve
|
||||
* local declares if the header is missing.
|
||||
*
|
||||
* Revision 1.11 2001/05/20 15:09:40 steve
|
||||
* Mingw32 support (Venkat Iyer)
|
||||
*
|
||||
* Revision 1.10 2001/05/17 03:14:26 steve
|
||||
* Update help message.
|
||||
*
|
||||
* Revision 1.9 2001/04/26 16:04:39 steve
|
||||
* Handle missing or uninstalled .conf files.
|
||||
*
|
||||
* Revision 1.8 2001/02/01 17:12:22 steve
|
||||
* Forgot to actually allow the -p flag.
|
||||
*
|
||||
* Revision 1.7 2001/01/20 19:02:05 steve
|
||||
* Switch hte -f flag to the -p flag.
|
||||
*/
|
||||
|
||||
+164
@@ -0,0 +1,164 @@
|
||||
%{
|
||||
/*
|
||||
* Copyright (c) 2000 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
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: parse.y,v 1.3 2001/07/25 03:10:50 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# include <stdio.h>
|
||||
# include <malloc.h>
|
||||
# include "globals.h"
|
||||
|
||||
|
||||
void yyerror(const char*);
|
||||
|
||||
enum drive_code_t {
|
||||
CODE_S,
|
||||
CODE_t,
|
||||
};
|
||||
|
||||
struct drive_cond {
|
||||
struct drive_cond*next;
|
||||
enum drive_code_t code;
|
||||
char* text;
|
||||
};
|
||||
|
||||
static struct drive_cond *cur_cond = 0;
|
||||
|
||||
static void add_cond(enum drive_code_t code, char*text)
|
||||
{
|
||||
struct drive_cond*tmp;
|
||||
tmp = calloc(1, sizeof(struct drive_cond));
|
||||
tmp->code = code;
|
||||
tmp->text = text;
|
||||
|
||||
tmp->next = cur_cond;
|
||||
cur_cond = tmp;
|
||||
}
|
||||
|
||||
struct drive_pattern {
|
||||
struct drive_pattern*next;
|
||||
char*name;
|
||||
char*text;
|
||||
struct drive_cond*cond;
|
||||
};
|
||||
|
||||
static struct drive_pattern *patterns = 0;
|
||||
static struct drive_pattern *plast = 0;
|
||||
|
||||
static void add_pattern(char*name, char*text)
|
||||
{
|
||||
struct drive_pattern*tmp;
|
||||
tmp = calloc(1, sizeof(struct drive_pattern));
|
||||
tmp->name = name;
|
||||
tmp->text = text;
|
||||
tmp->cond = cur_cond;
|
||||
tmp->next = 0;
|
||||
|
||||
|
||||
if (plast) {
|
||||
plast->next = tmp;
|
||||
plast = tmp;
|
||||
} else {
|
||||
patterns = tmp;
|
||||
plast = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
const char*lookup_pattern(const char*key)
|
||||
{
|
||||
struct drive_pattern*cur;
|
||||
struct drive_cond*cc;
|
||||
|
||||
for (cur = patterns ; cur ; cur = cur->next) {
|
||||
|
||||
if (strcmp(key, cur->name) != 0)
|
||||
continue;
|
||||
|
||||
for (cc = cur->cond ; cc ; cc = cc->next) {
|
||||
|
||||
switch (cc->code) {
|
||||
case CODE_S:
|
||||
if (synth_flag)
|
||||
continue;
|
||||
break;
|
||||
case CODE_t:
|
||||
if (strcmp(targ, cc->text) == 0)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (cc) continue;
|
||||
|
||||
return cur->text;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
%}
|
||||
|
||||
%union {
|
||||
char*text;
|
||||
};
|
||||
|
||||
%token <text> PATTERN_NAME PATTERN_TEXT
|
||||
%token <text> CT_t
|
||||
%token CT_S
|
||||
|
||||
%%
|
||||
|
||||
start: section_list
|
||||
|
||||
section_list
|
||||
: section
|
||||
| section_list section
|
||||
;
|
||||
|
||||
section : '[' ctoken_list ']' pattern_list { cur_cond = 0; } ;
|
||||
|
||||
ctoken_list
|
||||
: ctoken
|
||||
| ctoken_list ctoken
|
||||
;
|
||||
|
||||
ctoken : CT_S { add_cond(CODE_S, 0); }
|
||||
| CT_t { add_cond(CODE_t, $1); }
|
||||
;
|
||||
|
||||
pattern_list
|
||||
: pattern
|
||||
| pattern_list pattern
|
||||
;
|
||||
|
||||
pattern : PATTERN_NAME PATTERN_TEXT
|
||||
{ add_pattern($1, $2); }
|
||||
;
|
||||
|
||||
%%
|
||||
|
||||
void yyerror(const char*msg)
|
||||
{
|
||||
fprintf(stderr, "%s\n", msg);
|
||||
}
|
||||
+28
-2
@@ -16,10 +16,12 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: dup_expr.cc,v 1.1 1999/11/27 19:07:57 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: dup_expr.cc,v 1.5 2001/07/25 03:10:48 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# include "netlist.h"
|
||||
# include <cassert>
|
||||
|
||||
@@ -29,8 +31,32 @@ NetEScope* NetEScope::dup_expr() const
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetESFunc* NetESFunc::dup_expr() const
|
||||
{
|
||||
NetESFunc*tmp = new NetESFunc(name_, expr_width(), nparms());
|
||||
for (unsigned idx = 0 ; idx < nparms() ; idx += 1)
|
||||
tmp->parm(idx, tmp->parm(idx)->dup_expr());
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: dup_expr.cc,v $
|
||||
* Revision 1.5 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.4 2000/05/07 18:20:07 steve
|
||||
* Import MCD support from Stephen Tell, and add
|
||||
* system function parameter support to the IVL core.
|
||||
*
|
||||
* Revision 1.3 2000/05/04 03:37:58 steve
|
||||
* Add infrastructure for system functions, move
|
||||
* $time to that structure and add $random.
|
||||
*
|
||||
* Revision 1.2 2000/02/23 02:56:54 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.1 1999/11/27 19:07:57 steve
|
||||
* Support the creation of scopes.
|
||||
*
|
||||
|
||||
+163
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
* Copyright (c) 2000 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
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: elab_anet.cc,v 1.3 2001/07/25 03:10:48 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
/*
|
||||
* The elaborate_anet methods elaborate expressions that are intended
|
||||
* to be the left side of procedural continuous assignments.
|
||||
*/
|
||||
|
||||
# include "PExpr.h"
|
||||
# include "netlist.h"
|
||||
# include <iostream>
|
||||
|
||||
NetNet* PExpr::elaborate_anet(Design*des, NetScope*scope) const
|
||||
{
|
||||
cerr << get_line() << ": error: Invalid expression on left side "
|
||||
<< "of precedural continuous asignment." << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
NetNet* PEConcat::elaborate_anet(Design*des, NetScope*scope) const
|
||||
{
|
||||
if (repeat_) {
|
||||
cerr << get_line() << ": error: Repeat concatenations make "
|
||||
"no sense in l-value expressions. I refuse." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
svector<NetNet*>nets (parms_.count());
|
||||
unsigned pins = 0;
|
||||
unsigned errors = 0;
|
||||
|
||||
for (unsigned idx = 0 ; idx < nets.count() ; idx += 1) {
|
||||
|
||||
if (parms_[idx] == 0) {
|
||||
cerr << get_line() << ": error: Empty expressions "
|
||||
<< "not allowed in concatenations." << endl;
|
||||
errors += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
nets[idx] = parms_[idx]->elaborate_anet(des, scope);
|
||||
if (nets[idx] == 0)
|
||||
errors += 1;
|
||||
else
|
||||
pins += nets[idx]->pin_count();
|
||||
}
|
||||
|
||||
/* If any of the sub expressions failed to elaborate, then
|
||||
delete all those that did and abort myself. */
|
||||
if (errors) {
|
||||
for (unsigned idx = 0 ; idx < nets.count() ; idx += 1) {
|
||||
if (nets[idx]) delete nets[idx];
|
||||
}
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Make the temporary signal that connects to all the
|
||||
operands, and connect it up. Scan the operands of the
|
||||
concat operator from least significant to most significant,
|
||||
which is opposite from how they are given in the list.
|
||||
|
||||
Allow for a repeat count other then 1 by repeating the
|
||||
connect loop as many times as necessary. */
|
||||
|
||||
NetNet*osig = new NetNet(scope, des->local_symbol(scope->name()),
|
||||
NetNet::IMPLICIT_REG, pins);
|
||||
|
||||
pins = 0;
|
||||
for (unsigned idx = nets.count() ; idx > 0 ; idx -= 1) {
|
||||
NetNet*cur = nets[idx-1];
|
||||
for (unsigned pin = 0; pin < cur->pin_count(); pin += 1) {
|
||||
connect(osig->pin(pins), cur->pin(pin));
|
||||
pins += 1;
|
||||
}
|
||||
}
|
||||
|
||||
osig->local_flag(true);
|
||||
return osig;
|
||||
}
|
||||
|
||||
NetNet* PEIdent::elaborate_anet(Design*des, NetScope*scope) const
|
||||
{
|
||||
NetNet*sig = des->find_signal(scope, text_);
|
||||
|
||||
if (sig == 0) {
|
||||
if (NetMemory*mem = des->find_memory(scope, text_)) {
|
||||
cerr << get_line() << ": error: memories not allowed "
|
||||
<< "on left side of procedural continuous "
|
||||
<< "asignment." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
cerr << get_line() << ": error: reg ``" << text_ << "'' "
|
||||
<< "is undefined in this scope." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (sig->type()) {
|
||||
case NetNet::REG:
|
||||
case NetNet::IMPLICIT_REG:
|
||||
break;
|
||||
|
||||
default:
|
||||
cerr << get_line() << ": error: " << text_ << " is not "
|
||||
<< "a reg in this context." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(sig);
|
||||
|
||||
if (msb_ || lsb_) {
|
||||
|
||||
cerr << get_line() << ": error: bit/part selects not allowed "
|
||||
<< "on left side of procedural continuous asignment."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return sig;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: elab_anet.cc,v $
|
||||
* Revision 1.3 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.2 2001/01/06 02:29:36 steve
|
||||
* Support arrays of integers.
|
||||
*
|
||||
* Revision 1.1 2000/12/06 06:31:09 steve
|
||||
* Check lvalue of procedural continuous assign (PR#29)
|
||||
*
|
||||
*/
|
||||
|
||||
+403
-91
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1999-2000 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,24 +16,37 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: elab_expr.cc,v 1.12 1999/11/30 04:54:01 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: elab_expr.cc,v 1.42 2001/07/29 22:22:40 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
|
||||
# include "pform.h"
|
||||
# include "netlist.h"
|
||||
# include "netmisc.h"
|
||||
# include "util.h"
|
||||
|
||||
NetExpr* PExpr::elaborate_expr(Design*des, NetScope*) const
|
||||
{
|
||||
cerr << get_line() << ": internal error: I do not know how to elaborate"
|
||||
<< " expression. " << endl;
|
||||
cerr << get_line() << ": : Expression is: " << *this
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Elaborate binary expressions. This involves elaborating the left
|
||||
* and right sides, and creating one of a variety of different NetExpr
|
||||
* types.
|
||||
*/
|
||||
NetExpr* PEBinary::elaborate_expr(Design*des, const string&path) const
|
||||
NetEBinary* PEBinary::elaborate_expr(Design*des, NetScope*scope) const
|
||||
{
|
||||
bool flag;
|
||||
NetExpr*lp = left_->elaborate_expr(des, path);
|
||||
NetExpr*rp = right_->elaborate_expr(des, path);
|
||||
NetExpr*lp = left_->elaborate_expr(des, scope);
|
||||
NetExpr*rp = right_->elaborate_expr(des, scope);
|
||||
if ((lp == 0) || (rp == 0)) {
|
||||
delete lp;
|
||||
delete rp;
|
||||
@@ -55,7 +68,21 @@ NetExpr* PEBinary::elaborate_expr(Design*des, const string&path) const
|
||||
}
|
||||
}
|
||||
|
||||
NetEBinary*tmp = elaborate_expr_base_(des, lp, rp);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is common elaboration of the operator. It presumes that the
|
||||
* operands are elaborated as necessary, and all I need to do is make
|
||||
* the correct NetEBinary object and connect the parameters.
|
||||
*/
|
||||
NetEBinary* PEBinary::elaborate_expr_base_(Design*des,
|
||||
NetExpr*lp, NetExpr*rp) const
|
||||
{
|
||||
bool flag;
|
||||
NetEBinary*tmp;
|
||||
|
||||
switch (op_) {
|
||||
default:
|
||||
tmp = new NetEBinary(op_, lp, rp);
|
||||
@@ -68,6 +95,17 @@ NetExpr* PEBinary::elaborate_expr(Design*des, const string&path) const
|
||||
tmp->set_line(*this);
|
||||
break;
|
||||
|
||||
case '*':
|
||||
tmp = new NetEBMult(op_, lp, rp);
|
||||
tmp->set_line(*this);
|
||||
break;
|
||||
|
||||
case '/':
|
||||
case '%':
|
||||
tmp = new NetEBDiv(op_, lp, rp);
|
||||
tmp->set_line(*this);
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
case 'r':
|
||||
tmp = new NetEBShift(op_, lp, rp);
|
||||
@@ -111,38 +149,150 @@ NetExpr* PEBinary::elaborate_expr(Design*des, const string&path) const
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetESFunc* PECallFunction::elaborate_sfunc_(Design*des, const string&path) const
|
||||
/*
|
||||
* Given a call to a system function, generate the proper expression
|
||||
* nodes to represent the call in the netlist. Since we don't support
|
||||
* size_tf functions, make assumptions about widths based on some
|
||||
* known function names.
|
||||
*/
|
||||
NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope) const
|
||||
{
|
||||
cerr << get_line() << ": sorry: system functions not supported."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
unsigned wid = 32;
|
||||
|
||||
if (name_ == "$time")
|
||||
wid = 64;
|
||||
|
||||
|
||||
/* How many parameters are there? The Verilog language allows
|
||||
empty parameters in certain contexts, so the parser will
|
||||
allow things like func(1,,3). It will also cause func() to
|
||||
be interpreted as a single empty parameter.
|
||||
|
||||
Functions cannot really take empty parameters, but the
|
||||
case ``func()'' is the same as no parmaters at all. So
|
||||
catch that special case here. */
|
||||
unsigned nparms = parms_.count();
|
||||
if ((nparms == 1) && (parms_[0] == 0))
|
||||
nparms = 0;
|
||||
|
||||
NetESFunc*fun = new NetESFunc(name_, wid, nparms);
|
||||
|
||||
/* Now run through the expected parameters. If we find that
|
||||
there are missing parameters, print an error message.
|
||||
|
||||
While we're at it, try to evaluate the function parameter
|
||||
expression as much as possible, and use the reduced
|
||||
expression if one is created. */
|
||||
|
||||
unsigned missing_parms = 0;
|
||||
for (unsigned idx = 0 ; idx < nparms ; idx += 1) {
|
||||
PExpr*expr = parms_[idx];
|
||||
if (expr) {
|
||||
NetExpr*tmp1 = expr->elaborate_expr(des, scope);
|
||||
if (NetExpr*tmp2 = tmp1->eval_tree()) {
|
||||
delete tmp1;
|
||||
fun->parm(idx, tmp2);
|
||||
} else {
|
||||
fun->parm(idx, tmp1);
|
||||
}
|
||||
|
||||
} else {
|
||||
missing_parms += 1;
|
||||
fun->parm(idx, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (missing_parms > 0) {
|
||||
cerr << get_line() << ": error: The function " << name_
|
||||
<< " has been called with empty parameters." << endl;
|
||||
cerr << get_line() << ": : Verilog doesn't allow "
|
||||
<< "passing empty parameters to functions." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
return fun;
|
||||
}
|
||||
|
||||
NetExpr* PECallFunction::elaborate_expr(Design*des, const string&path) const
|
||||
NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope) const
|
||||
{
|
||||
if (name_[0] == '$')
|
||||
return elaborate_sfunc_(des, path);
|
||||
return elaborate_sfunc_(des, scope);
|
||||
|
||||
string myname = path+"."+name_;
|
||||
NetFuncDef*def = des->find_function(path, name_);
|
||||
NetFuncDef*def = des->find_function(scope, name_);
|
||||
if (def == 0) {
|
||||
cerr << get_line() << ": error: No function " << name_ <<
|
||||
" in this context (" << path << ")." << endl;
|
||||
" in this context (" << scope->name() << ")." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
assert(def);
|
||||
svector<NetExpr*> parms (parms_.count());
|
||||
|
||||
for (unsigned idx = 0 ; idx < parms.count() ; idx += 1) {
|
||||
NetExpr*tmp = parms_[idx]->elaborate_expr(des, myname);
|
||||
parms[idx] = tmp;
|
||||
NetScope*dscope = des->find_scope(def->name());
|
||||
assert(dscope);
|
||||
|
||||
/* How many parameters have I got? Normally the size of the
|
||||
list is correct, but there is the special case of a list of
|
||||
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();
|
||||
if ((parms_count == 1) && (parms_[0] == 0))
|
||||
parms_count = 0;
|
||||
|
||||
if (dscope->type() != NetScope::FUNC) {
|
||||
cerr << get_line() << ": error: Attempt to call scope "
|
||||
<< dscope->name() << " as a function." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Look for the return value signal for the called function in
|
||||
the context of the function definition, not my context. */
|
||||
NetNet*res = des->find_signal(def->name(), name_);
|
||||
if ((parms_count+1) != dscope->func_def()->port_count()) {
|
||||
cerr << get_line() << ": error: Function " << dscope->name()
|
||||
<< " expects " << (dscope->func_def()->port_count()-1)
|
||||
<< " parameters, you passed " << parms_count << "."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
svector<NetExpr*> parms (parms_count);
|
||||
|
||||
/* Elaborate the input expressions for the function. This is
|
||||
done in the scope of the function call, and not the scope
|
||||
of the function being called. The scope of the called
|
||||
function is elaborated when the definition is elaborated. */
|
||||
|
||||
unsigned missing_parms = 0;
|
||||
for (unsigned idx = 0 ; idx < parms.count() ; idx += 1) {
|
||||
PExpr*tmp = parms_[idx];
|
||||
if (tmp) {
|
||||
parms[idx] = tmp->elaborate_expr(des, scope);
|
||||
|
||||
} else {
|
||||
missing_parms += 1;
|
||||
parms[idx] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (missing_parms > 0) {
|
||||
cerr << get_line() << ": error: The function " << name_
|
||||
<< " has been called with empty parameters." << endl;
|
||||
cerr << get_line() << ": : Verilog doesn't allow "
|
||||
<< "passing empty parameters to functions." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
|
||||
/* Look for the return value signal for the called
|
||||
function. This return value is a magic signal in the scope
|
||||
of the function, that has the name of the function. The
|
||||
function code assigns to this signal to return a value.
|
||||
|
||||
dscope, in this case, is the scope of the function, so the
|
||||
return value is the name within that scope. */
|
||||
|
||||
string rname = name_;
|
||||
NetNet*res = des->find_signal(dscope, parse_last_name(rname));
|
||||
if (res == 0) {
|
||||
cerr << get_line() << ": internal error: Unable to locate "
|
||||
"function return value for " << name_ << " in " <<
|
||||
@@ -154,27 +304,81 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, const string&path) const
|
||||
assert(res);
|
||||
NetESignal*eres = new NetESignal(res);
|
||||
assert(eres);
|
||||
NetEUFunc*func = new NetEUFunc(def, eres, parms);
|
||||
NetEUFunc*func = new NetEUFunc(dscope, eres, parms);
|
||||
return func;
|
||||
}
|
||||
|
||||
|
||||
NetExpr* PEIdent::elaborate_expr(Design*des, const string&path) const
|
||||
NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope) const
|
||||
{
|
||||
// System identifiers show up in the netlist as identifiers.
|
||||
if (text_[0] == '$')
|
||||
return new NetEIdent(text_, 64);
|
||||
unsigned repeat = 1;
|
||||
|
||||
string name = path+"."+text_;
|
||||
/* If there is a repeat expression, then evaluate the constant
|
||||
value and set the repeat count. */
|
||||
if (repeat_) {
|
||||
NetExpr*tmp = elab_and_eval(des, scope, repeat_);
|
||||
assert(tmp);
|
||||
NetEConst*rep = dynamic_cast<NetEConst*>(tmp);
|
||||
|
||||
if (rep == 0) {
|
||||
cerr << get_line() << ": error: "
|
||||
"concatenation repeat expression cannot be evaluated."
|
||||
<< endl;
|
||||
cerr << get_line() << ": : The expression is: "
|
||||
<< *tmp << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
repeat = rep->value().as_ulong();
|
||||
}
|
||||
|
||||
/* Make the empty concat expression. */
|
||||
NetEConcat*tmp = new NetEConcat(parms_.count(), repeat);
|
||||
tmp->set_line(*this);
|
||||
|
||||
/* Elaborate all the parameters and attach them to the concat node. */
|
||||
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) {
|
||||
assert(parms_[idx]);
|
||||
NetExpr*ex = parms_[idx]->elaborate_expr(des, scope);
|
||||
if (ex == 0) continue;
|
||||
|
||||
ex->set_line(*parms_[idx]);
|
||||
|
||||
if (! ex->has_width()) {
|
||||
cerr << ex->get_line() << ": error: operand of "
|
||||
<< "concatenation has indefinite width: "
|
||||
<< *ex << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
tmp->set(idx, ex);
|
||||
}
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetExpr* PEFNumber::elaborate_expr(Design*des, NetScope*scope) const
|
||||
{
|
||||
long val = value_->as_long();
|
||||
return new NetEConst(verinum(val));
|
||||
}
|
||||
|
||||
NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope) const
|
||||
{
|
||||
assert(text_[0] != '$');
|
||||
|
||||
//string name = path+"."+text_;
|
||||
assert(scope);
|
||||
|
||||
// If the identifier name is a parameter name, then return
|
||||
// a reference to the parameter expression.
|
||||
if (const NetExpr*ex = des->find_parameter(path, text_)) {
|
||||
if (const NetExpr*ex = des->find_parameter(scope, text_)) {
|
||||
NetExpr*tmp;
|
||||
if (dynamic_cast<const NetExpr*>(ex))
|
||||
tmp = ex->dup_expr();
|
||||
else
|
||||
tmp = new NetEParam(des, path, text_);
|
||||
tmp = new NetEParam(des, scope, text_);
|
||||
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
@@ -182,15 +386,16 @@ NetExpr* PEIdent::elaborate_expr(Design*des, const string&path) const
|
||||
|
||||
// If the identifier names a signal (a register or wire)
|
||||
// then create a NetESignal node to handle it.
|
||||
if (NetNet*net = des->find_signal(path, text_)) {
|
||||
if (NetNet*net = des->find_signal(scope, text_)) {
|
||||
|
||||
// If this is a part select of a signal, then make a new
|
||||
// temporary signal that is connected to just the
|
||||
// selected bits.
|
||||
// selected bits. The lsb_ and msb_ expressions are from
|
||||
// the foo[msb:lsb] expression in the original.
|
||||
if (lsb_) {
|
||||
assert(msb_);
|
||||
verinum*lsn = lsb_->eval_const(des, path);
|
||||
verinum*msn = msb_->eval_const(des, path);
|
||||
verinum*lsn = lsb_->eval_const(des, scope->name());
|
||||
verinum*msn = msb_->eval_const(des, scope->name());
|
||||
if ((lsn == 0) || (msn == 0)) {
|
||||
cerr << get_line() << ": error: "
|
||||
"Part select expresions must be "
|
||||
@@ -201,24 +406,53 @@ NetExpr* PEIdent::elaborate_expr(Design*des, const string&path) const
|
||||
|
||||
assert(lsn);
|
||||
assert(msn);
|
||||
unsigned long lsv = lsn->as_ulong();
|
||||
unsigned long msv = msn->as_ulong();
|
||||
|
||||
/* The indices of part selects are signed
|
||||
integers, so allow negative values. However,
|
||||
the width that they represent is
|
||||
unsigned. Remember that any order is possible,
|
||||
i.e. [1:0], [-4,6], etc. */
|
||||
|
||||
long lsv = lsn->as_long();
|
||||
long msv = msn->as_long();
|
||||
unsigned long wid = 1 + ((msv>lsv)? (msv-lsv) : (lsv-msv));
|
||||
if (wid > net->pin_count()) {
|
||||
cerr << get_line() << ": error: part select ["
|
||||
<< msv << ":" << lsv << "] out of range."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
delete lsn;
|
||||
delete msn;
|
||||
return 0;
|
||||
}
|
||||
assert(wid <= net->pin_count());
|
||||
assert(net->sb_to_idx(msv) >= net->sb_to_idx(lsv));
|
||||
|
||||
string tname = des->local_symbol(path);
|
||||
NetTmp*tsig = new NetTmp(tname, wid);
|
||||
if (net->sb_to_idx(msv) < net->sb_to_idx(lsv)) {
|
||||
cerr << get_line() << ": error: part select ["
|
||||
<< msv << ":" << lsv << "] out of order."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
delete lsn;
|
||||
delete msn;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Connect the pins from the lsb up to the msb.
|
||||
unsigned off = net->sb_to_idx(lsv);
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1)
|
||||
connect(tsig->pin(idx), net->pin(idx+off));
|
||||
|
||||
NetESignal*tmp = new NetESignal(tsig);
|
||||
if (net->sb_to_idx(msv) >= net->pin_count()) {
|
||||
cerr << get_line() << ": error: part select ["
|
||||
<< msv << ":" << lsv << "] out of range."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
delete lsn;
|
||||
delete msn;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetESignal*tmp = new NetESignal(net,
|
||||
net->sb_to_idx(msv),
|
||||
net->sb_to_idx(lsv));
|
||||
tmp->set_line(*this);
|
||||
|
||||
des->add_signal(tsig);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
@@ -226,17 +460,22 @@ NetExpr* PEIdent::elaborate_expr(Design*des, const string&path) const
|
||||
// to the part select, so that I save the effort of
|
||||
// making a mux part in the netlist.
|
||||
verinum*msn;
|
||||
if (msb_ && (msn = msb_->eval_const(des, path))) {
|
||||
if (msb_ && (msn = msb_->eval_const(des, scope->name()))) {
|
||||
assert(idx_ == 0);
|
||||
unsigned long msv = msn->as_ulong();
|
||||
unsigned idx = net->sb_to_idx(msv);
|
||||
|
||||
string tname = des->local_symbol(path);
|
||||
NetTmp*tsig = new NetTmp(tname);
|
||||
connect(tsig->pin(0), net->pin(msv));
|
||||
NetESignal*tmp = new NetESignal(tsig);
|
||||
if (idx >= net->pin_count()) {
|
||||
cerr << get_line() << ": internal error: "
|
||||
<< "bit " << msv << " out of range of net "
|
||||
<< net->name() << "[" << net->msb()
|
||||
<< ":" << net->lsb() << "]." << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetESignal*tmp = new NetESignal(net, idx, idx);
|
||||
tmp->set_line(*this);
|
||||
|
||||
des->add_signal(tsig);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
@@ -246,8 +485,8 @@ NetExpr* PEIdent::elaborate_expr(Design*des, const string&path) const
|
||||
// Non-constant bit select? punt and make a subsignal
|
||||
// device to mux the bit in the net.
|
||||
if (msb_) {
|
||||
NetExpr*ex = msb_->elaborate_expr(des, path);
|
||||
NetESubSignal*ss = new NetESubSignal(node, ex);
|
||||
NetExpr*ex = msb_->elaborate_expr(des, scope);
|
||||
NetEBitSel*ss = new NetEBitSel(node, ex);
|
||||
ss->set_line(*this);
|
||||
return ss;
|
||||
}
|
||||
@@ -261,17 +500,23 @@ NetExpr* PEIdent::elaborate_expr(Design*des, const string&path) const
|
||||
// If the identifier names a memory, then this is a
|
||||
// memory reference and I must generate a NetEMemory
|
||||
// object to handle it.
|
||||
if (NetMemory*mem = des->find_memory(path, text_)) {
|
||||
if (NetMemory*mem = des->find_memory(scope, text_)) {
|
||||
if (msb_ == 0) {
|
||||
cerr << get_line() << ": error: Memory ``" << name <<
|
||||
"'' referenced without an index expression." << endl;
|
||||
NetEMemory*node = new NetEMemory(mem);
|
||||
node->set_line(*this);
|
||||
return node;
|
||||
}
|
||||
assert(msb_ != 0);
|
||||
if (lsb_) {
|
||||
cerr << get_line() << ": error: part select of a memory: "
|
||||
<< mem->name() << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
assert(msb_ != 0);
|
||||
|
||||
assert(lsb_ == 0);
|
||||
assert(idx_ == 0);
|
||||
NetExpr*i = msb_->elaborate_expr(des, path);
|
||||
NetExpr*i = msb_->elaborate_expr(des, scope);
|
||||
if (msb_ && i == 0) {
|
||||
cerr << get_line() << ": error: Unable to exaborate "
|
||||
"index expression `" << *msb_ << "'" << endl;
|
||||
@@ -284,7 +529,18 @@ NetExpr* PEIdent::elaborate_expr(Design*des, const string&path) const
|
||||
return node;
|
||||
}
|
||||
|
||||
// Finally, if this is a scope name, then return that.
|
||||
// Finally, if this is a scope name, then return that. Look
|
||||
// first to see if this is a name of a local scope. Failing
|
||||
// that, search globally for a heirarchical name.
|
||||
if (NetScope*nsc = scope->child(text_)) {
|
||||
NetEScope*tmp = new NetEScope(nsc);
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
// NOTE: This search pretty much assumes that text_ is a
|
||||
// complete hierarchical name, since there is no mention of
|
||||
// the current scope in the call to find_scope.
|
||||
if (NetScope*nsc = des->find_scope(text_)) {
|
||||
NetEScope*tmp = new NetEScope(nsc);
|
||||
tmp->set_line(*this);
|
||||
@@ -293,33 +549,48 @@ NetExpr* PEIdent::elaborate_expr(Design*des, const string&path) const
|
||||
|
||||
// I cannot interpret this identifier. Error message.
|
||||
cerr << get_line() << ": error: Unable to bind wire/reg/memory "
|
||||
"`" << path << "." << text_ << "'" << endl;
|
||||
"`" << text_ << "' in `" << scope->name() << "'" << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetEConst* PENumber::elaborate_expr(Design*des, NetScope*) const
|
||||
{
|
||||
assert(value_);
|
||||
NetEConst*tmp = new NetEConst(*value_);
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetEConst* PEString::elaborate_expr(Design*des, NetScope*) const
|
||||
{
|
||||
NetEConst*tmp = new NetEConst(value());
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Elaborate the Ternary operator. I know that the expressions were
|
||||
* parsed so I can presume that they exist, and call elaboration
|
||||
* methods. If any elaboration fails, then give up and return 0.
|
||||
*/
|
||||
NetExpr*PETernary::elaborate_expr(Design*des, const string&path) const
|
||||
NetETernary*PETernary::elaborate_expr(Design*des, NetScope*scope) const
|
||||
{
|
||||
assert(expr_);
|
||||
assert(tru_);
|
||||
assert(fal_);
|
||||
|
||||
NetExpr*con = expr_->elaborate_expr(des, path);
|
||||
NetExpr*con = expr_->elaborate_expr(des, scope);
|
||||
if (con == 0)
|
||||
return 0;
|
||||
|
||||
NetExpr*tru = tru_->elaborate_expr(des, path);
|
||||
NetExpr*tru = tru_->elaborate_expr(des, scope);
|
||||
if (tru == 0) {
|
||||
delete con;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetExpr*fal = fal_->elaborate_expr(des, path);
|
||||
NetExpr*fal = fal_->elaborate_expr(des, scope);
|
||||
if (fal == 0) {
|
||||
delete con;
|
||||
delete tru;
|
||||
@@ -330,44 +601,85 @@ NetExpr*PETernary::elaborate_expr(Design*des, const string&path) const
|
||||
return res;
|
||||
}
|
||||
|
||||
NetEUnary* PEUnary::elaborate_expr(Design*des, NetScope*scope) const
|
||||
{
|
||||
NetExpr*ip = expr_->elaborate_expr(des, scope);
|
||||
if (ip == 0) return 0;
|
||||
|
||||
/* Should we evaluate expressions ahead of time,
|
||||
* just like in PEBinary::elaborate_expr() ?
|
||||
*/
|
||||
|
||||
NetEUnary*tmp;
|
||||
switch (op_) {
|
||||
default:
|
||||
tmp = new NetEUnary(op_, ip);
|
||||
tmp->set_line(*this);
|
||||
break;
|
||||
case '!': // Logical NOT
|
||||
case '&': // Reduction AND
|
||||
case '|': // Reduction OR
|
||||
case '^': // Reduction XOR
|
||||
case 'A': // Reduction NAND (~&)
|
||||
case 'N': // Reduction NOR (~|)
|
||||
case 'X': // Reduction NXOR (~^)
|
||||
tmp = new NetEUReduce(op_, ip);
|
||||
tmp->set_line(*this);
|
||||
break;
|
||||
case '~':
|
||||
tmp = new NetEUBits(op_, ip);
|
||||
tmp->set_line(*this);
|
||||
break;
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: elab_expr.cc,v $
|
||||
* Revision 1.12 1999/11/30 04:54:01 steve
|
||||
* Match scope names as last resort.
|
||||
* Revision 1.42 2001/07/29 22:22:40 steve
|
||||
* support local reference to scope in expressions.
|
||||
*
|
||||
* Revision 1.11 1999/11/28 23:42:02 steve
|
||||
* NetESignal object no longer need to be NetNode
|
||||
* objects. Let them keep a pointer to NetNet objects.
|
||||
* Revision 1.41 2001/07/27 04:51:44 steve
|
||||
* Handle part select expressions as variants of
|
||||
* NetESignal/IVL_EX_SIGNAL objects, instead of
|
||||
* creating new and useless temporary signals.
|
||||
*
|
||||
* Revision 1.10 1999/11/27 19:07:57 steve
|
||||
* Support the creation of scopes.
|
||||
* Revision 1.40 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.9 1999/11/21 17:35:37 steve
|
||||
* Memory name lookup handles scopes.
|
||||
* Revision 1.39 2001/06/30 21:28:35 steve
|
||||
* Detect parameter mismatches.
|
||||
*
|
||||
* Revision 1.8 1999/11/10 02:52:24 steve
|
||||
* Create the vpiMemory handle type.
|
||||
* Revision 1.38 2001/06/23 19:53:03 steve
|
||||
* Look up functor return register with tail of name.
|
||||
*
|
||||
* Revision 1.7 1999/10/18 00:02:21 steve
|
||||
* Catch unindexed memory reference.
|
||||
* Revision 1.37 2001/04/06 02:28:02 steve
|
||||
* Generate vvp code for functions with ports.
|
||||
*
|
||||
* Revision 1.6 1999/09/30 02:43:02 steve
|
||||
* Elaborate ~^ and ~| operators.
|
||||
* Revision 1.36 2001/02/10 20:29:39 steve
|
||||
* In the context of range declarations, use elab_and_eval instead
|
||||
* of the less robust eval_const methods.
|
||||
*
|
||||
* Revision 1.5 1999/09/30 00:48:49 steve
|
||||
* Cope with errors during ternary operator elaboration.
|
||||
* Revision 1.35 2001/02/09 05:44:23 steve
|
||||
* support evaluation of constant < in expressions.
|
||||
*
|
||||
* Revision 1.4 1999/09/29 22:57:10 steve
|
||||
* Move code to elab_expr.cc
|
||||
* Revision 1.34 2001/01/14 23:04:55 steve
|
||||
* Generalize the evaluation of floating point delays, and
|
||||
* get it working with delay assignment statements.
|
||||
*
|
||||
* Revision 1.3 1999/09/25 02:57:30 steve
|
||||
* Parse system function calls.
|
||||
* Allow parameters to be referenced by hierarchical name.
|
||||
*
|
||||
* Revision 1.2 1999/09/21 00:13:40 steve
|
||||
* Support parameters that reference other paramters.
|
||||
* Revision 1.33 2001/01/13 22:20:08 steve
|
||||
* Parse parameters within nested scopes.
|
||||
*
|
||||
* Revision 1.1 1999/09/20 02:21:10 steve
|
||||
* Elaborate parameters in phases.
|
||||
* Revision 1.32 2001/01/02 04:21:13 steve
|
||||
* Support a bunch of unary operators in parameter expressions.
|
||||
*
|
||||
* Revision 1.31 2000/12/10 22:01:35 steve
|
||||
* Support decimal constants in behavioral delays.
|
||||
*
|
||||
* Revision 1.30 2000/11/29 05:24:00 steve
|
||||
* synthesis for unary reduction ! and N operators.
|
||||
*/
|
||||
|
||||
|
||||
+330
@@ -0,0 +1,330 @@
|
||||
/*
|
||||
* Copyright (c) 2000 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
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: elab_lval.cc,v 1.14 2001/08/25 23:50:02 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# include "PExpr.h"
|
||||
# include "netlist.h"
|
||||
|
||||
# include <iostream>
|
||||
|
||||
/*
|
||||
* These methods generate a NetAssign_ object for the l-value of the
|
||||
* assignemnt. This is common code for the = and <= statements.
|
||||
*
|
||||
* What gets generated depends on the structure of the l-value. If the
|
||||
* l-value is a simple name (i.e. foo <= <value>) the the NetAssign_
|
||||
* is created the width of the foo reg and connected to all the
|
||||
* bits.
|
||||
*
|
||||
* If there is a part select (i.e. foo[3:1] <= <value>) the NetAssign_
|
||||
* is made only as wide as it needs to be (3 bits in this example) and
|
||||
* connected to the correct bits of foo. A constant bit select is a
|
||||
* special case of the part select.
|
||||
*
|
||||
* If the bit-select is non-constant (i.e. foo[<expr>] = <value>) the
|
||||
* NetAssign_ is made wide enough to connect to all the bits of foo,
|
||||
* then the mux expression is elaborated and attached to the
|
||||
* NetAssign_ node as a b_mux value. The target must interpret the
|
||||
* presense of a bmux value as taking a single bit and assigning it to
|
||||
* the bit selected by the bmux expression.
|
||||
*
|
||||
* If the l-value expression is non-trivial, but can be fully
|
||||
* evaluated at compile time (meaning any bit selects are constant)
|
||||
* then elaboration will make a single NetAssign_ that connects to a
|
||||
* synthetic reg that in turn connects to all the proper pins of the
|
||||
* l-value.
|
||||
*
|
||||
* This last case can turn up in statements like: {a, b[1]} = c;
|
||||
* rather then create a NetAssign_ for each item in the contatenation,
|
||||
* elaboration makes a single NetAssign_ and connects it up properly.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* The default interpretation of an l-value to a procedural assignment
|
||||
* is to try to make a net elaboration, and see if the result is
|
||||
* suitable for assignment.
|
||||
*/
|
||||
NetAssign_* PExpr::elaborate_lval(Design*des, NetScope*scope) const
|
||||
{
|
||||
NetNet*ll = elaborate_net(des, scope->name(), 0, 0, 0, 0);
|
||||
if (ll == 0) {
|
||||
cerr << get_line() << ": Assignment l-value too complex."
|
||||
<< endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetAssign_*lv = new NetAssign_(ll);
|
||||
return lv;
|
||||
}
|
||||
|
||||
/*
|
||||
* Concatenation expressions can appear as l-values. Handle them here.
|
||||
*
|
||||
* If adjacent l-values in the concatenation are not bit selects, then
|
||||
* merge them into a single NetAssign_ object. This can happen is code
|
||||
* like ``{ ...a, b, ...}''. As long as "a" and "b" do not have bit
|
||||
* selects (or the bit selects are constant) we can merge the
|
||||
* NetAssign_ objects.
|
||||
*
|
||||
* Be careful to get the bit order right. In the expression ``{a, b}''
|
||||
* a is the MSB and b the LSB. Connect the LSB to the low pins of the
|
||||
* NetAssign_ object.
|
||||
*/
|
||||
NetAssign_* PEConcat::elaborate_lval(Design*des, NetScope*scope) const
|
||||
{
|
||||
if (repeat_) {
|
||||
cerr << get_line() << ": error: Repeat concatenations make "
|
||||
"no sense in l-value expressions. I refuse." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetAssign_*res = 0;
|
||||
|
||||
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) {
|
||||
NetAssign_*tmp = parms_[idx]->elaborate_lval(des, scope);
|
||||
|
||||
/* If the l-value doesn't elaborate, the error was
|
||||
already detected and printed. We just skip it and let
|
||||
the compiler catch more errors. */
|
||||
if (tmp == 0)
|
||||
continue;
|
||||
|
||||
assert(tmp);
|
||||
|
||||
|
||||
/* Link the new l-value to the previous one. */
|
||||
|
||||
NetAssign_*last = tmp;
|
||||
while (last->more)
|
||||
last = last->more;
|
||||
|
||||
last->more = res;
|
||||
res = tmp;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle the ident as an l-value. This includes bit and part selects
|
||||
* of that ident.
|
||||
*/
|
||||
NetAssign_* PEIdent::elaborate_lval(Design*des, NetScope*scope) const
|
||||
{
|
||||
/* Get the signal referenced by the identifier, and make sure
|
||||
it is a register. (Wires are not allows in this context. */
|
||||
NetNet*reg = des->find_signal(scope, name());
|
||||
|
||||
if (reg == 0) {
|
||||
NetMemory*mem = des->find_memory(scope, name());
|
||||
if (mem != 0) {
|
||||
cerr << get_line() << ": sorry: I cannot handle "
|
||||
<< "memories in this l-value context." << endl;
|
||||
} else {
|
||||
cerr << get_line() << ": error: Could not find variable ``"
|
||||
<< name() << "'' in ``" << scope->name() <<
|
||||
"''" << endl;
|
||||
}
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
assert(reg);
|
||||
|
||||
if (reg->type() != NetNet::REG) {
|
||||
cerr << get_line() << ": error: " << name() <<
|
||||
" is not a reg/integer/time in " << scope->name() <<
|
||||
"." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
long msb, lsb;
|
||||
NetExpr*mux;
|
||||
|
||||
if (msb_ && lsb_) {
|
||||
/* This handles part selects. In this case, there are
|
||||
two bit select expressions, and both must be
|
||||
constant. Evaluate them and pass the results back to
|
||||
the caller. */
|
||||
verinum*vl = lsb_->eval_const(des, scope->name());
|
||||
if (vl == 0) {
|
||||
cerr << lsb_->get_line() << ": error: "
|
||||
"Part select expressions must be constant: "
|
||||
<< *lsb_;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
verinum*vm = msb_->eval_const(des, scope->name());
|
||||
if (vl == 0) {
|
||||
cerr << msb_->get_line() << ": error: "
|
||||
"Part select expressions must be constant: "
|
||||
<< *msb_;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
msb = vm->as_long();
|
||||
lsb = vl->as_long();
|
||||
mux = 0;
|
||||
|
||||
} else if (msb_) {
|
||||
|
||||
/* 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. */
|
||||
assert(lsb_ == 0);
|
||||
verinum*v = msb_->eval_const(des, scope->name());
|
||||
if (v == 0) {
|
||||
NetExpr*m = msb_->elaborate_expr(des, scope);
|
||||
assert(m);
|
||||
msb = 0;
|
||||
lsb = 0;
|
||||
mux = m;
|
||||
|
||||
} else {
|
||||
|
||||
msb = v->as_long();
|
||||
lsb = v->as_long();
|
||||
mux = 0;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
/* No select expressions, so presume a part select the
|
||||
width of the register. */
|
||||
|
||||
assert(msb_ == 0);
|
||||
assert(lsb_ == 0);
|
||||
msb = reg->msb();
|
||||
lsb = reg->lsb();
|
||||
mux = 0;
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
|
||||
lv->set_bmux(mux);
|
||||
|
||||
} 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_line() << ": 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->pin_count()) {
|
||||
cerr << get_line() << ": 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(loff, wid);
|
||||
|
||||
assert(moff < reg->pin_count());
|
||||
}
|
||||
|
||||
|
||||
return lv;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: elab_lval.cc,v $
|
||||
* Revision 1.14 2001/08/25 23:50:02 steve
|
||||
* Change the NetAssign_ class to refer to the signal
|
||||
* instead of link into the netlist. This is faster
|
||||
* and uses less space. Make the NetAssignNB carry
|
||||
* the delays instead of the NetAssign_ lval objects.
|
||||
*
|
||||
* Change the vvp code generator to support multiple
|
||||
* l-values, i.e. concatenations of part selects.
|
||||
*
|
||||
* Revision 1.13 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.12 2001/02/09 03:16:48 steve
|
||||
* Report bit/part select out of range errors. (PR#133)
|
||||
*
|
||||
* Revision 1.11 2001/01/10 03:13:23 steve
|
||||
* Build task outputs as lval instead of nets. (PR#98)
|
||||
*
|
||||
* Revision 1.10 2001/01/06 06:31:58 steve
|
||||
* declaration initialization for time variables.
|
||||
*
|
||||
* Revision 1.9 2001/01/06 02:29:36 steve
|
||||
* Support arrays of integers.
|
||||
*
|
||||
* Revision 1.8 2000/12/12 06:14:51 steve
|
||||
* sorry for concatenated memories in l-values. (PR#76)
|
||||
*
|
||||
* Revision 1.7 2000/12/01 02:55:37 steve
|
||||
* Detect part select errors on l-values.
|
||||
*
|
||||
* Revision 1.6 2000/10/31 17:49:02 steve
|
||||
* Support time variables.
|
||||
*
|
||||
* Revision 1.5 2000/10/26 17:09:46 steve
|
||||
* Fix handling of errors in behavioral lvalues. (PR#28)
|
||||
*
|
||||
* Revision 1.4 2000/09/10 15:43:59 steve
|
||||
* Some error checking.
|
||||
*
|
||||
* Revision 1.3 2000/09/10 03:59:59 steve
|
||||
* Agressively merge NetAssign_ within concatenations.
|
||||
*
|
||||
* Revision 1.2 2000/09/10 02:18:16 steve
|
||||
* elaborate complex l-values
|
||||
*
|
||||
* Revision 1.1 2000/09/09 15:21:26 steve
|
||||
* move lval elaboration to PExpr virtual methods.
|
||||
*
|
||||
*/
|
||||
|
||||
+1491
-269
File diff suppressed because it is too large
Load Diff
+242
@@ -0,0 +1,242 @@
|
||||
/*
|
||||
* Copyright (c) 2000 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
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: elab_pexpr.cc,v 1.9 2001/07/25 03:10:49 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# include "PExpr.h"
|
||||
# include "util.h"
|
||||
|
||||
# include <iostream>
|
||||
|
||||
NetExpr*PExpr::elaborate_pexpr(Design*des, NetScope*sc) const
|
||||
{
|
||||
cerr << get_line() << ": error: invalid parameter expression: "
|
||||
<< *this << endl;
|
||||
des->errors += 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Binary operators have sub-expressions that must be elaborated as
|
||||
* parameter expressions. If either of them fail, then give up. Once
|
||||
* they are taken care of, make the base object just as in any other
|
||||
* expression.
|
||||
*/
|
||||
NetExpr*PEBinary::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;
|
||||
}
|
||||
|
||||
NetEBinary*tmp = elaborate_expr_base_(des, lp, rp);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Event though parameters are not generally sized, parameter
|
||||
* expressions can include concatenation expressions. This requires
|
||||
* that the subexpressions all have well-defined size (in spite of
|
||||
* being in a parameter expression) in order to get a defined
|
||||
* value. The sub-expressions themsilves must also be value parameter
|
||||
* expressions.
|
||||
*/
|
||||
NetEConcat* PEConcat::elaborate_pexpr(Design*des, NetScope*scope) const
|
||||
{
|
||||
unsigned repeat = 1;
|
||||
|
||||
/* If there is a repeat expression, then evaluate the constant
|
||||
value and set the repeat count.
|
||||
|
||||
XXXX Potential bug XXX In principle, the repeat expression
|
||||
can have a parameter name in it. Since where are in the
|
||||
working of parameters now, we will not be able to
|
||||
accurately evaluate such expressions. So eventually, I will
|
||||
need to be able to defer the evaluation of the expression. */
|
||||
if (repeat_) {
|
||||
verinum*vrep = repeat_->eval_const(des, scope->name());
|
||||
if (vrep == 0) {
|
||||
cerr << get_line() << ": error: "
|
||||
"concatenation repeat expression cannot be evaluated."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
repeat = vrep->as_ulong();
|
||||
delete vrep;
|
||||
}
|
||||
|
||||
/* Make the empty concat expression. */
|
||||
NetEConcat*tmp = new NetEConcat(parms_.count(), repeat);
|
||||
tmp->set_line(*this);
|
||||
|
||||
/* Elaborate all the operands and attach them to the concat
|
||||
node. Use the elaborate_pexpr method instead of the
|
||||
elaborate_expr method. */
|
||||
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) {
|
||||
assert(parms_[idx]);
|
||||
NetExpr*ex = parms_[idx]->elaborate_pexpr(des, scope);
|
||||
if (ex == 0) continue;
|
||||
ex->set_line(*parms_[idx]);
|
||||
tmp->set(idx, ex);
|
||||
}
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetExpr*PEFNumber::elaborate_pexpr(Design*des, NetScope*scope) const
|
||||
{
|
||||
return elaborate_expr(des, scope);
|
||||
}
|
||||
|
||||
/*
|
||||
* Parameter expressions may reference other parameters, but only in
|
||||
* the current scope. Preserve the parameter reference in the
|
||||
* parameter expression I'm generating, instead of evaluating it now,
|
||||
* because the referenced parameter may yet be overridden.
|
||||
*/
|
||||
NetExpr*PEIdent::elaborate_pexpr(Design*des, NetScope*scope) const
|
||||
{
|
||||
string path = text_;
|
||||
string name = parse_last_name(path);
|
||||
|
||||
NetScope*pscope = scope;
|
||||
if (path != "")
|
||||
pscope = des->find_scope(scope, path);
|
||||
|
||||
assert(pscope);
|
||||
|
||||
const NetExpr*ex = pscope->get_parameter(name);
|
||||
if (ex == 0) {
|
||||
cerr << get_line() << ": error: identifier ``" << text_ <<
|
||||
"'' is not a parameter in " << scope->name() << "." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetExpr*res = new NetEParam(des, pscope, name);
|
||||
assert(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Simple numbers can be elaborated by the elaborate_expr method.
|
||||
*/
|
||||
NetExpr*PENumber::elaborate_pexpr(Design*des, NetScope*sc) const
|
||||
{
|
||||
return elaborate_expr(des, sc);
|
||||
}
|
||||
|
||||
|
||||
NetEConst* PEString::elaborate_pexpr(Design*des, NetScope*scope) const
|
||||
{
|
||||
return elaborate_expr(des, scope);
|
||||
}
|
||||
|
||||
NetETernary* PETernary::elaborate_pexpr(Design*des, NetScope*scope) const
|
||||
{
|
||||
NetExpr*c = expr_->elaborate_pexpr(des, scope);
|
||||
NetExpr*t = tru_->elaborate_pexpr(des, scope);
|
||||
NetExpr*f = fal_->elaborate_pexpr(des, scope);
|
||||
if (c == 0) return 0;
|
||||
if (t == 0) return 0;
|
||||
if (f == 0) return 0;
|
||||
return new NetETernary(c, t, f);
|
||||
}
|
||||
|
||||
NetExpr*PEUnary::elaborate_pexpr (Design*des, NetScope*scope) const
|
||||
{
|
||||
NetExpr*ip = expr_->elaborate_pexpr(des, scope);
|
||||
if (ip == 0) return 0;
|
||||
|
||||
/* Should we evaluate expressions ahead of time,
|
||||
* just like in PEBinary::elaborate_expr() ?
|
||||
*/
|
||||
|
||||
NetEUnary*tmp;
|
||||
switch (op_) {
|
||||
default:
|
||||
tmp = new NetEUnary(op_, ip);
|
||||
tmp->set_line(*this);
|
||||
break;
|
||||
case '~':
|
||||
tmp = new NetEUBits(op_, ip);
|
||||
tmp->set_line(*this);
|
||||
break;
|
||||
case '!': // Logical NOT
|
||||
case '&': // Reduction AND
|
||||
case '|': // Reduction OR
|
||||
case '^': // Reduction XOR
|
||||
case 'A': // Reduction NAND (~&)
|
||||
case 'N': // Reduction NOR (~|)
|
||||
case 'X': // Reduction NXOR (~^)
|
||||
tmp = new NetEUReduce(op_, ip);
|
||||
tmp->set_line(*this);
|
||||
break;
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: elab_pexpr.cc,v $
|
||||
* Revision 1.9 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.8 2001/01/14 23:04:56 steve
|
||||
* Generalize the evaluation of floating point delays, and
|
||||
* get it working with delay assignment statements.
|
||||
*
|
||||
* Allow parameters to be referenced by hierarchical name.
|
||||
*
|
||||
* Revision 1.7 2001/01/02 04:21:13 steve
|
||||
* Support a bunch of unary operators in parameter expressions.
|
||||
*
|
||||
* Revision 1.6 2000/12/16 19:03:30 steve
|
||||
* Evaluate <= and ?: in parameter expressions (PR#81)
|
||||
*
|
||||
* Revision 1.5 2000/06/13 05:22:16 steve
|
||||
* Support concatenation in parameter expressions.
|
||||
*
|
||||
* Revision 1.4 2000/06/01 02:31:39 steve
|
||||
* Parameters can be strings.
|
||||
*
|
||||
* Revision 1.3 2000/03/12 18:22:11 steve
|
||||
* Binary and unary operators in parameter expressions.
|
||||
*
|
||||
* Revision 1.2 2000/03/12 04:35:22 steve
|
||||
* Allow parameter identifiers in parameter expressions.
|
||||
*
|
||||
* Revision 1.1 2000/03/08 04:36:53 steve
|
||||
* Redesign the implementation of scopes and parameters.
|
||||
* I now generate the scopes and notice the parameters
|
||||
* in a separate pass over the pform. Once the scopes
|
||||
* are generated, I can process overrides and evalutate
|
||||
* paremeters before elaboration begins.
|
||||
*
|
||||
*/
|
||||
|
||||
+495
@@ -0,0 +1,495 @@
|
||||
/*
|
||||
* Copyright (c) 2000 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
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: elab_scope.cc,v 1.9 2001/07/25 03:10:49 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# include <iostream>
|
||||
|
||||
/*
|
||||
* Elaboration happens in two passes, generally. The first scans the
|
||||
* pform to generate the NetScope tree and attach it to the Design
|
||||
* object. The methods in this source file implement the elaboration
|
||||
* of the scopes.
|
||||
*/
|
||||
|
||||
# include "Module.h"
|
||||
# include "PEvent.h"
|
||||
# include "PExpr.h"
|
||||
# include "PGate.h"
|
||||
# include "PTask.h"
|
||||
# include "PWire.h"
|
||||
# include "Statement.h"
|
||||
# include "netlist.h"
|
||||
# include <typeinfo>
|
||||
|
||||
bool Module::elaborate_scope(Design*des, NetScope*scope) const
|
||||
{
|
||||
// Generate all the parameters that this instance of this
|
||||
// module introduces to the design. This loop elaborates the
|
||||
// parameters, but doesn't evaluate references to
|
||||
// parameters. This scan practically locates all the
|
||||
// parameters and puts them in the parameter table in the
|
||||
// design.
|
||||
|
||||
// No expressions are evaluated, yet. For now, leave them in
|
||||
// the pform and just place a NetEParam placeholder in the
|
||||
// place of the elaborated expression.
|
||||
|
||||
typedef map<string,PExpr*>::const_iterator mparm_it_t;
|
||||
|
||||
|
||||
// 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 ++) {
|
||||
|
||||
scope->set_parameter((*cur).first, new NetEParam);
|
||||
}
|
||||
|
||||
for (mparm_it_t cur = localparams.begin()
|
||||
; cur != localparams.end() ; cur ++) {
|
||||
|
||||
scope->set_parameter((*cur).first, new NetEParam);
|
||||
}
|
||||
|
||||
|
||||
// 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 ++) {
|
||||
|
||||
PExpr*ex = (*cur).second;
|
||||
assert(ex);
|
||||
|
||||
NetExpr*val = ex->elaborate_pexpr(des, scope);
|
||||
val = scope->set_parameter((*cur).first, val);
|
||||
assert(val);
|
||||
delete val;
|
||||
}
|
||||
|
||||
for (mparm_it_t cur = localparams.begin()
|
||||
; cur != localparams.end() ; cur ++) {
|
||||
|
||||
PExpr*ex = (*cur).second;
|
||||
assert(ex);
|
||||
|
||||
NetExpr*val = ex->elaborate_pexpr(des, scope);
|
||||
val = scope->set_parameter((*cur).first, val);
|
||||
assert(val);
|
||||
delete val;
|
||||
}
|
||||
|
||||
// Run through the defparams for this module, elaborate the
|
||||
// expressions in this context and save the result is a table
|
||||
// for later final override.
|
||||
|
||||
// It is OK to elaborate the expressions of the defparam here
|
||||
// because Verilog requires that the expressions only use
|
||||
// local parameter names. It is *not* OK to do the override
|
||||
// here becuase the parameter receiving the assignment may be
|
||||
// in a scope not discovered by this pass.
|
||||
|
||||
for (mparm_it_t cur = defparms.begin()
|
||||
; cur != defparms.end() ; cur ++ ) {
|
||||
|
||||
PExpr*ex = (*cur).second;
|
||||
assert(ex);
|
||||
|
||||
NetExpr*val = ex->elaborate_pexpr(des, scope);
|
||||
if (val == 0) continue;
|
||||
scope->defparams[(*cur).first] = val;
|
||||
}
|
||||
|
||||
|
||||
// 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<string,PTask*>::const_iterator tasks_it_t;
|
||||
|
||||
for (tasks_it_t cur = tasks_.begin()
|
||||
; cur != tasks_.end() ; cur ++ ) {
|
||||
|
||||
NetScope*task_scope = new NetScope(scope, (*cur).first,
|
||||
NetScope::TASK);
|
||||
(*cur).second->elaborate_scope(des, task_scope);
|
||||
}
|
||||
|
||||
|
||||
// Functions are very similar to tasks, at least from the
|
||||
// perspective of scopes. So handle them exactly the same
|
||||
// way.
|
||||
|
||||
typedef map<string,PFunction*>::const_iterator funcs_it_t;
|
||||
|
||||
for (funcs_it_t cur = funcs_.begin()
|
||||
; cur != funcs_.end() ; cur ++ ) {
|
||||
|
||||
NetScope*func_scope = new NetScope(scope, (*cur).first,
|
||||
NetScope::FUNC);
|
||||
(*cur).second->elaborate_scope(des, func_scope);
|
||||
}
|
||||
|
||||
|
||||
// Gates include modules, which might introduce new scopes, so
|
||||
// scan all of them to create those scopes.
|
||||
|
||||
typedef list<PGate*>::const_iterator gates_it_t;
|
||||
|
||||
for (gates_it_t cur = gates_.begin()
|
||||
; cur != gates_.end() ; cur ++ ) {
|
||||
|
||||
(*cur) -> elaborate_scope(des, scope);
|
||||
}
|
||||
|
||||
|
||||
// initial and always blocks may contain begin-end and
|
||||
// fork-join blocks that can introduce scopes. Therefore, I
|
||||
// get to scan processes here.
|
||||
|
||||
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. We do not
|
||||
// need anything more then the current scope to do this
|
||||
// elaboration, so do it now. This allows for normal
|
||||
// elaboration to reference these events.
|
||||
|
||||
for (map<string,PEvent*>::const_iterator et = events.begin()
|
||||
; et != events.end() ; et ++ ) {
|
||||
|
||||
(*et).second->elaborate_scope(des, scope);
|
||||
}
|
||||
|
||||
return des->errors == 0;
|
||||
}
|
||||
|
||||
void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
|
||||
{
|
||||
if (get_name() == "") {
|
||||
cerr << get_line() << ": error: Instantiation of module "
|
||||
<< mod->get_name() << " requires an instance name." << endl;
|
||||
des->errors += 1;
|
||||
return;
|
||||
}
|
||||
|
||||
// Missing module instance names have already been rejected.
|
||||
assert(get_name() != "");
|
||||
|
||||
string path = sc->name();
|
||||
|
||||
// Check for duplicate scopes. Simply look up the scope I'm
|
||||
// about to create, and if I find it then somebody beat me to
|
||||
// it.
|
||||
|
||||
if (NetScope*tmp = des->find_scope(path + "." + get_name())) {
|
||||
cerr << get_line() << ": error: Instance/Scope name " <<
|
||||
get_name() << " already used in this context." <<
|
||||
endl;
|
||||
des->errors += 1;
|
||||
return;
|
||||
}
|
||||
|
||||
// check for recursive instantiation by scanning the current
|
||||
// scope and its parents. Look for a module instantiation of
|
||||
// the same module, but farther up in the scope.
|
||||
|
||||
for (NetScope*scn = sc ; scn ; scn = scn->parent()) {
|
||||
if (scn->type() != NetScope::MODULE)
|
||||
continue;
|
||||
|
||||
if (mod->get_name() != scn->module_name())
|
||||
continue;
|
||||
|
||||
cerr << get_line() << ": error: You cannot instantiate "
|
||||
<< "module " << mod->get_name() << " within itself." << endl;
|
||||
|
||||
cerr << get_line() << ": : The offending instance is "
|
||||
<< sc->name() << "." << get_name() << " within "
|
||||
<< scn->name() << "." << endl;
|
||||
|
||||
des->errors += 1;
|
||||
return;
|
||||
}
|
||||
|
||||
// Create the new scope as a MODULE with my name.
|
||||
NetScope*my_scope = new NetScope(sc, get_name(), NetScope::MODULE);
|
||||
my_scope->set_module_name(mod->get_name().c_str());
|
||||
|
||||
// Set time units and precision.
|
||||
my_scope->time_unit(mod->time_unit);
|
||||
my_scope->time_precision(mod->time_precision);
|
||||
des->set_precision(mod->time_precision);
|
||||
|
||||
// This call actually arranges for the description of the
|
||||
// module type to process this instance and handle parameters
|
||||
// and sub-scopes that might occur. Parameters are also
|
||||
// created in that scope, as they exist. (I'll override them
|
||||
// later.)
|
||||
mod->elaborate_scope(des, my_scope);
|
||||
|
||||
// Look for module parameter replacements. This map receives
|
||||
// those replacements.
|
||||
|
||||
typedef map<string,PExpr*>::const_iterator mparm_it_t;
|
||||
map<string,PExpr*> replace;
|
||||
|
||||
|
||||
// Positional parameter overrides are matched to parameter
|
||||
// names by using the param_names list of parameter
|
||||
// names. This is an ordered list of names so the first name
|
||||
// is parameter 0, the second parameter 1, and so on.
|
||||
|
||||
if (overrides_) {
|
||||
assert(parms_ == 0);
|
||||
list<string>::const_iterator cur = mod->param_names.begin();
|
||||
for (unsigned idx = 0
|
||||
; idx < overrides_->count()
|
||||
; idx += 1, cur++) {
|
||||
replace[*cur] = (*overrides_)[idx];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Named parameter overrides carry a name with each override
|
||||
// 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;
|
||||
|
||||
}
|
||||
|
||||
|
||||
// And here we scan the replacements we collected. Elaborate
|
||||
// the expression in my context, then replace the sub-scope
|
||||
// parameter value with the new expression.
|
||||
|
||||
for (mparm_it_t cur = replace.begin()
|
||||
; cur != replace.end() ; cur ++ ) {
|
||||
|
||||
PExpr*tmp = (*cur).second;
|
||||
NetExpr*val = tmp->elaborate_pexpr(des, sc);
|
||||
val = my_scope->set_parameter((*cur).first, val);
|
||||
assert(val);
|
||||
delete val;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The isn't really able to create new scopes, but it does create the
|
||||
* event name in the current scope, so can be done during the
|
||||
* elaborate_scope scan.
|
||||
*/
|
||||
void PEvent::elaborate_scope(Design*des, NetScope*scope) const
|
||||
{
|
||||
NetEvent*ev = new NetEvent(name_);
|
||||
ev->set_line(*this);
|
||||
scope->add_event(ev);
|
||||
}
|
||||
|
||||
void PFunction::elaborate_scope(Design*des, NetScope*scope) const
|
||||
{
|
||||
}
|
||||
|
||||
void PTask::elaborate_scope(Design*des, NetScope*scope) const
|
||||
{
|
||||
assert(scope->type() == NetScope::TASK);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The base statement does not have sub-statements and does not
|
||||
* introduce any scope, so this is a no-op.
|
||||
*/
|
||||
void Statement::elaborate_scope(Design*, NetScope*) const
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* When I get a behavioral block, check to see if it has a name. If it
|
||||
* does, then create a new scope for the statements within it,
|
||||
* otherwise use the current scope. Use the selected scope to scan the
|
||||
* statements that I contain.
|
||||
*/
|
||||
void PBlock::elaborate_scope(Design*des, NetScope*scope) const
|
||||
{
|
||||
NetScope*my_scope = scope;
|
||||
|
||||
if (name_ != "") {
|
||||
my_scope = new NetScope(scope, name_, bl_type_==BL_PAR
|
||||
? NetScope::FORK_JOIN
|
||||
: NetScope::BEGIN_END);
|
||||
}
|
||||
|
||||
for (unsigned idx = 0 ; idx < list_.count() ; idx += 1)
|
||||
list_[idx] -> elaborate_scope(des, my_scope);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* The case statement itseof does not introduce scope, but contains
|
||||
* other statements that may be named blocks. So scan the case items
|
||||
* with the elaborate_scope method.
|
||||
*/
|
||||
void PCase::elaborate_scope(Design*des, NetScope*scope) const
|
||||
{
|
||||
assert(items_);
|
||||
for (unsigned idx = 0 ; idx < (*items_).count() ; idx += 1) {
|
||||
assert( (*items_)[idx] );
|
||||
|
||||
if (Statement*sp = (*items_)[idx]->stat)
|
||||
sp -> elaborate_scope(des, scope);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The conditional statement (if-else) does not introduce scope, but
|
||||
* the statements of the clauses may, so elaborate_scope the contained
|
||||
* statements.
|
||||
*/
|
||||
void PCondit::elaborate_scope(Design*des, NetScope*scope) const
|
||||
{
|
||||
if (if_)
|
||||
if_ -> elaborate_scope(des, scope);
|
||||
|
||||
if (else_)
|
||||
else_ -> elaborate_scope(des, scope);
|
||||
}
|
||||
|
||||
/*
|
||||
* Statements that contain a further statement but do not
|
||||
* intrinsically add a scope need to elaborate_scope the contained
|
||||
* statement.
|
||||
*/
|
||||
void PDelayStatement::elaborate_scope(Design*des, NetScope*scope) const
|
||||
{
|
||||
if (statement_)
|
||||
statement_ -> elaborate_scope(des, scope);
|
||||
}
|
||||
|
||||
/*
|
||||
* Statements that contain a further statement but do not
|
||||
* intrinsically add a scope need to elaborate_scope the contained
|
||||
* statement.
|
||||
*/
|
||||
void PEventStatement::elaborate_scope(Design*des, NetScope*scope) const
|
||||
{
|
||||
if (statement_)
|
||||
statement_ -> elaborate_scope(des, scope);
|
||||
}
|
||||
|
||||
/*
|
||||
* Statements that contain a further statement but do not
|
||||
* intrinsically add a scope need to elaborate_scope the contained
|
||||
* statement.
|
||||
*/
|
||||
void PForever::elaborate_scope(Design*des, NetScope*scope) const
|
||||
{
|
||||
if (statement_)
|
||||
statement_ -> elaborate_scope(des, scope);
|
||||
}
|
||||
|
||||
/*
|
||||
* Statements that contain a further statement but do not
|
||||
* intrinsically add a scope need to elaborate_scope the contained
|
||||
* statement.
|
||||
*/
|
||||
void PForStatement::elaborate_scope(Design*des, NetScope*scope) const
|
||||
{
|
||||
if (statement_)
|
||||
statement_ -> elaborate_scope(des, scope);
|
||||
}
|
||||
|
||||
/*
|
||||
* Statements that contain a further statement but do not
|
||||
* intrinsically add a scope need to elaborate_scope the contained
|
||||
* statement.
|
||||
*/
|
||||
void PRepeat::elaborate_scope(Design*des, NetScope*scope) const
|
||||
{
|
||||
if (statement_)
|
||||
statement_ -> elaborate_scope(des, scope);
|
||||
}
|
||||
|
||||
/*
|
||||
* Statements that contain a further statement but do not
|
||||
* intrinsically add a scope need to elaborate_scope the contained
|
||||
* statement.
|
||||
*/
|
||||
void PWhile::elaborate_scope(Design*des, NetScope*scope) const
|
||||
{
|
||||
if (statement_)
|
||||
statement_ -> elaborate_scope(des, scope);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* $Log: elab_scope.cc,v $
|
||||
* Revision 1.9 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.8 2001/04/28 23:18:08 steve
|
||||
* UDP instances need not have user supplied names.
|
||||
*
|
||||
* Revision 1.7 2000/12/16 01:45:48 steve
|
||||
* Detect recursive instantiations (PR#2)
|
||||
*
|
||||
* Revision 1.6 2000/07/30 18:25:43 steve
|
||||
* Rearrange task and function elaboration so that the
|
||||
* NetTaskDef and NetFuncDef functions are created during
|
||||
* signal enaboration, and carry these objects in the
|
||||
* NetScope class instead of the extra, useless map in
|
||||
* the Design class.
|
||||
*
|
||||
* Revision 1.5 2000/07/22 22:09:03 steve
|
||||
* Parse and elaborate timescale to scopes.
|
||||
*
|
||||
* Revision 1.4 2000/04/09 17:44:30 steve
|
||||
* Catch event declarations during scope elaborate.
|
||||
*
|
||||
* Revision 1.3 2000/03/12 17:09:41 steve
|
||||
* Support localparam.
|
||||
*
|
||||
* Revision 1.2 2000/03/11 03:25:52 steve
|
||||
* Locate scopes in statements.
|
||||
*
|
||||
* Revision 1.1 2000/03/08 04:36:53 steve
|
||||
* Redesign the implementation of scopes and parameters.
|
||||
* I now generate the scopes and notice the parameters
|
||||
* in a separate pass over the pform. Once the scopes
|
||||
* are generated, I can process overrides and evalutate
|
||||
* paremeters before elaboration begins.
|
||||
*
|
||||
*/
|
||||
|
||||
+502
@@ -0,0 +1,502 @@
|
||||
/*
|
||||
* Copyright (c) 2000 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
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: elab_sig.cc,v 1.14 2001/07/25 03:10:49 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# include <iostream>
|
||||
|
||||
# include "Module.h"
|
||||
# include "PExpr.h"
|
||||
# include "PGate.h"
|
||||
# include "PTask.h"
|
||||
# include "PWire.h"
|
||||
# include "netlist.h"
|
||||
# include "netmisc.h"
|
||||
# include "util.h"
|
||||
|
||||
/*
|
||||
* This local function checks if a named signal is connected to a
|
||||
* port. It looks in the array of ports passed, for NetEIdent objects
|
||||
* within the port_t that have a matching name.
|
||||
*/
|
||||
static bool signal_is_in_port(const svector<Module::port_t*>&ports,
|
||||
const string&name)
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < ports.count() ; idx += 1) {
|
||||
|
||||
Module::port_t*pp = ports[idx];
|
||||
// Skip internally unconnected ports.
|
||||
if (pp == 0)
|
||||
continue;
|
||||
|
||||
// This port has an internal connection. In this case,
|
||||
// the port has 0 or more NetEIdent objects concatenated
|
||||
// together that form the port.
|
||||
for (unsigned cc = 0 ; cc < pp->expr.count() ; cc += 1) {
|
||||
assert(pp->expr[cc]);
|
||||
if (pp->expr[cc]->name() == name)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Module::elaborate_sig(Design*des, NetScope*scope) const
|
||||
{
|
||||
bool flag = true;
|
||||
|
||||
// Get all the explicitly declared wires of the module and
|
||||
// start the signals list with them.
|
||||
const map<string,PWire*>&wl = get_wires();
|
||||
|
||||
for (map<string,PWire*>::const_iterator wt = wl.begin()
|
||||
; wt != wl.end()
|
||||
; wt ++ ) {
|
||||
|
||||
PWire*cur = (*wt).second;
|
||||
cur->elaborate_sig(des, scope);
|
||||
|
||||
// If this wire is a signal of the module (as opposed to
|
||||
// a port of a function) and is a port, then check that
|
||||
// the module knows about it.
|
||||
NetNet*sig = scope->find_signal(cur->name());
|
||||
if (sig && (sig->scope() == scope)
|
||||
&& (cur->get_port_type() != NetNet::NOT_A_PORT)) {
|
||||
string name = (*wt).first;
|
||||
|
||||
if (! signal_is_in_port(ports_, name)) {
|
||||
|
||||
cerr << cur->get_line() << ": error: Signal "
|
||||
<< name << " has a declared direction "
|
||||
<< "but is not a port." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* If the signal is an input and is also declared as a
|
||||
reg, then report an error. */
|
||||
|
||||
if (sig && (sig->scope() == scope)
|
||||
&& (sig->port_type() == NetNet::PINPUT)
|
||||
&& (sig->type() == NetNet::REG)) {
|
||||
|
||||
cerr << cur->get_line() << ": error: "
|
||||
<< cur->name() << " in module "
|
||||
<< scope->module_name()
|
||||
<< " declared as input and as a reg type." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
if (sig && (sig->scope() == scope)
|
||||
&& (sig->port_type() == NetNet::PINOUT)
|
||||
&& (sig->type() == NetNet::REG)) {
|
||||
|
||||
cerr << cur->get_line() << ": error: "
|
||||
<< cur->name() << " in module "
|
||||
<< scope->module_name()
|
||||
<< " declared as inout and as a reg type." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Get all the gates of the module and elaborate them by
|
||||
// connecting them to the signals. The gate may be simple or
|
||||
// complex. What we are looking for is gates that are modules
|
||||
// that can create scopes and signals.
|
||||
|
||||
const list<PGate*>&gl = get_gates();
|
||||
|
||||
for (list<PGate*>::const_iterator gt = gl.begin()
|
||||
; gt != gl.end()
|
||||
; gt ++ ) {
|
||||
|
||||
flag &= (*gt)->elaborate_sig(des, scope);
|
||||
}
|
||||
|
||||
|
||||
typedef map<string,PFunction*>::const_iterator mfunc_it_t;
|
||||
|
||||
for (mfunc_it_t cur = funcs_.begin()
|
||||
; cur != funcs_.end() ; cur ++) {
|
||||
NetScope*fscope = scope->child((*cur).first);
|
||||
if (scope == 0) {
|
||||
cerr << (*cur).second->get_line() << ": internal error: "
|
||||
<< "Child scope for function " << (*cur).first
|
||||
<< " missing in " << scope->name() << "." << 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<string,PTask*>::const_iterator mtask_it_t;
|
||||
|
||||
for (mtask_it_t cur = tasks_.begin()
|
||||
; cur != tasks_.end() ; cur ++) {
|
||||
NetScope*tscope = scope->child((*cur).first);
|
||||
assert(tscope);
|
||||
(*cur).second->elaborate_sig(des, tscope);
|
||||
}
|
||||
|
||||
return flag;
|
||||
}
|
||||
|
||||
bool PGModule::elaborate_sig_mod_(Design*des, NetScope*scope,
|
||||
Module*rmod) const
|
||||
{
|
||||
// Missing module instance names have already been rejected.
|
||||
assert(get_name() != "");
|
||||
|
||||
if (msb_) {
|
||||
cerr << get_line() << ": sorry: Module instantiation arrays "
|
||||
"are not yet supported." << endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// 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 = scope->child(get_name());
|
||||
assert(my_scope);
|
||||
|
||||
return rmod->elaborate_sig(des, my_scope);
|
||||
}
|
||||
|
||||
/*
|
||||
* A function definition exists within an elaborated module.
|
||||
*/
|
||||
void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
||||
{
|
||||
string fname = scope->basename();
|
||||
assert(scope->type() == NetScope::FUNC);
|
||||
|
||||
svector<NetNet*>ports (ports_? ports_->count()+1 : 1);
|
||||
|
||||
/* Get the reg for the return value. I know the name of the
|
||||
reg variable, and I know that it is in this scope, so look
|
||||
it up directly. */
|
||||
ports[0] = scope->find_signal(scope->basename());
|
||||
if (ports[0] == 0) {
|
||||
cerr << get_line() << ": internal error: function scope "
|
||||
<< scope->name() << " is missing return reg "
|
||||
<< fname << "." << endl;
|
||||
scope->dump(cerr);
|
||||
des->errors += 1;
|
||||
return;
|
||||
}
|
||||
|
||||
if (ports_)
|
||||
for (unsigned idx = 0 ; idx < ports_->count() ; idx += 1) {
|
||||
|
||||
/* Parse the port name into the task name and the reg
|
||||
name. We know by design that the port name is given
|
||||
as two components: <func>.<port>. */
|
||||
|
||||
string pname = (*ports_)[idx]->name();
|
||||
string ppath = parse_first_name(pname);
|
||||
|
||||
if (ppath != scope->basename()) {
|
||||
cerr << get_line() << ": internal error: function "
|
||||
<< "port " << (*ports_)[idx]->name()
|
||||
<< " has wrong name for function "
|
||||
<< scope->name() << "." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
NetNet*tmp = scope->find_signal(pname);
|
||||
if (tmp == 0) {
|
||||
cerr << get_line() << ": internal error: function "
|
||||
<< scope->name() << " is missing port "
|
||||
<< pname << "." << endl;
|
||||
scope->dump(cerr);
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
ports[idx+1] = tmp;
|
||||
}
|
||||
|
||||
|
||||
NetFuncDef*def = new NetFuncDef(scope, ports);
|
||||
scope->set_func_def(def);
|
||||
}
|
||||
|
||||
/*
|
||||
* A task definition is a scope within an elaborated module. When we
|
||||
* are elaborating signals, the scopes have already been created, as
|
||||
* have the reg objects that are the parameters of this task. The
|
||||
* elaborate_sig method of PTask is therefore left to connect the
|
||||
* signals to the ports of the NetTaskDef definition. We know for
|
||||
* certain that signals exist (They are in my scope!) so the port
|
||||
* binding is sure to work.
|
||||
*/
|
||||
void PTask::elaborate_sig(Design*des, NetScope*scope) const
|
||||
{
|
||||
assert(scope->type() == NetScope::TASK);
|
||||
|
||||
svector<NetNet*>ports (ports_? ports_->count() : 0);
|
||||
for (unsigned idx = 0 ; idx < ports.count() ; idx += 1) {
|
||||
|
||||
/* Parse the port name into the task name and the reg
|
||||
name. We know by design that the port name is given
|
||||
as two components: <task>.<port>. */
|
||||
|
||||
string pname = (*ports_)[idx]->name();
|
||||
string ppath = parse_first_name(pname);
|
||||
assert(pname != "");
|
||||
|
||||
/* check that the current scope really does have the
|
||||
name of the first component of the task port name. Do
|
||||
this by looking up the task scope in the parent of
|
||||
the current scope. */
|
||||
if (scope->parent()->child(ppath) != scope) {
|
||||
cerr << "internal error: task scope " << ppath
|
||||
<< " not the same as scope " << scope->name()
|
||||
<< "?!" << endl;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Find the signal for the port. We know by definition
|
||||
that it is in the scope of the task, so look only in
|
||||
the scope. */
|
||||
NetNet*tmp = scope->find_signal(pname);
|
||||
|
||||
if (tmp == 0) {
|
||||
cerr << get_line() << ": internal error: "
|
||||
<< "Could not find port " << pname
|
||||
<< " in scope " << scope->name() << endl;
|
||||
scope->dump(cerr);
|
||||
}
|
||||
|
||||
ports[idx] = tmp;
|
||||
}
|
||||
|
||||
NetTaskDef*def = new NetTaskDef(scope->name(), ports);
|
||||
scope->set_task_def(def);
|
||||
}
|
||||
|
||||
bool PGate::elaborate_sig(Design*des, NetScope*scope) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Elaborate a source wire. The "wire" is the declaration of wires,
|
||||
* registers, ports and memories. The parser has already merged the
|
||||
* multiple properties of a wire (i.e. "input wire") so come the
|
||||
* elaboration this creates an object in the design that represent the
|
||||
* defined item.
|
||||
*/
|
||||
void PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
{
|
||||
/* The parser may produce hierarchical names for wires. I here
|
||||
follow the scopes down to the base where I actually want to
|
||||
elaborate the NetNet object. */
|
||||
string basename = name_;
|
||||
for (;;) {
|
||||
string p = parse_first_name(basename);
|
||||
if (basename == "") {
|
||||
basename = p;
|
||||
break;
|
||||
}
|
||||
|
||||
scope = scope->child(p);
|
||||
assert(scope);
|
||||
}
|
||||
|
||||
const string path = scope->name();
|
||||
NetNet::Type wtype = type_;
|
||||
if (wtype == NetNet::IMPLICIT)
|
||||
wtype = NetNet::WIRE;
|
||||
if (wtype == NetNet::IMPLICIT_REG)
|
||||
wtype = NetNet::REG;
|
||||
|
||||
unsigned wid = 1;
|
||||
long lsb = 0, msb = 0;
|
||||
|
||||
assert(msb_.count() == lsb_.count());
|
||||
if (msb_.count()) {
|
||||
svector<long>mnum (msb_.count());
|
||||
svector<long>lnum (msb_.count());
|
||||
|
||||
/* There may be multiple declarations of ranges, because
|
||||
the symbol may have its range declared in i.e. input
|
||||
and reg declarations. Calculate *all* the numbers
|
||||
here. I will resolve the values later. */
|
||||
|
||||
for (unsigned idx = 0 ; idx < msb_.count() ; idx += 1) {
|
||||
|
||||
NetEConst*tmp;
|
||||
NetExpr*texpr = elab_and_eval(des, scope, msb_[idx]);
|
||||
|
||||
tmp = dynamic_cast<NetEConst*>(texpr);
|
||||
if (tmp == 0) {
|
||||
cerr << msb_[idx]->get_line() << ": error: "
|
||||
"Unable to evaluate constant expression ``" <<
|
||||
*msb_[idx] << "''." << endl;
|
||||
des->errors += 1;
|
||||
return;
|
||||
}
|
||||
|
||||
mnum[idx] = tmp->value().as_long();
|
||||
delete texpr;
|
||||
|
||||
texpr = elab_and_eval(des, scope, lsb_[idx]);
|
||||
tmp = dynamic_cast<NetEConst*>(texpr);
|
||||
if (tmp == 0) {
|
||||
cerr << msb_[idx]->get_line() << ": error: "
|
||||
"Unable to evaluate constant expression ``" <<
|
||||
*lsb_[idx] << "''." << endl;
|
||||
des->errors += 1;
|
||||
return;
|
||||
}
|
||||
|
||||
lnum[idx] = tmp->value().as_long();
|
||||
delete texpr;
|
||||
|
||||
}
|
||||
|
||||
/* Make sure all the values for msb and lsb match by
|
||||
value. If not, report an error. */
|
||||
for (unsigned idx = 1 ; idx < msb_.count() ; idx += 1) {
|
||||
if ((mnum[idx] != mnum[0]) || (lnum[idx] != lnum[0])) {
|
||||
cerr << get_line() << ": error: Inconsistent width, "
|
||||
"[" << mnum[idx] << ":" << lnum[idx] << "]"
|
||||
" vs. [" << mnum[0] << ":" << lnum[0] << "]"
|
||||
" for signal ``" << basename << "''" << endl;
|
||||
des->errors += 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
lsb = lnum[0];
|
||||
msb = mnum[0];
|
||||
if (mnum[0] > lnum[0])
|
||||
wid = mnum[0] - lnum[0] + 1;
|
||||
else
|
||||
wid = lnum[0] - mnum[0] + 1;
|
||||
|
||||
|
||||
}
|
||||
|
||||
if (lidx_ || ridx_) {
|
||||
assert(lidx_ && ridx_);
|
||||
|
||||
// If the register has indices, then this is a
|
||||
// memory. Create the memory object.
|
||||
verinum*lval = lidx_->eval_const(des, path);
|
||||
verinum*rval = ridx_->eval_const(des, path);
|
||||
|
||||
if ((lval == 0) || (rval == 0)) {
|
||||
cerr << get_line() << ": internal error: There is "
|
||||
<< "a problem evaluating indices for ``"
|
||||
<< basename << "''." << endl;
|
||||
des->errors += 1;
|
||||
return;
|
||||
}
|
||||
|
||||
assert(lval);
|
||||
assert(rval);
|
||||
|
||||
long lnum = lval->as_long();
|
||||
long rnum = rval->as_long();
|
||||
delete lval;
|
||||
delete rval;
|
||||
NetMemory*sig = new NetMemory(scope, path+"."+basename,
|
||||
wid, lnum, rnum);
|
||||
|
||||
} else {
|
||||
|
||||
NetNet*sig = new NetNet(scope, path + "." +basename, wtype, msb, lsb);
|
||||
sig->set_line(*this);
|
||||
sig->port_type(port_type_);
|
||||
sig->set_signed(get_signed());
|
||||
sig->set_attributes(attributes);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: elab_sig.cc,v $
|
||||
* Revision 1.14 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.13 2001/05/25 02:21:34 steve
|
||||
* Detect input and input ports declared as reg.
|
||||
*
|
||||
* Revision 1.12 2001/02/17 05:15:33 steve
|
||||
* Allow task ports to be given real types.
|
||||
*
|
||||
* Revision 1.11 2001/02/10 20:29:39 steve
|
||||
* In the context of range declarations, use elab_and_eval instead
|
||||
* of the less robust eval_const methods.
|
||||
*
|
||||
* Revision 1.10 2001/01/13 22:20:08 steve
|
||||
* Parse parameters within nested scopes.
|
||||
*
|
||||
* Revision 1.9 2001/01/07 07:00:31 steve
|
||||
* Detect port direction attached to non-ports.
|
||||
*
|
||||
* Revision 1.8 2001/01/04 04:47:51 steve
|
||||
* Add support for << is signal indices.
|
||||
*
|
||||
* Revision 1.7 2000/12/11 00:31:43 steve
|
||||
* Add support for signed reg variables,
|
||||
* simulate in t-vvm signed comparisons.
|
||||
*
|
||||
* Revision 1.6 2000/12/04 17:37:04 steve
|
||||
* Add Attrib class for holding NetObj attributes.
|
||||
*
|
||||
* Revision 1.5 2000/11/20 00:58:40 steve
|
||||
* Add support for supply nets (PR#17)
|
||||
*
|
||||
* Revision 1.4 2000/09/07 22:37:48 steve
|
||||
* ack, detect when lval fails.
|
||||
*
|
||||
* Revision 1.3 2000/07/30 18:25:43 steve
|
||||
* Rearrange task and function elaboration so that the
|
||||
* NetTaskDef and NetFuncDef functions are created during
|
||||
* signal enaboration, and carry these objects in the
|
||||
* NetScope class instead of the extra, useless map in
|
||||
* the Design class.
|
||||
*
|
||||
* Revision 1.2 2000/07/14 06:12:57 steve
|
||||
* Move inital value handling from NetNet to Nexus
|
||||
* objects. This allows better propogation of inital
|
||||
* values.
|
||||
*
|
||||
* Clean up constant propagation a bit to account
|
||||
* for regs that are not really values.
|
||||
*
|
||||
* Revision 1.1 2000/05/02 16:27:38 steve
|
||||
* Move signal elaboration to a seperate pass.
|
||||
*
|
||||
*/
|
||||
|
||||
+1297
-917
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2000 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,200 +16,242 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: emit.cc,v 1.31 1999/11/28 23:42:02 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: emit.cc,v 1.62 2001/08/25 23:50:02 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# include <iostream>
|
||||
|
||||
/*
|
||||
* The emit function is called to generate the output required of the
|
||||
* target.
|
||||
*/
|
||||
# include "target.h"
|
||||
# include "netlist.h"
|
||||
# include <iostream>
|
||||
# include <typeinfo>
|
||||
# include <cassert>
|
||||
|
||||
void NetNode::emit_node(ostream&o, struct target_t*tgt) const
|
||||
bool NetNode::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
cerr << "EMIT: Gate type? " << typeid(*this).name() << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
void NetLogic::emit_node(ostream&o, struct target_t*tgt) const
|
||||
bool NetLogic::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
tgt->logic(o, this);
|
||||
tgt->logic(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
void NetUDP::emit_node(ostream&o, struct target_t*tgt) const
|
||||
bool NetUDP::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
tgt->udp(o, this);
|
||||
tgt->udp(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
void NetAddSub::emit_node(ostream&o, struct target_t*tgt) const
|
||||
bool NetAddSub::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
tgt->lpm_add_sub(o, this);
|
||||
tgt->lpm_add_sub(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
void NetAssign::emit_node(ostream&o, struct target_t*tgt) const
|
||||
bool NetCaseCmp::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
tgt->net_assign(o, this);
|
||||
tgt->net_case_cmp(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
void NetAssignNB::emit_node(ostream&o, struct target_t*tgt) const
|
||||
bool NetCAssign::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
tgt->net_assign_nb(o, this);
|
||||
tgt->net_cassign(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
void NetCaseCmp::emit_node(ostream&o, struct target_t*tgt) const
|
||||
bool NetCLShift::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
tgt->net_case_cmp(o, this);
|
||||
tgt->lpm_clshift(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
void NetCLShift::emit_node(ostream&o, struct target_t*tgt) const
|
||||
bool NetCompare::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
tgt->lpm_clshift(o, this);
|
||||
tgt->lpm_compare(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
void NetCompare::emit_node(ostream&o, struct target_t*tgt) const
|
||||
bool NetConst::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
tgt->lpm_compare(o, this);
|
||||
return tgt->net_const(this);
|
||||
}
|
||||
|
||||
void NetConst::emit_node(ostream&o, struct target_t*tgt) const
|
||||
bool NetDivide::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
tgt->net_const(o, this);
|
||||
tgt->lpm_divide(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
void NetFF::emit_node(ostream&o, struct target_t*tgt) const
|
||||
bool NetFF::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
tgt->lpm_ff(o, this);
|
||||
tgt->lpm_ff(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
void NetMux::emit_node(ostream&o, struct target_t*tgt) const
|
||||
bool NetForce::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
tgt->lpm_mux(o, this);
|
||||
tgt->net_force(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
void NetRamDq::emit_node(ostream&o, struct target_t*tgt) const
|
||||
bool NetModulo::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
tgt->lpm_ram_dq(o, this);
|
||||
tgt->lpm_modulo(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
void NetNEvent::emit_node(ostream&o, struct target_t*tgt) const
|
||||
bool NetMult::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
tgt->net_event(o, this);
|
||||
tgt->lpm_mult(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
void NetBUFZ::emit_node(ostream&o, struct target_t*tgt) const
|
||||
bool NetMux::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
tgt->bufz(o, this);
|
||||
tgt->lpm_mux(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetProcTop::emit(ostream&o, struct target_t*tgt) const
|
||||
bool NetRamDq::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->process(o, this);
|
||||
tgt->lpm_ram_dq(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetProc::emit_proc(ostream&o, struct target_t*tgt) const
|
||||
bool NetBUFZ::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->bufz(this);
|
||||
}
|
||||
|
||||
bool NetProcTop::emit(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->process(this);
|
||||
}
|
||||
|
||||
bool NetProc::emit_proc(struct target_t*tgt) const
|
||||
{
|
||||
cerr << "EMIT: Proc type? " << typeid(*this).name() << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NetAssign::emit_proc(ostream&o, struct target_t*tgt) const
|
||||
bool NetAssign::emit_proc(struct target_t*tgt) const
|
||||
{
|
||||
tgt->proc_assign(o, this);
|
||||
tgt->proc_assign(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetAssignNB::emit_proc(ostream&o, struct target_t*tgt) const
|
||||
bool NetAssignNB::emit_proc(struct target_t*tgt) const
|
||||
{
|
||||
tgt->proc_assign_nb(o, this);
|
||||
tgt->proc_assign_nb(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetAssignMem::emit_proc(ostream&o, struct target_t*tgt) const
|
||||
bool NetAssignMem::emit_proc(struct target_t*tgt) const
|
||||
{
|
||||
tgt->proc_assign_mem(o, this);
|
||||
tgt->proc_assign_mem(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetAssignMemNB::emit_proc(ostream&o, struct target_t*tgt) const
|
||||
bool NetAssignMemNB::emit_proc(struct target_t*tgt) const
|
||||
{
|
||||
tgt->proc_assign_mem_nb(o, this);
|
||||
tgt->proc_assign_mem_nb(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetBlock::emit_proc(ostream&o, struct target_t*tgt) const
|
||||
bool NetBlock::emit_proc(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->proc_block(o, this);
|
||||
return tgt->proc_block(this);
|
||||
}
|
||||
|
||||
bool NetCase::emit_proc(ostream&o, struct target_t*tgt) const
|
||||
bool NetCase::emit_proc(struct target_t*tgt) const
|
||||
{
|
||||
tgt->proc_case(o, this);
|
||||
tgt->proc_case(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetCondit::emit_proc(ostream&o, struct target_t*tgt) const
|
||||
bool NetCAssign::emit_proc(struct target_t*tgt) const
|
||||
{
|
||||
tgt->proc_condit(o, this);
|
||||
return tgt->proc_cassign(this);
|
||||
}
|
||||
|
||||
bool NetCondit::emit_proc(struct target_t*tgt) const
|
||||
{
|
||||
tgt->proc_condit(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetForever::emit_proc(ostream&o, struct target_t*tgt) const
|
||||
bool NetDeassign::emit_proc(struct target_t*tgt) const
|
||||
{
|
||||
tgt->proc_forever(o, this);
|
||||
return tgt->proc_deassign(this);
|
||||
}
|
||||
|
||||
bool NetDisable::emit_proc(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->proc_disable(this);
|
||||
}
|
||||
|
||||
bool NetForce::emit_proc(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->proc_force(this);
|
||||
}
|
||||
|
||||
bool NetForever::emit_proc(struct target_t*tgt) const
|
||||
{
|
||||
tgt->proc_forever(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetPDelay::emit_proc(ostream&o, struct target_t*tgt) const
|
||||
bool NetPDelay::emit_proc(struct target_t*tgt) const
|
||||
{
|
||||
tgt->proc_delay(o, this);
|
||||
return tgt->proc_delay(this);
|
||||
}
|
||||
|
||||
bool NetPDelay::emit_proc_recurse(struct target_t*tgt) const
|
||||
{
|
||||
if (statement_) return statement_->emit_proc(tgt);
|
||||
return true;
|
||||
}
|
||||
|
||||
void NetPDelay::emit_proc_recurse(ostream&o, struct target_t*tgt) const
|
||||
bool NetRelease::emit_proc(struct target_t*tgt) const
|
||||
{
|
||||
if (statement_) statement_->emit_proc(o, tgt);
|
||||
return tgt->proc_release(this);
|
||||
}
|
||||
|
||||
bool NetPEvent::emit_proc(ostream&o, struct target_t*tgt) const
|
||||
bool NetRepeat::emit_proc(struct target_t*tgt) const
|
||||
{
|
||||
tgt->proc_event(o, this);
|
||||
tgt->proc_repeat(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
void NetPEvent::emit_proc_recurse(ostream&o, struct target_t*tgt) const
|
||||
bool NetSTask::emit_proc(struct target_t*tgt) const
|
||||
{
|
||||
if (statement_) statement_->emit_proc(o, tgt);
|
||||
}
|
||||
|
||||
bool NetRepeat::emit_proc(ostream&o, struct target_t*tgt) const
|
||||
{
|
||||
tgt->proc_repeat(o, this);
|
||||
tgt->proc_stask(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetSTask::emit_proc(ostream&o, struct target_t*tgt) const
|
||||
bool NetUTask::emit_proc(struct target_t*tgt) const
|
||||
{
|
||||
tgt->proc_stask(o, this);
|
||||
tgt->proc_utask(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetUTask::emit_proc(ostream&o, struct target_t*tgt) const
|
||||
bool NetWhile::emit_proc(struct target_t*tgt) const
|
||||
{
|
||||
tgt->proc_utask(o, this);
|
||||
tgt->proc_while(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetWhile::emit_proc(ostream&o, struct target_t*tgt) const
|
||||
{
|
||||
tgt->proc_while(o, this);
|
||||
return true;
|
||||
}
|
||||
|
||||
void NetBlock::emit_recurse(ostream&o, struct target_t*tgt) const
|
||||
void NetBlock::emit_recurse(struct target_t*tgt) const
|
||||
{
|
||||
if (last_ == 0)
|
||||
return;
|
||||
@@ -217,101 +259,140 @@ void NetBlock::emit_recurse(ostream&o, struct target_t*tgt) const
|
||||
NetProc*cur = last_;
|
||||
do {
|
||||
cur = cur->next_;
|
||||
cur->emit_proc(o, tgt);
|
||||
cur->emit_proc(tgt);
|
||||
} while (cur != last_);
|
||||
}
|
||||
|
||||
void NetCondit::emit_recurse_if(ostream&o, struct target_t*tgt) const
|
||||
void NetCondit::emit_recurse_if(struct target_t*tgt) const
|
||||
{
|
||||
if (if_)
|
||||
if_->emit_proc(o, tgt);
|
||||
if_->emit_proc(tgt);
|
||||
}
|
||||
|
||||
void NetCondit::emit_recurse_else(ostream&o, struct target_t*tgt) const
|
||||
void NetCondit::emit_recurse_else(struct target_t*tgt) const
|
||||
{
|
||||
if (else_)
|
||||
else_->emit_proc(o, tgt);
|
||||
else_->emit_proc(tgt);
|
||||
}
|
||||
|
||||
void NetForever::emit_recurse(ostream&o, struct target_t*tgt) const
|
||||
bool NetEvProbe::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
tgt->net_probe(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetEvTrig::emit_proc(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->proc_trigger(this);
|
||||
}
|
||||
|
||||
bool NetEvWait::emit_proc(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->proc_wait(this);
|
||||
}
|
||||
|
||||
bool NetEvWait::emit_recurse(struct target_t*tgt) const
|
||||
{
|
||||
if (!statement_) return true;
|
||||
return statement_->emit_proc(tgt);
|
||||
}
|
||||
|
||||
void NetForever::emit_recurse(struct target_t*tgt) const
|
||||
{
|
||||
if (statement_)
|
||||
statement_->emit_proc(o, tgt);
|
||||
statement_->emit_proc(tgt);
|
||||
}
|
||||
|
||||
void NetRepeat::emit_recurse(ostream&o, struct target_t*tgt) const
|
||||
void NetRepeat::emit_recurse(struct target_t*tgt) const
|
||||
{
|
||||
if (statement_)
|
||||
statement_->emit_proc(o, tgt);
|
||||
statement_->emit_proc(tgt);
|
||||
}
|
||||
|
||||
void NetWhile::emit_proc_recurse(ostream&o, struct target_t*tgt) const
|
||||
void NetScope::emit_scope(struct target_t*tgt) const
|
||||
{
|
||||
proc_->emit_proc(o, tgt);
|
||||
}
|
||||
tgt->scope(this);
|
||||
|
||||
bool Design::emit(ostream&o, struct target_t*tgt) const
|
||||
{
|
||||
bool rc = true;
|
||||
tgt->start_design(o, this);
|
||||
for (NetEvent*cur = events_ ; cur ; cur = cur->snext_)
|
||||
tgt->event(cur);
|
||||
|
||||
// enumerate the scopes
|
||||
{ map<string,NetScope*>::const_iterator sc;
|
||||
for (sc = scopes_.begin() ; sc != scopes_.end() ; sc++) {
|
||||
tgt->scope(o, (*sc).second);
|
||||
}
|
||||
}
|
||||
for (NetScope*cur = sub_ ; cur ; cur = cur->sib_)
|
||||
cur->emit_scope(tgt);
|
||||
|
||||
// emit signals
|
||||
if (signals_) {
|
||||
NetNet*cur = signals_->sig_next_;
|
||||
do {
|
||||
tgt->signal(o, cur);
|
||||
tgt->signal(cur);
|
||||
cur = cur->sig_next_;
|
||||
} while (cur != signals_->sig_next_);
|
||||
}
|
||||
|
||||
|
||||
// emit memories
|
||||
{
|
||||
map<string,NetMemory*>::const_iterator mi;
|
||||
for (mi = memories_.begin() ; mi != memories_.end() ; mi++) {
|
||||
tgt->memory(o, (*mi).second);
|
||||
}
|
||||
if (memories_) {
|
||||
NetMemory*cur = memories_->snext_;
|
||||
do {
|
||||
tgt->memory(cur);
|
||||
cur = cur->snext_;
|
||||
} while (cur != memories_->snext_);
|
||||
}
|
||||
}
|
||||
|
||||
void NetScope::emit_defs(struct target_t*tgt) const
|
||||
{
|
||||
|
||||
switch (type_) {
|
||||
case MODULE:
|
||||
for (NetScope*cur = sub_ ; cur ; cur = cur->sib_)
|
||||
cur->emit_defs(tgt);
|
||||
break;
|
||||
|
||||
case FUNC:
|
||||
tgt->func_def(this);
|
||||
break;
|
||||
case TASK:
|
||||
tgt->task_def(this);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void NetWhile::emit_proc_recurse(struct target_t*tgt) const
|
||||
{
|
||||
proc_->emit_proc(tgt);
|
||||
}
|
||||
|
||||
bool Design::emit(struct target_t*tgt) const
|
||||
{
|
||||
bool rc = true;
|
||||
|
||||
rc = rc && tgt->start_design(this);
|
||||
if (rc == false)
|
||||
return false;
|
||||
|
||||
// enumerate the scopes
|
||||
root_scope_->emit_scope(tgt);
|
||||
|
||||
|
||||
// emit nodes
|
||||
if (nodes_) {
|
||||
NetNode*cur = nodes_->node_next_;
|
||||
do {
|
||||
cur->emit_node(o, tgt);
|
||||
rc = rc && cur->emit_node(tgt);
|
||||
cur = cur->node_next_;
|
||||
} while (cur != nodes_->node_next_);
|
||||
}
|
||||
|
||||
|
||||
// emit function definitions
|
||||
{
|
||||
map<string,NetFuncDef*>::const_iterator ta;
|
||||
for (ta = funcs_.begin() ; ta != funcs_.end() ; ta ++) {
|
||||
tgt->func_def(o, (*ta).second);
|
||||
}
|
||||
}
|
||||
// emit task and function definitions
|
||||
root_scope_->emit_defs(tgt);
|
||||
|
||||
// emit task definitions
|
||||
{
|
||||
map<string,NetTaskDef*>::const_iterator ta;
|
||||
for (ta = tasks_.begin() ; ta != tasks_.end() ; ta ++) {
|
||||
tgt->task_def(o, (*ta).second);
|
||||
}
|
||||
}
|
||||
|
||||
// emit the processes
|
||||
for (const NetProcTop*idx = procs_ ; idx ; idx = idx->next_)
|
||||
rc = rc && idx->emit(o, tgt);
|
||||
rc = rc && idx->emit(tgt);
|
||||
|
||||
if (tgt->end_design(this) != 0)
|
||||
rc = false;
|
||||
|
||||
tgt->end_design(o, this);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -330,11 +411,6 @@ void NetEConst::expr_scan(struct expr_scan_t*tgt) const
|
||||
tgt->expr_const(this);
|
||||
}
|
||||
|
||||
void NetEIdent::expr_scan(struct expr_scan_t*tgt) const
|
||||
{
|
||||
tgt->expr_ident(this);
|
||||
}
|
||||
|
||||
void NetEMemory::expr_scan(struct expr_scan_t*tgt) const
|
||||
{
|
||||
tgt->expr_memory(this);
|
||||
@@ -351,6 +427,11 @@ void NetEScope::expr_scan(struct expr_scan_t*tgt) const
|
||||
tgt->expr_scope(this);
|
||||
}
|
||||
|
||||
void NetESFunc::expr_scan(struct expr_scan_t*tgt) const
|
||||
{
|
||||
tgt->expr_sfunc(this);
|
||||
}
|
||||
|
||||
void NetEUFunc::expr_scan(struct expr_scan_t*tgt) const
|
||||
{
|
||||
tgt->expr_ufunc(this);
|
||||
@@ -361,7 +442,7 @@ void NetESignal::expr_scan(struct expr_scan_t*tgt) const
|
||||
tgt->expr_signal(this);
|
||||
}
|
||||
|
||||
void NetESubSignal::expr_scan(struct expr_scan_t*tgt) const
|
||||
void NetEBitSel::expr_scan(struct expr_scan_t*tgt) const
|
||||
{
|
||||
tgt->expr_subsignal(this);
|
||||
}
|
||||
@@ -376,12 +457,12 @@ void NetEUnary::expr_scan(struct expr_scan_t*tgt) const
|
||||
tgt->expr_unary(this);
|
||||
}
|
||||
|
||||
bool emit(ostream&o, const Design*des, const char*type)
|
||||
bool emit(const Design*des, const char*type)
|
||||
{
|
||||
for (unsigned idx = 0 ; target_table[idx] ; idx += 1) {
|
||||
const struct target*tgt = target_table[idx];
|
||||
if (tgt->name == type)
|
||||
return des->emit(o, tgt->meth);
|
||||
if (strcmp(tgt->name, type) == 0)
|
||||
return des->emit(tgt->meth);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -389,135 +470,100 @@ bool emit(ostream&o, const Design*des, const char*type)
|
||||
|
||||
/*
|
||||
* $Log: emit.cc,v $
|
||||
* Revision 1.31 1999/11/28 23:42:02 steve
|
||||
* NetESignal object no longer need to be NetNode
|
||||
* objects. Let them keep a pointer to NetNet objects.
|
||||
* Revision 1.62 2001/08/25 23:50:02 steve
|
||||
* Change the NetAssign_ class to refer to the signal
|
||||
* instead of link into the netlist. This is faster
|
||||
* and uses less space. Make the NetAssignNB carry
|
||||
* the delays instead of the NetAssign_ lval objects.
|
||||
*
|
||||
* Revision 1.30 1999/11/27 19:07:57 steve
|
||||
* Support the creation of scopes.
|
||||
* Change the vvp code generator to support multiple
|
||||
* l-values, i.e. concatenations of part selects.
|
||||
*
|
||||
* Revision 1.29 1999/11/21 00:13:08 steve
|
||||
* Support memories in continuous assignments.
|
||||
* Revision 1.61 2001/07/27 04:51:44 steve
|
||||
* Handle part select expressions as variants of
|
||||
* NetESignal/IVL_EX_SIGNAL objects, instead of
|
||||
* creating new and useless temporary signals.
|
||||
*
|
||||
* Revision 1.28 1999/11/14 23:43:45 steve
|
||||
* Support combinatorial comparators.
|
||||
* Revision 1.60 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.27 1999/11/14 20:24:28 steve
|
||||
* Add support for the LPM_CLSHIFT device.
|
||||
* Revision 1.59 2001/04/22 23:09:46 steve
|
||||
* More UDP consolidation from Stephan Boettcher.
|
||||
*
|
||||
* Revision 1.26 1999/11/04 03:53:26 steve
|
||||
* Patch to synthesize unary ~ and the ternary operator.
|
||||
* Thanks to Larry Doolittle <[email protected]>.
|
||||
* Revision 1.58 2001/04/06 02:28:02 steve
|
||||
* Generate vvp code for functions with ports.
|
||||
*
|
||||
* Add the LPM_MUX device, and integrate it with the
|
||||
* ternary synthesis from Larry. Replace the lpm_mux
|
||||
* generator in t-xnf.cc to use XNF EQU devices to
|
||||
* put muxs into function units.
|
||||
* Revision 1.57 2001/04/02 02:28:12 steve
|
||||
* Generate code for task calls.
|
||||
*
|
||||
* Rewrite elaborate_net for the PETernary class to
|
||||
* also use the LPM_MUX device.
|
||||
* Revision 1.56 2001/03/27 03:31:06 steve
|
||||
* Support error code from target_t::end_design method.
|
||||
*
|
||||
* Revision 1.25 1999/11/01 02:07:40 steve
|
||||
* Add the synth functor to do generic synthesis
|
||||
* and add the LPM_FF device to handle rows of
|
||||
* flip-flops.
|
||||
* Revision 1.55 2000/11/04 01:54:01 steve
|
||||
* Modifications in support of gcc 2.96
|
||||
*
|
||||
* Revision 1.24 1999/10/10 01:59:54 steve
|
||||
* Structural case equals device.
|
||||
* Revision 1.54 2000/09/26 01:35:42 steve
|
||||
* Remove the obsolete NetEIdent class.
|
||||
*
|
||||
* Revision 1.23 1999/09/22 16:57:23 steve
|
||||
* Catch parallel blocks in vvm emit.
|
||||
* Revision 1.53 2000/09/17 21:26:15 steve
|
||||
* Add support for modulus (Eric Aardoom)
|
||||
*
|
||||
* Revision 1.22 1999/09/20 02:21:10 steve
|
||||
* Elaborate parameters in phases.
|
||||
* Revision 1.52 2000/09/02 20:54:20 steve
|
||||
* Rearrange NetAssign to make NetAssign_ separate.
|
||||
*
|
||||
* Revision 1.21 1999/09/15 01:55:06 steve
|
||||
* Elaborate non-blocking assignment to memories.
|
||||
* Revision 1.51 2000/08/14 04:39:56 steve
|
||||
* add th t-dll functions for net_const, net_bufz and processes.
|
||||
*
|
||||
* Revision 1.20 1999/09/03 04:28:38 steve
|
||||
* elaborate the binary plus operator.
|
||||
* Revision 1.50 2000/08/09 03:43:45 steve
|
||||
* Move all file manipulation out of target class.
|
||||
*
|
||||
* Revision 1.19 1999/08/31 22:38:29 steve
|
||||
* Elaborate and emit to vvm procedural functions.
|
||||
* Revision 1.49 2000/08/08 01:50:42 steve
|
||||
* target methods need not take a file stream.
|
||||
*
|
||||
* Revision 1.18 1999/07/17 19:50:59 steve
|
||||
* netlist support for ternary operator.
|
||||
* Revision 1.48 2000/07/30 18:25:43 steve
|
||||
* Rearrange task and function elaboration so that the
|
||||
* NetTaskDef and NetFuncDef functions are created during
|
||||
* signal enaboration, and carry these objects in the
|
||||
* NetScope class instead of the extra, useless map in
|
||||
* the Design class.
|
||||
*
|
||||
* Revision 1.17 1999/07/17 03:39:11 steve
|
||||
* simplified process scan for targets.
|
||||
* Revision 1.47 2000/07/29 16:21:08 steve
|
||||
* Report code generation errors through proc_delay.
|
||||
*
|
||||
* Revision 1.16 1999/07/07 04:20:57 steve
|
||||
* Emit vvm for user defined tasks.
|
||||
* Revision 1.46 2000/07/27 05:13:44 steve
|
||||
* Support elaboration of disable statements.
|
||||
*
|
||||
* Revision 1.15 1999/07/03 02:12:51 steve
|
||||
* Elaborate user defined tasks.
|
||||
* Revision 1.45 2000/05/11 23:37:27 steve
|
||||
* Add support for procedural continuous assignment.
|
||||
*
|
||||
* Revision 1.14 1999/06/19 21:06:16 steve
|
||||
* Elaborate and supprort to vvm the forever
|
||||
* and repeat statements.
|
||||
* Revision 1.44 2000/05/04 03:37:58 steve
|
||||
* Add infrastructure for system functions, move
|
||||
* $time to that structure and add $random.
|
||||
*
|
||||
* Revision 1.13 1999/06/09 03:00:06 steve
|
||||
* Add support for procedural concatenation expression.
|
||||
* Revision 1.43 2000/05/02 03:13:31 steve
|
||||
* Move memories to the NetScope object.
|
||||
*
|
||||
* Revision 1.12 1999/06/06 20:45:38 steve
|
||||
* Add parse and elaboration of non-blocking assignments,
|
||||
* Replace list<PCase::Item*> with an svector version,
|
||||
* Add integer support.
|
||||
* Revision 1.42 2000/05/02 00:58:12 steve
|
||||
* Move signal tables to the NetScope class.
|
||||
*
|
||||
* Revision 1.11 1999/05/12 04:03:19 steve
|
||||
* emit NetAssignMem objects in vvm target.
|
||||
* Revision 1.41 2000/04/23 03:45:24 steve
|
||||
* Add support for the procedural release statement.
|
||||
*
|
||||
* Revision 1.10 1999/05/07 01:21:18 steve
|
||||
* Handle total lack of nodes and signals.
|
||||
* Revision 1.40 2000/04/22 04:20:19 steve
|
||||
* Add support for force assignment.
|
||||
*
|
||||
* Revision 1.9 1999/05/01 02:57:53 steve
|
||||
* Handle much more complex event expressions.
|
||||
* Revision 1.39 2000/04/12 04:23:58 steve
|
||||
* Named events really should be expressed with PEIdent
|
||||
* objects in the pform,
|
||||
*
|
||||
* Revision 1.8 1999/04/25 00:44:10 steve
|
||||
* Core handles subsignal expressions.
|
||||
*
|
||||
* Revision 1.7 1999/04/19 01:59:36 steve
|
||||
* Add memories to the parse and elaboration phases.
|
||||
*
|
||||
* Revision 1.6 1999/02/08 02:49:56 steve
|
||||
* Turn the NetESignal into a NetNode so
|
||||
* that it can connect to the netlist.
|
||||
* Implement the case statement.
|
||||
* Convince t-vvm to output code for
|
||||
* the case statement.
|
||||
*
|
||||
* Revision 1.5 1999/02/01 00:26:49 steve
|
||||
* Carry some line info to the netlist,
|
||||
* Dump line numbers for processes.
|
||||
* Elaborate prints errors about port vector
|
||||
* width mismatch
|
||||
* Emit better handles null statements.
|
||||
*
|
||||
* Revision 1.4 1998/12/01 00:42:14 steve
|
||||
* Elaborate UDP devices,
|
||||
* Support UDP type attributes, and
|
||||
* pass those attributes to nodes that
|
||||
* are instantiated by elaboration,
|
||||
* Put modules into a map instead of
|
||||
* a simple list.
|
||||
*
|
||||
* Revision 1.3 1998/11/09 18:55:34 steve
|
||||
* Add procedural while loops,
|
||||
* Parse procedural for loops,
|
||||
* Add procedural wait statements,
|
||||
* Add constant nodes,
|
||||
* Add XNOR logic gate,
|
||||
* Make vvm output look a bit prettier.
|
||||
*
|
||||
* Revision 1.2 1998/11/07 17:05:05 steve
|
||||
* Handle procedural conditional, and some
|
||||
* of the conditional expressions.
|
||||
*
|
||||
* Elaborate signals and identifiers differently,
|
||||
* allowing the netlist to hold signal information.
|
||||
*
|
||||
* Revision 1.1 1998/11/03 23:28:57 steve
|
||||
* Introduce verilog to CVS.
|
||||
* Handle named events within the mix of net events
|
||||
* and edges. As a unified lot they get caught together.
|
||||
* wait statements are broken into more complex statements
|
||||
* that include a conditional.
|
||||
*
|
||||
* Do not generate NetPEvent or NetNEvent objects in
|
||||
* elaboration. NetEvent, NetEvWait and NetEvProbe
|
||||
* take over those functions in the netlist.
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-1999 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,12 +16,17 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: eval.cc,v 1.12 1999/11/30 04:48:17 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: eval.cc,v 1.21 2001/07/25 03:10:49 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# include <iostream>
|
||||
|
||||
# include "PExpr.h"
|
||||
# include "netlist.h"
|
||||
# include "compiler.h"
|
||||
|
||||
verinum* PExpr::eval_const(const Design*, const string&) const
|
||||
{
|
||||
@@ -81,22 +86,39 @@ verinum* PEBinary::eval_const(const Design*des, const string&path) const
|
||||
res = new verinum(lv % rv, l->len());
|
||||
break;
|
||||
}
|
||||
case 'l': {
|
||||
assert(r->is_defined());
|
||||
unsigned long rv = r->as_ulong();
|
||||
res = new verinum(verinum::V0, l->len());
|
||||
if (rv < res->len()) {
|
||||
unsigned cnt = res->len() - rv;
|
||||
for (unsigned idx = 0 ; idx < cnt ; idx += 1)
|
||||
res->set(idx+rv, l->get(idx));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
delete l;
|
||||
delete r;
|
||||
return 0;
|
||||
}
|
||||
|
||||
delete l;
|
||||
delete r;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Evaluate an identifier as a constant expression. This is only
|
||||
* possible if the identifier is that of a parameter.
|
||||
*/
|
||||
verinum* PEIdent::eval_const(const Design*des, const string&path) const
|
||||
{
|
||||
const NetExpr*expr = des->find_parameter(path, text_);
|
||||
const NetScope*scope = des->find_scope(path);
|
||||
assert(scope);
|
||||
const NetExpr*expr = des->find_parameter(scope, text_);
|
||||
|
||||
if (expr == 0)
|
||||
return 0;
|
||||
@@ -105,7 +127,7 @@ verinum* PEIdent::eval_const(const Design*des, const string&path) const
|
||||
|
||||
if (dynamic_cast<const NetEParam*>(expr)) {
|
||||
cerr << get_line() << ": sorry: I cannot evaluate ``" <<
|
||||
text_ << "'' in this context." << endl;
|
||||
text_ << "'' in this scope: " << scope->name() << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -114,6 +136,12 @@ verinum* PEIdent::eval_const(const Design*des, const string&path) const
|
||||
return new verinum(eval->value());
|
||||
}
|
||||
|
||||
verinum* PEFNumber::eval_const(const Design*, const string&) const
|
||||
{
|
||||
long val = value_->as_long();
|
||||
return new verinum(val);
|
||||
}
|
||||
|
||||
verinum* PENumber::eval_const(const Design*, const string&) const
|
||||
{
|
||||
return new verinum(value());
|
||||
@@ -139,9 +167,72 @@ verinum* PETernary::eval_const(const Design*des, const string&path) const
|
||||
}
|
||||
}
|
||||
|
||||
verinum* PEUnary::eval_const(const Design*des, const string&path) const
|
||||
{
|
||||
verinum*val = expr_->eval_const(des, path);
|
||||
if (val == 0)
|
||||
return 0;
|
||||
|
||||
switch (op_) {
|
||||
case '+':
|
||||
return val;
|
||||
|
||||
case '-': {
|
||||
/* We need to expand the value a bit if we are
|
||||
taking the 2's complement so that we are
|
||||
guaranteed to not overflow. */
|
||||
verinum tmp (0UL, val->len()+1);
|
||||
for (unsigned idx = 0 ; idx < val->len() ; idx += 1)
|
||||
tmp.set(idx, val->get(idx));
|
||||
|
||||
*val = v_not(tmp) + verinum(verinum::V1, 1);
|
||||
val->has_sign(true);
|
||||
return val;
|
||||
}
|
||||
|
||||
}
|
||||
delete val;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* $Log: eval.cc,v $
|
||||
* Revision 1.21 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.20 2001/02/09 02:49:59 steve
|
||||
* Be more clear about scope of failure.
|
||||
*
|
||||
* Revision 1.19 2001/01/27 05:41:48 steve
|
||||
* Fix sign extension of evaluated constants. (PR#91)
|
||||
*
|
||||
* Revision 1.18 2001/01/14 23:04:56 steve
|
||||
* Generalize the evaluation of floating point delays, and
|
||||
* get it working with delay assignment statements.
|
||||
*
|
||||
* Allow parameters to be referenced by hierarchical name.
|
||||
*
|
||||
* Revision 1.17 2001/01/04 04:47:51 steve
|
||||
* Add support for << is signal indices.
|
||||
*
|
||||
* Revision 1.16 2000/12/10 22:01:36 steve
|
||||
* Support decimal constants in behavioral delays.
|
||||
*
|
||||
* Revision 1.15 2000/09/07 22:38:13 steve
|
||||
* Support unary + and - in constants.
|
||||
*
|
||||
* Revision 1.14 2000/03/08 04:36:53 steve
|
||||
* Redesign the implementation of scopes and parameters.
|
||||
* I now generate the scopes and notice the parameters
|
||||
* in a separate pass over the pform. Once the scopes
|
||||
* are generated, I can process overrides and evalutate
|
||||
* paremeters before elaboration begins.
|
||||
*
|
||||
* Revision 1.13 2000/02/23 02:56:54 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.12 1999/11/30 04:48:17 steve
|
||||
* Handle evaluation of ternary during elaboration.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 2001 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
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: eval_rconst.cc,v 1.2 2001/07/25 03:10:49 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# include "PExpr.h"
|
||||
|
||||
verireal* PExpr::eval_rconst(const Design*, const NetScope*) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
verireal* PEFNumber::eval_rconst(const Design*, const NetScope*) const
|
||||
{
|
||||
verireal*res = new verireal;
|
||||
*res = *value_;
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: eval_rconst.cc,v $
|
||||
* Revision 1.2 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.1 2001/01/14 23:04:56 steve
|
||||
* Generalize the evaluation of floating point delays, and
|
||||
* get it working with delay assignment statements.
|
||||
*
|
||||
* Allow parameters to be referenced by hierarchical name.
|
||||
*
|
||||
*/
|
||||
|
||||
+824
-17
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1999-2000 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,10 +16,14 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: eval_tree.cc,v 1.6 1999/10/22 23:57:53 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: eval_tree.cc,v 1.26 2001/07/25 03:10:49 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# include <iostream>
|
||||
|
||||
# include "netlist.h"
|
||||
|
||||
NetExpr* NetExpr::eval_tree()
|
||||
@@ -72,6 +76,72 @@ NetEConst* NetEBAdd::eval_tree()
|
||||
return new NetEConst(val);
|
||||
}
|
||||
|
||||
NetEConst* NetEBBits::eval_tree()
|
||||
{
|
||||
eval_sub_tree_();
|
||||
|
||||
NetEConst*lc = dynamic_cast<NetEConst*>(left_);
|
||||
if (lc == 0) return 0;
|
||||
NetEConst*rc = dynamic_cast<NetEConst*>(right_);
|
||||
if (rc == 0) return 0;
|
||||
|
||||
verinum lval = lc->value();
|
||||
verinum rval = rc->value();
|
||||
|
||||
unsigned lwid = lc->expr_width();
|
||||
if (lwid == 0) lwid = lval.len();
|
||||
|
||||
unsigned rwid = rc->expr_width();
|
||||
if (rwid == 0) rwid = rval.len();
|
||||
|
||||
unsigned wid = expr_width();
|
||||
if (wid == 0)
|
||||
wid = (rwid > lwid)? rwid : lwid;
|
||||
|
||||
verinum res (verinum::V0, wid);
|
||||
|
||||
if (lwid > wid)
|
||||
lwid = wid;
|
||||
if (rwid > wid)
|
||||
rwid = wid;
|
||||
|
||||
switch (op()) {
|
||||
|
||||
case '|': {
|
||||
unsigned cnt = lwid;
|
||||
if (cnt > wid) cnt = wid;
|
||||
if (cnt > rwid) cnt = rwid;
|
||||
for (unsigned idx = 0 ; idx < cnt ; idx += 1)
|
||||
res.set(idx, lval.get(idx) | rval.get(idx));
|
||||
|
||||
if (lwid < rwid)
|
||||
for (unsigned idx = lwid ; idx < rwid ; idx += 1)
|
||||
res.set(idx, lval.get(idx));
|
||||
|
||||
if (rwid < lwid)
|
||||
for (unsigned idx = rwid ; idx < lwid ; idx += 1)
|
||||
res.set(idx, rval.get(idx));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case '&': {
|
||||
unsigned cnt = lwid;
|
||||
if (cnt > wid) cnt = wid;
|
||||
if (cnt > rwid) cnt = rwid;
|
||||
for (unsigned idx = 0 ; idx < cnt ; idx += 1)
|
||||
res.set(idx, lval.get(idx) & rval.get(idx));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return new NetEConst(res);
|
||||
}
|
||||
|
||||
NetEConst* NetEBComp::eval_eqeq_()
|
||||
{
|
||||
NetEConst*l = dynamic_cast<NetEConst*>(left_);
|
||||
@@ -95,12 +165,60 @@ NetEConst* NetEBComp::eval_eqeq_()
|
||||
}
|
||||
|
||||
|
||||
NetEConst* NetEBComp::eval_less_()
|
||||
{
|
||||
NetEConst*r = dynamic_cast<NetEConst*>(right_);
|
||||
if (r == 0) return 0;
|
||||
|
||||
verinum rv = r->value();
|
||||
if (! rv.is_defined()) {
|
||||
verinum result(verinum::Vx, 1);
|
||||
return new NetEConst(result);
|
||||
}
|
||||
|
||||
/* Detect the case where the right side is greater that or
|
||||
equal to the largest value the left side can possibly
|
||||
have. */
|
||||
assert(left_->expr_width() > 0);
|
||||
verinum lv (verinum::V1, left_->expr_width());
|
||||
if (lv < rv) {
|
||||
verinum result(verinum::V1, 1);
|
||||
return new NetEConst(result);
|
||||
}
|
||||
|
||||
/* Now go on to the normal test of the values. */
|
||||
NetEConst*l = dynamic_cast<NetEConst*>(left_);
|
||||
if (l == 0) return 0;
|
||||
lv = l->value();
|
||||
if (! lv.is_defined()) {
|
||||
verinum result(verinum::Vx, 1);
|
||||
return new NetEConst(result);
|
||||
}
|
||||
|
||||
if (lv.has_sign() && rv.has_sign() && (lv.as_long() < rv.as_long())) {
|
||||
verinum result(verinum::V1, 1);
|
||||
return new NetEConst(result);
|
||||
}
|
||||
|
||||
if (lv.as_ulong() < rv.as_ulong()) {
|
||||
verinum result(verinum::V1, 1);
|
||||
return new NetEConst(result);
|
||||
}
|
||||
|
||||
verinum result(verinum::V0, 1);
|
||||
return new NetEConst(result);
|
||||
}
|
||||
|
||||
NetEConst* NetEBComp::eval_leeq_()
|
||||
{
|
||||
NetEConst*r = dynamic_cast<NetEConst*>(right_);
|
||||
if (r == 0) return 0;
|
||||
|
||||
verinum rv = r->value();
|
||||
if (! rv.is_defined()) {
|
||||
verinum result(verinum::Vx, 1);
|
||||
return new NetEConst(result);
|
||||
}
|
||||
|
||||
/* Detect the case where the right side is greater that or
|
||||
equal to the largest value the left side can possibly
|
||||
@@ -112,30 +230,388 @@ NetEConst* NetEBComp::eval_leeq_()
|
||||
return new NetEConst(result);
|
||||
}
|
||||
|
||||
return 0;
|
||||
/* Now go on to the normal test of the values. */
|
||||
NetEConst*l = dynamic_cast<NetEConst*>(left_);
|
||||
if (l == 0) return 0;
|
||||
lv = l->value();
|
||||
if (! lv.is_defined()) {
|
||||
verinum result(verinum::Vx, 1);
|
||||
return new NetEConst(result);
|
||||
}
|
||||
|
||||
if (lv.has_sign() && rv.has_sign() && (lv.as_long() <= rv.as_long())) {
|
||||
verinum result(verinum::V1, 1);
|
||||
return new NetEConst(result);
|
||||
}
|
||||
|
||||
if (lv.as_ulong() <= rv.as_ulong()) {
|
||||
verinum result(verinum::V1, 1);
|
||||
return new NetEConst(result);
|
||||
}
|
||||
|
||||
verinum result(verinum::V0, 1);
|
||||
return new NetEConst(result);
|
||||
}
|
||||
|
||||
NetEConst* NetEBComp::eval_gt_()
|
||||
{
|
||||
NetEConst*l = dynamic_cast<NetEConst*>(left_);
|
||||
if (l == 0) return 0;
|
||||
|
||||
verinum lv = l->value();
|
||||
if (! lv.is_defined()) {
|
||||
verinum result(verinum::Vx, 1);
|
||||
return new NetEConst(result);
|
||||
}
|
||||
|
||||
/* Detect the case where the left side is greater than the
|
||||
largest value the right side can possibly have. */
|
||||
assert(right_->expr_width() > 0);
|
||||
verinum rv (verinum::V1, right_->expr_width());
|
||||
if (lv > rv) {
|
||||
verinum result(verinum::V1, 1);
|
||||
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;
|
||||
rv = r->value();
|
||||
if (! rv.is_defined()) {
|
||||
verinum result(verinum::Vx, 1);
|
||||
return new NetEConst(result);
|
||||
}
|
||||
|
||||
if (lv.has_sign() && rv.has_sign() && (lv.as_long() > rv.as_long())) {
|
||||
verinum result(verinum::V1, 1);
|
||||
return new NetEConst(result);
|
||||
}
|
||||
|
||||
if (lv.as_ulong() > rv.as_ulong()) {
|
||||
verinum result(verinum::V1, 1);
|
||||
return new NetEConst(result);
|
||||
}
|
||||
|
||||
verinum result(verinum::V0, 1);
|
||||
return new NetEConst(result);
|
||||
}
|
||||
|
||||
NetEConst* NetEBComp::eval_gteq_()
|
||||
{
|
||||
NetEConst*l = dynamic_cast<NetEConst*>(left_);
|
||||
if (l == 0) return 0;
|
||||
|
||||
verinum lv = l->value();
|
||||
if (! lv.is_defined()) {
|
||||
verinum result(verinum::Vx, 1);
|
||||
return new NetEConst(result);
|
||||
}
|
||||
|
||||
/* Detect the case where the left side is greater than the
|
||||
largest value the right side can possibly have. */
|
||||
assert(right_->expr_width() > 0);
|
||||
verinum rv (verinum::V1, right_->expr_width());
|
||||
if (lv >= rv) {
|
||||
verinum result(verinum::V1, 1);
|
||||
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;
|
||||
rv = r->value();
|
||||
if (! rv.is_defined()) {
|
||||
verinum result(verinum::Vx, 1);
|
||||
return new NetEConst(result);
|
||||
}
|
||||
|
||||
if (lv.has_sign() && rv.has_sign() && (lv.as_long() >= rv.as_long())) {
|
||||
verinum result(verinum::V1, 1);
|
||||
return new NetEConst(result);
|
||||
}
|
||||
|
||||
if (lv.as_ulong() >= rv.as_ulong()) {
|
||||
verinum result(verinum::V1, 1);
|
||||
return new NetEConst(result);
|
||||
}
|
||||
|
||||
verinum result(verinum::V0, 1);
|
||||
return new NetEConst(result);
|
||||
}
|
||||
|
||||
NetEConst* NetEBComp::eval_neeq_()
|
||||
{
|
||||
NetEConst*l = dynamic_cast<NetEConst*>(left_);
|
||||
if (l == 0) return 0;
|
||||
NetEConst*r = dynamic_cast<NetEConst*>(right_);
|
||||
if (r == 0) return 0;
|
||||
|
||||
const verinum&lv = l->value();
|
||||
const verinum&rv = r->value();
|
||||
|
||||
verinum::V res = verinum::V0;
|
||||
unsigned top = lv.len();
|
||||
if (rv.len() < top)
|
||||
top = rv.len();
|
||||
|
||||
for (unsigned idx = 0 ; idx < top ; idx += 1) {
|
||||
|
||||
switch (lv.get(idx)) {
|
||||
|
||||
case verinum::Vx:
|
||||
case verinum::Vz:
|
||||
res = verinum::Vx;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (rv.get(idx)) {
|
||||
|
||||
case verinum::Vx:
|
||||
case verinum::Vz:
|
||||
res = verinum::Vx;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (res == verinum::Vx)
|
||||
break;
|
||||
|
||||
if (rv.get(idx) != lv.get(idx))
|
||||
res = verinum::V1;
|
||||
}
|
||||
|
||||
if (res != verinum::Vx) {
|
||||
for (unsigned idx = top ; idx < lv.len() ; idx += 1)
|
||||
switch (lv.get(idx)) {
|
||||
|
||||
case verinum::Vx:
|
||||
case verinum::Vz:
|
||||
res = verinum::Vx;
|
||||
break;
|
||||
|
||||
case verinum::V1:
|
||||
if (res != verinum::Vx)
|
||||
res = verinum::V1;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
for (unsigned idx = top ; idx < rv.len() ; idx += 1)
|
||||
switch (rv.get(idx)) {
|
||||
|
||||
case verinum::Vx:
|
||||
case verinum::Vz:
|
||||
res = verinum::Vx;
|
||||
break;
|
||||
|
||||
case verinum::V1:
|
||||
if (res != verinum::Vx)
|
||||
res = verinum::V1;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return new NetEConst(verinum(res));
|
||||
}
|
||||
|
||||
NetEConst* NetEBComp::eval_eqeqeq_()
|
||||
{
|
||||
NetEConst*l = dynamic_cast<NetEConst*>(left_);
|
||||
if (l == 0) return 0;
|
||||
NetEConst*r = dynamic_cast<NetEConst*>(right_);
|
||||
if (r == 0) return 0;
|
||||
|
||||
const verinum&lv = l->value();
|
||||
const verinum&rv = r->value();
|
||||
|
||||
verinum::V res = verinum::V1;
|
||||
|
||||
unsigned cnt = lv.len();
|
||||
if (cnt > rv.len())
|
||||
cnt = rv.len();
|
||||
|
||||
for (unsigned idx = 0 ; idx < cnt ; idx += 1)
|
||||
if (lv.get(idx) != rv.get(idx))
|
||||
res = verinum::V0;
|
||||
|
||||
for (unsigned idx = cnt ; idx < lv.len() ; idx += 1)
|
||||
if (lv.get(idx) != verinum::V0)
|
||||
res = verinum::V0;
|
||||
|
||||
for (unsigned idx = cnt ; idx < rv.len() ; idx += 1)
|
||||
if (rv.get(idx) != verinum::V0)
|
||||
res = verinum::V0;
|
||||
|
||||
return new NetEConst(verinum(res, 1));
|
||||
}
|
||||
|
||||
NetEConst* NetEBComp::eval_neeqeq_()
|
||||
{
|
||||
NetEConst*tmp = eval_eqeqeq_();
|
||||
if (tmp == 0)
|
||||
return 0;
|
||||
|
||||
NetEConst*res;
|
||||
|
||||
if (tmp->value().get(0) == verinum::V0)
|
||||
res = new NetEConst(verinum(verinum::V1,1));
|
||||
else
|
||||
res = new NetEConst(verinum(verinum::V0,1));
|
||||
|
||||
delete tmp;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
NetEConst* NetEBComp::eval_tree()
|
||||
{
|
||||
eval_sub_tree_();
|
||||
|
||||
switch (op_) {
|
||||
case 'e':
|
||||
case 'E': // Case equality (===)
|
||||
return eval_eqeqeq_();
|
||||
|
||||
case 'e': // Equality (==)
|
||||
return eval_eqeq_();
|
||||
|
||||
case 'L':
|
||||
case 'G': // >=
|
||||
return eval_gteq_();
|
||||
|
||||
case 'L': // <=
|
||||
return eval_leeq_();
|
||||
|
||||
case 'N': // Cse inequality (!==)
|
||||
return eval_neeqeq_();
|
||||
|
||||
case 'n': // not-equal (!=)
|
||||
return eval_neeq_();
|
||||
|
||||
case '<': // Less than
|
||||
return eval_less_();
|
||||
|
||||
case '>': // Greater then
|
||||
return eval_gt_();
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The NetEBDiv operator includes the / and % opeators. First evaluate
|
||||
* the sub-expressions, then perform the required operation.
|
||||
*/
|
||||
NetEConst* NetEBDiv::eval_tree()
|
||||
{
|
||||
eval_sub_tree_();
|
||||
|
||||
NetEConst*lc = dynamic_cast<NetEConst*>(left_);
|
||||
if (lc == 0) return 0;
|
||||
NetEConst*rc = dynamic_cast<NetEConst*>(right_);
|
||||
if (rc == 0) return 0;
|
||||
|
||||
verinum lval = lc->value();
|
||||
verinum rval = rc->value();
|
||||
|
||||
switch (op_) {
|
||||
case '/':
|
||||
return new NetEConst(lval / rval);
|
||||
|
||||
case '%':
|
||||
return new NetEConst(lval % rval);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetEConst* NetEBLogic::eval_tree()
|
||||
{
|
||||
eval_sub_tree_();
|
||||
return 0;
|
||||
NetEConst*lc = dynamic_cast<NetEConst*>(left_);
|
||||
if (lc == 0) return 0;
|
||||
NetEConst*rc = dynamic_cast<NetEConst*>(right_);
|
||||
if (rc == 0) return 0;
|
||||
|
||||
verinum::V lv = verinum::V0;
|
||||
verinum::V rv = verinum::V0;
|
||||
|
||||
verinum v = lc->value();
|
||||
for (unsigned idx = 0 ; idx < v.len() ; idx += 1)
|
||||
if (v.get(idx) == verinum::V1)
|
||||
lv = verinum::V1;
|
||||
|
||||
if (lv == verinum::V0)
|
||||
for (unsigned idx = 0 ; idx < v.len() ; idx += 1)
|
||||
if (v.get(idx) != verinum::V0)
|
||||
lv = verinum::Vx;
|
||||
|
||||
v = rc->value();
|
||||
for (unsigned idx = 0 ; idx < v.len() ; idx += 1)
|
||||
if (v.get(idx) == verinum::V1)
|
||||
rv = verinum::V1;
|
||||
|
||||
if (lv == verinum::V0)
|
||||
for (unsigned idx = 0 ; idx < v.len() ; idx += 1)
|
||||
if (v.get(idx) != verinum::V0)
|
||||
rv = verinum::Vx;
|
||||
|
||||
verinum::V res;
|
||||
switch (op_) {
|
||||
case 'a': { // Logical AND (&&)
|
||||
if ((lv == verinum::V0) || (rv == verinum::V0))
|
||||
res = verinum::V0;
|
||||
|
||||
else if ((lv == verinum::V1) && (rv == verinum::V1))
|
||||
res = verinum::V1;
|
||||
|
||||
else
|
||||
res = verinum::Vx;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 'o': { // Logical OR (||)
|
||||
if ((lv == verinum::V1) || (rv == verinum::V1))
|
||||
res = verinum::V1;
|
||||
|
||||
else if ((lv == verinum::V0) && (rv == verinum::V0))
|
||||
res = verinum::V0;
|
||||
|
||||
else
|
||||
res = verinum::Vx;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return new NetEConst(verinum(res, 1));
|
||||
}
|
||||
|
||||
NetEConst* NetEBMult::eval_tree()
|
||||
{
|
||||
eval_sub_tree_();
|
||||
|
||||
NetEConst*lc = dynamic_cast<NetEConst*>(left_);
|
||||
if (lc == 0) return 0;
|
||||
NetEConst*rc = dynamic_cast<NetEConst*>(right_);
|
||||
if (rc == 0) return 0;
|
||||
|
||||
verinum lval = lc->value();
|
||||
verinum rval = rc->value();
|
||||
|
||||
return new NetEConst(lval * rval);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -157,32 +633,57 @@ NetEConst* NetEBShift::eval_tree()
|
||||
|
||||
verinum rv = re->value();
|
||||
verinum lv = le->value();
|
||||
|
||||
/* Calculate the width of the result. If it is not fixed, then
|
||||
get it from the left operand. */
|
||||
unsigned wid = expr_width();
|
||||
if (wid == 0)
|
||||
wid = left_->expr_width();
|
||||
|
||||
if (rv.is_defined()) {
|
||||
|
||||
unsigned wid = expr_width();
|
||||
unsigned shift = rv.as_ulong();
|
||||
|
||||
|
||||
assert(wid);
|
||||
verinum nv (verinum::V0, wid);
|
||||
|
||||
if (op() == 'r')
|
||||
for (unsigned idx = 0 ; idx < (wid-shift) ; idx += 1)
|
||||
if (op() == 'r') {
|
||||
unsigned cnt = wid;
|
||||
if (cnt > nv.len())
|
||||
cnt = nv.len();
|
||||
if (shift >= lv.len())
|
||||
cnt = 0;
|
||||
else if (cnt > (lv.len()-shift))
|
||||
cnt = (lv.len()-shift);
|
||||
for (unsigned idx = 0 ; idx < cnt ; idx += 1)
|
||||
nv.set(idx, lv[idx+shift]);
|
||||
|
||||
else
|
||||
for (unsigned idx = 0 ; idx < (wid-shift) ; idx += 1)
|
||||
} else {
|
||||
unsigned cnt = wid;
|
||||
if (cnt > lv.len())
|
||||
cnt = lv.len();
|
||||
if (shift >= nv.len())
|
||||
cnt = 0;
|
||||
else if (cnt > (nv.len()-shift))
|
||||
cnt = nv.len() - shift;
|
||||
|
||||
for (unsigned idx = 0 ; idx < cnt ; idx += 1)
|
||||
nv.set(idx+shift, lv[idx]);
|
||||
}
|
||||
|
||||
res = new NetEConst(nv);
|
||||
|
||||
} else {
|
||||
verinum nv (verinum::Vx, expr_width());
|
||||
assert(wid);
|
||||
verinum nv (verinum::Vx, wid);
|
||||
res = new NetEConst(nv);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
NetExpr* NetEConcat::eval_tree()
|
||||
NetEConst* NetEConcat::eval_tree()
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) {
|
||||
|
||||
@@ -207,6 +708,18 @@ NetExpr* NetEConcat::eval_tree()
|
||||
}
|
||||
}
|
||||
|
||||
// Handle the special case that the repeat expression is
|
||||
// zero. In this case, just return a 0 value with the expected
|
||||
// width.
|
||||
if (repeat_ == 0) {
|
||||
verinum val (verinum::V0, expr_width());
|
||||
NetEConst*res = new NetEConst(val);
|
||||
res->set_width(val.len());
|
||||
return res;
|
||||
}
|
||||
|
||||
// Figure out the width of the repeated expression, and make a
|
||||
// verinum to hold the result.
|
||||
unsigned gap = expr_width() / repeat_;
|
||||
verinum val (verinum::Vx, repeat_ * gap);
|
||||
|
||||
@@ -235,7 +748,15 @@ NetExpr* NetEParam::eval_tree()
|
||||
if (des_ == 0)
|
||||
return 0;
|
||||
|
||||
const NetExpr*expr = des_->find_parameter(path_, name_);
|
||||
assert(scope_);
|
||||
const NetExpr*expr = scope_->get_parameter(name_);
|
||||
if (expr == 0) {
|
||||
cerr << get_line() << ": internal error: Unable to match "
|
||||
<< "parameter " << name_ << " in scope "
|
||||
<< scope_->name() << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(expr);
|
||||
|
||||
NetExpr*nexpr = expr->dup_expr();
|
||||
@@ -256,12 +777,298 @@ NetExpr* NetEParam::eval_tree()
|
||||
|
||||
// The result can be saved as the value of the parameter for
|
||||
// future reference, and return a copy to the caller.
|
||||
des_->set_parameter(path_+"."+name_, res);
|
||||
scope_->set_parameter(name_, res);
|
||||
return res->dup_expr();
|
||||
}
|
||||
|
||||
/*
|
||||
* A ternary expression evaluation is controlled by the condition
|
||||
* expression. If the condition evaluates to true or false, then
|
||||
* return the evaluated true or false expression. If the condition
|
||||
* evaluates to x or z, then merge the constant bits of the true and
|
||||
* false expressions.
|
||||
*/
|
||||
NetExpr* NetETernary::eval_tree()
|
||||
{
|
||||
NetExpr*tmp;
|
||||
|
||||
/* Evaluate the cond_ to a constant. If it already is a
|
||||
constant, then there is nothing to do. */
|
||||
|
||||
NetEConst*c = dynamic_cast<NetEConst*>(cond_);
|
||||
if (c == 0) {
|
||||
tmp = cond_->eval_tree();
|
||||
c = dynamic_cast<NetEConst*>(tmp);
|
||||
if (c == 0)
|
||||
return 0;
|
||||
|
||||
assert(cond_ != c);
|
||||
delete cond_;
|
||||
cond_ = c;
|
||||
}
|
||||
|
||||
/* If the condition is 1 or 0, return the true or false
|
||||
expression. Try to evaluate the expression down as far as
|
||||
we can. */
|
||||
|
||||
if (c->value().get(0) == verinum::V1) {
|
||||
tmp = dynamic_cast<NetEConst*>(true_val_);
|
||||
if (tmp) return tmp->dup_expr();
|
||||
|
||||
tmp = true_val_->eval_tree();
|
||||
if (tmp) {
|
||||
delete true_val_;
|
||||
true_val_ = tmp;
|
||||
}
|
||||
return true_val_->dup_expr();
|
||||
}
|
||||
|
||||
if (c->value().get(0) == verinum::V0) {
|
||||
tmp = dynamic_cast<NetEConst*>(false_val_);
|
||||
if (tmp) return tmp->dup_expr();
|
||||
|
||||
tmp = false_val_->eval_tree();
|
||||
if (tmp) {
|
||||
delete false_val_;
|
||||
false_val_ = tmp;
|
||||
}
|
||||
return false_val_->dup_expr();
|
||||
}
|
||||
|
||||
|
||||
/* Here we have a more complex case. We need to evaluate both
|
||||
expressions down to constants then compare the values to
|
||||
build up a constant result. */
|
||||
|
||||
NetEConst*t = dynamic_cast<NetEConst*>(true_val_);
|
||||
if (t == 0) {
|
||||
tmp = true_val_->eval_tree();
|
||||
t = dynamic_cast<NetEConst*>(tmp);
|
||||
if (t == 0)
|
||||
return 0;
|
||||
|
||||
delete true_val_;
|
||||
true_val_ = t;
|
||||
}
|
||||
|
||||
|
||||
NetEConst*f = dynamic_cast<NetEConst*>(false_val_);
|
||||
if (f == 0) {
|
||||
tmp = false_val_->eval_tree();
|
||||
f = dynamic_cast<NetEConst*>(tmp);
|
||||
if (f == 0)
|
||||
return 0;
|
||||
|
||||
delete false_val_;
|
||||
false_val_ = f;
|
||||
}
|
||||
|
||||
unsigned size = t->expr_width();
|
||||
assert(size == f->expr_width());
|
||||
|
||||
verinum val (verinum::V0, size);
|
||||
for (unsigned idx = 0 ; idx < size ; idx += 1) {
|
||||
verinum::V tv = t->value().get(idx);
|
||||
verinum::V fv = f->value().get(idx);
|
||||
|
||||
if (tv == fv)
|
||||
val.set(idx, tv);
|
||||
else
|
||||
val.set(idx, verinum::Vx);
|
||||
}
|
||||
|
||||
NetEConst*rc = new NetEConst(val);
|
||||
rc->set_line(*this);
|
||||
return rc;
|
||||
}
|
||||
|
||||
void NetEUnary::eval_expr_()
|
||||
{
|
||||
if (dynamic_cast<NetEConst*>(expr_))
|
||||
return;
|
||||
|
||||
NetExpr*oper = expr_->eval_tree();
|
||||
if (oper == 0)
|
||||
return;
|
||||
|
||||
delete expr_;
|
||||
expr_ = oper;
|
||||
}
|
||||
|
||||
NetEConst* NetEUnary::eval_tree()
|
||||
{
|
||||
eval_expr_();
|
||||
NetEConst*rval = dynamic_cast<NetEConst*>(expr_);
|
||||
if (rval == 0)
|
||||
return 0;
|
||||
|
||||
verinum val = rval->value();
|
||||
|
||||
switch (op_) {
|
||||
|
||||
|
||||
case '~': {
|
||||
/* Bitwise not is even simpler then logical
|
||||
not. Just invert all the bits of the operand and
|
||||
make the new value with the same dimensions. */
|
||||
for (unsigned idx = 0 ; idx < val.len() ; idx += 1)
|
||||
switch (val.get(idx)) {
|
||||
case verinum::V0:
|
||||
val.set(idx, verinum::V1);
|
||||
break;
|
||||
case verinum::V1:
|
||||
val.set(idx, verinum::V0);
|
||||
break;
|
||||
default:
|
||||
val.set(idx, verinum::Vx);
|
||||
}
|
||||
|
||||
return new NetEConst(val);
|
||||
}
|
||||
|
||||
default:
|
||||
delete rval;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
NetEConst* NetEUBits::eval_tree()
|
||||
{
|
||||
return NetEUnary::eval_tree();
|
||||
}
|
||||
|
||||
NetEConst* NetEUReduce::eval_tree()
|
||||
{
|
||||
eval_expr_();
|
||||
NetEConst*rval = dynamic_cast<NetEConst*>(expr_);
|
||||
if (rval == 0)
|
||||
return 0;
|
||||
|
||||
verinum val = rval->value();
|
||||
verinum::V res;
|
||||
|
||||
switch (op_) {
|
||||
|
||||
case '!': {
|
||||
/* Evaluate the unary logical not by first scanning
|
||||
the operand value for V1 and Vx bits. If we find
|
||||
any V1 bits we know that the value is TRUE, so
|
||||
the result of ! is V0. If there are no V1 bits
|
||||
but there are some Vx/Vz bits, the result is
|
||||
unknown. Otherwise, the result is V1. */
|
||||
unsigned v1 = 0, vx = 0;
|
||||
for (unsigned idx = 0 ; idx < val.len() ; idx += 1) {
|
||||
switch (val.get(idx)) {
|
||||
case verinum::V0:
|
||||
break;
|
||||
case verinum::V1:
|
||||
v1 += 1;
|
||||
break;
|
||||
default:
|
||||
vx += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
res = v1? verinum::V0 : (vx? verinum::Vx : verinum::V1);
|
||||
}
|
||||
|
||||
case '&': {
|
||||
res = verinum::V1;
|
||||
for (unsigned idx = 0 ; idx < val.len() ; idx += 1)
|
||||
res = res & val.get(idx);
|
||||
break;
|
||||
}
|
||||
|
||||
case '|': {
|
||||
res = verinum::V0;
|
||||
for (unsigned idx = 0 ; idx < val.len() ; idx += 1)
|
||||
res = res | val.get(idx);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return new NetEConst(verinum(res, 1));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* $Log: eval_tree.cc,v $
|
||||
* Revision 1.26 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.25 2001/07/16 20:41:41 steve
|
||||
* Handle 0 counts in repeat concatenation.
|
||||
*
|
||||
* Revision 1.24 2001/02/10 20:29:39 steve
|
||||
* In the context of range declarations, use elab_and_eval instead
|
||||
* of the less robust eval_const methods.
|
||||
*
|
||||
* Revision 1.23 2001/02/09 05:44:23 steve
|
||||
* support evaluation of constant < in expressions.
|
||||
*
|
||||
* Revision 1.22 2001/02/07 02:46:31 steve
|
||||
* Support constant evaluation of / and % (PR#124)
|
||||
*
|
||||
* Revision 1.21 2001/01/14 23:04:56 steve
|
||||
* Generalize the evaluation of floating point delays, and
|
||||
* get it working with delay assignment statements.
|
||||
*
|
||||
* Allow parameters to be referenced by hierarchical name.
|
||||
*
|
||||
* Revision 1.20 2001/01/04 16:49:50 steve
|
||||
* Evaluate constant === and !== expressions.
|
||||
*
|
||||
* Revision 1.19 2001/01/04 04:28:42 steve
|
||||
* Evaluate constant logical && and ||.
|
||||
*
|
||||
* Revision 1.18 2001/01/02 04:21:14 steve
|
||||
* Support a bunch of unary operators in parameter expressions.
|
||||
*
|
||||
* Revision 1.17 2001/01/02 03:23:40 steve
|
||||
* Evaluate constant &, | and unary ~.
|
||||
*
|
||||
* Revision 1.16 2001/01/01 21:49:33 steve
|
||||
* Fix shift and ternary operators in parameter expressions (PR#86)
|
||||
*
|
||||
* Revision 1.15 2000/12/16 20:00:17 steve
|
||||
* Handle non-constant l-values.
|
||||
*
|
||||
* Revision 1.14 2000/12/16 19:03:30 steve
|
||||
* Evaluate <= and ?: in parameter expressions (PR#81)
|
||||
*
|
||||
* Revision 1.13 2000/09/29 04:42:56 steve
|
||||
* Cnstant evaluation of NE.
|
||||
*
|
||||
* Revision 1.12 2000/09/27 18:28:37 steve
|
||||
* multiply in parameter expressions.
|
||||
*
|
||||
* Revision 1.11 2000/07/07 04:53:54 steve
|
||||
* Add support for non-constant delays in delay statements,
|
||||
* Support evaluating ! in constant expressions, and
|
||||
* move some code from netlist.cc to net_proc.cc.
|
||||
*
|
||||
* Revision 1.10 2000/04/28 18:43:23 steve
|
||||
* integer division in expressions properly get width.
|
||||
*
|
||||
* Revision 1.9 2000/03/08 04:36:53 steve
|
||||
* Redesign the implementation of scopes and parameters.
|
||||
* I now generate the scopes and notice the parameters
|
||||
* in a separate pass over the pform. Once the scopes
|
||||
* are generated, I can process overrides and evalutate
|
||||
* paremeters before elaboration begins.
|
||||
*
|
||||
* Revision 1.8 2000/02/23 02:56:54 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.7 2000/01/13 03:35:35 steve
|
||||
* Multiplication all the way to simulation.
|
||||
*
|
||||
* Revision 1.6 1999/10/22 23:57:53 steve
|
||||
* do the <= in bits, not numbers.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright (c) 2000 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
|
||||
*/
|
||||
|
||||
/*
|
||||
* This source file demonstrates how to synthesize CLB flip-flops from
|
||||
* Icarus Verilog, including giving the device an initial value.
|
||||
*
|
||||
* To compile this for XNF, try a command like this:
|
||||
*
|
||||
* iverilog -txnf -ppart=XC4010XLPQ160 -pncf=clbff.ncf -oclbff.xnf clbff.v
|
||||
*
|
||||
* That command causes an clbff.xnf and clbff.ncf file to be created.
|
||||
* Next, make the clbff.ngd file with the command:
|
||||
*
|
||||
* xnf2ngd -l xilinxun -u clbff.xnf clbff.ngo
|
||||
* ngdbuild clbff.ngo clbff.ngd
|
||||
*
|
||||
* Finally, map the file to fully render it in the target part. The
|
||||
* par command is the step that actually optimizes the design and tries
|
||||
* to meet timing constraints.
|
||||
*
|
||||
* map -o map.ncd clbff.ngd
|
||||
* par -w map.ncd clbff.ncd
|
||||
*
|
||||
* At this point, you can use the FPGA Editor to edit the clbff.ncd
|
||||
* file. Notice that the design uses two CLB flip-flops (possibly in
|
||||
* the same CLB) with their outputs ANDed together. If you go into the
|
||||
* block editor, you will see that the FF connected to main/Q<0> is
|
||||
* configured so start up reset, and the FF connected to main/Q<1> is
|
||||
* configured to start up set.
|
||||
*/
|
||||
|
||||
module main;
|
||||
|
||||
wire clk, iclk;
|
||||
wire i0, i1;
|
||||
wire out;
|
||||
|
||||
wire [1:0] D = {i1, i0};
|
||||
|
||||
// This statement declares Q to be a 2 bit reg vector. The
|
||||
// initial assignment will cause the synthesized device to take
|
||||
// on an initial value specified here. Without the assignment,
|
||||
// the initial value is unspecified. (Verilog simulates it as 2'bx.)
|
||||
reg [1:0] Q = 2'b10;
|
||||
|
||||
// This simple logic gate get turned into a function unit.
|
||||
// The par program will map this into a CLB F or G unit.
|
||||
and (out, Q[0], Q[1]);
|
||||
|
||||
// This creates a global clock buffer. Notice how I attach an
|
||||
// attribute to the named gate to force it to be mapped to the
|
||||
// desired XNF device. This device will not be pulled into the
|
||||
// IOB associated with iclk because of the attribute.
|
||||
buf gbuf(clk, iclk);
|
||||
$attribute(gbuf, "XNF-LCA", "GCLK:O,I");
|
||||
|
||||
// This is mapped to a DFF. Since Q and D are two bits wide, the
|
||||
// code generator actually makes two DFF devices that share a
|
||||
// clock input.
|
||||
always @(posedge clk) Q <= D;
|
||||
|
||||
// These attribute commands assign pins to the listed wires.
|
||||
// This can be done to wires and registers, as internally both
|
||||
// are treated as named signals.
|
||||
$attribute(out, "PAD", "o150");
|
||||
$attribute(i0, "PAD", "i152");
|
||||
$attribute(i1, "PAD", "i153");
|
||||
$attribute(iclk,"PAD", "i154");
|
||||
|
||||
endmodule /* main */
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) 1998 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
|
||||
*/
|
||||
|
||||
/*
|
||||
* Here we have the canonical "Hello, World" program written in Verilog.
|
||||
* We simply print to the program output a simple message. This example
|
||||
* demonstrates the process of compiling and executing a program with
|
||||
* Icarus Verilog.
|
||||
*
|
||||
* Compile this program with the command:
|
||||
*
|
||||
* iverilog -ohello hello.vl
|
||||
*
|
||||
* After churning for a little while, the program will create the output
|
||||
* file "hello" which is compiled, linked and ready to run. Run this
|
||||
* program like so:
|
||||
*
|
||||
* ./hello
|
||||
*
|
||||
* and the program will print the message to its output. Easy! For
|
||||
* more on how to make the iverilog command work, see the iverilog
|
||||
* manual page.
|
||||
*/
|
||||
|
||||
module main();
|
||||
|
||||
initial
|
||||
begin
|
||||
$display("Hello, World");
|
||||
$finish ;
|
||||
end
|
||||
|
||||
endmodule
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (c) 1998-1999 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
|
||||
*/
|
||||
|
||||
/*
|
||||
* IVL should generate an AND gate, and should make an OBUF and two
|
||||
* IBUF objects, along with the PAD objects.
|
||||
*
|
||||
* To compile this for XNF, try a command like this:
|
||||
*
|
||||
* iverilog -txnf -ppart=XC4010XLPQ160 -ooutff.xnf -pncf=outff.ncf outff.v
|
||||
*
|
||||
* That command causes an outff.xnf and outff.ncf file to be created.
|
||||
* Next, make the outff.ngd file with the command:
|
||||
*
|
||||
* xnf2ngd -l xilinxun -u outff.xnf outff.ngo
|
||||
* ngdbuild outff.ngo outff.ngd
|
||||
*
|
||||
* Finally, map the file to fully render it in the target part. The
|
||||
* par command is the step that actually optimizes the design and tries
|
||||
* to meet timing constraints.
|
||||
*
|
||||
* map -o map.ncd outff.ngd
|
||||
* par -w map.ncd outff.ncd
|
||||
*
|
||||
* At this point, you can use the FPGA Editor to edit the outff.ncd
|
||||
* file to see that the AND gate is in a CLB and the IOB for pin 150
|
||||
* has its flip-flop in use, and that gbuf is a global buffer.
|
||||
*/
|
||||
|
||||
module main;
|
||||
|
||||
wire clk, iclk;
|
||||
wire i0, i1;
|
||||
wire out;
|
||||
reg o0;
|
||||
|
||||
// This simple logic gate get turned into a function unit.
|
||||
// The par program will map this into a CLB F or G unit.
|
||||
and (out, i0, i1);
|
||||
|
||||
// This creates a global clock buffer. Notice how I attach an
|
||||
// attribute to the named gate to force it to be mapped to the
|
||||
// desired XNF device. This device will not be pulled into the
|
||||
// IOB associated with iclk because of the attribute.
|
||||
buf gbuf(clk, iclk);
|
||||
$attribute(gbuf, "XNF-LCA", "GCLK:O,I");
|
||||
|
||||
// This is mapped to a DFF. Since o0 is connected to a PAD, it
|
||||
// is turned into a OUTFF so that it get placed into an IOB.
|
||||
always @(posedge clk) o0 = out;
|
||||
|
||||
// These attribute commands assign pins to the listed wires.
|
||||
// This can be done to wires and registers, as internally both
|
||||
// are treated as named signals.
|
||||
$attribute(o0, "PAD", "o150");
|
||||
$attribute(i0, "PAD", "i152");
|
||||
$attribute(i1, "PAD", "i153");
|
||||
$attribute(iclk,"PAD", "i154");
|
||||
|
||||
endmodule /* main */
|
||||
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright (c) 2000 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
|
||||
*/
|
||||
|
||||
/*
|
||||
* This example shows how to use Icarus Verilog to generate PLD output.
|
||||
* The design is intended to fit into a 22v10 in a PLCC package, with
|
||||
* pin assignments locked down by design. The command to compile this
|
||||
* into a jedec file is;
|
||||
*
|
||||
* iverilog -tpal -ppart=generic-22v10-plcc -opal_reg.jed pal_reg.v
|
||||
*
|
||||
* The output file name (passed through the -o<file> switch) can be
|
||||
* any file you desire. If the compilation and fittin all succeed, the
|
||||
* output file will be a JEDEC file that you can take to your favorite
|
||||
* PROM programmer to program the part.
|
||||
*
|
||||
* This source demonstrates some important principles of synthesizing
|
||||
* a design for a PLD, including how to specify synchronous logic, and
|
||||
* how to assign signals to pins. The pin assignment in particular is
|
||||
* part specific, and must be right for the fitting to succeed.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* The register module is an 8 bit register that copies the input to
|
||||
* the output registers on the rising edge of the clk input. The
|
||||
* always statement creates a simple d-type flip-flop that is loaded
|
||||
* on the rising edge of the clock.
|
||||
*
|
||||
* The output drivers are controlled by a single active low output
|
||||
* enable. I used bufif0 devices in this example, but the exact same
|
||||
* thing can be achived with a continuous assignment like so:
|
||||
*
|
||||
* assign out = oe? 8'hzz : Q;
|
||||
*
|
||||
* Many people prefer the expression form. It is true that it does
|
||||
* seem to express the intent a bit more clearly.
|
||||
*/
|
||||
module register (out, val, clk, oe);
|
||||
|
||||
output [7:0] out;
|
||||
input [7:0] val;
|
||||
input clk, oe;
|
||||
|
||||
reg [7:0] Q;
|
||||
|
||||
wire [7:0] out;
|
||||
|
||||
bufif0 drv[7:0](out, Q, oe);
|
||||
|
||||
always @(posedge clk) Q = val;
|
||||
|
||||
endmodule
|
||||
|
||||
|
||||
/*
|
||||
* The module pal is used to attach pin information to all the pins of
|
||||
* the device. We use this to lock down the pin assignments of the
|
||||
* synthesized result. The pin number assignments are for a 22v10 in
|
||||
* a PLCC package.
|
||||
*
|
||||
* Note that this module has no logic in it. It is a convention I use
|
||||
* that I put all the functionality in a seperate module (seen above)
|
||||
* and isolate the Icarus Verilog specific $attribute madness into a
|
||||
* top-level module. The advantage of this style is that the entire
|
||||
* module can be `ifdef'ed out when doing simulation and you don't
|
||||
* need to worry that functionality will be affected.
|
||||
*/
|
||||
module pal;
|
||||
|
||||
wire out7, out6, out5, out4, out3, out2, out1, out0;
|
||||
wire inp7, inp6, inp5, inp4, inp3, inp2, inp1, inp0;
|
||||
wire clk, oe;
|
||||
|
||||
// The PAD attributes attach the wires to pins of the
|
||||
// device. Output pins are prefixed by a 'o', and input pins by an
|
||||
// 'i'. If not all the available output pins are used, then the
|
||||
// remaining are available for the synthesizer to drop internal
|
||||
// registers or extra logic layers.
|
||||
$attribute(out7, "PAD", "o27");
|
||||
$attribute(out6, "PAD", "o26");
|
||||
$attribute(out5, "PAD", "o25");
|
||||
$attribute(out4, "PAD", "o24");
|
||||
$attribute(out3, "PAD", "o23");
|
||||
$attribute(out2, "PAD", "o21");
|
||||
$attribute(out1, "PAD", "o20");
|
||||
$attribute(out0, "PAD", "o19");
|
||||
|
||||
$attribute(inp7, "PAD", "i10");
|
||||
$attribute(inp6, "PAD", "i9");
|
||||
$attribute(inp5, "PAD", "i7");
|
||||
$attribute(inp4, "PAD", "i6");
|
||||
$attribute(inp3, "PAD", "i5");
|
||||
$attribute(inp2, "PAD", "i4");
|
||||
$attribute(inp1, "PAD", "i3");
|
||||
$attribute(inp0, "PAD", "i2");
|
||||
|
||||
//$attribute(clk, "PAD", "CLK");
|
||||
$attribute(oe, "PAD", "i13");
|
||||
|
||||
register dev({out7, out6, out5, out4, out3, out2, out1, out0},
|
||||
{inp7, inp6, inp5, inp4, inp3, inp2, inp1, inp0},
|
||||
clk, oe);
|
||||
|
||||
endmodule // pal
|
||||
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (c) 1999 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
|
||||
*/
|
||||
|
||||
/*
|
||||
* This example program simulates a 16x1 ram, and is used as an
|
||||
* example for using VCD output and waveform viewers.
|
||||
*
|
||||
* Like any other Verilog simulation, compile this program with the
|
||||
* command:
|
||||
*
|
||||
* iverilog show_vcd.vl
|
||||
*
|
||||
* This will generate the show_vcd command in the current directory.
|
||||
* When you run the command, you will see the output from all the
|
||||
* calls to $display, but also there will be a dump file ``show_vcd.vcd''.
|
||||
* The name of this file is set by the statement:
|
||||
*
|
||||
* $dumpfile("show_vcd.vcd");
|
||||
*
|
||||
* in the main module. The output file uses the standard VCD file format
|
||||
* so can be viewed using off-the-shelf waveform viewers. The remaining
|
||||
* steps describe how to use GTKWave to view the file. If you are using
|
||||
* a different viewer, see the documentation for that tool.
|
||||
*
|
||||
* To view the output generated by running show_vcd, start the GTKWave
|
||||
* viewer with the command:
|
||||
*
|
||||
* wave show_vcd.vcd
|
||||
*
|
||||
* The GTKWave program will display its main window, and show in a small
|
||||
* status box (upper left corner) that it succeeded in loading the dump
|
||||
* file. However, there are no waveforms displayed yet. Select signals to
|
||||
* add to the waveform display using the menu selection:
|
||||
*
|
||||
* "Search --> Signal Search Tree"
|
||||
*
|
||||
* This will bring up a dialog box that shows in directory tree format
|
||||
* the signals of the program. Select the signals you wish to view, and
|
||||
* click one of the buttons on the bottom of the dialog box to display
|
||||
* the selected signals in the waveform window. Click "Exit" on the box
|
||||
* to get rid of it.
|
||||
*
|
||||
* The magic that makes all this work is contained in the $dumpfile and
|
||||
* $dumpvars system tasks. The $dumpfile task tells the simulation where
|
||||
* to write the VCD output. This task must be called once before the
|
||||
* $dumpvars task is called.
|
||||
*
|
||||
* The $dumpvars task tells the simulation what variables to write to
|
||||
* the VCD output. The first parameter is how far to descend while
|
||||
* scanning a scope, and the remaining paramters are signals or scope
|
||||
* names to include in the dump. If a scope name is given, all the
|
||||
* signals within the scope are dumped. If a wire or register name is
|
||||
* given, that signal is included.
|
||||
*/
|
||||
|
||||
module ram16x1 (q, d, a, we, wclk);
|
||||
output q;
|
||||
input d;
|
||||
input [3:0] a;
|
||||
input we;
|
||||
input wclk;
|
||||
|
||||
reg mem[15:0];
|
||||
|
||||
assign q = mem[a];
|
||||
always @(posedge wclk) if (we) mem[a] = d;
|
||||
|
||||
endmodule /* ram16x1 */
|
||||
|
||||
module main;
|
||||
wire q;
|
||||
reg d;
|
||||
reg [3:0] a;
|
||||
reg we, wclk;
|
||||
|
||||
ram16x1 r1 (q, d, a, we, wclk);
|
||||
|
||||
initial begin
|
||||
$dumpfile("show_vcd.vcd");
|
||||
$dumpvars(1, main.r1);
|
||||
wclk = 0;
|
||||
we = 1;
|
||||
for (a = 0 ; a < 4'hf ; a = a + 1) begin
|
||||
d = a[0];
|
||||
#1 wclk = 1;
|
||||
#1 wclk = 0;
|
||||
$display("r1[%x] == %b", a, q);
|
||||
end
|
||||
|
||||
for (a = 0 ; a < 4'hf ; a = a + 1)
|
||||
#1 if (q !== a[0]) begin
|
||||
$display("FAILED -- mem[%h] !== %b", a, a[0]);
|
||||
$finish;
|
||||
end
|
||||
|
||||
$display("PASSED");
|
||||
end
|
||||
endmodule /* main */
|
||||
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* Copyright (c) 1999 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
|
||||
*
|
||||
* $Id: sqrt.vl,v 1.3 2000/11/04 01:53:24 steve Exp $"
|
||||
*/
|
||||
|
||||
/*
|
||||
* This example shows that Icarus Verilog can run non-trivial
|
||||
* programs, too. This uses a variety of Verilog language features
|
||||
* to implement the module of a square-root device. The program
|
||||
* uses IEEE1364-1995 language features and should work correctly
|
||||
* on any Verilog compiler.
|
||||
*
|
||||
* Run the file with Icarus Verilog under UNIX using the command:
|
||||
*
|
||||
* % iverilog -osqrt sqrt.v
|
||||
* % ./sqrt
|
||||
*/
|
||||
|
||||
/*
|
||||
* This module approximates the square root of an unsigned 32bit
|
||||
* number. The algorithm works by doing a bit-wise binary search.
|
||||
* Starting from the most significant bit, the accumulated value
|
||||
* tries to put a 1 in the bit position. If that makes the square
|
||||
* to big for the input, the bit is left zero, otherwise it is set
|
||||
* in the result. This continues for each bit, decreasing in
|
||||
* significance, until all the bits are calculated or all the
|
||||
* remaining bits are zero.
|
||||
*
|
||||
* Since the result is an integer, this function really calculates
|
||||
* value of the expression:
|
||||
*
|
||||
* x = floor(sqrt(y))
|
||||
*
|
||||
* where sqrt(y) is the exact square root of y and floor(N) is the
|
||||
* largest integer <= N.
|
||||
*
|
||||
* For 32bit numbers, this will never run more then 16 iterations,
|
||||
* which amounts to 16 clocks.
|
||||
*/
|
||||
|
||||
module sqrt32(clk, rdy, reset, x, .y(acc));
|
||||
input clk;
|
||||
output rdy;
|
||||
input reset;
|
||||
|
||||
input [31:0] x;
|
||||
output [15:0] acc;
|
||||
|
||||
|
||||
// acc holds the accumulated result, and acc2 is the accumulated
|
||||
// square of the accumulated result.
|
||||
reg [15:0] acc;
|
||||
reg [31:0] acc2;
|
||||
|
||||
// Keep track of which bit I'm working on.
|
||||
reg [4:0] bitl;
|
||||
wire [15:0] bit = 1 << bitl;
|
||||
wire [31:0] bit2 = 1 << (bitl << 1);
|
||||
|
||||
// The output is ready when the bitl counter underflows.
|
||||
wire rdy = bitl[4];
|
||||
|
||||
// guess holds the potential next values for acc, and guess2 holds
|
||||
// the square of that guess. The guess2 calculation is a little bit
|
||||
// subtle. The idea is that:
|
||||
//
|
||||
// guess2 = (acc + bit) * (acc + bit)
|
||||
// = (acc * acc) + 2*acc*bit + bit*bit
|
||||
// = acc2 + 2*acc*bit + bit2
|
||||
// = acc2 + 2 * (acc<<bitl) + bit
|
||||
//
|
||||
// This works out using shifts because bit and bit2 are known to
|
||||
// have only a single bit in them.
|
||||
wire [15:0] guess = acc | bit;
|
||||
wire [31:0] guess2 = acc2 + bit2 + ((acc << bitl) << 1);
|
||||
|
||||
task clear;
|
||||
begin
|
||||
acc = 0;
|
||||
acc2 = 0;
|
||||
bitl = 15;
|
||||
end
|
||||
endtask
|
||||
|
||||
initial clear;
|
||||
|
||||
always @(reset or posedge clk)
|
||||
if (reset)
|
||||
clear;
|
||||
else begin
|
||||
if (guess2 <= x) begin
|
||||
acc <= guess;
|
||||
acc2 <= guess2;
|
||||
end
|
||||
bitl <= bitl - 1;
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
module main;
|
||||
|
||||
reg clk, reset;
|
||||
reg [31:0] value;
|
||||
wire [15:0] result;
|
||||
wire rdy;
|
||||
|
||||
sqrt32 root(.clk(clk), .rdy(rdy), .reset(reset), .x(value), .y(result));
|
||||
|
||||
always #5 clk = ~clk;
|
||||
|
||||
always @(posedge rdy) begin
|
||||
$display("sqrt(%d) --> %d", value, result);
|
||||
$finish;
|
||||
end
|
||||
|
||||
|
||||
initial begin
|
||||
clk = 0;
|
||||
reset = 1;
|
||||
$monitor($time,,"%m.acc = %b", root.acc);
|
||||
#100 value = 63;
|
||||
reset = 0;
|
||||
end
|
||||
endmodule /* main */
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (c) 1999 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
|
||||
*/
|
||||
|
||||
/*
|
||||
* This example demonstrates Icarus Verilog's ability to synthesize
|
||||
* efficient adders for Xilinx 4000 series FPGAs. The synthesis and
|
||||
* code generation makes an adder and translates that into XOR gates
|
||||
* and fast carry chain hardware.
|
||||
*
|
||||
* To compile this for XNF, try a command like this:
|
||||
*
|
||||
* iverilog -txnf -ppart=XC4010XLPQ160 -pncf=xnf_add.ncf -oxnf_add.xnf xnf_add.v
|
||||
*
|
||||
* That command causes an xnf_add.xnf and xnf_add.ncf file to be created.
|
||||
* Next, Use Xilinx Alliance or Foundation tools to make the xnf_add.ngd
|
||||
* file with the command:
|
||||
*
|
||||
* xnf2ngd -l xilinxun -u xnf_add.xnf xnf_add.ngo
|
||||
* ngdbuild xnf_add.ngo xnf_add.ngd
|
||||
*
|
||||
* Finally, map the file to fully render it in the target part. The
|
||||
* par command is the step that actually optimizes the design and tries
|
||||
* to meet timing constraints.
|
||||
*
|
||||
* map -o map.ncd xnf_add.ngd
|
||||
* par -w map.ncd xnf_add.ncd
|
||||
*
|
||||
* At this point, you can use the Xilinx FPGA Editor to edit the xnf_add.ncd
|
||||
* file and see the carry chains made up to support the adder.
|
||||
*/
|
||||
|
||||
module main;
|
||||
|
||||
wire [3:0] a, b;
|
||||
wire [3:0] out;
|
||||
wire carry;
|
||||
|
||||
wire a0, a1, a2, a3, b0, b1, b2, b3;
|
||||
wire out0, out1, out2, out3;
|
||||
|
||||
// This creates the actual adder. Note that we also create a link
|
||||
// to the carry output. The principle adder is 4 bits wide, so two
|
||||
// IOBs are used to to the actual addition. PAR will place them in
|
||||
// order along carry lines. An extra carry cell from below a[0] is
|
||||
// used in FORCE-0 mode to load the bottom carry node.
|
||||
//
|
||||
// The carry signal from the top CY device is used to drive the
|
||||
// main.carry wire shown here. It is managed in this case by using
|
||||
// an ADD-FG-CI CY device for the top pair and using the CLB above
|
||||
// the carry chain, with its CY in EXAMINE-CI mode, to put the carry
|
||||
// out through its G function unit.
|
||||
|
||||
assign {carry, out} = a + b;
|
||||
|
||||
|
||||
// These attribute commands assign pins to the listed wires.
|
||||
// This can be done to wires and registers, as internally both
|
||||
// are treated as named signals. It doesn't work (yet) on vectors,
|
||||
// though, so break out the vectors with scaler assignments.
|
||||
|
||||
assign a[0] = a0;
|
||||
assign a[1] = a1;
|
||||
assign a[2] = a2;
|
||||
assign a[3] = a3;
|
||||
$attribute(a0, "PAD", "i150");
|
||||
$attribute(a1, "PAD", "i152");
|
||||
$attribute(a2, "PAD", "i153");
|
||||
$attribute(a3, "PAD", "i154");
|
||||
assign b[0] = b0;
|
||||
assign b[1] = b1;
|
||||
assign b[2] = b2;
|
||||
assign b[3] = b3;
|
||||
$attribute(b0, "PAD", "i155");
|
||||
$attribute(b1, "PAD", "i156");
|
||||
$attribute(b2, "PAD", "i157");
|
||||
$attribute(b3, "PAD", "i158");
|
||||
assign out0 = out[0];
|
||||
assign out1 = out[1];
|
||||
assign out2 = out[2];
|
||||
assign out3 = out[3];
|
||||
$attribute(out0, "PAD", "o71");
|
||||
$attribute(out1, "PAD", "o72");
|
||||
$attribute(out2, "PAD", "o73");
|
||||
$attribute(out3, "PAD", "o74");
|
||||
$attribute(carry, "PAD", "o75");
|
||||
|
||||
endmodule /* main */
|
||||
+451
-34
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2000 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,12 +16,16 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: expr_synth.cc,v 1.6 1999/11/28 23:42:02 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: expr_synth.cc,v 1.26 2001/08/31 22:59:48 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
# include "config.h"
|
||||
|
||||
# include <iostream>
|
||||
|
||||
# include "netlist.h"
|
||||
# include "netmisc.h"
|
||||
|
||||
NetNet* NetExpr::synthesize(Design*des)
|
||||
{
|
||||
@@ -38,24 +42,23 @@ NetNet* NetEBAdd::synthesize(Design*des)
|
||||
{
|
||||
assert((op()=='+') || (op()=='-'));
|
||||
|
||||
string path = des->local_symbol("SYNTH");
|
||||
NetNet*lsig = left_->synthesize(des);
|
||||
NetNet*rsig = right_->synthesize(des);
|
||||
|
||||
assert(lsig->pin_count() == rsig->pin_count());
|
||||
unsigned width=lsig->pin_count();
|
||||
|
||||
NetNet*osig = new NetNet(0, path, NetNet::IMPLICIT, width);
|
||||
string path = lsig->scope()->name()+"."+lsig->scope()->local_symbol();
|
||||
NetNet*osig = new NetNet(lsig->scope(), path, NetNet::IMPLICIT, width);
|
||||
|
||||
string oname = des->local_symbol(path);
|
||||
NetAddSub *adder = new NetAddSub(oname, width);
|
||||
NetAddSub *adder = new NetAddSub(lsig->scope(), oname, width);
|
||||
for (unsigned idx = 0 ; idx < width; idx += 1) {
|
||||
connect(lsig->pin(idx), adder->pin_DataA(idx));
|
||||
connect(rsig->pin(idx), adder->pin_DataB(idx));
|
||||
connect(osig->pin(idx), adder->pin_Result(idx));
|
||||
}
|
||||
des->add_node(adder);
|
||||
des->add_signal(osig);
|
||||
|
||||
switch (op()) {
|
||||
case '+':
|
||||
@@ -77,12 +80,28 @@ NetNet* NetEBAdd::synthesize(Design*des)
|
||||
*/
|
||||
NetNet* NetEBBits::synthesize(Design*des)
|
||||
{
|
||||
string path = des->local_symbol("SYNTH");
|
||||
NetNet*lsig = left_->synthesize(des);
|
||||
NetNet*rsig = right_->synthesize(des);
|
||||
|
||||
NetScope*scope = lsig->scope();
|
||||
assert(scope);
|
||||
string path = des->local_symbol(scope->name());
|
||||
|
||||
if (lsig->pin_count() != rsig->pin_count()) {
|
||||
cerr << get_line() << ": internal error: bitwise (" << op_
|
||||
<< ") widths do not match: " << lsig->pin_count()
|
||||
<< " != " << rsig->pin_count() << endl;
|
||||
cerr << get_line() << ": : width="
|
||||
<< lsig->pin_count() << ": " << *left_ << endl;
|
||||
cerr << get_line() << ": : width="
|
||||
<< rsig->pin_count() << ": " << *right_ << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(lsig->pin_count() == rsig->pin_count());
|
||||
NetNet*osig = new NetNet(0, path, NetNet::IMPLICIT, lsig->pin_count());
|
||||
NetNet*osig = new NetNet(scope, path, NetNet::IMPLICIT,
|
||||
lsig->pin_count());
|
||||
osig->local_flag(true);
|
||||
|
||||
for (unsigned idx = 0 ; idx < osig->pin_count() ; idx += 1) {
|
||||
string oname = des->local_symbol(path);
|
||||
@@ -90,19 +109,19 @@ NetNet* NetEBBits::synthesize(Design*des)
|
||||
|
||||
switch (op()) {
|
||||
case '&':
|
||||
gate = new NetLogic(oname, 3, NetLogic::AND);
|
||||
gate = new NetLogic(scope, oname, 3, NetLogic::AND);
|
||||
break;
|
||||
case '|':
|
||||
gate = new NetLogic(oname, 3, NetLogic::OR);
|
||||
gate = new NetLogic(scope, oname, 3, NetLogic::OR);
|
||||
break;
|
||||
case '^':
|
||||
gate = new NetLogic(oname, 3, NetLogic::XOR);
|
||||
gate = new NetLogic(scope, oname, 3, NetLogic::XOR);
|
||||
break;
|
||||
case 'O':
|
||||
gate = new NetLogic(oname, 3, NetLogic::NOR);
|
||||
gate = new NetLogic(scope, oname, 3, NetLogic::NOR);
|
||||
break;
|
||||
case 'X':
|
||||
gate = new NetLogic(oname, 3, NetLogic::XNOR);
|
||||
gate = new NetLogic(scope, oname, 3, NetLogic::XNOR);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
@@ -115,23 +134,264 @@ NetNet* NetEBBits::synthesize(Design*des)
|
||||
des->add_node(gate);
|
||||
}
|
||||
|
||||
des->add_signal(osig);
|
||||
return osig;
|
||||
}
|
||||
|
||||
NetNet* NetEBComp::synthesize(Design*des)
|
||||
{
|
||||
NetEConst*lcon = reinterpret_cast<NetEConst*>(left_);
|
||||
NetEConst*rcon = reinterpret_cast<NetEConst*>(right_);
|
||||
|
||||
/* Handle the special case where one of the inputs is constant
|
||||
0. We can use an OR gate to do the comparison. Synthesize
|
||||
the non-const side as normal, then or(nor) the signals
|
||||
together to get result. */
|
||||
if ((rcon && (rcon->value() == verinum(0UL,rcon->expr_width())))
|
||||
|| (lcon && (lcon->value() == verinum(0UL,lcon->expr_width())))) {
|
||||
|
||||
NetNet*lsig = rcon
|
||||
? left_->synthesize(des)
|
||||
: right_->synthesize(des);
|
||||
NetScope*scope = lsig->scope();
|
||||
assert(scope);
|
||||
string path = des->local_symbol(scope->name());
|
||||
|
||||
NetNet*osig = new NetNet(scope, path, NetNet::IMPLICIT, 1);
|
||||
osig->local_flag(true);
|
||||
|
||||
NetLogic*gate;
|
||||
switch (op_) {
|
||||
case 'e':
|
||||
case 'E':
|
||||
gate = new NetLogic(scope, des->local_symbol(path),
|
||||
lsig->pin_count()+1, NetLogic::NOR);
|
||||
break;
|
||||
case 'n':
|
||||
case 'N':
|
||||
gate = new NetLogic(scope, des->local_symbol(path),
|
||||
lsig->pin_count()+1, NetLogic::OR);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
connect(gate->pin(0), osig->pin(0));
|
||||
for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1)
|
||||
connect(gate->pin(idx+1), lsig->pin(idx));
|
||||
|
||||
des->add_node(gate);
|
||||
return osig;
|
||||
}
|
||||
|
||||
NetNet*lsig = left_->synthesize(des);
|
||||
NetNet*rsig = right_->synthesize(des);
|
||||
|
||||
NetScope*scope = lsig->scope();
|
||||
assert(scope);
|
||||
string path = des->local_symbol(scope->name());
|
||||
|
||||
unsigned width = lsig->pin_count();
|
||||
if (rsig->pin_count() > lsig->pin_count())
|
||||
width = rsig->pin_count();
|
||||
|
||||
lsig = pad_to_width(des, lsig, width);
|
||||
rsig = pad_to_width(des, rsig, width);
|
||||
|
||||
NetNet*osig = new NetNet(scope, path, NetNet::IMPLICIT, 1);
|
||||
osig->local_flag(true);
|
||||
|
||||
/* 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'))) {
|
||||
NetLogic*gate = new NetLogic(scope, des->local_symbol(path),
|
||||
3, NetLogic::XNOR);
|
||||
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 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'))) {
|
||||
NetLogic*gate = new NetLogic(scope, des->local_symbol(path),
|
||||
3, NetLogic::XOR);
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
NetCompare*dev = new NetCompare(scope, des->local_symbol(path), width);
|
||||
des->add_node(dev);
|
||||
|
||||
for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1)
|
||||
connect(dev->pin_DataA(idx), lsig->pin(idx));
|
||||
|
||||
for (unsigned idx = 0 ; idx < rsig->pin_count() ; idx += 1)
|
||||
connect(dev->pin_DataB(idx), rsig->pin(idx));
|
||||
|
||||
|
||||
switch (op_) {
|
||||
case '<':
|
||||
connect(dev->pin_ALB(), osig->pin(0));
|
||||
break;
|
||||
case '>':
|
||||
connect(dev->pin_AGB(), osig->pin(0));
|
||||
break;
|
||||
case 'e': // ==
|
||||
case 'E': // === ?
|
||||
connect(dev->pin_AEB(), osig->pin(0));
|
||||
break;
|
||||
case 'G': // >=
|
||||
connect(dev->pin_AGEB(), osig->pin(0));
|
||||
break;
|
||||
case 'L': // <=
|
||||
connect(dev->pin_ALEB(), osig->pin(0));
|
||||
break;
|
||||
case 'n': // !=
|
||||
case 'N': // !==
|
||||
connect(dev->pin_ANEB(), osig->pin(0));
|
||||
break;
|
||||
|
||||
default:
|
||||
cerr << get_line() << ": internal error: cannot synthesize "
|
||||
"comparison: " << *this << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return osig;
|
||||
}
|
||||
|
||||
NetNet* NetEBDiv::synthesize(Design*des)
|
||||
{
|
||||
cerr << get_line() << ": internal error: cannot synthesize division: "
|
||||
<< *this << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetNet* NetEBLogic::synthesize(Design*des)
|
||||
{
|
||||
NetNet*lsig = left_->synthesize(des);
|
||||
NetNet*rsig = right_->synthesize(des);
|
||||
|
||||
if (lsig == 0)
|
||||
return 0;
|
||||
|
||||
if (rsig == 0)
|
||||
return 0;
|
||||
|
||||
NetScope*scope = lsig->scope();
|
||||
assert(scope);
|
||||
string path = des->local_symbol(scope->name());
|
||||
|
||||
NetNet*osig = new NetNet(scope, path, NetNet::IMPLICIT, 1);
|
||||
osig->local_flag(true);
|
||||
|
||||
|
||||
if (op() == 'o') {
|
||||
|
||||
/* Logic OR can handle the reduction *and* the logical
|
||||
comparison with a single wide OR gate. So handle this
|
||||
magically. */
|
||||
|
||||
string oname = des->local_symbol(path);
|
||||
NetLogic*olog;
|
||||
|
||||
olog = new NetLogic(scope, oname,
|
||||
lsig->pin_count()+rsig->pin_count()+1,
|
||||
NetLogic::OR);
|
||||
|
||||
connect(osig->pin(0), olog->pin(0));
|
||||
|
||||
unsigned pin = 1;
|
||||
for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx = 1)
|
||||
connect(olog->pin(pin+idx), lsig->pin(idx));
|
||||
|
||||
pin += lsig->pin_count();
|
||||
for (unsigned idx = 0 ; idx < rsig->pin_count() ; idx = 1)
|
||||
connect(olog->pin(pin+idx), rsig->pin(idx));
|
||||
|
||||
des->add_node(olog);
|
||||
|
||||
} else {
|
||||
assert(op() == 'a');
|
||||
|
||||
/* Create the logic AND gate. This is a single bit
|
||||
output, with inputs for each of the operands. */
|
||||
NetLogic*olog;
|
||||
string oname = des->local_symbol(path);
|
||||
|
||||
olog = new NetLogic(scope, oname, 3, NetLogic::AND);
|
||||
|
||||
connect(osig->pin(0), olog->pin(0));
|
||||
des->add_node(olog);
|
||||
|
||||
/* XXXX Here, I need to reduce the parameters with
|
||||
reduction or. */
|
||||
|
||||
|
||||
/* By this point, the left and right parameters have been
|
||||
reduced to single bit values. Now we just connect them to
|
||||
the logic gate. */
|
||||
assert(lsig->pin_count() == 1);
|
||||
connect(lsig->pin(0), olog->pin(1));
|
||||
|
||||
assert(rsig->pin_count() == 1);
|
||||
connect(lsig->pin(0), olog->pin(2));
|
||||
}
|
||||
|
||||
|
||||
return osig;
|
||||
}
|
||||
|
||||
NetNet* NetEConcat::synthesize(Design*des)
|
||||
{
|
||||
NetScope*scope = des->find_root_scope();
|
||||
assert(scope);
|
||||
assert(repeat_ == 1);
|
||||
|
||||
string path = scope->name() + "." + scope->local_symbol();
|
||||
NetNet*osig = new NetNet(scope, path, NetNet::IMPLICIT, expr_width());
|
||||
osig->local_flag(true);
|
||||
|
||||
unsigned obit = 0;
|
||||
for (unsigned idx = parms_.count() ; idx > 0 ; idx -= 1) {
|
||||
NetNet*tmp = parms_[idx-1]->synthesize(des);
|
||||
|
||||
for (unsigned bit = 0 ; bit < tmp->pin_count() ; bit += 1) {
|
||||
connect(osig->pin(obit), tmp->pin(bit));
|
||||
obit += 1;
|
||||
}
|
||||
|
||||
if (tmp->local_flag() && tmp->get_eref() == 0)
|
||||
delete tmp;
|
||||
}
|
||||
|
||||
return osig;
|
||||
}
|
||||
|
||||
NetNet* NetEConst::synthesize(Design*des)
|
||||
{
|
||||
string path = des->local_symbol("SYNTH");
|
||||
NetScope*scope = des->find_root_scope();
|
||||
assert(scope);
|
||||
|
||||
string path = scope->name() + "." + scope->local_symbol();
|
||||
unsigned width=expr_width();
|
||||
|
||||
NetNet*osig = new NetNet(0, path, NetNet::IMPLICIT, width);
|
||||
for (unsigned idx = 0 ; idx < width; idx += 1) {
|
||||
string oname = des->local_symbol(path);
|
||||
NetConst *c = new NetConst(oname, value().get(idx));
|
||||
connect(osig->pin(idx), c->pin(0));
|
||||
des->add_node(c);
|
||||
}
|
||||
des->add_signal(osig);
|
||||
NetNet*osig = new NetNet(scope, path, NetNet::IMPLICIT, width);
|
||||
osig->local_flag(true);
|
||||
NetConst*con = new NetConst(des->local_symbol(path), value());
|
||||
for (unsigned idx = 0 ; idx < width; idx += 1)
|
||||
connect(osig->pin(idx), con->pin(idx));
|
||||
|
||||
des->add_node(con);
|
||||
return osig;
|
||||
}
|
||||
|
||||
@@ -141,10 +401,15 @@ NetNet* NetEConst::synthesize(Design*des)
|
||||
*/
|
||||
NetNet* NetEUBits::synthesize(Design*des)
|
||||
{
|
||||
string path = des->local_symbol("SYNTH");
|
||||
NetNet*isig = expr_->synthesize(des);
|
||||
|
||||
NetNet*osig = new NetNet(0, path, NetNet::IMPLICIT, isig->pin_count());
|
||||
NetScope*scope = isig->scope();
|
||||
assert(scope);
|
||||
string path = des->local_symbol(scope->name());
|
||||
|
||||
NetNet*osig = new NetNet(scope, path, NetNet::IMPLICIT,
|
||||
isig->pin_count());
|
||||
osig->local_flag(true);
|
||||
|
||||
for (unsigned idx = 0 ; idx < osig->pin_count() ; idx += 1) {
|
||||
string oname = des->local_symbol(path);
|
||||
@@ -152,7 +417,7 @@ NetNet* NetEUBits::synthesize(Design*des)
|
||||
|
||||
switch (op()) {
|
||||
case '~':
|
||||
gate = new NetLogic(oname, 2, NetLogic::NOT);
|
||||
gate = new NetLogic(scope, oname, 2, NetLogic::NOT);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
@@ -163,25 +428,67 @@ NetNet* NetEUBits::synthesize(Design*des)
|
||||
|
||||
des->add_node(gate);
|
||||
}
|
||||
des->add_signal(osig);
|
||||
|
||||
return osig;
|
||||
}
|
||||
|
||||
NetNet* NetEUReduce::synthesize(Design*des)
|
||||
{
|
||||
NetNet*isig = expr_->synthesize(des);
|
||||
|
||||
NetScope*scope = isig->scope();
|
||||
assert(scope);
|
||||
string path = des->local_symbol(scope->name());
|
||||
|
||||
NetNet*osig = new NetNet(scope, path, NetNet::IMPLICIT, 1);
|
||||
osig->local_flag(true);
|
||||
|
||||
string oname = des->local_symbol(path);
|
||||
NetLogic*gate;
|
||||
|
||||
switch (op()) {
|
||||
case 'N':
|
||||
case '!':
|
||||
gate = new NetLogic(scope, oname, isig->pin_count()+1,
|
||||
NetLogic::NOR);
|
||||
break;
|
||||
|
||||
case '&':
|
||||
gate = new NetLogic(scope, oname, isig->pin_count()+1,
|
||||
NetLogic::AND);
|
||||
break;
|
||||
|
||||
default:
|
||||
cerr << get_line() << ": internal error: "
|
||||
<< "Unable to synthesize " << *this << "." << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
des->add_node(gate);
|
||||
connect(gate->pin(0), osig->pin(0));
|
||||
for (unsigned idx = 0 ; idx < isig->pin_count() ; idx += 1)
|
||||
connect(gate->pin(1+idx), isig->pin(idx));
|
||||
|
||||
return osig;
|
||||
}
|
||||
|
||||
|
||||
NetNet* NetETernary::synthesize(Design *des)
|
||||
{
|
||||
string path = des->local_symbol("SYNTH");
|
||||
NetNet*csig = cond_->synthesize(des);
|
||||
NetNet*tsig = true_val_->synthesize(des);
|
||||
NetNet*fsig = false_val_->synthesize(des);
|
||||
|
||||
string path = csig->scope()->name()+"."+csig->scope()->local_symbol();
|
||||
|
||||
assert(csig->pin_count() == 1);
|
||||
assert(tsig->pin_count() == fsig->pin_count());
|
||||
unsigned width=tsig->pin_count();
|
||||
NetNet*osig = new NetNet(0, path, NetNet::IMPLICIT, width);
|
||||
NetNet*osig = new NetNet(csig->scope(), path, NetNet::IMPLICIT, width);
|
||||
osig->local_flag(true);
|
||||
|
||||
string oname = des->local_symbol(path);
|
||||
NetMux *mux = new NetMux(oname, width, 2, 1);
|
||||
NetMux *mux = new NetMux(csig->scope(), oname, width, 2, 1);
|
||||
for (unsigned idx = 0 ; idx < width; idx += 1) {
|
||||
connect(tsig->pin(idx), mux->pin_Data(idx, 1));
|
||||
connect(fsig->pin(idx), mux->pin_Data(idx, 0));
|
||||
@@ -189,17 +496,127 @@ NetNet* NetETernary::synthesize(Design *des)
|
||||
}
|
||||
des->add_node(mux);
|
||||
connect(csig->pin(0), mux->pin_Sel(0));
|
||||
des->add_signal(osig);
|
||||
|
||||
return osig;
|
||||
}
|
||||
|
||||
/*
|
||||
* When synthesizing a signal expressoin, it is usually fine to simply
|
||||
* return the NetNet that it refers to. If this is a part select,
|
||||
* though, a bit more work needs to be done. Return a temporary that
|
||||
* represents the connections to the selected bits.
|
||||
*
|
||||
* For example, if there is a reg foo, like so:
|
||||
* reg [5:0] foo;
|
||||
* and this expression node represents a part select foo[3:2], then
|
||||
* create a temporary like so:
|
||||
*
|
||||
* foo
|
||||
* +---+
|
||||
* | 5 |
|
||||
* +---+
|
||||
* tmp | 4 |
|
||||
* +---+ +---+
|
||||
* | 1 | <---> | 3 |
|
||||
* +---+ +---+
|
||||
* | 0 | <---> | 2 |
|
||||
* +---+ +---+
|
||||
* | 1 |
|
||||
* +---+
|
||||
* | 0 |
|
||||
* +---+
|
||||
* The temporary is marked as a temporary and returned to the
|
||||
* caller. This causes the caller to get only the selected part of the
|
||||
* signal, and when it hooks up to tmp, it hooks up to the right parts
|
||||
* of foo.
|
||||
*/
|
||||
NetNet* NetESignal::synthesize(Design*des)
|
||||
{
|
||||
return net_;
|
||||
if ((lsi_ == 0) && (msi_ == (net_->pin_count() - 1)))
|
||||
return net_;
|
||||
|
||||
assert(msi_ >= lsi_);
|
||||
unsigned wid = msi_ - lsi_ + 1;
|
||||
|
||||
NetScope*scope = net_->scope();
|
||||
assert(scope);
|
||||
|
||||
string name = scope->name() + "." + scope->local_symbol();
|
||||
NetNet*tmp = new NetNet(scope, name, NetNet::NetNet::WIRE, wid);
|
||||
tmp->local_flag(true);
|
||||
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1)
|
||||
connect(tmp->pin(idx), net_->pin(idx+lsi_));
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: expr_synth.cc,v $
|
||||
* Revision 1.26 2001/08/31 22:59:48 steve
|
||||
* synthesize the special case of compare with 0.
|
||||
*
|
||||
* Revision 1.25 2001/08/05 02:49:07 steve
|
||||
* Properly synthesize part selects.
|
||||
*
|
||||
* Revision 1.24 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.23 2001/07/07 01:38:45 steve
|
||||
* Put synthesized signals in proper scope.
|
||||
*
|
||||
* Revision 1.22 2001/06/15 04:14:18 steve
|
||||
* Generate vvp code for GT and GE comparisons.
|
||||
*
|
||||
* Revision 1.21 2001/06/07 02:12:43 steve
|
||||
* Support structural addition.
|
||||
*
|
||||
* Revision 1.20 2001/02/15 06:59:36 steve
|
||||
* FreeBSD port has a maintainer now.
|
||||
*
|
||||
* Revision 1.19 2001/01/18 03:16:35 steve
|
||||
* NetMux needs a scope. (PR#115)
|
||||
*
|
||||
* Revision 1.18 2000/11/29 23:16:18 steve
|
||||
* Do not delete synthesized signals used in expressions.
|
||||
*
|
||||
* Revision 1.17 2000/11/29 05:24:00 steve
|
||||
* synthesis for unary reduction ! and N operators.
|
||||
*
|
||||
* Revision 1.16 2000/11/29 02:09:52 steve
|
||||
* Add support for || synthesis (PR#53)
|
||||
*
|
||||
* Revision 1.15 2000/10/07 19:45:43 steve
|
||||
* Put logic devices into scopes.
|
||||
*
|
||||
* Revision 1.14 2000/05/02 00:58:12 steve
|
||||
* Move signal tables to the NetScope class.
|
||||
*
|
||||
* Revision 1.13 2000/04/28 18:43:23 steve
|
||||
* integer division in expressions properly get width.
|
||||
*
|
||||
* Revision 1.12 2000/04/20 00:28:03 steve
|
||||
* Catch some simple identity compareoptimizations.
|
||||
*
|
||||
* Revision 1.11 2000/04/16 23:32:18 steve
|
||||
* Synthesis of comparator in expressions.
|
||||
*
|
||||
* Connect the NetEvent and related classes
|
||||
* together better.
|
||||
*
|
||||
* Revision 1.10 2000/02/23 02:56:54 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.9 2000/01/01 06:18:00 steve
|
||||
* Handle synthesis of concatenation.
|
||||
*
|
||||
* Revision 1.8 1999/12/17 06:18:15 steve
|
||||
* Rewrite the cprop functor to use the functor_t interface.
|
||||
*
|
||||
* Revision 1.7 1999/12/17 03:38:46 steve
|
||||
* NetConst can now hold wide constants.
|
||||
*
|
||||
* Revision 1.6 1999/11/28 23:42:02 steve
|
||||
* NetESignal object no longer need to be NetNode
|
||||
* objects. Let them keep a pointer to NetNet objects.
|
||||
|
||||
+247
-15
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2000 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,10 +16,14 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: functor.cc,v 1.5 1999/12/01 06:06:16 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: functor.cc,v 1.25 2001/07/25 03:10:49 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# include <iostream>
|
||||
|
||||
# include "functor.h"
|
||||
# include "netlist.h"
|
||||
|
||||
@@ -27,6 +31,10 @@ functor_t::~functor_t()
|
||||
{
|
||||
}
|
||||
|
||||
void functor_t::event(class Design*, class NetEvent*)
|
||||
{
|
||||
}
|
||||
|
||||
void functor_t::signal(class Design*, class NetNet*)
|
||||
{
|
||||
}
|
||||
@@ -35,21 +43,78 @@ void functor_t::process(class Design*, class NetProcTop*)
|
||||
{
|
||||
}
|
||||
|
||||
void functor_t::lpm_add_sub(class Design*, class NetAddSub*)
|
||||
{
|
||||
}
|
||||
|
||||
void functor_t::lpm_compare(class Design*, class NetCompare*)
|
||||
{
|
||||
}
|
||||
|
||||
void functor_t::lpm_const(class Design*, class NetConst*)
|
||||
{
|
||||
}
|
||||
|
||||
void functor_t::lpm_divide(class Design*, class NetDivide*)
|
||||
{
|
||||
}
|
||||
|
||||
void functor_t::lpm_modulo(class Design*, class NetModulo*)
|
||||
{
|
||||
}
|
||||
|
||||
void functor_t::lpm_ff(class Design*, class NetFF*)
|
||||
{
|
||||
}
|
||||
|
||||
void Design::functor(functor_t*fun)
|
||||
void functor_t::lpm_logic(class Design*, class NetLogic*)
|
||||
{
|
||||
// apply to signals
|
||||
}
|
||||
|
||||
void functor_t::lpm_mult(class Design*, class NetMult*)
|
||||
{
|
||||
}
|
||||
|
||||
void functor_t::lpm_mux(class Design*, class NetMux*)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void NetScope::run_functor(Design*des, functor_t*fun)
|
||||
{
|
||||
for (NetScope*cur = sub_ ; cur ; cur = cur->sib_) {
|
||||
cur->run_functor(des, fun);
|
||||
}
|
||||
|
||||
for (NetEvent*cur = events_ ; cur ; /* */) {
|
||||
NetEvent*tmp = cur;
|
||||
cur = cur->snext_;
|
||||
fun->event(des, tmp);
|
||||
}
|
||||
|
||||
// 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 {
|
||||
NetNet*tmp = cur->sig_next_;
|
||||
fun->signal(this, cur);
|
||||
cur = tmp;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Design::functor(functor_t*fun)
|
||||
{
|
||||
// Scan the scopes
|
||||
root_scope_->run_functor(this, fun);
|
||||
|
||||
// apply to processes
|
||||
procs_idx_ = procs_;
|
||||
@@ -61,12 +126,30 @@ void Design::functor(functor_t*fun)
|
||||
|
||||
// apply to nodes
|
||||
if (nodes_) {
|
||||
/* Scan the circular list of nodes, starting with the
|
||||
front of the list. (nodes_ points to the *end* of the
|
||||
list.) The bar is the end point. At the end of the
|
||||
do-while loop, I know that the bar has been
|
||||
processed or (if bar == 0) no undeleted node has been
|
||||
processed. */
|
||||
NetNode*cur = nodes_->node_next_;
|
||||
NetNode*bar = 0;
|
||||
do {
|
||||
NetNode*tmp = cur->node_next_;
|
||||
cur->functor_node(this, fun);
|
||||
|
||||
/* Detect the case that cur has been deleted by
|
||||
noticing if tmp->node_prev_ no longer points to
|
||||
cur. If that's the case, clear the bar. */
|
||||
if (tmp->node_prev_ != cur) {
|
||||
if (cur == bar)
|
||||
bar = 0;
|
||||
} else if (bar == 0) {
|
||||
bar = cur;
|
||||
}
|
||||
cur = tmp;
|
||||
} while (cur != nodes_->node_next_);
|
||||
|
||||
} while (nodes_ && (cur != bar));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,11 +158,51 @@ void NetNode::functor_node(Design*, functor_t*)
|
||||
{
|
||||
}
|
||||
|
||||
void NetAddSub::functor_node(Design*des, functor_t*fun)
|
||||
{
|
||||
fun->lpm_add_sub(des, this);
|
||||
}
|
||||
|
||||
void NetCompare::functor_node(Design*des, functor_t*fun)
|
||||
{
|
||||
fun->lpm_compare(des, this);
|
||||
}
|
||||
|
||||
void NetConst::functor_node(Design*des, functor_t*fun)
|
||||
{
|
||||
fun->lpm_const(des, this);
|
||||
}
|
||||
|
||||
void NetDivide::functor_node(Design*des, functor_t*fun)
|
||||
{
|
||||
fun->lpm_divide(des, this);
|
||||
}
|
||||
|
||||
void NetFF::functor_node(Design*des, functor_t*fun)
|
||||
{
|
||||
fun->lpm_ff(des, this);
|
||||
}
|
||||
|
||||
void NetLogic::functor_node(Design*des, functor_t*fun)
|
||||
{
|
||||
fun->lpm_logic(des, this);
|
||||
}
|
||||
|
||||
void NetModulo::functor_node(Design*des, functor_t*fun)
|
||||
{
|
||||
fun->lpm_modulo(des, this);
|
||||
}
|
||||
|
||||
void NetMult::functor_node(Design*des, functor_t*fun)
|
||||
{
|
||||
fun->lpm_mult(des, this);
|
||||
}
|
||||
|
||||
void NetMux::functor_node(Design*des, functor_t*fun)
|
||||
{
|
||||
fun->lpm_mux(des, this);
|
||||
}
|
||||
|
||||
proc_match_t::~proc_match_t()
|
||||
{
|
||||
}
|
||||
@@ -99,6 +222,48 @@ int NetAssign::match_proc(proc_match_t*that)
|
||||
return that->assign(this);
|
||||
}
|
||||
|
||||
int proc_match_t::assign_nb(NetAssignNB*)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int NetAssignNB::match_proc(proc_match_t*that)
|
||||
{
|
||||
return that->assign_nb(this);
|
||||
}
|
||||
|
||||
int proc_match_t::assign_mem(NetAssignMem*)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int NetAssignMem::match_proc(proc_match_t*that)
|
||||
{
|
||||
return that->assign_mem(this);
|
||||
}
|
||||
|
||||
int proc_match_t::assign_mem_nb(NetAssignMemNB*)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int NetAssignMemNB::match_proc(proc_match_t*that)
|
||||
{
|
||||
return that->assign_mem_nb(this);
|
||||
}
|
||||
|
||||
int proc_match_t::block(NetBlock*)
|
||||
{
|
||||
cerr << "default (failing) match for block" << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int NetBlock::match_proc(proc_match_t*that)
|
||||
{
|
||||
cerr << "NetBlock::match_proc" << endl;
|
||||
return that->block(this);
|
||||
}
|
||||
|
||||
int proc_match_t::condit(NetCondit*)
|
||||
{
|
||||
return 0;
|
||||
@@ -109,18 +274,85 @@ int NetCondit::match_proc(proc_match_t*that)
|
||||
return that->condit(this);
|
||||
}
|
||||
|
||||
int proc_match_t::pevent(NetPEvent*)
|
||||
int NetEvWait::match_proc(proc_match_t*that)
|
||||
{
|
||||
return that->event_wait(this);
|
||||
}
|
||||
|
||||
int proc_match_t::event_wait(NetEvWait*)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int NetPEvent::match_proc(proc_match_t*that)
|
||||
{
|
||||
return that->pevent(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: functor.cc,v $
|
||||
* Revision 1.25 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.24 2000/11/19 20:48:30 steve
|
||||
* Fix cases where signal iteration might die early.
|
||||
*
|
||||
* Revision 1.23 2000/11/18 04:53:04 steve
|
||||
* Watch out in functor, it may delete the last signal.
|
||||
*
|
||||
* Revision 1.22 2000/09/17 21:26:15 steve
|
||||
* Add support for modulus (Eric Aardoom)
|
||||
*
|
||||
* Revision 1.21 2000/08/01 02:48:41 steve
|
||||
* Support <= in synthesis of DFF and ram devices.
|
||||
*
|
||||
* Revision 1.20 2000/07/16 04:56:07 steve
|
||||
* Handle some edge cases during node scans.
|
||||
*
|
||||
* Revision 1.19 2000/07/15 05:13:43 steve
|
||||
* Detect muxing Vz as a bufufN.
|
||||
*
|
||||
* Revision 1.18 2000/05/02 00:58:12 steve
|
||||
* Move signal tables to the NetScope class.
|
||||
*
|
||||
* Revision 1.17 2000/04/20 00:28:03 steve
|
||||
* Catch some simple identity compareoptimizations.
|
||||
*
|
||||
* Revision 1.16 2000/04/18 04:50:19 steve
|
||||
* Clean up unneeded NetEvent objects.
|
||||
*
|
||||
* Revision 1.15 2000/04/16 23:32:18 steve
|
||||
* Synthesis of comparator in expressions.
|
||||
*
|
||||
* Connect the NetEvent and related classes
|
||||
* together better.
|
||||
*
|
||||
* Revision 1.14 2000/04/12 20:02:53 steve
|
||||
* Finally remove the NetNEvent and NetPEvent classes,
|
||||
* Get synthesis working with the NetEvWait class,
|
||||
* and get started supporting multiple events in a
|
||||
* wait in vvm.
|
||||
*
|
||||
* Revision 1.13 2000/04/01 21:40:22 steve
|
||||
* Add support for integer division.
|
||||
*
|
||||
* Revision 1.12 2000/02/23 02:56:54 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.11 2000/02/13 04:35:43 steve
|
||||
* Include some block matching from Larry.
|
||||
*
|
||||
* Revision 1.10 2000/01/13 03:35:35 steve
|
||||
* Multiplication all the way to simulation.
|
||||
*
|
||||
* Revision 1.9 2000/01/02 17:57:20 steve
|
||||
* Handle nodes running out during node scan.
|
||||
*
|
||||
* Revision 1.8 1999/12/30 04:19:12 steve
|
||||
* Propogate constant 0 in low bits of adders.
|
||||
*
|
||||
* Revision 1.7 1999/12/17 06:18:16 steve
|
||||
* Rewrite the cprop functor to use the functor_t interface.
|
||||
*
|
||||
* Revision 1.6 1999/12/05 02:24:08 steve
|
||||
* Synthesize LPM_RAM_DQ for writes into memories.
|
||||
*
|
||||
* Revision 1.5 1999/12/01 06:06:16 steve
|
||||
* Redo synth to use match_proc_t scanner.
|
||||
*
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __functor_H
|
||||
#define __functor_H
|
||||
/*
|
||||
* Copyright (c) 1999 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2000 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
|
||||
@@ -18,14 +18,21 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: functor.h,v 1.3 1999/12/01 06:06:16 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: functor.h,v 1.17 2000/09/17 21:26:15 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The functor is an object that can be applied to a design to
|
||||
* transform it. This is different from the target_t, which can only
|
||||
* scan the design but not transform it in any way.
|
||||
*
|
||||
* When a functor it scanning a process, signal or node, the functor
|
||||
* is free to manipulate the list by deleting items, including the
|
||||
* node being scanned. The Design class scanner knows how to handle
|
||||
* the situation. However, if objects are added to the netlist, there
|
||||
* is no guarantee that object will be scanned unless the functor is
|
||||
* rerun.
|
||||
*/
|
||||
|
||||
class Design;
|
||||
@@ -35,38 +42,98 @@ class NetProcTop;
|
||||
struct functor_t {
|
||||
virtual ~functor_t();
|
||||
|
||||
/* Signals are scanned first. This is called once for each
|
||||
signal in the design. */
|
||||
/* Events are scanned here. */
|
||||
virtual void event(class Design*des, class NetEvent*);
|
||||
|
||||
/* This is called once for each signal in the design. */
|
||||
virtual void signal(class Design*des, class NetNet*);
|
||||
|
||||
/* This method is called for each process in the design. */
|
||||
virtual void process(class Design*des, class NetProcTop*);
|
||||
|
||||
/* This method is called for each structural adder. */
|
||||
virtual void lpm_add_sub(class Design*des, class NetAddSub*);
|
||||
|
||||
/* This method is called for each structural comparator. */
|
||||
virtual void lpm_compare(class Design*des, class NetCompare*);
|
||||
|
||||
/* This method is called for each structural constant. */
|
||||
virtual void lpm_const(class Design*des, class NetConst*);
|
||||
|
||||
/* This method is called for each structural constant. */
|
||||
virtual void lpm_divide(class Design*des, class NetDivide*);
|
||||
|
||||
/* This method is called for each structural constant. */
|
||||
virtual void lpm_modulo(class Design*des, class NetModulo*);
|
||||
|
||||
/* This method is called for each FF in the design. */
|
||||
virtual void lpm_ff(class Design*des, class NetFF*);
|
||||
|
||||
/* Handle LPM combinational logic devices. */
|
||||
virtual void lpm_logic(class Design*des, class NetLogic*);
|
||||
|
||||
/* This method is called for each multiplier. */
|
||||
virtual void lpm_mult(class Design*des, class NetMult*);
|
||||
|
||||
/* This method is called for each MUX. */
|
||||
virtual void lpm_mux(class Design*des, class NetMux*);
|
||||
};
|
||||
|
||||
struct proc_match_t {
|
||||
virtual ~proc_match_t();
|
||||
|
||||
virtual int assign(class NetAssign*);
|
||||
virtual int assign_mem(class NetAssignMem*);
|
||||
virtual int assign_nb(class NetAssignNB*);
|
||||
virtual int assign_mem_nb(class NetAssignMemNB*);
|
||||
virtual int condit(class NetCondit*);
|
||||
virtual int pevent(class NetPEvent*);
|
||||
virtual int event_wait(class NetEvWait*);
|
||||
virtual int block(class NetBlock*);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* $Log: functor.h,v $
|
||||
* Revision 1.3 1999/12/01 06:06:16 steve
|
||||
* Redo synth to use match_proc_t scanner.
|
||||
* Revision 1.17 2000/09/17 21:26:15 steve
|
||||
* Add support for modulus (Eric Aardoom)
|
||||
*
|
||||
* Revision 1.2 1999/11/01 02:07:40 steve
|
||||
* Add the synth functor to do generic synthesis
|
||||
* and add the LPM_FF device to handle rows of
|
||||
* flip-flops.
|
||||
* Revision 1.16 2000/08/01 02:48:42 steve
|
||||
* Support <= in synthesis of DFF and ram devices.
|
||||
*
|
||||
* Revision 1.1 1999/07/17 22:01:13 steve
|
||||
* Add the functor interface for functor transforms.
|
||||
* Revision 1.15 2000/07/16 04:56:07 steve
|
||||
* Handle some edge cases during node scans.
|
||||
*
|
||||
* Revision 1.14 2000/07/15 05:13:44 steve
|
||||
* Detect muxing Vz as a bufufN.
|
||||
*
|
||||
* Revision 1.13 2000/04/20 00:28:03 steve
|
||||
* Catch some simple identity compareoptimizations.
|
||||
*
|
||||
* Revision 1.12 2000/04/18 04:50:19 steve
|
||||
* Clean up unneeded NetEvent objects.
|
||||
*
|
||||
* Revision 1.11 2000/04/12 20:02:53 steve
|
||||
* Finally remove the NetNEvent and NetPEvent classes,
|
||||
* Get synthesis working with the NetEvWait class,
|
||||
* and get started supporting multiple events in a
|
||||
* wait in vvm.
|
||||
*
|
||||
* Revision 1.10 2000/04/01 21:40:22 steve
|
||||
* Add support for integer division.
|
||||
*
|
||||
* Revision 1.9 2000/02/23 02:56:54 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.8 2000/02/13 04:35:43 steve
|
||||
* Include some block matching from Larry.
|
||||
*
|
||||
* Revision 1.7 2000/01/13 03:35:35 steve
|
||||
* Multiplication all the way to simulation.
|
||||
*
|
||||
* Revision 1.6 1999/12/30 04:19:12 steve
|
||||
* Propogate constant 0 in low bits of adders.
|
||||
*
|
||||
* Revision 1.5 1999/12/17 06:18:16 steve
|
||||
* Rewrite the cprop functor to use the functor_t interface.
|
||||
*/
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
|
||||
Throughout Icarus Verilog descriptions and source code, I use a
|
||||
variety of terms and acronyms that might be specific to Icarus
|
||||
Verilog, have an Icarus Verilog specific meaning, or just aren't
|
||||
widely known. So here I define these terms.
|
||||
|
||||
|
||||
LRM - Language Reference Manual
|
||||
This is a generic acronym, but in the Verilog world we sometimes
|
||||
mean *the* language reference manual, the IEEE1364 standard.
|
||||
|
||||
|
||||
PLI - Programming Language Interface
|
||||
This is a C API into Verilog simulators that is defined by the
|
||||
IEEE1364. There are two major interfaces, sometimes called PLI 1
|
||||
and PLI 2. PLI 2 is also often called VPI.
|
||||
|
||||
|
||||
UDP - User Defined Primitive
|
||||
These are objects that Verilog programmers define with the
|
||||
"primitive" keyword. They are truth-table based devices. The
|
||||
syntax for defining them is described in the LRM.
|
||||
|
||||
|
||||
VPI -
|
||||
This is the C API that is defined by the Verilog standard, and
|
||||
that Icarus Verilog partially implements. See also PLI.
|
||||
|
||||
|
||||
VVM - Verilog Virtual Machine
|
||||
This is the Icarus Verilog runtime that works with the code
|
||||
generator that generates C++.
|
||||
|
||||
|
||||
VVP - Verilog Virtual Processor
|
||||
This is the Icarus Verilog runtime that reads in custom code in a
|
||||
form that I call "VVP Assembly". See the vvp/ directory for
|
||||
documentation on that.
|
||||
|
||||
@@ -0,0 +1,346 @@
|
||||
|
||||
Icarus Verilog vs. IEEE1364
|
||||
Copyright 2000 Stephen Williams
|
||||
|
||||
The IEEE1364 standard is the bible that defines the correctness of the
|
||||
Icarus Verilog implementation and behavior of the compiled
|
||||
program. The IEEE1364.1 is also referenced for matters of
|
||||
synthesis. So the ultimate definition of right and wrong comes from
|
||||
those documents.
|
||||
|
||||
That does not mean that a Verilog implementation is fully
|
||||
constrained. The standard document allows for implementation specific
|
||||
behavior that, when properly accounted for, does not effect the
|
||||
intended semantics of the specified language. It is therefore possible
|
||||
and common to write programs that produce different results when run
|
||||
by different Verilog implementations.
|
||||
|
||||
|
||||
STANDARDIZATION ISSUES
|
||||
|
||||
These are some issues where the IEEE1364 left unclear, unspecified or
|
||||
simply wrong. I'll try to be precise as I can, and reference the
|
||||
standard as needed. I've made implementation decisions for Icarus
|
||||
Verilog, and I will make clear what those decisions are and how they
|
||||
affect the language.
|
||||
|
||||
* OBJECTS CAN BE DECLARED ANYWHERE IN THE MODULE
|
||||
|
||||
Consider this module:
|
||||
|
||||
module sample1;
|
||||
initial foo = 1;
|
||||
reg foo;
|
||||
wire tmp = bar;
|
||||
initial #1 $display("foo = %b, bar = %b", foo, tmp);
|
||||
endmodule
|
||||
|
||||
Notice that the ``reg foo;'' declaration is placed after the first
|
||||
initial statement. It turns out that this is a perfectly legal module
|
||||
according to the -1995 and -2000 versions of the standard. The
|
||||
statement ``reg foo;'' is a module_item_declaration which is in turn a
|
||||
module_item. The BNF in the appendix of IEEE1364-1995 treats all
|
||||
module_item statements equally, so no order is imposed.
|
||||
|
||||
Furthermore, there is no text (that I can find) elsewhere in the
|
||||
standard that imposes any ordering restriction. The sorts of
|
||||
restrictions I would look for are "module_item_declarations must
|
||||
appear before all other module_items" or "variables must be declared
|
||||
textually before they are referenced." Such statements simply do not
|
||||
exist. (Personally, I think it is fine that they don't.)
|
||||
|
||||
The closest is the rules for implicit declarations of variables that
|
||||
are otherwise undeclared. In the above example, ``bar'' is implicitly
|
||||
declared and is therefore a wire. However, although ``initial foo = 1;''
|
||||
is written before foo is declared, foo *is* declared within the
|
||||
module, and declared legally by the BNF of the standard.
|
||||
|
||||
Here is another example:
|
||||
|
||||
module sample2;
|
||||
initial x.foo = 1;
|
||||
test x;
|
||||
initial #1 $display("foo = %b", x.foo);
|
||||
endmodule
|
||||
|
||||
module test;
|
||||
reg foo;
|
||||
endmodule;
|
||||
|
||||
From this example one can clearly see that foo is once again declared
|
||||
after its use in behavioral code. One also sees a forward reference of
|
||||
an entire module. Once again, the standard places no restriction on
|
||||
the order of module declarations in a source file, so this program is,
|
||||
according to the standard, perfectly well formed.
|
||||
|
||||
Icarus Verilog interprets both of these examples according to "The
|
||||
Standard As I Understand It." However, commercial tools in general
|
||||
break down with these programs. In particular, the first example
|
||||
may generate different errors depending on the tool. The most common
|
||||
error is to claim that ``foo'' is declared twice, once (implicitly) as
|
||||
a wire and once as a reg.
|
||||
|
||||
So the question now becomes, "Is the standard broken, or are the tools
|
||||
limited?" Coverage of the standard seems to vary widely from tool to
|
||||
tool so it is not clear that the standard really is at fault. It is
|
||||
clear, however, that somebody goofed somewhere.
|
||||
|
||||
My personal opinion is that there is no logical need to require that
|
||||
all module_item_declarations preceed any other module items. I
|
||||
personally would oppose such a restriction. It may make sense to
|
||||
require that declarations of variables within a module be preceded by
|
||||
their use, although even that is not necessary for the implementation
|
||||
of efficient compilers.
|
||||
|
||||
However, the existence hierarchical naming syntax as demonstrated in
|
||||
sample2 can have implications that affect any declaration order
|
||||
rules. When reaching into a module with a hierarchical name, the
|
||||
module being referenced is already completely declared (or not
|
||||
declared at all, as in sample2) so module_item order is completely
|
||||
irrelevent. But a "declare before use" rule would infect module
|
||||
ordering, by requiring that modules that are used be first defined.
|
||||
|
||||
|
||||
* TASK AND FUNCTION PARAMETERS CANNOT HAVE EXPLICIT TYPES
|
||||
|
||||
Consider a function negate that wants to take a signed integer value
|
||||
and return its negative:
|
||||
|
||||
function integer negate;
|
||||
input [15:0] val;
|
||||
negate = -val;
|
||||
endfunction
|
||||
|
||||
This is not quite right, because the input is implicitly a reg type,
|
||||
which is unsigned. The result, then, will always be a negative value,
|
||||
even if a negative val is passed in.
|
||||
|
||||
It is possible to fix up this specific example to work properly with
|
||||
the bit pattern of a 16bit number, but that is not the point. What's
|
||||
needed is clarification on whether an input can be declared in the
|
||||
port declaration as well as in the contained block declaration.
|
||||
|
||||
As I understand the situation, this should be allowed:
|
||||
|
||||
function integer negate;
|
||||
input [15:0] val;
|
||||
reg signed [15:0] val;
|
||||
negate = -val;
|
||||
endfunction
|
||||
|
||||
In the -1995 standard, the variable is already implicitly a reg if
|
||||
declared within a function or task. However, in the -2000 standard
|
||||
there is now (as in this example) a reason why one might want to
|
||||
actually declare the type explicitly.
|
||||
|
||||
I think that a port *cannot* be declared as an integer or time type
|
||||
(though the result can) because the range of the port declaration must
|
||||
match the range of the integer/time declaration, but the range of
|
||||
integers is unspecified. This, by the way, also applies to module
|
||||
ports.
|
||||
|
||||
With the above in mind, I have decided to *allow* function and task
|
||||
ports to be declared with types, as long as the types are variable
|
||||
types, such ag reg or integer. Without this, there would be no
|
||||
portable way to pass integers into functions/tasks. The standard does
|
||||
not say it is allowed, but it doesn't *disallow* it, and other
|
||||
commercial tools seem to work similarly.
|
||||
|
||||
|
||||
* ROUNDING OF TIME
|
||||
|
||||
When the `timescale directive is present, the compiler is supposed to
|
||||
round fractional times (after scaling) to the nearest integer. The
|
||||
confusing bit here is that it is apparently conventional that if the
|
||||
`timescale directive is *not* present, times are rounded towards zero
|
||||
always.
|
||||
|
||||
|
||||
* VALUE OF X IN PRIMITIVE OUTPUTS
|
||||
|
||||
The IEEE1364-1995 standard clearly states in Table 8-1 that the x
|
||||
symbols is allowed in input columns, but is not allowed in
|
||||
outputs. Furthermore, none of the examples have an x in the output of
|
||||
a primitive. Table 8-1 in the IEEE1364-2000 also says the same thing.
|
||||
|
||||
However, the BNF clearly states that 0, 1, x and X are valid
|
||||
output_symbol characters. The standard is self contradictory. So I
|
||||
take it that x is allowed, as that is what Verilog-XL does.
|
||||
|
||||
|
||||
* REPEAT LOOPS vs. REPEAT EVENT CONTROL
|
||||
|
||||
There seems to be ambiguity in how code like this should be parsed:
|
||||
|
||||
repeat (5) @(posedge clk) <statment>;
|
||||
|
||||
There are two valid interpretations of this code, from the
|
||||
IEEE1364-1995 standard. One looks like this:
|
||||
|
||||
procedural_timing_control_statement ::=
|
||||
delay_or_event_control statement_or_null
|
||||
|
||||
delay_or_event_control ::=
|
||||
event_control
|
||||
| repeat ( expression ) event_control
|
||||
|
||||
If this interpretation is used, then the statement <statement> should
|
||||
be executed after the 5th posedge of clk. However, there is also this
|
||||
interpretation:
|
||||
|
||||
loop_statement ::=
|
||||
repeat ( expression ) statement
|
||||
|
||||
If *this* interpretation is used, then <statement> should be executed
|
||||
5 times on the posedge of clk. The way the -1995 standard is written,
|
||||
these are both equally valid interpretations of the example, yet they
|
||||
produce very different results. The standard offers no guidance on how
|
||||
to resolve this conflict, and the IEEE1364-2000 DRAFT does not improve
|
||||
the situation.
|
||||
|
||||
Practice suggests that a repeat followed by an event control should be
|
||||
interpreted as a loop head, and this is what Icarus Verilog does, as
|
||||
well as all the other major Verilog tools, but the standard does not
|
||||
say this.
|
||||
|
||||
|
||||
* UNSIZED EXPRESSIONS AS PARAMETERS TO CONCATENATION {}
|
||||
|
||||
The Verilog standard clearly states in 4.1.14:
|
||||
|
||||
"Unsized constant numbers shall not be allowed in
|
||||
concatenations. This is because the size of each
|
||||
operand in the concatenation is needed to calculate
|
||||
the complete size of the concatenation."
|
||||
|
||||
So for example the expression {1'b0, 16} is clearly illegal. It
|
||||
also stands to reason that {1'b0, 15+1} is illegal, for exactly the
|
||||
same justification. What is the size of the expression (15+1)?
|
||||
Furthermore, it is reasonable to expect that (16) and (15+1) are
|
||||
exactly the same so far as the compiler is concerned.
|
||||
|
||||
Unfortunately, Cadence seems to feel otherwise. In particular, it has
|
||||
been reported that although {1'b0, 16} causes an error, {1'b0, 15+1}
|
||||
is accepted. Further testing shows that any expression other then a
|
||||
simple unsized constant is accepted there, even if all the operands of
|
||||
all the operators that make up the expression are unsized integers.
|
||||
|
||||
This is a semantic problem. Icarus Verilog doesn't limit the size of
|
||||
integer constants. This is valid as stated in 2.5.1 Note 3:
|
||||
|
||||
"The number of bits that make up an unsized number
|
||||
(which is a simple decimal number or a number without
|
||||
the size specification) shall be *at*least* 32."
|
||||
[emphasis added]
|
||||
|
||||
Icarus Verilog will hold any integer constant, so the size will be as
|
||||
large as it needs to be, whether that is 64bits, 128bits, or
|
||||
more. With this in mind, what is the value of these expressions?
|
||||
|
||||
{'h1_00_00_00_00}
|
||||
{'h1 << 32}
|
||||
{'h0_00_00_00_01 << 32}
|
||||
{'h5_00_00_00_00 + 1}
|
||||
|
||||
These examples show that the standard is justified in requiring that
|
||||
the operands of concatenation have size. The dispute is what it takes
|
||||
to cause an expression to have a size, and what that size is.
|
||||
Verilog-XL claims that (16) does not have a size, but (15+1) does. The
|
||||
size of the expression (15+1) is the size of the adder that is
|
||||
created, but how wide is the adder when adding unsized constants?
|
||||
|
||||
One might note that the quote from section 4.1.14 says "Unsized
|
||||
*constant*numbers* shall not be allowed." It does not say "Unsized
|
||||
expressions...", so arguably accepting (15+1) or even (16+0) as an
|
||||
operand to a concatenation is not a violation of the letter of the
|
||||
law. However, the very next sentence of the quote expresses the
|
||||
intent, and accepting (15+1) as having a more defined size then (16)
|
||||
seems to be a violation of that intent.
|
||||
|
||||
Whatever a compiler decides the size is, the user has no way to
|
||||
predict it, and the compiler should not have the right to treat (15+1)
|
||||
any differently then (16). Therefore, Icarus Verilog takes the
|
||||
position that such expressions are *unsized* and are not allowed as
|
||||
operands to concatenations. Icarus Verilog will in general assume that
|
||||
operations on unsized numbers produce unsized results. There are
|
||||
exceptions when the operator itself does define a size, such as the
|
||||
comparison operators or the reduction operators. Icarus Verilog will
|
||||
generate appropriate error messages.
|
||||
|
||||
|
||||
* MODULE INSTANCE WITH WRONG SIZE PORT LIST
|
||||
|
||||
A module declaration like this declares a module that takes three ports:
|
||||
|
||||
module three (a, b, c);
|
||||
input a, b, c;
|
||||
reg x;
|
||||
endmodule
|
||||
|
||||
This is fine and obvious. It is also clear from the standard that
|
||||
these are legal instantiations of this module:
|
||||
|
||||
three u1 (x,y,z);
|
||||
three u2 ( ,y, );
|
||||
three u3 ( , , );
|
||||
three u4 (.b(y));
|
||||
|
||||
In some of the above examples, there are unconnected ports. In the
|
||||
case of u4, the pass by name connects only port b, and leaves a and c
|
||||
unconnected. u2 and u4 are the same thing, in fact, but using
|
||||
positional or by-name syntax. The next example is a little less
|
||||
obvious:
|
||||
|
||||
three u4 ();
|
||||
|
||||
The trick here is that strictly speaking, the parser cannot tell
|
||||
whether this is a list of no pass by name ports (that is, all
|
||||
unconnected) or an empty positional list. If this were an empty
|
||||
positional list, then the wrong number of ports is given, but if it is
|
||||
an empty by-name list, it is an obviously valid instantiation. So it
|
||||
is fine to accept this case as valid.
|
||||
|
||||
These are more doubtful:
|
||||
|
||||
three u5(x,y);
|
||||
three u6(,);
|
||||
|
||||
These are definitely positional port lists, and they are definitely
|
||||
the wrong length. In this case, the standard is not explicit about
|
||||
what to do about positional port lists in module instantiations,
|
||||
except that the first is connected to the first, second to second,
|
||||
etc. It does not say that the list must be the right length, but every
|
||||
example of unconnected ports used by-name syntax, and every example of
|
||||
ordered list has the right size list.
|
||||
|
||||
Icarus Verilog takes the (very weak) hint that ordered lists should be
|
||||
the right length, and will therefore flag instances u5 and u6 as
|
||||
errors. The IEEE1364 standard should be more specific one way or the
|
||||
other.
|
||||
|
||||
$Id: ieee1364-notes.txt,v 1.8 2001/08/01 05:17:31 steve Exp $
|
||||
$Log: ieee1364-notes.txt,v $
|
||||
Revision 1.8 2001/08/01 05:17:31 steve
|
||||
Accept empty port lists to module instantiation.
|
||||
|
||||
Revision 1.7 2001/02/17 05:27:31 steve
|
||||
I allow function ports to have types.
|
||||
|
||||
Revision 1.6 2001/02/12 16:48:04 steve
|
||||
Rant about bit widths.
|
||||
|
||||
Revision 1.5 2001/01/02 17:28:08 steve
|
||||
Resolve repeat ambiguity in favor of loop.
|
||||
|
||||
Revision 1.4 2001/01/01 19:12:35 steve
|
||||
repeat loops ambiguity.
|
||||
|
||||
Revision 1.3 2000/12/15 00:21:46 steve
|
||||
rounding of time and x in primitives.
|
||||
|
||||
Revision 1.2 2000/11/19 22:03:04 steve
|
||||
Integer parameter comments.
|
||||
|
||||
Revision 1.1 2000/07/23 18:06:31 steve
|
||||
Document ieee1364 issues.
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
|
||||
# The iverilog.conf configuration file provides to the iverilog driver
|
||||
# strings based on switches that are passed by the user on the command
|
||||
# line.
|
||||
#
|
||||
# Comments start from the hash (#) character and run to the end of the
|
||||
# line.
|
||||
#
|
||||
# Conditions are a list of requirements between [] characters. For the
|
||||
# set of patterns following a string to b activated, all the
|
||||
# conditions must be true. Valid conditions are:
|
||||
#
|
||||
# -S -- The -S flag is passed to iverilog
|
||||
# -t<string> -- The -t<string> parameters is passed to iverilog
|
||||
#
|
||||
#
|
||||
# Patterns have a name and text. The name has the form <key> where the
|
||||
# key is some key value that is required by iverilog. The commonly
|
||||
# used keys are:
|
||||
#
|
||||
# <ivl>
|
||||
# The string here is the command line needed to take the
|
||||
# preprocessor output (ivlpp) and compile it with the
|
||||
# target. All target types use this key.
|
||||
#
|
||||
# The pattern text includes %<code> substitutions. iverilog
|
||||
# substitutes values for the %<code> sequences within the text.
|
||||
#
|
||||
# %B Substitute the base libdir, -B flag of iverilog.
|
||||
#
|
||||
# %f Substitute the -f flags from the command line.
|
||||
#
|
||||
# %s Substitute the start module (-s flag) from the user.
|
||||
#
|
||||
# %N Substitute the value of the -N<path> flag.
|
||||
#
|
||||
# %o Substitute the value of the -o<path> flag, or the default
|
||||
# output path if there is no -o flag.
|
||||
#
|
||||
# %T Substitute min, typ or max depending on the -T flag from the
|
||||
# command line.
|
||||
#
|
||||
#
|
||||
# %W Substitute the ivl warning flags.
|
||||
#
|
||||
# %[<c><text>]
|
||||
# This substitution pattern is magical, and is the only
|
||||
# multicharacter pattern. This tests the code <c>, and
|
||||
# substitutes <text> into the output only if <c> is true.
|
||||
# The <text> may include further substitution strings, and is
|
||||
# terminated by a ``]'' character.
|
||||
|
||||
|
||||
# This is the null (no op) target. Thre is a synthesis version and a
|
||||
# non-synthesis version. Normally, this does not matter, but this can
|
||||
# be useful and interesting if the -N flag is included.
|
||||
|
||||
[-tnull -S]
|
||||
<ivl>%B/ivl %[v-v] %W %[s-s%s] %[N-N%N] %[T-T%T] -tdll -fDLL=%B/null.tgt -- -
|
||||
|
||||
[-tnull]
|
||||
<ivl>%B/ivl %[v-v] %W %[s-s%s] %[N-N%N] %[T-T%T] -tdll -fDLL=%B/null.tgt -- -
|
||||
|
||||
# --
|
||||
# The vvp target generates code that the vvp simulation engine can execute.
|
||||
# These rules support synthesized and non-synthesized variants.
|
||||
|
||||
[-tvvp -S]
|
||||
<ivl>%B/ivl %[v-v] %W %[s-s%s] %[N-N%N] %[T-T%T] -tdll -fDLL=%B/vvp.tgt -fVVP_EXECUTABLE=%B/../../bin/vvp -Fsynth -Fsyn-rules -Fcprop -Fnodangle %f %m -o%o -- -
|
||||
|
||||
[-tvvp]
|
||||
<ivl>%B/ivl %[v-v] %W %[s-s%s] %[N-N%N] %[T-T%T] -tdll -fDLL=%B/vvp.tgt -fVVP_EXECUTABLE=%B/../../bin/vvp -Fcprop -Fnodangle %f %m -o%o -- -
|
||||
|
||||
# --
|
||||
# The vvm target uses the <ivl> string to take the preprocessed code from
|
||||
# standard input, compile it with the vvm code generator and write the
|
||||
# result to %o.cc. The driver assumes this when invoking the C++ compiler
|
||||
# on the result.
|
||||
|
||||
[-tvvm]
|
||||
<ivl>%B/ivl %[v-v] %W %[s-s%s] %[N-N%N] %[T-T%T] -tvvm -Fcprop -Fnodangle -fVPI_MODULE_PATH=%B %f %m -o%o.cc -- -
|
||||
|
||||
|
||||
# This is the XNF code generator.
|
||||
|
||||
[-txnf]
|
||||
<ivl>%B/ivl %[v-v] %[s-s%s] %[N-N%N] %[T-T%T] -txnf -Fsynth -Fsyn-rules -Fcprop -Fnodangle -o%o -- -
|
||||
|
||||
# And this is another XNF code generator, under development.
|
||||
[-tfpga]
|
||||
<ivl>%B/ivl %[v-v] %[s-s%s] %[N-N%N] %[T-T%T] %f -tdll -fDLL=%B/fpga.tgt -Fsynth -Fsyn-rules -Fcprop -Fnodangle -o%o -- -
|
||||
|
||||
# --
|
||||
# This is the pal code generator. The target module requires the -fpart=<type>
|
||||
# flag to specify the part type.
|
||||
[-tpal]
|
||||
<ivl>%B/ivl %[v-v] %[s-s%s] %[N-N%N] %[T-T%T] -tdll -fDLL=%B/pal.tgt -Fsynth -Fsyn-rules -Fcprop -Fnodangle -o%o -- -
|
||||
@@ -0,0 +1,157 @@
|
||||
EXPORTS
|
||||
|
||||
ivl_design_const
|
||||
ivl_design_consts
|
||||
ivl_design_flag
|
||||
ivl_design_process
|
||||
ivl_design_root
|
||||
ivl_design_time_precision
|
||||
|
||||
ivl_const_bits
|
||||
ivl_const_pin
|
||||
ivl_const_pins
|
||||
ivl_const_signed
|
||||
|
||||
ivl_event_any
|
||||
ivl_event_basename
|
||||
ivl_event_name
|
||||
ivl_event_nany
|
||||
ivl_event_neg
|
||||
ivl_event_nneg
|
||||
ivl_event_npos
|
||||
ivl_event_pos
|
||||
|
||||
ivl_expr_type
|
||||
ivl_expr_bits
|
||||
ivl_expr_def
|
||||
ivl_expr_lsi
|
||||
ivl_expr_memory
|
||||
ivl_expr_name
|
||||
ivl_expr_opcode
|
||||
ivl_expr_oper1
|
||||
ivl_expr_oper2
|
||||
ivl_expr_oper3
|
||||
ivl_expr_parm
|
||||
ivl_expr_parms
|
||||
ivl_expr_repeat
|
||||
ivl_expr_scope
|
||||
ivl_expr_signal
|
||||
ivl_expr_signed
|
||||
ivl_expr_string
|
||||
ivl_expr_uvalue
|
||||
ivl_expr_width
|
||||
|
||||
ivl_logic_name
|
||||
ivl_logic_basename
|
||||
ivl_logic_scope
|
||||
ivl_logic_type
|
||||
ivl_logic_pin
|
||||
ivl_logic_pins
|
||||
ivl_logic_udp
|
||||
|
||||
ivl_lpm_basename
|
||||
ivl_lpm_clk
|
||||
ivl_lpm_data
|
||||
ivl_lpm_datab
|
||||
ivl_lpm_data2
|
||||
ivl_lpm_enable
|
||||
ivl_lpm_memory
|
||||
ivl_lpm_name
|
||||
ivl_lpm_q
|
||||
ivl_lpm_scope
|
||||
ivl_lpm_select
|
||||
ivl_lpm_selects
|
||||
ivl_lpm_size
|
||||
ivl_lpm_type
|
||||
ivl_lpm_width
|
||||
|
||||
ivl_lval_idx
|
||||
ivl_lval_mem
|
||||
ivl_lval_mux
|
||||
ivl_lval_part_off
|
||||
ivl_lval_pin
|
||||
ivl_lval_pins
|
||||
ivl_lval_sig
|
||||
|
||||
ivl_memory_basename
|
||||
ivl_memory_name
|
||||
ivl_memory_root
|
||||
ivl_memory_size
|
||||
ivl_memory_width
|
||||
|
||||
ivl_nexus_get_private
|
||||
ivl_nexus_name
|
||||
ivl_nexus_ptrs
|
||||
ivl_nexus_ptr
|
||||
ivl_nexus_set_private
|
||||
|
||||
ivl_nexus_ptr_con
|
||||
ivl_nexus_ptr_drive0
|
||||
ivl_nexus_ptr_drive1
|
||||
ivl_nexus_ptr_pin
|
||||
ivl_nexus_ptr_lpm
|
||||
ivl_nexus_ptr_log
|
||||
ivl_nexus_ptr_sig
|
||||
|
||||
ivl_scope_basename
|
||||
ivl_scope_children
|
||||
ivl_scope_def
|
||||
ivl_scope_event
|
||||
ivl_scope_events
|
||||
ivl_scope_logs
|
||||
ivl_scope_log
|
||||
ivl_scope_lpms
|
||||
ivl_scope_lpm
|
||||
ivl_scope_mem
|
||||
ivl_scope_mems
|
||||
ivl_scope_name
|
||||
ivl_scope_parent
|
||||
ivl_scope_port
|
||||
ivl_scope_ports
|
||||
ivl_scope_sigs
|
||||
ivl_scope_sig
|
||||
ivl_scope_type
|
||||
ivl_scope_tname
|
||||
|
||||
ivl_signal_attr
|
||||
ivl_signal_pin
|
||||
ivl_signal_pins
|
||||
ivl_signal_port
|
||||
ivl_signal_signed
|
||||
ivl_signal_type
|
||||
ivl_signal_name
|
||||
ivl_signal_basename
|
||||
|
||||
ivl_process_scope
|
||||
ivl_process_stmt
|
||||
ivl_process_type
|
||||
|
||||
ivl_statement_type
|
||||
|
||||
ivl_stmt_block_count
|
||||
ivl_stmt_block_stmt
|
||||
ivl_stmt_call
|
||||
ivl_stmt_case_count
|
||||
ivl_stmt_case_expr
|
||||
ivl_stmt_case_stmt
|
||||
ivl_stmt_cond_expr
|
||||
ivl_stmt_cond_false
|
||||
ivl_stmt_cond_true
|
||||
ivl_stmt_delay_expr
|
||||
ivl_stmt_delay_val
|
||||
ivl_stmt_event
|
||||
ivl_stmt_lval
|
||||
ivl_stmt_lvals
|
||||
ivl_stmt_lwidth
|
||||
ivl_stmt_name
|
||||
ivl_stmt_parm
|
||||
ivl_stmt_parm_count
|
||||
ivl_stmt_rval
|
||||
ivl_stmt_sub_stmt
|
||||
|
||||
ivl_udp_init
|
||||
ivl_udp_name
|
||||
ivl_udp_nin
|
||||
ivl_udp_row
|
||||
ivl_udp_rows
|
||||
ivl_udp_sequ
|
||||
+1187
File diff suppressed because it is too large
Load Diff
+13
-13
@@ -18,7 +18,7 @@
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.6 1999/10/16 20:48:15 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.12 2001/08/10 00:39:22 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
@@ -31,8 +31,8 @@ srcdir = @srcdir@
|
||||
|
||||
VPATH = $(srcdir)
|
||||
|
||||
bindir = $(exec_prefix)/bin
|
||||
libdir = $(exec_prefix)/lib
|
||||
bindir = @bindir@
|
||||
libdir = @libdir@
|
||||
includedir = $(prefix)/include
|
||||
|
||||
CC = @CC@
|
||||
@@ -41,8 +41,8 @@ INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
|
||||
CPPFLAGS = @CPPFLAGS@ @DEFS@
|
||||
CFLAGS = @CFLAGS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
CFLAGS = @CFLAGS@ -I. -I$(srcdir)/..
|
||||
LDFLAGS = @LDFLAGS@
|
||||
|
||||
all: ivlpp
|
||||
|
||||
@@ -52,24 +52,24 @@ clean:
|
||||
O = main.o lexor.o parse.o
|
||||
|
||||
ivlpp: $O
|
||||
$(CC) $(LDFLAGS) $O -o ivlpp
|
||||
$(CC) $(LDFLAGS) $O -o ivlpp @EXTRALIBS@
|
||||
|
||||
lexor.c: lexor.lex
|
||||
flex -s -olexor.c lexor.lex
|
||||
flex -s -olexor.c $(srcdir)/lexor.lex
|
||||
|
||||
parse.h parse.c: parse.y
|
||||
bison --verbose -t -d parse.y -o parse.c
|
||||
bison --verbose -t -d -o parse.c $(srcdir)/parse.y
|
||||
|
||||
install: all installdirs $(bindir)/ivlpp
|
||||
install: all installdirs $(libdir)/ivl/ivlpp
|
||||
|
||||
$(bindir)/ivlpp: ivlpp
|
||||
$(INSTALL_PROGRAM) ./ivlpp $(bindir)/ivlpp
|
||||
$(libdir)/ivl/ivlpp: ivlpp
|
||||
$(INSTALL_PROGRAM) ./ivlpp $(libdir)/ivl/ivlpp
|
||||
|
||||
installdirs: ../mkinstalldirs
|
||||
$(srcdir)/../mkinstalldirs $(bindir)
|
||||
$(srcdir)/../mkinstalldirs $(libdir)/ivl
|
||||
|
||||
uninstall:
|
||||
rm -f $(bindir)/ivlpp
|
||||
rm -f $(libdir)/ivl/ivlpp
|
||||
|
||||
lexor.o: lexor.c parse.h globals.h
|
||||
main.o: main.c globals.h
|
||||
|
||||
+14
-3
@@ -18,14 +18,14 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: globals.h,v 1.2 1999/09/05 22:33:18 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: globals.h,v 1.5 2000/09/13 22:33:13 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <stdio.h>
|
||||
|
||||
extern void reset_lexor(FILE*out, char*paths[]);
|
||||
extern void define_macro(const char*name, const char*value);
|
||||
extern void define_macro(const char*name, const char*value, int keyword);
|
||||
|
||||
/* These variables contain the include directories to be searched when
|
||||
an include directive in encountered. */
|
||||
@@ -35,11 +35,22 @@ extern unsigned include_cnt;
|
||||
/* This flag is true if #line directives are to be generated. */
|
||||
extern int line_direct_flag;
|
||||
|
||||
extern unsigned error_count;
|
||||
|
||||
/* This is the entry to the parser. */
|
||||
extern int yyparse();
|
||||
|
||||
/*
|
||||
* $Log: globals.h,v $
|
||||
* Revision 1.5 2000/09/13 22:33:13 steve
|
||||
* undefined macros are null (with warnings.)
|
||||
*
|
||||
* Revision 1.4 2000/08/20 17:49:04 steve
|
||||
* Clean up warnings and portability issues.
|
||||
*
|
||||
* Revision 1.3 2000/06/30 15:49:44 steve
|
||||
* Handle errors from parser slightly differently.
|
||||
*
|
||||
* Revision 1.2 1999/09/05 22:33:18 steve
|
||||
* Take multiple source files on the command line.
|
||||
*
|
||||
|
||||
+70
-16
@@ -18,10 +18,12 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: lexor.lex,v 1.14 1999/10/08 17:27:56 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: lexor.lex,v 1.24 2001/07/25 03:10:50 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# include <stdio.h>
|
||||
# include <malloc.h>
|
||||
# include <string.h>
|
||||
@@ -35,6 +37,7 @@ static void output_init();
|
||||
|
||||
static void def_match();
|
||||
static void def_start();
|
||||
static void def_finish();
|
||||
static void def_undefine();
|
||||
static void do_define();
|
||||
static int is_defined(const char*name);
|
||||
@@ -84,6 +87,7 @@ static int comment_enter = 0;
|
||||
%x PPDEFINE
|
||||
%x CCOMMENT
|
||||
%x CSTRING
|
||||
%x ERROR_LINE
|
||||
|
||||
%x IFDEF_FALSE
|
||||
%s IFDEF_TRUE
|
||||
@@ -115,30 +119,59 @@ W [ \t\b\f]+
|
||||
that follows it. when the directive ends, the do_include function
|
||||
performs the include operation. */
|
||||
|
||||
^{W}?`include { BEGIN(PPINCLUDE); }
|
||||
^{W}?`include { yy_push_state(PPINCLUDE); }
|
||||
|
||||
<PPINCLUDE>\"[^\"]*\" { include_filename(); }
|
||||
|
||||
<PPINCLUDE>[ \t\b\f] { ; }
|
||||
|
||||
<PPINCLUDE>\n { istack->lineno += 1; BEGIN(0); do_include(); }
|
||||
/* 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. */
|
||||
|
||||
<PPINCLUDE>"//".* { ECHO; }
|
||||
|
||||
/* These finish the include directive (EOF or EOL) so I revert the
|
||||
lexor state and execute the inclusion. */
|
||||
|
||||
<PPINCLUDE>\n { istack->lineno += 1; yy_pop_state(); do_include(); }
|
||||
<PPINCLUDE>\r\n { istack->lineno += 1; yy_pop_state(); do_include(); }
|
||||
<PPINCLUDE>\n\r { istack->lineno += 1; yy_pop_state(); do_include(); }
|
||||
<PPINCLUDE><<EOF>> { istack->lineno += 1; yy_pop_state(); do_include(); }
|
||||
|
||||
/* Anything that is not matched by the above is an error of some
|
||||
sort. Print and error message and absorb the rest of the line. */
|
||||
<PPINCLUDE>. {
|
||||
fprintf(stderr, "%s:%u: error: malformed `include directive."
|
||||
" Did you quote the file name?\n", istack->path,
|
||||
istack->lineno+1);
|
||||
error_count += 1;
|
||||
BEGIN(ERROR_LINE); }
|
||||
|
||||
/* Detect the define directive, and match the name. Match any
|
||||
white space that might be found, as well. After I get the
|
||||
directive and the name, go into PPDEFINE mode and prepare to
|
||||
collect the defined value. */
|
||||
|
||||
`define{W}[a-zA-Z][a-zA-Z0-9_]*{W}? { BEGIN(PPDEFINE); def_start(); }
|
||||
`define{W}[a-zA-Z_][a-zA-Z0-9_]*{W}? { yy_push_state(PPDEFINE); def_start(); }
|
||||
|
||||
<PPDEFINE>.*\n {
|
||||
do_define();
|
||||
<PPDEFINE>.* { do_define(); }
|
||||
|
||||
<PPDEFINE>(\n|"\r\n"|"\n\r") {
|
||||
def_finish();
|
||||
istack->lineno += 1;
|
||||
fputc('\n', yyout);
|
||||
BEGIN(0);
|
||||
yy_pop_state();
|
||||
}
|
||||
|
||||
`undef{W}[a-zA-Z][a-zA-Z0-9_]*{W}?.* { def_undefine(); }
|
||||
<PPDEFINE><<EOF>> {
|
||||
def_finish();
|
||||
istack->lineno += 1;
|
||||
fputc('\n', yyout);
|
||||
yy_pop_state();
|
||||
}
|
||||
|
||||
`undef{W}[a-zA-Z_][a-zA-Z0-9_]*{W}?.* { def_undefine(); }
|
||||
|
||||
|
||||
/* Detect conditional compilation directives, and parse them. If I
|
||||
@@ -150,7 +183,7 @@ W [ \t\b\f]+
|
||||
condition that stacks on top of the IFDEF_FALSE so that output is
|
||||
not accidentally turned on within nested ifdefs. */
|
||||
|
||||
^{W}?`ifdef{W}[a-zA-Z][a-zA-Z0-9_]*.* {
|
||||
^{W}?`ifdef{W}[a-zA-Z_][a-zA-Z0-9_]*.* {
|
||||
char*name = strchr(yytext, '`');
|
||||
assert(name);
|
||||
name += 6;
|
||||
@@ -186,6 +219,9 @@ W [ \t\b\f]+
|
||||
. { ECHO; }
|
||||
\n { istack->lineno += 1; ECHO; }
|
||||
|
||||
/* Absorb the rest of the line when a broken directive is detected. */
|
||||
<ERROR_LINE>.* { yy_pop_state(); }
|
||||
|
||||
%%
|
||||
/* Defined macros are kept in this table for convenient lookup. As
|
||||
`define directives are matched (and the do_define() function
|
||||
@@ -194,6 +230,8 @@ W [ \t\b\f]+
|
||||
struct define_t {
|
||||
char*name;
|
||||
char*value;
|
||||
/* keywords don't get rescanned for fresh values. */
|
||||
int keyword;
|
||||
|
||||
struct define_t*left, *right, *up;
|
||||
};
|
||||
@@ -233,8 +271,14 @@ static void def_match()
|
||||
struct define_t*cur = def_lookup(yytext+1);
|
||||
|
||||
if (cur) {
|
||||
struct include_stack_t*isp
|
||||
= calloc(1, sizeof(struct include_stack_t));
|
||||
struct include_stack_t*isp;
|
||||
|
||||
if (cur->keyword) {
|
||||
fprintf(yyout, "%s", cur->value);
|
||||
return;
|
||||
}
|
||||
|
||||
isp = calloc(1, sizeof(struct include_stack_t));
|
||||
isp->str = cur->value;
|
||||
isp->next = istack;
|
||||
istack->yybs = YY_CURRENT_BUFFER;
|
||||
@@ -242,7 +286,9 @@ static void def_match()
|
||||
yy_switch_to_buffer(yy_new_buffer(istack->file, YY_BUF_SIZE));
|
||||
|
||||
} else {
|
||||
fprintf(yyout, "%s", yytext);
|
||||
fprintf(stderr, "%s:%u: warning: macro %s undefined "
|
||||
"(and assumed null) at this point.\n",
|
||||
istack->path, istack->lineno, yytext);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -253,11 +299,12 @@ static void def_start()
|
||||
sscanf(yytext, "`define %s", def_name);
|
||||
}
|
||||
|
||||
void define_macro(const char*name, const char*value)
|
||||
void define_macro(const char*name, const char*value, int keyword)
|
||||
{
|
||||
struct define_t*def = malloc(sizeof(struct define_t));
|
||||
def->name = strdup(name);
|
||||
def->value = strdup(value);
|
||||
def->keyword = keyword;
|
||||
def->left = 0;
|
||||
def->right = 0;
|
||||
def->up = 0;
|
||||
@@ -317,7 +364,14 @@ static void do_define()
|
||||
*cp = 0;
|
||||
}
|
||||
|
||||
define_macro(def_name, yytext);
|
||||
define_macro(def_name, yytext, 0);
|
||||
def_name[0] = 0;
|
||||
}
|
||||
|
||||
static void def_finish()
|
||||
{
|
||||
if (def_name[0])
|
||||
define_macro(def_name, "1", 0);
|
||||
}
|
||||
|
||||
static void def_undefine()
|
||||
@@ -522,7 +576,7 @@ static int yywrap()
|
||||
if (line_direct_flag)
|
||||
fprintf(yyout, "\n#line \"%s\" 0\n", istack->path);
|
||||
|
||||
yyrestart(isp->file);
|
||||
yyrestart(istack->file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+70
-5
@@ -16,10 +16,12 @@ const char COPYRIGHT[] =
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: main.c,v 1.4 1999/11/29 17:02:21 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: main.c,v 1.11 2001/07/25 03:10:50 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
const char NOTICE[] =
|
||||
" This program is free software; you can redistribute it and/or modify\n"
|
||||
" it under the terms of the GNU General Public License as published by\n"
|
||||
@@ -39,6 +41,7 @@ const char NOTICE[] =
|
||||
const char VERSION[] = "$Name: $ $State: Exp $";
|
||||
|
||||
# include <stdio.h>
|
||||
# include <stdlib.h>
|
||||
# include <malloc.h>
|
||||
# include <unistd.h>
|
||||
# include <string.h>
|
||||
@@ -47,11 +50,19 @@ const char VERSION[] = "$Name: $ $State: Exp $";
|
||||
#endif
|
||||
# include "globals.h"
|
||||
|
||||
#if defined(__MINGW32__) && !defined(HAVE_GETOPT_H)
|
||||
extern int getopt(int argc, char*argv[], const char*fmt);
|
||||
extern int optind;
|
||||
extern const char*optarg;
|
||||
#endif
|
||||
|
||||
char**include_dir = 0;
|
||||
unsigned include_cnt = 0;
|
||||
|
||||
int line_direct_flag = 0;
|
||||
|
||||
unsigned error_count = 0;
|
||||
|
||||
int main(int argc, char*argv[])
|
||||
{
|
||||
int opt;
|
||||
@@ -59,11 +70,30 @@ int main(int argc, char*argv[])
|
||||
char*out_path = 0;
|
||||
FILE*out;
|
||||
|
||||
/* Define preprocessor keywords that I plan to just pass. */
|
||||
define_macro("celldefine", "`celldefine", 1);
|
||||
define_macro("default_nettype", "`default_nettype", 1);
|
||||
define_macro("delay_mode_distributed", "`delay_mode_distributed", 1);
|
||||
define_macro("delay_mode_unit", "`delay_mode_unit", 1);
|
||||
define_macro("delay_mode_path", "`delay_mode_path", 1);
|
||||
define_macro("disable_portfaults", "`disable_portfaults", 1);
|
||||
define_macro("enable_portfaults", "`enable_portfaults", 1);
|
||||
define_macro("endcelldefine", "`endcelldefine", 1);
|
||||
define_macro("endprotect", "`endprotect", 1);
|
||||
define_macro("nosuppress_faults", "`nosuppress_faults", 1);
|
||||
define_macro("nounconnected_drive", "`nounconnected_drive", 1);
|
||||
define_macro("protect", "`protect", 1);
|
||||
define_macro("resetall", "`resetall", 1);
|
||||
define_macro("suppress_faults", "`suppress_faults", 1);
|
||||
define_macro("timescale", "`timescale", 1);
|
||||
define_macro("unconnected_drive", "`unconnected_drive", 1);
|
||||
define_macro("uselib", "`uselib", 1);
|
||||
|
||||
include_dir = malloc(sizeof(char*));
|
||||
include_dir[0] = strdup(".");
|
||||
include_cnt = 1;
|
||||
|
||||
while ((opt = getopt(argc, argv, "D:I:Lo:v")) != EOF) switch (opt) {
|
||||
while ((opt = getopt(argc, argv, "D:I:K:Lo:v")) != EOF) switch (opt) {
|
||||
|
||||
case 'D': {
|
||||
char*tmp = strdup(optarg);
|
||||
@@ -73,7 +103,7 @@ int main(int argc, char*argv[])
|
||||
else
|
||||
val = "1";
|
||||
|
||||
define_macro(tmp, val);
|
||||
define_macro(tmp, val, 0);
|
||||
free(tmp);
|
||||
break;
|
||||
}
|
||||
@@ -84,6 +114,15 @@ int main(int argc, char*argv[])
|
||||
include_cnt += 1;
|
||||
break;
|
||||
|
||||
case 'K': {
|
||||
char*buf = malloc(strlen(optarg) + 2);
|
||||
buf[0] = '`';
|
||||
strcpy(buf+1, optarg);
|
||||
define_macro(optarg, buf, 1);
|
||||
free(buf);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'L':
|
||||
line_direct_flag = 1;
|
||||
break;
|
||||
@@ -115,6 +154,7 @@ int main(int argc, char*argv[])
|
||||
fprintf(stderr, "\nUsage: %s [-v][-L][-I<dir>][-D<def>] <file>...\n"
|
||||
" -D<def> - Predefine a value.\n"
|
||||
" -I<dir> - Add an include file search directory\n"
|
||||
" -K<def> - Define a keyword macro that I just pass\n"
|
||||
" -L - Emit line number directives\n"
|
||||
" -o<fil> - Send the output to <fil>\n"
|
||||
" -v - Print version information\n",
|
||||
@@ -138,11 +178,36 @@ int main(int argc, char*argv[])
|
||||
}
|
||||
|
||||
reset_lexor(out, argv+optind);
|
||||
return yyparse();
|
||||
|
||||
if (yyparse()) return -1;
|
||||
|
||||
return error_count;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: main.c,v $
|
||||
* Revision 1.11 2001/07/25 03:10:50 steve
|
||||
* Create a config.h.in file to hold all the config
|
||||
* junk, and support gcc 3.0. (Stephan Boettcher)
|
||||
*
|
||||
* Revision 1.10 2001/06/23 18:41:02 steve
|
||||
* Include stdlib.h
|
||||
*
|
||||
* Revision 1.9 2001/05/20 18:08:07 steve
|
||||
* local declares if the header is missing.
|
||||
*
|
||||
* Revision 1.8 2000/12/06 05:15:21 steve
|
||||
* fix portfaults pass values.
|
||||
*
|
||||
* Revision 1.7 2000/09/13 22:33:13 steve
|
||||
* undefined macros are null (with warnings.)
|
||||
*
|
||||
* Revision 1.6 2000/08/20 17:49:05 steve
|
||||
* Clean up warnings and portability issues.
|
||||
*
|
||||
* Revision 1.5 2000/06/30 15:49:44 steve
|
||||
* Handle errors from parser slightly differently.
|
||||
*
|
||||
* Revision 1.4 1999/11/29 17:02:21 steve
|
||||
* include getopt if present.
|
||||
*
|
||||
|
||||
+2
-2
@@ -18,8 +18,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: parse.y,v 1.1 1999/07/03 17:24:11 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: parse.y,v 1.2 2000/08/20 17:49:05 steve Exp $"
|
||||
#endif
|
||||
|
||||
static void yyerror(const char*msg);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
%{
|
||||
/*
|
||||
* Copyright (c) 1998-1999 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2000 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,10 +18,12 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: lexor.lex,v 1.38 1999/11/23 02:49:04 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: lexor.lex,v 1.62 2001/08/31 17:38:41 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
//# define YYSTYPE lexval
|
||||
|
||||
# include <iostream.h>
|
||||
@@ -30,22 +32,57 @@
|
||||
# include "parse.h"
|
||||
# include <ctype.h>
|
||||
# include <string.h>
|
||||
# include "lexor_keyword.h"
|
||||
|
||||
extern FILE*vl_input;
|
||||
extern string vl_file;
|
||||
|
||||
# define YY_USER_INIT reset_lexor();
|
||||
# define yylval VLlval
|
||||
|
||||
/*
|
||||
* Lexical location information is passed in the yylloc variable to th
|
||||
* parser. The file names, strings, are kept in a list so that I can
|
||||
* re-use them. The set_file_name function will return a pointer to
|
||||
* the name as it exists in the list (and delete the passed string.)
|
||||
* If the name is new, it will be added to the list.
|
||||
*/
|
||||
extern YYLTYPE yylloc;
|
||||
|
||||
struct file_name_cell {
|
||||
const char*text;
|
||||
struct file_name_cell*next;
|
||||
};
|
||||
|
||||
static struct file_name_cell*file_names = 0;
|
||||
|
||||
static const char* set_file_name(char*text)
|
||||
{
|
||||
struct file_name_cell*cur = file_names;
|
||||
while (cur) {
|
||||
if (strcmp(cur->text, text) == 0) {
|
||||
delete[]text;
|
||||
return cur->text;
|
||||
}
|
||||
|
||||
cur = cur->next;
|
||||
}
|
||||
|
||||
cur = new struct file_name_cell;
|
||||
cur->text = text;
|
||||
cur->next = file_names;
|
||||
return text;
|
||||
}
|
||||
|
||||
|
||||
extern void pform_set_timescale(int, int);
|
||||
|
||||
static void reset_lexor();
|
||||
static void line_directive();
|
||||
static void line_directive2();
|
||||
|
||||
extern int check_identifier(const char*str, int len);
|
||||
static verinum*make_sized_binary(const char*txt);
|
||||
static verinum*make_sized_dec(const char*txt);
|
||||
static verinum*make_unsized_dec(const char*txt);
|
||||
static verinum*make_sized_octal(const char*txt);
|
||||
static verinum*make_sized_hex(const char*txt);
|
||||
static verinum*make_unsized_binary(const char*txt);
|
||||
@@ -53,6 +90,8 @@ static verinum*make_unsized_dec(const char*txt);
|
||||
static verinum*make_unsized_octal(const char*txt);
|
||||
static verinum*make_unsized_hex(const char*txt);
|
||||
|
||||
static void process_timescale(const char*txt);
|
||||
|
||||
static int comment_enter;
|
||||
%}
|
||||
|
||||
@@ -93,10 +132,14 @@ W [ \t\b\f\r]+
|
||||
"!==" { return K_CNE; }
|
||||
"||" { return K_LOR; }
|
||||
"&&" { return K_LAND; }
|
||||
"&&&" { return K_TAND; }
|
||||
"~|" { return K_NOR; }
|
||||
"~^" { return K_NXOR; }
|
||||
"^~" { return K_NXOR; }
|
||||
"~&" { return K_NAND; }
|
||||
"->" { return K_TRIGGER; }
|
||||
"+:" { return K_PO_POS; }
|
||||
"-:" { return K_PO_NEG; }
|
||||
|
||||
|
||||
[}{;:\[\],()#=.@&!?<>%|^~+*/-] { return yytext[0]; }
|
||||
@@ -106,6 +149,7 @@ W [ \t\b\f\r]+
|
||||
<CSTRING>\n { BEGIN(0);
|
||||
yylval.text = strdup(yytext);
|
||||
VLerror(yylloc, "Missing close quote of string.");
|
||||
yylloc.first_line += 1;
|
||||
return STRING; }
|
||||
<CSTRING>\" { BEGIN(0);
|
||||
yylval.text = strdup(yytext);
|
||||
@@ -113,72 +157,95 @@ W [ \t\b\f\r]+
|
||||
return STRING; }
|
||||
<CSTRING>. { yymore(); }
|
||||
|
||||
<UDPTABLE>\(\?0\) { return '_'; }
|
||||
<UDPTABLE>\(\?1\) { return '+'; }
|
||||
<UDPTABLE>\(\?x\) { return '%'; }
|
||||
<UDPTABLE>\(\?\?\) { return '*'; }
|
||||
<UDPTABLE>\(01\) { return 'r'; }
|
||||
<UDPTABLE>\(0x\) { return 'P'; }
|
||||
<UDPTABLE>\(10\) { return 'f'; }
|
||||
<UDPTABLE>\(1x\) { return 'N'; }
|
||||
<UDPTABLE>\(x0\) { return 'F'; }
|
||||
<UDPTABLE>\(x1\) { return 'R'; }
|
||||
<UDPTABLE>\(\?0\) { return '_'; }
|
||||
<UDPTABLE>\(\?1\) { return '+'; }
|
||||
<UDPTABLE>\(\?[xX]\) { return '%'; }
|
||||
<UDPTABLE>\(\?\?\) { return '*'; }
|
||||
<UDPTABLE>\(01\) { return 'r'; }
|
||||
<UDPTABLE>\(0[xX]\) { return 'Q'; }
|
||||
<UDPTABLE>\(0\?\) { return 'P'; }
|
||||
<UDPTABLE>\(10\) { return 'f'; }
|
||||
<UDPTABLE>\(1[xX]\) { return 'M'; }
|
||||
<UDPTABLE>\(1\?\) { return 'N'; }
|
||||
<UDPTABLE>\([xX]0\) { return 'F'; }
|
||||
<UDPTABLE>\([xX]1\) { return 'R'; }
|
||||
<UDPTABLE>\([xX]\?\) { return 'B'; }
|
||||
<UDPTABLE>[bB] { return 'b'; }
|
||||
<UDPTABLE>[lL] { return 'l'; /* IVL extension */ }
|
||||
<UDPTABLE>[hH] { return 'h'; /* IVL extension */ }
|
||||
<UDPTABLE>[fF] { return 'f'; }
|
||||
<UDPTABLE>[rR] { return 'r'; }
|
||||
<UDPTABLE>[xX] { return 'x'; }
|
||||
<UDPTABLE>[pPnN01\?\*\-] { return yytext[0]; }
|
||||
<UDPTABLE>[nN] { return 'n'; }
|
||||
<UDPTABLE>[pP] { return 'p'; }
|
||||
<UDPTABLE>[01\?\*\-] { return yytext[0]; }
|
||||
|
||||
[a-zA-Z_][a-zA-Z0-9$_]* {
|
||||
int rc = check_identifier(yytext, yyleng);
|
||||
int rc = lexor_keyword_code(yytext, yyleng);
|
||||
if (rc == IDENTIFIER)
|
||||
yylval.text = strdup(yytext);
|
||||
else
|
||||
yylval.text = 0;
|
||||
|
||||
return rc; }
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
[a-zA-Z_][a-zA-Z0-9$_]*(\.[a-zA-Z_][a-zA-Z0-9$_]*)+ {
|
||||
yylval.text = strdup(yytext);
|
||||
return HIDENTIFIER; }
|
||||
|
||||
\\[^ \t\b\f\r]+ {
|
||||
yylval.text = strdup(yytext);
|
||||
yylval.text = strdup(yytext+1);
|
||||
return IDENTIFIER; }
|
||||
|
||||
\$([a-zA-Z0-9$_]+) {
|
||||
if (strcmp(yytext,"$setuphold") == 0)
|
||||
return K_Ssetuphold;
|
||||
if (strcmp(yytext,"$attribute") == 0)
|
||||
return KK_attribute;
|
||||
if (strcmp(yytext,"$hold") == 0)
|
||||
return K_Shold;
|
||||
if (strcmp(yytext,"$period") == 0)
|
||||
return K_Speriod;
|
||||
if (strcmp(yytext,"$recovery") == 0)
|
||||
return K_Srecovery;
|
||||
if (strcmp(yytext,"$setup") == 0)
|
||||
return K_Ssetup;
|
||||
if (strcmp(yytext,"$width") == 0)
|
||||
return K_Swidth;
|
||||
yylval.text = strdup(yytext);
|
||||
return SYSTEM_IDENTIFIER; }
|
||||
|
||||
\.{W}?[a-zA-Z_][a-zA-Z0-9$_]* {
|
||||
\.{W}?(([a-zA-Z_][a-zA-Z0-9$_]*)|(\\[^ \t\b\f\r]+)) {
|
||||
char*cp = yytext+1;
|
||||
while (! (isalpha(*cp) || (*cp == '_')))
|
||||
while ( (!(isalpha(*cp) || (*cp == '_'))) && (*cp != '\\'))
|
||||
cp += 1;
|
||||
if (*cp == '\\')
|
||||
cp++;
|
||||
yylval.text = strdup(cp);
|
||||
return PORTNAME; }
|
||||
|
||||
[0-9][0-9_]*[ \t]*\'[dD][ \t]*[0-9][0-9_]* {
|
||||
[0-9][0-9_]*[ \t]*\'[sS]?[dD][ \t]*[0-9][0-9_]* {
|
||||
yylval.number = make_sized_dec(yytext);
|
||||
return NUMBER; }
|
||||
[0-9][0-9_]*[ \t]*\'[bB][ \t]*[0-1xzXZ_\?]+ {
|
||||
[0-9][0-9_]*[ \t]*\'[sS]?[bB][ \t]*[0-1xzXZ_\?]+ {
|
||||
yylval.number = make_sized_binary(yytext);
|
||||
return NUMBER; }
|
||||
[0-9][0-9_]*[ \t]*\'[oO][ \t]*[0-7xzXZ_\?]+ {
|
||||
[0-9][0-9_]*[ \t]*\'[sS]?[oO][ \t]*[0-7xzXZ_\?]+ {
|
||||
yylval.number = make_sized_octal(yytext);
|
||||
return NUMBER; }
|
||||
[0-9][0-9_]*[ \t]*\'[hH][ \t]*[0-9a-fA-FxzXZ_\?]+ {
|
||||
[0-9][0-9_]*[ \t]*\'[sS]?[hH][ \t]*[0-9a-fA-FxzXZ_\?]+ {
|
||||
yylval.number = make_sized_hex(yytext);
|
||||
return NUMBER; }
|
||||
|
||||
\'d[ \t]*[0-9][0-9_]* { yylval.number = make_unsized_dec(yytext);
|
||||
return NUMBER; }
|
||||
\'[bB][ \t]*[0-1xzXZ_\?]+ { yylval.number = make_unsized_binary(yytext);
|
||||
\'[sS]?[dD][ \t]*[0-9][0-9_]* { yylval.number = make_unsized_dec(yytext);
|
||||
return NUMBER; }
|
||||
\'[sS]?[bB][ \t]*[0-1xzXZ_\?]+ { yylval.number = make_unsized_binary(yytext);
|
||||
return NUMBER; }
|
||||
\'[oO][ \t]*[0-7xzXZ_\?]+ { yylval.number = make_unsized_octal(yytext);
|
||||
\'[sS]?[oO][ \t]*[0-7xzXZ_\?]+ { yylval.number = make_unsized_octal(yytext);
|
||||
return NUMBER; }
|
||||
\'[hH][ \t]*[0-9a-fA-FxzXZ_\?]+ { yylval.number = make_unsized_hex(yytext);
|
||||
\'[sS]?[hH][ \t]*[0-9a-fA-FxzXZ_\?]+ { yylval.number = make_unsized_hex(yytext);
|
||||
return NUMBER; }
|
||||
|
||||
[0-9][0-9_]* {
|
||||
@@ -198,6 +265,7 @@ W [ \t\b\f\r]+
|
||||
}
|
||||
|
||||
yylval.number = new verinum(bits, nbits, false);
|
||||
yylval.number->has_sign(true);
|
||||
delete[]bits;
|
||||
return NUMBER; }
|
||||
|
||||
@@ -212,11 +280,9 @@ W [ \t\b\f\r]+
|
||||
|
||||
/* Notice and handle the timescale directive. */
|
||||
|
||||
`timescale { BEGIN(PPTIMESCALE); }
|
||||
<PPTIMESCALE>. { ; }
|
||||
^{W}?`timescale { BEGIN(PPTIMESCALE); }
|
||||
<PPTIMESCALE>.* { process_timescale(yytext); }
|
||||
<PPTIMESCALE>\n {
|
||||
cerr << yylloc.text << ":" << yylloc.first_line
|
||||
<< ": Sorry, `timescale not supported." << endl;
|
||||
yylloc.first_line += 1;
|
||||
BEGIN(0); }
|
||||
|
||||
@@ -224,28 +290,28 @@ W [ \t\b\f\r]+
|
||||
/* These are directives that I do not yet support. I think that IVL
|
||||
should handle these, not an external preprocessor. */
|
||||
|
||||
^`celldefine{W}?.* { }
|
||||
^`default_nettype{W}?.* { }
|
||||
^`delay_mode_distributed{W}?.* { }
|
||||
^`delay_mode_unit{W}?.* { }
|
||||
^`delay_mode_path{W}?.* { }
|
||||
^`disable_portfaults{W}?.* { }
|
||||
^`enable_portfaults{W}?.* { }
|
||||
^`endcelldefine{W}?.* { }
|
||||
^`endprotect{W}?.* { }
|
||||
^`nosuppress_faults{W}?.* { }
|
||||
^`nounconnected_drive{W}?* { }
|
||||
^`protect{W}?.* { }
|
||||
^`resetall{W}?.* { }
|
||||
^`suppress_faults{W}?.* { }
|
||||
^`unconnected_drive{W}?* { }
|
||||
^`uselib{W}?.* { }
|
||||
^{W}?`celldefine{W}?.* { }
|
||||
^{W}?`default_nettype{W}?.* { }
|
||||
^{W}?`delay_mode_distributed{W}?.* { }
|
||||
^{W}?`delay_mode_unit{W}?.* { }
|
||||
^{W}?`delay_mode_path{W}?.* { }
|
||||
^{W}?`disable_portfaults{W}?.* { }
|
||||
^{W}?`enable_portfaults{W}?.* { }
|
||||
^{W}?`endcelldefine{W}?.* { }
|
||||
^{W}?`endprotect{W}?.* { }
|
||||
^{W}?`nosuppress_faults{W}?.* { }
|
||||
^{W}?`nounconnected_drive{W}?.* { }
|
||||
^{W}?`protect{W}?.* { }
|
||||
^{W}?`resetall{W}?.* { }
|
||||
^{W}?`suppress_faults{W}?.* { }
|
||||
^{W}?`unconnected_drive{W}?.* { }
|
||||
^{W}?`uselib{W}?.* { }
|
||||
|
||||
|
||||
/* These are directives that are not supported by me and should have
|
||||
been handled by an external preprocessor such as ivlpp. */
|
||||
|
||||
^`define{W}?.* {
|
||||
^{W}?`define{W}?.* {
|
||||
cerr << yylloc.text << ":" << yylloc.first_line <<
|
||||
": `define not supported. Use an external preprocessor."
|
||||
<< endl;
|
||||
@@ -312,22 +378,27 @@ void lex_end_table()
|
||||
|
||||
static verinum*make_binary_with_size(unsigned size, bool fixed, const char*ptr)
|
||||
{
|
||||
assert(tolower(*ptr) == 'b');
|
||||
bool sign_flag = false;
|
||||
verinum::V*bits = new verinum::V[size];
|
||||
|
||||
if (tolower(ptr[0]) == 's') {
|
||||
ptr += 1;
|
||||
sign_flag = true;
|
||||
}
|
||||
assert(tolower(*ptr) == 'b');
|
||||
ptr += 1;
|
||||
|
||||
while (*ptr && ((*ptr == ' ') || (*ptr == '\t')))
|
||||
ptr += 1;
|
||||
|
||||
unsigned idx = 0;
|
||||
const char*eptr = ptr + strlen(ptr) - 1;
|
||||
while ((eptr > ptr) && (idx < size)) {
|
||||
|
||||
if (*eptr == '_') {
|
||||
eptr -= 1;
|
||||
continue;
|
||||
}
|
||||
while ((eptr >= ptr) && (idx < size)) {
|
||||
|
||||
switch (*eptr) {
|
||||
case '_':
|
||||
break;
|
||||
case '0':
|
||||
bits[idx++] = verinum::V0;
|
||||
break;
|
||||
@@ -346,10 +417,22 @@ static verinum*make_binary_with_size(unsigned size, bool fixed, const char*ptr)
|
||||
|
||||
eptr -= 1;
|
||||
}
|
||||
|
||||
|
||||
/* If we filled up the expected number of bits, but there are
|
||||
still characters of the number part left, then report a
|
||||
warning that we are truncating. */
|
||||
|
||||
if ((idx >= size) && (eptr >= ptr))
|
||||
cerr << yylloc.text << ":" << yylloc.first_line <<
|
||||
": warning: Numeric binary constant ``" << ptr <<
|
||||
"'' truncated to " << size << " bits." << endl;
|
||||
|
||||
|
||||
// Zero-extend binary number, except that z or x is extended
|
||||
// if it is the highest supplied digit.
|
||||
while (idx < size) {
|
||||
switch (ptr[1]) {
|
||||
switch (ptr[0]) {
|
||||
case '0':
|
||||
case '1':
|
||||
bits[idx++] = verinum::V0;
|
||||
@@ -365,7 +448,10 @@ static verinum*make_binary_with_size(unsigned size, bool fixed, const char*ptr)
|
||||
}
|
||||
}
|
||||
|
||||
return new verinum(bits, size, fixed);
|
||||
verinum*out = new verinum(bits, size, fixed);
|
||||
delete[]bits;
|
||||
out->has_sign(sign_flag);
|
||||
return out;
|
||||
}
|
||||
|
||||
static verinum*make_sized_binary(const char*txt)
|
||||
@@ -376,16 +462,21 @@ static verinum*make_sized_binary(const char*txt)
|
||||
ptr += 1;
|
||||
assert(*ptr == '\'');
|
||||
ptr += 1;
|
||||
assert(tolower(*ptr) == 'b');
|
||||
|
||||
return make_binary_with_size(size, true, ptr);
|
||||
}
|
||||
|
||||
static verinum*make_unsized_binary(const char*txt)
|
||||
{
|
||||
bool sign_flag = false;
|
||||
const char*ptr = txt;
|
||||
assert(*ptr == '\'');
|
||||
ptr += 1;
|
||||
|
||||
if (tolower(*ptr) == 's') {
|
||||
sign_flag = true;
|
||||
ptr += 1;
|
||||
}
|
||||
assert(tolower(*ptr) == 'b');
|
||||
while (*ptr && ((*ptr == 'b') || (*ptr == ' ') || (*ptr == '\t')))
|
||||
ptr += 1;
|
||||
@@ -420,100 +511,114 @@ static verinum*make_unsized_binary(const char*txt)
|
||||
ptr += 1;
|
||||
}
|
||||
|
||||
return new verinum(bits, size);
|
||||
verinum*out = new verinum(bits, size);
|
||||
out->has_sign(sign_flag);
|
||||
delete[]bits;
|
||||
return out;
|
||||
}
|
||||
|
||||
static verinum*make_sized_octal(const char*txt)
|
||||
{
|
||||
bool sign_flag = false;
|
||||
char*ptr;
|
||||
|
||||
unsigned size = strtoul(txt,&ptr,10);
|
||||
while (*ptr && ((*ptr == ' ') || (*ptr == '\t')))
|
||||
ptr += 1;
|
||||
assert(*ptr == '\'');
|
||||
ptr += 1;
|
||||
assert(tolower(*ptr) == 'o');
|
||||
|
||||
/* We know from the size number how bit to make the verinom
|
||||
if (tolower(*ptr) == 's') {
|
||||
sign_flag = true;
|
||||
ptr += 1;
|
||||
}
|
||||
assert(tolower(*ptr) == 'o');
|
||||
ptr += 1;
|
||||
|
||||
/* We know from the size number how bit to make the verinum
|
||||
array, so make it now. */
|
||||
verinum::V*bits = new verinum::V[size];
|
||||
verinum::V*bits = new verinum::V[(size+2)/3 * 3];
|
||||
|
||||
/* skip white space between size and the base token. */
|
||||
while (*ptr && ((*ptr == ' ') || (*ptr == '\t')))
|
||||
ptr += 1;
|
||||
|
||||
/* Find the end of the digits. ptr already points to the start. */
|
||||
char*eptr = ptr + strlen(ptr);
|
||||
|
||||
/* From the last digit and forward, build up the number, least
|
||||
significant bit first. This loop will not get the last few
|
||||
bits if the size is not a multiple of 3. */
|
||||
/* Get a pointer to the last character of the number string,
|
||||
then work back from there (the least significant digit)
|
||||
forward until I run out of digits or space to put them. */
|
||||
char*eptr = ptr + strlen(ptr) - 1;
|
||||
unsigned idx = 0;
|
||||
while ((eptr > ptr) && ((idx/3) < (size/3))) switch (*--eptr) {
|
||||
|
||||
while ((eptr >= ptr) && (idx < size)) {
|
||||
switch (*eptr) {
|
||||
case 'x': case 'X':
|
||||
bits[idx++] = verinum::Vx;
|
||||
bits[idx++] = verinum::Vx;
|
||||
bits[idx++] = verinum::Vx;
|
||||
break;
|
||||
|
||||
case 'z': case 'Z': case '?':
|
||||
bits[idx++] = verinum::Vz;
|
||||
bits[idx++] = verinum::Vz;
|
||||
bits[idx++] = verinum::Vz;
|
||||
break;
|
||||
|
||||
default: {
|
||||
unsigned val = *eptr - '0';
|
||||
bits[idx++] = (val&1)? verinum::V1 : verinum::V0;
|
||||
bits[idx++] = (val&2)? verinum::V1 : verinum::V0;
|
||||
bits[idx++] = (val&4)? verinum::V1 : verinum::V0;
|
||||
}
|
||||
}
|
||||
|
||||
if ((eptr > ptr) && (idx < size)) switch (*--eptr) {
|
||||
|
||||
case 'x': case 'X':
|
||||
for ( ; idx < size ; idx += 1)
|
||||
bits[idx] = verinum::Vx;
|
||||
break;
|
||||
|
||||
case 'z': case 'Z': case '?':
|
||||
for ( ; idx < size ; idx += 1)
|
||||
bits[idx] = verinum::Vz;
|
||||
break;
|
||||
|
||||
default: {
|
||||
unsigned val = *eptr - '0';
|
||||
for ( ; idx < size ; idx += 1) {
|
||||
bits[idx] = (val&1)? verinum::V1 : verinum::V0;
|
||||
val >>= 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// zero extend octal numbers
|
||||
while (idx < size) switch (ptr[1]) {
|
||||
case 'x': case 'X':
|
||||
bits[idx++] = verinum::Vx;
|
||||
break;
|
||||
case 'z': case 'Z': case '?':
|
||||
bits[idx++] = verinum::Vz;
|
||||
case '0': case '1': case '2': case '3':
|
||||
case '4': case '5': case '6': case '7':
|
||||
{
|
||||
unsigned val = *eptr - '0';
|
||||
bits[idx++] = (val&1)? verinum::V1 : verinum::V0;
|
||||
bits[idx++] = (val&2)? verinum::V1 : verinum::V0;
|
||||
bits[idx++] = (val&4)? verinum::V1 : verinum::V0;
|
||||
break;
|
||||
}
|
||||
case '_':
|
||||
break;
|
||||
default:
|
||||
bits[idx++] = verinum::V0;
|
||||
assert(0);
|
||||
}
|
||||
|
||||
eptr -= 1;
|
||||
}
|
||||
|
||||
return new verinum(bits, size, true);
|
||||
/* If we filled up all the bits and there are still characters
|
||||
in the number string, then we overflowed. Report a warning
|
||||
that we are truncating. */
|
||||
if ((idx >= size) && (eptr >= ptr))
|
||||
cerr << yylloc.text << ":" << yylloc.first_line <<
|
||||
": warning: Numeric octal constant ``" << ptr <<
|
||||
"'' truncated to " << size << " bits." << endl;
|
||||
|
||||
|
||||
/* If we did not fill up all the bits from the string, then
|
||||
zero-extend the number. */
|
||||
while (idx < size) switch (ptr[1]) {
|
||||
case 'x': case 'X':
|
||||
bits[idx++] = verinum::Vx;
|
||||
break;
|
||||
case 'z': case 'Z': case '?':
|
||||
bits[idx++] = verinum::Vz;
|
||||
break;
|
||||
default:
|
||||
bits[idx++] = verinum::V0;
|
||||
}
|
||||
|
||||
verinum*out = new verinum(bits, size, true);
|
||||
delete[]bits;
|
||||
out->has_sign(sign_flag);
|
||||
return out;
|
||||
}
|
||||
|
||||
static verinum*make_unsized_octal(const char*txt)
|
||||
{
|
||||
bool sign_flag = false;
|
||||
const char*ptr = txt;
|
||||
assert(*ptr == '\'');
|
||||
ptr += 1;
|
||||
|
||||
if (tolower(*ptr) == 's') {
|
||||
sign_flag = true;
|
||||
ptr += 1;
|
||||
}
|
||||
|
||||
assert(tolower(*ptr) == 'o');
|
||||
ptr += 1;
|
||||
|
||||
@@ -555,11 +660,15 @@ static verinum*make_unsized_octal(const char*txt)
|
||||
ptr += 1;
|
||||
}
|
||||
|
||||
return new verinum(bits, size);
|
||||
verinum*out = new verinum(bits, size);
|
||||
out->has_sign(sign_flag);
|
||||
delete[]bits;
|
||||
return out;
|
||||
}
|
||||
|
||||
static verinum*make_sized_hex(const char*txt)
|
||||
{
|
||||
bool sign_flag = false;
|
||||
char*ptr;
|
||||
unsigned size = strtoul(txt,&ptr,10);
|
||||
|
||||
@@ -568,6 +677,12 @@ static verinum*make_sized_hex(const char*txt)
|
||||
|
||||
assert(*ptr == '\'');
|
||||
ptr += 1;
|
||||
|
||||
if (tolower(*ptr) == 's') {
|
||||
sign_flag = true;
|
||||
ptr += 1;
|
||||
}
|
||||
|
||||
assert(tolower(*ptr) == 'h');
|
||||
|
||||
ptr += 1;
|
||||
@@ -622,7 +737,15 @@ static verinum*make_sized_hex(const char*txt)
|
||||
eptr -= 1;
|
||||
}
|
||||
|
||||
// zero extend octal numbers
|
||||
/* If we filled up the expected number of bits, but there are
|
||||
still characters of the number part left, then report a
|
||||
warning that we are truncating. */
|
||||
if ((idx >= size) && (eptr >= ptr))
|
||||
cerr << yylloc.text << ":" << yylloc.first_line <<
|
||||
": warning: Numeric hex constant ``" << ptr <<
|
||||
"'' truncated to " << size << " bits." << endl;
|
||||
|
||||
// zero extend hex numbers
|
||||
while (idx < size) switch (ptr[1]) {
|
||||
case 'x': case 'X':
|
||||
bits[idx++] = verinum::Vx;
|
||||
@@ -634,14 +757,23 @@ static verinum*make_sized_hex(const char*txt)
|
||||
bits[idx++] = verinum::V0;
|
||||
}
|
||||
|
||||
return new verinum(bits, size, true);
|
||||
verinum*out = new verinum(bits, size, true);
|
||||
out->has_sign(sign_flag);
|
||||
delete[]bits;
|
||||
return out;
|
||||
}
|
||||
|
||||
static verinum*make_unsized_hex(const char*txt)
|
||||
{
|
||||
bool sign_flag = false;
|
||||
const char*ptr = txt;
|
||||
assert(*ptr == '\'');
|
||||
ptr += 1;
|
||||
|
||||
if (tolower(*ptr) == 's') {
|
||||
sign_flag = true;
|
||||
ptr += 1;
|
||||
}
|
||||
assert(tolower(*ptr) == 'h');
|
||||
|
||||
ptr += 1;
|
||||
@@ -694,7 +826,10 @@ static verinum*make_unsized_hex(const char*txt)
|
||||
ptr += 1;
|
||||
}
|
||||
|
||||
return new verinum(bits, size);
|
||||
verinum*out = new verinum(bits, size);
|
||||
out->has_sign(sign_flag);
|
||||
delete[]bits;
|
||||
return out;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -703,15 +838,30 @@ static verinum*make_unsized_hex(const char*txt)
|
||||
*/
|
||||
static verinum*make_dec_with_size(unsigned size, bool fixed, const char*ptr)
|
||||
{
|
||||
bool signed_flag = false;
|
||||
if (tolower(*ptr) == 's') {
|
||||
signed_flag = true;
|
||||
ptr += 1;
|
||||
}
|
||||
assert(tolower(*ptr) == 'd');
|
||||
|
||||
ptr += 1;
|
||||
while (*ptr && ((*ptr == ' ') || (*ptr == '\t')))
|
||||
ptr += 1;
|
||||
|
||||
|
||||
const char*digits = ptr;
|
||||
|
||||
/* Convert the decimal number to a binary value, one digit at
|
||||
a time. Watch out for overflow. */
|
||||
|
||||
unsigned long value = 0;
|
||||
for ( ; *ptr ; ptr += 1)
|
||||
if (isdigit(*ptr)) {
|
||||
unsigned long tmp = value * 10 + (*ptr - '0');
|
||||
if (tmp < value)
|
||||
cerr << yylloc.text << ":" << yylloc.first_line <<
|
||||
": warning: Numeric decimal constant ``"
|
||||
<< digits << "'' is too large." << endl;
|
||||
value *= 10;
|
||||
value += *ptr - '0';
|
||||
} else {
|
||||
@@ -726,7 +876,18 @@ static verinum*make_dec_with_size(unsigned size, bool fixed, const char*ptr)
|
||||
value /= 2;
|
||||
}
|
||||
|
||||
return new verinum(bits, size, fixed);
|
||||
/* If we run out of bits to hold the value, but there are
|
||||
still valueable bits in the number, print a warning. */
|
||||
|
||||
if (value != 0)
|
||||
cerr << yylloc.text << ":" << yylloc.first_line <<
|
||||
": warning: Numeric decimal constant ``" << digits <<
|
||||
"'' truncated to " << size << " bits." << endl;
|
||||
|
||||
verinum*out = new verinum(bits, size, fixed);
|
||||
out->has_sign(signed_flag);
|
||||
delete[]bits;
|
||||
return out;
|
||||
}
|
||||
|
||||
static verinum*make_sized_dec(const char*txt)
|
||||
@@ -739,7 +900,6 @@ static verinum*make_sized_dec(const char*txt)
|
||||
|
||||
assert(*ptr == '\'');
|
||||
ptr += 1;
|
||||
assert(tolower(*ptr) == 'd');
|
||||
|
||||
return make_dec_with_size(size, true, ptr);
|
||||
}
|
||||
@@ -749,8 +909,111 @@ static verinum*make_unsized_dec(const char*txt)
|
||||
return make_dec_with_size(INTEGER_WIDTH, false, txt+1);
|
||||
}
|
||||
|
||||
/*
|
||||
* The timescale parameter has the form:
|
||||
* " <num> xs / <num> xs"
|
||||
*/
|
||||
static void process_timescale(const char*txt)
|
||||
{
|
||||
unsigned num;
|
||||
const char*cp = txt + strspn(txt, " \t");
|
||||
char*tmp;
|
||||
const char*ctmp;
|
||||
|
||||
static int yywrap()
|
||||
int unit = 0;
|
||||
int prec = 0;
|
||||
|
||||
num = strtoul(cp, &tmp, 10);
|
||||
if (num == 0) {
|
||||
VLerror(yylloc, "Invalid timescale string.");
|
||||
return;
|
||||
}
|
||||
|
||||
while (num >= 10) {
|
||||
unit += 1;
|
||||
num /= 10;
|
||||
}
|
||||
if (num != 1) {
|
||||
VLerror(yylloc, "Invalid timescale unit number.");
|
||||
return;
|
||||
}
|
||||
|
||||
cp = tmp;
|
||||
cp += strspn(cp, " \t");
|
||||
ctmp = cp + strcspn(cp, " \t/");
|
||||
|
||||
if (strncmp("s", cp, ctmp-cp) == 0) {
|
||||
unit -= 0;
|
||||
|
||||
} else if (strncmp("ms", cp, ctmp-cp) == 0) {
|
||||
unit -= 3;
|
||||
|
||||
} else if (strncmp("us", cp, ctmp-cp) == 0) {
|
||||
unit -= 6;
|
||||
|
||||
} else if (strncmp("ns", cp, ctmp-cp) == 0) {
|
||||
unit -= 9;
|
||||
|
||||
} else if (strncmp("ps", cp, ctmp-cp) == 0) {
|
||||
unit -= 12;
|
||||
|
||||
} else if (strncmp("fs", cp, ctmp-cp) == 0) {
|
||||
unit -= 15;
|
||||
|
||||
} else {
|
||||
VLerror(yylloc, "Invalid timescale unit of measurement");
|
||||
return;
|
||||
}
|
||||
|
||||
cp = ctmp;
|
||||
cp += strspn(cp, " \t/");
|
||||
|
||||
num = strtoul(cp, &tmp, 10);
|
||||
if (num == 0) {
|
||||
VLerror(yylloc, "Invalid timescale string.");
|
||||
return;
|
||||
}
|
||||
assert(num);
|
||||
while (num >= 10) {
|
||||
prec += 1;
|
||||
num /= 10;
|
||||
}
|
||||
if (num != 1) {
|
||||
VLerror(yylloc, "Invalid timescale precision number.");
|
||||
return;
|
||||
}
|
||||
|
||||
cp = tmp;
|
||||
cp += strspn(cp, " \t");
|
||||
ctmp = cp + strcspn(cp, " \t\r");
|
||||
|
||||
if (strncmp("s", cp, ctmp-cp) == 0) {
|
||||
prec -= 0;
|
||||
|
||||
} else if (strncmp("ms", cp, ctmp-cp) == 0) {
|
||||
prec -= 3;
|
||||
|
||||
} else if (strncmp("us", cp, ctmp-cp) == 0) {
|
||||
prec -= 6;
|
||||
|
||||
} else if (strncmp("ns", cp, ctmp-cp) == 0) {
|
||||
prec -= 9;
|
||||
|
||||
} else if (strncmp("ps", cp, ctmp-cp) == 0) {
|
||||
prec -= 12;
|
||||
|
||||
} else if (strncmp("fs", cp, ctmp-cp) == 0) {
|
||||
prec -= 15;
|
||||
|
||||
} else {
|
||||
VLerror(yylloc, "Invalid timescale precision units of measurement");
|
||||
return;
|
||||
}
|
||||
|
||||
pform_set_timescale(unit, prec);
|
||||
}
|
||||
|
||||
int yywrap()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
@@ -773,8 +1036,7 @@ static void line_directive()
|
||||
strncpy(buf, qt1, qt2-qt1);
|
||||
buf[qt2-qt1] = 0;
|
||||
|
||||
delete[]yylloc.text;
|
||||
yylloc.text = buf;
|
||||
yylloc.text = set_file_name(buf);
|
||||
|
||||
qt2 += 1;
|
||||
yylloc.first_line = strtoul(qt2,0,0);
|
||||
@@ -801,13 +1063,19 @@ static void line_directive2()
|
||||
strncpy(buf, qt1, qt2-qt1);
|
||||
buf[qt2-qt1] = 0;
|
||||
|
||||
delete[]yylloc.text;
|
||||
yylloc.text = buf;
|
||||
yylloc.text = set_file_name(buf);
|
||||
}
|
||||
|
||||
static void reset_lexor()
|
||||
{
|
||||
yyrestart(vl_input);
|
||||
yylloc.first_line = 1;
|
||||
yylloc.text = strdup(vl_file.c_str());
|
||||
|
||||
/* Start the file_names list. From here on, as I get a file
|
||||
name, I will add it to this list. Only add the name if it
|
||||
is not already in the list. */
|
||||
file_names = new struct file_name_cell;
|
||||
file_names->text = strdup(vl_file.c_str());
|
||||
file_names->next = 0;
|
||||
yylloc.text = file_names->text;
|
||||
}
|
||||
|
||||
@@ -1,230 +0,0 @@
|
||||
/* C code produced by gperf version 2.7 */
|
||||
/* Command-line: gperf -o -i 1 -C -k 1-3,$ -L C -H keyword_hash -N check_identifier -tT lexor_keyword.gperf > lexor_keyword.cc */
|
||||
|
||||
#include "parse_misc.h"
|
||||
#include "parse.h"
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#define TOTAL_KEYWORDS 99
|
||||
#define MIN_WORD_LENGTH 2
|
||||
#define MAX_WORD_LENGTH 12
|
||||
#define MIN_HASH_VALUE 7
|
||||
#define MAX_HASH_VALUE 239
|
||||
/* maximum key range = 233, duplicates = 0 */
|
||||
|
||||
#ifdef __GNUC__
|
||||
__inline
|
||||
#endif
|
||||
static unsigned int
|
||||
keyword_hash (const char *str, int len)
|
||||
{
|
||||
static const unsigned char asso_values[] =
|
||||
{
|
||||
240, 240, 240, 240, 240, 240, 240, 240, 240, 240,
|
||||
240, 240, 240, 240, 240, 240, 240, 240, 240, 240,
|
||||
240, 240, 240, 240, 240, 240, 240, 240, 240, 240,
|
||||
240, 240, 240, 240, 240, 240, 240, 240, 240, 240,
|
||||
240, 240, 240, 240, 240, 240, 240, 240, 126, 66,
|
||||
240, 240, 240, 240, 240, 240, 240, 240, 240, 240,
|
||||
240, 240, 240, 240, 240, 240, 240, 240, 240, 240,
|
||||
240, 240, 240, 240, 240, 240, 240, 240, 240, 240,
|
||||
240, 240, 240, 240, 240, 240, 240, 240, 240, 240,
|
||||
240, 240, 240, 240, 240, 240, 240, 31, 11, 81,
|
||||
1, 1, 81, 26, 11, 51, 11, 21, 81, 81,
|
||||
1, 46, 16, 240, 1, 1, 6, 11, 36, 46,
|
||||
21, 16, 6, 240, 240, 240, 240, 240, 240, 240,
|
||||
240, 240, 240, 240, 240, 240, 240, 240, 240, 240,
|
||||
240, 240, 240, 240, 240, 240, 240, 240, 240, 240,
|
||||
240, 240, 240, 240, 240, 240, 240, 240, 240, 240,
|
||||
240, 240, 240, 240, 240, 240, 240, 240, 240, 240,
|
||||
240, 240, 240, 240, 240, 240, 240, 240, 240, 240,
|
||||
240, 240, 240, 240, 240, 240, 240, 240, 240, 240,
|
||||
240, 240, 240, 240, 240, 240, 240, 240, 240, 240,
|
||||
240, 240, 240, 240, 240, 240, 240, 240, 240, 240,
|
||||
240, 240, 240, 240, 240, 240, 240, 240, 240, 240,
|
||||
240, 240, 240, 240, 240, 240, 240, 240, 240, 240,
|
||||
240, 240, 240, 240, 240, 240, 240, 240, 240, 240,
|
||||
240, 240, 240, 240, 240, 240, 240, 240, 240, 240,
|
||||
240, 240, 240, 240, 240, 240
|
||||
};
|
||||
int hval = len;
|
||||
|
||||
hval += asso_values[(unsigned char)str[len - 1]];
|
||||
hval += asso_values[(unsigned char)str[0]];
|
||||
hval += asso_values[(unsigned char)str[1]];
|
||||
|
||||
if (len > 2)
|
||||
hval += asso_values[(unsigned char)str[2]];
|
||||
|
||||
return hval ;
|
||||
}
|
||||
|
||||
int
|
||||
check_identifier (const char *str, int len)
|
||||
{
|
||||
static const struct { const char *name; int tokenType; } wordlist[] =
|
||||
{
|
||||
{""}, {""}, {""}, {""}, {""}, {""}, {""},
|
||||
{"end", K_end},
|
||||
{""}, {""}, {""},
|
||||
{"endcase", K_endcase},
|
||||
{"endtable", K_endtable},
|
||||
{"endmodule", K_endmodule},
|
||||
{"rtran", K_rtran},
|
||||
{"endfunction", K_endfunction},
|
||||
{"endprimitive", K_endprimitive},
|
||||
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
|
||||
{""}, {""}, {""},
|
||||
{"endspecify", K_endspecify},
|
||||
{"repeat", K_repeat},
|
||||
{"endtask", K_endtask},
|
||||
{""},
|
||||
{"edge", K_edge},
|
||||
{""}, {""},
|
||||
{"negedge", K_negedge},
|
||||
{"and", K_and},
|
||||
{"nand", K_nand},
|
||||
{""},
|
||||
{"assign", K_assign},
|
||||
{"specify", K_specify},
|
||||
{"deassign", K_deassign},
|
||||
{"tran", K_tran},
|
||||
{"begin", K_begin},
|
||||
{""}, {""}, {""}, {""},
|
||||
{"event", K_event},
|
||||
{"or", K_or},
|
||||
{""},
|
||||
{"nor", K_nor},
|
||||
{""},
|
||||
{"table", K_table},
|
||||
{""}, {""},
|
||||
{"reg", K_reg},
|
||||
{"parameter", K_parameter},
|
||||
{""}, {""},
|
||||
{"disable", K_disable},
|
||||
{"not", K_not},
|
||||
{"task", K_task},
|
||||
{"trior", K_trior},
|
||||
{"triand", K_triand},
|
||||
{"integer", K_integer},
|
||||
{""}, {""}, {""}, {""},
|
||||
{"posedge", K_posedge},
|
||||
{"xor", K_xor},
|
||||
{"xnor", K_xnor},
|
||||
{""},
|
||||
{"output", K_output},
|
||||
{""}, {""},
|
||||
{"primitive", K_primitive},
|
||||
{"input", K_input},
|
||||
{""},
|
||||
{"strong1", K_strong1},
|
||||
{"rtranif1", K_rtranif1},
|
||||
{"wand", K_wand},
|
||||
{""}, {""}, {""}, {""},
|
||||
{"else", K_else},
|
||||
{"rnmos", K_rnmos},
|
||||
{"trireg", K_trireg},
|
||||
{"release", K_release},
|
||||
{""}, {""}, {""}, {""},
|
||||
{"default", K_default},
|
||||
{"wor", K_wor},
|
||||
{""}, {""}, {""},
|
||||
{"supply1", K_supply1},
|
||||
{"function", K_function},
|
||||
{"wire", K_wire},
|
||||
{"rpmos", K_rpmos},
|
||||
{""}, {""}, {""},
|
||||
{"specparam", K_specparam},
|
||||
{"inout", K_inout},
|
||||
{""},
|
||||
{"tranif1", K_tranif1},
|
||||
{"tri", K_tri},
|
||||
{"join", K_join},
|
||||
{"while", K_while},
|
||||
{""}, {""},
|
||||
{"pulldown", K_pulldown},
|
||||
{"case", K_case},
|
||||
{"large", K_large},
|
||||
{""}, {""},
|
||||
{"scalered", K_scalered},
|
||||
{""},
|
||||
{"casez", K_casez},
|
||||
{"notif1", K_notif1},
|
||||
{""},
|
||||
{"vectored", K_vectored},
|
||||
{"tri1", K_tri1},
|
||||
{""},
|
||||
{"pullup", K_pullup},
|
||||
{""},
|
||||
{"for", K_for},
|
||||
{"nmos", K_nmos},
|
||||
{"force", K_force},
|
||||
{"module", K_module},
|
||||
{"forever", K_forever},
|
||||
{""},
|
||||
{"wait", K_wait},
|
||||
{"casex", K_casex},
|
||||
{""},
|
||||
{"strong0", K_strong0},
|
||||
{"rtranif0", K_rtranif0},
|
||||
{"time", K_time},
|
||||
{""}, {""}, {""}, {""},
|
||||
{"pmos", K_pmos},
|
||||
{"weak1", K_weak1},
|
||||
{""}, {""}, {""},
|
||||
{"fork", K_fork},
|
||||
{""}, {""}, {""}, {""}, {""}, {""},
|
||||
{"highz1", K_highz1},
|
||||
{"supply0", K_supply0},
|
||||
{""}, {""}, {""},
|
||||
{"always", K_always},
|
||||
{""}, {""}, {""},
|
||||
{"rcmos", K_rcmos},
|
||||
{"medium", K_medium},
|
||||
{"tranif0", K_tranif0},
|
||||
{"defparam", K_defparam},
|
||||
{""}, {""},
|
||||
{"bufif1", K_bufif1},
|
||||
{""}, {""}, {""},
|
||||
{"pull1", K_pull1},
|
||||
{""}, {""}, {""}, {""}, {""},
|
||||
{"notif0", K_notif0},
|
||||
{""},
|
||||
{"buf", K_buf},
|
||||
{"tri0", K_tri0},
|
||||
{""}, {""},
|
||||
{"initial", K_initial},
|
||||
{""}, {""}, {""}, {""}, {""}, {""}, {""},
|
||||
{"small", K_small},
|
||||
{""}, {""}, {""}, {""}, {""},
|
||||
{"macromodule", K_macromodule},
|
||||
{""}, {""}, {""},
|
||||
{"weak0", K_weak0},
|
||||
{""}, {""}, {""},
|
||||
{"cmos", K_cmos},
|
||||
{""},
|
||||
{"if", K_if},
|
||||
{""}, {""}, {""}, {""},
|
||||
{"highz0", K_highz0},
|
||||
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
|
||||
{""}, {""}, {""}, {""}, {""},
|
||||
{"bufif0", K_bufif0},
|
||||
{""}, {""}, {""},
|
||||
{"pull0", K_pull0}
|
||||
};
|
||||
|
||||
if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
|
||||
{
|
||||
int key = keyword_hash (str, len);
|
||||
|
||||
if (key <= MAX_HASH_VALUE && key >= 0)
|
||||
{
|
||||
const char *s = wordlist[key].name;
|
||||
|
||||
if (*str == *s && !strcmp (str + 1, s + 1))
|
||||
return wordlist[key].tokenType;
|
||||
}
|
||||
}
|
||||
return IDENTIFIER;
|
||||
}
|
||||
+18
-5
@@ -1,15 +1,14 @@
|
||||
%{
|
||||
/* Command-line: gperf -o -i 1 -C -k 1-3,$ -L C -H keyword_hash -N check_identifier -tT lexor_keyword.gperf */
|
||||
|
||||
#include "config.h"
|
||||
#include "parse_misc.h"
|
||||
#include "parse.h"
|
||||
#include <string.h>
|
||||
#include "lexor_keyword.h"
|
||||
|
||||
%}
|
||||
struct Keywords {
|
||||
char *name;
|
||||
int tokenType;
|
||||
} Keywords;
|
||||
struct lexor_keyword { const char*name; int tokenType; };
|
||||
%%
|
||||
always, K_always
|
||||
and, K_and
|
||||
@@ -51,6 +50,7 @@ input, K_input
|
||||
integer, K_integer
|
||||
join, K_join
|
||||
large, K_large
|
||||
localparam, K_localparam
|
||||
macromodule, K_macromodule
|
||||
medium, K_medium
|
||||
module, K_module
|
||||
@@ -72,6 +72,8 @@ pull1, K_pull1
|
||||
pulldown, K_pulldown
|
||||
pullup, K_pullup
|
||||
rcmos, K_rcmos
|
||||
real, K_real
|
||||
realtime, K_realtime
|
||||
reg, K_reg
|
||||
release, K_release
|
||||
repeat, K_repeat
|
||||
@@ -81,6 +83,7 @@ rtran, K_rtran
|
||||
rtranif0, K_rtranif0
|
||||
rtranif1, K_rtranif1
|
||||
scalered, K_scalered
|
||||
signed, K_signed
|
||||
small, K_small
|
||||
specify, K_specify
|
||||
specparam, K_specparam
|
||||
@@ -109,4 +112,14 @@ while, K_while
|
||||
wire, K_wire
|
||||
wor, K_wor
|
||||
xnor, K_xnor
|
||||
xor, K_xor
|
||||
xor, K_xor
|
||||
%%
|
||||
|
||||
int lexor_keyword_code(const char*str, unsigned nstr)
|
||||
{
|
||||
const struct lexor_keyword*rc = check_identifier(str, nstr);
|
||||
if (rc == 0)
|
||||
return IDENTIFIER;
|
||||
else
|
||||
return rc->tokenType;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
#ifndef __lexor_keyword_H
|
||||
#define __lexor_keyword_H
|
||||
/*
|
||||
* Copyright (c) 2000 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
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: lexor_keyword.h,v 1.1 2000/03/12 17:09:41 steve Exp $"
|
||||
#endif
|
||||
|
||||
extern int lexor_keyword_code (const char*str, unsigned len);
|
||||
|
||||
/*
|
||||
* $Log: lexor_keyword.h,v $
|
||||
* Revision 1.1 2000/03/12 17:09:41 steve
|
||||
* Support localparam.
|
||||
*
|
||||
*/
|
||||
#endif
|
||||
+178
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
* Copyright (c) 2000 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
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: link_const.cc,v 1.11 2001/08/25 23:50:03 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# include "netlist.h"
|
||||
# include "netmisc.h"
|
||||
|
||||
/*
|
||||
* Scan the link for drivers. If there are only constant drivers, then
|
||||
* the nexus has a known constant value. If there is a supply net,
|
||||
* then the nexus again has a known constant value.
|
||||
*/
|
||||
bool link_drivers_constant(const Link&lnk)
|
||||
{
|
||||
const Nexus*nex = lnk.nexus();
|
||||
bool flag = true;
|
||||
|
||||
for (const Link*cur = nex->first_nlink()
|
||||
; cur ; cur = cur->next_nlink()) {
|
||||
const NetNet*sig;
|
||||
|
||||
if (cur == &lnk)
|
||||
continue;
|
||||
if (cur->get_dir() == Link::INPUT)
|
||||
continue;
|
||||
|
||||
/* If this is an input or inout port of a root module,
|
||||
then the is probably not a constant value. I
|
||||
certainly don't know what the value is, anyhow. This
|
||||
can happen in cases like this:
|
||||
|
||||
module main(sig);
|
||||
input sig;
|
||||
endmodule
|
||||
|
||||
If main is a root module (it has no parent) then sig
|
||||
is not constant because it connects to an unspecified
|
||||
outside world. */
|
||||
|
||||
if (sig = dynamic_cast<const NetNet*>(cur->get_obj())) do {
|
||||
if (sig->port_type() == NetNet::NOT_A_PORT)
|
||||
break;
|
||||
|
||||
if (sig->port_type() == NetNet::POUTPUT)
|
||||
break;
|
||||
|
||||
if (sig->scope()->parent())
|
||||
break;
|
||||
|
||||
flag = false;
|
||||
} while(0);
|
||||
|
||||
|
||||
/* If the link is PASSIVE then it doesn't count as a
|
||||
driver if its initial value is Vz. PASSIVE nodes
|
||||
include wires and tri nets. */
|
||||
if (cur->get_dir() == Link::PASSIVE)
|
||||
continue;
|
||||
|
||||
if (! dynamic_cast<const NetConst*>(cur->get_obj()))
|
||||
flag = false;
|
||||
|
||||
/* 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()) {
|
||||
case NetNet::SUPPLY0:
|
||||
case NetNet::SUPPLY1:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return flag;
|
||||
}
|
||||
|
||||
verinum::V driven_value(const Link&lnk)
|
||||
{
|
||||
verinum::V val = lnk.get_init();
|
||||
|
||||
const Nexus*nex = lnk.nexus();
|
||||
for (const Link*cur = nex->first_nlink()
|
||||
; cur ; cur = cur->next_nlink()) {
|
||||
|
||||
const NetConst*obj;
|
||||
const NetNet*sig;
|
||||
if (obj = dynamic_cast<const NetConst*>(cur->get_obj())) {
|
||||
val = obj->value(cur->get_pin());
|
||||
|
||||
} else if (sig = dynamic_cast<const NetNet*>(cur->get_obj())) {
|
||||
|
||||
if (sig->type() == NetNet::SUPPLY0)
|
||||
return verinum::V0;
|
||||
|
||||
if (sig->type() == NetNet::SUPPLY1)
|
||||
return verinum::V1;
|
||||
}
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: link_const.cc,v $
|
||||
* Revision 1.11 2001/08/25 23:50:03 steve
|
||||
* Change the NetAssign_ class to refer to the signal
|
||||
* instead of link into the netlist. This is faster
|
||||
* and uses less space. Make the NetAssignNB carry
|
||||
* the delays instead of the NetAssign_ lval objects.
|
||||
*
|
||||
* Change the vvp code generator to support multiple
|
||||
* l-values, i.e. concatenations of part selects.
|
||||
*
|
||||
* Revision 1.10 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.9 2001/07/07 03:01:37 steve
|
||||
* Detect and make available to t-dll the right shift.
|
||||
*
|
||||
* Revision 1.8 2001/02/16 03:27:07 steve
|
||||
* links to root inputs are not constant.
|
||||
*
|
||||
* Revision 1.7 2000/11/20 01:41:12 steve
|
||||
* Whoops, return the calculated constant value rom driven_value.
|
||||
*
|
||||
* Revision 1.6 2000/11/20 00:58:40 steve
|
||||
* Add support for supply nets (PR#17)
|
||||
*
|
||||
* Revision 1.5 2000/07/14 06:12:57 steve
|
||||
* Move inital value handling from NetNet to Nexus
|
||||
* objects. This allows better propogation of inital
|
||||
* values.
|
||||
*
|
||||
* Clean up constant propagation a bit to account
|
||||
* for regs that are not really values.
|
||||
*
|
||||
* Revision 1.4 2000/06/25 19:59:42 steve
|
||||
* Redesign Links to include the Nexus class that
|
||||
* carries properties of the connected set of links.
|
||||
*
|
||||
* Revision 1.3 2000/05/14 17:55:04 steve
|
||||
* Support initialization of FF Q value.
|
||||
*
|
||||
* Revision 1.2 2000/05/07 04:37:56 steve
|
||||
* Carry strength values from Verilog source to the
|
||||
* pform and netlist for gates.
|
||||
*
|
||||
* Change vvm constants to use the driver_t to drive
|
||||
* a constant value. This works better if there are
|
||||
* multiple drivers on a signal.
|
||||
*
|
||||
* Revision 1.1 2000/04/20 00:28:03 steve
|
||||
* Catch some simple identity compareoptimizations.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
const char COPYRIGHT[] =
|
||||
"Copyright (c) 1998-1999 Stephen Williams ([email protected])";
|
||||
"Copyright (c) 1998-2000 Stephen Williams ([email protected])";
|
||||
|
||||
/*
|
||||
* This source code is free software; you can redistribute it
|
||||
@@ -18,10 +18,12 @@ const char COPYRIGHT[] =
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: main.cc,v 1.26 1999/11/29 17:02:21 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: main.cc,v 1.47 2001/07/30 02:44:05 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
const char NOTICE[] =
|
||||
" This program is free software; you can redistribute it and/or modify\n"
|
||||
" it under the terms of the GNU General Public License as published by\n"
|
||||
@@ -44,12 +46,29 @@ const char NOTICE[] =
|
||||
# include <queue>
|
||||
# include <map>
|
||||
# include <unistd.h>
|
||||
# include <stdlib.h>
|
||||
#if defined(HAVE_TIMES)
|
||||
# include <sys/times.h>
|
||||
#endif
|
||||
#if defined(HAVE_GETOPT_H)
|
||||
# include <getopt.h>
|
||||
#endif
|
||||
# include "pform.h"
|
||||
# include "netlist.h"
|
||||
# include "target.h"
|
||||
# include "compiler.h"
|
||||
|
||||
#if defined(__MINGW32__) && !defined(HAVE_GETOPT_H)
|
||||
extern "C" int getopt(int argc, char*argv[], const char*fmt);
|
||||
extern "C" int optind;
|
||||
extern "C" const char*optarg;
|
||||
#endif
|
||||
|
||||
#if defined(__CYGWIN32__) && !defined(HAVE_GETOPT_H)
|
||||
extern "C" int getopt(int argc, char*argv[], const char*fmt);
|
||||
extern "C" int optind;
|
||||
extern "C" const char*optarg;
|
||||
#endif
|
||||
|
||||
const char VERSION[] = "$Name: $ $State: Exp $";
|
||||
|
||||
@@ -58,6 +77,12 @@ string start_module = "";
|
||||
|
||||
map<string,string> flags;
|
||||
|
||||
/*
|
||||
* These are the warning enable flags.
|
||||
*/
|
||||
bool warn_implicit = false;
|
||||
|
||||
|
||||
static void parm_to_flagmap(const string&flag)
|
||||
{
|
||||
string key, value;
|
||||
@@ -80,13 +105,10 @@ extern Design* elaborate(const map<string,Module*>&modules,
|
||||
const string&root);
|
||||
|
||||
extern void cprop(Design*des);
|
||||
extern void propinit(Design*des);
|
||||
extern void sigfold(Design*des);
|
||||
extern void synth(Design*des);
|
||||
extern void nobufz(Design*des);
|
||||
extern void syn_rules(Design*des);
|
||||
extern void nodangle(Design*des);
|
||||
extern void xnfio(Design*des);
|
||||
extern void xnfsyn(Design*des);
|
||||
|
||||
typedef void (*net_func)(Design*);
|
||||
static struct net_func_map {
|
||||
@@ -94,13 +116,10 @@ static struct net_func_map {
|
||||
void (*func)(Design*);
|
||||
} func_table[] = {
|
||||
{ "cprop", &cprop },
|
||||
{ "nobufz", &nobufz },
|
||||
{ "nodangle",&nodangle },
|
||||
{ "propinit",&propinit },
|
||||
{ "sigfold", &sigfold },
|
||||
{ "synth", &synth },
|
||||
{ "syn-rules", &syn_rules },
|
||||
{ "xnfio", &xnfio },
|
||||
{ "xnfsyn", &xnfsyn },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
@@ -113,18 +132,58 @@ net_func name_to_net_func(const string&name)
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *net_func_to_name(const net_func func)
|
||||
{
|
||||
for (unsigned idx = 0 ; func_table[idx].name ; idx += 1)
|
||||
if (func == func_table[idx].func)
|
||||
return func_table[idx].name;
|
||||
|
||||
return "This cannot happen";
|
||||
}
|
||||
|
||||
#if defined(HAVE_TIMES)
|
||||
static double cycles_diff(struct tms *a, struct tms *b)
|
||||
{
|
||||
clock_t aa = a->tms_utime
|
||||
+ a->tms_stime
|
||||
+ a->tms_cutime
|
||||
+ a->tms_cstime;
|
||||
|
||||
clock_t bb = b->tms_utime
|
||||
+ b->tms_stime
|
||||
+ b->tms_cutime
|
||||
+ b->tms_cstime;
|
||||
|
||||
return (aa-bb)/(double)sysconf(_SC_CLK_TCK);
|
||||
}
|
||||
#else // ! defined(HAVE_TIMES)
|
||||
// Provide dummies
|
||||
struct tms { int x; };
|
||||
inline static void times(struct tms *) { }
|
||||
inline static double cycles_diff(struct tms *a, struct tms *b) { return 0; }
|
||||
#endif // ! defined(HAVE_TIMES)
|
||||
|
||||
int main(int argc, char*argv[])
|
||||
{
|
||||
bool help_flag = false;
|
||||
bool verbose_flag = false;
|
||||
bool times_flag = false;
|
||||
|
||||
const char* net_path = 0;
|
||||
const char* out_path = 0;
|
||||
const char* pf_path = 0;
|
||||
const char* warn_en = "";
|
||||
int opt;
|
||||
unsigned flag_errors = 0;
|
||||
queue<net_func> net_func_queue;
|
||||
|
||||
while ((opt = getopt(argc, argv, "F:f:hN:o:P:s:t:v")) != EOF) switch (opt) {
|
||||
struct tms cycles[5];
|
||||
|
||||
flags["VPI_MODULE_LIST"] = "system";
|
||||
flags["-o"] = "a.out";
|
||||
min_typ_max_flag = TYP;
|
||||
min_typ_max_warn = 10;
|
||||
|
||||
while ((opt = getopt(argc, argv, "F:f:hm:N:o:P:p:s:T:t:VvW:")) != EOF) switch (opt) {
|
||||
case 'F': {
|
||||
net_func tmp = name_to_net_func(optarg);
|
||||
if (tmp == 0) {
|
||||
@@ -142,26 +201,57 @@ int main(int argc, char*argv[])
|
||||
case 'h':
|
||||
help_flag = true;
|
||||
break;
|
||||
case 'm':
|
||||
flags["VPI_MODULE_LIST"] = flags["VPI_MODULE_LIST"]+","+optarg;
|
||||
break;
|
||||
case 'N':
|
||||
net_path = optarg;
|
||||
break;
|
||||
case 'o':
|
||||
out_path = optarg;
|
||||
flags["-o"] = optarg;
|
||||
break;
|
||||
case 'P':
|
||||
pf_path = optarg;
|
||||
break;
|
||||
case 'p':
|
||||
parm_to_flagmap(optarg);
|
||||
break;
|
||||
case 's':
|
||||
start_module = optarg;
|
||||
break;
|
||||
case 'T':
|
||||
if (strcmp(optarg,"min") == 0) {
|
||||
min_typ_max_flag = MIN;
|
||||
min_typ_max_warn = 0;
|
||||
} else if (strcmp(optarg,"typ") == 0) {
|
||||
min_typ_max_flag = TYP;
|
||||
min_typ_max_warn = 0;
|
||||
} else if (strcmp(optarg,"max") == 0) {
|
||||
min_typ_max_flag = MAX;
|
||||
min_typ_max_warn = 0;
|
||||
} else {
|
||||
cerr << "Invalid argument (" << optarg << ") to -T flag."
|
||||
<< endl;
|
||||
flag_errors += 1;
|
||||
}
|
||||
break;
|
||||
case 't':
|
||||
target = optarg;
|
||||
break;
|
||||
case 'v':
|
||||
verbose_flag = true;
|
||||
# if defined(HAVE_TIMES)
|
||||
times_flag = true;
|
||||
# endif
|
||||
break;
|
||||
case 'V':
|
||||
cout << "Icarus Verilog version " << VERSION << endl;
|
||||
cout << COPYRIGHT << endl;
|
||||
cout << endl << NOTICE << endl;
|
||||
return 0;
|
||||
case 'W':
|
||||
warn_en = optarg;
|
||||
break;
|
||||
default:
|
||||
flag_errors += 1;
|
||||
break;
|
||||
@@ -171,12 +261,33 @@ int main(int argc, char*argv[])
|
||||
return flag_errors;
|
||||
|
||||
if (help_flag) {
|
||||
cout << "Icarus Verilog version " << VERSION << endl <<
|
||||
"usage: ivl <options> <file>\n"
|
||||
"options:\n"
|
||||
"\t-F <name> Apply netlist function <name>.\n"
|
||||
"\t-h Print usage information, and exit.\n"
|
||||
"\t-m <module> Load vpi module <module>.\n"
|
||||
"\t-N <file> Dump the elaborated netlist to <file>.\n"
|
||||
"\t-o <file> Write output to <file>.\n"
|
||||
"\t-P <file> Write the parsed input to <file>.\n"
|
||||
"\t-p <assign> Set a parameter value.\n"
|
||||
"\t-s <module> Select the top-level module.\n"
|
||||
"\t-T [min|typ|max] Select timing corner.\n"
|
||||
"\t-t <name> Select target <name>.\n"
|
||||
"\t-v Print progress indications"
|
||||
#if defined(HAVE_TIMES)
|
||||
" and execution times"
|
||||
#endif
|
||||
".\n"
|
||||
"\t-V Print version and copyright information, and exit.\n"
|
||||
|
||||
;
|
||||
cout << "Netlist functions:" << endl;
|
||||
for (unsigned idx = 0 ; func_table[idx].name ; idx += 1)
|
||||
cout << " " << func_table[idx].name << endl;
|
||||
cout << "\t-F " << func_table[idx].name << endl;
|
||||
cout << "Target types:" << endl;
|
||||
for (unsigned idx = 0 ; target_table[idx] ; idx += 1)
|
||||
cout << " " << target_table[idx]->name << endl;
|
||||
cout << "\t-t " << target_table[idx]->name << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -185,6 +296,21 @@ int main(int argc, char*argv[])
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Scan the warnings enable string for warning flags. */
|
||||
for (const char*cp = warn_en ; *cp ; cp += 1) switch (*cp) {
|
||||
case 'i':
|
||||
warn_implicit = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (verbose_flag) {
|
||||
if (times_flag)
|
||||
times(cycles+0);
|
||||
cout << "PARSING INPUT ..." << endl;
|
||||
}
|
||||
|
||||
/* Parse the input. Make the pform. */
|
||||
map<string,Module*> modules;
|
||||
map<string,PUdp*> primitives;
|
||||
@@ -210,6 +336,11 @@ int main(int argc, char*argv[])
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/* If the user did not give a specific module to start with,
|
||||
then look for the single module that has no ports. If there
|
||||
are multiple modules with no ports, then give up. */
|
||||
|
||||
if (start_module == "") {
|
||||
for (map<string,Module*>::iterator mod = modules.begin()
|
||||
; mod != modules.end()
|
||||
@@ -226,29 +357,65 @@ int main(int argc, char*argv[])
|
||||
}
|
||||
}
|
||||
|
||||
/* Select a root module, and elaborate the design. */
|
||||
/* If the previous attempt to find a start module failed, but
|
||||
there is only one module, then just let the user get away
|
||||
with it. */
|
||||
|
||||
if ((start_module == "") && (modules.size() == 1)) {
|
||||
map<string,Module*>::iterator mod = modules.begin();
|
||||
Module*cur = (*mod).second;
|
||||
start_module = cur->get_name();
|
||||
}
|
||||
|
||||
/* If there is *still* no guess for the root module, then give
|
||||
up completely, and complain. */
|
||||
|
||||
if (start_module == "") {
|
||||
cerr << "No top level modules, and no -s option." << endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
if (verbose_flag) {
|
||||
if (times_flag) {
|
||||
times(cycles+1);
|
||||
cerr<<" ... done, "
|
||||
<<cycles_diff(cycles+1, cycles+0)<<" seconds."<<endl;
|
||||
}
|
||||
cout << "ELABORATING DESIGN -s "<<start_module<<" ..." << endl;
|
||||
}
|
||||
|
||||
/* On with the process of elaborating the module. */
|
||||
Design*des = elaborate(modules, primitives, start_module);
|
||||
if (des == 0) {
|
||||
cerr << "Unable to elaborate module " << start_module <<
|
||||
"." << endl;
|
||||
cerr << start_module << ": error: "
|
||||
<< "Unable to elaborate module." << endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (des->errors) {
|
||||
cerr << des->errors << " error(s) elaborating design." << endl;
|
||||
cerr << start_module << ": error: " << des->errors
|
||||
<< " elaborating module." << endl;
|
||||
return des->errors;
|
||||
}
|
||||
|
||||
des->set_flags(flags);
|
||||
|
||||
|
||||
if (verbose_flag) {
|
||||
if (times_flag) {
|
||||
times(cycles+2);
|
||||
cerr<<" ... done, "
|
||||
<<cycles_diff(cycles+2, cycles+1)<<" seconds."<<endl;
|
||||
}
|
||||
cout << "RUNNING FUNCTORS ..." << endl;
|
||||
}
|
||||
|
||||
while (!net_func_queue.empty()) {
|
||||
net_func func = net_func_queue.front();
|
||||
net_func_queue.pop();
|
||||
if (verbose_flag)
|
||||
cerr<<" -F "<<net_func_to_name(func)<<endl;
|
||||
func(des);
|
||||
}
|
||||
|
||||
@@ -258,106 +425,93 @@ int main(int argc, char*argv[])
|
||||
}
|
||||
|
||||
|
||||
bool emit_rc;
|
||||
if (out_path) {
|
||||
ofstream out;
|
||||
out.open(out_path);
|
||||
if (! out.is_open()) {
|
||||
cerr << "Unable to open " << out_path << " for writing."
|
||||
<< endl;
|
||||
return 1;
|
||||
if (verbose_flag) {
|
||||
if (times_flag) {
|
||||
times(cycles+3);
|
||||
cerr<<" ... done, "
|
||||
<<cycles_diff(cycles+3, cycles+2)<<" seconds."<<endl;
|
||||
}
|
||||
|
||||
emit_rc = emit(out, des, target);
|
||||
|
||||
} else {
|
||||
emit_rc = emit(cout, des, target);
|
||||
cout << "CODE GENERATION -t "<<target<<" ..." << endl;
|
||||
}
|
||||
|
||||
bool emit_rc = emit(des, target);
|
||||
if (!emit_rc) {
|
||||
cerr << "internal error: Code generation had errors." << endl;
|
||||
cerr << "error: Code generation had errors." << endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (verbose_flag) {
|
||||
if (times_flag) {
|
||||
times(cycles+4);
|
||||
cerr<<" ... done, "
|
||||
<<cycles_diff(cycles+4, cycles+3)<<" seconds."<<endl;
|
||||
} else
|
||||
cout << "DONE." << endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: main.cc,v $
|
||||
* Revision 1.26 1999/11/29 17:02:21 steve
|
||||
* include getopt if present.
|
||||
* Revision 1.47 2001/07/30 02:44:05 steve
|
||||
* Cleanup defines and types for mingw compile.
|
||||
*
|
||||
* Revision 1.25 1999/11/18 03:52:19 steve
|
||||
* Turn NetTmp objects into normal local NetNet objects,
|
||||
* and add the nodangle functor to clean up the local
|
||||
* symbols generated by elaboration and other steps.
|
||||
* Revision 1.46 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.24 1999/11/01 02:07:40 steve
|
||||
* Add the synth functor to do generic synthesis
|
||||
* and add the LPM_FF device to handle rows of
|
||||
* flip-flops.
|
||||
* Revision 1.45 2001/07/16 18:14:56 steve
|
||||
* Reshuffle -v and -V flags of ivl. (Stephan Boettcher)
|
||||
*
|
||||
* Revision 1.23 1999/09/22 16:57:23 steve
|
||||
* Catch parallel blocks in vvm emit.
|
||||
* Revision 1.44 2001/07/03 04:09:24 steve
|
||||
* Generate verbuse status messages (Stephan Boettcher)
|
||||
*
|
||||
* Revision 1.22 1999/08/03 04:14:49 steve
|
||||
* Parse into pform arbitrarily complex module
|
||||
* port declarations.
|
||||
* Revision 1.43 2001/07/02 01:57:27 steve
|
||||
* Add the -V flag, and some verbose messages.
|
||||
*
|
||||
* Revision 1.21 1999/07/18 05:52:46 steve
|
||||
* xnfsyn generates DFF objects for XNF output, and
|
||||
* properly rewrites the Design netlist in the process.
|
||||
* Revision 1.42 2001/06/23 18:41:02 steve
|
||||
* Include stdlib.h
|
||||
*
|
||||
* Revision 1.20 1999/07/17 22:01:13 steve
|
||||
* Add the functor interface for functor transforms.
|
||||
* Revision 1.41 2001/05/20 17:35:05 steve
|
||||
* declare getopt by hand in mingw32 compile.
|
||||
*
|
||||
* Revision 1.19 1999/07/10 23:29:21 steve
|
||||
* pform even on parse errors.
|
||||
* Revision 1.40 2001/01/20 19:02:05 steve
|
||||
* Switch hte -f flag to the -p flag.
|
||||
*
|
||||
* Revision 1.18 1999/06/19 03:46:42 steve
|
||||
* Add the -v switch.
|
||||
* Revision 1.39 2000/11/22 20:48:32 steve
|
||||
* Allow sole module to be a root.
|
||||
*
|
||||
* Revision 1.17 1999/06/17 05:33:12 steve
|
||||
* Redundant declaration of pform_parse.
|
||||
* Revision 1.38 2000/09/12 01:17:40 steve
|
||||
* Version information for vlog_vpi_info.
|
||||
*
|
||||
* Revision 1.16 1999/06/15 03:44:53 steve
|
||||
* Get rid of the STL vector template.
|
||||
* Revision 1.37 2000/08/09 03:43:45 steve
|
||||
* Move all file manipulation out of target class.
|
||||
*
|
||||
* Revision 1.15 1999/05/05 03:27:15 steve
|
||||
* More intelligent selection of module to elaborate.
|
||||
* Revision 1.36 2000/07/29 17:58:21 steve
|
||||
* Introduce min:typ:max support.
|
||||
*
|
||||
* Revision 1.14 1999/04/23 04:34:32 steve
|
||||
* Make debug output file parameters.
|
||||
* Revision 1.35 2000/07/14 06:12:57 steve
|
||||
* Move inital value handling from NetNet to Nexus
|
||||
* objects. This allows better propogation of inital
|
||||
* values.
|
||||
*
|
||||
* Revision 1.13 1999/02/01 00:26:49 steve
|
||||
* Carry some line info to the netlist,
|
||||
* Dump line numbers for processes.
|
||||
* Elaborate prints errors about port vector
|
||||
* width mismatch
|
||||
* Emit better handles null statements.
|
||||
* Clean up constant propagation a bit to account
|
||||
* for regs that are not really values.
|
||||
*
|
||||
* Revision 1.12 1999/01/24 01:35:36 steve
|
||||
* Support null target for generating no output.
|
||||
* Revision 1.34 2000/05/13 20:55:47 steve
|
||||
* Use yacc based synthesizer.
|
||||
*
|
||||
* Revision 1.11 1998/12/20 02:05:41 steve
|
||||
* Function to calculate wire initial value.
|
||||
* Revision 1.33 2000/05/08 05:29:43 steve
|
||||
* no need for nobufz functor.
|
||||
*
|
||||
* Revision 1.10 1998/12/09 04:02:47 steve
|
||||
* Support the include directive.
|
||||
* Revision 1.32 2000/05/03 22:14:31 steve
|
||||
* More features of ivl available through iverilog.
|
||||
*
|
||||
* Revision 1.9 1998/12/07 04:53:17 steve
|
||||
* Generate OBUF or IBUF attributes (and the gates
|
||||
* to garry them) where a wire is a pad. This involved
|
||||
* figuring out enough of the netlist to know when such
|
||||
* was needed, and to generate new gates and signales
|
||||
* to handle what's missing.
|
||||
*
|
||||
* Revision 1.8 1998/12/02 04:37:13 steve
|
||||
* Add the nobufz function to eliminate bufz objects,
|
||||
* Object links are marked with direction,
|
||||
* constant propagation is more careful will wide links,
|
||||
* Signal folding is aware of attributes, and
|
||||
* the XNF target can dump UDP objects based on LCA
|
||||
* attributes.
|
||||
* Revision 1.31 2000/04/12 20:02:53 steve
|
||||
* Finally remove the NetNEvent and NetPEvent classes,
|
||||
* Get synthesis working with the NetEvWait class,
|
||||
* and get started supporting multiple events in a
|
||||
* wait in vvm.
|
||||
*/
|
||||
|
||||
|
||||
@@ -16,10 +16,12 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: mangle.cc,v 1.2 1999/02/15 05:52:50 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: mangle.cc,v 1.7 2001/07/25 03:10:49 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# include "target.h"
|
||||
# include <strstream>
|
||||
|
||||
@@ -32,7 +34,7 @@ string mangle(const string&str)
|
||||
string tmp = str;
|
||||
|
||||
while (tmp.length() > 0) {
|
||||
size_t pos = tmp.find_first_of(".<");
|
||||
size_t pos = tmp.find_first_of(".<\\[]/");
|
||||
if (pos > tmp.length())
|
||||
pos = tmp.length();
|
||||
|
||||
@@ -55,6 +57,48 @@ string mangle(const string&str)
|
||||
tmp = tmp.substr(1);
|
||||
res << "_";
|
||||
break;
|
||||
case '\\':
|
||||
res << "$$";
|
||||
tmp = tmp.substr(1);
|
||||
break;
|
||||
case '/':
|
||||
res << "$sl$";
|
||||
tmp = tmp.substr(1);
|
||||
break;
|
||||
case '[':
|
||||
res << "$lb$";
|
||||
tmp = tmp.substr(1);
|
||||
break;
|
||||
case ']':
|
||||
res << "$rb$";
|
||||
tmp = tmp.substr(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
res << ends;
|
||||
return res.str();
|
||||
}
|
||||
|
||||
string stresc(const string&str)
|
||||
{
|
||||
ostrstream res;
|
||||
string tmp = str;
|
||||
|
||||
while (tmp.length() > 0) {
|
||||
size_t pos = tmp.find_first_of("\\");
|
||||
if (pos > tmp.length())
|
||||
pos = tmp.length();
|
||||
|
||||
res << tmp.substr(0, pos);
|
||||
if (pos >= tmp.length())
|
||||
break;
|
||||
|
||||
tmp = tmp.substr(pos);
|
||||
switch (tmp[0]) {
|
||||
case '\\':
|
||||
res << "\\\\";
|
||||
tmp = tmp.substr(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
res << ends;
|
||||
@@ -63,6 +107,22 @@ string mangle(const string&str)
|
||||
|
||||
/*
|
||||
* $Log: mangle.cc,v $
|
||||
* Revision 1.7 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.6 2001/04/22 23:09:46 steve
|
||||
* More UDP consolidation from Stephan Boettcher.
|
||||
*
|
||||
* Revision 1.5 2000/12/11 01:06:24 steve
|
||||
* Mangle [] characters. (PR#67)
|
||||
*
|
||||
* Revision 1.4 2000/10/25 23:21:37 steve
|
||||
* mangle the backslash to a dollar.
|
||||
*
|
||||
* Revision 1.3 2000/02/23 02:56:54 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.2 1999/02/15 05:52:50 steve
|
||||
* Mangle that handles device instance numbers.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
|
||||
|
||||
MINGW PORT OF ICARUS VERILOG
|
||||
|
||||
Copyright 2001 Stephen Williams <[email protected]>
|
||||
|
||||
|
||||
Icarus Verilog source can be compiled with the mingw C/C++ compilers
|
||||
to get a Windows binary that does not require the posix compatibility
|
||||
cruft of the Cygwin.dll library. The configure scripts automatically
|
||||
detect that the compilers in use are the mingw compilers and will
|
||||
configure the Makefiles appropriately.
|
||||
|
||||
However, the mingw tools do not include all the other tools around the
|
||||
compiler, including the shell interpreter for the configure script,
|
||||
bison, flex, gperf, etc. Therefore, you still need Cygwin to compile
|
||||
Icarus Verilog, even if you don't need the Cygwin compilers.
|
||||
|
||||
* Install Cygwin
|
||||
|
||||
So, step 1 is "Download and Install Cygwin." See the web page
|
||||
http://www.cygwin.com for instructions and the files to do
|
||||
this. Cygwin *is* a kool package, and is worth having anyhow.
|
||||
|
||||
* Install mingw
|
||||
|
||||
The obvious step 2, then, is install the mingw compilers. These can be
|
||||
found as the web page <http://www.mingw.org>.
|
||||
|
||||
* Unpack Icarus Verilog source
|
||||
|
||||
Most of the remaining steps are best done in a Cygwin window. When you
|
||||
installed Cygwin, a start menu entry was created to allow you to start
|
||||
up the Cygwin window. I'll use the string "$ " to represent a command
|
||||
prompt in this window, because that is the usual bash prompt.
|
||||
|
||||
Anyhow, unpack the compressed tar file (.tar.gz) of the source with a
|
||||
command like this:
|
||||
|
||||
$ gunzip -d verilog-20010630.tar.gz | tar xvf -
|
||||
|
||||
This will create a directory "verilog-20010630" that contains all the
|
||||
source. Descend into that directory, as that is where we will work
|
||||
from now on.
|
||||
|
||||
$ cd verilog-20010630
|
||||
|
||||
* Select the mingw compilers
|
||||
|
||||
In your cygwin window, if you type "which c++" you will get the
|
||||
response path "/usr/bin/c++" which is the cygwin compiler. This is not
|
||||
the one we want to use, however. Tell the shell where the mingw
|
||||
compilers are by setting the search path like so:
|
||||
|
||||
$ PATH=/cygdrive/d/mingw/bin:$PATH
|
||||
|
||||
This assumes that you installed mingw in D:\mingw. The actual programs
|
||||
are in the bin directory under the root. After this command, check
|
||||
that you are now getting the right compilers with this "which"
|
||||
command:
|
||||
|
||||
$ which c++
|
||||
/cygdrive/d/mingw/bin/c++
|
||||
|
||||
Good!
|
||||
|
||||
|
||||
* Configure Icarus Verilog
|
||||
|
||||
Now we are all set to configure and compile Icarus Verilog. Choose a
|
||||
destination path where you will want to install the binaries. I chose
|
||||
on my system the directory "D:\iverilog". This choice is not
|
||||
permanent, so don't get too much angst over it. Just choose a name
|
||||
without white space.
|
||||
|
||||
Now, configure the source to make the makefiles and configuration
|
||||
details. Run this command:
|
||||
|
||||
$ ./configure --prefix=/cygdrive/d/iverilog
|
||||
|
||||
Substitute your chosen directory for the prefix. This will cause the
|
||||
makefiles to build and the source code to configure. The configure
|
||||
program will detect that this is a mingw environment and set things up
|
||||
to build properly.
|
||||
|
||||
|
||||
* Compile Icarus Verilog
|
||||
|
||||
This, believe it or not, should be the easy part:
|
||||
|
||||
$ make
|
||||
|
||||
It could take a while. Now is a good time to go get some coffee or
|
||||
take a tea break.
|
||||
|
||||
|
||||
* Install Icarus Verilog
|
||||
|
||||
If the compile ran OK, then next you install Icarus Verilog in the
|
||||
directory you have chosen. This is how:
|
||||
|
||||
$ make install
|
||||
|
||||
This is part of what the configure program did for you. The Makefiles
|
||||
now know to put the files under the D:\iverilog (or whatever directory
|
||||
you chose) directory, and away you go.
|
||||
|
||||
|
||||
* Running Icarus Verilog
|
||||
|
||||
Finally, put the D:\iverilog\bin directory in your Windows path, and
|
||||
you should be able to run the iverilog and vvp commands to your
|
||||
heart's content.
|
||||
|
||||
Currently, the iverilog.exe uses the path to itself to locate the
|
||||
libraries and modules associated with itself. In other words, if you
|
||||
execute the D:\iverilog\bin\iverilog.exe program, it will locate its
|
||||
subparts in the D:\iverilog directory and subdirectories below
|
||||
that. This means you can move the Icarus Verilog installation by
|
||||
simply moving the root directory and all its contents.
|
||||
@@ -0,0 +1,46 @@
|
||||
#ifndef __named_H
|
||||
#define __named_H
|
||||
/*
|
||||
* Copyright (c) 2000 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
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: named.h,v 1.2 2000/02/23 02:56:54 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <string>
|
||||
|
||||
/*
|
||||
* There are lots of places where names are attached to objects. This
|
||||
* simple template expresses the lot.
|
||||
*/
|
||||
|
||||
template <class T> struct named {
|
||||
string name;
|
||||
T parm;
|
||||
};
|
||||
|
||||
/*
|
||||
* $Log: named.h,v $
|
||||
* Revision 1.2 2000/02/23 02:56:54 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.1 2000/01/09 05:50:49 steve
|
||||
* Support named parameter override lists.
|
||||
*
|
||||
*/
|
||||
#endif
|
||||
+269
@@ -0,0 +1,269 @@
|
||||
/*
|
||||
* Copyright (c) 2000 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
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: net_assign.cc,v 1.8 2001/08/25 23:50:03 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# include "netlist.h"
|
||||
|
||||
/*
|
||||
* NetAssign
|
||||
*/
|
||||
|
||||
unsigned count_lval_width(const NetAssign_*idx)
|
||||
{
|
||||
unsigned wid = 0;
|
||||
while (idx) {
|
||||
wid += idx->lwidth();
|
||||
idx = idx->more;
|
||||
}
|
||||
return wid;
|
||||
}
|
||||
|
||||
NetAssign_::NetAssign_(NetNet*s)
|
||||
: sig_(s), bmux_(0)
|
||||
{
|
||||
loff_ = 0;
|
||||
lwid_ = sig_->pin_count();
|
||||
sig_->incr_eref();
|
||||
more = 0;
|
||||
}
|
||||
|
||||
NetAssign_::~NetAssign_()
|
||||
{
|
||||
if (sig_) sig_->decr_eref();
|
||||
assert( more == 0 );
|
||||
if (bmux_) delete bmux_;
|
||||
}
|
||||
|
||||
void NetAssign_::set_bmux(NetExpr*r)
|
||||
{
|
||||
assert(bmux_ == 0);
|
||||
bmux_ = r;
|
||||
}
|
||||
|
||||
const NetExpr* NetAssign_::bmux() const
|
||||
{
|
||||
return bmux_;
|
||||
}
|
||||
|
||||
unsigned NetAssign_::lwidth() const
|
||||
{
|
||||
if (bmux_) return 1;
|
||||
else return lwid_;
|
||||
}
|
||||
|
||||
const char*NetAssign_::name() const
|
||||
{
|
||||
if (sig_) {
|
||||
return sig_->name();
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
NetNet* NetAssign_::sig() const
|
||||
{
|
||||
assert(sig_);
|
||||
return sig_;
|
||||
}
|
||||
|
||||
void NetAssign_::set_part(unsigned lo, unsigned lw)
|
||||
{
|
||||
loff_ = lo;
|
||||
lwid_ = lw;
|
||||
assert(sig_->pin_count() >= (lo + lw));
|
||||
}
|
||||
|
||||
unsigned NetAssign_::get_loff() const
|
||||
{
|
||||
return loff_;
|
||||
}
|
||||
|
||||
NetAssignBase::NetAssignBase(NetAssign_*lv, NetExpr*rv)
|
||||
: lval_(lv), rval_(rv)
|
||||
{
|
||||
}
|
||||
|
||||
NetAssignBase::~NetAssignBase()
|
||||
{
|
||||
if (rval_) delete rval_;
|
||||
while (lval_) {
|
||||
NetAssign_*tmp = lval_;
|
||||
lval_ = tmp->more;
|
||||
tmp->more = 0;
|
||||
delete tmp;
|
||||
}
|
||||
}
|
||||
|
||||
NetExpr* NetAssignBase::rval()
|
||||
{
|
||||
return rval_;
|
||||
}
|
||||
|
||||
const NetExpr* NetAssignBase::rval() const
|
||||
{
|
||||
return rval_;
|
||||
}
|
||||
|
||||
void NetAssignBase::set_rval(NetExpr*r)
|
||||
{
|
||||
if (rval_) delete rval_;
|
||||
rval_ = r;
|
||||
}
|
||||
|
||||
NetAssign_* NetAssignBase::l_val(unsigned idx)
|
||||
{
|
||||
NetAssign_*cur = lval_;
|
||||
while (idx > 0) {
|
||||
if (cur == 0)
|
||||
return cur;
|
||||
|
||||
cur = cur->more;
|
||||
idx -= 1;
|
||||
}
|
||||
|
||||
assert(idx == 0);
|
||||
return cur;
|
||||
}
|
||||
|
||||
const NetAssign_* NetAssignBase::l_val(unsigned idx) const
|
||||
{
|
||||
const NetAssign_*cur = lval_;
|
||||
while (idx > 0) {
|
||||
if (cur == 0)
|
||||
return cur;
|
||||
|
||||
cur = cur->more;
|
||||
idx -= 1;
|
||||
}
|
||||
|
||||
assert(idx == 0);
|
||||
return cur;
|
||||
}
|
||||
|
||||
unsigned NetAssignBase::l_val_count() const
|
||||
{
|
||||
const NetAssign_*cur = lval_;
|
||||
unsigned cnt = 0;
|
||||
while (cur) {
|
||||
cnt += 1;
|
||||
cur = cur->more;
|
||||
}
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
unsigned NetAssignBase::lwidth() const
|
||||
{
|
||||
unsigned sum = 0;
|
||||
for (NetAssign_*cur = lval_ ; cur ; cur = cur->more)
|
||||
sum += cur->lwidth();
|
||||
return sum;
|
||||
}
|
||||
|
||||
|
||||
NetAssign::NetAssign(NetAssign_*lv, NetExpr*rv)
|
||||
: NetAssignBase(lv, rv)
|
||||
{
|
||||
}
|
||||
|
||||
NetAssign::~NetAssign()
|
||||
{
|
||||
}
|
||||
|
||||
NetAssignNB::NetAssignNB(NetAssign_*lv, NetExpr*rv)
|
||||
: NetAssignBase(lv, rv)
|
||||
{
|
||||
rise_time_ = 0;
|
||||
fall_time_ = 0;
|
||||
decay_time_ = 0;
|
||||
}
|
||||
|
||||
NetAssignNB::~NetAssignNB()
|
||||
{
|
||||
}
|
||||
|
||||
void NetAssignNB::rise_time(unsigned t)
|
||||
{
|
||||
rise_time_ = t;
|
||||
}
|
||||
|
||||
void NetAssignNB::fall_time(unsigned t)
|
||||
{
|
||||
fall_time_ = t;
|
||||
}
|
||||
|
||||
void NetAssignNB::decay_time(unsigned t)
|
||||
{
|
||||
decay_time_ = t;
|
||||
}
|
||||
|
||||
unsigned NetAssignNB::rise_time() const
|
||||
{
|
||||
return rise_time_;
|
||||
}
|
||||
|
||||
unsigned NetAssignNB::fall_time() const
|
||||
{
|
||||
return fall_time_;
|
||||
}
|
||||
|
||||
unsigned NetAssignNB::decay_time() const
|
||||
{
|
||||
return decay_time_;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: net_assign.cc,v $
|
||||
* Revision 1.8 2001/08/25 23:50:03 steve
|
||||
* Change the NetAssign_ class to refer to the signal
|
||||
* instead of link into the netlist. This is faster
|
||||
* and uses less space. Make the NetAssignNB carry
|
||||
* the delays instead of the NetAssign_ lval objects.
|
||||
*
|
||||
* Change the vvp code generator to support multiple
|
||||
* l-values, i.e. concatenations of part selects.
|
||||
*
|
||||
* Revision 1.7 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.6 2000/10/18 20:04:39 steve
|
||||
* Add ivl_lval_t and support for assignment l-values.
|
||||
*
|
||||
* Revision 1.5 2000/09/20 02:53:15 steve
|
||||
* Correctly measure comples l-values of assignments.
|
||||
*
|
||||
* Revision 1.4 2000/09/10 02:18:16 steve
|
||||
* elaborate complex l-values
|
||||
*
|
||||
* Revision 1.3 2000/09/07 00:06:53 steve
|
||||
* encapsulate access to the l-value expected width.
|
||||
*
|
||||
* Revision 1.2 2000/09/02 23:40:13 steve
|
||||
* Pull NetAssign_ creation out of constructors.
|
||||
*
|
||||
* Revision 1.1 2000/09/02 20:54:20 steve
|
||||
* Rearrange NetAssign to make NetAssign_ separate.
|
||||
*
|
||||
*/
|
||||
|
||||
+558
@@ -0,0 +1,558 @@
|
||||
/*
|
||||
* Copyright (c) 2000Stephen 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
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: net_design.cc,v 1.20 2001/07/25 03:10:49 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# include <iostream>
|
||||
|
||||
/*
|
||||
* This source file contains all the implementations of the Design
|
||||
* class declared in netlist.h.
|
||||
*/
|
||||
|
||||
# include "netlist.h"
|
||||
# include "util.h"
|
||||
# include <strstream>
|
||||
|
||||
Design:: Design()
|
||||
: errors(0), root_scope_(0), nodes_(0), procs_(0), lcounter_(0)
|
||||
{
|
||||
procs_idx_ = 0;
|
||||
des_precision_ = 0;
|
||||
}
|
||||
|
||||
Design::~Design()
|
||||
{
|
||||
}
|
||||
|
||||
string Design::local_symbol(const string&path)
|
||||
{
|
||||
strstream res;
|
||||
res << "_L" << (lcounter_++) << ends;
|
||||
|
||||
return path + "." + res.str();
|
||||
}
|
||||
|
||||
void Design::set_precision(int val)
|
||||
{
|
||||
if (val < des_precision_)
|
||||
des_precision_ = val;
|
||||
}
|
||||
|
||||
int Design::get_precision() const
|
||||
{
|
||||
return des_precision_;
|
||||
}
|
||||
|
||||
unsigned long Design::scale_to_precision(unsigned long val,
|
||||
const NetScope*scope) const
|
||||
{
|
||||
int units = scope->time_unit();
|
||||
assert( units >= des_precision_ );
|
||||
|
||||
while (units > des_precision_) {
|
||||
units -= 1;
|
||||
val *= 10;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
NetScope* Design::make_root_scope(const string&root)
|
||||
{
|
||||
assert(root_scope_ == 0);
|
||||
root_scope_ = new NetScope(0, root, NetScope::MODULE);
|
||||
root_scope_->set_module_name(root.c_str());
|
||||
return root_scope_;
|
||||
}
|
||||
|
||||
NetScope* Design::find_root_scope()
|
||||
{
|
||||
assert(root_scope_);
|
||||
return root_scope_;
|
||||
}
|
||||
|
||||
const NetScope* Design::find_root_scope() const
|
||||
{
|
||||
assert(root_scope_);
|
||||
return root_scope_;
|
||||
}
|
||||
|
||||
/*
|
||||
* This method locates a scope in the design, given its rooted
|
||||
* heirarchical name. Each component of the key is used to scan one
|
||||
* more step down the tree until the name runs out or the search
|
||||
* fails.
|
||||
*/
|
||||
NetScope* Design::find_scope(const string&key) const
|
||||
{
|
||||
if (key == root_scope_->name())
|
||||
return root_scope_;
|
||||
|
||||
string path = key;
|
||||
string root = parse_first_name(path);
|
||||
|
||||
NetScope*cur = root_scope_;
|
||||
if (root != cur->name())
|
||||
return 0;
|
||||
|
||||
while (cur) {
|
||||
string next = parse_first_name(path);
|
||||
cur = cur->child(next);
|
||||
if (path == "") return cur;
|
||||
}
|
||||
|
||||
return cur;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is a relative lookup of a scope by name. The starting point is
|
||||
* the scope parameter is the place within which I start looking for
|
||||
* the scope. If I do not find the scope within the passed scope,
|
||||
* start looking in parent scopes until I find it, or I run out of
|
||||
* parent scopes.
|
||||
*/
|
||||
NetScope* Design::find_scope(NetScope*scope, const string&name) const
|
||||
{
|
||||
assert(scope);
|
||||
|
||||
for ( ; scope ; scope = scope->parent()) {
|
||||
string path = name;
|
||||
string key = parse_first_name(path);
|
||||
|
||||
NetScope*cur = scope;
|
||||
do {
|
||||
cur = cur->child(key);
|
||||
if (cur == 0) break;
|
||||
key = parse_first_name(path);
|
||||
} while (key != "");
|
||||
|
||||
if (cur) return cur;
|
||||
}
|
||||
|
||||
// Last chance. Look for the name starting at the root.
|
||||
return find_scope(name);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find a parameter from within a specified context. If the name is
|
||||
* not here, keep looking up until I run out of up to look at. The
|
||||
* method works by scanning scopes, starting with the passed scope and
|
||||
* working up towards the root, looking for the named parameter. The
|
||||
* name in this case can be hierarchical, so there is an inner loop to
|
||||
* follow the scopes of the name down to to key.
|
||||
*/
|
||||
const NetExpr* Design::find_parameter(const NetScope*scope,
|
||||
const string&name) const
|
||||
{
|
||||
for ( ; scope ; scope = scope->parent()) {
|
||||
string path = name;
|
||||
string key = parse_first_name(path);
|
||||
|
||||
const NetScope*cur = scope;
|
||||
while (path != "") {
|
||||
cur = cur->child(key);
|
||||
if (cur == 0) break;
|
||||
key = parse_first_name(path);
|
||||
}
|
||||
|
||||
if (cur == 0) continue;
|
||||
|
||||
if (const NetExpr*res = cur->get_parameter(key))
|
||||
return res;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This method runs through the scope, noticing the defparam
|
||||
* statements that were collected during the elaborate_scope pass and
|
||||
* applying them to the target parameters. The implementation actually
|
||||
* works by using a specialized method from the NetScope class that
|
||||
* does all the work for me.
|
||||
*/
|
||||
void Design::run_defparams()
|
||||
{
|
||||
root_scope_->run_defparams(this);
|
||||
}
|
||||
|
||||
void NetScope::run_defparams(Design*des)
|
||||
{
|
||||
NetScope*cur = sub_;
|
||||
while (cur) {
|
||||
cur->run_defparams(des);
|
||||
cur = cur->sib_;
|
||||
}
|
||||
|
||||
map<string,NetExpr*>::const_iterator pp;
|
||||
for (pp = defparams.begin() ; pp != defparams.end() ; pp ++ ) {
|
||||
NetExpr*val = (*pp).second;
|
||||
string path = (*pp).first;
|
||||
string name = parse_last_name(path);
|
||||
|
||||
NetScope*targ_scope = des->find_scope(this, path);
|
||||
if (targ_scope == 0) {
|
||||
cerr << val->get_line() << ": warning: scope of " <<
|
||||
path << "." << name << " not found." << endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
val = targ_scope->set_parameter(name, val);
|
||||
if (val == 0) {
|
||||
cerr << val->get_line() << ": warning: parameter "
|
||||
<< name << " not found in " << targ_scope->name()
|
||||
<< "." << endl;
|
||||
} else {
|
||||
delete val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Design::evaluate_parameters()
|
||||
{
|
||||
root_scope_->evaluate_parameters(this);
|
||||
}
|
||||
|
||||
void NetScope::evaluate_parameters(Design*des)
|
||||
{
|
||||
NetScope*cur = sub_;
|
||||
while (cur) {
|
||||
cur->evaluate_parameters(des);
|
||||
cur = cur->sib_;
|
||||
}
|
||||
|
||||
|
||||
// Evaluate the parameter values. The parameter expressions
|
||||
// have already been elaborated and replaced by the scope
|
||||
// scanning code. Now the parameter expression can be fully
|
||||
// evaluated, or it cannot be evaluated at all.
|
||||
|
||||
typedef map<string,NetExpr*>::iterator mparm_it_t;
|
||||
|
||||
for (mparm_it_t cur = parameters_.begin()
|
||||
; cur != parameters_.end() ; cur ++) {
|
||||
|
||||
// Get the NetExpr for the parameter.
|
||||
NetExpr*expr = (*cur).second;
|
||||
assert(expr);
|
||||
|
||||
// If it's already a NetEConst, then this parameter is done.
|
||||
if (dynamic_cast<const NetEConst*>(expr))
|
||||
continue;
|
||||
|
||||
// Try to evaluate the expression.
|
||||
NetExpr*nexpr = expr->eval_tree();
|
||||
if (nexpr == 0) {
|
||||
cerr << (*cur).second->get_line() << ": internal error: "
|
||||
"unable to evaluate parm expression: " <<
|
||||
*expr << endl;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
// The evaluate worked, replace the old expression with
|
||||
// this constant value.
|
||||
assert(nexpr);
|
||||
delete expr;
|
||||
(*cur).second = nexpr;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
string Design::get_flag(const string&key) const
|
||||
{
|
||||
map<string,string>::const_iterator tmp = flags_.find(key);
|
||||
if (tmp == flags_.end())
|
||||
return "";
|
||||
else
|
||||
return (*tmp).second;
|
||||
}
|
||||
|
||||
/*
|
||||
* This method looks for a signal (reg, wire, whatever) starting at
|
||||
* the specified scope. If the name is hierarchical, it is split into
|
||||
* scope and name and the scope used to find the proper starting point
|
||||
* for the real search.
|
||||
*
|
||||
* It is the job of this function to properly implement Verilog scope
|
||||
* rules as signals are concerned.
|
||||
*/
|
||||
NetNet* Design::find_signal(NetScope*scope, const string&name)
|
||||
{
|
||||
assert(scope);
|
||||
|
||||
/* If the name has a path attached to it, parse it off and use
|
||||
that to locate the desired starting scope. */
|
||||
string path = name;
|
||||
string key = parse_last_name(path);
|
||||
if (path != "")
|
||||
scope = find_scope(scope, path);
|
||||
|
||||
/* Now from the starting point, scan upwards until we find the
|
||||
signal or we find a module boundary. */
|
||||
while (scope) {
|
||||
|
||||
if (NetNet*net = scope->find_signal(key))
|
||||
return net;
|
||||
|
||||
if (scope->type() == NetScope::MODULE)
|
||||
break;
|
||||
|
||||
scope = scope->parent();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetMemory* Design::find_memory(NetScope*scope, const string&name)
|
||||
{
|
||||
assert(scope);
|
||||
|
||||
/* If the name has a path attached to it, parse it off and use
|
||||
that to locate the desired scope. */
|
||||
string path = name;
|
||||
string key = parse_last_name(path);
|
||||
if (path != "")
|
||||
scope = find_scope(scope, path);
|
||||
|
||||
while (scope) {
|
||||
|
||||
if (NetMemory*mem = scope->find_memory(key))
|
||||
return mem;
|
||||
scope = scope->parent();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Design::find_symbol(NetScope*scope, const string&name,
|
||||
NetNet*&sig, NetMemory*&mem)
|
||||
{
|
||||
sig = 0;
|
||||
mem = 0;
|
||||
|
||||
|
||||
/* If the name has a path attached to it, parse it off and use
|
||||
that to locate the desired scope. Then locate the key
|
||||
within that scope. */
|
||||
string path = name;
|
||||
string key = parse_last_name(path);
|
||||
if (path != "")
|
||||
scope = find_scope(scope, path);
|
||||
|
||||
|
||||
/* If there is no path, then just search upwards for the key. */
|
||||
while (scope) {
|
||||
|
||||
if (NetNet*cur = scope->find_signal(key)) {
|
||||
sig = cur;
|
||||
return;
|
||||
}
|
||||
|
||||
if (NetMemory*cur = scope->find_memory(key)) {
|
||||
mem = cur;
|
||||
return;
|
||||
}
|
||||
|
||||
scope = scope->parent();
|
||||
}
|
||||
}
|
||||
|
||||
NetFuncDef* Design::find_function(NetScope*scope, const string&name)
|
||||
{
|
||||
assert(scope);
|
||||
NetScope*func = find_scope(scope, name);
|
||||
if (func && (func->type() == NetScope::FUNC))
|
||||
return func->func_def();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetFuncDef* Design::find_function(const string&key)
|
||||
{
|
||||
NetScope*func = find_scope(key);
|
||||
if (func && (func->type() == NetScope::FUNC))
|
||||
return func->func_def();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetScope* Design::find_task(NetScope*scope, const string&name)
|
||||
{
|
||||
NetScope*task = find_scope(scope, name);
|
||||
if (task && (task->type() == NetScope::TASK))
|
||||
return task;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetScope* Design::find_task(const string&key)
|
||||
{
|
||||
NetScope*task = find_scope(key);
|
||||
if (task && (task->type() == NetScope::TASK))
|
||||
return task;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Design::add_node(NetNode*net)
|
||||
{
|
||||
assert(net->design_ == 0);
|
||||
if (nodes_ == 0) {
|
||||
net->node_next_ = net;
|
||||
net->node_prev_ = net;
|
||||
} else {
|
||||
net->node_next_ = nodes_->node_next_;
|
||||
net->node_prev_ = nodes_;
|
||||
net->node_next_->node_prev_ = net;
|
||||
net->node_prev_->node_next_ = net;
|
||||
}
|
||||
nodes_ = net;
|
||||
net->design_ = this;
|
||||
}
|
||||
|
||||
void Design::del_node(NetNode*net)
|
||||
{
|
||||
assert(net->design_ == this);
|
||||
if (nodes_ == net)
|
||||
nodes_ = net->node_prev_;
|
||||
|
||||
if (nodes_ == net) {
|
||||
nodes_ = 0;
|
||||
} else {
|
||||
net->node_next_->node_prev_ = net->node_prev_;
|
||||
net->node_prev_->node_next_ = net->node_next_;
|
||||
}
|
||||
|
||||
net->design_ = 0;
|
||||
}
|
||||
|
||||
void Design::add_process(NetProcTop*pro)
|
||||
{
|
||||
pro->next_ = procs_;
|
||||
procs_ = pro;
|
||||
}
|
||||
|
||||
void Design::delete_process(NetProcTop*top)
|
||||
{
|
||||
assert(top);
|
||||
if (procs_ == top) {
|
||||
procs_ = top->next_;
|
||||
|
||||
} else {
|
||||
NetProcTop*cur = procs_;
|
||||
while (cur->next_ != top) {
|
||||
assert(cur->next_);
|
||||
cur = cur->next_;
|
||||
}
|
||||
|
||||
cur->next_ = top->next_;
|
||||
}
|
||||
|
||||
if (procs_idx_ == top)
|
||||
procs_idx_ = top->next_;
|
||||
|
||||
delete top;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: net_design.cc,v $
|
||||
* Revision 1.20 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.19 2001/04/02 02:28:12 steve
|
||||
* Generate code for task calls.
|
||||
*
|
||||
* Revision 1.18 2001/01/14 23:04:56 steve
|
||||
* Generalize the evaluation of floating point delays, and
|
||||
* get it working with delay assignment statements.
|
||||
*
|
||||
* Allow parameters to be referenced by hierarchical name.
|
||||
*
|
||||
* Revision 1.17 2000/12/16 01:45:48 steve
|
||||
* Detect recursive instantiations (PR#2)
|
||||
*
|
||||
* Revision 1.16 2000/09/24 17:41:13 steve
|
||||
* fix null pointer when elaborating undefined task.
|
||||
*
|
||||
* Revision 1.15 2000/08/26 00:54:03 steve
|
||||
* Get at gate information for ivl_target interface.
|
||||
*
|
||||
* Revision 1.14 2000/08/12 17:59:48 steve
|
||||
* Limit signal scope search at module boundaries.
|
||||
*
|
||||
* Revision 1.13 2000/07/30 18:25:43 steve
|
||||
* Rearrange task and function elaboration so that the
|
||||
* NetTaskDef and NetFuncDef functions are created during
|
||||
* signal enaboration, and carry these objects in the
|
||||
* NetScope class instead of the extra, useless map in
|
||||
* the Design class.
|
||||
*
|
||||
* Revision 1.12 2000/07/23 02:41:32 steve
|
||||
* Excessive assert.
|
||||
*
|
||||
* Revision 1.11 2000/07/22 22:09:03 steve
|
||||
* Parse and elaborate timescale to scopes.
|
||||
*
|
||||
* Revision 1.10 2000/07/16 04:56:08 steve
|
||||
* Handle some edge cases during node scans.
|
||||
*
|
||||
* Revision 1.9 2000/07/14 06:12:57 steve
|
||||
* Move inital value handling from NetNet to Nexus
|
||||
* objects. This allows better propogation of inital
|
||||
* values.
|
||||
*
|
||||
* Clean up constant propagation a bit to account
|
||||
* for regs that are not really values.
|
||||
*
|
||||
* Revision 1.8 2000/05/02 16:27:38 steve
|
||||
* Move signal elaboration to a seperate pass.
|
||||
*
|
||||
* Revision 1.7 2000/05/02 03:13:31 steve
|
||||
* Move memories to the NetScope object.
|
||||
*
|
||||
* Revision 1.6 2000/05/02 00:58:12 steve
|
||||
* Move signal tables to the NetScope class.
|
||||
*
|
||||
* Revision 1.5 2000/04/28 16:50:53 steve
|
||||
* Catch memory word parameters to tasks.
|
||||
*
|
||||
* Revision 1.4 2000/04/10 05:26:06 steve
|
||||
* All events now use the NetEvent class.
|
||||
*
|
||||
* Revision 1.3 2000/03/11 03:25:52 steve
|
||||
* Locate scopes in statements.
|
||||
*
|
||||
* Revision 1.2 2000/03/10 06:20:48 steve
|
||||
* Handle defparam to partial hierarchical names.
|
||||
*
|
||||
* Revision 1.1 2000/03/08 04:36:53 steve
|
||||
* Redesign the implementation of scopes and parameters.
|
||||
* I now generate the scopes and notice the parameters
|
||||
* in a separate pass over the pform. Once the scopes
|
||||
* are generated, I can process overrides and evalutate
|
||||
* paremeters before elaboration begins.
|
||||
*
|
||||
*/
|
||||
|
||||
+518
@@ -0,0 +1,518 @@
|
||||
/*
|
||||
* Copyright (c) 2000 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
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: net_event.cc,v 1.15 2001/07/25 03:10:49 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# include "netlist.h"
|
||||
|
||||
NetEvent::NetEvent(const string&n)
|
||||
: name_(0)
|
||||
{
|
||||
scope_ = 0;
|
||||
snext_ = 0;
|
||||
probes_ = 0;
|
||||
trig_ = 0;
|
||||
waitref_ = 0;
|
||||
wlist_ = 0;
|
||||
name_ = new char[n.length()+1];
|
||||
strcpy(name_, n.c_str());
|
||||
}
|
||||
|
||||
NetEvent::~NetEvent()
|
||||
{
|
||||
assert(waitref_ == 0);
|
||||
if (scope_) scope_->rem_event(this);
|
||||
while (probes_) {
|
||||
NetEvProbe*tmp = probes_->enext_;
|
||||
delete probes_;
|
||||
probes_ = tmp;
|
||||
}
|
||||
delete[]name_;
|
||||
}
|
||||
|
||||
const char* NetEvent::name() const
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
|
||||
string NetEvent::full_name() const
|
||||
{
|
||||
assert(scope_);
|
||||
return scope_->name() + "." + name_;
|
||||
}
|
||||
|
||||
const NetScope* NetEvent::scope() const
|
||||
{
|
||||
assert(scope_);
|
||||
return scope_;
|
||||
}
|
||||
|
||||
unsigned NetEvent::nprobe() const
|
||||
{
|
||||
unsigned cnt = 0;
|
||||
NetEvProbe*cur = probes_;
|
||||
while (cur) {
|
||||
cnt += 1;
|
||||
cur = cur->enext_;
|
||||
}
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
NetEvProbe* NetEvent::probe(unsigned idx)
|
||||
{
|
||||
NetEvProbe*cur = probes_;
|
||||
while (cur && idx) {
|
||||
cur = cur->enext_;
|
||||
idx -= 1;
|
||||
}
|
||||
return cur;
|
||||
}
|
||||
|
||||
const NetEvProbe* NetEvent::probe(unsigned idx) const
|
||||
{
|
||||
NetEvProbe*cur = probes_;
|
||||
while (cur && idx) {
|
||||
cur = cur->enext_;
|
||||
idx -= 1;
|
||||
}
|
||||
return cur;
|
||||
}
|
||||
|
||||
unsigned NetEvent::ntrig() const
|
||||
{
|
||||
unsigned cnt = 0;
|
||||
NetEvTrig*cur = trig_;
|
||||
while (cur) {
|
||||
cnt += 1;
|
||||
cur = cur->enext_;
|
||||
}
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
unsigned NetEvent::nwait() const
|
||||
{
|
||||
return waitref_;
|
||||
}
|
||||
|
||||
/*
|
||||
* A "similar" event is one that has an identical non-nil set of
|
||||
* probes.
|
||||
*/
|
||||
NetEvent* NetEvent::find_similar_event()
|
||||
{
|
||||
if (probes_ == 0)
|
||||
return 0;
|
||||
|
||||
struct table_s {
|
||||
NetEvent*ev;
|
||||
bool mark;
|
||||
} *table;
|
||||
|
||||
//NetEvent**cand;
|
||||
//bool*cflg;
|
||||
unsigned max_cand = 0, ncand = 0;
|
||||
|
||||
NetEvProbe*cur = probes_;
|
||||
|
||||
/* Get an estimate of the number of candidate events there
|
||||
are. To get it, count the number of probes that are
|
||||
connected to my first probe. Since there is no more then
|
||||
one NetEvent per NetEvProbe, this is the maximum number of
|
||||
similar events possible.
|
||||
|
||||
Once we get that count, allocate the arrays needed to
|
||||
account for these events. */
|
||||
|
||||
for (NetNode*idx = cur->next_node()
|
||||
; idx && (idx != cur) ; idx = idx->next_node()) {
|
||||
NetEvProbe*tmp = dynamic_cast<NetEvProbe*>(idx);
|
||||
if (tmp == 0)
|
||||
continue;
|
||||
if (tmp->edge() != cur->edge())
|
||||
continue;
|
||||
|
||||
max_cand += 1;
|
||||
}
|
||||
|
||||
table = new struct table_s[max_cand];
|
||||
|
||||
|
||||
/* First, locate all the candidate events from my first
|
||||
probe. Look for all the NetEvProbe objects connected to my
|
||||
probe (that are the same edge) and save the NetEvent that
|
||||
that probe drives. */
|
||||
|
||||
for (NetNode*idx = cur->next_node()
|
||||
; idx && (idx != cur) ; idx = idx->next_node()) {
|
||||
NetEvProbe*tmp = dynamic_cast<NetEvProbe*>(idx);
|
||||
if (tmp == 0)
|
||||
continue;
|
||||
if (tmp->edge() != cur->edge())
|
||||
continue;
|
||||
|
||||
table[ncand++].ev = tmp->event();
|
||||
assert(ncand <= max_cand);
|
||||
}
|
||||
|
||||
|
||||
/* All the events in the cand array are now known to connect
|
||||
through at least one NetEvProbe. Now go through all my
|
||||
remaining probes and check that each candidate event is
|
||||
also connected (through a NetEvProbe) to me.
|
||||
|
||||
By the time I finish this scan, only NetEvents that have
|
||||
equivilent NetEvProbes remain. These are candidates. The
|
||||
events may have *more* NetEvProbes then me, I'll catch
|
||||
those later. */
|
||||
|
||||
for (cur = cur->enext_ ; cur && ncand ; cur = cur->enext_) {
|
||||
for (unsigned idx = 0 ; idx < ncand ; idx += 1)
|
||||
table[idx].mark = false;
|
||||
|
||||
/* For this probe, look for other probes connected to it
|
||||
and find the event connected to it. Mark that event
|
||||
as connected to this probe. */
|
||||
|
||||
for (NetNode*idx = cur->next_node()
|
||||
; idx && (idx != cur) ; idx = idx->next_node()) {
|
||||
NetEvProbe*tmp = dynamic_cast<NetEvProbe*>(idx);
|
||||
if (tmp == 0)
|
||||
continue;
|
||||
if (tmp->edge() != cur->edge())
|
||||
continue;
|
||||
|
||||
for (unsigned srch = 0 ; srch < ncand ; srch += 1)
|
||||
if (table[srch].ev == tmp->event()) {
|
||||
table[srch].mark = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Look for all the candidates that did not connect to
|
||||
this probe (cflg is false) and eliminate them. */
|
||||
|
||||
for (unsigned idx = 0 ; idx < ncand ; ) {
|
||||
if (table[idx].mark) {
|
||||
idx += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
for (unsigned tmp = idx ; (tmp+1) < ncand ; tmp += 1)
|
||||
table[tmp] = table[tmp+1];
|
||||
|
||||
ncand -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Scan the remaining candidates for a similar
|
||||
NetEvent. Eliminate NetEvent objects that have more
|
||||
NetEvProbe objects then I, because those have a proper
|
||||
superset of my probes and were not eliminated by the
|
||||
previous scan.
|
||||
|
||||
As soon as we find a similar event, we're done. */
|
||||
|
||||
for (unsigned idx = 0 ; idx < ncand ; idx += 1) {
|
||||
if (table[idx].ev->nprobe() == nprobe()) {
|
||||
NetEvent*res = table[idx].ev;
|
||||
delete[]table;
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Oops, fell off the list without finding a result. return nil. */
|
||||
delete[]table;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void NetEvent::replace_event(NetEvent*that)
|
||||
{
|
||||
while (wlist_) {
|
||||
wlist_->obj->replace_event(this, that);
|
||||
}
|
||||
}
|
||||
|
||||
NetEvTrig::NetEvTrig(NetEvent*ev)
|
||||
: event_(ev)
|
||||
{
|
||||
enext_ = event_->trig_;
|
||||
event_->trig_ = this;
|
||||
}
|
||||
|
||||
NetEvTrig::~NetEvTrig()
|
||||
{
|
||||
if (event_->trig_ == this) {
|
||||
event_->trig_ = enext_;
|
||||
|
||||
} else {
|
||||
NetEvTrig*cur = event_->trig_;
|
||||
while (cur->enext_ != this) {
|
||||
assert(cur->enext_);
|
||||
cur = cur->enext_;
|
||||
}
|
||||
|
||||
cur->enext_ = this->enext_;
|
||||
}
|
||||
}
|
||||
|
||||
const NetEvent* NetEvTrig::event() const
|
||||
{
|
||||
return event_;
|
||||
}
|
||||
|
||||
NetEvProbe::NetEvProbe(const string&n, NetEvent*tgt,
|
||||
edge_t t, unsigned p)
|
||||
: NetNode(n, p), event_(tgt), edge_(t)
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < p ; idx += 1) {
|
||||
pin(idx).set_dir(Link::INPUT);
|
||||
pin(idx).set_name("P", idx);
|
||||
}
|
||||
|
||||
enext_ = event_->probes_;
|
||||
event_->probes_ = this;
|
||||
}
|
||||
|
||||
NetEvProbe::~NetEvProbe()
|
||||
{
|
||||
if (event_->probes_ == this) {
|
||||
event_->probes_ = enext_;
|
||||
|
||||
} else {
|
||||
NetEvProbe*cur = event_->probes_;
|
||||
while (cur->enext_ != this) {
|
||||
assert(cur->enext_);
|
||||
cur = cur->enext_;
|
||||
}
|
||||
|
||||
cur->enext_ = this->enext_;
|
||||
}
|
||||
}
|
||||
|
||||
NetEvProbe::edge_t NetEvProbe::edge() const
|
||||
{
|
||||
return edge_;
|
||||
}
|
||||
|
||||
NetEvent* NetEvProbe::event()
|
||||
{
|
||||
return event_;
|
||||
}
|
||||
|
||||
const NetEvent* NetEvProbe::event() const
|
||||
{
|
||||
return event_;
|
||||
}
|
||||
|
||||
NetEvWait::NetEvWait(NetProc*pr)
|
||||
: statement_(pr), nevents_(0), events_(0)
|
||||
{
|
||||
}
|
||||
|
||||
NetEvWait::~NetEvWait()
|
||||
{
|
||||
if (events_) {
|
||||
for (unsigned idx = 0 ; idx < nevents_ ; idx += 1) {
|
||||
NetEvent*tgt = events_[idx];
|
||||
tgt->waitref_ -= 1;
|
||||
|
||||
struct NetEvent::wcell_*tmp = tgt->wlist_;
|
||||
if (tmp->obj == this) {
|
||||
tgt->wlist_ = tmp->next;
|
||||
delete tmp;
|
||||
} else {
|
||||
assert(tmp->next);
|
||||
while (tmp->next->obj != this) {
|
||||
tmp = tmp->next;
|
||||
assert(tmp->next);
|
||||
}
|
||||
tmp->next = tmp->next->next;
|
||||
delete tmp;
|
||||
}
|
||||
}
|
||||
delete[]events_;
|
||||
}
|
||||
delete statement_;
|
||||
}
|
||||
|
||||
void NetEvWait::add_event(NetEvent*tgt)
|
||||
{
|
||||
assert(tgt);
|
||||
if (nevents_ == 0) {
|
||||
events_ = new NetEvent*[1];
|
||||
|
||||
} else {
|
||||
NetEvent**tmp = new NetEvent*[nevents_+1];
|
||||
for (unsigned idx = 0 ; idx < nevents_ ; idx += 1) {
|
||||
tmp[idx] = events_[idx];
|
||||
assert(tmp[idx] != tgt);
|
||||
}
|
||||
delete[]events_;
|
||||
events_ = tmp;
|
||||
}
|
||||
|
||||
events_[nevents_] = tgt;
|
||||
nevents_ += 1;
|
||||
|
||||
// Remember to tell the NetEvent that there is someone
|
||||
// pointing to it.
|
||||
tgt->waitref_ += 1;
|
||||
|
||||
struct NetEvent::wcell_*tmp = new NetEvent::wcell_;
|
||||
tmp->obj = this;
|
||||
tmp->next = tgt->wlist_;
|
||||
tgt->wlist_ = tmp;
|
||||
}
|
||||
|
||||
void NetEvWait::replace_event(NetEvent*src, NetEvent*repl)
|
||||
{
|
||||
unsigned idx;
|
||||
for (idx = 0 ; idx < nevents_ ; idx += 1) {
|
||||
if (events_[idx] == src)
|
||||
break;
|
||||
}
|
||||
|
||||
assert(idx < nevents_);
|
||||
|
||||
/* First, remove me from the list held by the src NetEvent. */
|
||||
assert(src->waitref_ > 0);
|
||||
src->waitref_ -= 1;
|
||||
struct NetEvent::wcell_*tmp = src->wlist_;
|
||||
if (tmp->obj == this) {
|
||||
src->wlist_ = tmp->next;
|
||||
delete tmp;
|
||||
} else {
|
||||
assert(tmp->next);
|
||||
while (tmp->next->obj != this) {
|
||||
tmp = tmp->next;
|
||||
assert(tmp->next);
|
||||
}
|
||||
tmp->next = tmp->next->next;
|
||||
delete tmp;
|
||||
}
|
||||
|
||||
events_[idx] = repl;
|
||||
|
||||
// Remember to tell the replacement NetEvent that there is
|
||||
// someone pointing to it.
|
||||
repl->waitref_ += 1;
|
||||
|
||||
tmp = new NetEvent::wcell_;
|
||||
tmp->obj = this;
|
||||
tmp->next = repl->wlist_;
|
||||
repl->wlist_ = tmp;
|
||||
|
||||
}
|
||||
|
||||
unsigned NetEvWait::nevents() const
|
||||
{
|
||||
return nevents_;
|
||||
}
|
||||
|
||||
const NetEvent* NetEvWait::event(unsigned idx) const
|
||||
{
|
||||
assert(idx < nevents_);
|
||||
return events_[idx];
|
||||
}
|
||||
|
||||
NetEvent* NetEvWait::event(unsigned idx)
|
||||
{
|
||||
assert(idx < nevents_);
|
||||
return events_[idx];
|
||||
}
|
||||
|
||||
NetProc* NetEvWait::statement()
|
||||
{
|
||||
return statement_;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: net_event.cc,v $
|
||||
* Revision 1.15 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.14 2001/03/29 02:52:19 steve
|
||||
* Add const probe method to NetEvent.
|
||||
*
|
||||
* Revision 1.13 2001/03/28 06:07:39 steve
|
||||
* Add the ivl_event_t to ivl_target, and use that to generate
|
||||
* .event statements in vvp way ahead of the thread that uses it.
|
||||
*
|
||||
* Revision 1.12 2000/12/15 17:45:07 steve
|
||||
* Remove limits from the similar events search.
|
||||
*
|
||||
* Revision 1.11 2000/10/04 16:30:39 steve
|
||||
* Use char8 instead of string to store name.
|
||||
*
|
||||
* Revision 1.10 2000/09/19 03:00:36 steve
|
||||
* Typo stepping ot next probe in delete.
|
||||
*
|
||||
* Revision 1.9 2000/07/29 03:55:38 steve
|
||||
* fix problem coalescing events w/ probes.
|
||||
*
|
||||
* Revision 1.8 2000/05/31 02:26:49 steve
|
||||
* Globally merge redundant event objects.
|
||||
*
|
||||
* Revision 1.7 2000/05/27 19:33:23 steve
|
||||
* Merge similar probes within a module.
|
||||
*
|
||||
* Revision 1.6 2000/04/18 04:50:20 steve
|
||||
* Clean up unneeded NetEvent objects.
|
||||
*
|
||||
* Revision 1.5 2000/04/16 23:32:18 steve
|
||||
* Synthesis of comparator in expressions.
|
||||
*
|
||||
* Connect the NetEvent and related classes
|
||||
* together better.
|
||||
*
|
||||
* Revision 1.4 2000/04/12 20:02:53 steve
|
||||
* Finally remove the NetNEvent and NetPEvent classes,
|
||||
* Get synthesis working with the NetEvWait class,
|
||||
* and get started supporting multiple events in a
|
||||
* wait in vvm.
|
||||
*
|
||||
* Revision 1.3 2000/04/12 04:23:58 steve
|
||||
* Named events really should be expressed with PEIdent
|
||||
* objects in the pform,
|
||||
*
|
||||
* Handle named events within the mix of net events
|
||||
* and edges. As a unified lot they get caught together.
|
||||
* wait statements are broken into more complex statements
|
||||
* that include a conditional.
|
||||
*
|
||||
* Do not generate NetPEvent or NetNEvent objects in
|
||||
* elaboration. NetEvent, NetEvWait and NetEvProbe
|
||||
* take over those functions in the netlist.
|
||||
*
|
||||
* Revision 1.2 2000/04/10 05:26:06 steve
|
||||
* All events now use the NetEvent class.
|
||||
*
|
||||
* Revision 1.1 2000/04/04 03:20:15 steve
|
||||
* Simulate named event trigger and waits.
|
||||
*
|
||||
*/
|
||||
|
||||
+131
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright (c) 2000 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
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: net_force.cc,v 1.3 2001/07/25 03:10:49 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
/*
|
||||
* This file contains implementatsion 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>
|
||||
|
||||
/*
|
||||
* Construct the procedural continuous assignment statement. This is a
|
||||
* bit different from a normal assignment because the the lval is only
|
||||
* intermittantly connected. The deassign in particular disconnects
|
||||
* the signals when they are not being assigned anymore. Because of
|
||||
* this, there is no other reference to the lval to make it stay put
|
||||
* so we increment the eref.
|
||||
*
|
||||
* XXXX I'm not sure this is the right way. Perhaps I should create
|
||||
* output pins to connect to the netlist? But that would cause the
|
||||
* link ring to grow, and that is not quite correct either. Hmm...
|
||||
*/
|
||||
NetCAssign::NetCAssign(const string&n, NetNet*l)
|
||||
: NetNode(n, l->pin_count()), lval_(l)
|
||||
{
|
||||
lval_->incr_eref();
|
||||
for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) {
|
||||
pin(idx).set_dir(Link::INPUT);
|
||||
pin(idx).set_name("I", idx);
|
||||
}
|
||||
}
|
||||
|
||||
NetCAssign::~NetCAssign()
|
||||
{
|
||||
lval_->decr_eref();
|
||||
}
|
||||
|
||||
const Link& NetCAssign::lval_pin(unsigned idx) const
|
||||
{
|
||||
assert(idx < lval_->pin_count());
|
||||
return lval_->pin(idx);
|
||||
}
|
||||
|
||||
NetDeassign::NetDeassign(NetNet*l)
|
||||
: lval_(l)
|
||||
{
|
||||
lval_->incr_eref();
|
||||
}
|
||||
|
||||
NetDeassign::~NetDeassign()
|
||||
{
|
||||
lval_->decr_eref();
|
||||
}
|
||||
|
||||
const NetNet*NetDeassign::lval() const
|
||||
{
|
||||
return lval_;
|
||||
}
|
||||
|
||||
NetForce::NetForce(const string&n, NetNet*l)
|
||||
: NetNode(n, l->pin_count()), lval_(l)
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) {
|
||||
pin(idx).set_dir(Link::INPUT);
|
||||
pin(idx).set_name("I", idx);
|
||||
}
|
||||
}
|
||||
|
||||
NetForce::~NetForce()
|
||||
{
|
||||
}
|
||||
|
||||
const Link& NetForce::lval_pin(unsigned idx) const
|
||||
{
|
||||
assert(idx < lval_->pin_count());
|
||||
return lval_->pin(idx);
|
||||
}
|
||||
|
||||
NetRelease::NetRelease(NetNet*l)
|
||||
: lval_(l)
|
||||
{
|
||||
}
|
||||
|
||||
NetRelease::~NetRelease()
|
||||
{
|
||||
}
|
||||
|
||||
const NetNet*NetRelease::lval() const
|
||||
{
|
||||
return lval_;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* $Log: net_force.cc,v $
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
+382
@@ -0,0 +1,382 @@
|
||||
/*
|
||||
* Copyright (c) 2000 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
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: net_link.cc,v 1.5 2001/07/25 03:10:49 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# include <iostream>
|
||||
|
||||
# include "netlist.h"
|
||||
# include <strstream>
|
||||
# include <string>
|
||||
# include <typeinfo>
|
||||
|
||||
void connect(Link&l, Link&r)
|
||||
{
|
||||
assert(&l != &r);
|
||||
assert(l.nexus_);
|
||||
assert(r.nexus_);
|
||||
|
||||
/* If the links are already connected, then we're done. */
|
||||
if (l.nexus_ == r.nexus_)
|
||||
return;
|
||||
|
||||
Nexus*tmp = r.nexus_;
|
||||
while (Link*cur = tmp->first_nlink()) {
|
||||
tmp->unlink(cur);
|
||||
l.nexus_->relink(cur);
|
||||
}
|
||||
|
||||
assert(tmp->list_ == 0);
|
||||
assert(l.is_linked(r));
|
||||
delete tmp;
|
||||
}
|
||||
|
||||
Link::Link()
|
||||
: dir_(PASSIVE), drive0_(STRONG), drive1_(STRONG), init_(verinum::Vx),
|
||||
inst_(0), next_(0), nexus_(0)
|
||||
{
|
||||
(new Nexus()) -> relink(this);
|
||||
}
|
||||
|
||||
Link::~Link()
|
||||
{
|
||||
assert(nexus_);
|
||||
Nexus*tmp = nexus_;
|
||||
nexus_->unlink(this);
|
||||
if (tmp->list_ == 0)
|
||||
delete tmp;
|
||||
}
|
||||
|
||||
Nexus* Link::nexus()
|
||||
{
|
||||
return nexus_;
|
||||
}
|
||||
|
||||
const Nexus* Link::nexus() const
|
||||
{
|
||||
return nexus_;
|
||||
}
|
||||
|
||||
void Link::set_dir(DIR d)
|
||||
{
|
||||
dir_ = d;
|
||||
}
|
||||
|
||||
Link::DIR Link::get_dir() const
|
||||
{
|
||||
return dir_;
|
||||
}
|
||||
|
||||
void Link::drive0(Link::strength_t str)
|
||||
{
|
||||
drive0_ = str;
|
||||
}
|
||||
|
||||
void Link::drive1(Link::strength_t str)
|
||||
{
|
||||
drive1_ = str;
|
||||
}
|
||||
|
||||
Link::strength_t Link::drive0() const
|
||||
{
|
||||
return drive0_;
|
||||
}
|
||||
|
||||
Link::strength_t Link::drive1() const
|
||||
{
|
||||
return drive1_;
|
||||
}
|
||||
|
||||
void Link::set_init(verinum::V val)
|
||||
{
|
||||
init_ = val;
|
||||
}
|
||||
|
||||
verinum::V Link::get_init() const
|
||||
{
|
||||
return init_;
|
||||
}
|
||||
|
||||
|
||||
void Link::cur_link(NetObj*&net, unsigned &pin)
|
||||
{
|
||||
net = node_;
|
||||
pin = pin_;
|
||||
}
|
||||
|
||||
void Link::cur_link(const NetObj*&net, unsigned &pin) const
|
||||
{
|
||||
net = node_;
|
||||
pin = pin_;
|
||||
}
|
||||
|
||||
void Link::unlink()
|
||||
{
|
||||
assert(nexus_);
|
||||
if (! is_linked())
|
||||
return;
|
||||
|
||||
nexus_->unlink(this);
|
||||
(new Nexus()) -> relink(this);
|
||||
}
|
||||
|
||||
bool Link::is_equal(const Link&that) const
|
||||
{
|
||||
return (node_ == that.node_) && (pin_ == that.pin_);
|
||||
}
|
||||
|
||||
bool Link::is_linked() const
|
||||
{
|
||||
if (next_)
|
||||
return true;
|
||||
if (nexus_->first_nlink() != this)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Link::is_linked(const Link&that) const
|
||||
{
|
||||
return nexus_ == that.nexus_;
|
||||
}
|
||||
|
||||
Link* Link::next_nlink()
|
||||
{
|
||||
return next_;
|
||||
}
|
||||
|
||||
const Link* Link::next_nlink() const
|
||||
{
|
||||
return next_;
|
||||
}
|
||||
|
||||
const NetObj*Link::get_obj() const
|
||||
{
|
||||
return node_;
|
||||
}
|
||||
|
||||
NetObj*Link::get_obj()
|
||||
{
|
||||
return node_;
|
||||
}
|
||||
|
||||
unsigned Link::get_pin() const
|
||||
{
|
||||
return pin_;
|
||||
}
|
||||
|
||||
void Link::set_name(const string&n, unsigned i)
|
||||
{
|
||||
name_ = n;
|
||||
inst_ = i;
|
||||
}
|
||||
|
||||
const string& Link::get_name() const
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
|
||||
unsigned Link::get_inst() const
|
||||
{
|
||||
return inst_;
|
||||
}
|
||||
|
||||
Nexus::Nexus()
|
||||
{
|
||||
name_ = 0;
|
||||
list_ = 0;
|
||||
t_cookie_ = 0;
|
||||
}
|
||||
|
||||
Nexus::~Nexus()
|
||||
{
|
||||
assert(list_ == 0);
|
||||
if (name_)
|
||||
delete[]name_;
|
||||
}
|
||||
|
||||
verinum::V Nexus::get_init() const
|
||||
{
|
||||
assert(list_);
|
||||
for (Link*cur = list_ ; cur ; cur = cur->next_) {
|
||||
if (cur->get_dir() == Link::OUTPUT)
|
||||
return verinum::Vx;
|
||||
|
||||
if ((cur->get_dir() == Link::PASSIVE)
|
||||
&& (cur->get_init() != verinum::Vz))
|
||||
return cur->get_init();
|
||||
}
|
||||
|
||||
return verinum::Vz;
|
||||
}
|
||||
|
||||
void Nexus::unlink(Link*that)
|
||||
{
|
||||
if (name_) {
|
||||
delete[] name_;
|
||||
name_ = 0;
|
||||
}
|
||||
|
||||
assert(that);
|
||||
if (list_ == that) {
|
||||
list_ = that->next_;
|
||||
that->next_ = 0;
|
||||
that->nexus_ = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
Link*cur = list_;
|
||||
while (cur->next_ != that) {
|
||||
assert(cur->next_);
|
||||
cur = cur->next_;
|
||||
}
|
||||
|
||||
cur->next_ = that->next_;
|
||||
that->nexus_ = 0;
|
||||
that->next_ = 0;
|
||||
}
|
||||
|
||||
void Nexus::relink(Link*that)
|
||||
{
|
||||
if (name_) {
|
||||
delete[] name_;
|
||||
name_ = 0;
|
||||
}
|
||||
|
||||
assert(that->nexus_ == 0);
|
||||
assert(that->next_ == 0);
|
||||
that->next_ = list_;
|
||||
that->nexus_ = this;
|
||||
list_ = that;
|
||||
}
|
||||
|
||||
Link* Nexus::first_nlink()
|
||||
{
|
||||
return list_;
|
||||
}
|
||||
|
||||
const Link* Nexus::first_nlink() const
|
||||
{
|
||||
return list_;
|
||||
}
|
||||
|
||||
void* Nexus::t_cookie() const
|
||||
{
|
||||
return t_cookie_;
|
||||
}
|
||||
|
||||
void* Nexus::t_cookie(void*val)const
|
||||
{
|
||||
void*tmp = t_cookie_;
|
||||
t_cookie_ = val;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
const char* Nexus::name() const
|
||||
{
|
||||
if (name_)
|
||||
return name_;
|
||||
|
||||
const NetNet*sig = 0;
|
||||
unsigned pin = 0;
|
||||
for (const Link*cur = first_nlink()
|
||||
; cur ; cur = cur->next_nlink()) {
|
||||
|
||||
const NetNet*cursig = dynamic_cast<const NetNet*>(cur->get_obj());
|
||||
if (cursig == 0)
|
||||
continue;
|
||||
|
||||
if (sig == 0) {
|
||||
sig = cursig;
|
||||
pin = cur->get_pin();
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((cursig->pin_count() == 1) && (sig->pin_count() > 1))
|
||||
continue;
|
||||
|
||||
if ((cursig->pin_count() > 1) && (sig->pin_count() == 1)) {
|
||||
sig = cursig;
|
||||
pin = cur->get_pin();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cursig->local_flag() && !sig->local_flag())
|
||||
continue;
|
||||
|
||||
if (cursig->name() < sig->name())
|
||||
continue;
|
||||
|
||||
sig = cursig;
|
||||
pin = cur->get_pin();
|
||||
}
|
||||
|
||||
if (sig == 0) {
|
||||
const Link*lnk = first_nlink();
|
||||
const NetObj*obj = 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;
|
||||
|
||||
}
|
||||
assert(sig);
|
||||
ostrstream tmp;
|
||||
tmp << sig->name();
|
||||
if (sig->pin_count() > 1)
|
||||
tmp << "<" << pin << ">";
|
||||
tmp << ends;
|
||||
|
||||
name_ = new char[strlen(tmp.str()) + 1];
|
||||
strcpy(name_, tmp.str());
|
||||
return name_;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: net_link.cc,v $
|
||||
* Revision 1.5 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.4 2000/10/06 23:46:50 steve
|
||||
* ivl_target updates, including more complete
|
||||
* handling of ivl_nexus_t objects. Much reduced
|
||||
* dependencies on pointers to netlist objects.
|
||||
*
|
||||
* Revision 1.3 2000/08/26 00:54:03 steve
|
||||
* Get at gate information for ivl_target interface.
|
||||
*
|
||||
* Revision 1.2 2000/07/14 06:12:57 steve
|
||||
* Move inital value handling from NetNet to Nexus
|
||||
* objects. This allows better propogation of inital
|
||||
* values.
|
||||
*
|
||||
* Clean up constant propagation a bit to account
|
||||
* for regs that are not really values.
|
||||
*
|
||||
* Revision 1.1 2000/06/25 19:59:42 steve
|
||||
* Redesign Links to include the Nexus class that
|
||||
* carries properties of the connected set of links.
|
||||
*
|
||||
*/
|
||||
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (c) 2000 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
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: net_modulo.cc,v 1.2 2001/07/25 03:10:49 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# include <typeinfo>
|
||||
# include <iostream>
|
||||
# include <iomanip>
|
||||
# include <cassert>
|
||||
|
||||
# include "netlist.h"
|
||||
|
||||
|
||||
NetModulo::NetModulo(const string&n, unsigned wr,
|
||||
unsigned wa, unsigned wb)
|
||||
: NetNode(n, wr+wa+wb), width_r_(wr), width_a_(wa), width_b_(wb)
|
||||
{
|
||||
unsigned p = 0;
|
||||
for (unsigned idx = 0 ; idx < width_r_ ; idx += 1, p += 1) {
|
||||
pin(p).set_dir(Link::OUTPUT);
|
||||
pin(p).set_name("Result", idx);
|
||||
}
|
||||
for (unsigned idx = 0 ; idx < width_a_ ; idx += 1, p += 1) {
|
||||
pin(p).set_dir(Link::INPUT);
|
||||
pin(p).set_name("DataA", idx);
|
||||
}
|
||||
for (unsigned idx = 0 ; idx < width_b_ ; idx += 1, p += 1) {
|
||||
pin(p).set_dir(Link::INPUT);
|
||||
pin(p).set_name("DataB", idx);
|
||||
}
|
||||
}
|
||||
|
||||
NetModulo::~NetModulo()
|
||||
{
|
||||
}
|
||||
|
||||
unsigned NetModulo::width_r() const
|
||||
{
|
||||
return width_r_;
|
||||
}
|
||||
|
||||
unsigned NetModulo::width_a() const
|
||||
{
|
||||
return width_a_;
|
||||
}
|
||||
|
||||
unsigned NetModulo::width_b() const
|
||||
{
|
||||
return width_b_;
|
||||
}
|
||||
|
||||
Link& NetModulo::pin_Result(unsigned idx)
|
||||
{
|
||||
assert(idx < width_r_);
|
||||
return pin(idx);
|
||||
}
|
||||
|
||||
const Link& NetModulo::pin_Result(unsigned idx) const
|
||||
{
|
||||
assert(idx < width_r_);
|
||||
return pin(idx);
|
||||
}
|
||||
|
||||
Link& NetModulo::pin_DataA(unsigned idx)
|
||||
{
|
||||
assert(idx < width_a_);
|
||||
return pin(idx+width_r_);
|
||||
}
|
||||
|
||||
const Link& NetModulo::pin_DataA(unsigned idx) const
|
||||
{
|
||||
assert(idx < width_a_);
|
||||
return pin(idx+width_r_);
|
||||
}
|
||||
|
||||
Link& NetModulo::pin_DataB(unsigned idx)
|
||||
{
|
||||
assert(idx < width_b_);
|
||||
return pin(idx+width_r_+width_a_);
|
||||
}
|
||||
|
||||
const Link& NetModulo::pin_DataB(unsigned idx) const
|
||||
{
|
||||
assert(idx < width_b_);
|
||||
return pin(idx+width_r_+width_a_);
|
||||
}
|
||||
|
||||
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (c) 2000 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
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: net_proc.cc,v 1.3 2001/07/25 03:10:49 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# include "netlist.h"
|
||||
# include <assert.h>
|
||||
|
||||
NetDisable::NetDisable(NetScope*tgt)
|
||||
: target_(tgt)
|
||||
{
|
||||
}
|
||||
|
||||
NetDisable::~NetDisable()
|
||||
{
|
||||
}
|
||||
|
||||
const NetScope* NetDisable::target() const
|
||||
{
|
||||
return target_;
|
||||
}
|
||||
|
||||
NetForever::NetForever(NetProc*p)
|
||||
: statement_(p)
|
||||
{
|
||||
}
|
||||
|
||||
NetForever::~NetForever()
|
||||
{
|
||||
delete statement_;
|
||||
}
|
||||
|
||||
NetPDelay::NetPDelay(unsigned long d, NetProc*st)
|
||||
: delay_(d), expr_(0), statement_(st)
|
||||
{
|
||||
}
|
||||
|
||||
NetPDelay::NetPDelay(NetExpr*d, NetProc*st)
|
||||
: delay_(0), expr_(d), statement_(st)
|
||||
{
|
||||
}
|
||||
|
||||
NetPDelay::~NetPDelay()
|
||||
{
|
||||
if (expr_) delete expr_;
|
||||
}
|
||||
|
||||
unsigned long NetPDelay::delay() const
|
||||
{
|
||||
assert(expr_ == 0);
|
||||
return delay_;
|
||||
}
|
||||
|
||||
const NetExpr* NetPDelay::expr() const
|
||||
{
|
||||
return expr_;
|
||||
}
|
||||
|
||||
NetRepeat::NetRepeat(NetExpr*e, NetProc*p)
|
||||
: expr_(e), statement_(p)
|
||||
{
|
||||
}
|
||||
|
||||
NetRepeat::~NetRepeat()
|
||||
{
|
||||
delete expr_;
|
||||
delete statement_;
|
||||
}
|
||||
|
||||
const NetExpr* NetRepeat::expr() const
|
||||
{
|
||||
return expr_;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* $Log: net_proc.cc,v $
|
||||
* 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/07/27 05:13:44 steve
|
||||
* Support elaboration of disable statements.
|
||||
*
|
||||
* Revision 1.1 2000/07/07 04:53:54 steve
|
||||
* Add support for non-constant delays in delay statements,
|
||||
* Support evaluating ! in constant expressions, and
|
||||
* move some code from netlist.cc to net_proc.cc.
|
||||
*
|
||||
*/
|
||||
|
||||
+402
@@ -0,0 +1,402 @@
|
||||
/*
|
||||
* Copyright (c) 2000 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
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: net_scope.cc,v 1.13 2001/07/25 03:10:49 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# include "netlist.h"
|
||||
# include <strstream>
|
||||
|
||||
/*
|
||||
* The NetScope class keeps a scope tree organized. Each node of the
|
||||
* scope tree points to its parent, its right sibling and its leftmost
|
||||
* child. The root node has no parent or siblings. The node stores the
|
||||
* name of the scope. The complete hierarchical name of the scope is
|
||||
* formed by appending the path of scopes from the root to the scope
|
||||
* in question.
|
||||
*/
|
||||
|
||||
NetScope::NetScope(NetScope*up, const string&n, NetScope::TYPE t)
|
||||
: type_(t), up_(up), sib_(0), sub_(0)
|
||||
{
|
||||
memories_ = 0;
|
||||
signals_ = 0;
|
||||
events_ = 0;
|
||||
|
||||
if (up) {
|
||||
time_unit_ = up->time_unit();
|
||||
time_prec_ = up->time_precision();
|
||||
sib_ = up_->sub_;
|
||||
up_->sub_ = this;
|
||||
} else {
|
||||
time_unit_ = 0;
|
||||
time_prec_ = 0;
|
||||
assert(t == MODULE);
|
||||
}
|
||||
|
||||
switch (t) {
|
||||
case NetScope::TASK:
|
||||
task_ = 0;
|
||||
break;
|
||||
case NetScope::FUNC:
|
||||
func_ = 0;
|
||||
break;
|
||||
case NetScope::MODULE:
|
||||
module_name_ = 0;
|
||||
break;
|
||||
}
|
||||
name_ = new char[n.length()+1];
|
||||
strcpy(name_, n.c_str());
|
||||
}
|
||||
|
||||
NetScope::~NetScope()
|
||||
{
|
||||
assert(sib_ == 0);
|
||||
assert(sub_ == 0);
|
||||
lcounter_ = 0;
|
||||
delete[]name_;
|
||||
if ((type_ == MODULE) && module_name_)
|
||||
free(module_name_);
|
||||
}
|
||||
|
||||
NetExpr* NetScope::set_parameter(const string&key, NetExpr*expr)
|
||||
{
|
||||
NetExpr*&ref = parameters_[key];
|
||||
NetExpr* res = ref;
|
||||
ref = expr;
|
||||
return res;
|
||||
}
|
||||
|
||||
NetExpr* NetScope::set_localparam(const string&key, NetExpr*expr)
|
||||
{
|
||||
NetExpr*&ref = localparams_[key];
|
||||
NetExpr* res = ref;
|
||||
ref = expr;
|
||||
return res;
|
||||
}
|
||||
|
||||
const NetExpr* NetScope::get_parameter(const string&key) const
|
||||
{
|
||||
map<string,NetExpr*>::const_iterator idx;
|
||||
|
||||
idx = parameters_.find(key);
|
||||
if (idx != parameters_.end())
|
||||
return (*idx).second;
|
||||
|
||||
idx = localparams_.find(key);
|
||||
if (idx != localparams_.end())
|
||||
return (*idx).second;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetScope::TYPE NetScope::type() const
|
||||
{
|
||||
return type_;
|
||||
}
|
||||
|
||||
void NetScope::set_task_def(NetTaskDef*def)
|
||||
{
|
||||
assert( type_ == TASK );
|
||||
assert( task_ == 0 );
|
||||
task_ = def;
|
||||
}
|
||||
|
||||
NetTaskDef* NetScope::task_def()
|
||||
{
|
||||
assert( type_ == TASK );
|
||||
return task_;
|
||||
}
|
||||
|
||||
const NetTaskDef* NetScope::task_def() const
|
||||
{
|
||||
assert( type_ == TASK );
|
||||
return task_;
|
||||
}
|
||||
|
||||
void NetScope::set_func_def(NetFuncDef*def)
|
||||
{
|
||||
assert( type_ == FUNC );
|
||||
assert( func_ == 0 );
|
||||
func_ = def;
|
||||
}
|
||||
|
||||
NetFuncDef* NetScope::func_def()
|
||||
{
|
||||
assert( type_ == FUNC );
|
||||
return func_;
|
||||
}
|
||||
|
||||
const NetFuncDef* NetScope::func_def() const
|
||||
{
|
||||
assert( type_ == FUNC );
|
||||
return func_;
|
||||
}
|
||||
|
||||
void NetScope::set_module_name(const char*n)
|
||||
{
|
||||
assert(type_ == MODULE);
|
||||
module_name_ = strdup(n);
|
||||
}
|
||||
|
||||
const char* NetScope::module_name() const
|
||||
{
|
||||
assert(type_ == MODULE);
|
||||
return module_name_;
|
||||
}
|
||||
|
||||
void NetScope::time_unit(int val)
|
||||
{
|
||||
time_unit_ = val;
|
||||
}
|
||||
|
||||
void NetScope::time_precision(int val)
|
||||
{
|
||||
time_prec_ = val;
|
||||
}
|
||||
|
||||
int NetScope::time_unit() const
|
||||
{
|
||||
return time_unit_;
|
||||
}
|
||||
|
||||
int NetScope::time_precision() const
|
||||
{
|
||||
return time_prec_;
|
||||
}
|
||||
|
||||
const char* NetScope::basename() const
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
|
||||
string NetScope::name() const
|
||||
{
|
||||
if (up_)
|
||||
return up_->name() + "." + name_;
|
||||
else
|
||||
return name_;
|
||||
}
|
||||
|
||||
void NetScope::add_event(NetEvent*ev)
|
||||
{
|
||||
assert(ev->scope_ == 0);
|
||||
ev->scope_ = this;
|
||||
ev->snext_ = events_;
|
||||
events_ = ev;
|
||||
}
|
||||
|
||||
void NetScope::rem_event(NetEvent*ev)
|
||||
{
|
||||
assert(ev->scope_ == this);
|
||||
ev->scope_ = 0;
|
||||
if (events_ == ev) {
|
||||
events_ = ev->snext_;
|
||||
|
||||
} else {
|
||||
NetEvent*cur = events_;
|
||||
while (cur->snext_ != ev) {
|
||||
assert(cur->snext_);
|
||||
cur = cur->snext_;
|
||||
}
|
||||
cur->snext_ = ev->snext_;
|
||||
}
|
||||
|
||||
ev->snext_ = 0;
|
||||
}
|
||||
|
||||
|
||||
NetEvent* NetScope::find_event(const string&name)
|
||||
{
|
||||
for (NetEvent*cur = events_; cur ; cur = cur->snext_)
|
||||
if (cur->name() == name)
|
||||
return cur;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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_;
|
||||
}
|
||||
}
|
||||
|
||||
NetNet* NetScope::find_signal(const string&key)
|
||||
{
|
||||
if (signals_ == 0)
|
||||
return 0;
|
||||
|
||||
string fulname = name()+"."+key;
|
||||
NetNet*cur = signals_;
|
||||
do {
|
||||
if (cur->name() == fulname)
|
||||
return cur;
|
||||
cur = cur->sig_prev_;
|
||||
} while (cur != signals_);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void NetScope::add_memory(NetMemory*mem)
|
||||
{
|
||||
if (memories_ == 0) {
|
||||
mem->snext_ = mem;
|
||||
mem->sprev_ = mem;
|
||||
} else {
|
||||
mem->snext_ = memories_->snext_;
|
||||
mem->sprev_ = memories_;
|
||||
mem->snext_->sprev_ = mem;
|
||||
mem->sprev_->snext_ = mem;
|
||||
}
|
||||
memories_ = mem;
|
||||
mem->scope_ = this;
|
||||
}
|
||||
|
||||
void NetScope::rem_memory(NetMemory*mem)
|
||||
{
|
||||
assert(mem->scope_ == this);
|
||||
if (memories_ == mem)
|
||||
memories_ = mem->sprev_;
|
||||
|
||||
if (memories_ == mem) {
|
||||
memories_ = 0;
|
||||
} else {
|
||||
mem->sprev_->snext_ = mem->snext_;
|
||||
mem->snext_->sprev_ = mem->sprev_;
|
||||
}
|
||||
mem->scope_ = 0;
|
||||
}
|
||||
|
||||
NetMemory* NetScope::find_memory(const string&key)
|
||||
{
|
||||
if (memories_ == 0)
|
||||
return 0;
|
||||
|
||||
string fulname = name()+"."+key;
|
||||
NetMemory*cur = memories_;
|
||||
do {
|
||||
if (cur->name() == fulname)
|
||||
return cur;
|
||||
cur = cur->sprev_;
|
||||
} while (cur != memories_);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This method locates a child scope by name. The name is the simple
|
||||
* name of the child, no heirarchy is searched.
|
||||
*/
|
||||
NetScope* NetScope::child(const string&name)
|
||||
{
|
||||
if (sub_ == 0) return 0;
|
||||
|
||||
NetScope*cur = sub_;
|
||||
while (cur->name_ != name) {
|
||||
if (cur->sib_ == 0) return 0;
|
||||
cur = cur->sib_;
|
||||
}
|
||||
|
||||
return cur;
|
||||
}
|
||||
|
||||
const NetScope* NetScope::child(const string&name) const
|
||||
{
|
||||
if (sub_ == 0) return 0;
|
||||
|
||||
NetScope*cur = sub_;
|
||||
while (cur->name_ != name) {
|
||||
if (cur->sib_ == 0) return 0;
|
||||
cur = cur->sib_;
|
||||
}
|
||||
|
||||
return cur;
|
||||
}
|
||||
|
||||
NetScope* NetScope::parent()
|
||||
{
|
||||
return up_;
|
||||
}
|
||||
|
||||
const NetScope* NetScope::parent() const
|
||||
{
|
||||
return up_;
|
||||
}
|
||||
|
||||
string NetScope::local_symbol()
|
||||
{
|
||||
strstream res;
|
||||
res << "_s" << (lcounter_++) << ends;
|
||||
return res.str();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* $Log: net_scope.cc,v $
|
||||
* Revision 1.13 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.12 2001/07/04 04:34:06 steve
|
||||
* Scope-locals use _s instead of _l.
|
||||
*
|
||||
* Revision 1.11 2000/12/16 01:45:48 steve
|
||||
* Detect recursive instantiations (PR#2)
|
||||
*
|
||||
* Revision 1.10 2000/10/06 23:46:50 steve
|
||||
* ivl_target updates, including more complete
|
||||
* handling of ivl_nexus_t objects. Much reduced
|
||||
* dependencies on pointers to netlist objects.
|
||||
*
|
||||
* Revision 1.9 2000/08/27 15:51:50 steve
|
||||
* t-dll iterates signals, and passes them to the
|
||||
* target module.
|
||||
*
|
||||
* Some of NetObj should return char*, not string.
|
||||
*
|
||||
* Revision 1.8 2000/07/30 18:25:44 steve
|
||||
* Rearrange task and function elaboration so that the
|
||||
* NetTaskDef and NetFuncDef functions are created during
|
||||
* signal enaboration, and carry these objects in the
|
||||
* NetScope class instead of the extra, useless map in
|
||||
* the Design class.
|
||||
*/
|
||||
|
||||
+114
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (c) 2000 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2001 Stephan Boettcher <stephan@nevis.columbia.edu>
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: net_udp.cc,v 1.6 2001/07/25 03:10:49 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# include "netlist.h"
|
||||
|
||||
NetUDP::NetUDP(NetScope*s, const string&n, unsigned pins, PUdp *u)
|
||||
: NetNode(s, n, pins), udp(u)
|
||||
{
|
||||
pin(0).set_dir(Link::OUTPUT);
|
||||
pin(0).set_name("O", 0);
|
||||
for (unsigned idx = 1 ; idx < pins ; idx += 1) {
|
||||
pin(idx).set_dir(Link::INPUT);
|
||||
pin(idx).set_name("I", idx-1);
|
||||
}
|
||||
}
|
||||
|
||||
bool NetUDP::first(string&inp, char&out) const
|
||||
{
|
||||
table_idx = (unsigned) -1;
|
||||
return next(inp, out);
|
||||
}
|
||||
|
||||
bool NetUDP::next(string&inp, char&out) const
|
||||
{
|
||||
table_idx++;
|
||||
|
||||
if (table_idx >= udp->tinput.count())
|
||||
return false;
|
||||
|
||||
if (is_sequential())
|
||||
{
|
||||
inp = string("") + udp->tcurrent[table_idx] + udp->tinput[table_idx];
|
||||
assert(inp.length() == pin_count());
|
||||
}
|
||||
else
|
||||
{
|
||||
inp = udp->tinput[table_idx];
|
||||
assert(inp.length() == (pin_count()-1));
|
||||
}
|
||||
|
||||
out = udp->toutput[table_idx];
|
||||
assert( (out == '0')
|
||||
|| (out == '1')
|
||||
|| (out == 'x')
|
||||
|| (is_sequential() && (out == '-')));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
char NetUDP::get_initial() const
|
||||
{
|
||||
assert (is_sequential());
|
||||
|
||||
switch (udp->initial)
|
||||
{
|
||||
case verinum::V0:
|
||||
return '0';
|
||||
case verinum::V1:
|
||||
return '1';
|
||||
case verinum::Vx:
|
||||
case verinum::Vz:
|
||||
return 'x';
|
||||
}
|
||||
|
||||
assert(0);
|
||||
return 'x';
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* $Log: net_udp.cc,v $
|
||||
* Revision 1.6 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.5 2001/04/24 02:23:58 steve
|
||||
* Support for UDP devices in VVP (Stephen Boettcher)
|
||||
*
|
||||
* Revision 1.4 2001/04/22 23:09:46 steve
|
||||
* More UDP consolidation from Stephan Boettcher.
|
||||
*
|
||||
* Revision 1.3 2000/12/15 01:24:17 steve
|
||||
* Accept x in outputs of primitive. (PR#84)
|
||||
*
|
||||
* Revision 1.2 2000/11/04 06:36:24 steve
|
||||
* Apply sequential UDP rework from Stephan Boettcher (PR#39)
|
||||
*
|
||||
* Revision 1.1 2000/03/29 04:37:11 steve
|
||||
* New and improved combinational primitives.
|
||||
*
|
||||
*/
|
||||
|
||||
+1128
-1500
File diff suppressed because it is too large
Load Diff
+77
-6
@@ -16,7 +16,7 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ident "$Id: netlist.txt,v 1.7 1999/11/28 23:42:02 steve Exp $"
|
||||
#ident "$Id: netlist.txt,v 1.10 2000/07/23 18:06:15 steve Exp $"
|
||||
|
||||
|
||||
Note that the netlist.h header contains detailed descriptions of how
|
||||
@@ -60,13 +60,20 @@ changed during processing.
|
||||
STRUCTURAL LINKS
|
||||
|
||||
The NetNode and NetNet classes contain arrays of Link objects, one
|
||||
object per pin. Each pin is a single bit. The Link objects link
|
||||
circularly to all the NetNode and NetNet objects' links that are
|
||||
connected together in the design. This way, code that examines a node
|
||||
object per pin. Each pin is a single bit. The Link objects link to all
|
||||
the NetNode and NetNet objects' links that are connected together in
|
||||
the design, and to a Nexus object. This way, code that examines a node
|
||||
of the design can discover what is connected to each pin.
|
||||
|
||||
See the NetObj::Link class definition for a description of the link
|
||||
methods.
|
||||
The connected set of links also has common properties that are stored
|
||||
or access from the Nexus object. All the Links that are connected
|
||||
together are also connected to a single Nexus object. This object is
|
||||
useful for accessing the properties and values that come from the
|
||||
connected set of links. The Nexus object is also handy for iterating
|
||||
over the connected set of Links.
|
||||
|
||||
See the Link class definition in netlist.h for a description of the link
|
||||
methods, and the Nexus class for nexus global methods.
|
||||
|
||||
Currently, a link has 3 possible direction properties:
|
||||
|
||||
@@ -229,6 +236,29 @@ can operate globally, with optimizations freely crossing module
|
||||
boundaries. This makes coding of netlist transform functions such as
|
||||
constant propagation more effective and easier to write.
|
||||
|
||||
|
||||
SCOPE REPRESENTATION IN NETLISTS
|
||||
|
||||
In spite of the literal flattening of the design, scope information is
|
||||
preserved in the netlist, with the NetScope class. The Design class
|
||||
keeps a single pointer to the root scope of the design. This is the
|
||||
scope of the root module. Scopes that are then created within that
|
||||
(or any nested) module are placed as children of the root scope, and
|
||||
those children can have further children, and so on.
|
||||
|
||||
Each scope in the tree carries its own name, and its relationship to
|
||||
its parent and children. This makes it possible to walk the tree of
|
||||
scopes. In practice, the walking of the scopes is handled by recursive
|
||||
methods.
|
||||
|
||||
Each scope also carries the parameters that are applicable to the
|
||||
scope itself. The parameter expression (possibly evaluated) can be
|
||||
located by name, given the scope object itself. The scan of the pform
|
||||
to generate scopes also places the parameters that are declared in the
|
||||
scope. Overrides are managed during the scan, and once the scan is
|
||||
complete, defparam overrides are applied.
|
||||
|
||||
|
||||
TASKS IN NETLISTS
|
||||
|
||||
The flattening of the design does not include tasks and named
|
||||
@@ -239,7 +269,48 @@ recurse. (The elaboration process does reserve the right to flatten
|
||||
some task calls. C++ programmers recognize this as inlining a task.)
|
||||
|
||||
|
||||
TIME SCALE IN NETLISTS
|
||||
|
||||
The Design class and the NetScope classes carry time scale and
|
||||
resolution information of the elaborated design. There is a global
|
||||
resolution, and there are scope specific units and resolutions. Units
|
||||
and resolutions are specified as signed integers, and interpreted as
|
||||
the power of 10 of the value. For example, a resolution "-9" means
|
||||
that "1" is 1ns (1e-9). The notation supports units from -128 to +127.
|
||||
It is up to the back-ends to interpret "-4" as "100us".
|
||||
|
||||
Delays are expressed in the netlist by integers. The units of these
|
||||
delays are always given in the units of the design precision. This
|
||||
allows everything to work with integers, and generally places the
|
||||
burden of scaling delays into elaboration. This is, after all, a
|
||||
common task. The Design::get_precision() method gets the global design
|
||||
precision.
|
||||
|
||||
Each NetScope also carries its local time_units and time_precision
|
||||
values. These are filled in during scope elaboration and are used in
|
||||
subsequent elaboration phases to arrange for scaling of delays. This
|
||||
information can also be used by the code generator to scale times back
|
||||
to the units of the scope, if that is desired.
|
||||
|
||||
$Log: netlist.txt,v $
|
||||
Revision 1.10 2000/07/23 18:06:15 steve
|
||||
Document time scale in netlists.
|
||||
|
||||
Revision 1.9 2000/07/14 06:12:57 steve
|
||||
Move inital value handling from NetNet to Nexus
|
||||
objects. This allows better propogation of inital
|
||||
values.
|
||||
|
||||
Clean up constant propagation a bit to account
|
||||
for regs that are not really values.
|
||||
|
||||
Revision 1.8 2000/03/08 04:36:54 steve
|
||||
Redesign the implementation of scopes and parameters.
|
||||
I now generate the scopes and notice the parameters
|
||||
in a separate pass over the pform. Once the scopes
|
||||
are generated, I can process overrides and evalutate
|
||||
paremeters before elaboration begins.
|
||||
|
||||
Revision 1.7 1999/11/28 23:42:02 steve
|
||||
NetESignal object no longer need to be NetNode
|
||||
objects. Let them keep a pointer to NetNet objects.
|
||||
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (c) 2001 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
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: netmisc.cc,v 1.2 2001/07/25 03:10:49 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# include "netlist.h"
|
||||
# include "netmisc.h"
|
||||
# include "PExpr.h"
|
||||
|
||||
|
||||
NetExpr* elab_and_eval(Design*des, NetScope*scope, const PExpr*pe)
|
||||
{
|
||||
NetExpr*tmp = pe->elaborate_expr(des, scope);
|
||||
if (tmp == 0)
|
||||
return 0;
|
||||
|
||||
if (NetExpr*tmp2 = tmp->eval_tree()) {
|
||||
delete tmp;
|
||||
tmp = tmp2;
|
||||
}
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* $Log: netmisc.cc,v $
|
||||
* Revision 1.2 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.1 2001/02/11 02:15:52 steve
|
||||
* Add the netmisc.cc source file.
|
||||
*
|
||||
*/
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user