mirror of
https://github.com/steveicarus/iverilog.git
synced 2026-08-26 07:46:31 +02:00
Compare commits
900
Commits
s20121218
...
vec4-stack
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
105521b547 | ||
|
|
fd3086f0a9 | ||
|
|
77ebfcacb9 | ||
|
|
d62a307c34 | ||
|
|
011519cb5b | ||
|
|
8a0b9acadc | ||
|
|
77d1671d8f | ||
|
|
561564065d | ||
|
|
409f8c5823 | ||
|
|
03198356a5 | ||
|
|
b1d2393789 | ||
|
|
0f740289e9 | ||
|
|
46ce236cfb | ||
|
|
86139c855d | ||
|
|
eb070b061b | ||
|
|
2b1393e7b9 | ||
|
|
85c7b07a9b | ||
|
|
0c5ed2b60f | ||
|
|
8fd1ead082 | ||
|
|
3bd307db85 | ||
|
|
35db02d35d | ||
|
|
f287546f49 | ||
|
|
1645e682f4 | ||
|
|
a57e0a1e3f | ||
|
|
b83144c552 | ||
|
|
58fb80aec4 | ||
|
|
38f277d81b | ||
|
|
f3ba335493 | ||
|
|
fb5ae48b18 | ||
|
|
68258f244e | ||
|
|
ee34ccec70 | ||
|
|
1834d470cb | ||
|
|
9bc463aac0 | ||
|
|
7c77097f71 | ||
|
|
cc4c5f4998 | ||
|
|
230c435ae7 | ||
|
|
4ddef32631 | ||
|
|
a236c274f3 | ||
|
|
21a8cb71ee | ||
|
|
b4ccaa1b0c | ||
|
|
a8d43fa743 | ||
|
|
ca2ef5c956 | ||
|
|
6015aceda2 | ||
|
|
9538501b54 | ||
|
|
ea7fa24f9e | ||
|
|
48d3701c02 | ||
|
|
c1164dcc33 | ||
|
|
1166cd932a | ||
|
|
c3a318f14e | ||
|
|
b2deae7ba9 | ||
|
|
675dd91403 | ||
|
|
b12e00d875 | ||
|
|
103828577b | ||
|
|
21c8b8ca5a | ||
|
|
25c588252f | ||
|
|
89d1125979 | ||
|
|
43c6a0bacd | ||
|
|
610ca95cbe | ||
|
|
daa59a95ad | ||
|
|
13f861a963 | ||
|
|
82ca4cf641 | ||
|
|
ac2e8dd6cd | ||
|
|
cd992b4d5a | ||
|
|
679021a1b5 | ||
|
|
f3392561ed | ||
|
|
7a9a022744 | ||
|
|
c222b3b6a4 | ||
|
|
663c79d4af | ||
|
|
bea03db25d | ||
|
|
b96f04ccce | ||
|
|
a9db765f98 | ||
|
|
c71ab5869a | ||
|
|
04bdfbccee | ||
|
|
2acc9fbdee | ||
|
|
725ed869ba | ||
|
|
301edf69d3 | ||
|
|
1612c6d638 | ||
|
|
aadd67cd3b | ||
|
|
c2ca9c3b73 | ||
|
|
0601b4e43b | ||
|
|
8aca66b109 | ||
|
|
2aeb3871ed | ||
|
|
ea21fb856e | ||
|
|
754899c99e | ||
|
|
4e94b81a4b | ||
|
|
6948c27c2d | ||
|
|
2e9c4cde55 | ||
|
|
2e8c4e3dbc | ||
|
|
cc9fcfd13d | ||
|
|
4660e0bf2f | ||
|
|
1e7509a021 | ||
|
|
c2e53f0d63 | ||
|
|
f171161822 | ||
|
|
0237297e93 | ||
|
|
e38b5d9fb7 | ||
|
|
d5123011b3 | ||
|
|
9a471bd81c | ||
|
|
632e15a55c | ||
|
|
d4313dad75 | ||
|
|
c25538d750 | ||
|
|
871d447ff7 | ||
|
|
b286b76134 | ||
|
|
4f62a0d1f2 | ||
|
|
e7df9774aa | ||
|
|
08afbde08d | ||
|
|
7ab0824adf | ||
|
|
7fad4779c5 | ||
|
|
8ac06fb63f | ||
|
|
4e727adc25 | ||
|
|
3e9c14060f | ||
|
|
702a8c3a05 | ||
|
|
48d3972299 | ||
|
|
62fce50f8c | ||
|
|
e4b862f3d1 | ||
|
|
09d3a5de59 | ||
|
|
97bde47c31 | ||
|
|
1c80c6e37a | ||
|
|
4588f7c615 | ||
|
|
006aef93d0 | ||
|
|
24b8752475 | ||
|
|
3ddcf03764 | ||
|
|
35f5d51028 | ||
|
|
87c019c65c | ||
|
|
69a1fecd2e | ||
|
|
9964d67e5e | ||
|
|
a98f21aa65 | ||
|
|
a63ca15735 | ||
|
|
d139142c29 | ||
|
|
af85d44d9f | ||
|
|
c5e0507941 | ||
|
|
c55a013162 | ||
|
|
dfbca0b186 | ||
|
|
4a779f43bd | ||
|
|
97df6183a9 | ||
|
|
95faed8e9d | ||
|
|
76aab15798 | ||
|
|
e896f0c8e6 | ||
|
|
f36bebf0e1 | ||
|
|
3fd622e4eb | ||
|
|
da4200c5bd | ||
|
|
712f394224 | ||
|
|
d6685f40a1 | ||
|
|
9ff9cbf4aa | ||
|
|
a992f3ce7c | ||
|
|
1a4edcac48 | ||
|
|
8cac72192f | ||
|
|
7f6100be2a | ||
|
|
4b60d2737e | ||
|
|
c7beef907d | ||
|
|
44da7de651 | ||
|
|
6887c82540 | ||
|
|
1333bc54a2 | ||
|
|
fddb3ec129 | ||
|
|
bfafd175fa | ||
|
|
23238aa7ac | ||
|
|
2397aa1587 | ||
|
|
b4119de9b1 | ||
|
|
338a0eb11a | ||
|
|
fde6525acb | ||
|
|
c5fee8bdb9 | ||
|
|
194a950f8d | ||
|
|
9951521212 | ||
|
|
9e856810b9 | ||
|
|
675b7d8efa | ||
|
|
e352bea476 | ||
|
|
747e656a0e | ||
|
|
7b5470c8a7 | ||
|
|
985a3eb206 | ||
|
|
e1ec27e18c | ||
|
|
d13e488f4c | ||
|
|
f5dd2ac87e | ||
|
|
94abef195a | ||
|
|
54696e0127 | ||
|
|
d85096c56a | ||
|
|
d16a9dcfc6 | ||
|
|
9842035d89 | ||
|
|
480668fee6 | ||
|
|
fa21527e9f | ||
|
|
98799ff7fa | ||
|
|
ea4b000be6 | ||
|
|
e330a0bd6e | ||
|
|
cb03802a17 | ||
|
|
22d18cb28d | ||
|
|
c98c3e5d14 | ||
|
|
a63289c2fc | ||
|
|
251b75003f | ||
|
|
01b4d49d4a | ||
|
|
f851fc6981 | ||
|
|
a25cde3bc7 | ||
|
|
51b121ae7a | ||
|
|
94caa4881e | ||
|
|
ef7ac5ed03 | ||
|
|
acce9fc2a0 | ||
|
|
1cfbd2db63 | ||
|
|
853512868b | ||
|
|
9b1de4b038 | ||
|
|
ec2793c9b0 | ||
|
|
697701a26e | ||
|
|
facc982af4 | ||
|
|
8bb1d3dabe | ||
|
|
88e951418b | ||
|
|
1572dcd3fd | ||
|
|
96d793ed6b | ||
|
|
15ccd8f4c9 | ||
|
|
d1a35d5152 | ||
|
|
3b0dfaadba | ||
|
|
1465fd1570 | ||
|
|
886b6cd349 | ||
|
|
0dc28c0fc3 | ||
|
|
dec4cd5071 | ||
|
|
0cd6fbaf41 | ||
|
|
9fa764285a | ||
|
|
fe8e7a6261 | ||
|
|
a0ea7e17cf | ||
|
|
8c3f7d78b9 | ||
|
|
684c2fe19e | ||
|
|
a67f18f8ef | ||
|
|
931039761a | ||
|
|
3852545f21 | ||
|
|
b4d0c43a96 | ||
|
|
c24c26725e | ||
|
|
1269c12054 | ||
|
|
4fb91ec7c7 | ||
|
|
e5f49baaac | ||
|
|
0f728b9150 | ||
|
|
b0c79d5d1c | ||
|
|
150fe088a6 | ||
|
|
bb66ed8b9d | ||
|
|
447e402d16 | ||
|
|
86bb269d47 | ||
|
|
486dc7abeb | ||
|
|
6765e32ab9 | ||
|
|
b1d15436fd | ||
|
|
c846b2cf3f | ||
|
|
10446df80e | ||
|
|
0a2100c87f | ||
|
|
27730395ca | ||
|
|
8e9c25a23e | ||
|
|
feccae56bf | ||
|
|
5de83906f7 | ||
|
|
8b969202c0 | ||
|
|
ea5789e4d9 | ||
|
|
f602ae84ab | ||
|
|
335db49282 | ||
|
|
8c2d51142b | ||
|
|
5ee253b03b | ||
|
|
c9ff48bd4e | ||
|
|
9b4681918b | ||
|
|
0894bc6409 | ||
|
|
da63ef02d4 | ||
|
|
a730572e37 | ||
|
|
d891285326 | ||
|
|
e8b8fcba57 | ||
|
|
6d052d4ff7 | ||
|
|
72ff9ac00b | ||
|
|
c92dea77fc | ||
|
|
4ea512c4fd | ||
|
|
89f1344288 | ||
|
|
96414af721 | ||
|
|
2d2a720ea8 | ||
|
|
9031f392ba | ||
|
|
4786f80b0b | ||
|
|
0f294cb607 | ||
|
|
f4c88b4a01 | ||
|
|
374948ce1b | ||
|
|
6a2b579fb0 | ||
|
|
d2ad7a4d28 | ||
|
|
5830ecd67e | ||
|
|
69b145e216 | ||
|
|
5ed60a151f | ||
|
|
c7a36722e3 | ||
|
|
66d31b02be | ||
|
|
0a6d75f1db | ||
|
|
6a2956c672 | ||
|
|
cdb1ea6264 | ||
|
|
df1d0a7b47 | ||
|
|
8d9ac35202 | ||
|
|
945584c310 | ||
|
|
d6b6b76015 | ||
|
|
0cbd6d99af | ||
|
|
8e7e3c7493 | ||
|
|
588409389e | ||
|
|
cc9d5f90e0 | ||
|
|
714795709c | ||
|
|
7b10570e11 | ||
|
|
cb381b3ee3 | ||
|
|
f5e01081d1 | ||
|
|
9c5113194d | ||
|
|
6bc3f98e0a | ||
|
|
b99b4b0223 | ||
|
|
fa38a8e08d | ||
|
|
14f597acdd | ||
|
|
b991a991a7 | ||
|
|
515137c8c7 | ||
|
|
d26a081cbc | ||
|
|
dff9953bc2 | ||
|
|
d8f10e7aa2 | ||
|
|
d5fb0f4344 | ||
|
|
c1e533d484 | ||
|
|
58ec35a6af | ||
|
|
ae6743cf69 | ||
|
|
850d8c3ee9 | ||
|
|
467e8afc41 | ||
|
|
f17690ebde | ||
|
|
774d173d69 | ||
|
|
9d99a64bf0 | ||
|
|
00a9c69348 | ||
|
|
8f7277a5ab | ||
|
|
e221a8ced9 | ||
|
|
a575eeb29d | ||
|
|
0dc12676f0 | ||
|
|
6ebb57195b | ||
|
|
78cb0a7876 | ||
|
|
47ddb18d54 | ||
|
|
0611135758 | ||
|
|
0ffd61a835 | ||
|
|
0728690df2 | ||
|
|
e82bafcb84 | ||
|
|
54f4c1147b | ||
|
|
642acb4082 | ||
|
|
6101044bff | ||
|
|
c6e44f2da1 | ||
|
|
3c0a982ab3 | ||
|
|
0f85bf0b9a | ||
|
|
ccce9d9271 | ||
|
|
9c79e321ae | ||
|
|
6d2fa6e579 | ||
|
|
f8dc430fe5 | ||
|
|
26f71f2d94 | ||
|
|
7cd3bdb0d0 | ||
|
|
81947edaa5 | ||
|
|
684e46a6c1 | ||
|
|
2bc9cb90dd | ||
|
|
1e18d43107 | ||
|
|
6a45a0d570 | ||
|
|
529e029abd | ||
|
|
855bf9cfe8 | ||
|
|
35a8485a44 | ||
|
|
12379ed26a | ||
|
|
6323e6a0a5 | ||
|
|
41ff18206a | ||
|
|
f104ffc133 | ||
|
|
ded1bd4949 | ||
|
|
579b59b8eb | ||
|
|
ef79f538d5 | ||
|
|
76883fa18c | ||
|
|
d05abf5ca4 | ||
|
|
ff72782ec6 | ||
|
|
d96e8872c1 | ||
|
|
6547fdee3d | ||
|
|
b7b77b2e75 | ||
|
|
f16c67d45a | ||
|
|
020e280a98 | ||
|
|
109c5d895d | ||
|
|
ce864fc634 | ||
|
|
be0c61051d | ||
|
|
ec0c66ff25 | ||
|
|
5893d13ea3 | ||
|
|
8d9f3a0920 | ||
|
|
17be8e8c7c | ||
|
|
c32610d135 | ||
|
|
be8df11217 | ||
|
|
650cedb516 | ||
|
|
a1d65336d2 | ||
|
|
d6405f86d4 | ||
|
|
8c80193fc5 | ||
|
|
e4476d544f | ||
|
|
c6cbaf3076 | ||
|
|
b687cc5f21 | ||
|
|
4d29df17b8 | ||
|
|
fdcb073c14 | ||
|
|
734d56ce25 | ||
|
|
a5423ce5ce | ||
|
|
e336eca00f | ||
|
|
3a77537ed8 | ||
|
|
c8b20da4be | ||
|
|
97e1151388 | ||
|
|
e6b394f825 | ||
|
|
f752007e9c | ||
|
|
40b36337e2 | ||
|
|
df4889ba3d | ||
|
|
2e2317b7c7 | ||
|
|
e2bad56a5c | ||
|
|
0accab6ec4 | ||
|
|
e55e832ea0 | ||
|
|
fc1f9ac6a5 | ||
|
|
6caa41cc93 | ||
|
|
751f19cc46 | ||
|
|
f8e33b12cd | ||
|
|
aaee9989c2 | ||
|
|
a849249a86 | ||
|
|
849ba64cf7 | ||
|
|
bb182cf3ce | ||
|
|
bc9382eea3 | ||
|
|
88e4938074 | ||
|
|
e932c7a637 | ||
|
|
b5e0099f28 | ||
|
|
1afe7476e3 | ||
|
|
4068570f43 | ||
|
|
3e41a93f3e | ||
|
|
7ceb18fb37 | ||
|
|
d2ff77d56c | ||
|
|
3c660d04f3 | ||
|
|
d0d421ebe2 | ||
|
|
13c1925045 | ||
|
|
c61d2151c1 | ||
|
|
065c48527c | ||
|
|
ed2e339dd6 | ||
|
|
5dcd2e8957 | ||
|
|
1f81d4c081 | ||
|
|
a3450bf856 | ||
|
|
91b7c6ab55 | ||
|
|
ebed793dec | ||
|
|
320f6d008c | ||
|
|
a76be3571d | ||
|
|
345c9cf21c | ||
|
|
5a06602af2 | ||
|
|
830083d99b | ||
|
|
6902bf44e3 | ||
|
|
8f849a9944 | ||
|
|
b1ef0997ed | ||
|
|
ecce1d25bc | ||
|
|
f43080fbcb | ||
|
|
463407572f | ||
|
|
6b6574dd8a | ||
|
|
4e81939eda | ||
|
|
66bdbb77ec | ||
|
|
5853f7d867 | ||
|
|
68f8de28af | ||
|
|
ac3aee0172 | ||
|
|
8135f369a5 | ||
|
|
be5bfeb172 | ||
|
|
801e795112 | ||
|
|
e66fc7e5cc | ||
|
|
1d63875e5d | ||
|
|
be1130ddbf | ||
|
|
9f2b7d6553 | ||
|
|
f5041e6c09 | ||
|
|
959ac3229e | ||
|
|
554fb7ebdd | ||
|
|
c9e8392dc7 | ||
|
|
60d37e1f53 | ||
|
|
e0ac4893f0 | ||
|
|
401fccdf6e | ||
|
|
f5564a195f | ||
|
|
c7e61f3aa4 | ||
|
|
a012406ca4 | ||
|
|
52a9fdde8a | ||
|
|
4f1c43b690 | ||
|
|
7f59c51ca2 | ||
|
|
0be577cc44 | ||
|
|
49cf5556a2 | ||
|
|
1805598eae | ||
|
|
0eca210722 | ||
|
|
3e95966d70 | ||
|
|
fdc9e8590d | ||
|
|
f76d56beb8 | ||
|
|
be17bfc0e9 | ||
|
|
77a01f65d0 | ||
|
|
e497f63e29 | ||
|
|
75233a9bca | ||
|
|
11197baf86 | ||
|
|
23ba0bc019 | ||
|
|
9cfb15a302 | ||
|
|
607b63a758 | ||
|
|
8bebe59e20 | ||
|
|
20d415463a | ||
|
|
9c1dcad994 | ||
|
|
0e13726e83 | ||
|
|
54346d7095 | ||
|
|
0121fbc88c | ||
|
|
f1855eed0e | ||
|
|
0f9828f179 | ||
|
|
d2c2d6d8dc | ||
|
|
f94a655121 | ||
|
|
078a3fd409 | ||
|
|
dfaed128c0 | ||
|
|
1fc4093191 | ||
|
|
ae1f8be277 | ||
|
|
d8533104b0 | ||
|
|
c6c697bdb7 | ||
|
|
660d59a7a9 | ||
|
|
92a5e6a698 | ||
|
|
aaa054a932 | ||
|
|
079065ea73 | ||
|
|
1905264061 | ||
|
|
b0a9430e98 | ||
|
|
f906384423 | ||
|
|
fc42f40770 | ||
|
|
6ec31517a9 | ||
|
|
8a4d769b3d | ||
|
|
a3b29dd70b | ||
|
|
b0491b9c54 | ||
|
|
6a93b6a7e4 | ||
|
|
ec6009dd8f | ||
|
|
4820d46353 | ||
|
|
a2845cee70 | ||
|
|
c897ca017c | ||
|
|
aee540d8bb | ||
|
|
19402aeef2 | ||
|
|
fcc0a6a203 | ||
|
|
2165905613 | ||
|
|
e5eb754150 | ||
|
|
d1c9dd554b | ||
|
|
063c6d6065 | ||
|
|
2fc8ce8a16 | ||
|
|
1a3adbe9cd | ||
|
|
63fa44fa4a | ||
|
|
f89dbd48c8 | ||
|
|
9fc3e84e93 | ||
|
|
e708a5b59d | ||
|
|
d55e4c0552 | ||
|
|
ef06bf7589 | ||
|
|
54926840e6 | ||
|
|
5ef077fdf6 | ||
|
|
336b29955d | ||
|
|
7fa2a4ccf3 | ||
|
|
e4fc5806c4 | ||
|
|
4def0110b5 | ||
|
|
503a1bf6d7 | ||
|
|
92e4ca3a92 | ||
|
|
9e25884f12 | ||
|
|
819770a6c4 | ||
|
|
7669a42cfb | ||
|
|
0495d75fcb | ||
|
|
0d6c15e45a | ||
|
|
49756a8e7a | ||
|
|
0b4056817a | ||
|
|
aced587461 | ||
|
|
077bd5b7ef | ||
|
|
bf9781e8fd | ||
|
|
40840368bb | ||
|
|
5946fa46a6 | ||
|
|
196df151aa | ||
|
|
c1566bc02b | ||
|
|
f349197df3 | ||
|
|
7e55babb62 | ||
|
|
5a0f9f4604 | ||
|
|
ae90da9951 | ||
|
|
9544cb516d | ||
|
|
fa8d35ae9c | ||
|
|
37ac1ed474 | ||
|
|
483d0534ae | ||
|
|
be7d763352 | ||
|
|
04bab6b197 | ||
|
|
f47af361cd | ||
|
|
676786a399 | ||
|
|
0692cd54e7 | ||
|
|
68d83383ff | ||
|
|
9bd9c8f301 | ||
|
|
f16fd03dab | ||
|
|
a7d8c983ba | ||
|
|
d192f545ac | ||
|
|
0157a156fb | ||
|
|
9f83882bcc | ||
|
|
bfb14fbbc6 | ||
|
|
be2595085f | ||
|
|
4625e7e2b6 | ||
|
|
bb39d09d5e | ||
|
|
36c91491cc | ||
|
|
d291e2b23d | ||
|
|
1814c24a90 | ||
|
|
92e08fdcd8 | ||
|
|
7875880aa1 | ||
|
|
383708fde8 | ||
|
|
4047ed7976 | ||
|
|
3c7d7a7856 | ||
|
|
d7c2118d10 | ||
|
|
97d06b107f | ||
|
|
61fbfb562e | ||
|
|
7e82a37fa3 | ||
|
|
141a23690e | ||
|
|
a024efb615 | ||
|
|
e60804cf41 | ||
|
|
d5a0f2fc07 | ||
|
|
2464582587 | ||
|
|
82ebf6372c | ||
|
|
3945b9df45 | ||
|
|
96813f76c1 | ||
|
|
2030e06988 | ||
|
|
cd85a42acc | ||
|
|
18c338ad09 | ||
|
|
2355e1ed8e | ||
|
|
5494c9ae09 | ||
|
|
20ad1ff261 | ||
|
|
589bb59268 | ||
|
|
e12d2b2f36 | ||
|
|
c64b8900ca | ||
|
|
1cd72d375c | ||
|
|
aa9a7435dd | ||
|
|
12c588fc35 | ||
|
|
8f0687adb7 | ||
|
|
281556e93d | ||
|
|
a196af8e15 | ||
|
|
7b07fca285 | ||
|
|
095cedb305 | ||
|
|
d5823b3e55 | ||
|
|
51ca2d1243 | ||
|
|
ec8081f983 | ||
|
|
34643d9628 | ||
|
|
68db6c5a65 | ||
|
|
d564e054e5 | ||
|
|
8616e3d6fa | ||
|
|
2c2ab24c8f | ||
|
|
d025c8aa93 | ||
|
|
7534abe325 | ||
|
|
7bc94d7810 | ||
|
|
a9a1c50268 | ||
|
|
5084a23417 | ||
|
|
46f551073e | ||
|
|
d9e1bcf3d0 | ||
|
|
13bb927d8a | ||
|
|
16414f921f | ||
|
|
9a116498a2 | ||
|
|
d8f945be23 | ||
|
|
8412d0d55f | ||
|
|
07cc18284c | ||
|
|
7d6d93e4e2 | ||
|
|
64b2345cf2 | ||
|
|
9b3987bf3c | ||
|
|
15cda5fef2 | ||
|
|
a10e07908e | ||
|
|
c2c9e09a49 | ||
|
|
1b79df810f | ||
|
|
9dde4b705d | ||
|
|
1abf4f1aa1 | ||
|
|
a47447610f | ||
|
|
d209d8ee39 | ||
|
|
8117f4b383 | ||
|
|
6b5ae5e4db | ||
|
|
a40c8f6bca | ||
|
|
a6fb6be8b5 | ||
|
|
ec99faff05 | ||
|
|
1352abfc98 | ||
|
|
687d0a928b | ||
|
|
947d642da7 | ||
|
|
1cbd6c3a80 | ||
|
|
11be93ce55 | ||
|
|
aaf35ca6ab | ||
|
|
4294a47cec | ||
|
|
b983d5546b | ||
|
|
ed9a3c3b10 | ||
|
|
d8f4ff4b57 | ||
|
|
af29735f44 | ||
|
|
638300045c | ||
|
|
71552b7d1a | ||
|
|
7c0a75cf0c | ||
|
|
f054500fe2 | ||
|
|
6684b2db04 | ||
|
|
999a53ab75 | ||
|
|
534d44ba55 | ||
|
|
c7c10613d7 | ||
|
|
dfc44db0ef | ||
|
|
7a6192b5c8 | ||
|
|
05f90bcf55 | ||
|
|
1be59d8ae7 | ||
|
|
b4dbb81af7 | ||
|
|
e709849243 | ||
|
|
1b2fa39cdc | ||
|
|
b4ec36ec78 | ||
|
|
dddaacc6fd | ||
|
|
e0c9efd129 | ||
|
|
01b81e0dbc | ||
|
|
d2034a6458 | ||
|
|
c4edbda969 | ||
|
|
f3917778bc | ||
|
|
032f12af45 | ||
|
|
bb37b74f98 | ||
|
|
817a38494c | ||
|
|
d6fe6ea936 | ||
|
|
af48acca14 | ||
|
|
11696e23d1 | ||
|
|
8b7dde0e41 | ||
|
|
54cb85adfc | ||
|
|
f636ffde48 | ||
|
|
87235b618b | ||
|
|
e4cc12f3b9 | ||
|
|
9d1084d3c0 | ||
|
|
21b24c7725 | ||
|
|
3e75f8e41f | ||
|
|
dec0fa622c | ||
|
|
dbd05557ca | ||
|
|
e30334e527 | ||
|
|
3e76f6d656 | ||
|
|
91ad8a72c6 | ||
|
|
e2361fab29 | ||
|
|
f6b8d613ab | ||
|
|
3a3cd8565d | ||
|
|
b9bcacd803 | ||
|
|
cbd1b948a2 | ||
|
|
d1c1997acf | ||
|
|
fcbb41c391 | ||
|
|
e736c022b1 | ||
|
|
d08e0270e4 | ||
|
|
bb1d26f4f7 | ||
|
|
173577d5f7 | ||
|
|
5326790932 | ||
|
|
4ef3ac5ca6 | ||
|
|
cf47a759d1 | ||
|
|
046535cfbb | ||
|
|
637d43fb5a | ||
|
|
fbc5557a10 | ||
|
|
75b4b94061 | ||
|
|
d346fb098f | ||
|
|
633360a0f9 | ||
|
|
0e8a257ec2 | ||
|
|
7fa4cf5a34 | ||
|
|
eecc3312b7 | ||
|
|
11e5641089 | ||
|
|
f631cb6314 | ||
|
|
a586bfd1ec | ||
|
|
4dbd0442aa | ||
|
|
fa9a439bf1 | ||
|
|
11e394aacf | ||
|
|
9af0811a1c | ||
|
|
503487e9ea | ||
|
|
ca9616dc7b | ||
|
|
24bd630cb2 | ||
|
|
8487cb5616 | ||
|
|
d630e4dfe9 | ||
|
|
3d5765949e | ||
|
|
0fcd2d9db6 | ||
|
|
3446455055 | ||
|
|
af304fea65 | ||
|
|
bcaa6accec | ||
|
|
5c00b96127 | ||
|
|
bfe3998eaa | ||
|
|
096e53dea4 | ||
|
|
bc77a19059 | ||
|
|
1b178d56b7 | ||
|
|
dca6171f5f | ||
|
|
164b5f9348 | ||
|
|
e927960121 | ||
|
|
6394a4d78d | ||
|
|
13be45bd73 | ||
|
|
7f7decde03 | ||
|
|
d9fea802da | ||
|
|
34f6e25b4e | ||
|
|
afe1e79338 | ||
|
|
cbaf36d4b8 | ||
|
|
6f8eede371 | ||
|
|
c693930595 | ||
|
|
6364aba975 | ||
|
|
10ec58703f | ||
|
|
9a69fcff7b | ||
|
|
26dc6d68cd | ||
|
|
0aca19356c | ||
|
|
5e94554d72 | ||
|
|
7d26515bc4 | ||
|
|
71c6193ff1 | ||
|
|
b0b6be0d23 | ||
|
|
7c1638652a | ||
|
|
1b1aa06dee | ||
|
|
51d3c03922 | ||
|
|
431d62185b | ||
|
|
c55eb37148 | ||
|
|
de6c57d661 | ||
|
|
ac78ba588f | ||
|
|
8e559e4e91 | ||
|
|
eff6e7a441 | ||
|
|
8994ef1483 | ||
|
|
20ee350601 | ||
|
|
c4257ecfc9 | ||
|
|
a91840c15d | ||
|
|
a748736d10 | ||
|
|
11682fc7eb | ||
|
|
255922e545 | ||
|
|
98694f15ce | ||
|
|
36b04748d4 | ||
|
|
d2928d500d | ||
|
|
15379f1750 | ||
|
|
0a4d8acefb | ||
|
|
632fd006c5 | ||
|
|
256c0986bb | ||
|
|
db7fbba08e | ||
|
|
f536a43e92 | ||
|
|
283ae6e538 | ||
|
|
fbafb915d2 | ||
|
|
4c52f66f5d | ||
|
|
46f63db746 | ||
|
|
4ad556d464 | ||
|
|
4dffd97d28 | ||
|
|
b1d853bf9b | ||
|
|
eba3d407ca | ||
|
|
44cd9158e8 | ||
|
|
b122ec2a1a | ||
|
|
bae0f1d3a7 | ||
|
|
23dbfabb1e | ||
|
|
6da71fdf56 | ||
|
|
bdfd5b9b55 | ||
|
|
64dffa5745 | ||
|
|
b9011d89ae | ||
|
|
3b3a4d3ddc | ||
|
|
b1613e99e6 | ||
|
|
d0f2a9e961 | ||
|
|
fb23493a98 | ||
|
|
17330a3073 | ||
|
|
fac5cbca43 | ||
|
|
670601bc2a | ||
|
|
25b48fa790 | ||
|
|
dd5fb47c6c | ||
|
|
b80401e1ee | ||
|
|
1bcd3a97ad | ||
|
|
09f90ab4e1 | ||
|
|
5929a00845 | ||
|
|
5d7558b5e0 | ||
|
|
ee71ade720 | ||
|
|
e437321ea7 | ||
|
|
6da610fe1e | ||
|
|
e8d4039175 | ||
|
|
faece5816c | ||
|
|
bc2a4c01c9 | ||
|
|
22769afd20 | ||
|
|
03ebd2f98d | ||
|
|
b378dccbe9 | ||
|
|
1f9489a65d | ||
|
|
f436b5d18e | ||
|
|
64401ab815 | ||
|
|
952169ded9 | ||
|
|
1b36aa5560 | ||
|
|
69705ef32b | ||
|
|
2e86c208d1 | ||
|
|
27b8738d06 | ||
|
|
8fa79ceb30 | ||
|
|
60cb78e4ab | ||
|
|
97f3a01dc5 | ||
|
|
99b8086ad2 | ||
|
|
c4386da666 | ||
|
|
51112131ad | ||
|
|
8808cd9514 | ||
|
|
890589191c | ||
|
|
75c78c7c5b | ||
|
|
69de1da172 | ||
|
|
28bc333cba | ||
|
|
8b4dc05ff8 | ||
|
|
6de80adbe8 | ||
|
|
fdcef3cbc4 | ||
|
|
41c7aa9e83 | ||
|
|
1929cfc4f9 | ||
|
|
8b70fefa59 | ||
|
|
af91920a17 | ||
|
|
89244e0f70 | ||
|
|
5abd939655 | ||
|
|
06ce23d9c2 | ||
|
|
a581e0ef0e | ||
|
|
b6ec138644 | ||
|
|
dc387ad9d1 | ||
|
|
48b186576e | ||
|
|
15b0946fc4 | ||
|
|
5830e65829 | ||
|
|
f3a51fdfd1 | ||
|
|
afd23d13d5 | ||
|
|
11f479e028 | ||
|
|
838f6ce862 | ||
|
|
e99d53b80b | ||
|
|
1d314faf97 | ||
|
|
751587e112 | ||
|
|
673675fecd | ||
|
|
ee58fd749c | ||
|
|
bcc7973792 | ||
|
|
b176a6410d | ||
|
|
d8592b1444 | ||
|
|
4568766cff | ||
|
|
c49b21115a | ||
|
|
106850ca7d | ||
|
|
2ea5919a4a | ||
|
|
0375ff3923 | ||
|
|
59ce217ce2 | ||
|
|
350369f3fc | ||
|
|
d9c400ac0c | ||
|
|
922b74be9e | ||
|
|
cd239a9857 | ||
|
|
8e515a9a64 | ||
|
|
45bb1313e7 | ||
|
|
d04aa4b234 | ||
|
|
074055bc58 | ||
|
|
d6726f62fc | ||
|
|
bc9e31a444 | ||
|
|
f682d9cad1 | ||
|
|
1305d7659c | ||
|
|
502a0708ea | ||
|
|
c64407f7cf | ||
|
|
cdbfe28c4e | ||
|
|
fbd2843cad | ||
|
|
10b5a82904 | ||
|
|
1527b87595 | ||
|
|
4407bc1d50 | ||
|
|
927edf03d6 | ||
|
|
f5717a6e87 | ||
|
|
84a24f2a34 | ||
|
|
60b1ade52d | ||
|
|
81ba40456f | ||
|
|
1b684a4846 | ||
|
|
3b43fcfc21 | ||
|
|
4b3ef8a314 | ||
|
|
679ef3a380 | ||
|
|
367d7bf94b | ||
|
|
e5f84002b1 | ||
|
|
f926cbcc59 | ||
|
|
5451a4830f |
@@ -30,6 +30,10 @@ Makefile
|
||||
/_pli_types.h
|
||||
config.h
|
||||
/tgt-pcb/pcb_config.h
|
||||
/tgt-pcb/fp.cc
|
||||
/tgt-pcb/fp.h
|
||||
/tgt-pcb/fp.output
|
||||
/tgt-pcb/fp_lex.cc
|
||||
/tgt-vvp/vvp_config.h
|
||||
/tgt-vhdl/vhdl_config.h
|
||||
/vpi/vpi_config.h
|
||||
@@ -47,6 +51,8 @@ dep
|
||||
*.vpi
|
||||
/cadpli/cadpli.vpl
|
||||
|
||||
/tgt-blif/Makefile
|
||||
|
||||
# lex, yacc and gperf output
|
||||
/driver/cflexor.c
|
||||
/driver/cfparse.c
|
||||
|
||||
+4
-4
@@ -1,7 +1,7 @@
|
||||
#ifndef __AStatement_H
|
||||
#define __AStatement_H
|
||||
#ifndef IVL_AStatement_H
|
||||
#define IVL_AStatement_H
|
||||
/*
|
||||
* Copyright (c) 2008 Stephen Williams ([email protected])
|
||||
* Copyright (c) 2008-2014 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
|
||||
@@ -82,4 +82,4 @@ class AProcess : public LineInfo {
|
||||
AProcess& operator= (const AProcess&);
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif /* IVL_AStatement_H */
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __Attrib_H
|
||||
#define __Attrib_H
|
||||
#ifndef IVL_Attrib_H
|
||||
#define IVL_Attrib_H
|
||||
/*
|
||||
* Copyright (c) 2000-2009 Stephen Williams ([email protected])
|
||||
* Copyright (c) 2000-2014 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
|
||||
@@ -57,4 +57,4 @@ class Attrib {
|
||||
Attrib& operator= (const Attrib&);
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif /* IVL_Attrib_H */
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
@@ -16,7 +15,7 @@ software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
@@ -56,8 +55,8 @@ patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
@@ -111,7 +110,7 @@ above, provided that you also meet all of these conditions:
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
@@ -169,7 +168,7 @@ access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
@@ -226,7 +225,7 @@ impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
@@ -256,7 +255,7 @@ make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
@@ -278,9 +277,9 @@ YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
Appendix: How to Apply These Terms to Your New Programs
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
@@ -292,7 +291,7 @@ convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) 19yy <name of author>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -304,16 +303,16 @@ the "copyright" line and a pointer to where the full notice is found.
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) 19yy name of author
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
@@ -336,5 +335,5 @@ necessary. Here is a sample; alter the names:
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001-2012 Stephen Williams ([email protected])
|
||||
* Copyright (c) 2001-2014 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
|
||||
@@ -22,22 +22,26 @@
|
||||
# include <iostream>
|
||||
# include <cstring>
|
||||
# include <cstdlib>
|
||||
# include <climits>
|
||||
|
||||
using namespace std;
|
||||
|
||||
hname_t::hname_t()
|
||||
{
|
||||
number_ = INT_MIN;
|
||||
}
|
||||
|
||||
hname_t::hname_t(perm_string text)
|
||||
: name_(text)
|
||||
{
|
||||
number_ = INT_MIN;
|
||||
}
|
||||
|
||||
hname_t::hname_t(perm_string text, int num)
|
||||
: name_(text), number_(num)
|
||||
: name_(text), number_(1)
|
||||
{
|
||||
number_[0] = num;
|
||||
}
|
||||
|
||||
hname_t::hname_t(perm_string text, vector<int>&nums)
|
||||
: name_(text), number_(nums)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -53,24 +57,50 @@ hname_t& hname_t::operator = (const hname_t&that)
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator < (const hname_t&l, const hname_t&r)
|
||||
bool hname_t::operator < (const hname_t&r) const
|
||||
{
|
||||
int cmp = strcmp(l.peek_name(), r.peek_name());
|
||||
int cmp = strcmp(name_, r.name_);
|
||||
if (cmp < 0) return true;
|
||||
if (cmp > 0) return false;
|
||||
if (l.has_number() && r.has_number())
|
||||
return l.peek_number() < r.peek_number();
|
||||
else
|
||||
return false;
|
||||
|
||||
// The text parts are equal, so compare then number
|
||||
// parts. Finish as soon as we find one to be less or more
|
||||
// than the other.
|
||||
size_t idx = 0;
|
||||
while (number_.size() > idx || r.number_.size() > idx) {
|
||||
|
||||
// Ran out of l numbers, so less.
|
||||
if (number_.size() <= idx)
|
||||
return true;
|
||||
|
||||
// Ran out of r numbers, so greater.
|
||||
if (r.number_.size() <= idx)
|
||||
return false;
|
||||
|
||||
if (number_[idx] < r.number_[idx])
|
||||
return true;
|
||||
|
||||
if (number_[idx] > r.number_[idx])
|
||||
return false;
|
||||
|
||||
idx += 1;
|
||||
}
|
||||
|
||||
// Fall-through means that we are equal, including all the
|
||||
// number parts, so not less.
|
||||
return false;
|
||||
}
|
||||
|
||||
bool operator == (const hname_t&l, const hname_t&r)
|
||||
bool hname_t::operator == (const hname_t&r) const
|
||||
{
|
||||
if (l.peek_name() == r.peek_name()) {
|
||||
if (l.has_number() && r.has_number())
|
||||
return l.peek_number() == r.peek_number();
|
||||
else
|
||||
return true;
|
||||
if (name_ == r.name_) {
|
||||
if (number_.size() != r.number_.size())
|
||||
return false;
|
||||
|
||||
for (size_t idx = 0 ; idx < number_.size() ; idx += 1)
|
||||
if (number_[idx] != r.number_[idx]) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -84,8 +114,8 @@ ostream& operator<< (ostream&out, const hname_t&that)
|
||||
}
|
||||
|
||||
out << that.peek_name();
|
||||
if (that.has_number())
|
||||
out << "[" << that.peek_number() << "]";
|
||||
for (size_t idx = 0 ; idx < that.number_.size() ; idx += 1)
|
||||
out << "[" << that.number_[idx] << "]";
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __HName_H
|
||||
#define __HName_H
|
||||
#ifndef IVL_HName_H
|
||||
#define IVL_HName_H
|
||||
/*
|
||||
* Copyright (c) 2001-2010 Stephen Williams ([email protected])
|
||||
* Copyright (c) 2001-2014 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -21,13 +21,10 @@
|
||||
|
||||
# include <iostream>
|
||||
# include <list>
|
||||
# include <vector>
|
||||
# include "StringHeap.h"
|
||||
# include <climits>
|
||||
#ifdef __GNUC__
|
||||
#if __GNUC__ > 2
|
||||
using namespace std;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
# include <cassert>
|
||||
|
||||
/*
|
||||
* This class represents a component of a Verilog hierarchical name. A
|
||||
@@ -39,27 +36,33 @@ using namespace std;
|
||||
|
||||
class hname_t {
|
||||
|
||||
friend ostream& operator<< (ostream&out, const hname_t&that);
|
||||
|
||||
public:
|
||||
hname_t ();
|
||||
explicit hname_t (perm_string text);
|
||||
explicit hname_t (perm_string text, int num);
|
||||
explicit hname_t (perm_string text, std::vector<int>&nums);
|
||||
hname_t (const hname_t&that);
|
||||
~hname_t();
|
||||
|
||||
hname_t& operator= (const hname_t&);
|
||||
|
||||
bool operator == (const hname_t&that) const;
|
||||
bool operator < (const hname_t&that) const;
|
||||
|
||||
// Return the string part of the hname_t.
|
||||
perm_string peek_name(void) const;
|
||||
|
||||
bool has_number() const;
|
||||
int peek_number() const;
|
||||
size_t has_numbers() const;
|
||||
int peek_number(size_t idx) const;
|
||||
|
||||
private:
|
||||
perm_string name_;
|
||||
// If the number is anything other than INT_MIN, then this is
|
||||
// the numeric part of the name. Otherwise, it is not part of
|
||||
// the name at all.
|
||||
int number_;
|
||||
std::vector<int> number_;
|
||||
|
||||
private: // not implemented
|
||||
};
|
||||
@@ -73,18 +76,17 @@ inline perm_string hname_t::peek_name(void) const
|
||||
return name_;
|
||||
}
|
||||
|
||||
inline int hname_t::peek_number() const
|
||||
inline int hname_t::peek_number(size_t idx) const
|
||||
{
|
||||
return number_;
|
||||
assert(number_.size() > idx);
|
||||
return number_[idx];
|
||||
}
|
||||
|
||||
inline bool hname_t::has_number() const
|
||||
inline size_t hname_t::has_numbers() const
|
||||
{
|
||||
return number_ != INT_MIN;
|
||||
return number_.size();
|
||||
}
|
||||
|
||||
extern bool operator < (const hname_t&, const hname_t&);
|
||||
extern bool operator == (const hname_t&, const hname_t&);
|
||||
extern ostream& operator<< (ostream&, const hname_t&);
|
||||
|
||||
inline bool operator != (const hname_t&l, const hname_t&r)
|
||||
@@ -102,4 +104,4 @@ inline ostream& operator<< (ostream&out, const list<hname_t>&ll)
|
||||
return out;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* IVL_HName_H */
|
||||
|
||||
+8
-5
@@ -38,7 +38,7 @@ srcdir = @srcdir@
|
||||
datarootdir = @datarootdir@
|
||||
|
||||
SUBDIRS = ivlpp vhdlpp vvp vpi libveriuser cadpli tgt-null tgt-stub tgt-vvp \
|
||||
tgt-vhdl tgt-vlog95 tgt-pcb driver
|
||||
tgt-vhdl tgt-vlog95 tgt-pcb tgt-blif tgt-sizer driver
|
||||
# Only run distclean for these directories.
|
||||
NOTUSED = tgt-fpga tgt-pal tgt-verilog
|
||||
|
||||
@@ -68,7 +68,7 @@ dllib=@DLLIB@
|
||||
|
||||
# For a cross compile these defines will need to be set accordingly.
|
||||
HOSTCC = @CC@
|
||||
HOSTCFLAGS = @WARNING_FLAGS@ @CFLAGS@
|
||||
HOSTCFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CC@ @CFLAGS@
|
||||
|
||||
CC = @CC@
|
||||
CXX = @CXX@
|
||||
@@ -90,7 +90,7 @@ INCLUDE_PATH = -I. -I$(srcdir) -I$(srcdir)/libmisc
|
||||
endif
|
||||
|
||||
CPPFLAGS = @DEFS@ $(INCLUDE_PATH) @CPPFLAGS@
|
||||
CFLAGS = @WARNING_FLAGS@ @CFLAGS@
|
||||
CFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CC@ @CFLAGS@
|
||||
CXXFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CXX@ @CXXFLAGS@
|
||||
PICFLAGS = @PICFLAG@
|
||||
LDFLAGS = @rdynamic@ @LDFLAGS@
|
||||
@@ -109,7 +109,8 @@ O = main.o async.o design_dump.o discipline.o dup_expr.o elaborate.o \
|
||||
eval_tree.o expr_synth.o functor.o lexor.o lexor_keyword.o link_const.o \
|
||||
load_module.o netlist.o netmisc.o nettypes.o net_analog.o net_assign.o \
|
||||
net_design.o netclass.o netdarray.o \
|
||||
netenum.o netparray.o netstruct.o netvector.o net_event.o net_expr.o net_func.o \
|
||||
netenum.o netparray.o netqueue.o netscalar.o netstruct.o netvector.o \
|
||||
net_event.o net_expr.o net_func.o \
|
||||
net_func_eval.o net_link.o net_modulo.o \
|
||||
net_nex_input.o net_nex_output.o net_proc.o net_scope.o net_tran.o \
|
||||
net_udp.o pad_to_width.o parse.o parse_misc.o pform.o pform_analog.o \
|
||||
@@ -174,6 +175,8 @@ endif
|
||||
|
||||
cppcheck: $(O:.o=.cc) $(srcdir)/dosify.c $(srcdir)/version.c
|
||||
cppcheck --enable=all -f --suppressions-list=$(srcdir)/cppcheck.sup \
|
||||
-UYYPARSE_PARAM -UYYPRINT -Ushort -Usize_t -Uyyoverflow \
|
||||
-UYYTYPE_INT8 -UYYTYPE_INT16 -UYYTYPE_UINT8 -UYYTYPE_UINT16 \
|
||||
--relative-paths=$(srcdir) $(INCLUDE_PATH) $^
|
||||
|
||||
cppcheck-all:
|
||||
@@ -264,7 +267,7 @@ lexor.cc: $(srcdir)/lexor.lex
|
||||
lexor_keyword.o: lexor_keyword.cc parse.h
|
||||
|
||||
lexor_keyword.cc: $(srcdir)/lexor_keyword.gperf
|
||||
gperf -o -i 7 -C -k 1-4,6,9,$$ -L ANSI-C -H keyword_hash -N check_identifier -t $(srcdir)/lexor_keyword.gperf > lexor_keyword.cc || (rm -f lexor_keyword.cc ; false)
|
||||
gperf -o -i 7 -C -k 1-4,6,9,$$ -H keyword_hash -N check_identifier -t $(srcdir)/lexor_keyword.gperf > lexor_keyword.cc || (rm -f lexor_keyword.cc ; false)
|
||||
|
||||
iverilog-vpi.man: $(srcdir)/iverilog-vpi.man.in version.exe
|
||||
./version.exe `head -1 $(srcdir)/iverilog-vpi.man.in`'\n' > $@
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __Module_H
|
||||
#define __Module_H
|
||||
#ifndef IVL_Module_H
|
||||
#define IVL_Module_H
|
||||
/*
|
||||
* Copyright (c) 1998-2010,2012 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2014 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
|
||||
@@ -160,4 +160,4 @@ class Module : public PScopeExtra, public LineInfo {
|
||||
Module& operator= (const Module&);
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif /* IVL_Module_H */
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
# include "PClass.h"
|
||||
|
||||
PClass::PClass(perm_string name, LexicalScope*parent)
|
||||
: PScopeExtra(name, parent)
|
||||
: PScopeExtra(name, parent), type(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __PClass_H
|
||||
#define __PClass_H
|
||||
#ifndef IVL_PClass_H
|
||||
#define IVL_PClass_H
|
||||
/*
|
||||
* Copyright (c) 2012 Stephen Williams ([email protected])
|
||||
* Copyright (c) 2012-2014 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -24,6 +24,8 @@
|
||||
# include "StringHeap.h"
|
||||
# include <iostream>
|
||||
|
||||
class PChainConstructor;
|
||||
|
||||
/*
|
||||
* SystemVerilog supports class declarations with their own lexical
|
||||
* scope, etc. The parser arranges for these to be created and
|
||||
@@ -42,4 +44,4 @@ class PClass : public PScopeExtra, public LineInfo {
|
||||
class_type_t*type;
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif /* IVL_PClass_H */
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __PDelays_H
|
||||
#define __PDelays_H
|
||||
#ifndef IVL_PDelays_H
|
||||
#define IVL_PDelays_H
|
||||
/*
|
||||
* Copyright (c) 1999-2010 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1999-2014 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
|
||||
@@ -72,4 +72,4 @@ class PDelays {
|
||||
|
||||
ostream& operator << (ostream&o, const PDelays&);
|
||||
|
||||
#endif
|
||||
#endif /* IVL_PDelays_H */
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __PEvent_H
|
||||
#define __PEvent_H
|
||||
#ifndef IVL_PEvent_H
|
||||
#define IVL_PEvent_H
|
||||
/*
|
||||
* Copyright (c) 2000-2004 Stephen Williams ([email protected])
|
||||
* Copyright (c) 2000-2014 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
|
||||
@@ -51,4 +51,4 @@ class PEvent : public LineInfo {
|
||||
PEvent& operator= (const PEvent&);
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif /* IVL_PEvent_H */
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 1998-2012 Stephen Williams <[email protected]>
|
||||
* Copyright CERN 2013 / 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
|
||||
@@ -76,6 +77,44 @@ bool PExpr::is_collapsible_net(Design*, NetScope*) const
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
const char* PExpr::width_mode_name(width_mode_t mode)
|
||||
{
|
||||
switch (mode) {
|
||||
case PExpr::SIZED:
|
||||
return "sized";
|
||||
case PExpr::UNSIZED:
|
||||
return "unsized";
|
||||
case PExpr::EXPAND:
|
||||
return "expand";
|
||||
case PExpr::LOSSLESS:
|
||||
return "lossless";
|
||||
case PExpr::UPSIZE:
|
||||
return "upsize";
|
||||
default:
|
||||
return "??";
|
||||
}
|
||||
}
|
||||
|
||||
PEAssignPattern::PEAssignPattern()
|
||||
{
|
||||
}
|
||||
|
||||
PEAssignPattern::PEAssignPattern(const list<PExpr*>&p)
|
||||
: parms_(p.size())
|
||||
{
|
||||
size_t idx = 0;
|
||||
for (list<PExpr*>::const_iterator cur = p.begin()
|
||||
; cur != p.end() ; ++cur) {
|
||||
parms_[idx] = *cur;
|
||||
idx += 1;
|
||||
}
|
||||
}
|
||||
|
||||
PEAssignPattern::~PEAssignPattern()
|
||||
{
|
||||
}
|
||||
|
||||
PEBinary::PEBinary(char op, PExpr*l, PExpr*r)
|
||||
: op_(op), left_(l), right_(r)
|
||||
{
|
||||
@@ -107,6 +146,15 @@ PECastSize::~PECastSize()
|
||||
{
|
||||
}
|
||||
|
||||
PECastType::PECastType(data_type_t*t, PExpr*b)
|
||||
: target_(t), base_(b)
|
||||
{
|
||||
}
|
||||
|
||||
PECastType::~PECastType()
|
||||
{
|
||||
}
|
||||
|
||||
PEBComp::PEBComp(char op, PExpr*l, PExpr*r)
|
||||
: PEBinary(op, l, r)
|
||||
{
|
||||
@@ -156,7 +204,12 @@ PEBShift::~PEBShift()
|
||||
}
|
||||
|
||||
PECallFunction::PECallFunction(const pform_name_t&n, const vector<PExpr *> &parms)
|
||||
: path_(n), parms_(parms)
|
||||
: package_(0), path_(n), parms_(parms)
|
||||
{
|
||||
}
|
||||
|
||||
PECallFunction::PECallFunction(PPackage*pkg, const pform_name_t&n, const vector<PExpr *> &parms)
|
||||
: package_(pkg), path_(n), parms_(parms)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -168,19 +221,29 @@ static pform_name_t pn_from_ps(perm_string n)
|
||||
return tmp;
|
||||
}
|
||||
|
||||
PECallFunction::PECallFunction(PPackage*pkg, perm_string n, const list<PExpr *> &parms)
|
||||
: package_(pkg), path_(pn_from_ps(n)), parms_(parms.size())
|
||||
{
|
||||
int tmp_idx = 0;
|
||||
assert(parms_.size() == parms.size());
|
||||
for (list<PExpr*>::const_iterator idx = parms.begin()
|
||||
; idx != parms.end() ; ++idx)
|
||||
parms_[tmp_idx++] = *idx;
|
||||
}
|
||||
|
||||
PECallFunction::PECallFunction(perm_string n, const vector<PExpr*>&parms)
|
||||
: path_(pn_from_ps(n)), parms_(parms)
|
||||
: package_(0), path_(pn_from_ps(n)), parms_(parms)
|
||||
{
|
||||
}
|
||||
|
||||
PECallFunction::PECallFunction(perm_string n)
|
||||
: path_(pn_from_ps(n))
|
||||
: package_(0), path_(pn_from_ps(n))
|
||||
{
|
||||
}
|
||||
|
||||
// NOTE: Anachronism. Try to work all use of svector out.
|
||||
PECallFunction::PECallFunction(const pform_name_t&n, const list<PExpr *> &parms)
|
||||
: path_(n), parms_(parms.size())
|
||||
: package_(0), path_(n), parms_(parms.size())
|
||||
{
|
||||
int tmp_idx = 0;
|
||||
assert(parms_.size() == parms.size());
|
||||
@@ -190,7 +253,7 @@ PECallFunction::PECallFunction(const pform_name_t&n, const list<PExpr *> &parms)
|
||||
}
|
||||
|
||||
PECallFunction::PECallFunction(perm_string n, const list<PExpr*>&parms)
|
||||
: path_(pn_from_ps(n)), parms_(parms.size())
|
||||
: package_(0), path_(pn_from_ps(n)), parms_(parms.size())
|
||||
{
|
||||
int tmp_idx = 0;
|
||||
assert(parms_.size() == parms.size());
|
||||
@@ -305,16 +368,21 @@ const verireal& PEFNumber::value() const
|
||||
}
|
||||
|
||||
PEIdent::PEIdent(const pform_name_t&that)
|
||||
: path_(that), no_implicit_sig_(false)
|
||||
: package_(0), path_(that), no_implicit_sig_(false)
|
||||
{
|
||||
}
|
||||
|
||||
PEIdent::PEIdent(perm_string s, bool no_implicit_sig)
|
||||
: no_implicit_sig_(no_implicit_sig)
|
||||
: package_(0), no_implicit_sig_(no_implicit_sig)
|
||||
{
|
||||
path_.push_back(name_component_t(s));
|
||||
}
|
||||
|
||||
PEIdent::PEIdent(PPackage*pkg, const pform_name_t&that)
|
||||
: package_(pkg), path_(that), no_implicit_sig_(true)
|
||||
{
|
||||
}
|
||||
|
||||
PEIdent::~PEIdent()
|
||||
{
|
||||
}
|
||||
@@ -379,12 +447,12 @@ bool PEIdent::has_aa_term(Design*des, NetScope*scope) const
|
||||
return false;
|
||||
}
|
||||
|
||||
PENew::PENew(PExpr*size_expr)
|
||||
: size_(size_expr)
|
||||
PENewArray::PENewArray(PExpr*size_expr, PExpr*init_expr)
|
||||
: size_(size_expr), init_(init_expr)
|
||||
{
|
||||
}
|
||||
|
||||
PENew::~PENew()
|
||||
PENewArray::~PENewArray()
|
||||
{
|
||||
delete size_;
|
||||
}
|
||||
@@ -393,10 +461,29 @@ PENewClass::PENewClass(void)
|
||||
{
|
||||
}
|
||||
|
||||
PENewClass::PENewClass(const list<PExpr*>&p)
|
||||
: parms_(p.size())
|
||||
{
|
||||
size_t tmp_idx = 0;
|
||||
for (list<PExpr*>::const_iterator cur = p.begin()
|
||||
; cur != p.end() ; ++ cur) {
|
||||
parms_[tmp_idx++] = *cur;
|
||||
}
|
||||
}
|
||||
|
||||
PENewClass::~PENewClass()
|
||||
{
|
||||
}
|
||||
|
||||
PENewCopy::PENewCopy(PExpr*src)
|
||||
: src_(src)
|
||||
{
|
||||
}
|
||||
|
||||
PENewCopy::~PENewCopy()
|
||||
{
|
||||
}
|
||||
|
||||
PENumber::PENumber(verinum*vp)
|
||||
: value_(vp)
|
||||
{
|
||||
@@ -462,6 +549,15 @@ bool PETernary::has_aa_term(Design*des, NetScope*scope) const
|
||||
|| fal_->has_aa_term(des, scope);
|
||||
}
|
||||
|
||||
PETypename::PETypename(data_type_t*dt)
|
||||
: data_type_(dt)
|
||||
{
|
||||
}
|
||||
|
||||
PETypename::~PETypename()
|
||||
{
|
||||
}
|
||||
|
||||
PEUnary::PEUnary(char op, PExpr*ex)
|
||||
: op_(op), expr_(ex)
|
||||
{
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
#ifndef __PExpr_H
|
||||
#define __PExpr_H
|
||||
#ifndef IVL_PExpr_H
|
||||
#define IVL_PExpr_H
|
||||
/*
|
||||
* Copyright (c) 1998-2011 Stephen Williams <[email protected]>
|
||||
* Copyright (c) 1998-2014 Stephen Williams <[email protected]>
|
||||
* Copyright CERN 2013 / 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
|
||||
@@ -33,6 +34,7 @@ class LexicalScope;
|
||||
class NetNet;
|
||||
class NetExpr;
|
||||
class NetScope;
|
||||
class PPackage;
|
||||
|
||||
/*
|
||||
* The PExpr class hierarchy supports the description of
|
||||
@@ -43,14 +45,18 @@ class NetScope;
|
||||
class PExpr : public LineInfo {
|
||||
|
||||
public:
|
||||
enum width_mode_t { SIZED, EXPAND, LOSSLESS, UNSIZED };
|
||||
// Mode values used by test_width() (see below for description).
|
||||
enum width_mode_t { SIZED, UNSIZED, EXPAND, LOSSLESS, UPSIZE };
|
||||
|
||||
// Flag values that can be passed to elaborate_expr.
|
||||
// Flag values that can be passed to elaborate_expr().
|
||||
static const unsigned NO_FLAGS = 0x0;
|
||||
static const unsigned NEED_CONST = 0x1;
|
||||
static const unsigned SYS_TASK_ARG = 0x2;
|
||||
static const unsigned ANNOTATABLE = 0x4;
|
||||
|
||||
// Convert width mode to human-readable form.
|
||||
static const char*width_mode_name(width_mode_t mode);
|
||||
|
||||
PExpr();
|
||||
virtual ~PExpr();
|
||||
|
||||
@@ -77,33 +83,42 @@ class PExpr : public LineInfo {
|
||||
// without changing the result. This allows the expression width to
|
||||
// be pruned when not all bits of the result are used.
|
||||
//
|
||||
// Normally mode should be initialised to SIZED before starting to
|
||||
// Normally mode should be initialized to SIZED before starting to
|
||||
// test the width of an expression. In SIZED mode the expression
|
||||
// width will be calculated strictly according to the IEEE standard
|
||||
// rules for expression width.
|
||||
// If the expression contains an unsized literal, mode will be
|
||||
// changed to LOSSLESS. In LOSSLESS mode the expression width will
|
||||
// be calculated as the minimum width necessary to avoid arithmetic
|
||||
// overflow or underflow.
|
||||
// If the expression both contains an unsized literal and contains
|
||||
// an operation that coerces a vector operand to a different type
|
||||
// (signed <-> unsigned), mode is changed to UNSIZED. UNSIZED mode
|
||||
// is the same as LOSSLESS, except that the final expression width
|
||||
// will be forced to be at least integer_width. This is necessary
|
||||
// to ensure compatibility with the IEEE standard, which requires
|
||||
// unsized literals to be treated as having the same width as an
|
||||
// integer. The lossless width calculation is inadequate in this
|
||||
// case because coercing an operand to a different type means that
|
||||
// the expression no longer obeys the normal rules of arithmetic.
|
||||
//
|
||||
// If mode is initialised to EXPAND instead of SIZED, the expression
|
||||
// If the expression is found to contain an unsized literal number
|
||||
// and gn_strict_expr_width_flag is set, mode will be changed to
|
||||
// UNSIZED. In UNSIZED mode the expression width will be calculated
|
||||
// exactly as in SIZED mode - the change in mode simply flags that
|
||||
// the expression contains an unsized numbers.
|
||||
//
|
||||
// If the expression is found to contain an unsized literal number
|
||||
// and gn_strict_expr_width_flag is not set, mode will be changed
|
||||
// to LOSSLESS. In LOSSLESS mode the expression width will be
|
||||
// calculated as the minimum width necessary to avoid arithmetic
|
||||
// overflow or underflow.
|
||||
//
|
||||
// Once in LOSSLESS mode, if the expression is found to contain
|
||||
// an operation that coerces a vector operand to a different type
|
||||
// (signed <-> unsigned), mode will be changed to UPSIZE. UPSIZE
|
||||
// mode is the same as LOSSLESS, except that the final expression
|
||||
// width will be forced to be at least integer_width. This is
|
||||
// necessary to ensure compatibility with the IEEE standard, which
|
||||
// requires unsized numbers to be treated as having the same width
|
||||
// as an integer. The lossless width calculation is inadequate in
|
||||
// this case because coercing an operand to a different type means
|
||||
// that the expression no longer obeys the normal rules of arithmetic.
|
||||
//
|
||||
// If mode is initialized to EXPAND instead of SIZED, the expression
|
||||
// width will be calculated as the minimum width necessary to avoid
|
||||
// arithmetic overflow or underflow, even if it contains no unsized
|
||||
// literals. mode will be changed LOSSLESS or UNSIZED as described
|
||||
// literals. mode will be changed LOSSLESS or UPSIZE as described
|
||||
// above. This supports a non-standard mode of expression width
|
||||
// calculation.
|
||||
//
|
||||
// When the final value of mode is UNSIZED, the width returned by
|
||||
// When the final value of mode is UPSIZE, the width returned by
|
||||
// this method is the calculated lossless width, but the width
|
||||
// returned by a subsequent call to the expr_width method will be
|
||||
// the final expression width.
|
||||
@@ -149,11 +164,12 @@ class PExpr : public LineInfo {
|
||||
|
||||
// Expressions that can be in the l-value of procedural
|
||||
// assignments can be elaborated with this method. If the
|
||||
// is_force flag is true, then the set of valid l-value types
|
||||
// is slightly modified to accommodate the Verilog force
|
||||
// statement
|
||||
// is_cassign or is_force flags are true, then the set of
|
||||
// valid l-value types is slightly modified to accommodate
|
||||
// the Verilog procedural continuous assignment statements.
|
||||
virtual NetAssign_* elaborate_lval(Design*des,
|
||||
NetScope*scope,
|
||||
bool is_cassign,
|
||||
bool is_force) const;
|
||||
|
||||
// This attempts to evaluate a constant expression, and return
|
||||
@@ -188,6 +204,29 @@ class PExpr : public LineInfo {
|
||||
|
||||
ostream& operator << (ostream&, const PExpr&);
|
||||
|
||||
class PEAssignPattern : public PExpr {
|
||||
public:
|
||||
explicit PEAssignPattern();
|
||||
explicit PEAssignPattern(const std::list<PExpr*>&p);
|
||||
~PEAssignPattern();
|
||||
|
||||
void dump(std::ostream&) const;
|
||||
|
||||
virtual unsigned test_width(Design*des, NetScope*scope, width_mode_t&mode);
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
|
||||
ivl_type_t type, unsigned flags) const;
|
||||
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
|
||||
unsigned expr_wid,
|
||||
unsigned flags) const;
|
||||
private:
|
||||
NetExpr* elaborate_expr_darray_(Design*des, NetScope*scope,
|
||||
ivl_type_t type, unsigned flags) const;
|
||||
|
||||
private:
|
||||
std::vector<PExpr*>parms_;
|
||||
};
|
||||
|
||||
class PEConcat : public PExpr {
|
||||
|
||||
public:
|
||||
@@ -206,11 +245,16 @@ class PEConcat : public PExpr {
|
||||
|
||||
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope) const;
|
||||
virtual NetNet* elaborate_bi_net(Design*des, NetScope*scope) const;
|
||||
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
|
||||
ivl_type_t type, unsigned flags) const;
|
||||
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
|
||||
unsigned expr_wid,
|
||||
unsigned flags) const;
|
||||
virtual NetAssign_* elaborate_lval(Design*des,
|
||||
NetScope*scope,
|
||||
bool is_cassign,
|
||||
bool is_force) const;
|
||||
virtual bool is_collapsible_net(Design*des, NetScope*scope) const;
|
||||
private:
|
||||
@@ -272,6 +316,8 @@ class PEFNumber : public PExpr {
|
||||
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
width_mode_t&mode);
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
|
||||
ivl_type_t type, unsigned flags) const;
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
|
||||
unsigned expr_wid,
|
||||
unsigned flags) const;
|
||||
@@ -286,6 +332,7 @@ class PEIdent : public PExpr {
|
||||
|
||||
public:
|
||||
explicit PEIdent(perm_string, bool no_implicit_sig=false);
|
||||
explicit PEIdent(PPackage*pkg, const pform_name_t&name);
|
||||
explicit PEIdent(const pform_name_t&);
|
||||
~PEIdent();
|
||||
|
||||
@@ -310,6 +357,7 @@ class PEIdent : public PExpr {
|
||||
// Identifiers are also allowed as procedural assignment l-values.
|
||||
virtual NetAssign_* elaborate_lval(Design*des,
|
||||
NetScope*scope,
|
||||
bool is_cassign,
|
||||
bool is_force) const;
|
||||
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
|
||||
@@ -322,6 +370,11 @@ class PEIdent : public PExpr {
|
||||
// only applies to Ident expressions.
|
||||
NetNet* elaborate_subport(Design*des, NetScope*sc) const;
|
||||
|
||||
// Elaborate the identifier allowing for unpacked arrays. This
|
||||
// method only applies to Ident expressions because only Ident
|
||||
// expressions can can be unpacked arrays.
|
||||
NetNet* elaborate_unpacked_net(Design*des, NetScope*sc) const;
|
||||
|
||||
verinum* eval_const(Design*des, NetScope*sc) const;
|
||||
|
||||
virtual bool is_collapsible_net(Design*des, NetScope*scope) const;
|
||||
@@ -329,6 +382,7 @@ class PEIdent : public PExpr {
|
||||
const pform_name_t& path() const { return path_; }
|
||||
|
||||
private:
|
||||
PPackage*package_;
|
||||
pform_name_t path_;
|
||||
bool no_implicit_sig_;
|
||||
|
||||
@@ -368,14 +422,18 @@ class PEIdent : public PExpr {
|
||||
std::list<long>&prefix_indices) const;
|
||||
|
||||
private:
|
||||
NetAssign_*elaborate_lval_net_word_(Design*, NetScope*, NetNet*) const;
|
||||
bool elaborate_lval_net_bit_(Design*, NetScope*, NetAssign_*) const;
|
||||
NetAssign_*elaborate_lval_method_class_member_(Design*, NetScope*) const;
|
||||
NetAssign_*elaborate_lval_net_word_(Design*, NetScope*, NetNet*,
|
||||
bool need_const_idx) const;
|
||||
bool elaborate_lval_net_bit_(Design*, NetScope*, NetAssign_*,
|
||||
bool need_const_idx) const;
|
||||
bool elaborate_lval_net_part_(Design*, NetScope*, NetAssign_*) const;
|
||||
bool elaborate_lval_net_idx_(Design*, NetScope*, NetAssign_*,
|
||||
index_component_t::ctype_t) const;
|
||||
bool elaborate_lval_net_class_member_(Design*, NetScope*,
|
||||
NetAssign_*,
|
||||
const perm_string&) const;
|
||||
index_component_t::ctype_t,
|
||||
bool need_const_idx) const;
|
||||
NetAssign_*elaborate_lval_net_class_member_(Design*, NetScope*,
|
||||
NetNet*,
|
||||
const perm_string&) const;
|
||||
bool elaborate_lval_net_packed_member_(Design*, NetScope*,
|
||||
NetAssign_*,
|
||||
const perm_string&) const;
|
||||
@@ -391,6 +449,13 @@ class PEIdent : public PExpr {
|
||||
const NetExpr*par_lsb,
|
||||
unsigned expr_wid,
|
||||
unsigned flags) const;
|
||||
NetExpr*elaborate_expr_param_bit_(Design*des,
|
||||
NetScope*scope,
|
||||
const NetExpr*par,
|
||||
NetScope*found_in,
|
||||
const NetExpr*par_msb,
|
||||
const NetExpr*par_lsb,
|
||||
bool need_const) const;
|
||||
NetExpr*elaborate_expr_param_part_(Design*des,
|
||||
NetScope*scope,
|
||||
const NetExpr*par,
|
||||
@@ -444,20 +509,38 @@ class PEIdent : public PExpr {
|
||||
NetESignal*net,
|
||||
NetScope*found,
|
||||
bool need_const) const;
|
||||
NetExpr*elaborate_expr_net_bit_last_(Design*des,
|
||||
NetScope*scope,
|
||||
NetESignal*net,
|
||||
NetScope*found,
|
||||
bool need_const) const;
|
||||
|
||||
NetExpr*elaborate_expr_class_member_(Design*des,
|
||||
NetScope*scope,
|
||||
unsigned expr_wid,
|
||||
unsigned flags) const;
|
||||
|
||||
unsigned test_width_method_(Design*des, NetScope*scope, width_mode_t&mode);
|
||||
NetExpr*elaborate_expr_method_(Design*des,
|
||||
NetScope*scope,
|
||||
unsigned expr_wid,
|
||||
unsigned flags) const;
|
||||
|
||||
private:
|
||||
NetNet* elaborate_lnet_common_(Design*des, NetScope*scope,
|
||||
bool bidirectional_flag) const;
|
||||
|
||||
NetAssign_*scan_lname_for_nested_members_(Design*des, NetScope*scope,
|
||||
const pform_name_t&path) const;
|
||||
bool eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
|
||||
long&midx, long&lidx) const;
|
||||
};
|
||||
|
||||
class PENew : public PExpr {
|
||||
class PENewArray : public PExpr {
|
||||
|
||||
public:
|
||||
explicit PENew (PExpr*s);
|
||||
~PENew();
|
||||
explicit PENewArray (PExpr*s, PExpr*i);
|
||||
~PENewArray();
|
||||
|
||||
virtual void dump(ostream&) const;
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
@@ -470,13 +553,19 @@ class PENew : public PExpr {
|
||||
|
||||
private:
|
||||
PExpr*size_;
|
||||
PExpr*init_;
|
||||
};
|
||||
|
||||
class PENewClass : public PExpr {
|
||||
|
||||
public:
|
||||
// New without (or with default) constructor
|
||||
explicit PENewClass ();
|
||||
// New with constructor arguments
|
||||
explicit PENewClass (const std::list<PExpr*>&p);
|
||||
|
||||
~PENewClass();
|
||||
|
||||
virtual void dump(ostream&) const;
|
||||
// Class objects don't have a useful width, but the expression
|
||||
// is IVL_VT_CLASS.
|
||||
@@ -484,11 +573,37 @@ class PENewClass : public PExpr {
|
||||
width_mode_t&mode);
|
||||
// Note that class (new) expressions only appear in context
|
||||
// that uses this form of the elaborate_expr method. In fact,
|
||||
// the type argument is going to be a netclas_t object.
|
||||
// the type argument is going to be a netclass_t object.
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
|
||||
ivl_type_t type, unsigned flags) const;
|
||||
|
||||
private:
|
||||
NetExpr* elaborate_expr_constructor_(Design*des, NetScope*scope,
|
||||
const netclass_t*ctype,
|
||||
NetExpr*obj, unsigned flags) const;
|
||||
|
||||
private:
|
||||
std::vector<PExpr*>parms_;
|
||||
};
|
||||
|
||||
class PENewCopy : public PExpr {
|
||||
public:
|
||||
explicit PENewCopy(PExpr*src);
|
||||
~PENewCopy();
|
||||
|
||||
virtual void dump(ostream&) const;
|
||||
// Class objects don't have a useful width, but the expression
|
||||
// is IVL_VT_CLASS.
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
width_mode_t&mode);
|
||||
// Note that class (new) expressions only appear in context
|
||||
// that uses this form of the elaborate_expr method. In fact,
|
||||
// the type argument is going to be a netclass_t object.
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
|
||||
ivl_type_t type, unsigned flags) const;
|
||||
|
||||
private:
|
||||
PExpr*src_;
|
||||
};
|
||||
|
||||
class PENull : public PExpr {
|
||||
@@ -518,10 +633,13 @@ class PENumber : public PExpr {
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
width_mode_t&mode);
|
||||
|
||||
virtual NetExpr *elaborate_expr(Design*des, NetScope*scope,
|
||||
ivl_type_t type, unsigned flags) const;
|
||||
virtual NetEConst*elaborate_expr(Design*des, NetScope*,
|
||||
unsigned expr_wid, unsigned) const;
|
||||
virtual NetAssign_* elaborate_lval(Design*des,
|
||||
NetScope*scope,
|
||||
bool is_cassign,
|
||||
bool is_force) const;
|
||||
|
||||
virtual verinum* eval_const(Design*des, NetScope*sc) const;
|
||||
@@ -551,6 +669,9 @@ class PEString : public PExpr {
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
width_mode_t&mode);
|
||||
|
||||
virtual NetEConst*elaborate_expr(Design*des, NetScope*scope,
|
||||
ivl_type_t type, unsigned flags) const;
|
||||
|
||||
virtual NetEConst*elaborate_expr(Design*des, NetScope*,
|
||||
unsigned expr_wid, unsigned) const;
|
||||
verinum* eval_const(Design*, NetScope*) const;
|
||||
@@ -559,6 +680,23 @@ class PEString : public PExpr {
|
||||
char*text_;
|
||||
};
|
||||
|
||||
class PETypename : public PExpr {
|
||||
public:
|
||||
explicit PETypename(data_type_t*data_type);
|
||||
~PETypename();
|
||||
|
||||
virtual void dump(ostream&) const;
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
width_mode_t&mode);
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
|
||||
ivl_type_t type, unsigned flags) const;
|
||||
|
||||
inline data_type_t* get_type() const { return data_type_; }
|
||||
|
||||
private:
|
||||
data_type_t*data_type_;
|
||||
};
|
||||
|
||||
class PEUnary : public PExpr {
|
||||
|
||||
public:
|
||||
@@ -739,7 +877,7 @@ class PETernary : public PExpr {
|
||||
private:
|
||||
NetExpr* elab_and_eval_alternative_(Design*des, NetScope*scope,
|
||||
PExpr*expr, unsigned expr_wid,
|
||||
unsigned flags) const;
|
||||
unsigned flags, bool short_cct) const;
|
||||
|
||||
private:
|
||||
PExpr*expr_;
|
||||
@@ -755,11 +893,18 @@ class PETernary : public PExpr {
|
||||
class PECallFunction : public PExpr {
|
||||
public:
|
||||
explicit PECallFunction(const pform_name_t&n, const vector<PExpr *> &parms);
|
||||
// Call function defined in package.
|
||||
explicit PECallFunction(PPackage*pkg, perm_string n, const std::vector<PExpr *> &parms);
|
||||
explicit PECallFunction(PPackage*pkg, perm_string n, const std::list<PExpr *> &parms);
|
||||
|
||||
// Used to convert a user function called as a task
|
||||
explicit PECallFunction(PPackage*pkg, const pform_name_t&n, const std::vector<PExpr *> &parms);
|
||||
|
||||
// Call of system function (name is not hierarchical)
|
||||
explicit PECallFunction(perm_string n, const vector<PExpr *> &parms);
|
||||
explicit PECallFunction(perm_string n);
|
||||
|
||||
// svector versions. Should be removed!
|
||||
// std::list versions. Should be removed!
|
||||
explicit PECallFunction(const pform_name_t&n, const list<PExpr *> &parms);
|
||||
explicit PECallFunction(perm_string n, const list<PExpr *> &parms);
|
||||
|
||||
@@ -779,16 +924,20 @@ class PECallFunction : public PExpr {
|
||||
width_mode_t&mode);
|
||||
|
||||
private:
|
||||
PPackage*package_;
|
||||
pform_name_t path_;
|
||||
vector<PExpr *> parms_;
|
||||
std::vector<PExpr *> parms_;
|
||||
|
||||
bool check_call_matches_definition_(Design*des, NetScope*dscope) const;
|
||||
|
||||
|
||||
NetExpr* cast_to_width_(NetExpr*expr, unsigned wid) const;
|
||||
|
||||
NetExpr*elaborate_expr_pkg_(Design*des, NetScope*scope,
|
||||
unsigned expr_wid, unsigned flags)const;
|
||||
NetExpr*elaborate_expr_method_(Design*des, NetScope*scope,
|
||||
unsigned expr_wid) const;
|
||||
unsigned expr_wid,
|
||||
bool add_this_flag = false) const;
|
||||
#if 0
|
||||
NetExpr*elaborate_expr_string_method_(Design*des, NetScope*scope) const;
|
||||
NetExpr*elaborate_expr_enum_method_(Design*des, NetScope*scope,
|
||||
@@ -804,6 +953,14 @@ class PECallFunction : public PExpr {
|
||||
width_mode_t&mode);
|
||||
unsigned test_width_method_(Design*des, NetScope*scope,
|
||||
width_mode_t&mode);
|
||||
|
||||
NetExpr*elaborate_base_(Design*des, NetScope*scope, NetScope*dscope,
|
||||
unsigned expr_wid, unsigned flags) const;
|
||||
|
||||
unsigned elaborate_arguments_(Design*des, NetScope*scope,
|
||||
NetFuncDef*def, bool need_const,
|
||||
std::vector<NetExpr*>&parms,
|
||||
unsigned parm_off) const;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -829,6 +986,28 @@ class PECastSize : public PExpr {
|
||||
PExpr* base_;
|
||||
};
|
||||
|
||||
/*
|
||||
* Support the SystemVerilog cast to a different type.
|
||||
*/
|
||||
class PECastType : public PExpr {
|
||||
|
||||
public:
|
||||
explicit PECastType(data_type_t*target, PExpr*base);
|
||||
~PECastType();
|
||||
|
||||
void dump(ostream &out) const;
|
||||
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
|
||||
unsigned expr_wid, unsigned flags) const;
|
||||
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
width_mode_t&mode);
|
||||
|
||||
private:
|
||||
data_type_t* target_;
|
||||
PExpr* base_;
|
||||
};
|
||||
|
||||
/*
|
||||
* This class is used for error recovery. All methods do nothing and return
|
||||
* null or default values.
|
||||
@@ -844,4 +1023,4 @@ class PEVoid : public PExpr {
|
||||
unsigned flags) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif /* IVL_PExpr_H */
|
||||
|
||||
+46
-12
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2008,2010 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1999-2013 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,26 +18,22 @@
|
||||
*/
|
||||
|
||||
# include "config.h"
|
||||
|
||||
#include "PTask.h"
|
||||
# include "PTask.h"
|
||||
# include "Statement.h"
|
||||
# include <cassert>
|
||||
# include "ivl_assert.h"
|
||||
|
||||
PFunction::PFunction(perm_string name, LexicalScope*parent, bool is_auto__)
|
||||
: PScope(name, parent), ports_(0), statement_(0)
|
||||
: PTaskFunc(name, parent), statement_(0)
|
||||
{
|
||||
is_auto_ = is_auto__;
|
||||
return_type_.type = PTF_NONE;
|
||||
return_type_ = 0;
|
||||
}
|
||||
|
||||
PFunction::~PFunction()
|
||||
{
|
||||
}
|
||||
|
||||
void PFunction::set_ports(svector<PWire *>*p)
|
||||
{
|
||||
assert(ports_ == 0);
|
||||
ports_ = p;
|
||||
}
|
||||
|
||||
void PFunction::set_statement(Statement*s)
|
||||
{
|
||||
assert(s != 0);
|
||||
@@ -45,7 +41,45 @@ void PFunction::set_statement(Statement*s)
|
||||
statement_ = s;
|
||||
}
|
||||
|
||||
void PFunction::set_return(PTaskFuncArg t)
|
||||
void PFunction::push_statement_front(Statement*stmt)
|
||||
{
|
||||
// This can only happen after the statement is initially set.
|
||||
ivl_assert(*this, statement_);
|
||||
|
||||
// Get the PBlock of the statement. If it is not a PBlock,
|
||||
// then create one to wrap the existing statement and the new
|
||||
// statement that we're pushing.
|
||||
PBlock*blk = dynamic_cast<PBlock*> (statement_);
|
||||
if (blk == 0) {
|
||||
PBlock*tmp = new PBlock(PBlock::BL_SEQ);
|
||||
tmp->set_line(*this);
|
||||
vector<Statement*>tmp_list(1);
|
||||
tmp_list[0] = statement_;
|
||||
tmp->set_statement(tmp_list);
|
||||
|
||||
statement_ = tmp;
|
||||
blk = tmp;
|
||||
}
|
||||
|
||||
// Now do the push.
|
||||
blk->push_statement_front(stmt);
|
||||
}
|
||||
|
||||
void PFunction::set_return(data_type_t*t)
|
||||
{
|
||||
return_type_ = t;
|
||||
}
|
||||
|
||||
PChainConstructor* PFunction::extract_chain_constructor()
|
||||
{
|
||||
PChainConstructor*res = 0;
|
||||
|
||||
if ((res = dynamic_cast<PChainConstructor*> (statement_))) {
|
||||
statement_ = 0;
|
||||
|
||||
} else if (PBlock*blk = dynamic_cast<PBlock*>(statement_)) {
|
||||
res = blk->extract_chain_constructor();
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2010 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1999-2013 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
|
||||
@@ -260,18 +260,16 @@ const char* PGBuiltin::gate_name() const
|
||||
}
|
||||
|
||||
PGModule::PGModule(perm_string type, perm_string name, list<PExpr*>*pins)
|
||||
: PGate(name, pins), bound_type_(0), overrides_(0), pins_(0),
|
||||
: PGate(name, pins), bound_type_(0), type_(type), overrides_(0), pins_(0),
|
||||
npins_(0), parms_(0), nparms_(0), msb_(0), lsb_(0)
|
||||
{
|
||||
type_ = type;
|
||||
}
|
||||
|
||||
PGModule::PGModule(perm_string type, perm_string name,
|
||||
named<PExpr*>*pins, unsigned npins)
|
||||
: PGate(name, 0), bound_type_(0), overrides_(0), pins_(pins),
|
||||
: PGate(name, 0), bound_type_(0), type_(type), overrides_(0), pins_(pins),
|
||||
npins_(npins), parms_(0), nparms_(0), msb_(0), lsb_(0)
|
||||
{
|
||||
type_ = type;
|
||||
}
|
||||
|
||||
PGModule::PGModule(Module*type, perm_string name)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __PGate_H
|
||||
#define __PGate_H
|
||||
#ifndef IVL_PGate_H
|
||||
#define IVL_PGate_H
|
||||
/*
|
||||
* Copyright (c) 1998-2011 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2014 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
|
||||
@@ -124,6 +124,7 @@ class PGAssign : public PGate {
|
||||
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
|
||||
|
||||
private:
|
||||
void elaborate_unpacked_array_(Design*des, NetScope*scope, NetNet*lval) const;
|
||||
};
|
||||
|
||||
|
||||
@@ -259,4 +260,4 @@ class PGModule : public PGate {
|
||||
NetNet::PortType dir, bool as_signed) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif /* IVL_PGate_H */
|
||||
|
||||
+4
-4
@@ -1,7 +1,7 @@
|
||||
#ifndef __PGenerate_H
|
||||
#define __PGenerate_H
|
||||
#ifndef IVL_PGenerate_H
|
||||
#define IVL_PGenerate_H
|
||||
/*
|
||||
* Copyright (c) 2006-2010,2012 Stephen Williams ([email protected])
|
||||
* Copyright (c) 2006-2014 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
|
||||
@@ -139,4 +139,4 @@ class PGenerate : public LineInfo, public LexicalScope {
|
||||
|
||||
extern std::ostream& operator << (std::ostream&, PGenerate::scheme_t);
|
||||
|
||||
#endif
|
||||
#endif /* IVL_PGenerate_H */
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2012 Picture Elements, Inc.
|
||||
* Stephen Williams ([email protected])
|
||||
* Copyright (c) 2012 Stephen Williams ([email protected])
|
||||
* Copyright CERN 2013 / 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
|
||||
|
||||
+11
-4
@@ -1,7 +1,8 @@
|
||||
#ifndef __PPackage_H
|
||||
#define __PPackage_H
|
||||
#ifndef IVL_PPackage_H
|
||||
#define IVL_PPackage_H
|
||||
/*
|
||||
* Copyright (c) 2012 Stephen Williams ([email protected])
|
||||
* Copyright (c) 2012-2014 Stephen Williams ([email protected])
|
||||
* Copyright CERN 2013 / 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
|
||||
@@ -22,6 +23,7 @@
|
||||
# include "PScope.h"
|
||||
# include "LineInfo.h"
|
||||
# include "StringHeap.h"
|
||||
# include <iostream>
|
||||
|
||||
/*
|
||||
* SystemVerilog supports class declarations with their own lexical
|
||||
@@ -35,6 +37,11 @@ class PPackage : public PScopeExtra, public LineInfo {
|
||||
explicit PPackage (perm_string name, LexicalScope*parent);
|
||||
~PPackage();
|
||||
|
||||
bool elaborate_scope(Design*des, NetScope*scope);
|
||||
bool elaborate_sig(Design*des, NetScope*scope) const;
|
||||
bool elaborate(Design*des, NetScope*scope) const;
|
||||
|
||||
void pform_dump(std::ostream&out) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif /* IVL_PPackage_H */
|
||||
|
||||
@@ -31,6 +31,9 @@ PScope::PScope(perm_string n)
|
||||
|
||||
PScope::~PScope()
|
||||
{
|
||||
for(map<perm_string, data_type_t*>::iterator it = typedefs.begin();
|
||||
it != typedefs.end(); ++it)
|
||||
delete it->second;
|
||||
}
|
||||
|
||||
PWire* LexicalScope::wires_find(perm_string name)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __PScope_H
|
||||
#define __PScope_H
|
||||
#ifndef IVL_PScope_H
|
||||
#define IVL_PScope_H
|
||||
/*
|
||||
* Copyright (c) 2008,2010 Stephen Williams ([email protected])
|
||||
* Copyright (c) 2008-2014 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -24,10 +24,13 @@
|
||||
# include "pform_types.h"
|
||||
# include "ivl_target.h"
|
||||
# include <map>
|
||||
# include <set>
|
||||
# include <vector>
|
||||
|
||||
class PEvent;
|
||||
class PExpr;
|
||||
class PFunction;
|
||||
class PPackage;
|
||||
class AProcess;
|
||||
class PProcess;
|
||||
class PClass;
|
||||
@@ -92,6 +95,10 @@ class LexicalScope {
|
||||
// Named events in the scope.
|
||||
map<perm_string,PEvent*>events;
|
||||
|
||||
// Symbols that are imported. Bind the imported name to the
|
||||
// package from which the name is imported.
|
||||
std::map<perm_string,PPackage*>imports;
|
||||
|
||||
// Nets and variables (wires) in the scope
|
||||
map<perm_string,PWire*>wires;
|
||||
PWire* wires_find(perm_string name);
|
||||
@@ -106,7 +113,7 @@ class LexicalScope {
|
||||
list<AProcess*> analog_behaviors;
|
||||
|
||||
// Enumeration sets.
|
||||
list<enum_type_t*> enum_sets;
|
||||
std::set<enum_type_t*> enum_sets;
|
||||
|
||||
LexicalScope* parent_scope() const { return parent_; }
|
||||
|
||||
@@ -170,9 +177,14 @@ class PScopeExtra : public PScope {
|
||||
std::map<perm_string,PFunction*> funcs;
|
||||
/* class definitions within this module. */
|
||||
std::map<perm_string,PClass*> classes;
|
||||
/* This is the lexical order of the classes, and is used by
|
||||
elaboration to choose an elaboration order. */
|
||||
std::vector<PClass*> classes_lexical;
|
||||
|
||||
protected:
|
||||
void dump_classes_(ostream&out, unsigned indent) const;
|
||||
void dump_tasks_(ostream&out, unsigned indent) const;
|
||||
void dump_funcs_(ostream&out, unsigned indent) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif /* IVL_PScope_H */
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __PSpec_H
|
||||
#define __PSpec_H
|
||||
#ifndef IVL_PSpec_H
|
||||
#define IVL_PSpec_H
|
||||
/*
|
||||
* Copyright (c) 2006-2011 Stephen Williams <[email protected]>
|
||||
* Copyright (c) 2006-2014 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
|
||||
@@ -84,4 +84,4 @@ class PSpecPath : public LineInfo {
|
||||
std::vector<class PExpr*>delays;
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif /* IVL_PSpec_H */
|
||||
|
||||
@@ -18,11 +18,43 @@
|
||||
*/
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# include "PTask.h"
|
||||
# include <cassert>
|
||||
|
||||
PTaskFunc::PTaskFunc(perm_string n, LexicalScope*p)
|
||||
: PScope(n,p), this_type_(0), ports_(0)
|
||||
{
|
||||
}
|
||||
|
||||
PTaskFunc::~PTaskFunc()
|
||||
{
|
||||
}
|
||||
|
||||
void PTaskFunc::set_ports(vector<pform_tf_port_t>*p)
|
||||
{
|
||||
assert(ports_ == 0);
|
||||
ports_ = p;
|
||||
}
|
||||
|
||||
void PTaskFunc::set_this(class_type_t*type, PWire*this_wire)
|
||||
{
|
||||
assert(this_type_ == 0);
|
||||
this_type_ = type;
|
||||
|
||||
// Push a synthethis argument that is the "this" value.
|
||||
if (ports_==0)
|
||||
ports_ = new vector<pform_tf_port_t>;
|
||||
|
||||
size_t use_size = ports_->size();
|
||||
ports_->resize(use_size + 1);
|
||||
for (size_t idx = use_size ; idx > 0 ; idx -= 1)
|
||||
ports_->at(idx) = ports_->at(idx-1);
|
||||
|
||||
ports_->at(0) = pform_tf_port_t(this_wire);
|
||||
}
|
||||
|
||||
PTask::PTask(perm_string name, LexicalScope*parent, bool is_auto__)
|
||||
: PScope(name, parent), ports_(0), statement_(0)
|
||||
: PTaskFunc(name, parent), statement_(0)
|
||||
{
|
||||
is_auto_ = is_auto__;
|
||||
}
|
||||
@@ -31,12 +63,6 @@ PTask::~PTask()
|
||||
{
|
||||
}
|
||||
|
||||
void PTask::set_ports(svector<PWire*>*p)
|
||||
{
|
||||
assert(ports_ == 0);
|
||||
ports_ = p;
|
||||
}
|
||||
|
||||
void PTask::set_statement(Statement*s)
|
||||
{
|
||||
assert(statement_ == 0);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __PTask_H
|
||||
#define __PTask_H
|
||||
#ifndef IVL_PTask_H
|
||||
#define IVL_PTask_H
|
||||
/*
|
||||
* Copyright (c) 1999-2008,2010,2012 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1999-2014 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -21,46 +21,64 @@
|
||||
|
||||
# include "LineInfo.h"
|
||||
# include "PScope.h"
|
||||
# include "svector.h"
|
||||
# include "StringHeap.h"
|
||||
# include <string>
|
||||
# include <vector>
|
||||
# include <list>
|
||||
class Design;
|
||||
class NetExpr;
|
||||
class NetNet;
|
||||
class NetScope;
|
||||
class PChainConstructor;
|
||||
class PWire;
|
||||
class Statement;
|
||||
class PExpr;
|
||||
|
||||
enum PTaskFuncEnum {
|
||||
PTF_NONE,
|
||||
PTF_REG,
|
||||
PTF_REG_S,
|
||||
PTF_INTEGER,
|
||||
PTF_REAL,
|
||||
PTF_REALTIME,
|
||||
PTF_TIME,
|
||||
PTF_ATOM2,
|
||||
PTF_ATOM2_S,
|
||||
PTF_STRING,
|
||||
PTF_VOID
|
||||
};
|
||||
|
||||
struct PTaskFuncArg {
|
||||
PTaskFuncEnum type;
|
||||
std::list<pform_range_t>*range;
|
||||
class PTaskFunc : public PScope, public LineInfo {
|
||||
|
||||
public:
|
||||
PTaskFunc(perm_string name, LexicalScope*parent);
|
||||
~PTaskFunc();
|
||||
|
||||
void set_ports(std::vector<pform_tf_port_t>*p);
|
||||
|
||||
void set_this(class_type_t*use_type, PWire*this_wire);
|
||||
|
||||
// If this task is a method of a class, this returns a pointer
|
||||
// to the class type.
|
||||
inline class_type_t* method_of() const { return this_type_; }
|
||||
|
||||
|
||||
virtual void elaborate_sig(Design*des, NetScope*scope) const =0;
|
||||
virtual void elaborate(Design*des, NetScope*scope) const =0;
|
||||
|
||||
virtual void dump(std::ostream&, unsigned) const =0;
|
||||
|
||||
protected:
|
||||
// Elaborate the ports list. Write into the ports vector the
|
||||
// NetNet pointers for the ports, and write into the pdefs the
|
||||
// default value expressions, if any.
|
||||
void elaborate_sig_ports_(Design*des, NetScope*scope,
|
||||
std::vector<NetNet*>&ports,
|
||||
std::vector<NetExpr*>&pdefs) const;
|
||||
|
||||
void dump_ports_(std::ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
class_type_t*this_type_;
|
||||
std::vector<pform_tf_port_t>*ports_;
|
||||
};
|
||||
|
||||
/*
|
||||
* The PTask holds the parsed definitions of a task.
|
||||
*/
|
||||
class PTask : public PScope, public LineInfo {
|
||||
class PTask : public PTaskFunc {
|
||||
|
||||
public:
|
||||
explicit PTask(perm_string name, LexicalScope*parent, bool is_auto);
|
||||
~PTask();
|
||||
|
||||
void set_ports(svector<PWire *>*p);
|
||||
void set_statement(Statement *s);
|
||||
|
||||
// Tasks introduce scope, to need to be handled during the
|
||||
@@ -80,7 +98,6 @@ class PTask : public PScope, public LineInfo {
|
||||
void dump(ostream&, unsigned) const;
|
||||
|
||||
private:
|
||||
svector<PWire*>*ports_;
|
||||
Statement*statement_;
|
||||
bool is_auto_;
|
||||
|
||||
@@ -96,15 +113,26 @@ class PTask : public PScope, public LineInfo {
|
||||
*
|
||||
* The output value is not elaborated until elaborate_sig.
|
||||
*/
|
||||
class PFunction : public PScope, public LineInfo {
|
||||
class PFunction : public PTaskFunc {
|
||||
|
||||
public:
|
||||
explicit PFunction(perm_string name, LexicalScope*parent, bool is_auto);
|
||||
~PFunction();
|
||||
|
||||
void set_ports(svector<PWire *>*p);
|
||||
void set_statement(Statement *s);
|
||||
void set_return(PTaskFuncArg t);
|
||||
void set_return(data_type_t*t);
|
||||
|
||||
inline Statement* get_statement() { return statement_; }
|
||||
|
||||
// Push this statement to the front of the existing
|
||||
// definition. If the statement is a simple statement, make a
|
||||
// block to contain the statements.
|
||||
void push_statement_front(Statement*stmt);
|
||||
|
||||
// This is only used if this function is a constructor. In
|
||||
// that case, this method looks for a PChainConstructor in the
|
||||
// statement and extracts it if found.
|
||||
PChainConstructor*extract_chain_constructor();
|
||||
|
||||
void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
|
||||
@@ -119,10 +147,9 @@ class PFunction : public PScope, public LineInfo {
|
||||
void dump(ostream&, unsigned) const;
|
||||
|
||||
private:
|
||||
PTaskFuncArg return_type_;
|
||||
svector<PWire *> *ports_;
|
||||
data_type_t* return_type_;
|
||||
Statement *statement_;
|
||||
bool is_auto_;
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif /* IVL_PTask_H */
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __PUdp_H
|
||||
#define __PUdp_H
|
||||
#ifndef IVL_PUdp_H
|
||||
#define IVL_PUdp_H
|
||||
/*
|
||||
* Copyright (c) 1998-2011 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2014 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
|
||||
@@ -76,4 +76,4 @@ class PUdp : public LineInfo {
|
||||
PUdp& operator= (const PUdp&);
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif /* IVL_PUdp_H */
|
||||
|
||||
@@ -120,6 +120,7 @@ bool PWire::set_data_type(ivl_variable_type_t dt)
|
||||
|
||||
assert(data_type_ == IVL_VT_NO_TYPE);
|
||||
data_type_ = dt;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -140,7 +141,14 @@ bool PWire::get_signed() const
|
||||
|
||||
bool PWire::get_isint() const
|
||||
{
|
||||
return isint_;
|
||||
if (isint_)
|
||||
return true;
|
||||
|
||||
if (vector_type_t*tmp = dynamic_cast<vector_type_t*>(set_data_type_)) {
|
||||
return tmp->integer_flag;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PWire::get_scalar() const
|
||||
@@ -257,6 +265,11 @@ void PWire::set_data_type(data_type_t*type)
|
||||
{
|
||||
assert(set_data_type_ == 0);
|
||||
set_data_type_ = type;
|
||||
|
||||
if (vector_type_t*tmp = dynamic_cast<vector_type_t*>(type)) {
|
||||
if (tmp->integer_flag)
|
||||
isint_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
void PWire::set_discipline(ivl_discipline_t d)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __PWire_H
|
||||
#define __PWire_H
|
||||
#ifndef IVL_PWire_H
|
||||
#define IVL_PWire_H
|
||||
/*
|
||||
* Copyright (c) 1998-2009,2012 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2014 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
|
||||
@@ -129,4 +129,4 @@ class PWire : public LineInfo {
|
||||
PWire& operator= (const PWire&);
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif /* IVL_PWire_H */
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ 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>.
|
||||
home page at <http://iverilog.icarus.com/>.
|
||||
|
||||
Icarus Verilog is not aimed at being a simulator in the traditional
|
||||
sense, but a compiler that generates code employed by back-end
|
||||
|
||||
+93
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998-2008,2010,2012 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2013 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
# include "Statement.h"
|
||||
# include "PExpr.h"
|
||||
# include "ivl_assert.h"
|
||||
|
||||
Statement::~Statement()
|
||||
{
|
||||
@@ -114,6 +115,21 @@ PBlock::~PBlock()
|
||||
delete list_[idx];
|
||||
}
|
||||
|
||||
PChainConstructor* PBlock::extract_chain_constructor()
|
||||
{
|
||||
if (list_.empty())
|
||||
return 0;
|
||||
|
||||
if (PChainConstructor*res = dynamic_cast<PChainConstructor*> (list_[0])) {
|
||||
for (size_t idx = 0 ; idx < list_.size()-1 ; idx += 1)
|
||||
list_[idx] = list_[idx+1];
|
||||
list_.resize(list_.size()-1);
|
||||
return res;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void PBlock::set_join_type(PBlock::BL_TYPE type)
|
||||
{
|
||||
assert(bl_type_ == BL_PAR);
|
||||
@@ -126,8 +142,30 @@ void PBlock::set_statement(const vector<Statement*>&st)
|
||||
list_ = st;
|
||||
}
|
||||
|
||||
void PBlock::push_statement_front(Statement*that)
|
||||
{
|
||||
ivl_assert(*this, bl_type_==BL_SEQ);
|
||||
|
||||
list_.resize(list_.size()+1);
|
||||
for (size_t idx = list_.size()-1 ; idx > 0 ; idx -= 1)
|
||||
list_[idx] = list_[idx-1];
|
||||
|
||||
list_[0] = that;
|
||||
}
|
||||
|
||||
PCallTask::PCallTask(const pform_name_t&n, const list<PExpr*>&p)
|
||||
: path_(n), parms_(p.size())
|
||||
: package_(0), path_(n), parms_(p.size())
|
||||
{
|
||||
list<PExpr*>::const_iterator cur = p.begin();
|
||||
for (size_t idx = 0 ; idx < parms_.size() ; idx += 1) {
|
||||
parms_[idx] = *cur;
|
||||
++cur;
|
||||
}
|
||||
assert(cur == p.end());
|
||||
}
|
||||
|
||||
PCallTask::PCallTask(PPackage*pkg, const pform_name_t&n, const list<PExpr*>&p)
|
||||
: package_(pkg), path_(n), parms_(p.size())
|
||||
{
|
||||
list<PExpr*>::const_iterator cur = p.begin();
|
||||
for (size_t idx = 0 ; idx < parms_.size() ; idx += 1) {
|
||||
@@ -138,7 +176,7 @@ PCallTask::PCallTask(const pform_name_t&n, const list<PExpr*>&p)
|
||||
}
|
||||
|
||||
PCallTask::PCallTask(perm_string n, const list<PExpr*>&p)
|
||||
: parms_(p.size())
|
||||
: package_(0), parms_(p.size())
|
||||
{
|
||||
list<PExpr*>::const_iterator cur = p.begin();
|
||||
for (size_t idx = 0 ; idx < parms_.size() ; idx += 1) {
|
||||
@@ -183,6 +221,21 @@ PCAssign::~PCAssign()
|
||||
delete expr_;
|
||||
}
|
||||
|
||||
PChainConstructor::PChainConstructor(const list<PExpr*>&parms)
|
||||
: parms_(parms.size())
|
||||
{
|
||||
list<PExpr*>::const_iterator cur = parms.begin();
|
||||
for (size_t idx = 0 ; idx < parms_.size() ; idx += 1) {
|
||||
parms_[idx] = *cur;
|
||||
++cur;
|
||||
}
|
||||
assert(cur == parms.end());
|
||||
}
|
||||
|
||||
PChainConstructor::~PChainConstructor()
|
||||
{
|
||||
}
|
||||
|
||||
PCondit::PCondit(PExpr*ex, Statement*i, Statement*e)
|
||||
: expr_(ex), if_(i), else_(e)
|
||||
{
|
||||
@@ -224,6 +277,17 @@ PDisable::~PDisable()
|
||||
{
|
||||
}
|
||||
|
||||
PDoWhile::PDoWhile(PExpr*ex, Statement*st)
|
||||
: cond_(ex), statement_(st)
|
||||
{
|
||||
}
|
||||
|
||||
PDoWhile::~PDoWhile()
|
||||
{
|
||||
delete cond_;
|
||||
delete statement_;
|
||||
}
|
||||
|
||||
PEventStatement::PEventStatement(const svector<PEEvent*>&ee)
|
||||
: expr_(ee), statement_(0)
|
||||
{
|
||||
@@ -272,6 +336,20 @@ PForce::~PForce()
|
||||
delete expr_;
|
||||
}
|
||||
|
||||
PForeach::PForeach(perm_string av, const list<perm_string>&ix, Statement*s)
|
||||
: array_var_(av), index_vars_(ix.size()), statement_(s)
|
||||
{
|
||||
size_t idx = 0;
|
||||
for (list<perm_string>::const_iterator cur = ix.begin()
|
||||
; cur != ix.end() ; ++cur)
|
||||
index_vars_[idx++] = *cur;
|
||||
}
|
||||
|
||||
PForeach::~PForeach()
|
||||
{
|
||||
delete statement_;
|
||||
}
|
||||
|
||||
PForever::PForever(Statement*s)
|
||||
: statement_(s)
|
||||
{
|
||||
@@ -318,6 +396,16 @@ PRepeat::~PRepeat()
|
||||
delete statement_;
|
||||
}
|
||||
|
||||
PReturn::PReturn(PExpr*e)
|
||||
: expr_(e)
|
||||
{
|
||||
}
|
||||
|
||||
PReturn::~PReturn()
|
||||
{
|
||||
delete expr_;
|
||||
}
|
||||
|
||||
PTrigger::PTrigger(const pform_name_t&e)
|
||||
: event_(e)
|
||||
{
|
||||
@@ -327,8 +415,8 @@ PTrigger::~PTrigger()
|
||||
{
|
||||
}
|
||||
|
||||
PWhile::PWhile(PExpr*e1, Statement*st)
|
||||
: cond_(e1), statement_(st)
|
||||
PWhile::PWhile(PExpr*ex, Statement*st)
|
||||
: cond_(ex), statement_(st)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
+102
-8
@@ -1,7 +1,7 @@
|
||||
#ifndef __Statement_H
|
||||
#define __Statement_H
|
||||
#ifndef IVL_Statement_H
|
||||
#define IVL_Statement_H
|
||||
/*
|
||||
* Copyright (c) 1998-2008,2012 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2014 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -31,6 +31,8 @@
|
||||
# include "HName.h"
|
||||
# include "LineInfo.h"
|
||||
class PExpr;
|
||||
class PChainConstructor;
|
||||
class PPackage;
|
||||
class Statement;
|
||||
class PEventStatement;
|
||||
class Design;
|
||||
@@ -104,8 +106,9 @@ class PAssign_ : public Statement {
|
||||
|
||||
protected:
|
||||
NetAssign_* elaborate_lval(Design*, NetScope*scope) const;
|
||||
NetExpr* elaborate_rval_(Design*, NetScope*, unsigned lv_width,
|
||||
ivl_variable_type_t type) const;
|
||||
NetExpr* elaborate_rval_(Design*, NetScope*, ivl_type_t lv_net_type,
|
||||
ivl_variable_type_t lv_type,
|
||||
unsigned lv_width) const;
|
||||
NetExpr* elaborate_rval_(Design*, NetScope*, ivl_type_t ntype) const;
|
||||
|
||||
NetExpr* elaborate_rval_obj_(Design*, NetScope*,
|
||||
@@ -179,12 +182,21 @@ class PBlock : public PScope, public Statement {
|
||||
|
||||
BL_TYPE bl_type() const { return bl_type_; }
|
||||
|
||||
// This is only used if this block is the statement list for a
|
||||
// constructor. We look for a PChainConstructor as the first
|
||||
// statement, and if it is there, extract it.
|
||||
PChainConstructor*extract_chain_constructor();
|
||||
|
||||
// If the bl_type() is BL_PAR, it is possible to replace it
|
||||
// with JOIN_NONE or JOIN_ANY. This is to help the parser.
|
||||
void set_join_type(BL_TYPE);
|
||||
|
||||
void set_statement(const std::vector<Statement*>&st);
|
||||
|
||||
// Copy the statement from that block to the front of this
|
||||
// block.
|
||||
void push_statement_front(Statement*that);
|
||||
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
@@ -198,6 +210,7 @@ class PBlock : public PScope, public Statement {
|
||||
class PCallTask : public Statement {
|
||||
|
||||
public:
|
||||
explicit PCallTask(PPackage*pkg, const pform_name_t&n, const list<PExpr*>&parms);
|
||||
explicit PCallTask(const pform_name_t&n, const list<PExpr*>&parms);
|
||||
explicit PCallTask(perm_string n, const list<PExpr*>&parms);
|
||||
~PCallTask();
|
||||
@@ -211,8 +224,19 @@ class PCallTask : public Statement {
|
||||
NetProc* elaborate_sys(Design*des, NetScope*scope) const;
|
||||
NetProc* elaborate_usr(Design*des, NetScope*scope) const;
|
||||
|
||||
NetProc*elaborate_method_(Design*des, NetScope*scope) const;
|
||||
NetProc*elaborate_method_(Design*des, NetScope*scope,
|
||||
bool add_this_flag = false) const;
|
||||
NetProc*elaborate_function_(Design*des, NetScope*scope) const;
|
||||
|
||||
NetProc*elaborate_build_call_(Design*des, NetScope*scope,
|
||||
NetScope*task, NetExpr*use_this) const;
|
||||
NetProc*elaborate_sys_task_method_(Design*des, NetScope*scope,
|
||||
NetNet*net,
|
||||
perm_string method_name,
|
||||
const char*sys_task_name) const;
|
||||
bool test_task_calls_ok_(Design*des, NetScope*scope) const;
|
||||
|
||||
PPackage*package_;
|
||||
pform_name_t path_;
|
||||
vector<PExpr*> parms_;
|
||||
};
|
||||
@@ -258,6 +282,26 @@ class PCAssign : public Statement {
|
||||
PExpr*expr_;
|
||||
};
|
||||
|
||||
/*
|
||||
* This represents the syntax "super.new(...)". This is not really an
|
||||
* executable statement, but the elaborator will handle these
|
||||
* specially and will remove them from the statement stream. If any
|
||||
*/
|
||||
class PChainConstructor : public Statement {
|
||||
public:
|
||||
PChainConstructor(const list<PExpr*>&parms);
|
||||
~PChainConstructor();
|
||||
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
|
||||
inline const std::vector<PExpr*>& chain_args(void) const
|
||||
{ return parms_; }
|
||||
|
||||
private:
|
||||
std::vector<PExpr*> parms_;
|
||||
};
|
||||
|
||||
class PCondit : public Statement {
|
||||
|
||||
public:
|
||||
@@ -325,6 +369,22 @@ class PDisable : public Statement {
|
||||
pform_name_t scope_;
|
||||
};
|
||||
|
||||
class PDoWhile : public Statement {
|
||||
|
||||
public:
|
||||
PDoWhile(PExpr*ex, Statement*st);
|
||||
~PDoWhile();
|
||||
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_sig(Design*des, NetScope*scope) const;
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
PExpr*cond_;
|
||||
Statement*statement_;
|
||||
};
|
||||
|
||||
/*
|
||||
* The event statement represents the event delay in behavioral
|
||||
* code. It comes from such things as:
|
||||
@@ -361,6 +421,7 @@ class PEventStatement : public Statement {
|
||||
NetProc* elaborate_st(Design*des, NetScope*scope, NetProc*st) const;
|
||||
|
||||
NetProc* elaborate_wait(Design*des, NetScope*scope, NetProc*st) const;
|
||||
NetProc* elaborate_wait_fork(Design*des, NetScope*scope) const;
|
||||
|
||||
private:
|
||||
svector<PEEvent*>expr_;
|
||||
@@ -383,6 +444,26 @@ class PForce : public Statement {
|
||||
PExpr*expr_;
|
||||
};
|
||||
|
||||
class PForeach : public Statement {
|
||||
public:
|
||||
explicit PForeach(perm_string var, const std::list<perm_string>&ix, Statement*stmt);
|
||||
~PForeach();
|
||||
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_sig(Design*des, NetScope*scope) const;
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
NetProc* elaborate_static_array_(Design*des, NetScope*scope,
|
||||
const std::vector<netrange_t>&dims) const;
|
||||
|
||||
private:
|
||||
perm_string array_var_;
|
||||
std::vector<perm_string> index_vars_;
|
||||
Statement*statement_;
|
||||
};
|
||||
|
||||
class PForever : public Statement {
|
||||
public:
|
||||
explicit PForever(Statement*s);
|
||||
@@ -455,6 +536,19 @@ class PRelease : public Statement {
|
||||
PExpr*lval_;
|
||||
};
|
||||
|
||||
class PReturn : public Statement {
|
||||
|
||||
public:
|
||||
explicit PReturn(PExpr*e);
|
||||
~PReturn();
|
||||
|
||||
NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void dump(std::ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
PExpr*expr_;
|
||||
};
|
||||
|
||||
/*
|
||||
* The PTrigger statement sends a trigger to a named event. Take the
|
||||
* name here.
|
||||
@@ -475,7 +569,7 @@ class PTrigger : public Statement {
|
||||
class PWhile : public Statement {
|
||||
|
||||
public:
|
||||
PWhile(PExpr*e1, Statement*st);
|
||||
PWhile(PExpr*ex, Statement*st);
|
||||
~PWhile();
|
||||
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
@@ -488,4 +582,4 @@ class PWhile : public Statement {
|
||||
Statement*statement_;
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif /* IVL_Statement_H */
|
||||
|
||||
+4
-4
@@ -1,7 +1,7 @@
|
||||
#ifndef PLI_TYPES
|
||||
#define PLI_TYPES
|
||||
#ifndef PLI_TYPES_H
|
||||
#define PLI_TYPES_H
|
||||
/*
|
||||
* Copyright (c) 2003 Stephen Williams ([email protected])
|
||||
* Copyright (c) 2003-2014 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
|
||||
@@ -85,4 +85,4 @@ typedef char PLI_BYTE8;
|
||||
typedef unsigned char PLI_UBYTE8;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif /* PLI_TYPES_H */
|
||||
|
||||
+5
-4
@@ -1,7 +1,7 @@
|
||||
#ifndef __acc_user_H
|
||||
#define __acc_user_H
|
||||
#ifndef ACC_USER_H
|
||||
#define ACC_USER_H
|
||||
/*
|
||||
* Copyright (c) 2002 Stephen Williams ([email protected])
|
||||
* Copyright (c) 2002-2014 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
|
||||
@@ -228,6 +228,7 @@ extern PLI_INT32 acc_fetch_size(handle obj);
|
||||
|
||||
extern PLI_INT32 acc_fetch_type(handle obj);
|
||||
extern PLI_INT32 acc_fetch_fulltype(handle obj);
|
||||
extern PLI_INT32 acc_fetch_paramtype(handle obj);
|
||||
extern PLI_INT32 acc_fetch_range(handle object, int *msb, int *lsb);
|
||||
extern const char* acc_fetch_type_str(PLI_INT32 type);
|
||||
|
||||
@@ -270,4 +271,4 @@ extern char* acc_version(void);
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
||||
#endif /* ACC_USER_H */
|
||||
|
||||
Vendored
-11
@@ -218,17 +218,6 @@ AC_SUBST(strip_dynamic)
|
||||
# AC_MSG_RESULT($strip_dynamic)
|
||||
])# AX_LD_RDYNAMIC
|
||||
|
||||
# AX_CPP_PRECOMP
|
||||
# --------------
|
||||
AC_DEFUN([AX_CPP_PRECOMP],
|
||||
[# Darwin requires -no-cpp-precomp
|
||||
case "${host}" in
|
||||
*-*-darwin*)
|
||||
CPPFLAGS="-no-cpp-precomp $CPPFLAGS"
|
||||
CFLAGS="-no-cpp-precomp $CFLAGS"
|
||||
;;
|
||||
esac
|
||||
])# AX_CPP_PRECOMP
|
||||
|
||||
# AX_C99_STRTOD
|
||||
# -------------
|
||||
|
||||
@@ -50,8 +50,8 @@ bool NetEvWait::is_asynchronous()
|
||||
level sensitive, but the nex_async_ method takes care of
|
||||
that test. */
|
||||
NexusSet*sense = new NexusSet;
|
||||
for (unsigned idx = 0 ; idx < nevents_ ; idx += 1) {
|
||||
NexusSet*tmp = event(idx)->nex_async_();
|
||||
for (unsigned idx = 0 ; idx < events_.size() ; idx += 1) {
|
||||
NexusSet*tmp = events_[idx]->nex_async_();
|
||||
if (tmp == 0) {
|
||||
delete sense;
|
||||
return false;
|
||||
|
||||
+4
-1
@@ -10,4 +10,7 @@ echo "Autoconf in root..."
|
||||
autoconf -f
|
||||
|
||||
echo "Precompiling lexor_keyword.gperf"
|
||||
gperf -o -i 7 -C -k 1-4,6,9,\$ -L ANSI-C -H keyword_hash -N check_identifier -t ./lexor_keyword.gperf > lexor_keyword.cc
|
||||
gperf -o -i 7 -C -k 1-4,6,9,\$ -H keyword_hash -N check_identifier -t ./lexor_keyword.gperf > lexor_keyword.cc
|
||||
|
||||
echo "Precompiling vhdlpp/lexor_keyword.gperf"
|
||||
(cd vhdlpp ; gperf -o -i 7 --ignore-case -C -k 1-4,6,9,\$ -H keyword_hash -N check_identifier -t ./lexor_keyword.gperf > lexor_keyword.cc )
|
||||
|
||||
+1
-1
@@ -43,7 +43,7 @@ INCLUDE_PATH = -I. -I.. -I$(srcdir) -I$(srcdir)/..
|
||||
endif
|
||||
|
||||
CPPFLAGS = $(INCLUDE_PATH) @CPPFLAGS@ @DEFS@ @PICFLAG@
|
||||
CFLAGS = @WARNING_FLAGS@ @CFLAGS@
|
||||
CFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CC@ @CFLAGS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
|
||||
O = cadpli.o
|
||||
|
||||
+1
-1
@@ -79,7 +79,7 @@ static void thunker_register(void)
|
||||
}
|
||||
}
|
||||
|
||||
void (*vlog_startup_routines[])() = {
|
||||
void (*vlog_startup_routines[])(void) = {
|
||||
thunker_register,
|
||||
0
|
||||
};
|
||||
|
||||
+4
-4
@@ -1,7 +1,7 @@
|
||||
#ifndef __ivl_dlfcn_H
|
||||
#define __ivl_dlfcn_H
|
||||
#ifndef IVL_ivl_dlfcn_H
|
||||
#define IVL_ivl_dlfcn_H
|
||||
/*
|
||||
* Copyright (c) 2001 Stephen Williams ([email protected])
|
||||
* Copyright (c) 2001-2014 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
|
||||
@@ -91,4 +91,4 @@ static __inline__ const char*dlerror(void)
|
||||
{ return strerror( errno ); }
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif /* IVL_ivl_dlfcn_H */
|
||||
|
||||
+34
-7
@@ -1,7 +1,7 @@
|
||||
#ifndef __compiler_H
|
||||
#define __compiler_H
|
||||
#ifndef IVL_compiler_H
|
||||
#define IVL_compiler_H
|
||||
/*
|
||||
* Copyright (c) 1999-2011 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1999-2014 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -36,6 +36,11 @@
|
||||
*/
|
||||
extern unsigned integer_width;
|
||||
|
||||
/*
|
||||
* The width_cap is the width limit for unsized expressions.
|
||||
*/
|
||||
extern unsigned width_cap;
|
||||
|
||||
/*
|
||||
* This is the maximum number of recursive module loops allowed within
|
||||
* a generate block.
|
||||
@@ -92,7 +97,7 @@ extern bool warn_inf_loop;
|
||||
extern bool warn_sens_entire_vec;
|
||||
extern bool warn_sens_entire_arr;
|
||||
|
||||
/* Warn about level-appropriate anochronisms. */
|
||||
/* Warn about level-appropriate anachronisms. */
|
||||
extern bool warn_anachronisms;
|
||||
|
||||
/* This is true if verbose output is requested. */
|
||||
@@ -101,12 +106,26 @@ extern bool verbose_flag;
|
||||
extern bool debug_scopes;
|
||||
extern bool debug_eval_tree;
|
||||
extern bool debug_elaborate;
|
||||
extern bool debug_emit;
|
||||
extern bool debug_synth2;
|
||||
extern bool debug_optimizer;
|
||||
|
||||
/* Control evaluation of functions at compile time:
|
||||
* 0 = only for functions in constant expressions
|
||||
* 1 = only for automatic functions
|
||||
* 2 = for all functions
|
||||
* Level 2 should only be used if the user can guarantee that a
|
||||
* function's local variables are never accessed from outside the
|
||||
* function. */
|
||||
extern unsigned opt_const_func;
|
||||
|
||||
/* Possibly temporary flag to control virtualization of pin arrays */
|
||||
extern bool disable_virtual_pins;
|
||||
|
||||
/* The vlog95 code generator does not want the compiler to generate concat-Z
|
||||
* LPM objects so this flag is used to block them from being generated. */
|
||||
extern bool disable_concatz_generation;
|
||||
|
||||
/* Limit to size of devirtualized arrays */
|
||||
extern unsigned long array_size_limit;
|
||||
|
||||
@@ -127,6 +146,7 @@ enum generation_t {
|
||||
GN_VER2005 = 4,
|
||||
GN_VER2005_SV = 5,
|
||||
GN_VER2009 = 6,
|
||||
GN_VER2012 = 7,
|
||||
GN_DEFAULT = 4
|
||||
};
|
||||
|
||||
@@ -142,6 +162,10 @@ extern bool gn_icarus_misc_flag;
|
||||
is false, then skip elaboration of specify behavior. */
|
||||
extern bool gn_specify_blocks_flag;
|
||||
|
||||
/* If this flag is true, then elaborate assertions. If this flag is
|
||||
false, then stub out assertion statements. */
|
||||
extern bool gn_assertions_flag;
|
||||
|
||||
/* If this flag is true, then support/elaborate Verilog-AMS. */
|
||||
extern bool gn_verilog_ams_flag;
|
||||
|
||||
@@ -164,7 +188,8 @@ extern bool gn_strict_expr_width_flag;
|
||||
static inline bool gn_var_can_be_uwire(void)
|
||||
{
|
||||
if (generation_flag == GN_VER2005_SV ||
|
||||
generation_flag == GN_VER2009)
|
||||
generation_flag == GN_VER2009 ||
|
||||
generation_flag == GN_VER2012)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
@@ -172,7 +197,8 @@ static inline bool gn_var_can_be_uwire(void)
|
||||
static inline bool gn_system_verilog(void)
|
||||
{
|
||||
if (generation_flag == GN_VER2005_SV ||
|
||||
generation_flag == GN_VER2009)
|
||||
generation_flag == GN_VER2009 ||
|
||||
generation_flag == GN_VER2012)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
@@ -193,6 +219,7 @@ enum { GN_KEYWORDS_1364_1995 = 0x0001,
|
||||
GN_KEYWORDS_VAMS_2_3 = 0x0010,
|
||||
GN_KEYWORDS_1800_2005 = 0x0020,
|
||||
GN_KEYWORDS_1800_2009 = 0x0040,
|
||||
GN_KEYWORDS_1800_2012 = 0x0080,
|
||||
GN_KEYWORDS_ICARUS = 0x8000
|
||||
};
|
||||
extern int lexor_keyword_mask;
|
||||
@@ -256,4 +283,4 @@ extern void cleanup_sys_func_table();
|
||||
*/
|
||||
extern ivl_sfunc_as_task_t def_sfunc_as_task;
|
||||
|
||||
#endif
|
||||
#endif /* IVL_compiler_H */
|
||||
|
||||
+4
-4
@@ -1,7 +1,7 @@
|
||||
#ifndef __config_H /* -*- c++ -*- */
|
||||
#define __config_H
|
||||
#ifndef IVL_config_H /* -*- c++ -*- */
|
||||
#define IVL_config_H
|
||||
/*
|
||||
* Copyright (c) 2001-2012 Stephen Williams ([email protected])
|
||||
* Copyright (c) 2001-2014 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
|
||||
@@ -62,4 +62,4 @@
|
||||
*/
|
||||
# undef CHECK_WITH_VALGRIND
|
||||
|
||||
#endif /* __config_H */
|
||||
#endif /* IVL_config_H */
|
||||
|
||||
+4
-10
@@ -14,10 +14,6 @@ AC_CANONICAL_HOST
|
||||
dnl Checks for programs.
|
||||
AC_PROG_CC
|
||||
# AC_PROG_CC_C99 is only available in autoconf version 2.60 and later.
|
||||
# If you must use an older version then comment out the following two
|
||||
# lines, but be warned that there could be issues with finding the
|
||||
# nan(), etc. functions. It is really best to upgrade to a supported
|
||||
# version of autoconf.
|
||||
AC_PREREQ([2.60])
|
||||
AC_PROG_CC_C99
|
||||
AC_PROG_CXX
|
||||
@@ -85,8 +81,9 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])],
|
||||
CFLAGS="$iverilog_temp_cflags"
|
||||
|
||||
AC_SUBST(DEPENDENCY_FLAG, [-MD])
|
||||
AC_SUBST(WARNING_FLAGS, ["-Wall -Wshadow"])
|
||||
AC_SUBST(WARNING_FLAGS_CXX, ["$iverilog_wextra_flag"])
|
||||
AC_SUBST(WARNING_FLAGS, ["-Wall $iverilog_wextra_flag -Wshadow"])
|
||||
AC_SUBST(WARNING_FLAGS_CC, [""])
|
||||
AC_SUBST(WARNING_FLAGS_CXX, [""])
|
||||
fi
|
||||
|
||||
AC_LANG(C++)
|
||||
@@ -217,9 +214,6 @@ AX_LD_EXTRALIBS
|
||||
# CFLAGS inherited by cadpli/Makefile?
|
||||
AX_C_PICFLAG
|
||||
|
||||
# may modify CPPFLAGS and CFLAGS
|
||||
AX_CPP_PRECOMP
|
||||
|
||||
# may modify LDFLAGS
|
||||
AX_C99_STRTOD
|
||||
|
||||
@@ -325,4 +319,4 @@ AC_MSG_ERROR(cannot configure white space in libdir: $libdir)
|
||||
fi
|
||||
AC_MSG_RESULT(ok)
|
||||
|
||||
AC_OUTPUT(Makefile ivlpp/Makefile vhdlpp/Makefile vvp/Makefile vpi/Makefile driver/Makefile driver-vpi/Makefile cadpli/Makefile libveriuser/Makefile tgt-null/Makefile tgt-stub/Makefile tgt-vvp/Makefile tgt-vhdl/Makefile tgt-fpga/Makefile tgt-verilog/Makefile tgt-pal/Makefile tgt-vlog95/Makefile tgt-pcb/Makefile)
|
||||
AC_OUTPUT(Makefile ivlpp/Makefile vhdlpp/Makefile vvp/Makefile vpi/Makefile driver/Makefile driver-vpi/Makefile cadpli/Makefile libveriuser/Makefile tgt-null/Makefile tgt-stub/Makefile tgt-vvp/Makefile tgt-vhdl/Makefile tgt-fpga/Makefile tgt-verilog/Makefile tgt-pal/Makefile tgt-vlog95/Makefile tgt-pcb/Makefile tgt-blif/Makefile tgt-sizer/Makefile)
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
// These are correct and are used to find the base (zero) pin.
|
||||
thisSubtraction:netlist.h:4430
|
||||
thisSubtraction:netlist.h:4439
|
||||
thisSubtraction:netlist.h:4938
|
||||
thisSubtraction:netlist.h:4947
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998-2010 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2013 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -19,13 +19,14 @@
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# include <algorithm>
|
||||
# include <vector>
|
||||
# include <cstdlib>
|
||||
# include "netlist.h"
|
||||
# include "netmisc.h"
|
||||
# include "functor.h"
|
||||
# include "compiler.h"
|
||||
# include "ivl_assert.h"
|
||||
# include <vector>
|
||||
|
||||
|
||||
/*
|
||||
@@ -42,11 +43,14 @@ struct cprop_functor : public functor_t {
|
||||
virtual void signal(Design*des, NetNet*obj);
|
||||
virtual void lpm_add_sub(Design*des, NetAddSub*obj);
|
||||
virtual void lpm_compare(Design*des, NetCompare*obj);
|
||||
virtual void lpm_compare_eq_(Design*des, NetCompare*obj);
|
||||
virtual void lpm_concat(Design*des, NetConcat*obj);
|
||||
virtual void lpm_ff(Design*des, NetFF*obj);
|
||||
virtual void lpm_logic(Design*des, NetLogic*obj);
|
||||
virtual void lpm_mux(Design*des, NetMux*obj);
|
||||
};
|
||||
virtual void lpm_part_select(Design*des, NetPartSelect*obj);
|
||||
|
||||
void lpm_compare_eq_(Design*des, NetCompare*obj);
|
||||
};
|
||||
|
||||
void cprop_functor::signal(Design*, NetNet*)
|
||||
{
|
||||
@@ -74,6 +78,50 @@ void cprop_functor::lpm_compare_eq_(Design*, NetCompare*)
|
||||
{
|
||||
}
|
||||
|
||||
void cprop_functor::lpm_concat(Design*des, NetConcat*obj)
|
||||
{
|
||||
// Sorry, I don't know how to constant-propagate through
|
||||
// transparent concatenations.
|
||||
if (obj->transparent())
|
||||
return;
|
||||
|
||||
verinum result (verinum::Vz, obj->width());
|
||||
unsigned off = 0;
|
||||
|
||||
for (unsigned idx = 1 ; idx < obj->pin_count() ; idx += 1) {
|
||||
Nexus*nex = obj->pin(idx).nexus();
|
||||
// If there are non-constant drivers, then give up.
|
||||
if (! nex->drivers_constant())
|
||||
return;
|
||||
|
||||
verinum tmp = nex->driven_vector();
|
||||
result.set(off, tmp);
|
||||
off += tmp.len();
|
||||
}
|
||||
|
||||
if (debug_optimizer)
|
||||
cerr << obj->get_fileline() << ": cprop_functor::lpm_concat: "
|
||||
<< "Replace NetConcat with " << result << "." << endl;
|
||||
|
||||
|
||||
NetScope*scope = obj->scope();
|
||||
|
||||
// Create a NetConst object to carry the result. Give it the
|
||||
// same name as the Concat object that we are replacing, and
|
||||
// link the NetConst to the NetConcat object. Then delete the
|
||||
// concat that is now replaced.
|
||||
NetConst*result_obj = new NetConst(scope, obj->name(), result);
|
||||
result_obj->set_line(*obj);
|
||||
des->add_node(result_obj);
|
||||
connect(obj->pin(0), result_obj->pin(0));
|
||||
|
||||
// Note that this will leave the const inputs to dangle. They
|
||||
// will be reaped by other passes of cprop_functor.
|
||||
delete obj;
|
||||
|
||||
count += 1;
|
||||
}
|
||||
|
||||
void cprop_functor::lpm_ff(Design*, NetFF*obj)
|
||||
{
|
||||
// Look for and count unlinked FF outputs. Note that if the
|
||||
@@ -115,11 +163,6 @@ void cprop_functor::lpm_mux(Design*des, NetMux*obj)
|
||||
if (! sel_nex->drivers_constant())
|
||||
return;
|
||||
|
||||
// If the select input is assigned or forced, then again there
|
||||
// is nothing we can do here.
|
||||
if (sel_nex->assign_lval())
|
||||
return;
|
||||
|
||||
// If the constant select is 'bz or 'bx, then give up.
|
||||
verinum::V sel_val = sel_nex->driven_value();
|
||||
if (sel_val == verinum::Vz || sel_val == verinum::Vx)
|
||||
@@ -150,6 +193,142 @@ void cprop_functor::lpm_mux(Design*des, NetMux*obj)
|
||||
count += 1;
|
||||
}
|
||||
|
||||
static bool compare_base(NetPartSelect*a, NetPartSelect*b)
|
||||
{
|
||||
return a->base() < b->base();
|
||||
}
|
||||
|
||||
/*
|
||||
* This optimization searches for Nexa that are driven only by
|
||||
* NetPartSelect(PV) outputs. These might turn from Verilog input that
|
||||
* looks like this:
|
||||
* wire [7:0] foo
|
||||
* assign foo[7:4] = a;
|
||||
* assign foo[3:0] = b;
|
||||
* The idea is to convert the part selects of the above to a single
|
||||
* concatenation that looks like this:
|
||||
* assign foo = {a, b};
|
||||
*/
|
||||
void cprop_functor::lpm_part_select(Design*des, NetPartSelect*obj)
|
||||
{
|
||||
if (obj->dir() != NetPartSelect::PV)
|
||||
return;
|
||||
|
||||
NetScope*scope = obj->scope();
|
||||
Nexus*nex = obj->pin(1).nexus();
|
||||
vector<NetPartSelect*> obj_set;
|
||||
|
||||
for (Link*cur = nex->first_nlink() ; cur ; cur = cur->next_nlink()) {
|
||||
|
||||
// If this is an input (or passive) then ignore it.
|
||||
if (cur->get_dir() != Link::OUTPUT)
|
||||
continue;
|
||||
|
||||
// Check to see if this is the output of a
|
||||
// NetPartSelect::PV. If not, then give up on the blend.
|
||||
NetPins*tmp_obj = cur->get_obj();
|
||||
unsigned tmp_pin = cur->get_pin();
|
||||
|
||||
NetPartSelect*cur_obj = dynamic_cast<NetPartSelect*> (tmp_obj);
|
||||
if (cur_obj == 0)
|
||||
return;
|
||||
|
||||
if (cur_obj->dir() != NetPartSelect::PV)
|
||||
return;
|
||||
|
||||
if (tmp_pin != 1)
|
||||
return;
|
||||
|
||||
obj_set.push_back(cur_obj);
|
||||
}
|
||||
|
||||
if (obj_set.size() < 2)
|
||||
return;
|
||||
|
||||
if (debug_optimizer)
|
||||
cerr << obj->get_fileline() << ": cprop::lpm_part_select: "
|
||||
<< "Found " << obj_set.size() << " NetPartSelect(PV) objects."
|
||||
<< endl;
|
||||
|
||||
// Sort by increasing base offset.
|
||||
sort(obj_set.begin(), obj_set.end(), compare_base);
|
||||
|
||||
// Check and make sure there are no overlaps. If there are,
|
||||
// then give up on this optimization.
|
||||
for (size_t idx = 1 ; idx < obj_set.size() ; idx += 1) {
|
||||
unsigned top = obj_set[idx-1]->base() + obj_set[idx-1]->width();
|
||||
if (top > obj_set[idx]->base()) {
|
||||
if (debug_optimizer)
|
||||
cerr << obj->get_fileline() << ": cprop::lpm_part_select: "
|
||||
<< "Range [" << obj_set[idx-1]->base()
|
||||
<< " " << top << ") overlaps PV starting at "
|
||||
<< obj_set[idx]->base() << ". Give up." << endl;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the tail runs off the end of the target. If so it
|
||||
// should be possible to replace it with a bit select to
|
||||
// shorten the object for the target, but for now just give up.
|
||||
unsigned sig_width = nex->vector_width();
|
||||
if (obj_set.back()->base() + obj_set.back()->width() > sig_width) {
|
||||
if (debug_optimizer)
|
||||
cerr << obj->get_fileline() << ": cprop::lpm_part_select: "
|
||||
<< "Range [" << obj_set.back()->base()
|
||||
<< ":" << (obj_set.back()->base() + obj_set.back()->width() - 1)
|
||||
<< "] runs off the end of target." << endl;
|
||||
return;
|
||||
}
|
||||
|
||||
// Figure out how many components we are going to need.
|
||||
unsigned part_count = 0;
|
||||
unsigned off = 0;
|
||||
for (size_t idx = 0 ; idx < obj_set.size() ; idx += 1) {
|
||||
if (obj_set[idx]->base() > off) {
|
||||
off = obj_set[idx]->base();
|
||||
part_count += 1;
|
||||
}
|
||||
off += obj_set[idx]->width();
|
||||
part_count += 1;
|
||||
}
|
||||
|
||||
if (off < sig_width)
|
||||
part_count += 1;
|
||||
|
||||
NetConcat*concat = new NetConcat(scope, scope->local_symbol(),
|
||||
sig_width, part_count);
|
||||
concat->set_line(*obj);
|
||||
des->add_node(concat);
|
||||
connect(concat->pin(0), obj->pin(1));
|
||||
|
||||
off = 0;
|
||||
size_t concat_pin = 1;
|
||||
for (size_t idx = 0 ; idx < obj_set.size() ; idx += 1) {
|
||||
NetPartSelect*cobj = obj_set[idx];
|
||||
if (cobj->base() > off) {
|
||||
NetNet*zzz = make_const_z(des, scope, cobj->base()-off);
|
||||
connect(concat->pin(concat_pin), zzz->pin(0));
|
||||
concat_pin += 1;
|
||||
off = cobj->base();
|
||||
}
|
||||
connect(concat->pin(concat_pin), cobj->pin(0));
|
||||
concat_pin += 1;
|
||||
off += cobj->width();
|
||||
}
|
||||
if (off < sig_width) {
|
||||
NetNet*zzz = make_const_z(des, scope, sig_width-off);
|
||||
connect(concat->pin(concat_pin), zzz->pin(0));
|
||||
concat_pin += 1;
|
||||
}
|
||||
ivl_assert(*obj, concat_pin == concat->pin_count());
|
||||
|
||||
for (size_t idx = 0 ; idx < obj_set.size() ; idx += 1) {
|
||||
delete obj_set[idx];
|
||||
}
|
||||
|
||||
count += 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* This functor looks to see if the constant is connected to nothing
|
||||
* but signals. If that is the case, delete the dangling constant and
|
||||
|
||||
+309
-48
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998-2012 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2014 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -28,7 +28,9 @@
|
||||
# include "netlist.h"
|
||||
# include "compiler.h"
|
||||
# include "discipline.h"
|
||||
# include "netclass.h"
|
||||
# include "netdarray.h"
|
||||
# include "netqueue.h"
|
||||
# include "netvector.h"
|
||||
# include "ivl_assert.h"
|
||||
# include "PExpr.h"
|
||||
@@ -112,6 +114,9 @@ ostream& operator << (ostream&o, ivl_variable_type_t val)
|
||||
case IVL_VT_CLASS:
|
||||
o << "class";
|
||||
break;
|
||||
case IVL_VT_QUEUE:
|
||||
o << "queue";
|
||||
break;
|
||||
}
|
||||
return o;
|
||||
}
|
||||
@@ -144,18 +149,87 @@ ostream& operator << (ostream&o, ivl_switch_type_t val)
|
||||
return o;
|
||||
}
|
||||
|
||||
ostream& operator << (ostream&fd, PortType::Enum val)
|
||||
{
|
||||
switch (val) {
|
||||
case PortType::NOT_A_PORT:
|
||||
fd << "NOT_A_PORT";
|
||||
break;
|
||||
case PortType::PIMPLICIT:
|
||||
fd << "PIMPLICIT";
|
||||
break;
|
||||
case PortType::PINPUT:
|
||||
fd << "PINPUT";
|
||||
break;
|
||||
case PortType::POUTPUT:
|
||||
fd << "POUTPUT";
|
||||
break;
|
||||
case PortType::PINOUT:
|
||||
fd << "PINOUT";
|
||||
break;
|
||||
case PortType::PREF:
|
||||
fd << "PREF";
|
||||
break;
|
||||
default:
|
||||
fd << "PortType::Enum::?";
|
||||
break;
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
ostream& operator << (ostream&fd, NetCaseCmp::kind_t that)
|
||||
{
|
||||
switch (that) {
|
||||
case NetCaseCmp::EEQ:
|
||||
fd << "===";
|
||||
break;
|
||||
case NetCaseCmp::NEQ:
|
||||
fd << "!==";
|
||||
break;
|
||||
case NetCaseCmp::XEQ:
|
||||
fd << "==?";
|
||||
break;
|
||||
case NetCaseCmp::ZEQ:
|
||||
fd << "==z?";
|
||||
break;
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
|
||||
ostream& ivl_type_s::debug_dump(ostream&o) const
|
||||
{
|
||||
o << typeid(*this).name();
|
||||
return o;
|
||||
}
|
||||
|
||||
ostream& netclass_t::debug_dump(ostream&fd) const
|
||||
{
|
||||
fd << "class " << name_ << "{";
|
||||
for (size_t idx = 0 ; idx < property_table_.size() ; idx += 1) {
|
||||
if (idx != 0) fd << "; ";
|
||||
if (property_table_[idx].type)
|
||||
property_table_[idx].type->debug_dump(fd);
|
||||
else
|
||||
fd << "NO_TYPE";
|
||||
fd << " " << property_table_[idx].name;
|
||||
}
|
||||
fd << "}";
|
||||
return fd;
|
||||
}
|
||||
|
||||
ostream& netdarray_t::debug_dump(ostream&o) const
|
||||
{
|
||||
o << "dynamic array of " << *element_type();
|
||||
return o;
|
||||
}
|
||||
|
||||
ostream& netqueue_t::debug_dump(ostream&fd) const
|
||||
{
|
||||
fd << "queue of " << *element_type();
|
||||
return fd;
|
||||
}
|
||||
|
||||
ostream& netvector_t::debug_dump(ostream&o) const
|
||||
{
|
||||
o << type_ << (signed_? " signed" : " unsigned") << packed_dims_;
|
||||
@@ -169,10 +243,7 @@ static inline void dump_scope_path(ostream&o, const NetScope*scope)
|
||||
dump_scope_path(o, parent);
|
||||
o << ".";
|
||||
}
|
||||
const hname_t name = scope->fullname();
|
||||
o << name.peek_name();
|
||||
if (name.has_number())
|
||||
o << "[" << name.peek_number() << "]";
|
||||
o << scope->fullname();
|
||||
}
|
||||
|
||||
ostream& operator <<(ostream&o, struct __ScopePathManip marg)
|
||||
@@ -182,6 +253,77 @@ ostream& operator <<(ostream&o, struct __ScopePathManip marg)
|
||||
return o;
|
||||
}
|
||||
|
||||
ostream& operator <<(ostream&o, struct __ObjectPathManip marg)
|
||||
{
|
||||
if (marg.obj != 0) {
|
||||
dump_scope_path(o, marg.obj->scope());
|
||||
o << "." << marg.obj->name();
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
ostream& operator <<(ostream&fd, Link::DIR dir)
|
||||
{
|
||||
switch (dir) {
|
||||
case Link::PASSIVE:
|
||||
fd << "PASSIVE";
|
||||
break;
|
||||
case Link::INPUT:
|
||||
fd << "INPUT";
|
||||
break;
|
||||
case Link::OUTPUT:
|
||||
fd << "OUTPUT";
|
||||
break;
|
||||
default:
|
||||
fd << "<" << (int)dir << ">";
|
||||
break;
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
|
||||
void NetPins::show_type(ostream&fd) const
|
||||
{
|
||||
fd << typeid(*this).name();
|
||||
}
|
||||
|
||||
void NetObj::show_type(ostream&fd) const
|
||||
{
|
||||
fd << typeid(*this).name() << "[" << scope_path(scope_) << "." << name_ << "]";
|
||||
}
|
||||
|
||||
struct __ShowTypeManip { const NetPins*pins; };
|
||||
inline __ShowTypeManip show_type(const NetPins*pins)
|
||||
{ __ShowTypeManip tmp; tmp.pins = pins; return tmp; }
|
||||
|
||||
inline ostream& operator << (ostream&fd, __ShowTypeManip man)
|
||||
{
|
||||
if (man.pins == 0)
|
||||
fd << "NexusSet";
|
||||
else
|
||||
man.pins->show_type(fd);
|
||||
return fd;
|
||||
}
|
||||
|
||||
|
||||
void Link::dump_link(ostream&fd, unsigned ind) const
|
||||
{
|
||||
const Link*cur;
|
||||
const Nexus*nex = nexus();
|
||||
|
||||
if (nex == 0) {
|
||||
fd << setw(ind) << "" << "<unlinked>" << endl;
|
||||
return;
|
||||
}
|
||||
|
||||
for (cur = nex->first_nlink() ; cur; cur = cur->next_nlink()) {
|
||||
const NetPins*obj = cur->get_obj();
|
||||
unsigned pin = cur->get_pin();
|
||||
fd << setw(ind) << "" << "Pin " << pin
|
||||
<< " of " << show_type(obj)
|
||||
<< ", dir=" << cur->dir_ << endl;
|
||||
}
|
||||
}
|
||||
|
||||
void NetBranch::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
static const char*pin_names[2] = {
|
||||
@@ -445,8 +587,12 @@ void NetCompare::dump_node(ostream&o, unsigned ind) const
|
||||
|
||||
void NetConcat::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "NetConcat: "
|
||||
<< name();
|
||||
if (transparent_)
|
||||
o << setw(ind) << "" << "NetConcat8: ";
|
||||
else
|
||||
o << setw(ind) << "" << "NetConcat: ";
|
||||
o << name();
|
||||
|
||||
if (rise_time())
|
||||
o << " #(" << *rise_time()
|
||||
<< "," << *fall_time() << "," << *decay_time() << ")";
|
||||
@@ -509,19 +655,14 @@ void NetBUFZ::dump_node(ostream&o, unsigned ind) const
|
||||
|
||||
void NetCaseCmp::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
if (eeq_)
|
||||
o << setw(ind) << "" << "case compare === : " << name() << endl;
|
||||
else
|
||||
o << setw(ind) << "" << "case compare !== : " << name() << endl;
|
||||
o << setw(ind) << "" << "case compare " << kind_ << ": " << name() << endl;
|
||||
|
||||
dump_node_pins(o, ind+4);
|
||||
}
|
||||
|
||||
void NetConst::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "constant " << width_ << "'b";
|
||||
for (unsigned idx = width_ ; idx > 0 ; idx -= 1)
|
||||
o << value_[idx-1];
|
||||
o << setw(ind) << "" << "constant " << value_;
|
||||
o << ": " << name();
|
||||
if (rise_time())
|
||||
o << " #(" << *rise_time()
|
||||
@@ -662,6 +803,21 @@ void NetPartSelect::dump_node(ostream&o, unsigned ind) const
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetSubstitute::dump_node(ostream&fd, unsigned ind) const
|
||||
{
|
||||
fd << setw(ind) << "" << "NetSubstitute: "
|
||||
<< name();
|
||||
if (rise_time())
|
||||
fd << " #(" << *rise_time()
|
||||
<< "," << *fall_time()
|
||||
<< "," << *decay_time() << ")";
|
||||
else
|
||||
fd << " #(.,.,.)";
|
||||
fd << " width=" << wid_ << " base=" << off_ <<endl;
|
||||
dump_node_pins(fd, ind+4);
|
||||
dump_obj_attr(fd, ind+4);
|
||||
}
|
||||
|
||||
void NetReplicate::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "NetReplicate: "
|
||||
@@ -743,12 +899,13 @@ void NetUserFunc::dump_node(ostream&o, unsigned ind) const
|
||||
|
||||
void NetTaskDef::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "task " << scope_path(scope_) << ";" << endl;
|
||||
o << setw(ind) << "" << "task " << scope_path(scope()) << ";" << endl;
|
||||
|
||||
for (unsigned idx = 0 ; idx < ports_.count() ; idx += 1) {
|
||||
for (unsigned idx = 0 ; idx < port_count() ; idx += 1) {
|
||||
const NetNet*pnet = port(idx);
|
||||
o << setw(ind+4) << "";
|
||||
assert(ports_[idx]);
|
||||
switch (ports_[idx]->port_type()) {
|
||||
assert(pnet);
|
||||
switch (pnet->port_type()) {
|
||||
case NetNet::PINPUT:
|
||||
o << "input ";
|
||||
break;
|
||||
@@ -762,10 +919,13 @@ void NetTaskDef::dump(ostream&o, unsigned ind) const
|
||||
o << "NOT_A_PORT ";
|
||||
break;
|
||||
}
|
||||
o << ports_[idx]->name() << ";" << endl;
|
||||
o << pnet->name() << ";" << endl;
|
||||
}
|
||||
|
||||
proc_->dump(o, ind+4);
|
||||
if (proc_)
|
||||
proc_->dump(o, ind+4);
|
||||
else
|
||||
o << setw(ind+4) << "" << "MISSING PROCEDURAL CODE" << endl;
|
||||
|
||||
o << setw(ind) << "" << "endtask" << endl;
|
||||
}
|
||||
@@ -855,19 +1015,18 @@ void NetAlloc::dump(ostream&o, unsigned ind) const
|
||||
|
||||
void NetAssign_::dump_lval(ostream&o) const
|
||||
{
|
||||
if (sig_) {
|
||||
o << sig_->name();
|
||||
if (! member_.nil()) {
|
||||
o << "." << member_;
|
||||
}
|
||||
if (word_) {
|
||||
o << "[word=" << *word_ << "]";
|
||||
}
|
||||
if (base_) {
|
||||
o << "[" << *base_ << " +: " << lwid_ << "]";
|
||||
}
|
||||
} else {
|
||||
o << "";
|
||||
if (sig_) o << sig_->name();
|
||||
else if (nest_) nest_->dump_lval(o);
|
||||
else o << "<?>";
|
||||
|
||||
if (! member_.nil()) {
|
||||
o << "." << member_;
|
||||
}
|
||||
if (word_) {
|
||||
o << "[word=" << *word_ << "]";
|
||||
}
|
||||
if (base_) {
|
||||
o << "[" << *base_ << " +: " << lwid_ << "]";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -962,7 +1121,7 @@ void NetCase::dump(ostream&o, unsigned ind) const
|
||||
break;
|
||||
}
|
||||
|
||||
for (unsigned idx = 0 ; idx < nitems_ ; idx += 1) {
|
||||
for (unsigned idx = 0 ; idx < items_.size() ; idx += 1) {
|
||||
o << setw(ind+2) << "";
|
||||
if (items_[idx].guard)
|
||||
o << *items_[idx].guard << ":";
|
||||
@@ -1020,8 +1179,17 @@ void NetDeassign::dump(ostream&o, unsigned ind) const
|
||||
|
||||
void NetDisable::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "disable " << scope_path(target_) << "; "
|
||||
<< "/* " << get_fileline() << " */" << endl;
|
||||
o << setw(ind) << "" << "disable ";
|
||||
if (target_) o << scope_path(target_);
|
||||
else o << "fork";
|
||||
o << "; " << "/* " << get_fileline() << " */" << endl;
|
||||
}
|
||||
|
||||
void NetDoWhile::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "do" << endl;
|
||||
proc_->dump(o, ind+3);
|
||||
o << setw(ind) << "" << "while (" << *cond_ << ");" << endl;
|
||||
}
|
||||
|
||||
void NetEvProbe::dump_node(ostream&o, unsigned ind) const
|
||||
@@ -1052,7 +1220,15 @@ void NetEvTrig::dump(ostream&o, unsigned ind) const
|
||||
|
||||
void NetEvWait::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) <<"" << "@(";
|
||||
o << setw(ind) << "";
|
||||
|
||||
/* Check for a wait fork. */
|
||||
if ((nevents() == 1) && (event(0) == 0)) {
|
||||
o << "wait fork;";
|
||||
return;
|
||||
}
|
||||
|
||||
o << "@(";
|
||||
|
||||
if (nevents() > 0)
|
||||
o << event(0)->name();
|
||||
@@ -1076,6 +1252,12 @@ ostream& operator << (ostream&out, const NetEvWait&obj)
|
||||
|
||||
void NetEvWait::dump_inline(ostream&o) const
|
||||
{
|
||||
/* Check for a wait fork. */
|
||||
if ((nevents() == 1) && (event(0) == 0)) {
|
||||
o << "wait fork;";
|
||||
return;
|
||||
}
|
||||
|
||||
o << "@(";
|
||||
|
||||
if (nevents() > 0)
|
||||
@@ -1100,6 +1282,13 @@ void NetForever::dump(ostream&o, unsigned ind) const
|
||||
statement_->dump(o, ind+2);
|
||||
}
|
||||
|
||||
void NetForLoop::dump(ostream&fd, unsigned ind) const
|
||||
{
|
||||
fd << setw(ind) << "" << "FOR LOOP index=" << index_->name() << endl;
|
||||
statement_->dump(fd, ind+4);
|
||||
step_statement_->dump(fd, ind+4);
|
||||
}
|
||||
|
||||
void NetFree::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "// free storage : " << scope_path(scope_) << endl;
|
||||
@@ -1107,7 +1296,7 @@ void NetFree::dump(ostream&o, unsigned ind) const
|
||||
|
||||
void NetFuncDef::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "function definition for " << scope_path(scope_) << endl;
|
||||
o << setw(ind) << "" << "function definition for " << scope_path(scope()) << endl;
|
||||
if (result_sig_) {
|
||||
o << setw(ind+2) << "" << "Return signal: ";
|
||||
if (result_sig_->get_signed()) o << "+";
|
||||
@@ -1135,10 +1324,10 @@ void NetFuncDef::dump(ostream&o, unsigned ind) const
|
||||
if (port(idx)->get_signed()) o << "+";
|
||||
o << port(idx)->name() << endl;
|
||||
}
|
||||
if (statement_)
|
||||
statement_->dump(o, ind+2);
|
||||
if (proc_)
|
||||
proc_->dump(o, ind+2);
|
||||
else
|
||||
o << setw(ind+2) << "" << "// NO STATEMENT" << endl;
|
||||
o << setw(ind+2) << "" << "MISSING PROCEDURAL CODE" << endl;
|
||||
}
|
||||
|
||||
void NetPDelay::dump(ostream&o, unsigned ind) const
|
||||
@@ -1171,6 +1360,11 @@ void NetRepeat::dump(ostream&o, unsigned ind) const
|
||||
statement_->dump(o, ind+2);
|
||||
}
|
||||
|
||||
void netclass_t::dump_scope(ostream&fd) const
|
||||
{
|
||||
class_scope_->dump(fd);
|
||||
}
|
||||
|
||||
void NetScope::dump(ostream&o) const
|
||||
{
|
||||
/* This is a constructed hierarchical name. */
|
||||
@@ -1181,8 +1375,8 @@ void NetScope::dump(ostream&o) const
|
||||
if (is_cell()) o << " (cell)";
|
||||
if (nested_module()) o << " (nested)";
|
||||
if (program_block()) o << " (program)";
|
||||
|
||||
o << endl;
|
||||
o << " " << children_.size() << " children, "
|
||||
<< classes_.size() << " classes" << endl;
|
||||
|
||||
for (unsigned idx = 0 ; idx < attr_cnt() ; idx += 1)
|
||||
o << " (* " << attr_key(idx) << " = "
|
||||
@@ -1270,9 +1464,9 @@ void NetScope::dump(ostream&o) const
|
||||
o << " enum sets {" << endl;
|
||||
|
||||
/* Dump the enumerations and enum names in this scope. */
|
||||
for (list<netenum_t*>::const_iterator cur = enum_sets_.begin()
|
||||
for (map<const enum_type_t*,netenum_t*>::const_iterator cur = enum_sets_.begin()
|
||||
; cur != enum_sets_.end() ; ++ cur) {
|
||||
o << " " << *cur << endl;
|
||||
o << " " << cur->second << endl;
|
||||
}
|
||||
o << " }" << endl;
|
||||
|
||||
@@ -1318,6 +1512,11 @@ void NetScope::dump(ostream&o) const
|
||||
for (map<hname_t,NetScope*>::const_iterator cur = children_.begin()
|
||||
; cur != children_.end() ; ++ cur )
|
||||
cur->second->dump(o);
|
||||
|
||||
for (map<perm_string,netclass_t*>::const_iterator cur = classes_.begin()
|
||||
; cur != classes_.end() ; ++ cur ) {
|
||||
cur->second->dump_scope(o);
|
||||
}
|
||||
}
|
||||
|
||||
void NetSTask::dump(ostream&o, unsigned ind) const
|
||||
@@ -1375,6 +1574,19 @@ void NetEAccess::dump(ostream&o) const
|
||||
o << ")";
|
||||
}
|
||||
|
||||
void NetEArrayPattern::dump(ostream&fd) const
|
||||
{
|
||||
fd << "'{";
|
||||
if (items_.size() >= 1) {
|
||||
if (items_[0]) fd << *items_[0];
|
||||
}
|
||||
for (size_t idx = 1 ; idx < items_.size() ; idx += 1) {
|
||||
fd << ", ";
|
||||
if (items_[idx]) fd << *items_[idx];
|
||||
}
|
||||
fd << "}";
|
||||
}
|
||||
|
||||
void NetEBinary::dump(ostream&o) const
|
||||
{
|
||||
if (op_ == 'm' || op_ == 'M') {
|
||||
@@ -1449,6 +1661,16 @@ void NetEBinary::dump(ostream&o) const
|
||||
o << ")";
|
||||
}
|
||||
|
||||
void NetECast::dump(ostream&fd) const
|
||||
{
|
||||
if (op_=='2')
|
||||
fd << "bool<" << expr_width() << ">(" << *expr_ << ")";
|
||||
else if (op_=='4')
|
||||
fd << "logic<" << expr_width() << ">(" << *expr_ << ")";
|
||||
else
|
||||
NetEUnary::dump(fd);
|
||||
}
|
||||
|
||||
void NetEConcat::dump(ostream&o) const
|
||||
{
|
||||
if (repeat_ != 1)
|
||||
@@ -1507,6 +1729,11 @@ void NetEEvent::dump(ostream&o) const
|
||||
o << "<event=" << event_->name() << ">";
|
||||
}
|
||||
|
||||
void NetELast::dump(ostream&fd) const
|
||||
{
|
||||
fd << "<last of " << sig_->name() << ">";
|
||||
}
|
||||
|
||||
void NetENetenum::dump(ostream&o) const
|
||||
{
|
||||
o << "<netenum=" << netenum_ << ">";
|
||||
@@ -1514,7 +1741,14 @@ void NetENetenum::dump(ostream&o) const
|
||||
|
||||
void NetENew::dump(ostream&o) const
|
||||
{
|
||||
o << "new <type>";
|
||||
o << "new <type> [";
|
||||
if (size_) size_->dump(o);
|
||||
o << "]";
|
||||
if (init_val_) {
|
||||
o << "(";
|
||||
init_val_->dump(o);
|
||||
o << ")";
|
||||
}
|
||||
}
|
||||
|
||||
void NetENull::dump(ostream&o) const
|
||||
@@ -1525,6 +1759,8 @@ void NetENull::dump(ostream&o) const
|
||||
void NetEProperty::dump(ostream&o) const
|
||||
{
|
||||
o << net_->name() << ".<" << pidx_ << ">";
|
||||
if (index_)
|
||||
o << "[" << *index_ << "]";
|
||||
}
|
||||
|
||||
void NetEScope::dump(ostream&o) const
|
||||
@@ -1568,6 +1804,11 @@ void NetESFunc::dump(ostream&o) const
|
||||
o << ")";
|
||||
}
|
||||
|
||||
void NetEShallowCopy::dump(ostream&o) const
|
||||
{
|
||||
o << "<ShallowCopy, " << *arg1_ << " <-- " << *arg2_ << ">";
|
||||
}
|
||||
|
||||
void NetESignal::dump(ostream&o) const
|
||||
{
|
||||
if (has_sign())
|
||||
@@ -1586,7 +1827,7 @@ void NetETernary::dump(ostream&o) const
|
||||
|
||||
void NetEUFunc::dump(ostream&o) const
|
||||
{
|
||||
o << func_->basename() << "(";
|
||||
o << scope_path(func_) << "(";
|
||||
if (! parms_.empty()) {
|
||||
parms_[0]->dump(o);
|
||||
for (unsigned idx = 1 ; idx < parms_.size() ; idx += 1) {
|
||||
@@ -1641,10 +1882,30 @@ void NetEUnary::dump(ostream&o) const
|
||||
void Design::dump(ostream&o) const
|
||||
{
|
||||
o << "DESIGN TIME PRECISION: 10e" << get_precision() << endl;
|
||||
|
||||
o << "PACKAGES:" << endl;
|
||||
for (map<perm_string,NetScope*>::const_iterator cur = packages_.begin()
|
||||
; cur != packages_.end() ; ++cur) {
|
||||
cur->second->dump(o);
|
||||
}
|
||||
|
||||
o << "$ROOT CLASSESS:" << endl;
|
||||
for (map<perm_string,netclass_t*>::const_iterator cur = classes_.begin()
|
||||
; cur != classes_.end() ; ++cur) {
|
||||
cur->second->dump_scope(o);
|
||||
}
|
||||
|
||||
o << "$ROOT TASKS/FUNCTIONS:" << endl;
|
||||
for (map<NetScope*,PTaskFunc*>::const_iterator cur = root_tasks_.begin()
|
||||
; cur != root_tasks_.end() ; ++ cur) {
|
||||
cur->first->dump(o);
|
||||
}
|
||||
|
||||
o << "SCOPES:" << endl;
|
||||
for (list<NetScope*>::const_iterator scope = root_scopes_.begin();
|
||||
scope != root_scopes_.end(); ++ scope )
|
||||
scope != root_scopes_.end(); ++ scope ) {
|
||||
(*scope)->dump(o);
|
||||
}
|
||||
|
||||
o << "ELABORATED NODES:" << endl;
|
||||
|
||||
|
||||
+4
-4
@@ -1,7 +1,7 @@
|
||||
#ifndef __discipline_H
|
||||
#define __discipline_H
|
||||
#ifndef IVL_discipline_H
|
||||
#define IVL_discipline_H
|
||||
/*
|
||||
* Copyright (c) 2008-2010 Stephen Williams ([email protected])
|
||||
* Copyright (c) 2008-2014 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
|
||||
@@ -74,4 +74,4 @@ extern map<perm_string,ivl_discipline_t> disciplines;
|
||||
// Map access function name to the nature that it accesses.
|
||||
extern map<perm_string,ivl_nature_t> access_function_nature;
|
||||
|
||||
#endif
|
||||
#endif /* IVL_discipline_H */
|
||||
|
||||
@@ -48,7 +48,7 @@ INCLUDE_PATH = -I. -I.. -I$(srcdir) -I$(srcdir)/..
|
||||
endif
|
||||
|
||||
CPPFLAGS = $(INCLUDE_PATH) @CPPFLAGS@ @DEFS@
|
||||
CFLAGS = @WARNING_FLAGS@ @CFLAGS@
|
||||
CFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CC@ @CFLAGS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
|
||||
O = main.o res.o
|
||||
|
||||
+6
-2
@@ -49,7 +49,7 @@ INCLUDE_PATH = -I. -I.. -I$(srcdir) -I$(srcdir)/..
|
||||
endif
|
||||
|
||||
CPPFLAGS = $(INCLUDE_PATH) @CPPFLAGS@ @DEFS@
|
||||
CFLAGS = @WARNING_FLAGS@ @CFLAGS@
|
||||
CFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CC@ @CFLAGS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
|
||||
O = main.o substit.o cflexor.o cfparse.o
|
||||
@@ -67,7 +67,11 @@ distclean: clean
|
||||
rm -f Makefile config.log
|
||||
|
||||
cppcheck: $(O:.o=.c)
|
||||
cppcheck --enable=all -f $(INCLUDE_PATH) $^
|
||||
cppcheck --enable=all -f \
|
||||
-UYY_USER_INIT \
|
||||
-UYYPARSE_PARAM -UYYPRINT -Ushort -Uyyoverflow \
|
||||
-UYYTYPE_INT8 -UYYTYPE_INT16 -UYYTYPE_UINT8 -UYYTYPE_UINT16 \
|
||||
$(INCLUDE_PATH) $^
|
||||
|
||||
Makefile: $(srcdir)/Makefile.in ../config.status
|
||||
cd ..; ./config.status --file=driver/$@
|
||||
|
||||
+4
-2
@@ -4,7 +4,7 @@
|
||||
|
||||
%{
|
||||
/*
|
||||
* Copyright (c) 2001-2009 Stephen Williams ([email protected])
|
||||
* Copyright (c) 2001-2014 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
|
||||
@@ -92,6 +92,8 @@ int cmdfile_stack_ptr = 0;
|
||||
|
||||
"+vhdl-libdir+" { BEGIN(PLUS_ARGS); return TOK_VHDL_LIBDIR; }
|
||||
|
||||
"+width-cap+" { BEGIN(PLUS_ARGS); return TOK_WIDTH_CAP; }
|
||||
|
||||
/* If it is not any known plus-flag, return the generic form. */
|
||||
"+"[^\n \t\b\f\r+]* {
|
||||
cflval.text = strdup(yytext);
|
||||
@@ -245,7 +247,7 @@ void cfreset(FILE*fd, const char*path)
|
||||
/*
|
||||
* Modern version of flex (>=2.5.9) can clean up the scanner data.
|
||||
*/
|
||||
void destroy_lexor()
|
||||
void destroy_lexor(void)
|
||||
{
|
||||
# ifdef FLEX_SCANNER
|
||||
# if YY_FLEX_MAJOR_VERSION >= 2 && YY_FLEX_MINOR_VERSION >= 5
|
||||
|
||||
+11
-2
@@ -1,6 +1,6 @@
|
||||
%{
|
||||
/*
|
||||
* Copyright (c) 2001-2011 Stephen Williams ([email protected])
|
||||
* Copyright (c) 2001-2014 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
|
||||
@@ -61,6 +61,7 @@ static void translate_file_name(char*text)
|
||||
%token TOK_Da TOK_Dc TOK_Dv TOK_Dy
|
||||
%token TOK_DEFINE TOK_INCDIR TOK_INTEGER_WIDTH TOK_LIBDIR TOK_LIBDIR_NOCASE
|
||||
%token TOK_LIBEXT TOK_PARAMETER TOK_TIMESCALE TOK_VHDL_WORK TOK_VHDL_LIBDIR
|
||||
%token TOK_WIDTH_CAP
|
||||
%token <text> TOK_PLUSARG TOK_PLUSWORD TOK_STRING
|
||||
|
||||
%%
|
||||
@@ -191,6 +192,13 @@ item
|
||||
free(tmp);
|
||||
}
|
||||
|
||||
| TOK_WIDTH_CAP TOK_PLUSARG
|
||||
{ char*tmp = substitutions($2);
|
||||
free($2);
|
||||
width_cap = strtoul(tmp,0,10);
|
||||
free(tmp);
|
||||
}
|
||||
|
||||
/* The +<word> tokens that are not otherwise matched, are
|
||||
ignored. The skip_args rule arranges for all the argument words
|
||||
to be consumed. */
|
||||
@@ -213,7 +221,7 @@ item
|
||||
}
|
||||
|
||||
| error
|
||||
{ fprintf(stderr, "Error: unable to parse line %d in "
|
||||
{ fprintf(stderr, "Error: unable to parse line %u in "
|
||||
"%s.\n", cflloc.first_line, current_file);
|
||||
return 1;
|
||||
}
|
||||
@@ -262,5 +270,6 @@ skip_arg : TOK_PLUSARG
|
||||
|
||||
int yyerror(const char*msg)
|
||||
{
|
||||
(void)msg; /* Parameter is not used. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __cfparse_misc_H
|
||||
#define __cfparse_misc_H
|
||||
#ifndef IVL_cfparse_misc_H
|
||||
#define IVL_cfparse_misc_H
|
||||
/*
|
||||
* Copyright (c) 2001-2009 Picture Elements, Inc.
|
||||
* Copyright (c) 2001-2014 Picture Elements, Inc.
|
||||
* Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
@@ -38,7 +38,7 @@ int cflex(void);
|
||||
int cferror(const char *);
|
||||
int cfparse(void);
|
||||
void switch_to_command_file(const char *);
|
||||
void destroy_lexor();
|
||||
void destroy_lexor(void);
|
||||
char *current_file;
|
||||
|
||||
#endif
|
||||
#endif /* IVL_cfparse_misc_H */
|
||||
|
||||
+7
-4
@@ -1,7 +1,7 @@
|
||||
#ifndef __globals_H
|
||||
#define __globals_H
|
||||
#ifndef IVL_globals_H
|
||||
#define IVL_globals_H
|
||||
/*
|
||||
* Copyright (c) 2000-2009 Stephen Williams ([email protected])
|
||||
* Copyright (c) 2000-2014 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -24,6 +24,9 @@
|
||||
/* This is the integer-width argument that will be passed to ivl. */
|
||||
extern unsigned integer_width;
|
||||
|
||||
/* This is the width-cap argument that will be passed to ivl. */
|
||||
extern unsigned width_cap;
|
||||
|
||||
extern const char*vhdlpp_work;
|
||||
extern const char**vhdlpp_libdir;
|
||||
extern unsigned vhdlpp_libdir_cnt;
|
||||
@@ -51,4 +54,4 @@ extern void process_parameter(const char*name);
|
||||
/* Set the default timescale for the simulator. */
|
||||
extern void process_timescale(const char*ts_string);
|
||||
|
||||
#endif
|
||||
#endif /* IVL_globals_H */
|
||||
|
||||
+15
-6
@@ -1,4 +1,4 @@
|
||||
.TH iverilog 1 "February 27th, 2011" "" "Version %M.%m.%n %E"
|
||||
.TH iverilog 1 "February 26th, 2014" "" "Version %M.%m.%n %E"
|
||||
.SH NAME
|
||||
iverilog - Icarus Verilog compiler
|
||||
|
||||
@@ -6,7 +6,7 @@ iverilog - Icarus Verilog compiler
|
||||
.B iverilog
|
||||
[\-ESVv] [\-Bpath] [\-ccmdfile|\-fcmdfile] [\-Dmacro[=defn]]
|
||||
[\-Pparameter=value] [\-pflag=value]
|
||||
[\-dname] [\-g1995|\-g2001|\-g2005|\-g2005-sv|\-g2009|\-g<feature>]
|
||||
[\-dname] [\-g1995|\-g2001|\-g2005|\-g2005-sv|\-g2009|\-g2012|\-g<feature>]
|
||||
[\-Iincludedir] [\-mmodule] [\-M[mode=]file] [\-Nfile] [\-ooutputfilename]
|
||||
[\-stopmodule] [\-ttype] [\-Tmin/typ/max] [\-Wclass] [\-ypath] sourcefile
|
||||
|
||||
@@ -61,10 +61,11 @@ 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 -g1995\fI|\fP-g2001\fI|\fP-g2001-noconfig\fI|\fP-g2005\fI|\fP-g2005-sv\fI|\fP-g2009
|
||||
.B -g1995\fI|\fP-g2001\fI|\fP-g2001-noconfig\fI|\fP-g2005\fI|\fP-g2005-sv\fI|\fP-g2009\fI|\fP-g2012
|
||||
Select the Verilog language \fIgeneration\fP to support in the compiler.
|
||||
This selects between \fIIEEE1364\-1995\fP, \fIIEEE1364\-2001\fP,
|
||||
\fIIEEE1364\-2005\fP, \fIIEEE1800\-2005\fP, or \fIIEEE1800\-2009\fP.
|
||||
\fIIEEE1364\-2005\fP, \fIIEEE1800\-2005\fP, \fIIEEE1800\-2009\fP, or
|
||||
\fIIEEE1800\-2012\fP.
|
||||
Icarus Verilog currently defaults to the \fIIEEE1364\-2005\fP generation
|
||||
of the language. This flag is used to restrict the language to a set of
|
||||
keywords/features, this allows simulation of older Verilog code that may
|
||||
@@ -128,7 +129,9 @@ standard compliant behavior (with some loss in performance).
|
||||
.B -gstrict-expr-width\fI|\fP-gno-strict-expr-width
|
||||
Enable or disable (default) strict compliance with the standard rules
|
||||
for determining expression bit lengths. When disabled, the RHS of a
|
||||
parameter assignment is evaluated as a lossless expression.
|
||||
parameter assignment is evaluated as a lossless expression, as is any
|
||||
expression containing an unsized constant number, and unsized constant
|
||||
numbers are not truncated to integer width.
|
||||
.TP 8
|
||||
.B -I\fIincludedir\fP
|
||||
Append directory \fIincludedir\fP to list of directories searched
|
||||
@@ -459,6 +462,12 @@ This allows the programmer to select the width for integer variables
|
||||
in the Verilog source. The default is 32, the value can be any desired
|
||||
integer value.
|
||||
|
||||
.TP 8
|
||||
.B +width-cap+\fIvalue\fP
|
||||
This allows the programmer to select the width cap for unsized expressions.
|
||||
If the calculated width for an unsized expression exceeds this value, the
|
||||
compiler will issue a warning and limit the expression width to this value.
|
||||
|
||||
.SH "VARIABLES IN COMMAND FILES"
|
||||
|
||||
In certain cases, iverilog supports variables in command files. These
|
||||
@@ -512,7 +521,7 @@ Tips on using, debugging, and developing the compiler can be found at
|
||||
|
||||
.SH COPYRIGHT
|
||||
.nf
|
||||
Copyright \(co 2002\-2011 Stephen Williams
|
||||
Copyright \(co 2002\-2014 Stephen Williams
|
||||
|
||||
This document can be freely redistributed according to the terms of the
|
||||
GNU General Public License version 2.0
|
||||
|
||||
+34
-16
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2011 Stephen Williams ([email protected])
|
||||
* Copyright (c) 2000-2014 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
|
||||
@@ -39,7 +39,7 @@ const char NOTICE[] =
|
||||
|
||||
const char HELP[] =
|
||||
"Usage: iverilog [-ESvV] [-B base] [-c cmdfile|-f cmdfile]\n"
|
||||
" [-g1995|-g2001|-g2005|-g2005-sv|-g2009] [-g<feature>]\n"
|
||||
" [-g1995|-g2001|-g2005|-g2005-sv|-g2009|-g2012] [-g<feature>]\n"
|
||||
" [-D macro[=defn]] [-I includedir]\n"
|
||||
" [-M [mode=]depfile] [-m module]\n"
|
||||
" [-N file] [-o filename] [-p flag=value]\n"
|
||||
@@ -71,7 +71,7 @@ const char HELP[] =
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
|
||||
#if HAVE_GETOPT_H
|
||||
#ifdef HAVE_GETOPT_H
|
||||
#include <getopt.h>
|
||||
#endif
|
||||
|
||||
@@ -122,6 +122,7 @@ char depmode = 'a';
|
||||
|
||||
const char*generation = "2005";
|
||||
const char*gen_specify = "no-specify";
|
||||
const char*gen_assertions = "assertions";
|
||||
const char*gen_xtypes = "xtypes";
|
||||
const char*gen_icarus = "icarus-misc";
|
||||
const char*gen_io_range_error = "io-range-error";
|
||||
@@ -140,6 +141,8 @@ char warning_flags[16] = "n";
|
||||
|
||||
unsigned integer_width = 32;
|
||||
|
||||
unsigned width_cap = 65536;
|
||||
|
||||
char*mod_list = 0;
|
||||
char*command_filename = 0;
|
||||
|
||||
@@ -185,7 +188,7 @@ static const char** defparm_base = 0;
|
||||
static int defparm_size = 0;
|
||||
|
||||
/* Function to add a command file name to the FIFO. */
|
||||
void add_cmd_file(const char* filename)
|
||||
static void add_cmd_file(const char* filename)
|
||||
{
|
||||
p_command_file new;
|
||||
|
||||
@@ -202,7 +205,7 @@ void add_cmd_file(const char* filename)
|
||||
}
|
||||
|
||||
/* Function to return the top command file name from the FIFO. */
|
||||
char *get_cmd_file()
|
||||
static char *get_cmd_file(void)
|
||||
{
|
||||
char *filename;
|
||||
|
||||
@@ -399,7 +402,7 @@ static int t_preprocess_only(void)
|
||||
* 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_compile()
|
||||
static int t_compile(void)
|
||||
{
|
||||
unsigned rc;
|
||||
|
||||
@@ -622,7 +625,7 @@ void process_file_name(const char*name, int lib_flag)
|
||||
}
|
||||
}
|
||||
|
||||
int process_generation(const char*name)
|
||||
static int process_generation(const char*name)
|
||||
{
|
||||
if (strcmp(name,"1995") == 0)
|
||||
generation = "1995";
|
||||
@@ -642,6 +645,9 @@ int process_generation(const char*name)
|
||||
else if (strcmp(name,"2009") == 0)
|
||||
generation = "2009";
|
||||
|
||||
else if (strcmp(name,"2012") == 0)
|
||||
generation = "2012";
|
||||
|
||||
else if (strcmp(name,"1") == 0) { /* Deprecated: use 1995 */
|
||||
generation = "1995";
|
||||
gen_xtypes = "no-xtypes";
|
||||
@@ -675,6 +681,12 @@ int process_generation(const char*name)
|
||||
else if (strcmp(name,"no-specify") == 0)
|
||||
gen_specify = "no-specify";
|
||||
|
||||
else if (strcmp(name,"assertions") == 0)
|
||||
gen_assertions = "assertions";
|
||||
|
||||
else if (strcmp(name,"no-assertions") == 0)
|
||||
gen_assertions = "no-assertions";
|
||||
|
||||
else if (strcmp(name,"std-include") == 0)
|
||||
gen_std_include = 1;
|
||||
|
||||
@@ -720,6 +732,7 @@ int process_generation(const char*name)
|
||||
" 2005 -- IEEE1364-2005\n"
|
||||
" 2005-sv -- IEEE1800-2005\n"
|
||||
" 2009 -- IEEE1800-2009\n"
|
||||
" 2012 -- IEEE1800-2012\n"
|
||||
"Other generation flags:\n"
|
||||
" specify | no-specify\n"
|
||||
" verilog-ams | no-verilog-ams\n"
|
||||
@@ -737,7 +750,7 @@ int process_generation(const char*name)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int process_depfile(const char*name)
|
||||
static int process_depfile(const char*name)
|
||||
{
|
||||
const char*cp = strchr(name, '=');
|
||||
if (cp) {
|
||||
@@ -771,7 +784,7 @@ int process_depfile(const char*name)
|
||||
/*
|
||||
* If it exists add the SFT file for the given module.
|
||||
*/
|
||||
void add_sft_file(const char *module)
|
||||
static void add_sft_file(const char *module)
|
||||
{
|
||||
char *file;
|
||||
|
||||
@@ -786,7 +799,7 @@ int main(int argc, char **argv)
|
||||
{
|
||||
int e_flag = 0;
|
||||
int version_flag = 0;
|
||||
int opt, idx;
|
||||
int opt;
|
||||
|
||||
#ifdef __MINGW32__
|
||||
/* Calculate the ivl_root from the path to the command. This
|
||||
@@ -894,7 +907,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
while ((opt = getopt(argc, argv, "B:c:D:d:Ef:g:hI:M:m:N::o:P:p:Ss:T:t:vVW:y:Y:")) != EOF) {
|
||||
while ((opt = getopt(argc, argv, "B:c:D:d:Ef:g:hI:M:m:N:o:P:p:Ss:T:t:vVW:y:Y:")) != EOF) {
|
||||
|
||||
switch (opt) {
|
||||
case 'B':
|
||||
@@ -1031,7 +1044,7 @@ int main(int argc, char **argv)
|
||||
|
||||
if (version_flag || verbose_flag) {
|
||||
printf("Icarus Verilog version " VERSION " (" VERSION_TAG ")\n\n");
|
||||
printf("Copyright 1998-2011 Stephen Williams\n\n");
|
||||
printf("Copyright 1998-2013 Stephen Williams\n\n");
|
||||
puts(NOTICE);
|
||||
}
|
||||
|
||||
@@ -1057,10 +1070,11 @@ int main(int argc, char **argv)
|
||||
fprintf(iconfig_file, "sys_func:%s%csystem.sft\n", base, sep);
|
||||
fprintf(iconfig_file, "sys_func:%s%cvhdl_sys.sft\n", base, sep);
|
||||
|
||||
/* If verilog-2005/9 is enabled or icarus-misc or verilog-ams,
|
||||
/* If verilog-2005/09/12 is enabled or icarus-misc or verilog-ams,
|
||||
* then include the v2005_math library. */
|
||||
if (strcmp(generation, "2005") == 0 ||
|
||||
strcmp(generation, "2009") == 0 ||
|
||||
strcmp(generation, "2012") == 0 ||
|
||||
strcmp(gen_icarus, "icarus-misc") == 0 ||
|
||||
strcmp(gen_verilog_ams, "verilog-ams") == 0) {
|
||||
fprintf(iconfig_file, "sys_func:%s%cv2005_math.sft\n", base, sep);
|
||||
@@ -1076,7 +1090,8 @@ int main(int argc, char **argv)
|
||||
/* If verilog-2009 (SystemVerilog) is enabled, then include the
|
||||
v2009 module. */
|
||||
if (strcmp(generation, "2005-sv") == 0 ||
|
||||
strcmp(generation, "2009") == 0) {
|
||||
strcmp(generation, "2009") == 0 ||
|
||||
strcmp(generation, "2012") == 0) {
|
||||
fprintf(iconfig_file, "sys_func:%s%cv2009.sft\n", base, sep);
|
||||
fprintf(iconfig_file, "module:v2009\n");
|
||||
}
|
||||
@@ -1084,6 +1099,7 @@ int main(int argc, char **argv)
|
||||
if (mtm != 0) fprintf(iconfig_file, "-T:%s\n", mtm);
|
||||
fprintf(iconfig_file, "generation:%s\n", generation);
|
||||
fprintf(iconfig_file, "generation:%s\n", gen_specify);
|
||||
fprintf(iconfig_file, "generation:%s\n", gen_assertions);
|
||||
fprintf(iconfig_file, "generation:%s\n", gen_xtypes);
|
||||
fprintf(iconfig_file, "generation:%s\n", gen_io_range_error);
|
||||
fprintf(iconfig_file, "generation:%s\n", gen_strict_ca_eval);
|
||||
@@ -1126,7 +1142,7 @@ int main(int argc, char **argv)
|
||||
vhdlpp_work = "ivl_vhdl_work";
|
||||
fprintf(defines_file, "vhdlpp:%s%cvhdlpp\n", vhdlpp_dir, sep);
|
||||
fprintf(defines_file, "vhdlpp-work:%s\n", vhdlpp_work);
|
||||
for (idx = 0 ; idx < vhdlpp_libdir_cnt ; idx += 1)
|
||||
for (unsigned idx = 0 ; idx < vhdlpp_libdir_cnt ; idx += 1)
|
||||
fprintf(defines_file, "vhdlpp-libdir:%s\n", vhdlpp_libdir[idx]);
|
||||
|
||||
/* Process parameter definition from command line. The last
|
||||
@@ -1140,7 +1156,7 @@ int main(int argc, char **argv)
|
||||
|
||||
/* Finally, process all the remaining words on the command
|
||||
line as file names. */
|
||||
for (idx = optind ; idx < argc ; idx += 1)
|
||||
for (int idx = optind ; idx < argc ; idx += 1)
|
||||
process_file_name(argv[idx], 0);
|
||||
|
||||
/* If the use of a default include directory is not
|
||||
@@ -1178,6 +1194,8 @@ int main(int argc, char **argv)
|
||||
|
||||
fprintf(iconfig_file, "iwidth:%u\n", integer_width);
|
||||
|
||||
fprintf(iconfig_file, "widthcap:%u\n", width_cap);
|
||||
|
||||
/* Write the preprocessor command needed to preprocess a
|
||||
single file. This may be used to preprocess library
|
||||
files. */
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
# include <stdlib.h>
|
||||
# include <stdio.h>
|
||||
# include "ivl_alloc.h"
|
||||
# include "globals.h"
|
||||
|
||||
|
||||
char* substitutions(const char*str)
|
||||
|
||||
+28
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2011 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1999-2013 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
|
||||
@@ -32,6 +32,17 @@ NetEAccess* NetEAccess::dup_expr() const
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetEArrayPattern*NetEArrayPattern::dup_expr() const
|
||||
{
|
||||
vector<NetExpr*>tmp (items_.size());
|
||||
for (size_t idx = 0 ; idx < tmp.size() ; idx += 1)
|
||||
tmp[idx] = items_[idx]->dup_expr();
|
||||
|
||||
NetEArrayPattern*res = new NetEArrayPattern(net_type(), tmp);
|
||||
res->set_line(*this);
|
||||
return res;
|
||||
}
|
||||
|
||||
NetEBinary* NetEBinary::dup_expr() const
|
||||
{
|
||||
ivl_assert(*this, 0);
|
||||
@@ -171,6 +182,14 @@ NetEEvent* NetEEvent::dup_expr() const
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetELast* NetELast::dup_expr() const
|
||||
{
|
||||
NetELast*tmp = new NetELast(sig_);
|
||||
ivl_assert(*this, tmp);
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetENetenum* NetENetenum::dup_expr() const
|
||||
{
|
||||
ivl_assert(*this, 0);
|
||||
@@ -207,6 +226,7 @@ NetESelect* NetESelect::dup_expr() const
|
||||
base_? base_->dup_expr() : 0,
|
||||
expr_width(), sel_type_);
|
||||
ivl_assert(*this, tmp);
|
||||
tmp->cast_signed(has_sign());
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
}
|
||||
@@ -226,11 +246,18 @@ NetESFunc* NetESFunc::dup_expr() const
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetEShallowCopy* NetEShallowCopy::dup_expr() const
|
||||
{
|
||||
ivl_assert(*this, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetESignal* NetESignal::dup_expr() const
|
||||
{
|
||||
NetESignal*tmp = new NetESignal(net_, word_);
|
||||
ivl_assert(*this, tmp);
|
||||
tmp->expr_width(expr_width());
|
||||
tmp->cast_signed(has_sign());
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
+1747
-365
File diff suppressed because it is too large
Load Diff
+526
-106
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2012 Stephen Williams (steve@icarus.com)
|
||||
* Copyright CERN 2012 / Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright CERN 2012-2013 / Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -21,10 +21,14 @@
|
||||
# include "config.h"
|
||||
|
||||
# include "PExpr.h"
|
||||
# include "PPackage.h"
|
||||
# include "netlist.h"
|
||||
# include "netmisc.h"
|
||||
# include "netstruct.h"
|
||||
# include "netclass.h"
|
||||
# include "netdarray.h"
|
||||
# include "netparray.h"
|
||||
# include "netvector.h"
|
||||
# include "compiler.h"
|
||||
# include <cstdlib>
|
||||
# include <iostream>
|
||||
@@ -69,7 +73,7 @@
|
||||
* is to try to make a net elaboration, and see if the result is
|
||||
* suitable for assignment.
|
||||
*/
|
||||
NetAssign_* PExpr::elaborate_lval(Design*, NetScope*, bool) const
|
||||
NetAssign_* PExpr::elaborate_lval(Design*, NetScope*, bool, bool) const
|
||||
{
|
||||
NetNet*ll = 0;
|
||||
if (ll == 0) {
|
||||
@@ -97,6 +101,7 @@ NetAssign_* PExpr::elaborate_lval(Design*, NetScope*, bool) const
|
||||
*/
|
||||
NetAssign_* PEConcat::elaborate_lval(Design*des,
|
||||
NetScope*scope,
|
||||
bool is_cassign,
|
||||
bool is_force) const
|
||||
{
|
||||
if (repeat_) {
|
||||
@@ -117,7 +122,8 @@ NetAssign_* PEConcat::elaborate_lval(Design*des,
|
||||
continue;
|
||||
}
|
||||
|
||||
NetAssign_*tmp = parms_[idx]->elaborate_lval(des, scope, is_force);
|
||||
NetAssign_*tmp = parms_[idx]->elaborate_lval(des, scope,
|
||||
is_cassign, is_force);
|
||||
|
||||
/* If the l-value doesn't elaborate, the error was
|
||||
already detected and printed. We just skip it and let
|
||||
@@ -144,12 +150,51 @@ NetAssign_* PEConcat::elaborate_lval(Design*des,
|
||||
return res;
|
||||
}
|
||||
|
||||
NetAssign_*PEIdent::scan_lname_for_nested_members_(Design*des, NetScope*scope,
|
||||
const pform_name_t&cur_path) const
|
||||
{
|
||||
if (cur_path.size() == 1)
|
||||
return 0;
|
||||
|
||||
pform_name_t use_path = cur_path;
|
||||
perm_string tmp_name = peek_tail_name(use_path);
|
||||
use_path.pop_back();
|
||||
|
||||
NetNet* reg = 0;
|
||||
const NetExpr*par = 0;
|
||||
NetEvent* eve = 0;
|
||||
symbol_search(this, des, scope, use_path, reg, par, eve);
|
||||
|
||||
if (reg == 0) {
|
||||
NetAssign_*tmp = scan_lname_for_nested_members_(des, scope, use_path);
|
||||
if (tmp == 0)
|
||||
return 0;
|
||||
|
||||
tmp = new NetAssign_(tmp);
|
||||
tmp->set_property(tmp_name);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
if (reg->struct_type()) {
|
||||
cerr << get_fileline() << ": sorry: "
|
||||
<< "I don't know what to do with struct " << use_path << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (reg->class_type()) {
|
||||
return elaborate_lval_net_class_member_(des, scope, reg, tmp_name);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle the ident as an l-value. This includes bit and part selects
|
||||
* of that ident.
|
||||
*/
|
||||
NetAssign_* PEIdent::elaborate_lval(Design*des,
|
||||
NetScope*scope,
|
||||
bool is_cassign,
|
||||
bool is_force) const
|
||||
{
|
||||
NetNet* reg = 0;
|
||||
@@ -157,7 +202,26 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
||||
NetEvent* eve = 0;
|
||||
perm_string method_name;
|
||||
|
||||
symbol_search(this, des, scope, path_, reg, par, eve);
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PEIdent::elaborate_lval: "
|
||||
<< "Elaborate l-value ident expression: " << *this << endl;
|
||||
}
|
||||
|
||||
/* Try to detect the special case that we are in a method and
|
||||
the identifier is a member of the class. */
|
||||
if (NetAssign_*tmp = elaborate_lval_method_class_member_(des, scope))
|
||||
return tmp;
|
||||
|
||||
/* Normally find the name in the passed scope. But if this is
|
||||
imported from a package, then located the variable from the
|
||||
package scope. */
|
||||
NetScope*use_scope = scope;
|
||||
if (package_) {
|
||||
use_scope = des->find_package(package_->pscope_name());
|
||||
ivl_assert(*this, use_scope);
|
||||
}
|
||||
|
||||
symbol_search(this, des, use_scope, path_, reg, par, eve);
|
||||
|
||||
/* If the signal is not found, check to see if this is a
|
||||
member of a struct. Take the name of the form "a.b.member",
|
||||
@@ -167,7 +231,7 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
||||
pform_name_t use_path = path_;
|
||||
perm_string tmp_name = peek_tail_name(use_path);
|
||||
use_path.pop_back();
|
||||
symbol_search(this, des, scope, use_path, reg, par, eve);
|
||||
symbol_search(this, des, use_scope, use_path, reg, par, eve);
|
||||
|
||||
if (reg && reg->struct_type()) {
|
||||
method_name = tmp_name;
|
||||
@@ -175,21 +239,39 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
||||
} else if (reg && reg->class_type()) {
|
||||
method_name = tmp_name;
|
||||
|
||||
} else if (NetAssign_*subl = scan_lname_for_nested_members_(des, use_scope, path_)) {
|
||||
return subl;
|
||||
|
||||
} else {
|
||||
reg = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (reg == 0) {
|
||||
cerr << get_fileline() << ": error: Could not find variable ``"
|
||||
<< path_ << "'' in ``" << scope_path(scope) <<
|
||||
"''" << endl;
|
||||
|
||||
if (use_scope->type()==NetScope::FUNC
|
||||
&& use_scope->func_def()->return_sig()==0
|
||||
&& use_scope->basename()==peek_tail_name(path_)) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< "Cannot assign to " << path_
|
||||
<< " because function " << scope_path(use_scope)
|
||||
<< " is void." << endl;
|
||||
} else {
|
||||
cerr << get_fileline() << ": error: Could not find variable ``"
|
||||
<< path_ << "'' in ``" << scope_path(use_scope) <<
|
||||
"''" << endl;
|
||||
}
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ivl_assert(*this, reg);
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PEIdent::elaborate_lval: "
|
||||
<< "Found l-value as reg."
|
||||
<< " unpacked_dimensions()=" << reg->unpacked_dimensions() << endl;
|
||||
}
|
||||
|
||||
// We are processing the tail of a string of names. For
|
||||
// example, the verilog may be "a.b.c", so we are processing
|
||||
// "c" at this point. (Note that if method_name is not nil,
|
||||
@@ -220,9 +302,11 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
||||
/* Get the signal referenced by the identifier, and make sure
|
||||
it is a register. Wires are not allowed in this context,
|
||||
unless this is the l-value of a force. */
|
||||
if ((reg->type() != NetNet::REG) && !is_force) {
|
||||
if ((reg->type() != NetNet::REG)
|
||||
&& (reg->type() != NetNet::UNRESOLVED_WIRE)
|
||||
&& !is_force) {
|
||||
cerr << get_fileline() << ": error: " << path_ <<
|
||||
" is not a valid l-value in " << scope_path(scope) <<
|
||||
" is not a valid l-value in " << scope_path(use_scope) <<
|
||||
"." << endl;
|
||||
cerr << reg->get_fileline() << ": : " << path_ <<
|
||||
" is declared here as " << reg->type() << "." << endl;
|
||||
@@ -232,13 +316,12 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
||||
|
||||
if (reg->struct_type() && !method_name.nil()) {
|
||||
NetAssign_*lv = new NetAssign_(reg);
|
||||
elaborate_lval_net_packed_member_(des, scope, lv, method_name);
|
||||
elaborate_lval_net_packed_member_(des, use_scope, lv, method_name);
|
||||
return lv;
|
||||
}
|
||||
|
||||
if (reg->class_type() && !method_name.nil() && gn_system_verilog()) {
|
||||
NetAssign_*lv = new NetAssign_(reg);
|
||||
elaborate_lval_net_class_member_(des, scope, lv, method_name);
|
||||
NetAssign_*lv = elaborate_lval_net_class_member_(des, use_scope, reg, method_name);
|
||||
return lv;
|
||||
}
|
||||
|
||||
@@ -246,8 +329,10 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
||||
// where the name is a member/method of a struct/class.
|
||||
ivl_assert(*this, method_name.nil());
|
||||
|
||||
bool need_const_idx = is_cassign || is_force || (reg->type()==NetNet::UNRESOLVED_WIRE);
|
||||
|
||||
if (reg->unpacked_dimensions() > 0)
|
||||
return elaborate_lval_net_word_(des, scope, reg);
|
||||
return elaborate_lval_net_word_(des, scope, reg, need_const_idx);
|
||||
|
||||
// This must be after the array word elaboration above!
|
||||
if (reg->get_scalar() &&
|
||||
@@ -269,7 +354,7 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
||||
if (use_sel == index_component_t::SEL_IDX_UP ||
|
||||
use_sel == index_component_t::SEL_IDX_DO) {
|
||||
NetAssign_*lv = new NetAssign_(reg);
|
||||
elaborate_lval_net_idx_(des, scope, lv, use_sel);
|
||||
elaborate_lval_net_idx_(des, scope, lv, use_sel, need_const_idx);
|
||||
return lv;
|
||||
}
|
||||
|
||||
@@ -281,13 +366,21 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
||||
return lv;
|
||||
} else {
|
||||
NetAssign_*lv = new NetAssign_(reg);
|
||||
elaborate_lval_net_bit_(des, scope, lv);
|
||||
elaborate_lval_net_bit_(des, scope, lv, need_const_idx);
|
||||
return lv;
|
||||
}
|
||||
}
|
||||
|
||||
ivl_assert(*this, use_sel == index_component_t::SEL_NONE);
|
||||
|
||||
if (reg->type()==NetNet::UNRESOLVED_WIRE && !is_force) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< path_ << " Unable to assign to unresolved wires."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* No select expressions. */
|
||||
|
||||
NetAssign_*lv = new NetAssign_(reg);
|
||||
@@ -295,13 +388,138 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
||||
return lv;
|
||||
}
|
||||
|
||||
NetAssign_* PEIdent::elaborate_lval_method_class_member_(Design*des,
|
||||
NetScope*scope) const
|
||||
{
|
||||
if (!gn_system_verilog())
|
||||
return 0;
|
||||
if (scope->parent() == 0)
|
||||
return 0;
|
||||
if (path_.size() != 1)
|
||||
return 0;
|
||||
|
||||
const netclass_t*class_type = find_class_containing_scope(*this, scope);
|
||||
if (class_type == 0)
|
||||
return 0;
|
||||
|
||||
const name_component_t&name_comp = path_.back();
|
||||
|
||||
perm_string member_name = name_comp.name;
|
||||
int pidx = class_type->property_idx_from_name(member_name);
|
||||
if (pidx < 0)
|
||||
return 0;
|
||||
|
||||
NetScope*scope_method = find_method_containing_scope(*this, scope);
|
||||
ivl_assert(*this, scope_method);
|
||||
|
||||
NetNet*this_net = scope_method->find_signal(perm_string::literal("@"));
|
||||
if (this_net == 0) {
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<< "Unable to find 'this' port of " << scope_path(scope_method)
|
||||
<< "." << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PEIdent::elaborate_lval_method_class_member_: "
|
||||
<< "Ident " << member_name
|
||||
<< " is a property of class " << class_type->get_name() << endl;
|
||||
}
|
||||
|
||||
NetExpr*canon_index = 0;
|
||||
if (! name_comp.index.empty()) {
|
||||
ivl_type_t property_type = class_type->get_prop_type(pidx);
|
||||
|
||||
if (const netsarray_t* stype = dynamic_cast<const netsarray_t*> (property_type)) {
|
||||
canon_index = make_canonical_index(des, scope, this,
|
||||
name_comp.index, stype, false);
|
||||
|
||||
} else {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< "Index expressions don't apply to this type of property." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Detect assignment to constant properties. Note that the
|
||||
// initializer constructor MAY assign to constant properties,
|
||||
// as this is how the property gets its value.
|
||||
property_qualifier_t qual = class_type->get_prop_qual(pidx);
|
||||
if (qual.test_const()) {
|
||||
if (class_type->get_prop_initialized(pidx)) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< "Property " << class_type->get_prop_name(pidx)
|
||||
<< " is constant in this method."
|
||||
<< " (scope=" << scope_path(scope) << ")" << endl;
|
||||
des->errors += 1;
|
||||
|
||||
} else if (scope->basename()!="new" && scope->basename()!="new@") {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< "Property " << class_type->get_prop_name(pidx)
|
||||
<< " is constant in this method."
|
||||
<< " (scope=" << scope_path(scope) << ")" << endl;
|
||||
des->errors += 1;
|
||||
|
||||
} else {
|
||||
|
||||
// Mark this property as initialized. This is used
|
||||
// to know that we have initialized the constant
|
||||
// object so the next assignment will be marked as
|
||||
// illegal.
|
||||
class_type->set_prop_initialized(pidx);
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PEIdent::elaborate_lval_method_class_member_: "
|
||||
<< "Found initialzers for property " << class_type->get_prop_name(pidx) << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ivl_type_t tmp_type = class_type->get_prop_type(pidx);
|
||||
if (const netuarray_t*tmp_ua = dynamic_cast<const netuarray_t*>(tmp_type)) {
|
||||
|
||||
const std::vector<netrange_t>&dims = tmp_ua->static_dimensions();
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PEIdent::elaborate_lval_method_class_member_: "
|
||||
<< "Property " << class_type->get_prop_name(pidx)
|
||||
<< " has " << dims.size() << " dimensions, "
|
||||
<< " got " << name_comp.index.size() << " indices." << endl;
|
||||
if (canon_index) {
|
||||
cerr << get_fileline() << ": PEIdent::elaborate_lval_method_class_member_: "
|
||||
<< "Canonical index is:" << *canon_index << endl;
|
||||
};
|
||||
}
|
||||
|
||||
if (dims.size() != name_comp.index.size()) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< "Got " << name_comp.index.size() << " indices, "
|
||||
<< "expecting " << dims.size()
|
||||
<< " to index the property " << class_type->get_prop_name(pidx) << "." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
}
|
||||
|
||||
NetAssign_*this_lval = new NetAssign_(this_net);
|
||||
this_lval->set_property(member_name);
|
||||
if (canon_index) this_lval->set_word(canon_index);
|
||||
|
||||
return this_lval;
|
||||
}
|
||||
|
||||
NetAssign_* PEIdent::elaborate_lval_net_word_(Design*des,
|
||||
NetScope*scope,
|
||||
NetNet*reg) const
|
||||
NetNet*reg,
|
||||
bool need_const_idx) const
|
||||
{
|
||||
const name_component_t&name_tail = path_.back();
|
||||
ivl_assert(*this, !name_tail.index.empty());
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PEIdent::elaborate_lval_net_word_: "
|
||||
<< "Handle as n-dimensional array." << endl;
|
||||
}
|
||||
|
||||
if (name_tail.index.size() < reg->unpacked_dimensions()) {
|
||||
cerr << get_fileline() << ": error: Array " << reg->name()
|
||||
<< " needs " << reg->unpacked_dimensions() << " indices,"
|
||||
@@ -310,6 +528,8 @@ NetAssign_* PEIdent::elaborate_lval_net_word_(Design*des,
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned array_need_words = reg->unpacked_count();
|
||||
|
||||
// Make sure there are enough indices to address an array element.
|
||||
const index_component_t&index_head = name_tail.index.front();
|
||||
if (index_head.sel == index_component_t::SEL_PART) {
|
||||
@@ -324,30 +544,62 @@ NetAssign_* PEIdent::elaborate_lval_net_word_(Design*des,
|
||||
// "unpacked_indices" array.
|
||||
list<NetExpr*>unpacked_indices;
|
||||
list<long> unpacked_indices_const;
|
||||
bool flag = indices_to_expressions(des, scope, this,
|
||||
name_tail.index, reg->unpacked_dimensions(),
|
||||
false,
|
||||
unpacked_indices,
|
||||
unpacked_indices_const);
|
||||
indices_flags flags;
|
||||
indices_to_expressions(des, scope, this,
|
||||
name_tail.index, reg->unpacked_dimensions(),
|
||||
false, array_need_words,
|
||||
flags,
|
||||
unpacked_indices,
|
||||
unpacked_indices_const);
|
||||
|
||||
NetExpr*canon_index = 0;
|
||||
if (flag) {
|
||||
ivl_assert(*this, unpacked_indices_const.size() == reg->unpacked_dimensions());
|
||||
canon_index = normalize_variable_unpacked(reg, unpacked_indices_const);
|
||||
if (canon_index == 0) {
|
||||
cerr << get_fileline() << ": warning: "
|
||||
<< "ignoring out of bounds l-value array access " << reg->name();
|
||||
for (list<long>::const_iterator cur = unpacked_indices_const.begin()
|
||||
; cur != unpacked_indices_const.end() ; ++cur) {
|
||||
cerr << "[" << *cur << "]";
|
||||
}
|
||||
cerr << "." << endl;
|
||||
if (flags.invalid) {
|
||||
// Nothing to do.
|
||||
|
||||
} else if (flags.undefined) {
|
||||
cerr << get_fileline() << ": warning: "
|
||||
<< "ignoring undefined l-value array access "
|
||||
<< reg->name() << as_indices(unpacked_indices)
|
||||
<< "." << endl;
|
||||
|
||||
} else if (flags.variable) {
|
||||
if (need_const_idx) {
|
||||
cerr << get_fileline() << ": error: array '" << reg->name()
|
||||
<< "' index must be a constant in this context." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
ivl_assert(*this, unpacked_indices.size() == reg->unpacked_dimensions());
|
||||
canon_index = normalize_variable_unpacked(reg, unpacked_indices);
|
||||
|
||||
} else {
|
||||
ivl_assert(*this, unpacked_indices_const.size() == reg->unpacked_dimensions());
|
||||
canon_index = normalize_variable_unpacked(reg, unpacked_indices_const);
|
||||
|
||||
if (canon_index == 0) {
|
||||
cerr << get_fileline() << ": warning: "
|
||||
<< "ignoring out of bounds l-value array access "
|
||||
<< reg->name() << as_indices(unpacked_indices_const)
|
||||
<< "." << endl;
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure invalid array accesses are ignored.
|
||||
if (canon_index == 0)
|
||||
canon_index = new NetEConst(verinum(verinum::Vx));
|
||||
canon_index->set_line(*this);
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PEIdent::elaborate_lval_net_word_: "
|
||||
<< "canon_index=" << *canon_index << endl;
|
||||
}
|
||||
|
||||
if (reg->type()==NetNet::UNRESOLVED_WIRE) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< "Unable to assign words of unresolved wire array." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetAssign_*lv = new NetAssign_(reg);
|
||||
lv->set_word(canon_index);
|
||||
@@ -368,27 +620,28 @@ NetAssign_* PEIdent::elaborate_lval_net_word_(Design*des,
|
||||
if (reg->data_type() == IVL_VT_REAL) cerr << "real";
|
||||
else cerr << "scalar";
|
||||
cerr << " array word: " << reg->name()
|
||||
<< "[" << *canon_index << "]" << endl;
|
||||
<< as_indices(unpacked_indices) << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (use_sel == index_component_t::SEL_BIT)
|
||||
elaborate_lval_net_bit_(des, scope, lv);
|
||||
elaborate_lval_net_bit_(des, scope, lv, need_const_idx);
|
||||
|
||||
if (use_sel == index_component_t::SEL_PART)
|
||||
elaborate_lval_net_part_(des, scope, lv);
|
||||
|
||||
if (use_sel == index_component_t::SEL_IDX_UP ||
|
||||
use_sel == index_component_t::SEL_IDX_DO)
|
||||
elaborate_lval_net_idx_(des, scope, lv, use_sel);
|
||||
elaborate_lval_net_idx_(des, scope, lv, use_sel, need_const_idx);
|
||||
|
||||
return lv;
|
||||
}
|
||||
|
||||
bool PEIdent::elaborate_lval_net_bit_(Design*des,
|
||||
NetScope*scope,
|
||||
NetAssign_*lv) const
|
||||
NetAssign_*lv,
|
||||
bool need_const_idx) const
|
||||
{
|
||||
list<long>prefix_indices;
|
||||
bool rc = calculate_packed_indices_(des, scope, lv->sig(), prefix_indices);
|
||||
@@ -402,6 +655,7 @@ bool PEIdent::elaborate_lval_net_bit_(Design*des,
|
||||
ivl_assert(*this, index_tail.lsb == 0);
|
||||
|
||||
NetNet*reg = lv->sig();
|
||||
ivl_assert(*this, reg);
|
||||
|
||||
// Bit selects have a single select expression. Evaluate the
|
||||
// constant value and treat it as a part select with a bit
|
||||
@@ -410,10 +664,47 @@ bool PEIdent::elaborate_lval_net_bit_(Design*des,
|
||||
long lsb = 0;
|
||||
|
||||
if (NetEConst*index_con = dynamic_cast<NetEConst*> (mux)) {
|
||||
lsb = index_con->value().as_long();
|
||||
mux = 0;
|
||||
// The index has a constant defined value.
|
||||
if (index_con->value().is_defined()) {
|
||||
lsb = index_con->value().as_long();
|
||||
mux = 0;
|
||||
// The index is undefined and this is a packed array.
|
||||
} else if (prefix_indices.size()+2 <= reg->packed_dims().size()) {
|
||||
long loff;
|
||||
unsigned long lwid;
|
||||
bool rcl = reg->sb_to_slice(prefix_indices, lsb, loff, lwid);
|
||||
ivl_assert(*this, rcl);
|
||||
cerr << get_fileline() << ": warning: L-value packed array "
|
||||
<< "select of " << reg->name();
|
||||
if (reg->unpacked_dimensions() > 0) cerr << "[]";
|
||||
cerr << " has an undefined index." << endl;
|
||||
|
||||
lv->set_part(new NetEConst(verinum(verinum::Vx)), lwid);
|
||||
return true;
|
||||
// The index is undefined and this is a bit select.
|
||||
} else {
|
||||
cerr << get_fileline() << ": warning: L-value bit select of "
|
||||
<< reg->name();
|
||||
if (reg->unpacked_dimensions() > 0) cerr << "[]";
|
||||
cerr << " has an undefined index." << endl;
|
||||
|
||||
lv->set_part(new NetEConst(verinum(verinum::Vx)), 1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (debug_elaborate && (reg->type()==NetNet::UNRESOLVED_WIRE)) {
|
||||
cerr << get_fileline() << ": PEIdent::elaborate_lval_net_bit_: "
|
||||
<< "Try to assign bits of unresolved wire."
|
||||
<< endl;
|
||||
}
|
||||
|
||||
// Notice that we might be assigning to an unresolved wire. This
|
||||
// can happen if we are actually assigning to a variable that
|
||||
// has a partial continuous assignment to it. If that is the
|
||||
// case, then the bit select must be constant.
|
||||
ivl_assert(*this, need_const_idx || (reg->type()!=NetNet::UNRESOLVED_WIRE));
|
||||
|
||||
|
||||
if (prefix_indices.size()+2 <= reg->packed_dims().size()) {
|
||||
// Special case: this is a slice of a multi-dimensional
|
||||
@@ -429,8 +720,19 @@ bool PEIdent::elaborate_lval_net_bit_(Design*des,
|
||||
bool rcl = reg->sb_to_slice(prefix_indices, lsb, loff, lwid);
|
||||
ivl_assert(*this, rcl);
|
||||
|
||||
if (reg->type()==NetNet::UNRESOLVED_WIRE) {
|
||||
bool rct = reg->test_and_set_part_driver(loff+lwid-1, loff);
|
||||
if (rct) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< "These bits are already driven." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
}
|
||||
|
||||
lv->set_part(new NetEConst(verinum(loff)), lwid);
|
||||
|
||||
} else {
|
||||
ivl_assert(*this, reg->type()!=NetNet::UNRESOLVED_WIRE);
|
||||
unsigned long lwid;
|
||||
mux = normalize_variable_slice_base(prefix_indices, mux,
|
||||
reg, lwid);
|
||||
@@ -438,6 +740,7 @@ bool PEIdent::elaborate_lval_net_bit_(Design*des,
|
||||
}
|
||||
|
||||
} else if (reg->data_type() == IVL_VT_STRING) {
|
||||
ivl_assert(*this, reg->type()!=NetNet::UNRESOLVED_WIRE);
|
||||
// Special case: This is a select of a string
|
||||
// variable. The target of the assignment is a character
|
||||
// select of a string. Force the r-value to be an 8bit
|
||||
@@ -454,9 +757,18 @@ bool PEIdent::elaborate_lval_net_bit_(Design*des,
|
||||
lv->set_part(new NetEConst(verinum(lsb)), 8);
|
||||
|
||||
} else if (mux) {
|
||||
ivl_assert(*this, reg->type()!=NetNet::UNRESOLVED_WIRE);
|
||||
|
||||
// Non-constant bit mux. Correct the mux for the range
|
||||
// of the vector, then set the l-value part select
|
||||
// expression.
|
||||
if (need_const_idx) {
|
||||
cerr << get_fileline() << ": error: '" << reg->name()
|
||||
<< "' bit select must be a constant in this context."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
mux = normalize_variable_bit_base(prefix_indices, mux, reg);
|
||||
lv->set_part(mux, 1);
|
||||
|
||||
@@ -464,6 +776,10 @@ bool PEIdent::elaborate_lval_net_bit_(Design*des,
|
||||
// Constant bit mux that happens to select the only bit
|
||||
// of the l-value. Don't bother with any select at all.
|
||||
|
||||
// NOTE: Don't know what to do about unresolved wires
|
||||
// here, but they are probably wrong.
|
||||
ivl_assert(*this, reg->type()!=NetNet::UNRESOLVED_WIRE);
|
||||
|
||||
} else {
|
||||
// Constant bit select that does something useful.
|
||||
long loff = reg->sb_to_idx(prefix_indices,lsb);
|
||||
@@ -476,6 +792,15 @@ bool PEIdent::elaborate_lval_net_bit_(Design*des,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (reg->type()==NetNet::UNRESOLVED_WIRE) {
|
||||
bool rct = reg->test_and_set_part_driver(loff, loff);
|
||||
if (rct) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< "Bit " << loff << " is already driven." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
}
|
||||
|
||||
lv->set_part(new NetEConst(verinum(loff)), 1);
|
||||
}
|
||||
|
||||
@@ -490,6 +815,14 @@ bool PEIdent::elaborate_lval_darray_bit_(Design*des, NetScope*scope, NetAssign_*
|
||||
// For now, only support single-dimension dynamic arrays.
|
||||
ivl_assert(*this, name_tail.index.size() == 1);
|
||||
|
||||
if (lv->sig()->type()==NetNet::UNRESOLVED_WIRE) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< path_ << " Unable to darray word select unresolved wires."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
const index_component_t&index_tail = name_tail.index.back();
|
||||
ivl_assert(*this, index_tail.msb != 0);
|
||||
ivl_assert(*this, index_tail.lsb == 0);
|
||||
@@ -516,35 +849,69 @@ bool PEIdent::elaborate_lval_net_part_(Design*des,
|
||||
long msb, lsb;
|
||||
bool parts_defined_flag;
|
||||
bool flag = calculate_parts_(des, scope, msb, lsb, parts_defined_flag);
|
||||
if (!flag)
|
||||
return false;
|
||||
|
||||
ivl_assert(*this, parts_defined_flag);
|
||||
if (!flag) return false;
|
||||
|
||||
NetNet*reg = lv->sig();
|
||||
ivl_assert(*this, reg);
|
||||
|
||||
const vector<netrange_t>&packed = reg->packed_dims();
|
||||
|
||||
// Part selects cannot select slices. So there must be enough
|
||||
// prefix_indices to get all the way to the final dimension.
|
||||
if (prefix_indices.size()+1 < packed.size()) {
|
||||
cerr << get_fileline() << ": error: Cannot select a range "
|
||||
<< "of slices from a packed array." << endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
if (! parts_defined_flag) {
|
||||
cerr << get_fileline() << ": warning: L-value part select of "
|
||||
<< reg->name();
|
||||
if (reg->unpacked_dimensions() > 0) cerr << "[]";
|
||||
cerr << " has an undefined index." << endl;
|
||||
// Use a width of two here so we can distinguish between an
|
||||
// undefined bit or part select.
|
||||
lv->set_part(new NetEConst(verinum(verinum::Vx)), 2);
|
||||
return true;
|
||||
}
|
||||
|
||||
long loff = reg->sb_to_idx(prefix_indices,lsb);
|
||||
long moff = reg->sb_to_idx(prefix_indices,msb);
|
||||
long wid = moff - loff + 1;
|
||||
if (reg->type()==NetNet::UNRESOLVED_WIRE) {
|
||||
bool rct = reg->test_and_set_part_driver(msb, lsb);
|
||||
if (rct) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< path_ << "Part select is double-driving unresolved wire."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (moff < loff) {
|
||||
cerr << get_fileline() << ": error: part select "
|
||||
<< reg->name() << "[" << msb<<":"<<lsb<<"]"
|
||||
<< " is reversed." << endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
const vector<netrange_t>&packed = reg->packed_dims();
|
||||
|
||||
long loff, moff;
|
||||
long wid;
|
||||
if (prefix_indices.size()+1 < packed.size()) {
|
||||
// If there are fewer indices then there are packed
|
||||
// dimensions, then this is a range of slices. Calculate
|
||||
// it into a big slice.
|
||||
bool lrc;
|
||||
unsigned long tmp_lwid, tmp_mwid;
|
||||
lrc = reg->sb_to_slice(prefix_indices,lsb, loff, tmp_lwid);
|
||||
ivl_assert(*this, lrc);
|
||||
lrc = reg->sb_to_slice(prefix_indices,msb, moff, tmp_mwid);
|
||||
ivl_assert(*this, lrc);
|
||||
|
||||
if (loff < moff) {
|
||||
moff = moff + tmp_mwid - 1;
|
||||
} else {
|
||||
long ltmp = moff;
|
||||
moff = loff + tmp_lwid - 1;
|
||||
loff = ltmp;
|
||||
}
|
||||
wid = moff - loff + 1;
|
||||
|
||||
} else {
|
||||
loff = reg->sb_to_idx(prefix_indices,lsb);
|
||||
moff = reg->sb_to_idx(prefix_indices,msb);
|
||||
wid = moff - loff + 1;
|
||||
|
||||
if (moff < loff) {
|
||||
cerr << get_fileline() << ": error: part select "
|
||||
<< reg->name() << "[" << msb<<":"<<lsb<<"]"
|
||||
<< " is reversed." << endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Special case: The range winds up selecting the entire
|
||||
@@ -572,7 +939,8 @@ bool PEIdent::elaborate_lval_net_part_(Design*des,
|
||||
bool PEIdent::elaborate_lval_net_idx_(Design*des,
|
||||
NetScope*scope,
|
||||
NetAssign_*lv,
|
||||
index_component_t::ctype_t use_sel) const
|
||||
index_component_t::ctype_t use_sel,
|
||||
bool need_const_idx) const
|
||||
{
|
||||
list<long>prefix_indices;
|
||||
bool rc = calculate_packed_indices_(des, scope, lv->sig(), prefix_indices);
|
||||
@@ -588,16 +956,6 @@ bool PEIdent::elaborate_lval_net_idx_(Design*des,
|
||||
NetNet*reg = lv->sig();
|
||||
assert(reg);
|
||||
|
||||
if (reg->type() != NetNet::REG) {
|
||||
cerr << get_fileline() << ": error: " << path_ <<
|
||||
" is not a reg/integer/time in " << scope_path(scope) <<
|
||||
"." << endl;
|
||||
cerr << reg->get_fileline() << ": : " << path_ <<
|
||||
" is declared here as " << reg->type() << "." << endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned long wid;
|
||||
calculate_up_do_width_(des, scope, wid);
|
||||
|
||||
@@ -654,19 +1012,19 @@ bool PEIdent::elaborate_lval_net_idx_(Design*des,
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (warn_ob_select) {
|
||||
cerr << get_fileline() << ": warning: " << reg->name();
|
||||
if (reg->unpacked_dimensions() > 0) cerr << "[]";
|
||||
cerr << "['bx";
|
||||
if (use_sel == index_component_t::SEL_IDX_UP) {
|
||||
cerr << "+:";
|
||||
} else {
|
||||
cerr << "-:";
|
||||
}
|
||||
cerr << wid << "] is always outside vector." << endl;
|
||||
}
|
||||
cerr << get_fileline() << ": warning: L-value indexed part "
|
||||
<< "select of " << reg->name();
|
||||
if (reg->unpacked_dimensions() > 0) cerr << "[]";
|
||||
cerr << " has an undefined base." << endl;
|
||||
}
|
||||
} else {
|
||||
if (need_const_idx) {
|
||||
cerr << get_fileline() << ": error: '" << reg->name()
|
||||
<< "' base index must be a constant in this context."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
ivl_assert(*this, prefix_indices.size()+1 == reg->packed_dims().size());
|
||||
/* Correct the mux for the range of the vector. */
|
||||
if (use_sel == index_component_t::SEL_IDX_UP) {
|
||||
@@ -690,31 +1048,70 @@ bool PEIdent::elaborate_lval_net_idx_(Design*des,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PEIdent::elaborate_lval_net_class_member_(Design*des, NetScope*,
|
||||
NetAssign_*lv,
|
||||
const perm_string&method_name) const
|
||||
NetAssign_* PEIdent::elaborate_lval_net_class_member_(Design*des, NetScope*scope,
|
||||
NetNet*sig, const perm_string&method_name) const
|
||||
{
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": elaborate_lval_net_class_member_: "
|
||||
<< "l-value is property " << method_name
|
||||
<< " of " << lv->sig()->name() << "." << endl;
|
||||
<< " of " << sig->name() << "." << endl;
|
||||
}
|
||||
|
||||
netclass_t*class_type = lv->sig()->class_type();
|
||||
const netclass_t*class_type = sig->class_type();
|
||||
ivl_assert(*this, class_type);
|
||||
|
||||
/* Make sure the property is really present in the class. If
|
||||
not, then generate an error message and return an error. */
|
||||
const ivl_type_s*ptype = class_type->get_property(method_name);
|
||||
if (ptype == 0) {
|
||||
int pidx = class_type->property_idx_from_name(method_name);
|
||||
if (pidx < 0) {
|
||||
cerr << get_fileline() << ": error: Class " << class_type->get_name()
|
||||
<< " does not have a property " << method_name << "." << endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
property_qualifier_t qual = class_type->get_prop_qual(pidx);
|
||||
if (qual.test_local() && ! class_type->test_scope_is_method(scope)) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< "Local property " << class_type->get_prop_name(pidx)
|
||||
<< " is not accessible (l-value) in this context."
|
||||
<< " (scope=" << scope_path(scope) << ")" << endl;
|
||||
des->errors += 1;
|
||||
|
||||
} else if (qual.test_static()) {
|
||||
|
||||
// Special case: this is a static property. Ignore the
|
||||
// "this" sig and use the property itself, which is not
|
||||
// part of the sig, as the l-value.
|
||||
NetNet*psig = class_type->find_static_property(method_name);
|
||||
ivl_assert(*this, psig);
|
||||
|
||||
NetAssign_*lv = new NetAssign_(psig);
|
||||
return lv;
|
||||
|
||||
} else if (qual.test_const()) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< "Property " << class_type->get_prop_name(pidx)
|
||||
<< " is constant in this context." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
NetAssign_*lv = new NetAssign_(sig);
|
||||
lv->set_property(method_name);
|
||||
return true;
|
||||
|
||||
ivl_type_t ptype = class_type->get_prop_type(pidx);
|
||||
const netdarray_t*mtype = dynamic_cast<const netdarray_t*> (ptype);
|
||||
if (mtype) {
|
||||
const name_component_t&name_tail = path_.back();
|
||||
if (! name_tail.index.empty()) {
|
||||
cerr << get_fileline() << ": sorry: "
|
||||
<< "Array index of array properties not supported."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
}
|
||||
|
||||
return lv;
|
||||
}
|
||||
|
||||
|
||||
@@ -760,7 +1157,9 @@ bool PEIdent::elaborate_lval_net_packed_member_(Design*des, NetScope*scope,
|
||||
|
||||
// Calculate the offset within the packed structure of the
|
||||
// member, and any indices. We will add in the offset of the
|
||||
// struct into the packed array later.
|
||||
// struct into the packed array later. Note that this works
|
||||
// for packed unions as well (although the offset will be 0
|
||||
// for union members).
|
||||
unsigned long off;
|
||||
const netstruct_t::member_t* member = struct_type->packed_member(member_name, off);
|
||||
|
||||
@@ -771,13 +1170,7 @@ bool PEIdent::elaborate_lval_net_packed_member_(Design*des, NetScope*scope,
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned long use_width = member->width();
|
||||
|
||||
if (name_tail.index.size() > member->packed_dims.size()) {
|
||||
cerr << get_fileline() << ": error: Too many index expressions for member." << endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
unsigned long use_width = member->net_type->packed_width();
|
||||
|
||||
// Get the index component type. At this point, we only
|
||||
// support bit select or none.
|
||||
@@ -788,6 +1181,25 @@ bool PEIdent::elaborate_lval_net_packed_member_(Design*des, NetScope*scope,
|
||||
ivl_assert(*this, use_sel == index_component_t::SEL_NONE || use_sel == index_component_t::SEL_BIT);
|
||||
|
||||
if (! name_tail.index.empty()) {
|
||||
|
||||
// If there are index expressions in this l-value
|
||||
// expression, then the implicit assumption is that the
|
||||
// member is a vector type with packed dimensions. For
|
||||
// example, if the l-value expression is "foo.member[1][2]",
|
||||
// then the member should be something like:
|
||||
// ... logic [h:l][m:n] foo;
|
||||
// Get the dimensions from the netvector_t that this implies.
|
||||
const netvector_t*mem_vec = dynamic_cast<const netvector_t*>(member->net_type);
|
||||
ivl_assert(*this, mem_vec);
|
||||
const vector<netrange_t>&mem_packed_dims = mem_vec->packed_dims();
|
||||
|
||||
if (name_tail.index.size() > mem_packed_dims.size()) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< "Too many index expressions for member." << endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Evaluate all but the last index expression, into prefix_indices.
|
||||
list<long>prefix_indices;
|
||||
bool rc = evaluate_index_prefix(des, scope, prefix_indices, name_tail.index);
|
||||
@@ -809,13 +1221,13 @@ bool PEIdent::elaborate_lval_net_packed_member_(Design*des, NetScope*scope,
|
||||
// offset and width of the addressed slice of the member.
|
||||
long loff;
|
||||
unsigned long lwid;
|
||||
prefix_to_slice(member->packed_dims, prefix_indices, tmp, loff, lwid);
|
||||
prefix_to_slice(mem_packed_dims, prefix_indices, tmp, loff, lwid);
|
||||
|
||||
off += loff;
|
||||
use_width = lwid;
|
||||
}
|
||||
|
||||
// The dimenions in the expression must match the packed
|
||||
// The dimensions in the expression must match the packed
|
||||
// dimensions that are declared for the variable. For example,
|
||||
// if foo is a packed array of struct, then this expression
|
||||
// must be "b[n][m]" with the right number of dimensions to
|
||||
@@ -844,6 +1256,14 @@ bool PEIdent::elaborate_lval_net_packed_member_(Design*des, NetScope*scope,
|
||||
packed_base = 0;
|
||||
}
|
||||
|
||||
if (reg->type()==NetNet::UNRESOLVED_WIRE) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< path_ << " Unable to member-select unresolved wires."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (packed_base == 0) {
|
||||
lv->set_part(new NetEConst(verinum(off)), use_width);
|
||||
return true;
|
||||
@@ -857,7 +1277,7 @@ bool PEIdent::elaborate_lval_net_packed_member_(Design*des, NetScope*scope,
|
||||
return false;
|
||||
}
|
||||
|
||||
NetAssign_* PENumber::elaborate_lval(Design*des, NetScope*, bool) const
|
||||
NetAssign_* PENumber::elaborate_lval(Design*des, NetScope*, bool, bool) const
|
||||
{
|
||||
cerr << get_fileline() << ": error: Constant values not allowed "
|
||||
<< "in l-value expressions." << endl;
|
||||
|
||||
+165
-41
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2012 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright CERN 2012 / Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
@@ -255,7 +255,7 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
|
||||
} else {
|
||||
cerr << "-:";
|
||||
}
|
||||
cerr << wid << "] is always outside vector."
|
||||
cerr << wid << "] is always outside the vector."
|
||||
<< endl;
|
||||
}
|
||||
return false;
|
||||
@@ -315,7 +315,18 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
|
||||
long msb, lsb;
|
||||
bool part_defined_flag;
|
||||
/* bool flag = */ calculate_parts_(des, scope, msb, lsb, part_defined_flag);
|
||||
ivl_assert(*this, part_defined_flag);
|
||||
|
||||
/* We have an undefined index and that is out of range. */
|
||||
if (!part_defined_flag) {
|
||||
if (warn_ob_select) {
|
||||
cerr << get_fileline() << ": warning: "
|
||||
<< sig->name();
|
||||
if (sig->unpacked_dimensions() > 0) cerr << "[]";
|
||||
cerr << "['bx] is always outside the vector."
|
||||
<< endl;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
long lidx_tmp = sig->sb_to_idx(prefix_indices, lsb);
|
||||
long midx_tmp = sig->sb_to_idx(prefix_indices, msb);
|
||||
@@ -358,7 +369,19 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
|
||||
long msb;
|
||||
bool bit_defined_flag;
|
||||
/* bool flag = */ calculate_bits_(des, scope, msb, bit_defined_flag);
|
||||
ivl_assert(*this, bit_defined_flag);
|
||||
|
||||
/* We have an undefined index and that is out of range. */
|
||||
if (!bit_defined_flag) {
|
||||
if (warn_ob_select) {
|
||||
cerr << get_fileline() << ": warning: "
|
||||
<< sig->name();
|
||||
if (sig->unpacked_dimensions() > 0) cerr << "[]";
|
||||
cerr << "['bx] is always outside the vector."
|
||||
<< endl;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (prefix_indices.size()+2 <= sig->packed_dims().size()) {
|
||||
long tmp_loff;
|
||||
@@ -478,6 +501,10 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
|
||||
unsigned midx = sig->vector_width()-1, lidx = 0;
|
||||
// The default word select is the first.
|
||||
long widx = 0;
|
||||
// Set this to true if we calculate the word index. This is
|
||||
// used to distinguish between unpacked array assignment and
|
||||
// array word assignment.
|
||||
bool widx_flag = false;
|
||||
|
||||
list<long> unpacked_indices_const;
|
||||
|
||||
@@ -501,7 +528,7 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PEIdent::elaborate_lnet_common_: "
|
||||
<< "Member " << method_name
|
||||
<< " has packed dimensions " << member->packed_dims << "." << endl;
|
||||
<< " has type " << *member->net_type << "." << endl;
|
||||
cerr << get_fileline() << ": : "
|
||||
<< "Tail name has " << path_tail.index.size() << " indices." << endl;
|
||||
}
|
||||
@@ -509,13 +536,13 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
|
||||
// Rewrite a member select of a packed structure as a
|
||||
// part select of the base variable.
|
||||
lidx = member_off;
|
||||
midx = lidx + member->width() - 1;
|
||||
midx = lidx + member->net_type->packed_width() - 1;
|
||||
|
||||
// The dimensions of the tail of the prefix must match
|
||||
// the dimensions of the signal at this point. (The sig
|
||||
// has a packed dimension for the packed struct size.)
|
||||
// For example, if the path_=a[<m>][<n>].member, then
|
||||
// sig must have 3 packed dimenions: one for the struct
|
||||
// sig must have 3 packed dimensions: one for the struct
|
||||
// members and two actual packed dimensions.
|
||||
ivl_assert(*this, path_prefix.back().index.size()+1 == sig->packed_dimensions());
|
||||
|
||||
@@ -532,15 +559,16 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
|
||||
packed_base = collapse_array_indices(des, scope, sig, tmp_index);
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: "
|
||||
<< "packed_base expression = " << *packed_base << endl;
|
||||
cerr << get_fileline() << ": PEIdent::elaborate_lnet_common_: "
|
||||
<< "packed_base=" << *packed_base
|
||||
<< ", member_off=" << member_off << endl;
|
||||
}
|
||||
}
|
||||
|
||||
long tmp;
|
||||
if (packed_base && eval_as_long(tmp, packed_base)) {
|
||||
lidx = tmp;
|
||||
midx = lidx + member->width() - 1;
|
||||
midx = lidx + member->net_type->packed_width() - 1;
|
||||
delete packed_base;
|
||||
packed_base = 0;
|
||||
}
|
||||
@@ -551,7 +579,7 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
|
||||
// Now the lidx/midx values get us to the member. Next
|
||||
// up, deal with bit/part selects from the member
|
||||
// itself.
|
||||
ivl_assert(*this, member->packed_dims.size() <= 1);
|
||||
//XXXXivl_assert(*this, member->packed_dims.size() <= 1);
|
||||
ivl_assert(*this, path_tail.index.size() <= 1);
|
||||
if (! path_tail.index.empty()) {
|
||||
long tmp_off;
|
||||
@@ -567,13 +595,31 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
|
||||
midx = lidx + tmp_wid - 1;
|
||||
}
|
||||
|
||||
} else if (gn_system_verilog() && sig->unpacked_dimensions() > 0 && path_tail.index.empty()) {
|
||||
|
||||
// In this case, we are doing a continuous assignment to
|
||||
// an unpacked array. The NetNet representation is a
|
||||
// NetNet with a pin for each array element, so there is
|
||||
// nothing more needed here.
|
||||
//
|
||||
// This can come up from code like this:
|
||||
// logic [...] data [0:3];
|
||||
// assign data = ...;
|
||||
// In this case, "sig" is "data", and sig->pin_count()
|
||||
// is 4 to account for the unpacked size.
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PEIdent::elaborate_lnet_common_: "
|
||||
<< "Net assign to unpacked array \"" << sig->name()
|
||||
<< "\" with " << sig->pin_count() << " elements." << endl;
|
||||
}
|
||||
|
||||
} else if (sig->unpacked_dimensions() > 0) {
|
||||
|
||||
// Make sure there are enough indices to address an array element.
|
||||
if (path_tail.index.size() < sig->unpacked_dimensions()) {
|
||||
cerr << get_fileline() << ": error: Array " << path()
|
||||
<< " needs " << sig->unpacked_dimensions() << " indices,"
|
||||
<< " but got only " << path_tail.index.size() << "." << endl;
|
||||
<< " but got only " << path_tail.index.size() << ". (net)" << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
@@ -581,35 +627,52 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
|
||||
// Evaluate all the index expressions into an
|
||||
// "unpacked_indices" array.
|
||||
list<NetExpr*>unpacked_indices;
|
||||
bool flag = indices_to_expressions(des, scope, this,
|
||||
path_tail.index, sig->unpacked_dimensions(),
|
||||
true,
|
||||
unpacked_indices,
|
||||
unpacked_indices_const);
|
||||
// Note that !flag includes that there were any other
|
||||
// elaboration errors generating the unpacked_indices list.
|
||||
if (!flag) {
|
||||
cerr << get_fileline() << ": error: array " << sig->name()
|
||||
<< " index must be a constant in this context." << endl;
|
||||
indices_flags flags;
|
||||
indices_to_expressions(des, scope, this,
|
||||
path_tail.index, sig->unpacked_dimensions(),
|
||||
true, sig->unpacked_count(),
|
||||
flags,
|
||||
unpacked_indices,
|
||||
unpacked_indices_const);
|
||||
|
||||
if (flags.invalid) {
|
||||
return 0;
|
||||
|
||||
} else if (flags.variable) {
|
||||
cerr << get_fileline() << ": error: array '" << sig->name()
|
||||
<< "' index must be a constant in this context." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetExpr*canon_index = 0;
|
||||
ivl_assert(*this, unpacked_indices_const.size() == sig->unpacked_dimensions());
|
||||
canon_index = normalize_variable_unpacked(sig, unpacked_indices_const);
|
||||
if (canon_index == 0) {
|
||||
// Normalize detected an out-of-bounds
|
||||
// index. Indicate that by setting the generated
|
||||
// widx to -1.
|
||||
} else if (flags.undefined) {
|
||||
cerr << get_fileline() << ": warning: "
|
||||
<< "ignoring undefined l-value array access "
|
||||
<< sig->name() << as_indices(unpacked_indices)
|
||||
<< "." << endl;
|
||||
widx = -1;
|
||||
widx_flag = true;
|
||||
|
||||
} else {
|
||||
NetEConst*canon_const = dynamic_cast<NetEConst*>(canon_index);
|
||||
ivl_assert(*this, canon_const);
|
||||
NetExpr*canon_index = 0;
|
||||
ivl_assert(*this, unpacked_indices_const.size() == sig->unpacked_dimensions());
|
||||
canon_index = normalize_variable_unpacked(sig, unpacked_indices_const);
|
||||
|
||||
widx = canon_const->value().as_long();
|
||||
delete canon_index;
|
||||
if (canon_index == 0) {
|
||||
cerr << get_fileline() << ": warning: "
|
||||
<< "ignoring out of bounds l-value array access "
|
||||
<< sig->name() << as_indices(unpacked_indices_const)
|
||||
<< "." << endl;
|
||||
widx = -1;
|
||||
widx_flag = true;
|
||||
|
||||
} else {
|
||||
NetEConst*canon_const = dynamic_cast<NetEConst*>(canon_index);
|
||||
ivl_assert(*this, canon_const);
|
||||
|
||||
widx = canon_const->value().as_long();
|
||||
widx_flag = true;
|
||||
delete canon_index;
|
||||
}
|
||||
}
|
||||
|
||||
if (debug_elaborate)
|
||||
@@ -645,6 +708,16 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
|
||||
}
|
||||
|
||||
} else if (!path_tail.index.empty()) {
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PEIdent::elaborate_lnet_common_: "
|
||||
<< "path_tail.index.size()=" << path_tail.index.size()
|
||||
<< endl;
|
||||
}
|
||||
|
||||
// There are index expressions on the name, so this is a
|
||||
// bit/slice select of the name. Calculate a canonical
|
||||
// part select.
|
||||
|
||||
if (sig->get_scalar()) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< "can not select part of ";
|
||||
@@ -673,20 +746,23 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
|
||||
unsigned subnet_wid = midx-lidx+1;
|
||||
|
||||
/* Check if the l-value bits are double-driven. */
|
||||
if (sig->type() == NetNet::UNRESOLVED_WIRE && sig->test_part_lref(midx,lidx)) {
|
||||
if (sig->type() == NetNet::UNRESOLVED_WIRE && sig->test_and_set_part_driver(midx,lidx, widx_flag? widx : 0)) {
|
||||
cerr << get_fileline() << ": error: Unresolved net/uwire "
|
||||
<< sig->name() << " cannot have multiple drivers." << endl;
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": : Overlap in "
|
||||
<< "[" << midx << ":" << lidx << "] (canonical)"
|
||||
<< ", widx=" << (widx_flag? widx : 0)
|
||||
<< ", vector width=" << sig->vector_width()
|
||||
<< endl;
|
||||
}
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sig->pin_count() > 1) {
|
||||
if (widx < 0 || widx >= (long) sig->pin_count()) {
|
||||
cerr << get_fileline() << ": warning: ignoring out of "
|
||||
"bounds l-value array access "
|
||||
<< sig->name() << as_indices(unpacked_indices_const) << "." << endl;
|
||||
if (sig->pin_count() > 1 && widx_flag) {
|
||||
if (widx < 0 || widx >= (long) sig->pin_count())
|
||||
return 0;
|
||||
}
|
||||
|
||||
netvector_t*tmp2_vec = new netvector_t(sig->data_type(),
|
||||
sig->vector_width()-1,0);
|
||||
@@ -696,6 +772,13 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
|
||||
tmp->local_flag(true);
|
||||
connect(sig->pin(widx), tmp->pin(0));
|
||||
sig = tmp;
|
||||
|
||||
} else if (sig->pin_count() > 1) {
|
||||
|
||||
// If this turns out to be an l-value unpacked array,
|
||||
// then let the caller handle it. It will probably be
|
||||
// converted into an array of assignments.
|
||||
return sig;
|
||||
}
|
||||
|
||||
/* If the desired l-value vector is narrower than the
|
||||
@@ -818,6 +901,33 @@ NetNet* PEIdent::elaborate_subport(Design*des, NetScope*scope) const
|
||||
long midx;
|
||||
long lidx;
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PEIdent::elaborate_subport: "
|
||||
<< "path_ = \"" << path_
|
||||
<< "\", unpacked_dimensions=" << sig->unpacked_dimensions()
|
||||
<< ", port_type()=" << sig->port_type() << endl;
|
||||
}
|
||||
|
||||
if (sig->unpacked_dimensions() && !gn_system_verilog()) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< "Ports cannot be unpacked arrays. Try enabling SystemVerilog support." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// There cannot be parts to an unpacked array, so process this
|
||||
// simply as an unpacked array.
|
||||
if (sig->unpacked_dimensions()) {
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PEIdent::elaborate_subport: "
|
||||
<< "path_=\"" << path_
|
||||
<< "\" is an unpacked array with " << sig->pin_count()
|
||||
<< " elements." << endl;
|
||||
}
|
||||
scope->add_module_port_net(sig);
|
||||
return sig;
|
||||
}
|
||||
|
||||
/* Evaluate the part/bit select expressions, to get the part
|
||||
select of the signal that attaches to the port. Also handle
|
||||
range and direction checking here. */
|
||||
@@ -879,6 +989,20 @@ NetNet* PEIdent::elaborate_subport(Design*des, NetScope*scope) const
|
||||
return sig;
|
||||
}
|
||||
|
||||
NetNet*PEIdent::elaborate_unpacked_net(Design*des, NetScope*scope) const
|
||||
{
|
||||
NetNet* sig = 0;
|
||||
const NetExpr*par = 0;
|
||||
NetEvent* eve = 0;
|
||||
perm_string method_name;
|
||||
|
||||
symbol_search(this, des, scope, path_, sig, par, eve);
|
||||
|
||||
ivl_assert(*this, sig);
|
||||
|
||||
return sig;
|
||||
}
|
||||
|
||||
bool PEIdent::is_collapsible_net(Design*des, NetScope*scope) const
|
||||
{
|
||||
assert(scope);
|
||||
|
||||
+476
-84
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2012 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright CERN 2013 / 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
|
||||
@@ -39,6 +40,7 @@
|
||||
# include "PClass.h"
|
||||
# include "PGate.h"
|
||||
# include "PGenerate.h"
|
||||
# include "PPackage.h"
|
||||
# include "PTask.h"
|
||||
# include "PWire.h"
|
||||
# include "Statement.h"
|
||||
@@ -46,6 +48,7 @@
|
||||
# include "netlist.h"
|
||||
# include "netclass.h"
|
||||
# include "netenum.h"
|
||||
# include "parse_api.h"
|
||||
# include "util.h"
|
||||
# include <typeinfo>
|
||||
# include <cassert>
|
||||
@@ -154,6 +157,10 @@ static void collect_scope_specparams_(Design*des, NetScope*scope,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Elaborate the enumeration into the given scope. If scope==0, then
|
||||
* the enumeration goes into $root instead of a scope.
|
||||
*/
|
||||
static void elaborate_scope_enumeration(Design*des, NetScope*scope,
|
||||
enum_type_t*enum_type)
|
||||
{
|
||||
@@ -161,7 +168,7 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope,
|
||||
assert(enum_type->range->size() == 1);
|
||||
pform_range_t&range = enum_type->range->front();
|
||||
NetExpr*msb_ex = elab_and_eval(des, scope, range.first, -1);
|
||||
NetExpr*lsb_ex = elab_and_eval(des, scope, range.second, -1);
|
||||
NetExpr*lsb_ex = elab_and_eval(des, scope, range.second, -1);
|
||||
|
||||
long msb = 0;
|
||||
rc_flag = eval_as_long(msb, msb_ex);
|
||||
@@ -170,34 +177,44 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope,
|
||||
rc_flag = eval_as_long(lsb, lsb_ex);
|
||||
assert(rc_flag);
|
||||
|
||||
netenum_t*use_enum = new netenum_t(enum_type->base_type, enum_type->signed_flag,
|
||||
msb, lsb, enum_type->names->size());
|
||||
netenum_t*use_enum = new netenum_t(enum_type->base_type,
|
||||
enum_type->signed_flag,
|
||||
enum_type->integer_flag, msb, lsb,
|
||||
enum_type->names->size(),
|
||||
enum_type);
|
||||
|
||||
use_enum->set_line(enum_type->li);
|
||||
scope->add_enumeration_set(use_enum);
|
||||
if (scope)
|
||||
scope->add_enumeration_set(enum_type, use_enum);
|
||||
else
|
||||
des->add_enumeration_set(enum_type, use_enum);
|
||||
|
||||
verinum cur_value (0);
|
||||
verinum one_value (1);
|
||||
size_t name_idx = 0;
|
||||
// Find the minimum and maximum allowed enumeration values.
|
||||
// Find the enumeration width.
|
||||
long raw_width = use_enum->packed_width();
|
||||
assert(raw_width > 0);
|
||||
unsigned enum_width = (unsigned)raw_width;
|
||||
// Define the default start value and the increment value to be the
|
||||
// correct type for this enumeration.
|
||||
verinum cur_value ((uint64_t)0, enum_width);
|
||||
cur_value.has_sign(enum_type->signed_flag);
|
||||
verinum one_value ((uint64_t)1, enum_width);
|
||||
one_value.has_sign(enum_type->signed_flag);
|
||||
// Find the maximum allowed enumeration value.
|
||||
verinum min_value (0);
|
||||
verinum max_value (0);
|
||||
if (enum_type->signed_flag) {
|
||||
min_value = v_not((pow(verinum(2),
|
||||
verinum(use_enum->packed_width()-1)))) +
|
||||
one_value;
|
||||
max_value = pow(verinum(2), verinum(use_enum->packed_width()-1)) -
|
||||
one_value;
|
||||
min_value = -pow(verinum(2), verinum(enum_width-1));
|
||||
max_value = pow(verinum(2), verinum(enum_width-1)) - one_value;
|
||||
} else {
|
||||
max_value = pow(verinum(2), verinum(use_enum->packed_width())) -
|
||||
one_value;
|
||||
max_value = pow(verinum(2), verinum(enum_width)) - one_value;
|
||||
}
|
||||
min_value.has_sign(true);
|
||||
max_value.has_sign(enum_type->signed_flag);
|
||||
// Process the enumeration definition.
|
||||
for (list<named_pexpr_t>::const_iterator cur = enum_type->names->begin()
|
||||
; cur != enum_type->names->end() ; ++ cur, name_idx += 1) {
|
||||
|
||||
|
||||
// Check to see if the enumeration name has a value given.
|
||||
if (cur->parm) {
|
||||
// There is an explicit value. elaborate/evaluate
|
||||
// the value and assign it to the enumeration name.
|
||||
@@ -205,37 +222,140 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope,
|
||||
NetEConst*val_const = dynamic_cast<NetEConst*> (val);
|
||||
if (val_const == 0) {
|
||||
cerr << use_enum->get_fileline()
|
||||
<< ": error: Enumeration expression is not "
|
||||
"constant." << endl;
|
||||
<< ": error: Enumeration expression for "
|
||||
<< cur->name <<" is not an integer constant."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
}
|
||||
cur_value = val_const->value();
|
||||
|
||||
// A 2-state value can not have a constant with X/Z bits.
|
||||
if (enum_type->base_type==IVL_VT_BOOL &&
|
||||
! cur_value.is_defined()) {
|
||||
cerr << use_enum->get_fileline()
|
||||
<< ": error: Enumeration name " << cur->name
|
||||
<< " cannot have an undefined value." << endl;
|
||||
<< " can not have an undefined value." << endl;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
}
|
||||
// If this is a literal constant and it has a defined
|
||||
// width then the width must match the enumeration width.
|
||||
if (PENumber *tmp = dynamic_cast<PENumber*>(cur->parm)) {
|
||||
if (tmp->value().has_len() &&
|
||||
(tmp->value().len() != enum_width)) {
|
||||
cerr << use_enum->get_fileline()
|
||||
<< ": error: Enumeration name " << cur->name
|
||||
<< " has an incorrectly sized constant."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// If we are padding/truncating a negative value for an
|
||||
// unsigned enumeration that is an error or if the new
|
||||
// value does not have a defined width.
|
||||
if (((cur_value.len() != enum_width) ||
|
||||
! cur_value.has_len()) &&
|
||||
! enum_type->signed_flag && cur_value.is_negative()) {
|
||||
cerr << use_enum->get_fileline()
|
||||
<< ": error: Enumeration name " << cur->name
|
||||
<< " has a negative value." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
// Narrower values need to be padded to the width of the
|
||||
// enumeration and defined to have the specified width.
|
||||
if (cur_value.len() < enum_width) {
|
||||
cur_value = pad_to_width(cur_value, enum_width);
|
||||
}
|
||||
|
||||
// Some wider values can be truncated.
|
||||
if (cur_value.len() > enum_width) {
|
||||
unsigned check_width = enum_width - 1;
|
||||
// Check that the upper bits match the MSB
|
||||
for (unsigned idx = enum_width;
|
||||
idx < cur_value.len();
|
||||
idx += 1) {
|
||||
if (cur_value[idx] != cur_value[check_width]) {
|
||||
// If this is an unsigned enumeration
|
||||
// then zero padding is okay.
|
||||
if (! enum_type->signed_flag &&
|
||||
(idx == enum_width) &&
|
||||
(cur_value[idx] == verinum::V0)) {
|
||||
check_width += 1;
|
||||
continue;
|
||||
}
|
||||
if (cur_value.is_defined()) {
|
||||
cerr << use_enum->get_fileline()
|
||||
<< ": error: Enumeration name "
|
||||
<< cur->name
|
||||
<< " has a value that is too "
|
||||
<< ((cur_value > max_value) ?
|
||||
"large" : "small")
|
||||
<< " " << cur_value << "."
|
||||
<< endl;
|
||||
} else {
|
||||
cerr << use_enum->get_fileline()
|
||||
<< ": error: Enumeration name "
|
||||
<< cur->name
|
||||
<< " has trimmed bits that do "
|
||||
<< "not match the enumeration "
|
||||
<< "MSB: " << cur_value << "."
|
||||
<< endl;
|
||||
}
|
||||
des->errors += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// If this is an unsigned value then make sure
|
||||
// The upper bits are not 1.
|
||||
if (! cur_value.has_sign() &&
|
||||
(cur_value[enum_width] == verinum::V1)) {
|
||||
cerr << use_enum->get_fileline()
|
||||
<< ": error: Enumeration name "
|
||||
<< cur->name
|
||||
<< " has a value that is too large: "
|
||||
<< cur_value << "." << endl;
|
||||
des->errors += 1;
|
||||
break;
|
||||
}
|
||||
cur_value = verinum(cur_value, enum_width);
|
||||
}
|
||||
|
||||
// At this point the value has the correct size and needs
|
||||
// to have the correct sign attribute set.
|
||||
cur_value.has_len(true);
|
||||
cur_value.has_sign(enum_type->signed_flag);
|
||||
|
||||
} else if (! cur_value.is_defined()) {
|
||||
cerr << use_enum->get_fileline()
|
||||
<< ": error: Enumeration name " << cur->name
|
||||
<< " cannot have an undefined inferred value." << endl;
|
||||
<< " has an undefined inferred value." << endl;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Cast any undefined bits to zero so the comparisons below
|
||||
// return just true (1) or false (0).
|
||||
verinum two_state_value = cur_value;
|
||||
two_state_value.cast_to_int2();
|
||||
|
||||
// The enumeration value must fit into the enumeration bits.
|
||||
if ((cur_value > max_value) ||
|
||||
(cur_value.has_sign() && (cur_value < min_value))) {
|
||||
if (!cur_value.is_defined()) {
|
||||
if (cur_value.len() > (unsigned long)use_enum->packed_width()) {
|
||||
cerr << use_enum->get_fileline()
|
||||
<< ": error: Enumeration name " << cur->name
|
||||
<< " value=" << cur_value
|
||||
<< " is too wide for enumeration base type." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
} else if ((two_state_value > max_value) ||
|
||||
(cur_value.has_sign() && (two_state_value < min_value))) {
|
||||
|
||||
cerr << use_enum->get_fileline()
|
||||
<< ": error: Enumeration name " << cur->name
|
||||
<< " cannot have a value equal to " << cur_value
|
||||
<< "." << endl;
|
||||
<< " has an inferred value that overflowed." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
@@ -249,23 +369,12 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope,
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
// The values are explicitly sized to the width of the
|
||||
// base type of the enumeration.
|
||||
verinum tmp_val (0);
|
||||
if (cur_value.len() < (unsigned long)use_enum->packed_width()) {
|
||||
// Pad the current value if it is narrower than the final
|
||||
// width of the enum.
|
||||
tmp_val = pad_to_width (cur_value, use_enum->packed_width());
|
||||
tmp_val.has_len(true);
|
||||
} else {
|
||||
// Truncate an oversized value. We report out of bound
|
||||
// values above. This may create duplicates.
|
||||
tmp_val = verinum(cur_value, use_enum->packed_width());
|
||||
}
|
||||
tmp_val.has_sign(enum_type->signed_flag);
|
||||
rc_flag = use_enum->insert_name(name_idx, cur->name, cur_value);
|
||||
if (scope)
|
||||
rc_flag &= scope->add_enumeration_name(use_enum, cur->name);
|
||||
else
|
||||
rc_flag &= des->add_enumeration_name(use_enum, cur->name);
|
||||
|
||||
rc_flag = use_enum->insert_name(name_idx, cur->name, tmp_val);
|
||||
rc_flag &= scope->add_enumeration_name(use_enum, cur->name);
|
||||
if (! rc_flag) {
|
||||
cerr << use_enum->get_fileline()
|
||||
<< ": error: Duplicate enumeration name "
|
||||
@@ -275,41 +384,238 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope,
|
||||
|
||||
// In case the next name has an implicit value,
|
||||
// increment the current value by one.
|
||||
if (cur_value.is_defined())
|
||||
if (cur_value.is_defined()) {
|
||||
cur_value = cur_value + one_value;
|
||||
}
|
||||
}
|
||||
|
||||
use_enum->insert_name_close();
|
||||
}
|
||||
|
||||
static void elaborate_scope_enumerations(Design*des, NetScope*scope,
|
||||
const list<enum_type_t*>&enum_types)
|
||||
const set<enum_type_t*>&enum_types)
|
||||
{
|
||||
for (list<enum_type_t*>::const_iterator cur = enum_types.begin()
|
||||
for (set<enum_type_t*>::const_iterator cur = enum_types.begin()
|
||||
; cur != enum_types.end() ; ++ cur) {
|
||||
elaborate_scope_enumeration(des, scope, *cur);
|
||||
enum_type_t*curp = *cur;
|
||||
elaborate_scope_enumeration(des, scope, curp);
|
||||
}
|
||||
}
|
||||
|
||||
static void elaborate_scope_class(Design*des, NetScope*scope,
|
||||
PClass*pclass)
|
||||
void elaborate_rootscope_enumerations(Design*des)
|
||||
{
|
||||
class_type_t*use_type = pclass->type;
|
||||
netclass_t*use_class = new netclass_t(use_type->name);
|
||||
for (set<enum_type_t*>::const_iterator cur = pform_enum_sets.begin()
|
||||
; cur != pform_enum_sets.end() ; ++ cur) {
|
||||
enum_type_t*curp = *cur;
|
||||
elaborate_scope_enumeration(des, 0, curp);
|
||||
}
|
||||
}
|
||||
|
||||
for (map<perm_string, data_type_t*>::iterator cur = use_type->properties.begin()
|
||||
; cur != use_type->properties.end() ; ++ cur) {
|
||||
ivl_type_s*tmp = cur->second->elaborate_type(des, scope);
|
||||
use_class->set_property(cur->first, tmp);
|
||||
/*
|
||||
* If the pclass includes an implicit and explicit constructor, then
|
||||
* merge the implicit constructor into the explicit constructor as
|
||||
* statements in the beginning.
|
||||
*
|
||||
* This is not necessary for proper functionality, it is an
|
||||
* optimization, so we can easily give up if it doesn't seem like it
|
||||
* will obviously work.
|
||||
*/
|
||||
static void blend_class_constructors(PClass*pclass)
|
||||
{
|
||||
perm_string new1 = perm_string::literal("new");
|
||||
perm_string new2 = perm_string::literal("new@");
|
||||
|
||||
PFunction*use_new;
|
||||
PFunction*use_new2;
|
||||
|
||||
// Locate the explicit constructor.
|
||||
map<perm_string,PFunction*>::iterator iter_new = pclass->funcs.find(new1);
|
||||
if (iter_new == pclass->funcs.end())
|
||||
use_new = 0;
|
||||
else
|
||||
use_new = iter_new->second;
|
||||
|
||||
// Locate the implicit constructor.
|
||||
map<perm_string,PFunction*>::iterator iter_new2 = pclass->funcs.find(new2);
|
||||
if (iter_new2 == pclass->funcs.end())
|
||||
use_new2 = 0;
|
||||
else
|
||||
use_new2 = iter_new2->second;
|
||||
|
||||
// If there are no constructors, then we are done.
|
||||
if (use_new==0 && use_new2==0)
|
||||
return;
|
||||
|
||||
// While we're here, look for a super.new() call. If we find
|
||||
// it, strip it out of the constructor and set it aside for
|
||||
// when we actually call the chained constructor.
|
||||
PChainConstructor*chain_new = use_new? use_new->extract_chain_constructor() : 0;
|
||||
|
||||
// If we do not have an explicit constructor chain, but there
|
||||
// is a parent class, then create an implicit chain.
|
||||
if (chain_new==0 && pclass->type->base_type!=0) {
|
||||
chain_new = new PChainConstructor(pclass->type->base_args);
|
||||
chain_new->set_line(*pclass);
|
||||
}
|
||||
|
||||
scope->add_class(use_class);
|
||||
// If there are both an implicit and explicit constructor,
|
||||
// then blend the implicit constructor into the explicit
|
||||
// constructor. This eases the task for the elaborator later.
|
||||
if (use_new && use_new2) {
|
||||
// These constructors must be methods of the same class.
|
||||
ivl_assert(*use_new, use_new->method_of() == use_new2->method_of());
|
||||
|
||||
Statement*def_new = use_new->get_statement();
|
||||
Statement*def_new2 = use_new2->get_statement();
|
||||
|
||||
// It is possible, i.e. recovering from a parse error,
|
||||
// for the statement from the constructor to be
|
||||
// missing. In that case, create an empty one.
|
||||
if (def_new==0) {
|
||||
def_new = new PBlock(PBlock::BL_SEQ);
|
||||
use_new->set_statement(def_new);
|
||||
}
|
||||
|
||||
if (def_new2) use_new->push_statement_front(def_new2);
|
||||
|
||||
// Now the implicit initializations are all built into
|
||||
// the constructor. Delete the "new@" constructor.
|
||||
pclass->funcs.erase(iter_new2);
|
||||
delete use_new2;
|
||||
use_new2 = 0;
|
||||
}
|
||||
|
||||
if (chain_new) {
|
||||
if (use_new2) {
|
||||
use_new2->push_statement_front(chain_new);
|
||||
} else {
|
||||
use_new->push_statement_front(chain_new);
|
||||
}
|
||||
chain_new = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass)
|
||||
{
|
||||
class_type_t*use_type = pclass->type;
|
||||
|
||||
if (debug_scopes) {
|
||||
cerr << pclass->get_fileline() <<": elaborate_scope_class: "
|
||||
<< "Elaborate scope class " << pclass->pscope_name() << endl;
|
||||
}
|
||||
|
||||
class_type_t*base_class = dynamic_cast<class_type_t*> (use_type->base_type);
|
||||
if (use_type->base_type && !base_class) {
|
||||
cerr << pclass->get_fileline() << ": error: "
|
||||
<< "Base type of " << use_type->name
|
||||
<< " is not a class." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
netclass_t*use_base_class = 0;
|
||||
if (base_class) {
|
||||
ivl_assert(*pclass, scope);
|
||||
use_base_class = scope->find_class(base_class->name);
|
||||
if (use_base_class == 0) {
|
||||
cerr << pclass->get_fileline() << ": error: "
|
||||
<< "Base class " << base_class->name
|
||||
<< " not found." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
}
|
||||
|
||||
netclass_t*use_class = new netclass_t(use_type->name, use_base_class);
|
||||
|
||||
ivl_assert(*pclass, use_type->save_elaborated_type == 0);
|
||||
use_type->save_elaborated_type = use_class;
|
||||
|
||||
// Class scopes have no parent scope, because references are
|
||||
// not allowed to escape a class method.
|
||||
NetScope*class_scope = new NetScope(0, hname_t(pclass->pscope_name()),
|
||||
NetScope::CLASS);
|
||||
class_scope->set_line(pclass);
|
||||
class_scope->set_class_def(use_class);
|
||||
use_class->set_class_scope(class_scope);
|
||||
use_class->set_definition_scope(scope);
|
||||
|
||||
// Collect the properties, elaborate them, and add them to the
|
||||
// elaborated class definition.
|
||||
for (map<perm_string, class_type_t::prop_info_t>::iterator cur = use_type->properties.begin()
|
||||
; cur != use_type->properties.end() ; ++ cur) {
|
||||
|
||||
ivl_type_s*tmp = cur->second.type->elaborate_type(des, scope);
|
||||
ivl_assert(*pclass, tmp);
|
||||
if (debug_scopes) {
|
||||
cerr << pclass->get_fileline() << ": elaborate_scope_class: "
|
||||
<< " Property " << cur->first
|
||||
<< " type=" << *tmp << endl;
|
||||
}
|
||||
use_class->set_property(cur->first, cur->second.qual, tmp);
|
||||
|
||||
}
|
||||
|
||||
for (map<perm_string,PTask*>::iterator cur = pclass->tasks.begin()
|
||||
; cur != pclass->tasks.end() ; ++cur) {
|
||||
|
||||
hname_t use_name (cur->first);
|
||||
NetScope*method_scope = new NetScope(class_scope, use_name, NetScope::TASK);
|
||||
// Task methods are always automatic...
|
||||
method_scope->is_auto(true);
|
||||
method_scope->set_line(cur->second);
|
||||
|
||||
if (debug_scopes) {
|
||||
cerr << cur->second->get_fileline() << ": elaborate_scope_class: "
|
||||
<< "Elaborate method (task) scope "
|
||||
<< scope_path(method_scope) << endl;
|
||||
}
|
||||
|
||||
cur->second->elaborate_scope(des, method_scope);
|
||||
}
|
||||
|
||||
for (map<perm_string,PFunction*>::iterator cur = pclass->funcs.begin()
|
||||
; cur != pclass->funcs.end() ; ++cur) {
|
||||
|
||||
hname_t use_name (cur->first);
|
||||
NetScope*method_scope = new NetScope(class_scope, use_name, NetScope::FUNC);
|
||||
// Function methods are always automatic...
|
||||
method_scope->is_auto(true);
|
||||
method_scope->set_line(cur->second);
|
||||
|
||||
if (debug_scopes) {
|
||||
cerr << cur->second->get_fileline() << ": elaborate_scope_class: "
|
||||
<< "Elaborate method (function) scope "
|
||||
<< scope_path(method_scope) << endl;
|
||||
}
|
||||
|
||||
cur->second->elaborate_scope(des, method_scope);
|
||||
}
|
||||
|
||||
if (scope) {
|
||||
scope->add_class(use_class);
|
||||
|
||||
} else {
|
||||
des->add_class(use_class, pclass);
|
||||
}
|
||||
}
|
||||
|
||||
static void elaborate_scope_classes(Design*des, NetScope*scope,
|
||||
const map<perm_string,PClass*>&classes)
|
||||
const vector<PClass*>&classes)
|
||||
{
|
||||
for (map<perm_string,PClass*>::const_iterator cur = classes.begin()
|
||||
; cur != classes.end() ; ++ cur) {
|
||||
elaborate_scope_class(des, scope, cur->second);
|
||||
for (size_t idx = 0 ; idx < classes.size() ; idx += 1) {
|
||||
blend_class_constructors(classes[idx]);
|
||||
elaborate_scope_class(des, scope, classes[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
void elaborate_rootscope_classes(Design*des)
|
||||
{
|
||||
if (pform_classes.empty())
|
||||
return;
|
||||
|
||||
for (map<perm_string,PClass*>::iterator cur = pform_classes.begin()
|
||||
; cur != pform_classes.end() ; ++ cur) {
|
||||
blend_class_constructors(cur->second);
|
||||
elaborate_scope_class(des, 0, cur->second);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -354,6 +660,25 @@ static void elaborate_scope_events_(Design*des, NetScope*scope,
|
||||
}
|
||||
}
|
||||
|
||||
static void elaborate_scope_task(Design*des, NetScope*scope, PTask*task)
|
||||
{
|
||||
hname_t use_name( task->pscope_name() );
|
||||
|
||||
NetScope*task_scope = new NetScope(scope, use_name, NetScope::TASK);
|
||||
task_scope->is_auto(task->is_auto());
|
||||
task_scope->set_line(task);
|
||||
|
||||
if (scope==0)
|
||||
des->add_root_task(task_scope, task);
|
||||
|
||||
if (debug_scopes) {
|
||||
cerr << task->get_fileline() << ": elaborate_scope_task: "
|
||||
<< "Elaborate task scope " << scope_path(task_scope) << endl;
|
||||
}
|
||||
|
||||
task->elaborate_scope(des, task_scope);
|
||||
}
|
||||
|
||||
static void elaborate_scope_tasks(Design*des, NetScope*scope,
|
||||
const map<perm_string,PTask*>&tasks)
|
||||
{
|
||||
@@ -395,19 +720,30 @@ static void elaborate_scope_tasks(Design*des, NetScope*scope,
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
NetScope*task_scope = new NetScope(scope, use_name,
|
||||
NetScope::TASK);
|
||||
task_scope->is_auto((*cur).second->is_auto());
|
||||
task_scope->set_line((*cur).second);
|
||||
|
||||
if (debug_scopes)
|
||||
cerr << cur->second->get_fileline() << ": debug: "
|
||||
<< "Elaborate task scope " << scope_path(task_scope) << endl;
|
||||
(*cur).second->elaborate_scope(des, task_scope);
|
||||
elaborate_scope_task(des, scope, cur->second);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void elaborate_scope_func(Design*des, NetScope*scope, PFunction*task)
|
||||
{
|
||||
hname_t use_name( task->pscope_name() );
|
||||
|
||||
NetScope*task_scope = new NetScope(scope, use_name, NetScope::FUNC);
|
||||
task_scope->is_auto(task->is_auto());
|
||||
task_scope->set_line(task);
|
||||
|
||||
if (scope==0)
|
||||
des->add_root_task(task_scope, task);
|
||||
|
||||
if (debug_scopes) {
|
||||
cerr << task->get_fileline() << ": elaborate_scope_func: "
|
||||
<< "Elaborate task scope " << scope_path(task_scope) << endl;
|
||||
}
|
||||
|
||||
task->elaborate_scope(des, task_scope);
|
||||
}
|
||||
|
||||
static void elaborate_scope_funcs(Design*des, NetScope*scope,
|
||||
const map<perm_string,PFunction*>&funcs)
|
||||
{
|
||||
@@ -450,19 +786,33 @@ static void elaborate_scope_funcs(Design*des, NetScope*scope,
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
NetScope*func_scope = new NetScope(scope, use_name,
|
||||
NetScope::FUNC);
|
||||
func_scope->is_auto((*cur).second->is_auto());
|
||||
func_scope->set_line((*cur).second);
|
||||
|
||||
if (debug_scopes)
|
||||
cerr << cur->second->get_fileline() << ": debug: "
|
||||
<< "Elaborate function scope " << scope_path(func_scope) << endl;
|
||||
(*cur).second->elaborate_scope(des, func_scope);
|
||||
elaborate_scope_func(des, scope, cur->second);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void elaborate_rootscope_tasks(Design*des)
|
||||
{
|
||||
for (map<perm_string,PTaskFunc*>::iterator cur = pform_tasks.begin()
|
||||
; cur != pform_tasks.end() ; ++ cur) {
|
||||
|
||||
if (PTask*task = dynamic_cast<PTask*> (cur->second)) {
|
||||
elaborate_scope_task(des, 0, task);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (PFunction*func = dynamic_cast<PFunction*>(cur->second)) {
|
||||
elaborate_scope_func(des, 0, func);
|
||||
continue;
|
||||
}
|
||||
|
||||
cerr << cur->second->get_fileline() << ": internal error: "
|
||||
<< "elabortae_rootscope_tasks does not understand "
|
||||
<< "this object," << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
}
|
||||
|
||||
class generate_schemes_work_item_t : public elaborator_work_item_t {
|
||||
public:
|
||||
generate_schemes_work_item_t(Design*des__, NetScope*scope, Module*mod)
|
||||
@@ -495,12 +845,28 @@ class generate_schemes_work_item_t : public elaborator_work_item_t {
|
||||
Module*mod_;
|
||||
};
|
||||
|
||||
bool PPackage::elaborate_scope(Design*des, NetScope*scope)
|
||||
{
|
||||
if (debug_scopes) {
|
||||
cerr << get_fileline() << ": PPackage::elaborate_scope: "
|
||||
<< "Elaborate package " << scope_path(scope) << "." << endl;
|
||||
}
|
||||
|
||||
collect_scope_parameters_(des, scope, parameters);
|
||||
collect_scope_localparams_(des, scope, localparams);
|
||||
elaborate_scope_enumerations(des, scope, enum_sets);
|
||||
elaborate_scope_classes(des, scope, classes_lexical);
|
||||
elaborate_scope_funcs(des, scope, funcs);
|
||||
elaborate_scope_tasks(des, scope, tasks);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Module::elaborate_scope(Design*des, NetScope*scope,
|
||||
const replace_t&replacements)
|
||||
{
|
||||
if (debug_scopes) {
|
||||
cerr << get_fileline() << ": debug: Elaborate scope "
|
||||
<< scope_path(scope) << "." << endl;
|
||||
cerr << get_fileline() << ": Module::elaborate_scope: "
|
||||
<< "Elaborate " << scope_path(scope) << "." << endl;
|
||||
}
|
||||
|
||||
// Add the genvars to the scope.
|
||||
@@ -527,7 +893,8 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
|
||||
|
||||
elaborate_scope_enumerations(des, scope, enum_sets);
|
||||
|
||||
elaborate_scope_classes(des, scope, classes);
|
||||
assert(classes.size() == classes_lexical.size());
|
||||
elaborate_scope_classes(des, scope, classes_lexical);
|
||||
|
||||
// Run through the defparams for this module and save the result
|
||||
// in a table for later final override.
|
||||
@@ -549,7 +916,7 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
|
||||
delete[]attr;
|
||||
|
||||
// Generate schemes need to have their scopes elaborated, but
|
||||
// we cannot do that until defparams are run, so push it off
|
||||
// we can not do that until defparams are run, so push it off
|
||||
// into an elaborate work item.
|
||||
if (debug_scopes)
|
||||
cerr << get_fileline() << ": debug: "
|
||||
@@ -685,8 +1052,10 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
|
||||
|
||||
// Check the generate block name.
|
||||
|
||||
// A generate "loop" can not have the same name as another scope object.
|
||||
const NetScope *child = container->child(hname_t(scope_name));
|
||||
// A generate "loop" can not have the same name as another
|
||||
// scope object. Find any scope with this name, not just an
|
||||
// exact match scope.
|
||||
const NetScope *child = container->child_byname(scope_name);
|
||||
if (child) {
|
||||
cerr << get_fileline() << ": error: generate \"loop\" and ";
|
||||
child->print_type(cerr);
|
||||
@@ -1289,7 +1658,7 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
|
||||
continue;
|
||||
}
|
||||
|
||||
cerr << get_fileline() << ": error: You cannot instantiate "
|
||||
cerr << get_fileline() << ": error: You can not instantiate "
|
||||
<< "module " << mod->mod_name() << " within itself." << endl;
|
||||
cerr << get_fileline() << ": : The offending instance is "
|
||||
<< get_name() << " within " << scope_path(scn) << "." << endl;
|
||||
@@ -1668,6 +2037,17 @@ void PDelayStatement::elaborate_scope(Design*des, NetScope*scope) const
|
||||
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 PDoWhile::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
|
||||
@@ -1679,6 +2059,18 @@ void PEventStatement::elaborate_scope(Design*des, NetScope*scope) const
|
||||
statement_ -> elaborate_scope(des, scope);
|
||||
}
|
||||
|
||||
/*
|
||||
* The standard says that we create an implicit scope for foreach
|
||||
* loops, but that is just to hold the index variables, and we'll
|
||||
* handle them by creating unique names. So just jump into the
|
||||
* contained statement for scope elaboration.
|
||||
*/
|
||||
void PForeach::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
|
||||
|
||||
+317
-327
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2012 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright CERN 2012 / Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
@@ -25,9 +25,11 @@
|
||||
# include <iostream>
|
||||
|
||||
# include "Module.h"
|
||||
# include "PClass.h"
|
||||
# include "PExpr.h"
|
||||
# include "PGate.h"
|
||||
# include "PGenerate.h"
|
||||
# include "PPackage.h"
|
||||
# include "PTask.h"
|
||||
# include "PWire.h"
|
||||
# include "Statement.h"
|
||||
@@ -36,10 +38,10 @@
|
||||
# include "netmisc.h"
|
||||
# include "netclass.h"
|
||||
# include "netenum.h"
|
||||
# include "netstruct.h"
|
||||
# include "netvector.h"
|
||||
# include "netdarray.h"
|
||||
# include "netparray.h"
|
||||
# include "netqueue.h"
|
||||
# include "util.h"
|
||||
# include "ivl_assert.h"
|
||||
|
||||
@@ -71,6 +73,8 @@ static bool get_const_argument(NetExpr*exp, verinum&res)
|
||||
return true;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* This function is not currently used. */
|
||||
static bool get_const_argument(NetExpr*exp, long&res)
|
||||
{
|
||||
verinum tmp;
|
||||
@@ -79,6 +83,7 @@ static bool get_const_argument(NetExpr*exp, long&res)
|
||||
res = tmp.as_long();
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
void Statement::elaborate_sig(Design*, NetScope*) const
|
||||
{
|
||||
@@ -165,7 +170,13 @@ static void elaborate_sig_funcs(Design*des, NetScope*scope,
|
||||
continue;
|
||||
}
|
||||
|
||||
(*cur).second->elaborate_sig(des, fscope);
|
||||
if (debug_elaborate) {
|
||||
cerr << cur->second->get_fileline() << ": elaborate_sig_funcs: "
|
||||
<< "Elaborate function " << use_name
|
||||
<< " in " << scope_path(fscope) << endl;
|
||||
}
|
||||
|
||||
cur->second->elaborate_sig(des, fscope);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,6 +193,43 @@ static void elaborate_sig_tasks(Design*des, NetScope*scope,
|
||||
}
|
||||
}
|
||||
|
||||
static void elaborate_sig_classes(Design*des, NetScope*scope,
|
||||
const map<perm_string,PClass*>&classes)
|
||||
{
|
||||
for (map<perm_string,PClass*>::const_iterator cur = classes.begin()
|
||||
; cur != classes.end() ; ++ cur) {
|
||||
netclass_t*use_class = scope->find_class(cur->second->pscope_name());
|
||||
use_class->elaborate_sig(des, cur->second);
|
||||
}
|
||||
}
|
||||
|
||||
bool PPackage::elaborate_sig(Design*des, NetScope*scope) const
|
||||
{
|
||||
bool flag = true;
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PPackage::elaborate_sig: "
|
||||
<< "Start package scope=" << scope_path(scope) << endl;
|
||||
}
|
||||
|
||||
flag = elaborate_sig_wires_(des, scope) && flag;
|
||||
|
||||
// After all the wires are elaborated, we are free to
|
||||
// elaborate the ports of the tasks defined within this
|
||||
// module. Run through them now.
|
||||
|
||||
elaborate_sig_funcs(des, scope, funcs);
|
||||
elaborate_sig_tasks(des, scope, tasks);
|
||||
elaborate_sig_classes(des, scope, classes);
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PPackage::elaborate_sig: "
|
||||
<< "Done package scope=" << scope_path(scope)
|
||||
<< ", flag=" << flag << endl;
|
||||
}
|
||||
|
||||
return flag;
|
||||
}
|
||||
|
||||
bool Module::elaborate_sig(Design*des, NetScope*scope) const
|
||||
{
|
||||
@@ -262,6 +310,7 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const
|
||||
|
||||
elaborate_sig_funcs(des, scope, funcs);
|
||||
elaborate_sig_tasks(des, scope, tasks);
|
||||
elaborate_sig_classes(des, scope, classes);
|
||||
|
||||
// initial and always blocks may contain begin-end and
|
||||
// fork-join blocks that can introduce scopes. Therefore, I
|
||||
@@ -278,6 +327,53 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const
|
||||
return flag;
|
||||
}
|
||||
|
||||
void netclass_t::elaborate_sig(Design*des, PClass*pclass)
|
||||
{
|
||||
for (map<perm_string,struct class_type_t::prop_info_t>::iterator cur = pclass->type->properties.begin()
|
||||
; cur != pclass->type->properties.end() ; ++ cur) {
|
||||
|
||||
if (! cur->second.qual.test_static())
|
||||
continue;
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << pclass->get_fileline() << ": netclass_t::elaborate_sig: "
|
||||
<< "Elaborate static property " << cur->first
|
||||
<< " as signal in scope " << scope_path(class_scope_)
|
||||
<< "." << endl;
|
||||
}
|
||||
|
||||
list<netrange_t> nil_list;
|
||||
ivl_type_t use_type = cur->second.type->elaborate_type(des, class_scope_);
|
||||
/* NetNet*sig = */ new NetNet(class_scope_, cur->first, NetNet::REG,
|
||||
nil_list, use_type);
|
||||
}
|
||||
|
||||
for (map<perm_string,PFunction*>::iterator cur = pclass->funcs.begin()
|
||||
; cur != pclass->funcs.end() ; ++ cur) {
|
||||
if (debug_elaborate) {
|
||||
cerr << cur->second->get_fileline() << ": netclass_t::elaborate_sig: "
|
||||
<< "Elaborate signals in function method " << cur->first << endl;
|
||||
}
|
||||
|
||||
NetScope*scope = class_scope_->child( hname_t(cur->first) );
|
||||
ivl_assert(*cur->second, scope);
|
||||
cur->second->elaborate_sig(des, scope);
|
||||
}
|
||||
|
||||
for (map<perm_string,PTask*>::iterator cur = pclass->tasks.begin()
|
||||
; cur != pclass->tasks.end() ; ++ cur) {
|
||||
if (debug_elaborate) {
|
||||
cerr << cur->second->get_fileline() << ": netclass_t::elaborate_sig: "
|
||||
<< "Elaborate signals in task method " << cur->first << endl;
|
||||
}
|
||||
|
||||
NetScope*scope = class_scope_->child( hname_t(cur->first) );
|
||||
ivl_assert(*cur->second, scope);
|
||||
cur->second->elaborate_sig(des, scope);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool PGate::elaborate_sig(Design*, NetScope*) const
|
||||
{
|
||||
return true;
|
||||
@@ -475,218 +571,73 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
||||
|
||||
elaborate_sig_wires_(des, scope);
|
||||
|
||||
/* Make sure the function has at least one input port. If it
|
||||
fails this test, print an error message. Keep going so we
|
||||
can find more errors. */
|
||||
if (ports_ == 0 && !gn_system_verilog()) {
|
||||
cerr << get_fileline() << ": error: Function " << fname
|
||||
<< " has no ports." << endl;
|
||||
cerr << get_fileline() << ": : Functions must have"
|
||||
<< " at least one input port." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
NetNet*ret_sig;
|
||||
if (gn_system_verilog() && (fname=="new" || fname=="new@")) {
|
||||
// Special case: this is a constructor, so the return
|
||||
// signal is also the first argument. For example, the
|
||||
// source code for the definition may be:
|
||||
// function new(...);
|
||||
// endfunction
|
||||
// In this case, the "@" port is the synthetic "this"
|
||||
// argument and we also use it as a return value at the
|
||||
// same time.
|
||||
ret_sig = scope->find_signal(perm_string::literal("@"));
|
||||
ivl_assert(*this, ret_sig);
|
||||
|
||||
NetNet*ret_sig = 0;
|
||||
netvector_t*ret_vec = 0;
|
||||
if (debug_elaborate)
|
||||
cerr << get_fileline() << ": PFunction::elaborate_sig: "
|
||||
<< "Scope " << scope_path(scope)
|
||||
<< " is a CONSTRUCTOR, so use \"this\" argument"
|
||||
<< " as return value." << endl;
|
||||
|
||||
/* Create the signals/variables of the return value and write
|
||||
them into the function scope. */
|
||||
switch (return_type_.type) {
|
||||
} else {
|
||||
ivl_type_t ret_type;
|
||||
|
||||
case PTF_REG:
|
||||
case PTF_REG_S:
|
||||
if (return_type_.range) {
|
||||
ivl_assert(*this, return_type_.range->size() == 1);
|
||||
pform_range_t&return_range = return_type_.range->front();
|
||||
|
||||
NetExpr*me = elab_and_eval(des, scope,
|
||||
return_range.first, -1,
|
||||
true);
|
||||
assert(me);
|
||||
NetExpr*le = elab_and_eval(des, scope,
|
||||
return_range.second, -1,
|
||||
true);
|
||||
assert(le);
|
||||
|
||||
long mnum = 0, lnum = 0;
|
||||
if ( ! get_const_argument(me, mnum) ) {
|
||||
cerr << me->get_fileline() << ": error: "
|
||||
"Unable to evaluate constant expression "
|
||||
<< *me << "." << endl;
|
||||
des->errors += 1;
|
||||
if (return_type_) {
|
||||
if (dynamic_cast<const struct void_type_t*> (return_type_)) {
|
||||
ret_type = 0;
|
||||
} else {
|
||||
ret_type = return_type_->elaborate_type(des, scope->parent());
|
||||
ivl_assert(*this, ret_type);
|
||||
}
|
||||
|
||||
if ( ! get_const_argument(le, lnum) ) {
|
||||
cerr << le->get_fileline() << ": error: "
|
||||
"Unable to evaluate constant expression "
|
||||
<< *le << "." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
vector<netrange_t> packed;
|
||||
packed.push_back(netrange_t(mnum, lnum));
|
||||
ret_vec = new netvector_t(packed, IVL_VT_LOGIC);
|
||||
ret_vec->set_signed(return_type_.type == PTF_REG_S);
|
||||
ret_vec->set_scalar(false);
|
||||
ret_sig = new NetNet(scope, fname, NetNet::REG, ret_vec);
|
||||
|
||||
} else {
|
||||
ret_vec = new netvector_t(IVL_VT_LOGIC);
|
||||
ret_vec->set_signed(return_type_.type == PTF_REG_S);
|
||||
ret_vec->set_scalar(true);
|
||||
ret_sig = new NetNet(scope, fname, NetNet::REG, ret_vec);
|
||||
netvector_t*tmp = new netvector_t(IVL_VT_LOGIC);
|
||||
tmp->set_scalar(true);
|
||||
ret_type = tmp;
|
||||
}
|
||||
ret_sig->set_line(*this);
|
||||
ret_sig->port_type(NetNet::POUTPUT);
|
||||
break;
|
||||
|
||||
case PTF_INTEGER:
|
||||
ret_vec = new netvector_t(IVL_VT_LOGIC, integer_width-1,0);
|
||||
ret_vec->set_signed(true);
|
||||
ret_vec->set_isint(true);
|
||||
ret_vec->set_scalar(false);
|
||||
ret_sig = new NetNet(scope, fname, NetNet::REG, ret_vec);
|
||||
ret_sig->set_line(*this);
|
||||
ret_sig->port_type(NetNet::POUTPUT);
|
||||
break;
|
||||
|
||||
case PTF_TIME:
|
||||
ret_vec = new netvector_t(IVL_VT_LOGIC, 64-1,0);
|
||||
ret_vec->set_isint(false);
|
||||
ret_vec->set_scalar(false);
|
||||
ret_sig = new NetNet(scope, fname, NetNet::REG, ret_vec);
|
||||
ret_sig->set_line(*this);
|
||||
ret_sig->port_type(NetNet::POUTPUT);
|
||||
break;
|
||||
|
||||
case PTF_REAL:
|
||||
case PTF_REALTIME:
|
||||
ret_vec = new netvector_t(IVL_VT_REAL);
|
||||
ret_vec->set_signed(true);
|
||||
ret_vec->set_isint(false);
|
||||
ret_vec->set_scalar(true);
|
||||
ret_sig = new NetNet(scope, fname, NetNet::REG, ret_vec);
|
||||
ret_sig->set_line(*this);
|
||||
ret_sig->port_type(NetNet::POUTPUT);
|
||||
break;
|
||||
|
||||
case PTF_ATOM2:
|
||||
case PTF_ATOM2_S:
|
||||
long use_wid;
|
||||
{
|
||||
ivl_assert(*this, return_type_.range->size() == 1);
|
||||
pform_range_t&return_range = return_type_.range->front();
|
||||
NetExpr*me = elab_and_eval(des, scope,
|
||||
return_range.first, -1,
|
||||
true);
|
||||
ivl_assert(*this, me);
|
||||
NetExpr*le = elab_and_eval(des, scope,
|
||||
return_range.second, -1,
|
||||
true);
|
||||
ivl_assert(*this, le);
|
||||
|
||||
long mnum = 0, lnum = 0;
|
||||
if ( ! get_const_argument(me, mnum) ) {
|
||||
cerr << me->get_fileline() << ": error: "
|
||||
"Unable to evaluate constant expression "
|
||||
<< *me << "." << endl;
|
||||
des->errors += 1;
|
||||
if (ret_type) {
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PFunction::elaborate_sig: "
|
||||
<< "return type: " << *ret_type << endl;
|
||||
if (return_type_)
|
||||
return_type_->pform_dump(cerr, 8);
|
||||
}
|
||||
list<netrange_t> ret_unpacked;
|
||||
ret_sig = new NetNet(scope, fname, NetNet::REG, ret_unpacked, ret_type);
|
||||
|
||||
if ( ! get_const_argument(le, lnum) ) {
|
||||
cerr << le->get_fileline() << ": error: "
|
||||
"Unable to evaluate constant expression "
|
||||
<< *le << "." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
use_wid = mnum - lnum + 1;
|
||||
}
|
||||
ret_vec = new netvector_t(IVL_VT_BOOL, use_wid-1, 0);
|
||||
ret_vec->set_isint(true);
|
||||
ret_vec->set_scalar(false);
|
||||
ret_vec->set_signed(return_type_.type == PTF_ATOM2_S? true : false);
|
||||
ret_sig = new NetNet(scope, fname, NetNet::REG, ret_vec);
|
||||
ret_sig->set_line(*this);
|
||||
ret_sig->port_type(NetNet::POUTPUT);
|
||||
break;
|
||||
|
||||
case PTF_STRING:
|
||||
cerr << get_fileline() << ": sorry: String functions are not supported yet" << endl;
|
||||
break;
|
||||
|
||||
case PTF_VOID:
|
||||
// Void functions have no return value, so there is no
|
||||
// signal to create here.
|
||||
break;
|
||||
|
||||
default:
|
||||
if (ports_) {
|
||||
cerr << get_fileline() << ": internal error: I don't know "
|
||||
<< "how to deal with return type of function "
|
||||
<< scope->basename() << "." << endl;
|
||||
ret_sig->set_line(*this);
|
||||
ret_sig->port_type(NetNet::POUTPUT);
|
||||
} else {
|
||||
/* If we do not have any ports or a return type this
|
||||
* is probably a bad function definition. */
|
||||
cerr << get_fileline() << ": error: Bad definition for "
|
||||
<< "function " << scope->basename() << "?" << endl;
|
||||
return;
|
||||
ret_sig = 0;
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PFunction::elaborate_sig: "
|
||||
<< "Detected that function is void." << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vector<NetNet*>ports (ports_? ports_->count() : 0);
|
||||
vector<NetNet*>ports;
|
||||
vector<NetExpr*>pdef;
|
||||
elaborate_sig_ports_(des, scope, ports, pdef);
|
||||
|
||||
if (ports_)
|
||||
for (unsigned idx = 0 ; idx < ports_->count() ; idx += 1) {
|
||||
NetFuncDef*def = new NetFuncDef(scope, ret_sig, ports, pdef);
|
||||
|
||||
/* 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>. */
|
||||
|
||||
perm_string pname = (*ports_)[idx]->basename();
|
||||
|
||||
NetNet*tmp = scope->find_signal(pname);
|
||||
ports[idx] = 0;
|
||||
|
||||
if (tmp == 0) {
|
||||
cerr << get_fileline() << ": internal error: function "
|
||||
<< scope_path(scope) << " is missing port "
|
||||
<< pname << "." << endl;
|
||||
scope->dump(cerr);
|
||||
cerr << get_fileline() << ": Continuing..." << endl;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tmp->port_type() == NetNet::NOT_A_PORT) {
|
||||
cerr << get_fileline() << ": internal error: function "
|
||||
<< scope_path(scope) << " port " << pname
|
||||
<< " is a port but is not a port?" << endl;
|
||||
des->errors += 1;
|
||||
scope->dump(cerr);
|
||||
continue;
|
||||
}
|
||||
|
||||
ports[idx] = tmp;
|
||||
if (tmp->port_type() != NetNet::PINPUT) {
|
||||
cerr << tmp->get_fileline() << ": error: function "
|
||||
<< scope_path(scope) << " port " << pname
|
||||
<< " is not an input port." << endl;
|
||||
cerr << tmp->get_fileline() << ": : Function arguments "
|
||||
<< "must be input ports." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
NetFuncDef*def = 0;
|
||||
if (ret_sig) def = new NetFuncDef(scope, ret_sig, ports);
|
||||
|
||||
assert(def);
|
||||
if (debug_elaborate)
|
||||
cerr << get_fileline() << ": debug: "
|
||||
<< "Attach function definition to scope "
|
||||
<< scope_path(scope) << "." << endl;
|
||||
cerr << get_fileline() << ": PFunction::elaborate_sig: "
|
||||
<< "Attach function definition " << scope_path(scope)
|
||||
<< " with ret_sig width=" << (ret_sig? ret_sig->vector_width() : 0)
|
||||
<< "." << endl;
|
||||
|
||||
scope->set_func_def(def);
|
||||
|
||||
@@ -710,28 +661,10 @@ void PTask::elaborate_sig(Design*des, NetScope*scope) const
|
||||
|
||||
elaborate_sig_wires_(des, scope);
|
||||
|
||||
svector<NetNet*>ports (ports_? ports_->count() : 0);
|
||||
for (unsigned idx = 0 ; idx < ports.count() ; idx += 1) {
|
||||
|
||||
perm_string port_name = (*ports_)[idx]->basename();
|
||||
|
||||
/* 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(port_name);
|
||||
|
||||
if (tmp == 0) {
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<< "Could not find port " << port_name
|
||||
<< " in scope " << scope_path(scope) << endl;
|
||||
scope->dump(cerr);
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
ports[idx] = tmp;
|
||||
}
|
||||
|
||||
NetTaskDef*def = new NetTaskDef(scope, ports);
|
||||
vector<NetNet*>ports;
|
||||
vector<NetExpr*>pdefs;
|
||||
elaborate_sig_ports_(des, scope, ports, pdefs);
|
||||
NetTaskDef*def = new NetTaskDef(scope, ports, pdefs);
|
||||
scope->set_task_def(def);
|
||||
|
||||
// Look for further signals in the sub-statement
|
||||
@@ -739,6 +672,87 @@ void PTask::elaborate_sig(Design*des, NetScope*scope) const
|
||||
statement_->elaborate_sig(des, scope);
|
||||
}
|
||||
|
||||
void PTaskFunc::elaborate_sig_ports_(Design*des, NetScope*scope,
|
||||
vector<NetNet*>&ports, vector<NetExpr*>&pdefs) const
|
||||
{
|
||||
if (ports_ == 0) {
|
||||
ports.clear();
|
||||
pdefs.clear();
|
||||
|
||||
/* Make sure the function has at least one input
|
||||
port. If it fails this test, print an error
|
||||
message. Keep going so we can find more errors. */
|
||||
if (scope->type()==NetScope::FUNC && !gn_system_verilog()) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< "Function " << scope->basename()
|
||||
<< " has no ports." << endl;
|
||||
cerr << get_fileline() << ": : "
|
||||
<< "Functions must have at least one input port." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
ports.resize(ports_->size());
|
||||
pdefs.resize(ports_->size());
|
||||
|
||||
for (size_t idx = 0 ; idx < ports_->size() ; idx += 1) {
|
||||
|
||||
perm_string port_name = ports_->at(idx).port->basename();
|
||||
|
||||
ports[idx] = 0;
|
||||
pdefs[idx] = 0;
|
||||
NetNet*tmp = scope->find_signal(port_name);
|
||||
NetExpr*tmp_def = 0;
|
||||
if (tmp == 0) {
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<< "task/function " << scope_path(scope)
|
||||
<< " is missing port " << port_name << "." << endl;
|
||||
scope->dump(cerr);
|
||||
cerr << get_fileline() << ": Continuing..." << endl;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
// If the port has a default expression that can be used
|
||||
// as a value when the caller doesn't bind, then
|
||||
// elaborate that expression here. This expression
|
||||
// should evaluate down do a constant.
|
||||
if (ports_->at(idx).defe != 0) {
|
||||
tmp_def = elab_and_eval(des, scope, ports_->at(idx).defe, -1, true);
|
||||
if (tmp_def==0) {
|
||||
cerr << get_fileline() << ": error: Unable to evaluate "
|
||||
<< *ports_->at(idx).defe
|
||||
<< " as a port default (constant) expression." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (tmp->port_type() == NetNet::NOT_A_PORT) {
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<< "task/function " << scope_path(scope)
|
||||
<< " port " << port_name
|
||||
<< " is a port but is not a port?" << endl;
|
||||
des->errors += 1;
|
||||
scope->dump(cerr);
|
||||
continue;
|
||||
}
|
||||
|
||||
ports[idx] = tmp;
|
||||
pdefs[idx] = tmp_def;
|
||||
if (scope->type()==NetScope::FUNC && tmp->port_type()!=NetNet::PINPUT) {
|
||||
cerr << tmp->get_fileline() << ": error: "
|
||||
<< "Function " << scope_path(scope)
|
||||
<< " port " << port_name
|
||||
<< " is not an input port." << endl;
|
||||
cerr << tmp->get_fileline() << ": : "
|
||||
<< "Function arguments must be input ports." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PBlock::elaborate_sig(Design*des, NetScope*scope) const
|
||||
{
|
||||
NetScope*my_scope = scope;
|
||||
@@ -793,12 +807,24 @@ void PDelayStatement::elaborate_sig(Design*des, NetScope*scope) const
|
||||
statement_->elaborate_sig(des, scope);
|
||||
}
|
||||
|
||||
void PDoWhile::elaborate_sig(Design*des, NetScope*scope) const
|
||||
{
|
||||
if (statement_)
|
||||
statement_->elaborate_sig(des, scope);
|
||||
}
|
||||
|
||||
void PEventStatement::elaborate_sig(Design*des, NetScope*scope) const
|
||||
{
|
||||
if (statement_)
|
||||
statement_->elaborate_sig(des, scope);
|
||||
}
|
||||
|
||||
void PForeach::elaborate_sig(Design*des, NetScope*scope) const
|
||||
{
|
||||
if (statement_)
|
||||
statement_->elaborate_sig(des, scope);
|
||||
}
|
||||
|
||||
void PForever::elaborate_sig(Design*des, NetScope*scope) const
|
||||
{
|
||||
if (statement_)
|
||||
@@ -823,96 +849,11 @@ void PWhile::elaborate_sig(Design*des, NetScope*scope) const
|
||||
statement_->elaborate_sig(des, scope);
|
||||
}
|
||||
|
||||
static bool evaluate_ranges(Design*des, NetScope*scope,
|
||||
vector<netrange_t>&llist,
|
||||
const list<pform_range_t>&rlist)
|
||||
{
|
||||
bool bad_msb = false, bad_lsb = false;
|
||||
|
||||
for (list<pform_range_t>::const_iterator cur = rlist.begin()
|
||||
; cur != rlist.end() ; ++cur) {
|
||||
long use_msb, use_lsb;
|
||||
|
||||
NetExpr*texpr = elab_and_eval(des, scope, cur->first, -1, true);
|
||||
if (! eval_as_long(use_msb, texpr)) {
|
||||
cerr << cur->first->get_fileline() << ": error: "
|
||||
"Range expressions must be constant." << endl;
|
||||
cerr << cur->first->get_fileline() << " : "
|
||||
"This MSB expression violates the rule: "
|
||||
<< *cur->first << endl;
|
||||
des->errors += 1;
|
||||
bad_msb = true;
|
||||
}
|
||||
|
||||
delete texpr;
|
||||
|
||||
texpr = elab_and_eval(des, scope, cur->second, -1, true);
|
||||
if (! eval_as_long(use_lsb, texpr)) {
|
||||
cerr << cur->second->get_fileline() << ": error: "
|
||||
"Range expressions must be constant." << endl;
|
||||
cerr << cur->second->get_fileline() << " : "
|
||||
"This LSB expression violates the rule: "
|
||||
<< *cur->second << endl;
|
||||
des->errors += 1;
|
||||
bad_lsb = true;
|
||||
}
|
||||
|
||||
delete texpr;
|
||||
|
||||
llist.push_back(netrange_t(use_msb, use_lsb));
|
||||
}
|
||||
|
||||
return bad_msb | bad_lsb;
|
||||
}
|
||||
|
||||
static netclass_t* locate_class_type(Design*des, NetScope*scope,
|
||||
class_type_t*class_type)
|
||||
{
|
||||
netclass_t*use_class = scope->find_class(class_type->name);
|
||||
return use_class;
|
||||
}
|
||||
|
||||
static netstruct_t* elaborate_struct_type(Design*des, NetScope*scope,
|
||||
struct_type_t*struct_type)
|
||||
{
|
||||
netstruct_t*res = new netstruct_t;
|
||||
|
||||
res->packed(struct_type->packed_flag);
|
||||
|
||||
for (list<struct_member_t*>::iterator cur = struct_type->members->begin()
|
||||
; cur != struct_type->members->end() ; ++ cur) {
|
||||
|
||||
vector<netrange_t>packed_dimensions;
|
||||
|
||||
struct_member_t*curp = *cur;
|
||||
if (curp->range.get() && ! curp->range->empty()) {
|
||||
bool bad_range;
|
||||
bad_range = evaluate_ranges(des, scope, packed_dimensions, *curp->range);
|
||||
ivl_assert(*curp, !bad_range);
|
||||
} else {
|
||||
packed_dimensions.push_back(netrange_t(0,0));
|
||||
}
|
||||
|
||||
for (list<decl_assignment_t*>::iterator name = curp->names->begin()
|
||||
; name != curp->names->end() ; ++ name) {
|
||||
decl_assignment_t*namep = *name;
|
||||
|
||||
netstruct_t::member_t memb;
|
||||
memb.name = namep->name;
|
||||
memb.type = curp->type;
|
||||
memb.packed_dims = packed_dimensions;
|
||||
res->append_member(memb);
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static ivl_type_s*elaborate_type(Design*des, NetScope*scope,
|
||||
data_type_t*pform_type)
|
||||
{
|
||||
if (struct_type_t*struct_type = dynamic_cast<struct_type_t*>(pform_type)) {
|
||||
netstruct_t*use_type = elaborate_struct_type(des, scope, struct_type);
|
||||
ivl_type_s*use_type = struct_type->elaborate_type(des, scope);
|
||||
return use_type;
|
||||
}
|
||||
|
||||
@@ -928,7 +869,7 @@ static netparray_t* elaborate_parray_type(Design*des, NetScope*scope,
|
||||
{
|
||||
|
||||
vector<netrange_t>packed_dimensions;
|
||||
bool bad_range = evaluate_ranges(des, scope, packed_dimensions, * data_type->packed_dims);
|
||||
bool bad_range = evaluate_ranges(des, scope, packed_dimensions, * data_type->dims);
|
||||
ivl_assert(*data_type, !bad_range);
|
||||
|
||||
ivl_type_s*element_type = elaborate_type(des, scope, data_type->base_type);
|
||||
@@ -985,7 +926,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
des->errors += error_cnt_;
|
||||
|
||||
// A signal can not have the same name as a scope object.
|
||||
const NetScope *child = scope->child(hname_t(name_));
|
||||
const NetScope *child = scope->child_byname(name_);
|
||||
if (child) {
|
||||
cerr << get_fileline() << ": error: signal and ";
|
||||
child->print_type(cerr);
|
||||
@@ -1001,7 +942,10 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
<< "'." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
// A signal can not have the same name as a parameter.
|
||||
// A signal can not have the same name as a parameter. Note
|
||||
// that we treat enumeration literals similar to parameters,
|
||||
// so if the name matches an enumeration literal, it will be
|
||||
// caught here.
|
||||
const NetExpr *ex_msb, *ex_lsb;
|
||||
const NetExpr *parm = scope->get_parameter(des, name_, ex_msb, ex_lsb);
|
||||
if (parm) {
|
||||
@@ -1024,6 +968,10 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
vector<netrange_t> plist, nlist;
|
||||
/* If they exist get the port definition MSB and LSB */
|
||||
if (port_set_ && !port_.empty()) {
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PWire::elaborate_sig: "
|
||||
<< "Evaluate ranges for port " << basename() << endl;
|
||||
}
|
||||
bad_range |= evaluate_ranges(des, scope, plist, port_);
|
||||
nlist = plist;
|
||||
/* An implicit port can have a range so note that here. */
|
||||
@@ -1034,13 +982,19 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
/* If they exist get the net/etc. definition MSB and LSB */
|
||||
if (net_set_ && !net_.empty() && !bad_range) {
|
||||
nlist.clear();
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PWire::elaborate_sig: "
|
||||
<< "Evaluate ranges for net " << basename() << endl;
|
||||
}
|
||||
bad_range |= evaluate_ranges(des, scope, nlist, net_);
|
||||
}
|
||||
assert(net_set_ || net_.empty());
|
||||
|
||||
/* If we find errors here, then give up on this signal. */
|
||||
if (bad_range)
|
||||
return 0;
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PWire::elaborate_sig: "
|
||||
<< "Calculated ranges for " << basename()
|
||||
<< ". Now check for consistency." << endl;
|
||||
}
|
||||
|
||||
/* We have a port size error */
|
||||
if (port_set_ && net_set_ && !test_ranges_eeq(plist, nlist)) {
|
||||
@@ -1097,7 +1051,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
|
||||
|
||||
list<netrange_t>unpacked_dimensions;
|
||||
netdarray_t*netarray = 0;
|
||||
netdarray_t*netdarray = 0;
|
||||
|
||||
for (list<pform_range_t>::const_iterator cur = unpacked_.begin()
|
||||
; cur != unpacked_.end() ; ++cur) {
|
||||
@@ -1110,13 +1064,23 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
if (use_lidx==0 && use_ridx==0) {
|
||||
netvector_t*vec = new netvector_t(packed_dimensions, data_type_);
|
||||
packed_dimensions.clear();
|
||||
ivl_assert(*this, netarray==0);
|
||||
netarray = new netdarray_t(vec);
|
||||
ivl_assert(*this, netdarray==0);
|
||||
netdarray = new netdarray_t(vec);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Special case: Detect the mark for a QUEUE
|
||||
// declaration, which is the dimensions [null:<nil>].
|
||||
if (use_ridx==0 && dynamic_cast<PENull*>(use_lidx)) {
|
||||
netvector_t*vec = new netvector_t(packed_dimensions, data_type_);
|
||||
packed_dimensions.clear();
|
||||
ivl_assert(*this, netdarray==0);
|
||||
netdarray = new netqueue_t(vec);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Cannot handle dynamic arrays of arrays yet.
|
||||
ivl_assert(*this, netarray==0);
|
||||
ivl_assert(*this, netdarray==0);
|
||||
ivl_assert(*this, use_lidx && use_ridx);
|
||||
|
||||
NetExpr*lexp = elab_and_eval(des, scope, use_lidx, -1, true);
|
||||
@@ -1209,15 +1173,17 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
// should already have been elaborated. All we need to
|
||||
// do right now is locate the netclass_t object for the
|
||||
// class, and use that to build the net.
|
||||
netclass_t*use_type = locate_class_type(des, scope, class_type);
|
||||
// (No arrays of classes)
|
||||
list<netrange_t> use_unpacked;
|
||||
sig = new NetNet(scope, name_, wtype, use_unpacked, use_type);
|
||||
|
||||
ivl_assert(*this, class_type->save_elaborated_type);
|
||||
netclass_t*use_type = class_type->save_elaborated_type;
|
||||
|
||||
sig = new NetNet(scope, name_, wtype, unpacked_dimensions, use_type);
|
||||
|
||||
} else if (struct_type_t*struct_type = dynamic_cast<struct_type_t*>(set_data_type_)) {
|
||||
// If this is a struct type, then build the net with the
|
||||
// struct type.
|
||||
netstruct_t*use_type = elaborate_struct_type(des, scope, struct_type);
|
||||
ivl_type_s*tmp_type = struct_type->elaborate_type(des, scope);
|
||||
netstruct_t*use_type = dynamic_cast<netstruct_t*>(tmp_type);
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: Create signal " << wtype;
|
||||
if (use_type->packed())
|
||||
@@ -1232,7 +1198,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
|
||||
} else if (enum_type_t*enum_type = dynamic_cast<enum_type_t*>(set_data_type_)) {
|
||||
list<named_pexpr_t>::const_iterator sample_name = enum_type->names->begin();
|
||||
netenum_t*use_enum = scope->enumeration_for_name(sample_name->name);
|
||||
const netenum_t*use_enum = scope->find_enumeration_for_name(sample_name->name);
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: Create signal " << wtype
|
||||
@@ -1246,7 +1212,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
sig = new NetNet(scope, name_, wtype, unpacked_dimensions, use_enum);
|
||||
|
||||
|
||||
} else if (netarray) {
|
||||
} else if (netdarray) {
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: Create signal " << wtype
|
||||
@@ -1256,7 +1222,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
|
||||
ivl_assert(*this, packed_dimensions.empty());
|
||||
ivl_assert(*this, unpacked_dimensions.empty());
|
||||
sig = new NetNet(scope, name_, wtype, netarray);
|
||||
sig = new NetNet(scope, name_, wtype, netdarray);
|
||||
|
||||
} else if (parray_type_t*parray_type = dynamic_cast<parray_type_t*>(set_data_type_)) {
|
||||
// The pform gives us a parray_type_t for packed arrays
|
||||
@@ -1266,13 +1232,13 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
// The trick here is that the parray type has an
|
||||
// arbitrary sub-type, and not just a scalar bit...
|
||||
netparray_t*use_type = elaborate_parray_type(des, scope, parray_type);
|
||||
// Should not be getting packed dimensions other then
|
||||
// Should not be getting packed dimensions other than
|
||||
// through the parray type declaration.
|
||||
ivl_assert(*this, packed_dimensions.empty());
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: Create signal " << wtype
|
||||
<< " parray=" << use_type->packed_dimensions()
|
||||
<< " parray=" << use_type->static_dimensions()
|
||||
<< " " << name_ << unpacked_dimensions
|
||||
<< " in scope " << scope_path(scope) << endl;
|
||||
}
|
||||
@@ -1327,3 +1293,27 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
|
||||
return sig;
|
||||
}
|
||||
|
||||
|
||||
void Design::root_elaborate_sig(void)
|
||||
{
|
||||
for (map<perm_string,netclass_t*>::const_iterator cur = classes_.begin()
|
||||
; cur != classes_.end() ; ++ cur) {
|
||||
|
||||
netclass_t*cur_class = cur->second;
|
||||
PClass*cur_pclass = class_to_pclass_[cur_class];
|
||||
|
||||
cur_class->elaborate_sig(this, cur_pclass);
|
||||
}
|
||||
|
||||
for (map<NetScope*,PTaskFunc*>::iterator cur = root_tasks_.begin()
|
||||
; cur != root_tasks_.end() ; ++ cur) {
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << cur->second->get_fileline() << ": root_elaborate_sig: "
|
||||
<< "Elaborate_sig for root task/func " << scope_path(cur->first) << endl;
|
||||
}
|
||||
|
||||
cur->second->elaborate_sig(this, cur->first);
|
||||
}
|
||||
}
|
||||
|
||||
+185
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2012-2014 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -19,13 +19,39 @@
|
||||
|
||||
# include "pform_types.h"
|
||||
# include "netlist.h"
|
||||
# include "netclass.h"
|
||||
# include "netdarray.h"
|
||||
# include "netenum.h"
|
||||
# include "netparray.h"
|
||||
# include "netscalar.h"
|
||||
# include "netstruct.h"
|
||||
# include "netvector.h"
|
||||
# include "netmisc.h"
|
||||
# include <typeinfo>
|
||||
# include "ivl_assert.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
ivl_type_s* data_type_t::elaborate_type(Design*des, NetScope*) const
|
||||
/*
|
||||
* Elaborations of types may vary depending on the scope that it is
|
||||
* done in, so keep a per-scope cache of the results.
|
||||
*/
|
||||
ivl_type_s* data_type_t::elaborate_type(Design*des, NetScope*scope)
|
||||
{
|
||||
Definitions*use_definitions = scope;
|
||||
if (use_definitions == 0)
|
||||
use_definitions = des;
|
||||
|
||||
map<Definitions*,ivl_type_s*>::iterator pos = cache_type_elaborate_.lower_bound(use_definitions);
|
||||
if (pos->first == use_definitions)
|
||||
return pos->second;
|
||||
|
||||
ivl_type_s*tmp = elaborate_type_raw(des, scope);
|
||||
cache_type_elaborate_.insert(pos, pair<NetScope*,ivl_type_s*>(scope, tmp));
|
||||
return tmp;
|
||||
}
|
||||
|
||||
ivl_type_s* data_type_t::elaborate_type_raw(Design*des, NetScope*) const
|
||||
{
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<< "Elaborate method not implemented for " << typeid(*this).name()
|
||||
@@ -34,9 +60,15 @@ ivl_type_s* data_type_t::elaborate_type(Design*des, NetScope*) const
|
||||
return 0;
|
||||
}
|
||||
|
||||
ivl_type_s* atom2_type_t::elaborate_type(Design*des, NetScope*) const
|
||||
ivl_type_s* atom2_type_t::elaborate_type_raw(Design*des, NetScope*) const
|
||||
{
|
||||
switch (type_code) {
|
||||
case 64:
|
||||
if (signed_flag)
|
||||
return &netvector_t::atom2s64;
|
||||
else
|
||||
return &netvector_t::atom2u64;
|
||||
|
||||
case 32:
|
||||
if (signed_flag)
|
||||
return &netvector_t::atom2s32;
|
||||
@@ -62,3 +94,153 @@ ivl_type_s* atom2_type_t::elaborate_type(Design*des, NetScope*) const
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
ivl_type_s* class_type_t::elaborate_type_raw(Design*, NetScope*) const
|
||||
{
|
||||
ivl_assert(*this, save_elaborated_type);
|
||||
return save_elaborated_type;
|
||||
}
|
||||
|
||||
/*
|
||||
* elaborate_type_raw for enumerations is actually mostly performed
|
||||
* during scope elaboration so that the enumeration literals are
|
||||
* available at the right time. At that time, the netenum_t* object is
|
||||
* stashed in the scope so that I can retrieve it here.
|
||||
*/
|
||||
ivl_type_s* enum_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
|
||||
{
|
||||
ivl_assert(*this, scope);
|
||||
ivl_type_s*tmp = scope->enumeration_for_key(this);
|
||||
if (tmp) return tmp;
|
||||
|
||||
tmp = des->enumeration_for_key(this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
ivl_type_s* vector_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
|
||||
{
|
||||
vector<netrange_t> packed;
|
||||
|
||||
if (pdims.get()) {
|
||||
for (list<pform_range_t>::const_iterator cur = pdims->begin()
|
||||
; cur != pdims->end() ; ++ cur) {
|
||||
|
||||
NetExpr*me = elab_and_eval(des, scope, cur->first, 0, true);
|
||||
|
||||
NetExpr*le = elab_and_eval(des, scope, cur->second, 0, true);
|
||||
|
||||
/* If elaboration failed for either expression, we
|
||||
should have already reported the error, so just
|
||||
skip the following evaluation to recover. */
|
||||
|
||||
long mnum = 0, lnum = 0;
|
||||
if ( me && ! eval_as_long(mnum, me) ) {
|
||||
assert(0);
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
if ( le && ! eval_as_long(lnum, le) ) {
|
||||
assert(0);
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
packed.push_back(netrange_t(mnum, lnum));
|
||||
}
|
||||
}
|
||||
|
||||
netvector_t*tmp = new netvector_t(packed, base_type);
|
||||
tmp->set_signed(signed_flag);
|
||||
tmp->set_isint(integer_flag);
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
ivl_type_s* real_type_t::elaborate_type_raw(Design*, NetScope*) const
|
||||
{
|
||||
switch (type_code) {
|
||||
case REAL:
|
||||
return &netreal_t::type_real;
|
||||
case SHORTREAL:
|
||||
return &netreal_t::type_shortreal;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
ivl_type_s* string_type_t::elaborate_type_raw(Design*, NetScope*) const
|
||||
{
|
||||
return &netstring_t::type_string;
|
||||
}
|
||||
|
||||
ivl_type_s* parray_type_t::elaborate_type_raw(Design*des, NetScope*) const
|
||||
{
|
||||
cerr << get_fileline() << " : sorry: "
|
||||
<< "Packed arrays are not currently supported in this context."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
netstruct_t* struct_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
|
||||
{
|
||||
netstruct_t*res = new netstruct_t;
|
||||
|
||||
res->packed(packed_flag);
|
||||
|
||||
if (union_flag)
|
||||
res->union_flag(true);
|
||||
|
||||
for (list<struct_member_t*>::iterator cur = members->begin()
|
||||
; cur != members->end() ; ++ cur) {
|
||||
|
||||
// Elaborate the type of the member.
|
||||
struct_member_t*curp = *cur;
|
||||
ivl_type_t mem_vec = curp->type->elaborate_type(des, scope);
|
||||
if (mem_vec == 0)
|
||||
continue;
|
||||
|
||||
// There may be several names that are the same type:
|
||||
// <data_type> name1, name2, ...;
|
||||
// Process all the member, and give them a type.
|
||||
for (list<decl_assignment_t*>::iterator name = curp->names->begin()
|
||||
; name != curp->names->end() ; ++ name) {
|
||||
decl_assignment_t*namep = *name;
|
||||
|
||||
netstruct_t::member_t memb;
|
||||
memb.name = namep->name;
|
||||
memb.net_type = mem_vec;
|
||||
res->append_member(des, memb);
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
ivl_type_s* uarray_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
|
||||
{
|
||||
|
||||
ivl_type_t btype = base_type->elaborate_type(des, scope);
|
||||
|
||||
assert(dims->size() >= 1);
|
||||
list<pform_range_t>::const_iterator cur = dims->begin();
|
||||
|
||||
// Special case: if the dimension is nil:nil, this is a
|
||||
// dynamic array. Note that we only know how to handle dynamic
|
||||
// arrays with 1 dimension at a time.
|
||||
if (cur->first==0 && cur->second==0) {
|
||||
assert(dims->size()==1);
|
||||
ivl_type_s*res = new netdarray_t(btype);
|
||||
return res;
|
||||
}
|
||||
|
||||
vector<netrange_t> dimensions;
|
||||
bool bad_range = evaluate_ranges(des, scope, dimensions, *dims);
|
||||
|
||||
if (bad_range) {
|
||||
cerr << get_fileline() << " : warning: "
|
||||
<< "Bad dimensions for type here." << endl;
|
||||
}
|
||||
|
||||
ivl_assert(*this, btype);
|
||||
ivl_type_s*res = new netuarray_t(dimensions, btype);
|
||||
return res;
|
||||
}
|
||||
|
||||
+1376
-246
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998-2011 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-2013 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -26,7 +26,9 @@
|
||||
* target.
|
||||
*/
|
||||
# include "target.h"
|
||||
# include "netclass.h"
|
||||
# include "netlist.h"
|
||||
# include "compiler.h"
|
||||
# include <typeinfo>
|
||||
# include <cassert>
|
||||
# include <cstring>
|
||||
@@ -165,6 +167,11 @@ bool NetSignExtend::emit_node(struct target_t*tgt) const
|
||||
return tgt->sign_extend(this);
|
||||
}
|
||||
|
||||
bool NetSubstitute::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->substitute(this);
|
||||
}
|
||||
|
||||
bool NetUReduce::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->ureduce(this);
|
||||
@@ -259,6 +266,17 @@ bool NetDisable::emit_proc(struct target_t*tgt) const
|
||||
return tgt->proc_disable(this);
|
||||
}
|
||||
|
||||
bool NetDoWhile::emit_proc(struct target_t*tgt) const
|
||||
{
|
||||
tgt->proc_do_while(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
void NetDoWhile::emit_proc_recurse(struct target_t*tgt) const
|
||||
{
|
||||
proc_->emit_proc(tgt);
|
||||
}
|
||||
|
||||
bool NetForce::emit_proc(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->proc_force(this);
|
||||
@@ -270,6 +288,11 @@ bool NetForever::emit_proc(struct target_t*tgt) const
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetForLoop::emit_proc(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->proc_block(as_block_);
|
||||
}
|
||||
|
||||
bool NetFree::emit_proc(struct target_t*tgt) const
|
||||
{
|
||||
tgt->proc_free(this);
|
||||
@@ -316,6 +339,11 @@ bool NetWhile::emit_proc(struct target_t*tgt) const
|
||||
return true;
|
||||
}
|
||||
|
||||
void NetWhile::emit_proc_recurse(struct target_t*tgt) const
|
||||
{
|
||||
proc_->emit_proc(tgt);
|
||||
}
|
||||
|
||||
void NetBlock::emit_recurse(struct target_t*tgt) const
|
||||
{
|
||||
if (last_ == 0)
|
||||
@@ -378,20 +406,32 @@ void NetRepeat::emit_recurse(struct target_t*tgt) const
|
||||
statement_->emit_proc(tgt);
|
||||
}
|
||||
|
||||
void netclass_t::emit_scope(struct target_t*tgt) const
|
||||
{
|
||||
class_scope_->emit_scope(tgt);
|
||||
}
|
||||
|
||||
void NetScope::emit_scope(struct target_t*tgt) const
|
||||
{
|
||||
if (debug_emit) {
|
||||
cerr << "NetScope::emit_scope: "
|
||||
<< "Emit scope " << scope_path(this) << endl;
|
||||
}
|
||||
|
||||
tgt->scope(this);
|
||||
|
||||
for (NetEvent*cur = events_ ; cur ; cur = cur->snext_)
|
||||
tgt->event(cur);
|
||||
|
||||
for (map<perm_string,netclass_t*>::const_iterator cur = classes_.begin()
|
||||
; cur != classes_.end() ; ++cur)
|
||||
; cur != classes_.end() ; ++cur) {
|
||||
cur->second->emit_scope(tgt);
|
||||
tgt->class_type(this, cur->second);
|
||||
}
|
||||
|
||||
for (list<netenum_t*>::const_iterator cur = enum_sets_.begin()
|
||||
for (map<const enum_type_t*,netenum_t*>::const_iterator cur = enum_sets_.begin()
|
||||
; cur != enum_sets_.end() ; ++cur)
|
||||
tgt->enumeration(this, *cur);
|
||||
tgt->enumeration(this, cur->second);
|
||||
|
||||
for (map<hname_t,NetScope*>::const_iterator cur = children_.begin()
|
||||
; cur != children_.end() ; ++ cur )
|
||||
@@ -420,11 +460,20 @@ bool NetScope::emit_defs(struct target_t*tgt) const
|
||||
{
|
||||
bool flag = true;
|
||||
|
||||
if (debug_emit) {
|
||||
cerr << "NetScope::emit_defs: "
|
||||
<< "Emit definitions for " << scope_path(this) << endl;
|
||||
}
|
||||
|
||||
switch (type_) {
|
||||
case PACKAGE:
|
||||
case MODULE:
|
||||
for (map<hname_t,NetScope*>::const_iterator cur = children_.begin()
|
||||
; cur != children_.end() ; ++ cur )
|
||||
flag &= cur->second->emit_defs(tgt);
|
||||
for (map<perm_string,netclass_t*>::const_iterator cur = classes_.begin()
|
||||
; cur != classes_.end() ; ++ cur)
|
||||
flag &= cur->second->emit_defs(tgt);
|
||||
break;
|
||||
|
||||
case FUNC:
|
||||
@@ -443,9 +492,9 @@ bool NetScope::emit_defs(struct target_t*tgt) const
|
||||
return flag;
|
||||
}
|
||||
|
||||
void NetWhile::emit_proc_recurse(struct target_t*tgt) const
|
||||
bool netclass_t::emit_defs(struct target_t*tgt) const
|
||||
{
|
||||
proc_->emit_proc(tgt);
|
||||
return class_scope_->emit_defs(tgt);
|
||||
}
|
||||
|
||||
int Design::emit(struct target_t*tgt) const
|
||||
@@ -455,11 +504,31 @@ int Design::emit(struct target_t*tgt) const
|
||||
if (tgt->start_design(this) == false)
|
||||
return -2;
|
||||
|
||||
// enumerate the scopes
|
||||
for (list<NetScope*>::const_iterator scope = root_scopes_.begin();
|
||||
scope != root_scopes_.end(); ++ scope )
|
||||
(*scope)->emit_scope(tgt);
|
||||
for (map<NetScope*,PTaskFunc*>::const_iterator scope = root_tasks_.begin()
|
||||
; scope != root_tasks_.end() ; ++ scope) {
|
||||
scope->first->emit_scope(tgt);
|
||||
scope->first->emit_defs(tgt);
|
||||
}
|
||||
|
||||
// enumerate package scopes
|
||||
for (map<perm_string,NetScope*>::const_iterator scope = packages_.begin()
|
||||
; scope != packages_.end() ; ++ scope) {
|
||||
scope->second->emit_scope(tgt);
|
||||
}
|
||||
|
||||
for (map<perm_string,netclass_t*>::const_iterator cur = classes_.begin()
|
||||
; cur != classes_.end() ; ++cur) {
|
||||
const NetScope*use_scope = cur->second->class_scope();
|
||||
cur->second->emit_scope(tgt);
|
||||
tgt->class_type(use_scope, cur->second);
|
||||
cur->second->emit_defs(tgt);
|
||||
}
|
||||
|
||||
// enumerate root scopes
|
||||
for (list<NetScope*>::const_iterator scope = root_scopes_.begin()
|
||||
; scope != root_scopes_.end(); ++ scope ) {
|
||||
(*scope)->emit_scope(tgt);
|
||||
}
|
||||
|
||||
// emit nodes
|
||||
bool nodes_rc = true;
|
||||
@@ -479,8 +548,11 @@ int Design::emit(struct target_t*tgt) const
|
||||
|
||||
// emit task and function definitions
|
||||
bool tasks_rc = true;
|
||||
for (list<NetScope*>::const_iterator scope = root_scopes_.begin();
|
||||
scope != root_scopes_.end(); ++ scope )
|
||||
for (map<perm_string,NetScope*>::const_iterator scope = packages_.begin()
|
||||
; scope != packages_.end() ; ++ scope )
|
||||
tasks_rc &= scope->second->emit_defs(tgt);
|
||||
for (list<NetScope*>::const_iterator scope = root_scopes_.begin()
|
||||
; scope != root_scopes_.end(); ++ scope )
|
||||
tasks_rc &= (*scope)->emit_defs(tgt);
|
||||
|
||||
|
||||
@@ -491,6 +563,15 @@ int Design::emit(struct target_t*tgt) const
|
||||
for (const NetAnalogTop*idx = aprocs_ ; idx ; idx = idx->next_)
|
||||
proc_rc &= idx->emit(tgt);
|
||||
|
||||
if (nodes_rc == false)
|
||||
tgt->errors += 1;
|
||||
if (tasks_rc == false)
|
||||
tgt->errors += 1;
|
||||
if (proc_rc == false)
|
||||
tgt->errors += 1;
|
||||
if (branches_rc == false)
|
||||
tgt->errors += 1;
|
||||
|
||||
rc = tgt->end_design(this);
|
||||
|
||||
if (nodes_rc == false)
|
||||
@@ -498,7 +579,7 @@ int Design::emit(struct target_t*tgt) const
|
||||
if (tasks_rc == false)
|
||||
return -2;
|
||||
if (proc_rc == false)
|
||||
return -3;
|
||||
return -3;
|
||||
if (branches_rc == false)
|
||||
return -4;
|
||||
|
||||
@@ -510,6 +591,11 @@ void NetEAccess::expr_scan(struct expr_scan_t*tgt) const
|
||||
tgt->expr_access_func(this);
|
||||
}
|
||||
|
||||
void NetEArrayPattern::expr_scan(struct expr_scan_t*tgt) const
|
||||
{
|
||||
tgt->expr_array_pattern(this);
|
||||
}
|
||||
|
||||
void NetEBinary::expr_scan(struct expr_scan_t*tgt) const
|
||||
{
|
||||
tgt->expr_binary(this);
|
||||
@@ -550,6 +636,11 @@ void NetEEvent::expr_scan(struct expr_scan_t*tgt) const
|
||||
tgt->expr_event(this);
|
||||
}
|
||||
|
||||
void NetELast::expr_scan(struct expr_scan_t*tgt) const
|
||||
{
|
||||
tgt->expr_last(this);
|
||||
}
|
||||
|
||||
void NetENetenum::expr_scan(struct expr_scan_t*tgt) const
|
||||
{
|
||||
tgt->expr_netenum(this);
|
||||
@@ -585,6 +676,21 @@ void NetESFunc::expr_scan(struct expr_scan_t*tgt) const
|
||||
tgt->expr_sfunc(this);
|
||||
}
|
||||
|
||||
void NetEShallowCopy::expr_scan(struct expr_scan_t*tgt) const
|
||||
{
|
||||
tgt->expr_scopy(this);
|
||||
}
|
||||
|
||||
void NetEShallowCopy::expr_scan_oper1(struct expr_scan_t*tgt) const
|
||||
{
|
||||
arg1_->expr_scan(tgt);
|
||||
}
|
||||
|
||||
void NetEShallowCopy::expr_scan_oper2(struct expr_scan_t*tgt) const
|
||||
{
|
||||
arg2_->expr_scan(tgt);
|
||||
}
|
||||
|
||||
void NetEUFunc::expr_scan(struct expr_scan_t*tgt) const
|
||||
{
|
||||
tgt->expr_ufunc(this);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998-1999 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-2014 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -44,6 +44,14 @@ verinum* PEBinary::eval_const(Design*des, NetScope*scope) const
|
||||
verinum*res;
|
||||
|
||||
switch (op_) {
|
||||
case 'p': {
|
||||
if (l->is_defined() && r->is_defined()) {
|
||||
res = new verinum(pow(*l, *r));
|
||||
} else {
|
||||
res = new verinum(verinum::Vx, l->len());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case '+': {
|
||||
if (l->is_defined() && r->is_defined()) {
|
||||
res = new verinum(*l + *r);
|
||||
@@ -261,7 +269,7 @@ verinum* PEUnary::eval_const(Design*des, NetScope*scope) const
|
||||
for (unsigned idx = 0 ; idx < val->len() ; idx += 1)
|
||||
tmp.set(idx, val->get(idx));
|
||||
|
||||
*val = v_not(tmp) + verinum(verinum::V1, 1);
|
||||
*val = -tmp;
|
||||
val->has_sign(true);
|
||||
return val;
|
||||
}
|
||||
|
||||
+781
-473
File diff suppressed because it is too large
Load Diff
+34
-8
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2012 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2013 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
|
||||
@@ -274,7 +274,7 @@ NetNet* NetEBComp::synthesize(Design*des, NetScope*scope, NetExpr*root)
|
||||
|
||||
if (op_ == 'E' || op_ == 'N') {
|
||||
NetCaseCmp*gate = new NetCaseCmp(scope, scope->local_symbol(),
|
||||
width, op_=='E'?true:false);
|
||||
width, op_=='E'?NetCaseCmp::EEQ:NetCaseCmp::NEQ);
|
||||
gate->set_line(*this);
|
||||
connect(gate->pin(0), osig->pin(0));
|
||||
connect(gate->pin(1), lsig->pin(0));
|
||||
@@ -615,7 +615,8 @@ NetNet* NetEBShift::synthesize(Design*des, NetScope*scope, NetExpr*root)
|
||||
// to the amount left by the shift.
|
||||
NetPartSelect*psel = new NetPartSelect(lsig, shift<0? ushift : 0,
|
||||
part_width,
|
||||
NetPartSelect::VP);
|
||||
NetPartSelect::VP,
|
||||
signed_flag && right_flag);
|
||||
psel->set_line(*this);
|
||||
des->add_node(psel);
|
||||
|
||||
@@ -980,7 +981,10 @@ NetNet* NetECast::synthesize(Design*des, NetScope*scope, NetExpr*root)
|
||||
|
||||
switch (op()) {
|
||||
case 'v':
|
||||
isig = cast_to_int4(des, scope, isig, isig->vector_width());
|
||||
isig = cast_to_int4(des, scope, isig, expr_width());
|
||||
break;
|
||||
case '2':
|
||||
isig = cast_to_int2(des, scope, isig, expr_width());
|
||||
break;
|
||||
case 'r':
|
||||
isig = cast_to_real(des, scope, isig);
|
||||
@@ -1267,6 +1271,22 @@ NetNet* NetETernary::synthesize(Design *des, NetScope*scope, NetExpr*root)
|
||||
*/
|
||||
NetNet* NetESignal::synthesize(Design*des, NetScope*scope, NetExpr*root)
|
||||
{
|
||||
// If this is a synthesis with a specific value for the
|
||||
// signal, then replace it (here) with a constant value.
|
||||
if (net_->scope()==scope && net_->name()==scope->genvar_tmp) {
|
||||
netvector_t*tmp_vec = new netvector_t(net_->data_type(),
|
||||
net_->vector_width()-1, 0);
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, tmp_vec);
|
||||
verinum tmp_val ((uint64_t)scope->genvar_tmp_val, net_->vector_width());
|
||||
NetConst*tmp_const = new NetConst(scope, scope->local_symbol(), tmp_val);
|
||||
tmp_const->set_line(*this);
|
||||
des->add_node(tmp_const);
|
||||
|
||||
connect(tmp->pin(0), tmp_const->pin(0));
|
||||
return tmp;
|
||||
}
|
||||
|
||||
if (word_ == 0)
|
||||
return net_;
|
||||
|
||||
@@ -1306,16 +1326,16 @@ static NetEvWait* make_func_trigger(Design*des, NetScope*scope, NetExpr*root)
|
||||
NetEvWait*trigger = 0;
|
||||
|
||||
NexusSet*nset = root->nex_input(false);
|
||||
if (nset && (nset->count() > 0)) {
|
||||
if (nset && (nset->size() > 0)) {
|
||||
NetEvent*ev = new NetEvent(scope->local_symbol());
|
||||
ev->set_line(*root);
|
||||
|
||||
NetEvProbe*pr = new NetEvProbe(scope, scope->local_symbol(),
|
||||
ev, NetEvProbe::ANYEDGE,
|
||||
nset->count());
|
||||
nset->size());
|
||||
pr->set_line(*root);
|
||||
for (unsigned idx = 0 ; idx < nset->count() ; idx += 1)
|
||||
connect(nset[0][idx], pr->pin(idx));
|
||||
for (unsigned idx = 0 ; idx < nset->size() ; idx += 1)
|
||||
connect(nset->at(idx).lnk, pr->pin(idx));
|
||||
|
||||
des->add_node(pr);
|
||||
|
||||
@@ -1436,6 +1456,12 @@ NetNet* NetEUFunc::synthesize(Design*des, NetScope*scope, NetExpr*root)
|
||||
osig->local_flag(true);
|
||||
connect(net->pin(0), osig->pin(0));
|
||||
|
||||
if (debug_synth2) {
|
||||
cerr << get_fileline() << ": NetEUFunc::synthesize: "
|
||||
<< "result_sig_->vector_width()=" << result_sig_->vector_width()
|
||||
<< ", osig->vector_width()=" << osig->vector_width() << endl;
|
||||
}
|
||||
|
||||
/* Connect the pins to the arguments. */
|
||||
NetFuncDef*def = func_->func_def();
|
||||
for (unsigned idx = 0; idx < eparms.size(); idx += 1) {
|
||||
|
||||
+20
@@ -24,6 +24,8 @@
|
||||
# include "functor.h"
|
||||
# include "netlist.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
functor_t::~functor_t()
|
||||
{
|
||||
}
|
||||
@@ -52,6 +54,10 @@ void functor_t::lpm_compare(Design*, NetCompare*)
|
||||
{
|
||||
}
|
||||
|
||||
void functor_t::lpm_concat(Design*, NetConcat*)
|
||||
{
|
||||
}
|
||||
|
||||
void functor_t::lpm_const(Design*, NetConst*)
|
||||
{
|
||||
}
|
||||
@@ -84,6 +90,10 @@ void functor_t::lpm_mux(Design*, NetMux*)
|
||||
{
|
||||
}
|
||||
|
||||
void functor_t::lpm_part_select(Design*, NetPartSelect*)
|
||||
{
|
||||
}
|
||||
|
||||
void functor_t::lpm_pow(Design*, NetPow*)
|
||||
{
|
||||
}
|
||||
@@ -185,6 +195,11 @@ void NetCompare::functor_node(Design*des, functor_t*fun)
|
||||
fun->lpm_compare(des, this);
|
||||
}
|
||||
|
||||
void NetConcat::functor_node(Design*des, functor_t*fun)
|
||||
{
|
||||
fun->lpm_concat(des, this);
|
||||
}
|
||||
|
||||
void NetConst::functor_node(Design*des, functor_t*fun)
|
||||
{
|
||||
fun->lpm_const(des, this);
|
||||
@@ -225,6 +240,11 @@ void NetMux::functor_node(Design*des, functor_t*fun)
|
||||
fun->lpm_mux(des, this);
|
||||
}
|
||||
|
||||
void NetPartSelect::functor_node(Design*des, functor_t*fun)
|
||||
{
|
||||
fun->lpm_part_select(des, this);
|
||||
}
|
||||
|
||||
void NetPow::functor_node(Design*des, functor_t*fun)
|
||||
{
|
||||
fun->lpm_pow(des, this);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __functor_H
|
||||
#define __functor_H
|
||||
#ifndef IVL_functor_H
|
||||
#define IVL_functor_H
|
||||
/*
|
||||
* Copyright (c) 1999-2008 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2014 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -57,6 +57,9 @@ struct functor_t {
|
||||
/* This method is called for each structural comparator. */
|
||||
virtual void lpm_compare(class Design*des, class NetCompare*);
|
||||
|
||||
/* This method is called for each structural concatenation. */
|
||||
virtual void lpm_concat(class Design*des, class NetConcat*);
|
||||
|
||||
/* This method is called for each structural constant. */
|
||||
virtual void lpm_const(class Design*des, class NetConst*);
|
||||
|
||||
@@ -81,6 +84,8 @@ struct functor_t {
|
||||
/* This method is called for each MUX. */
|
||||
virtual void lpm_mux(class Design*des, class NetMux*);
|
||||
|
||||
virtual void lpm_part_select(class Design*des, class NetPartSelect*);
|
||||
|
||||
/* This method is called for each power. */
|
||||
virtual void lpm_pow(class Design*des, class NetPow*);
|
||||
|
||||
@@ -100,4 +105,4 @@ struct proc_match_t {
|
||||
virtual int block(class NetBlock*);
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif /* IVL_functor_H */
|
||||
|
||||
@@ -141,6 +141,7 @@ ivl_lpm_width
|
||||
|
||||
ivl_lval_idx
|
||||
ivl_lval_mux
|
||||
ivl_lval_nest
|
||||
ivl_lval_part_off
|
||||
ivl_lval_property_idx
|
||||
ivl_lval_sel_type
|
||||
@@ -170,6 +171,11 @@ ivl_parameter_expr
|
||||
ivl_parameter_file
|
||||
ivl_parameter_lineno
|
||||
ivl_parameter_local
|
||||
ivl_parameter_lsb
|
||||
ivl_parameter_msb
|
||||
ivl_parameter_scope
|
||||
ivl_parameter_signed
|
||||
ivl_parameter_width
|
||||
|
||||
ivl_path_condit
|
||||
ivl_path_delay
|
||||
@@ -192,6 +198,8 @@ ivl_scope_attr_cnt
|
||||
ivl_scope_attr_val
|
||||
ivl_scope_basename
|
||||
ivl_scope_children
|
||||
ivl_scope_child
|
||||
ivl_scope_childs
|
||||
ivl_scope_class
|
||||
ivl_scope_classes
|
||||
ivl_scope_def
|
||||
@@ -313,6 +321,7 @@ ivl_type_packed_msb
|
||||
ivl_type_prop_name
|
||||
ivl_type_prop_type
|
||||
ivl_type_properties
|
||||
ivl_type_signed
|
||||
|
||||
ivl_udp_init
|
||||
ivl_udp_file
|
||||
|
||||
+4
-4
@@ -1,7 +1,7 @@
|
||||
#ifndef __ivl_alloc_H
|
||||
#define __ivl_alloc_H
|
||||
#ifndef IVL_ivl_alloc_H
|
||||
#define IVL_ivl_alloc_H
|
||||
/*
|
||||
* Copyright (C) 2010 Cary R. (cygcary@yahoo.com)
|
||||
* Copyright (C) 2010-2014 Cary R. (cygcary@yahoo.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -83,4 +83,4 @@
|
||||
__ivl_rtn; \
|
||||
})
|
||||
|
||||
#endif
|
||||
#endif /* IVL_ivl_alloc_H */
|
||||
|
||||
+4
-5
@@ -1,5 +1,7 @@
|
||||
#ifndef IVL_ivl_assert_H
|
||||
#define IVL_ivl_assert_H
|
||||
/*
|
||||
* Copyright (c) 2007-2010 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2007-2014 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -17,9 +19,6 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __ivl_assert_h
|
||||
#define __ivl_assert_h
|
||||
|
||||
# include <cstdlib>
|
||||
|
||||
#define ivl_assert(tok, expression) \
|
||||
@@ -32,4 +31,4 @@
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#endif
|
||||
#endif /* IVL_ivl_assert_H */
|
||||
|
||||
+93
-28
@@ -1,7 +1,7 @@
|
||||
#ifndef __ivl_target_H
|
||||
#define __ivl_target_H
|
||||
#ifndef IVL_ivl_target_H
|
||||
#define IVL_ivl_target_H
|
||||
/*
|
||||
* Copyright (c) 2000-2012 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -20,10 +20,11 @@
|
||||
*/
|
||||
|
||||
# include <inttypes.h>
|
||||
# include <stddef.h>
|
||||
|
||||
/* Re the _CLASS define: clang++ wants this to be class to match the
|
||||
* definition, but clang (the C) compiler needs it to be a struct
|
||||
* since class is not defined in C. They are effecively both pointers
|
||||
* since class is not defined in C. They are effectively both pointers
|
||||
* to an object so everything works out. */
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -165,7 +166,7 @@ typedef struct ivl_branch_s *ivl_branch_t;
|
||||
typedef struct ivl_delaypath_s*ivl_delaypath_t;
|
||||
typedef struct ivl_design_s *ivl_design_t;
|
||||
typedef _CLASS ivl_discipline_s*ivl_discipline_t;
|
||||
typedef _CLASS netenum_t *ivl_enumtype_t;
|
||||
typedef const _CLASS netenum_t*ivl_enumtype_t;
|
||||
typedef struct ivl_event_s *ivl_event_t;
|
||||
typedef struct ivl_expr_s *ivl_expr_t;
|
||||
typedef struct ivl_island_s *ivl_island_t;
|
||||
@@ -227,11 +228,13 @@ typedef enum ivl_expr_type_e {
|
||||
IVL_EX_NEW = 23,
|
||||
IVL_EX_NULL = 22,
|
||||
IVL_EX_NUMBER = 5,
|
||||
IVL_EX_ARRAY_PATTERN = 26,
|
||||
IVL_EX_PROPERTY = 24,
|
||||
IVL_EX_REALNUM = 16,
|
||||
IVL_EX_SCOPE = 6,
|
||||
IVL_EX_SELECT = 7,
|
||||
IVL_EX_SFUNC = 8,
|
||||
IVL_EX_SHALLOWCOPY = 25,
|
||||
IVL_EX_SIGNAL = 9,
|
||||
IVL_EX_STRING = 10,
|
||||
IVL_EX_TERNARY = 11,
|
||||
@@ -295,7 +298,10 @@ typedef enum ivl_lpm_type_e {
|
||||
IVL_LPM_CAST_INT2 = 35,
|
||||
IVL_LPM_CAST_REAL = 33,
|
||||
IVL_LPM_CONCAT = 16,
|
||||
IVL_LPM_CONCATZ = 36, /* Transparent concat */
|
||||
IVL_LPM_CMP_EEQ= 18, /* Case EQ (===) */
|
||||
IVL_LPM_CMP_EQX= 37, /* Windcard EQ (==?) */
|
||||
IVL_LPM_CMP_EQZ= 38, /* casez EQ */
|
||||
IVL_LPM_CMP_EQ = 10,
|
||||
IVL_LPM_CMP_GE = 1,
|
||||
IVL_LPM_CMP_GT = 2,
|
||||
@@ -322,6 +328,7 @@ typedef enum ivl_lpm_type_e {
|
||||
IVL_LPM_SHIFTR = 7,
|
||||
IVL_LPM_SIGN_EXT=27,
|
||||
IVL_LPM_SUB = 8,
|
||||
IVL_LPM_SUBSTITUTE=39,
|
||||
/* IVL_LPM_RAM = 9, / obsolete */
|
||||
IVL_LPM_UFUNC = 14
|
||||
} ivl_lpm_type_t;
|
||||
@@ -352,7 +359,9 @@ typedef enum ivl_scope_type_e {
|
||||
IVL_SCT_TASK = 2,
|
||||
IVL_SCT_BEGIN = 3,
|
||||
IVL_SCT_FORK = 4,
|
||||
IVL_SCT_GENERATE= 5
|
||||
IVL_SCT_GENERATE= 5,
|
||||
IVL_SCT_PACKAGE = 6,
|
||||
IVL_SCT_CLASS = 7
|
||||
} ivl_scope_type_t;
|
||||
|
||||
/* Signals (ivl_signal_t) that are ports into the scope that contains
|
||||
@@ -397,6 +406,7 @@ typedef enum ivl_statement_type_e {
|
||||
IVL_ST_DELAY = 11,
|
||||
IVL_ST_DELAYX = 12,
|
||||
IVL_ST_DISABLE = 13,
|
||||
IVL_ST_DO_WHILE = 30,
|
||||
IVL_ST_FORCE = 14,
|
||||
IVL_ST_FOREVER = 15,
|
||||
IVL_ST_FORK = 16,
|
||||
@@ -430,6 +440,7 @@ typedef enum ivl_variable_type_e {
|
||||
IVL_VT_STRING = 5,
|
||||
IVL_VT_DARRAY = 6, /* Array (esp. dynamic array) */
|
||||
IVL_VT_CLASS = 7, /* SystemVerilog class instances */
|
||||
IVL_VT_QUEUE = 8, /* SystemVerilog queue instances */
|
||||
IVL_VT_VECTOR = IVL_VT_LOGIC /* For compatibility */
|
||||
} ivl_variable_type_t;
|
||||
|
||||
@@ -770,7 +781,7 @@ extern unsigned ivl_event_lineno(ivl_event_t net);
|
||||
*
|
||||
* ivl_expr_net_type
|
||||
* This is used in some cases to carry more advanced type
|
||||
* descriptions. Over the long run, all type informatino will be
|
||||
* descriptions. Over the long run, all type information will be
|
||||
* moved into the ivl_type_t type description method.
|
||||
*
|
||||
* ivl_expr_width
|
||||
@@ -821,6 +832,20 @@ extern unsigned ivl_event_lineno(ivl_event_t net);
|
||||
* table. That number can be passed to ivl_type_prop_*() functions to
|
||||
* get details about the property.
|
||||
*
|
||||
* If the property is an array, then the ivl_expr_oper1() function
|
||||
* returns the canonical expression for accessing the element of the
|
||||
* property.
|
||||
*
|
||||
* - IVL_EX_NEW
|
||||
* This expression takes one or two operands. The first operand,
|
||||
* returned by ivl_expr_oper1() is the number of elements to create
|
||||
* for the dynamic array. The second operand, if present, is returned
|
||||
* by the ivl_expr_oper2() function. If this returns a non-nil
|
||||
* expression, it is the initial value to be written to the elements
|
||||
* of the array. If the expression is an IVL_EX_ARRAY_PATTERN, then
|
||||
* this is the very special case of a list of values to be written to
|
||||
* array elements.
|
||||
*
|
||||
* - IVL_EX_SELECT
|
||||
* This expression takes two operands, oper1 is the expression to
|
||||
* select from, and oper2 is the selection base. The ivl_expr_width
|
||||
@@ -829,9 +854,9 @@ extern unsigned ivl_event_lineno(ivl_event_t net);
|
||||
* conversion from signal units to vector units, so the result of
|
||||
* ivl_expr_oper1 should range from 0 to ivl_expr_width().
|
||||
*
|
||||
* This exprsesion is also used to implement string substrings. If the
|
||||
* This expression is also used to implement string substrings. If the
|
||||
* sub-expression (oper1) is IVL_VT_STRING, then the base expression
|
||||
* (oper2) is a charaster address, with 0 the first address of the
|
||||
* (oper2) is a character address, with 0 the first address of the
|
||||
* string, 1 the second, and so on. This is OPPOSITE how a part select
|
||||
* of a string cast to a vector works, to be aware. The size of the
|
||||
* expression is an even multiple of 8, and is 8 times the number of
|
||||
@@ -889,17 +914,17 @@ extern const char* ivl_expr_name(ivl_expr_t net);
|
||||
extern ivl_nature_t ivl_expr_nature(ivl_expr_t net);
|
||||
/* IVL_EX_BINARY IVL_EX_UNARY */
|
||||
extern char ivl_expr_opcode(ivl_expr_t net);
|
||||
/* IVL_EX_BINARY IVL_EX_UNARY, IVL_EX_MEMORY IVL_EX_TERNARY */
|
||||
/* IVL_EX_BINARY IVL_EX_UNARY, IVL_EX_MEMORY IVL_EX_NEW IVL_EX_TERNARY */
|
||||
extern ivl_expr_t ivl_expr_oper1(ivl_expr_t net);
|
||||
/* IVL_EX_BINARY IVL_EX_TERNARY */
|
||||
/* IVL_EX_BINARY IVL_EX_NEW IVL_EX_TERNARY */
|
||||
extern ivl_expr_t ivl_expr_oper2(ivl_expr_t net);
|
||||
/* IVL_EX_TERNARY */
|
||||
extern ivl_expr_t ivl_expr_oper3(ivl_expr_t net);
|
||||
/* and expression */
|
||||
extern ivl_parameter_t ivl_expr_parameter(ivl_expr_t net);
|
||||
/* IVL_EX_CONCAT IVL_EX_UFUNC */
|
||||
/* IVL_EX_ARRAY_PATTERN IVL_EX_CONCAT IVL_EX_UFUNC */
|
||||
extern ivl_expr_t ivl_expr_parm(ivl_expr_t net, unsigned idx);
|
||||
/* IVL_EX_CONCAT IVL_EX_SFUNC IVL_EX_UFUNC */
|
||||
/* IVL_EX_ARRAY_PATTERN IVL_EX_CONCAT IVL_EX_SFUNC IVL_EX_UFUNC */
|
||||
extern unsigned ivl_expr_parms(ivl_expr_t net);
|
||||
/* IVL_EX_CONCAT */
|
||||
extern unsigned ivl_expr_repeat(ivl_expr_t net);
|
||||
@@ -1248,7 +1273,7 @@ extern unsigned ivl_lpm_lineno(ivl_lpm_t net);
|
||||
* width of the part. The ivl_lpm_q is the part end, and the
|
||||
* ivl_lpm_data(0) is the non-part end.
|
||||
*
|
||||
* - Comparisons (IVL_LPM_CMP_GT/GE/EQ/NE/EEQ/NEE)
|
||||
* - Comparisons (IVL_LPM_CMP_GT/GE/EQ/NE/EEQ/NEE/EQX/EQZ)
|
||||
* These devices have two inputs, available by the ivl_lpm_data()
|
||||
* function, and one output available by the ivl_lpm_q function. The
|
||||
* output width is always 1, but the ivl_lpm_width() returns the width
|
||||
@@ -1260,6 +1285,11 @@ extern unsigned ivl_lpm_lineno(ivl_lpm_t net);
|
||||
* magnitude compare, the signedness does matter. In any case, the
|
||||
* result of the compare is always unsigned.
|
||||
*
|
||||
* The EQX and EQZ nodes are windcard compares, where xz bits (EQX) or
|
||||
* z bits (EQZ) in the data(1) operand are treated as windcards. no
|
||||
* bits in the data(0) operand are wild. This matches the
|
||||
* SystemVerilog convention for the ==? operator.
|
||||
*
|
||||
* - Mux Device (IVL_LPM_MUX)
|
||||
* The MUX device has a q output, a select input, and a number of data
|
||||
* inputs. The ivl_lpm_q output and the ivl_lpm_data inputs all have
|
||||
@@ -1309,7 +1339,7 @@ extern unsigned ivl_lpm_lineno(ivl_lpm_t net);
|
||||
* repeated to get the desired width. The ivl core assures that the
|
||||
* input vector is exactly ivl_lpm_width() / ivl_lpm_size() bits.
|
||||
*
|
||||
* - Sign Exend (IVL_LPM_SIGN_EXT)
|
||||
* - Sign Extend (IVL_LPM_SIGN_EXT)
|
||||
* This node takes a single input and generates a single output. The
|
||||
* input must be signed, and the output will be a vector sign extended
|
||||
* to the desired width. The ivl_lpm_width() value is the output
|
||||
@@ -1385,7 +1415,7 @@ extern ivl_nexus_t ivl_lpm_sync_set(ivl_lpm_t net);
|
||||
extern ivl_expr_t ivl_lpm_sset_value(ivl_lpm_t net);
|
||||
/* IVL_LPM_ARRAY */
|
||||
extern ivl_signal_t ivl_lpm_array(ivl_lpm_t net);
|
||||
/* IVL_LPM_PART */
|
||||
/* IVL_LPM_PART IVL_LPM_SUBSTITUTE */
|
||||
extern unsigned ivl_lpm_base(ivl_lpm_t net);
|
||||
/* IVL_LPM_FF */
|
||||
extern ivl_nexus_t ivl_lpm_clk(ivl_lpm_t net);
|
||||
@@ -1395,12 +1425,14 @@ extern ivl_scope_t ivl_lpm_define(ivl_lpm_t net);
|
||||
extern ivl_nexus_t ivl_lpm_enable(ivl_lpm_t net);
|
||||
/* IVL_LPM_ADD IVL_LPM_CONCAT IVL_LPM_FF IVL_LPM_PART IVL_LPM_MULT
|
||||
IVL_LPM_MUX IVL_LPM_POW IVL_LPM_SHIFTL IVL_LPM_SHIFTR IVL_LPM_SUB
|
||||
IVL_LPM_UFUNC */
|
||||
IVL_LPM_UFUNC IVL_LPM_SUBSTITUTE */
|
||||
extern ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx);
|
||||
/* IVL_LPM_ADD IVL_LPM_MULT IVL_LPM_POW IVL_LPM_SUB */
|
||||
/* IVL_LPM_ADD IVL_LPM_MULT IVL_LPM_POW IVL_LPM_SUB IVL_LPM_CMP_EQ
|
||||
IVL_LPM_CMP_EEQ IVL_LPM_CMP_EQX IVL_LPM_CMP_EQZ IVL_LPM_CMP_NEE */
|
||||
extern ivl_nexus_t ivl_lpm_datab(ivl_lpm_t net, unsigned idx);
|
||||
/* IVL_LPM_ADD IVL_LPM_FF IVL_LPM_MULT IVL_LPM_PART IVL_LPM_POW
|
||||
IVL_LPM_SUB IVL_LPM_UFUNC */
|
||||
IVL_LPM_SUB IVL_LPM_UFUNC IVL_LPM_CMP_EEQ IVL_LPM_CMP_EQX
|
||||
IVL_LPM_CMP_EQZ IVL_LPM_CMP_NEE IVL_LPM_SUBSTITUTE */
|
||||
extern ivl_nexus_t ivl_lpm_q(ivl_lpm_t net);
|
||||
extern ivl_drive_t ivl_lpm_drive0(ivl_lpm_t net);
|
||||
extern ivl_drive_t ivl_lpm_drive1(ivl_lpm_t net);
|
||||
@@ -1427,12 +1459,11 @@ extern const char*ivl_lpm_string(ivl_lpm_t net);
|
||||
* for the local part selecting I might to in the lval object, as
|
||||
* well as the target object width.
|
||||
*
|
||||
* ivl_lval_mux
|
||||
* If the l-value includes a bit select expression, this method
|
||||
* returns an ivl_expr_t that represents that
|
||||
* expression. Otherwise, it returns 0.
|
||||
* ivl_lval_mux (* obsolete *)
|
||||
*
|
||||
* (Should this be combined with ivl_lval_idx? -Ed)
|
||||
* ivl_lval_nest
|
||||
* If the l-value is an object more complex than a variable, then
|
||||
* this returns the nested l-value (and ivl_lval_sig==0).
|
||||
*
|
||||
* ivl_lval_sig
|
||||
* If the l-value is a variable, this method returns the signal
|
||||
@@ -1472,15 +1503,21 @@ extern const char*ivl_lpm_string(ivl_lpm_t net);
|
||||
* then the ivl_lval_idx expression must *not* be present.
|
||||
*
|
||||
* For array words, the ivl_lval_width is the width of the word.
|
||||
*
|
||||
* - Arrayed properties
|
||||
* If the l-value is a class property, then the ivl_lval_idx function
|
||||
* will return an expression if the property is in fact arrayed. The
|
||||
* expression is the canonical index for elements in the property.
|
||||
*/
|
||||
|
||||
extern unsigned ivl_lval_width(ivl_lval_t net);
|
||||
extern ivl_expr_t ivl_lval_mux(ivl_lval_t net); /* XXXX Obsolete? */
|
||||
extern ivl_expr_t ivl_lval_mux(ivl_lval_t net) __attribute__((deprecated)); /* XXXX Obsolete? */
|
||||
extern ivl_expr_t ivl_lval_idx(ivl_lval_t net);
|
||||
extern ivl_expr_t ivl_lval_part_off(ivl_lval_t net);
|
||||
extern ivl_select_type_t ivl_lval_sel_type(ivl_lval_t net);
|
||||
extern int ivl_lval_property_idx(ivl_lval_t net);
|
||||
extern ivl_signal_t ivl_lval_sig(ivl_lval_t net);
|
||||
extern ivl_lval_t ivl_lval_nest(ivl_lval_t net);
|
||||
|
||||
|
||||
/* NEXUS
|
||||
@@ -1602,6 +1639,18 @@ extern ivl_signal_t ivl_nexus_ptr_sig(ivl_nexus_ptr_t net);
|
||||
* Return the value of the parameter. This should be a simple
|
||||
* constant expression, an IVL_EX_STRING or IVL_EX_NUMBER.
|
||||
*
|
||||
* ivl_parameter_msb
|
||||
* ivl_parameter_lsb
|
||||
* Returns the MSB and LSB for the parameter. For a parameter without
|
||||
* a range the value is zero based and the width of the expression is
|
||||
* used to determine the MSB.
|
||||
*
|
||||
* ivl_parameter_width
|
||||
* return |MSB - LSB| + 1
|
||||
*
|
||||
* ivl_parameter_signed
|
||||
* Returns if the parameter was declared to be signed.
|
||||
*
|
||||
* ivl_parameter_local
|
||||
* Return whether parameter was local (localparam, implicit genvar etc)
|
||||
* or not.
|
||||
@@ -1613,9 +1662,13 @@ extern ivl_signal_t ivl_nexus_ptr_sig(ivl_nexus_ptr_t net);
|
||||
extern const char* ivl_parameter_basename(ivl_parameter_t net);
|
||||
extern ivl_scope_t ivl_parameter_scope(ivl_parameter_t net);
|
||||
extern ivl_expr_t ivl_parameter_expr(ivl_parameter_t net);
|
||||
extern int ivl_parameter_local(ivl_parameter_t net);
|
||||
extern int ivl_parameter_msb(ivl_parameter_t net);
|
||||
extern int ivl_parameter_lsb(ivl_parameter_t net);
|
||||
extern unsigned ivl_parameter_width(ivl_parameter_t net);
|
||||
extern int ivl_parameter_signed(ivl_parameter_t net);
|
||||
extern int ivl_parameter_local(ivl_parameter_t net);
|
||||
extern const char* ivl_parameter_file(ivl_parameter_t net);
|
||||
extern unsigned ivl_parameter_lineno(ivl_parameter_t net);
|
||||
extern unsigned ivl_parameter_lineno(ivl_parameter_t net);
|
||||
|
||||
|
||||
/* SCOPE
|
||||
@@ -1658,6 +1711,11 @@ extern unsigned ivl_parameter_lineno(ivl_parameter_t net);
|
||||
* If the scope has no children, this method will return 0 and
|
||||
* otherwise do nothing.
|
||||
*
|
||||
* ivl_scope_childs
|
||||
* ivl_scope_child
|
||||
* This is an alternative way of getting at the childs scopes of a
|
||||
* given scope.
|
||||
*
|
||||
* ivl_scope_def
|
||||
* Task definition scopes carry a task definition, in the form of
|
||||
* a statement. This method accesses that definition. The
|
||||
@@ -1759,6 +1817,8 @@ extern ivl_statement_t ivl_scope_def(ivl_scope_t net);
|
||||
extern const char* ivl_scope_def_file(ivl_scope_t net);
|
||||
extern unsigned ivl_scope_def_lineno(ivl_scope_t net);
|
||||
|
||||
extern size_t ivl_scope_childs(ivl_scope_t net);
|
||||
extern ivl_scope_t ivl_scope_child(ivl_scope_t net, size_t idx);
|
||||
extern unsigned ivl_scope_classes(ivl_scope_t net);
|
||||
extern ivl_type_t ivl_scope_class(ivl_scope_t net, unsigned idx);
|
||||
extern unsigned ivl_scope_enumerates(ivl_scope_t net);
|
||||
@@ -2232,6 +2292,10 @@ extern unsigned ivl_switch_lineno(ivl_switch_t net);
|
||||
* Return the type of the element of an array. This is only valid
|
||||
* for array types.
|
||||
*
|
||||
* ivl_type_signed
|
||||
* Return TRUE if the type represents a signed packed vector or
|
||||
* signed atomic type, and FALSE otherwise.
|
||||
*
|
||||
* SEMANTIC NOTES
|
||||
*
|
||||
* Class types have names and properties.
|
||||
@@ -2241,6 +2305,7 @@ extern ivl_type_t ivl_type_element(ivl_type_t net);
|
||||
extern unsigned ivl_type_packed_dimensions(ivl_type_t net);
|
||||
extern int ivl_type_packed_lsb(ivl_type_t net, unsigned dim);
|
||||
extern int ivl_type_packed_msb(ivl_type_t net, unsigned dim);
|
||||
extern int ivl_type_signed(ivl_type_t net);
|
||||
extern const char* ivl_type_name(ivl_type_t net);
|
||||
extern int ivl_type_properties(ivl_type_t net);
|
||||
extern const char* ivl_type_prop_name(ivl_type_t net, int idx);
|
||||
@@ -2277,4 +2342,4 @@ typedef const char* (*target_query_f) (const char*key);
|
||||
|
||||
_END_DECL
|
||||
|
||||
#endif
|
||||
#endif /* IVL_ivl_target_H */
|
||||
|
||||
+16
-7
@@ -1,7 +1,7 @@
|
||||
#ifndef __ivl_target_priv_H
|
||||
#define __ivl_target_priv_H
|
||||
#ifndef IVL_ivl_target_priv_H
|
||||
#define IVL_ivl_target_priv_H
|
||||
/*
|
||||
* Copyright (c) 2008 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2008-2014 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -21,10 +21,13 @@
|
||||
|
||||
# include "ivl_target.h"
|
||||
# include <inttypes.h>
|
||||
# include <map>
|
||||
# include <vector>
|
||||
# include <ostream>
|
||||
# include <valarray>
|
||||
|
||||
class NetScope;
|
||||
|
||||
/*
|
||||
* This header has declarations related to the ivl_target.h API that
|
||||
* are not to be exported outside of the core via the ivl_target.h
|
||||
@@ -47,11 +50,17 @@ struct ivl_design_s {
|
||||
|
||||
ivl_process_t threads_;
|
||||
|
||||
ivl_scope_t *roots_;
|
||||
unsigned nroots_;
|
||||
// Keep arrays of root scopes.
|
||||
std::map<const NetScope*,ivl_scope_t> classes;
|
||||
std::map<const NetScope*,ivl_scope_t> root_tasks;
|
||||
std::vector<ivl_scope_t> packages;
|
||||
std::vector<ivl_scope_t> roots;
|
||||
|
||||
// This is used to implement the ivl_design_roots function.
|
||||
std::vector<ivl_scope_t> root_scope_list;
|
||||
|
||||
// Keep an array of constants objects.
|
||||
std::valarray<ivl_net_const_t> consts;
|
||||
std::vector<ivl_net_const_t> consts;
|
||||
|
||||
// Keep a handy array of all of the disciplines in the design.
|
||||
std::valarray<ivl_discipline_t> disciplines;
|
||||
@@ -82,4 +91,4 @@ struct ivl_island_s {
|
||||
|
||||
extern std::ostream& operator << (std::ostream&o, ivl_drive_t str);
|
||||
|
||||
#endif
|
||||
#endif /* IVL_ivl_target_priv_H */
|
||||
|
||||
+1
-1
@@ -44,7 +44,7 @@ INCLUDE_PATH = -I. -I.. -I$(srcdir) -I$(srcdir)/..
|
||||
endif
|
||||
|
||||
CPPFLAGS = $(INCLUDE_PATH) @CPPFLAGS@ @DEFS@
|
||||
CFLAGS = @WARNING_FLAGS@ @CFLAGS@
|
||||
CFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CC@ @CFLAGS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
|
||||
O = main.o lexor.o
|
||||
|
||||
+7
-7
@@ -1,7 +1,7 @@
|
||||
#ifndef __globals_H
|
||||
#define __globals_H
|
||||
#ifndef IVL_globals_H
|
||||
#define IVL_globals_H
|
||||
/*
|
||||
* Copyright (c) 1999-2009 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2014 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -22,11 +22,11 @@
|
||||
# include <stdio.h>
|
||||
|
||||
extern void reset_lexor(FILE*out, char*paths[]);
|
||||
extern void destroy_lexor();
|
||||
extern void destroy_lexor(void);
|
||||
extern void load_precompiled_defines(FILE*src);
|
||||
extern void define_macro(const char*name, const char*value, int keyword,
|
||||
int argc);
|
||||
extern void free_macros();
|
||||
extern void free_macros(void);
|
||||
extern void dump_precompiled_defines(FILE*out);
|
||||
|
||||
/* These variables contain the include directories to be searched when
|
||||
@@ -54,6 +54,6 @@ extern char dep_mode;
|
||||
extern int verbose_flag;
|
||||
|
||||
/* This is the entry to the lexer. */
|
||||
extern int yylex();
|
||||
extern int yylex(void);
|
||||
|
||||
#endif
|
||||
#endif /* IVL_globals_H */
|
||||
|
||||
+180
-62
@@ -1,7 +1,7 @@
|
||||
%option prefix="yy"
|
||||
%{
|
||||
/*
|
||||
* Copyright (c) 1999-2012 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1999-2014 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
|
||||
@@ -30,29 +30,29 @@
|
||||
# include "globals.h"
|
||||
# include "ivl_alloc.h"
|
||||
|
||||
static void output_init();
|
||||
static void output_init(void);
|
||||
#define YY_USER_INIT output_init()
|
||||
|
||||
static void def_start();
|
||||
static void def_add_arg();
|
||||
static void def_finish();
|
||||
static void def_undefine();
|
||||
static void do_define();
|
||||
static int def_is_done();
|
||||
static void def_start(void);
|
||||
static void def_add_arg(void);
|
||||
static void def_finish(void);
|
||||
static void def_undefine(void);
|
||||
static void do_define(void);
|
||||
static int def_is_done(void);
|
||||
static int is_defined(const char*name);
|
||||
|
||||
static int macro_needs_args(const char*name);
|
||||
static void macro_start_args();
|
||||
static void macro_add_to_arg();
|
||||
static void macro_finish_arg();
|
||||
static void macro_start_args(void);
|
||||
static void macro_add_to_arg(int is_whitespace);
|
||||
static void macro_finish_arg(void);
|
||||
static void do_expand(int use_args);
|
||||
static const char* do_magic(const char*name);
|
||||
static const char* macro_name();
|
||||
static const char* macro_name(void);
|
||||
|
||||
static void include_filename();
|
||||
static void do_include();
|
||||
static void include_filename(void);
|
||||
static void do_include(void);
|
||||
|
||||
static int load_next_input();
|
||||
static int load_next_input(void);
|
||||
|
||||
struct include_stack_t
|
||||
{
|
||||
@@ -255,6 +255,12 @@ keywords (include|define|undef|ifdef|ifndef|else|elseif|endif)
|
||||
if (macro_needs_args(yytext+1)) yy_push_state(MA_START); else do_expand(0);
|
||||
}
|
||||
|
||||
/* `" overrides the usual lexical meaning of " and `\`" indicates
|
||||
that the expansion should include the escape sequence \".
|
||||
*/
|
||||
`\" { fputc('"', yyout); }
|
||||
`\\`\" { fprintf(yyout, "\\\""); }
|
||||
|
||||
/* Strings do not contain preprocessor directives, but can expand
|
||||
* macros. If that happens, they get expanded in the context of the
|
||||
* string.
|
||||
@@ -346,6 +352,9 @@ keywords (include|define|undef|ifdef|ifndef|else|elseif|endif)
|
||||
<DEF_NAME>[a-zA-Z_][a-zA-Z0-9_$]*"("{W}? { BEGIN(DEF_ARG); def_start(); }
|
||||
<DEF_NAME>[a-zA-Z_][a-zA-Z0-9_$]*{W}? { BEGIN(DEF_TXT); def_start(); }
|
||||
|
||||
/* define arg: <name> = <text> */
|
||||
<DEF_ARG>[a-zA-Z_][a-zA-Z0-9_$]*{W}*"="[^,\)]*{W}? { BEGIN(DEF_SEP); def_add_arg(); }
|
||||
/* define arg: <name> */
|
||||
<DEF_ARG>[a-zA-Z_][a-zA-Z0-9_$]*{W}? { BEGIN(DEF_SEP); def_add_arg(); }
|
||||
|
||||
<DEF_SEP>","{W}? { BEGIN(DEF_ARG); }
|
||||
@@ -551,15 +560,25 @@ keywords (include|define|undef|ifdef|ifndef|else|elseif|endif)
|
||||
do_expand(0);
|
||||
}
|
||||
|
||||
/* Stringified version of macro expansion. */
|
||||
/* Stringified version of macro expansion. If the sequence `` is
|
||||
* encountered inside a macro definition, we use the SystemVerilog
|
||||
* handling of ignoring it so that identifiers can be constructed
|
||||
* from arguments. If istack->file is NULL, we are reading text
|
||||
* produced from a macro, so use SystemVerilog's handling;
|
||||
* otherwise, use the special Icarus handling.
|
||||
*/
|
||||
``[a-zA-Z_][a-zA-Z0-9_$]* {
|
||||
assert(do_expand_stringify_flag == 0);
|
||||
do_expand_stringify_flag = 1;
|
||||
fputc('"', yyout);
|
||||
if (macro_needs_args(yytext+2))
|
||||
yy_push_state(MA_START);
|
||||
else
|
||||
do_expand(0);
|
||||
if (istack->file == NULL)
|
||||
fprintf(yyout, "%s", yytext+2);
|
||||
else {
|
||||
assert(do_expand_stringify_flag == 0);
|
||||
do_expand_stringify_flag = 1;
|
||||
fputc('"', yyout);
|
||||
if (macro_needs_args(yytext+2))
|
||||
yy_push_state(MA_START);
|
||||
else
|
||||
do_expand(0);
|
||||
}
|
||||
}
|
||||
|
||||
<MA_START>\( { BEGIN(MA_ADD); macro_start_args(); }
|
||||
@@ -656,6 +675,7 @@ struct define_t
|
||||
char* value;
|
||||
int keyword; /* keywords don't get rescanned for fresh values. */
|
||||
int argc;
|
||||
char** defaults;
|
||||
int magic; /* 1 for 'magic' macros like __FILE__ and __LINE__. magic
|
||||
* macros cannot be undefined. magic macros are expanded
|
||||
* by do_magic. N.B. DON'T set a magic macro with
|
||||
@@ -758,13 +778,22 @@ static int is_defined(const char*name)
|
||||
|
||||
#define DEF_BUF_CHUNK 256
|
||||
|
||||
/*
|
||||
* During parse of macro definitions, and the name/arguments in
|
||||
* particular, keep the names and name lengths in a compact stretch of
|
||||
* memory. Note that we do not keep the argument names once the
|
||||
* definition is fully processed, because arguments are always
|
||||
* positional and the definition string hs replaced with position
|
||||
* tokens.
|
||||
*/
|
||||
static char* def_buf = 0;
|
||||
static int def_buf_size = 0;
|
||||
static int def_buf_free = 0;
|
||||
|
||||
static int def_argc = 0;
|
||||
static int def_argo[MAX_DEF_ARG]; /* offset of first character in arg */
|
||||
static int def_argl[MAX_DEF_ARG]; /* length of arg string. */
|
||||
static int def_argo[MAX_DEF_ARG]; /* offset of first character of arg name */
|
||||
static int def_argl[MAX_DEF_ARG]; /* lengths of arg names. */
|
||||
static int def_argd[MAX_DEF_ARG]; /* Offset of default value */
|
||||
|
||||
/*
|
||||
* Return a pointer to the start of argument 'arg'. Returned pointers
|
||||
@@ -775,7 +804,7 @@ static /* inline */ char* def_argv(int arg)
|
||||
return def_buf + def_argo[arg];
|
||||
}
|
||||
|
||||
static void check_for_max_args()
|
||||
static void check_for_max_args(void)
|
||||
{
|
||||
if (def_argc == MAX_DEF_ARG)
|
||||
{
|
||||
@@ -796,14 +825,14 @@ static void def_buf_grow_to_fit(int length)
|
||||
}
|
||||
}
|
||||
|
||||
static void def_start()
|
||||
static void def_start(void)
|
||||
{
|
||||
def_buf_free = def_buf_size;
|
||||
def_argc = 0;
|
||||
def_add_arg();
|
||||
}
|
||||
|
||||
static void def_add_arg()
|
||||
static void def_add_arg(void)
|
||||
{
|
||||
int length = yyleng;
|
||||
|
||||
@@ -813,23 +842,65 @@ static void def_add_arg()
|
||||
while (isspace((int)yytext[length - 1]))
|
||||
length--;
|
||||
|
||||
/* This can happen because we are also processing "argv[0]", the
|
||||
macro name, as a pseudo-argument. The lexor will match that
|
||||
as name(, so chop off the ( here. */
|
||||
if (yytext[length - 1] == '(')
|
||||
length--;
|
||||
|
||||
yytext[length] = 0;
|
||||
|
||||
char*arg = yytext;
|
||||
char*val;
|
||||
int val_length = 0;
|
||||
|
||||
/* Break into ARG = value. This happens if the source specifies
|
||||
a default value for the formal argument. In that case, the
|
||||
lexor will match the whole thing as the argument and it is up
|
||||
to us to chop it up to name and value. */
|
||||
if ( (val=strchr(arg,'=')) ) {
|
||||
*val++ = 0;
|
||||
while (*val && isspace(*val)) val += 1;
|
||||
|
||||
val_length = strlen(val);
|
||||
while (val_length>0 && isspace(val[val_length-1])) {
|
||||
val_length -= 1;
|
||||
val[val_length] = 0;
|
||||
}
|
||||
|
||||
/* Strip white space from betwen arg and "=". */
|
||||
length = strlen(arg);
|
||||
while (length>0 && isspace(arg[length-1])) {
|
||||
length -= 1;
|
||||
arg[length] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Make sure there's room in the buffer for the new argument. */
|
||||
def_buf_grow_to_fit(length);
|
||||
|
||||
/* Store the new argument. */
|
||||
/* Store the new argument name. */
|
||||
def_argl[def_argc] = length;
|
||||
def_argo[def_argc] = def_buf_size - def_buf_free;
|
||||
strcpy(def_argv(def_argc++), yytext);
|
||||
strcpy(def_argv(def_argc), arg);
|
||||
def_buf_free -= length + 1;
|
||||
|
||||
/* If there is a default text, then stash it away as well. */
|
||||
if (val) {
|
||||
def_buf_grow_to_fit(val_length);
|
||||
def_argd[def_argc] = def_buf_size - def_buf_free;
|
||||
strcpy(def_buf+def_argd[def_argc], val);
|
||||
def_buf_free -= val_length + 1;
|
||||
} else {
|
||||
def_argd[def_argc] = 0;
|
||||
}
|
||||
|
||||
def_argc += 1;
|
||||
}
|
||||
|
||||
void define_macro(const char* name, const char* value, int keyword, int argc)
|
||||
{
|
||||
int idx;
|
||||
struct define_t* def;
|
||||
|
||||
def = malloc(sizeof(struct define_t));
|
||||
@@ -841,6 +912,14 @@ void define_macro(const char* name, const char* value, int keyword, int argc)
|
||||
def->left = 0;
|
||||
def->right = 0;
|
||||
def->up = 0;
|
||||
def->defaults = calloc(argc, sizeof(char*));
|
||||
for (idx = 0 ; idx < argc ; idx += 1) {
|
||||
if (def_argd[idx] == 0) {
|
||||
def->defaults[idx] = 0;
|
||||
} else {
|
||||
def->defaults[idx] = strdup(def_buf+def_argd[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
if (def_table == 0)
|
||||
def_table = def;
|
||||
@@ -888,15 +967,19 @@ void define_macro(const char* name, const char* value, int keyword, int argc)
|
||||
|
||||
static void free_macro(struct define_t* def)
|
||||
{
|
||||
int idx;
|
||||
if (def == 0) return;
|
||||
free_macro(def->left);
|
||||
free_macro(def->right);
|
||||
free(def->name);
|
||||
free(def->value);
|
||||
for (idx = 0 ; idx < def->argc ; idx += 1)
|
||||
free(def->defaults[idx]);
|
||||
free(def->defaults);
|
||||
free(def);
|
||||
}
|
||||
|
||||
void free_macros()
|
||||
void free_macros(void)
|
||||
{
|
||||
free_macro(def_table);
|
||||
}
|
||||
@@ -969,7 +1052,7 @@ static char *find_arg(char*ptr, char*head, char*arg)
|
||||
* continuation, then return 1 and this function may be called again
|
||||
* to collect another line of the definition.
|
||||
*/
|
||||
static void do_define()
|
||||
static void do_define(void)
|
||||
{
|
||||
char* cp;
|
||||
char* head;
|
||||
@@ -1119,7 +1202,7 @@ static void do_define()
|
||||
* Return true if the definition text is done. This is the opposite of
|
||||
* the define_continue_flag.
|
||||
*/
|
||||
static int def_is_done()
|
||||
static int def_is_done(void)
|
||||
{
|
||||
return !define_continue_flag;
|
||||
}
|
||||
@@ -1129,7 +1212,7 @@ static int def_is_done()
|
||||
* assigned value to the parsed name. If there is no value, then
|
||||
* assign the string "" (empty string.)
|
||||
*/
|
||||
static void def_finish()
|
||||
static void def_finish(void)
|
||||
{
|
||||
define_continue_flag = 0;
|
||||
|
||||
@@ -1151,10 +1234,11 @@ static void def_finish()
|
||||
def_argc = 0;
|
||||
}
|
||||
|
||||
static void def_undefine()
|
||||
static void def_undefine(void)
|
||||
{
|
||||
struct define_t* cur;
|
||||
struct define_t* tail;
|
||||
int idx;
|
||||
|
||||
/* def_buf is used to store the macro name. Make sure there is
|
||||
* enough space.
|
||||
@@ -1248,6 +1332,9 @@ static void def_undefine()
|
||||
|
||||
free(cur->name);
|
||||
free(cur->value);
|
||||
for (idx = 0 ; idx < cur->argc ; idx += 1)
|
||||
free(cur->defaults[idx]);
|
||||
free(cur->defaults);
|
||||
free(cur);
|
||||
}
|
||||
|
||||
@@ -1273,12 +1360,12 @@ static int macro_needs_args(const char*text)
|
||||
}
|
||||
}
|
||||
|
||||
static const char* macro_name()
|
||||
static const char* macro_name(void)
|
||||
{
|
||||
return cur_macro ? cur_macro->name : "";
|
||||
}
|
||||
|
||||
static void macro_start_args()
|
||||
static void macro_start_args(void)
|
||||
{
|
||||
/* The macro name can be found via cur_macro, so create a null
|
||||
* entry for arg 0. This will be used by macro_finish_arg() to
|
||||
@@ -1315,7 +1402,7 @@ static void macro_add_to_arg(int is_white_space)
|
||||
def_buf_free -= length;
|
||||
}
|
||||
|
||||
static void macro_finish_arg()
|
||||
static void macro_finish_arg(void)
|
||||
{
|
||||
char* tail = &def_buf[def_buf_size - def_buf_free];
|
||||
|
||||
@@ -1356,7 +1443,7 @@ static void exp_buf_grow_to_fit(int length)
|
||||
}
|
||||
}
|
||||
|
||||
static void expand_using_args()
|
||||
static void expand_using_args(void)
|
||||
{
|
||||
char* head;
|
||||
char* tail;
|
||||
@@ -1382,13 +1469,22 @@ static void expand_using_args()
|
||||
{
|
||||
arg = tail[1]; assert(arg < def_argc);
|
||||
|
||||
length = (tail - head) + def_argl[arg];
|
||||
char*use_argv;
|
||||
int use_argl;
|
||||
if (def_argl[arg] == 0 && cur_macro->defaults[arg]) {
|
||||
use_argv = cur_macro->defaults[arg];
|
||||
use_argl = strlen(use_argv);
|
||||
} else {
|
||||
use_argv = def_argv(arg);
|
||||
use_argl = def_argl[arg];
|
||||
}
|
||||
length = (tail - head) + use_argl;
|
||||
exp_buf_grow_to_fit(length);
|
||||
|
||||
dest = &exp_buf[exp_buf_size - exp_buf_free];
|
||||
memcpy(dest, head, tail - head);
|
||||
dest += tail - head;
|
||||
memcpy(dest, def_argv(arg), def_argl[arg]);
|
||||
memcpy(dest, use_argv, use_argl);
|
||||
|
||||
exp_buf_free -= length;
|
||||
|
||||
@@ -1538,7 +1634,8 @@ static const char* do_magic(const char*name)
|
||||
|
||||
int actual_len = snprintf(magic_text, desired_cnt,
|
||||
"%u", get_line(istack));
|
||||
assert(actual_len < desired_cnt);
|
||||
assert(actual_len >= 0);
|
||||
assert((unsigned) actual_len < desired_cnt);
|
||||
return magic_text;
|
||||
}
|
||||
else if(!strcmp(name, "__FILE__"))
|
||||
@@ -1558,7 +1655,9 @@ static const char* do_magic(const char*name)
|
||||
|
||||
int actual_len = snprintf(magic_text, desired_cnt,
|
||||
"\"%s\"", path);
|
||||
assert(actual_len < desired_cnt);
|
||||
|
||||
assert(actual_len >= 0);
|
||||
assert((unsigned) actual_len < (unsigned)desired_cnt);
|
||||
return magic_text;
|
||||
}
|
||||
}
|
||||
@@ -1588,13 +1687,13 @@ static const char* do_magic(const char*name)
|
||||
* parsing resumes.
|
||||
*/
|
||||
|
||||
static void output_init()
|
||||
static void output_init(void)
|
||||
{
|
||||
if (line_direct_flag)
|
||||
fprintf(yyout, "`line 1 \"%s\" 0\n", istack->path);
|
||||
}
|
||||
|
||||
static void include_filename()
|
||||
static void include_filename(void)
|
||||
{
|
||||
if(standby) {
|
||||
emit_pathline(istack);
|
||||
@@ -1613,7 +1712,7 @@ static void include_filename()
|
||||
standby->comment = NULL;
|
||||
}
|
||||
|
||||
static void do_include()
|
||||
static void do_include(void)
|
||||
{
|
||||
/* standby is defined by include_filename() */
|
||||
if (standby->path[0] == '/') {
|
||||
@@ -1736,7 +1835,7 @@ static void emit_pathline(struct include_stack_t* isp)
|
||||
fprintf(stderr, "%s:%u: ", isp->path, isp->lineno+1);
|
||||
}
|
||||
|
||||
static void lexor_done()
|
||||
static void lexor_done(void)
|
||||
{
|
||||
while (ifdef_stack)
|
||||
{
|
||||
@@ -1824,7 +1923,7 @@ static void open_input_file(struct include_stack_t*isp)
|
||||
* end of a base file, in which case the next base source file is
|
||||
* opened.
|
||||
*/
|
||||
static int load_next_input()
|
||||
static int load_next_input(void)
|
||||
{
|
||||
int line_mask_flag = 0;
|
||||
struct include_stack_t* isp = istack;
|
||||
@@ -1967,51 +2066,66 @@ void dump_precompiled_defines(FILE* out)
|
||||
|
||||
void load_precompiled_defines(FILE* src)
|
||||
{
|
||||
char buf[4096];
|
||||
char*buf = malloc(4096);
|
||||
size_t buf_len = 4096;
|
||||
int ch;
|
||||
|
||||
while ((ch = fgetc(src)) != EOF)
|
||||
{
|
||||
char* cp = buf;
|
||||
char* name = 0;
|
||||
char* value = 0;
|
||||
|
||||
int argc = 0;
|
||||
size_t len = 0;
|
||||
|
||||
name = cp;
|
||||
|
||||
*cp++ = ch;
|
||||
|
||||
while ((ch = fgetc(src)) != EOF && ch != ':')
|
||||
while ((ch = fgetc(src)) != EOF && ch != ':') {
|
||||
*cp++ = ch;
|
||||
assert( (size_t)(cp-buf) < buf_len );
|
||||
}
|
||||
|
||||
if (ch != ':')
|
||||
return;
|
||||
|
||||
/* Terminate the name string. */
|
||||
*cp++ = 0;
|
||||
assert( (size_t)(cp-buf) < buf_len );
|
||||
|
||||
/* Read the argc number */
|
||||
/* Read the argc number. (this doesn't need buffer space) */
|
||||
while (isdigit(ch = fgetc(src)))
|
||||
argc = 10*argc + ch-'0';
|
||||
|
||||
if (ch != ':')
|
||||
return;
|
||||
return;
|
||||
|
||||
/* Read the value len (this doesn't need buffer space) */
|
||||
while (isdigit(ch = fgetc(src)))
|
||||
len = 10*len + ch-'0';
|
||||
|
||||
if (ch != ':')
|
||||
return;
|
||||
return;
|
||||
|
||||
value = cp;
|
||||
/* Save the name, and start the buffer over. */
|
||||
name = strdup(buf);
|
||||
|
||||
/* We now know how big the value should be, so if necessary,
|
||||
reallocate the buffer to be sure we can hold it. */
|
||||
if ((len+4) >= buf_len) {
|
||||
buf = realloc(buf, len+8);
|
||||
assert(buf);
|
||||
}
|
||||
|
||||
cp = buf;
|
||||
|
||||
while (len > 0)
|
||||
{
|
||||
ch = fgetc(src);
|
||||
if (ch == EOF)
|
||||
return;
|
||||
if (ch == EOF) {
|
||||
free(name);
|
||||
return;
|
||||
}
|
||||
|
||||
*cp++ = ch;
|
||||
len -= 1;
|
||||
@@ -2020,10 +2134,14 @@ void load_precompiled_defines(FILE* src)
|
||||
*cp++ = 0;
|
||||
|
||||
ch = fgetc(src);
|
||||
if (ch != '\n')
|
||||
return;
|
||||
if (ch != '\n') {
|
||||
free(name);
|
||||
free(buf);
|
||||
return;
|
||||
}
|
||||
|
||||
define_macro(name, value, 0, argc);
|
||||
define_macro(name, buf, 0, argc);
|
||||
free(name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2094,7 +2212,7 @@ void reset_lexor(FILE* out, char* paths[])
|
||||
/*
|
||||
* Modern version of flex (>=2.5.9) can clean up the scanner data.
|
||||
*/
|
||||
void destroy_lexor()
|
||||
void destroy_lexor(void)
|
||||
{
|
||||
# ifdef FLEX_SCANNER
|
||||
# if YY_FLEX_MAJOR_VERSION >= 2 && YY_FLEX_MINOR_VERSION >= 5
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
%{
|
||||
/*
|
||||
* Copyright (c) 1998-2012 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2014 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
|
||||
@@ -91,6 +91,19 @@ static bool in_module = false;
|
||||
static bool in_UDP = false;
|
||||
bool in_celldefine = false;
|
||||
UCDriveType uc_drive = UCD_NONE;
|
||||
|
||||
/*
|
||||
* The parser sometimes needs to indicate to the lexor that the next
|
||||
* identifier needs to be understood in the context of a package. The
|
||||
* parser feeds back that left context with calls to the
|
||||
* lex_in_package_scope.
|
||||
*/
|
||||
static PPackage* in_package_scope = 0;
|
||||
void lex_in_package_scope(PPackage*pkg)
|
||||
{
|
||||
in_package_scope = pkg;
|
||||
}
|
||||
|
||||
%}
|
||||
|
||||
%x CCOMMENT
|
||||
@@ -121,9 +134,17 @@ TU [munpf]
|
||||
\n { yylloc.first_line += 1; }
|
||||
|
||||
/* C++ style comments start with / / and run to the end of the
|
||||
current line. These are very easy to handle. */
|
||||
current line. These are very easy to handle. The meta-comments
|
||||
format is a little more tricky to handle, but do what we can. */
|
||||
|
||||
"//".* { comment_enter = YY_START; BEGIN(LCOMMENT); }
|
||||
/* The lexor detects "// synthesis translate_on/off" meta-comments,
|
||||
we handle them here by turning on/off a flag. The pform uses
|
||||
that flag to attach implicit attributes to "initial" and
|
||||
"always" statements. */
|
||||
|
||||
"//"{W}*"synthesis"{W}+"translate_on"{W}*\n { pform_mc_translate_on(true); }
|
||||
"//"{W}*"synthesis"{W}+"translate_off"{W}*\n { pform_mc_translate_on(false); }
|
||||
"//" { comment_enter = YY_START; BEGIN(LCOMMENT); }
|
||||
<LCOMMENT>. { yymore(); }
|
||||
<LCOMMENT>\n { yylloc.first_line += 1; BEGIN(comment_enter); }
|
||||
|
||||
@@ -216,6 +237,8 @@ TU [munpf]
|
||||
return STRING; }
|
||||
<CSTRING>. { yymore(); }
|
||||
|
||||
/* The UDP Table is a unique lexical environment. These are most
|
||||
tokens that we can expect in a table. */
|
||||
<UDPTABLE>\(\?0\) { return '_'; }
|
||||
<UDPTABLE>\(\?1\) { return '+'; }
|
||||
<UDPTABLE>\(\?[xX]\) { return '%'; }
|
||||
@@ -240,7 +263,7 @@ TU [munpf]
|
||||
<UDPTABLE>[xX] { return 'x'; }
|
||||
<UDPTABLE>[nN] { return 'n'; }
|
||||
<UDPTABLE>[pP] { return 'p'; }
|
||||
<UDPTABLE>[01\?\*\-] { return yytext[0]; }
|
||||
<UDPTABLE>[01\?\*\-:;] { return yytext[0]; }
|
||||
|
||||
<EDGES>"01" { return K_edge_descriptor; }
|
||||
<EDGES>"0x" { return K_edge_descriptor; }
|
||||
@@ -283,6 +306,10 @@ TU [munpf]
|
||||
in_UDP = false;
|
||||
break;
|
||||
|
||||
case K_table:
|
||||
BEGIN(UDPTABLE);
|
||||
break;
|
||||
|
||||
/* Translate these to checks if we already have or are
|
||||
* outside the declaration region. */
|
||||
case K_timeunit:
|
||||
@@ -297,6 +324,24 @@ TU [munpf]
|
||||
break;
|
||||
}
|
||||
|
||||
/* Special case: If this is part of a scoped name, then check
|
||||
the package for identifier details. For example, if the
|
||||
source file is foo::bar, the parse.y will note the
|
||||
PACKAGE_IDENTIFIER and "::" token and mark the
|
||||
"in_package_scope" variable. Then this lexor will see the
|
||||
identifier here and interpret it in the package scope. */
|
||||
if (in_package_scope) {
|
||||
if (rc == IDENTIFIER) {
|
||||
if (data_type_t*type = pform_test_type_identifier(in_package_scope, yylval.text)) {
|
||||
yylval.type_identifier.text = yylval.text;
|
||||
yylval.type_identifier.type = type;
|
||||
rc = TYPE_IDENTIFIER;
|
||||
}
|
||||
}
|
||||
in_package_scope = 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* If this identifier names a discipline, then return this as
|
||||
a DISCIPLINE_IDENTIFIER and return the discipline as the
|
||||
value instead. */
|
||||
@@ -310,12 +355,22 @@ TU [munpf]
|
||||
}
|
||||
}
|
||||
|
||||
/* If this identifier names a previously declared package, then
|
||||
return this as a PACKAGE_IDENTIFIER instead. */
|
||||
if (rc == IDENTIFIER && gn_system_verilog()) {
|
||||
if (PPackage*pkg = pform_test_package_identifier(yylval.text)) {
|
||||
delete[]yylval.text;
|
||||
yylval.package = pkg;
|
||||
rc = PACKAGE_IDENTIFIER;
|
||||
}
|
||||
}
|
||||
|
||||
/* If this identifier names a previously declared type, then
|
||||
return this as a TYPE_IDENTIFIER instead. */
|
||||
if (rc == IDENTIFIER && gn_system_verilog()) {
|
||||
if (data_type_t*type = pform_test_type_identifier(yylval.text)) {
|
||||
delete[]yylval.text;
|
||||
yylval.data_type = type;
|
||||
yylval.type_identifier.text = yylval.text;
|
||||
yylval.type_identifier.type = type;
|
||||
rc = TYPE_IDENTIFIER;
|
||||
}
|
||||
}
|
||||
@@ -327,9 +382,16 @@ TU [munpf]
|
||||
\\[^ \t\b\f\r\n]+ {
|
||||
yylval.text = strdupnew(yytext+1);
|
||||
if (gn_system_verilog()) {
|
||||
if (data_type_t*type = pform_test_type_identifier(yylval.text)) {
|
||||
if (PPackage*pkg = pform_test_package_identifier(yylval.text)) {
|
||||
delete[]yylval.text;
|
||||
yylval.data_type = type;
|
||||
yylval.package = pkg;
|
||||
return PACKAGE_IDENTIFIER;
|
||||
}
|
||||
}
|
||||
if (gn_system_verilog()) {
|
||||
if (data_type_t*type = pform_test_type_identifier(yylval.text)) {
|
||||
yylval.type_identifier.text = yylval.text;
|
||||
yylval.type_identifier.type = type;
|
||||
return TYPE_IDENTIFIER;
|
||||
}
|
||||
}
|
||||
@@ -392,14 +454,22 @@ TU [munpf]
|
||||
generation_flag = generation_save;
|
||||
return UNBASED_NUMBER; }
|
||||
|
||||
/* Decimal numbers are the usual. But watch out for the UDPTABLE
|
||||
mode, where there are no decimal numbers. Reject the match if we
|
||||
are in the UDPTABLE state. */
|
||||
[0-9][0-9_]* {
|
||||
yylval.number = make_unsized_dec(yytext);
|
||||
based_size = yylval.number->as_ulong();
|
||||
return DEC_NUMBER; }
|
||||
if (YY_START==UDPTABLE) {
|
||||
REJECT;
|
||||
} else {
|
||||
yylval.number = make_unsized_dec(yytext);
|
||||
based_size = yylval.number->as_ulong();
|
||||
return DEC_NUMBER;
|
||||
}
|
||||
}
|
||||
|
||||
/* This rule handles scaled time values for SystemVerilog. */
|
||||
[0-9][0-9_]*(\.[0-9][0-9_]*)?{TU}?s {
|
||||
if(generation_flag & (GN_VER2005_SV | GN_VER2009)) {
|
||||
if(generation_flag & (GN_VER2005_SV | GN_VER2009 | GN_VER2012)) {
|
||||
yylval.text = strdupnew(yytext);
|
||||
return TIME_LITERAL;
|
||||
} else REJECT; }
|
||||
@@ -572,6 +642,14 @@ TU [munpf]
|
||||
|GN_KEYWORDS_1364_2005
|
||||
|GN_KEYWORDS_1800_2005
|
||||
|GN_KEYWORDS_1800_2009;
|
||||
} else if (strcmp(word,"1800-2012") == 0) {
|
||||
lexor_keyword_mask = GN_KEYWORDS_1364_1995
|
||||
|GN_KEYWORDS_1364_2001
|
||||
|GN_KEYWORDS_1364_2001_CONFIG
|
||||
|GN_KEYWORDS_1364_2005
|
||||
|GN_KEYWORDS_1800_2005
|
||||
|GN_KEYWORDS_1800_2009
|
||||
|GN_KEYWORDS_1800_2012;
|
||||
} else if (strcmp(word,"VAMS-2.3") == 0) {
|
||||
lexor_keyword_mask = GN_KEYWORDS_1364_1995
|
||||
|GN_KEYWORDS_1364_2001
|
||||
@@ -735,16 +813,27 @@ TU [munpf]
|
||||
* lexor. The level characters are normally accepted as other things,
|
||||
* so the parser needs to switch my mode when it believes in needs to.
|
||||
*/
|
||||
void lex_start_table()
|
||||
{
|
||||
BEGIN(UDPTABLE);
|
||||
}
|
||||
|
||||
void lex_end_table()
|
||||
{
|
||||
BEGIN(INITIAL);
|
||||
}
|
||||
|
||||
static unsigned truncate_to_integer_width(verinum::V*bits, unsigned size)
|
||||
{
|
||||
if (size <= integer_width) return size;
|
||||
|
||||
verinum::V pad = bits[size-1];
|
||||
if (pad == verinum::V1) pad = verinum::V0;
|
||||
|
||||
for (unsigned idx = integer_width; idx < size; idx += 1) {
|
||||
if (bits[idx] != pad) {
|
||||
yywarn(yylloc, "Unsized numeric constant truncated to integer width.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
return integer_width;
|
||||
}
|
||||
|
||||
verinum*make_unsized_binary(const char*txt)
|
||||
{
|
||||
bool sign_flag = false;
|
||||
@@ -802,6 +891,9 @@ verinum*make_unsized_binary(const char*txt)
|
||||
ptr += 1;
|
||||
}
|
||||
|
||||
if (gn_strict_expr_width_flag && (based_size == 0))
|
||||
size = truncate_to_integer_width(bits, size);
|
||||
|
||||
verinum*out = new verinum(bits, size, false);
|
||||
out->has_sign(sign_flag);
|
||||
out->is_single(single_flag);
|
||||
@@ -870,6 +962,9 @@ verinum*make_unsized_octal(const char*txt)
|
||||
ptr += 1;
|
||||
}
|
||||
|
||||
if (gn_strict_expr_width_flag && (based_size == 0))
|
||||
size = truncate_to_integer_width(bits, size);
|
||||
|
||||
verinum*out = new verinum(bits, size, false);
|
||||
out->has_sign(sign_flag);
|
||||
delete[]bits;
|
||||
@@ -947,6 +1042,9 @@ verinum*make_unsized_hex(const char*txt)
|
||||
ptr += 1;
|
||||
}
|
||||
|
||||
if (gn_strict_expr_width_flag && (based_size == 0))
|
||||
size = truncate_to_integer_width(bits, size);
|
||||
|
||||
verinum*out = new verinum(bits, size, false);
|
||||
out->has_sign(sign_flag);
|
||||
delete[]bits;
|
||||
@@ -1136,6 +1234,9 @@ verinum*make_unsized_dec(const char*ptr)
|
||||
number represents we do not check for extra bits. */
|
||||
// if (based_size > 0) { }
|
||||
|
||||
if (gn_strict_expr_width_flag && (based_size == 0))
|
||||
size = truncate_to_integer_width(bits, size);
|
||||
|
||||
verinum*res = new verinum(bits, size, false);
|
||||
res->has_sign(signed_flag);
|
||||
|
||||
|
||||
+8
-2
@@ -3,9 +3,11 @@
|
||||
* tokenType values are not initialized for the empty table entries.
|
||||
*/
|
||||
%define initializer-suffix ,0,0
|
||||
%language=C++
|
||||
%define class-name Lkwd
|
||||
|
||||
%{
|
||||
/* Command-line: gperf -o -i 1 -C -k 1-3,$ -L C -H keyword_hash -N check_identifier -tT lexor_keyword.gperf */
|
||||
/* Command-line: gperf -o -i 7 -C -k '1-4,6,9,$' -H keyword_hash -N check_identifier -t ./lexor_keyword.gperf */
|
||||
|
||||
#include "config.h"
|
||||
#include "parse_misc.h"
|
||||
@@ -161,6 +163,7 @@ ifnone, GN_KEYWORDS_1364_1995, K_ifnone
|
||||
ignore_bins, GN_KEYWORDS_1800_2005, K_ignore_bins
|
||||
illegal_bins, GN_KEYWORDS_1800_2005, K_illegal_bins
|
||||
implies, GN_KEYWORDS_1800_2009, K_implies
|
||||
implements, GN_KEYWORDS_1800_2012, K_implements
|
||||
import, GN_KEYWORDS_1800_2005, K_import
|
||||
incdir, GN_KEYWORDS_1364_2001_CONFIG, K_incdir
|
||||
include, GN_KEYWORDS_1364_2001_CONFIG, K_include
|
||||
@@ -173,6 +176,7 @@ inside, GN_KEYWORDS_1800_2005, K_inside
|
||||
instance, GN_KEYWORDS_1364_2001_CONFIG, K_instance
|
||||
int, GN_KEYWORDS_1800_2005, K_int
|
||||
integer, GN_KEYWORDS_1364_1995, K_integer
|
||||
interconnect, GN_KEYWORDS_1800_2012, K_interconnect
|
||||
interface, GN_KEYWORDS_1800_2005, K_interface
|
||||
intersect, GN_KEYWORDS_1800_2005, K_intersect
|
||||
join, GN_KEYWORDS_1364_1995, K_join
|
||||
@@ -207,6 +211,7 @@ nand, GN_KEYWORDS_1364_1995, K_nand
|
||||
nature, GN_KEYWORDS_VAMS_2_3, K_nature
|
||||
negedge, GN_KEYWORDS_1364_1995, K_negedge
|
||||
net_resolution, GN_KEYWORDS_VAMS_2_3, K_net_resolution
|
||||
nettype, GN_KEYWORDS_1800_2012, K_nettype
|
||||
new, GN_KEYWORDS_1800_2005, K_new
|
||||
nexttime, GN_KEYWORDS_1800_2009, K_nexttime
|
||||
nmos, GN_KEYWORDS_1364_1995, K_nmos
|
||||
@@ -274,6 +279,7 @@ sin, GN_KEYWORDS_VAMS_2_3, K_sin
|
||||
sinh, GN_KEYWORDS_VAMS_2_3, K_sinh
|
||||
slew, GN_KEYWORDS_VAMS_2_3, K_slew
|
||||
small, GN_KEYWORDS_1364_1995, K_small
|
||||
soft, GN_KEYWORDS_1800_2012, K_soft
|
||||
solve, GN_KEYWORDS_1800_2005, K_solve
|
||||
specify, GN_KEYWORDS_1364_1995, K_specify
|
||||
specparam, GN_KEYWORDS_1364_1995, K_specparam
|
||||
@@ -358,7 +364,7 @@ int lexor_keyword_mask = 0;
|
||||
|
||||
int lexor_keyword_code(const char*str, unsigned nstr)
|
||||
{
|
||||
const struct lexor_keyword*rc = check_identifier(str, nstr);
|
||||
const struct lexor_keyword*rc = Lkwd::check_identifier(str, nstr);
|
||||
if (rc == 0)
|
||||
return IDENTIFIER;
|
||||
else if ((rc->mask & lexor_keyword_mask) == 0)
|
||||
|
||||
+4
-4
@@ -1,7 +1,7 @@
|
||||
#ifndef __lexor_keyword_H
|
||||
#define __lexor_keyword_H
|
||||
#ifndef IVL_lexor_keyword_H
|
||||
#define IVL_lexor_keyword_H
|
||||
/*
|
||||
* Copyright (c) 2000 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -21,4 +21,4 @@
|
||||
|
||||
extern int lexor_keyword_code (const char*str, unsigned len);
|
||||
|
||||
#endif
|
||||
#endif /* IVL_lexor_keyword_H */
|
||||
|
||||
+4
-4
@@ -1,7 +1,7 @@
|
||||
#ifndef __LineInfo_H
|
||||
#define __LineInfo_H
|
||||
#ifndef IVL_LineInfo_H
|
||||
#define IVL_LineInfo_H
|
||||
/*
|
||||
* Copyright (c) 1999-2011 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2014 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -54,4 +54,4 @@ class LineInfo {
|
||||
unsigned lineno_;
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif /* IVL_LineInfo_H */
|
||||
|
||||
@@ -210,3 +210,5 @@ ostream& operator << (ostream&out, perm_string that)
|
||||
out << that.str();
|
||||
return out;
|
||||
}
|
||||
|
||||
const perm_string empty_perm_string = perm_string::literal("");
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __StringHeap_H
|
||||
#define __StringHeap_H
|
||||
#ifndef IVL_StringHeap_H
|
||||
#define IVL_StringHeap_H
|
||||
/*
|
||||
* Copyright (c) 2002-2009 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2002-2014 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -52,6 +52,7 @@ class perm_string {
|
||||
const char*text_;
|
||||
};
|
||||
|
||||
extern const perm_string empty_perm_string;
|
||||
extern bool operator == (perm_string a, perm_string b);
|
||||
extern bool operator == (perm_string a, const char* b);
|
||||
extern bool operator != (perm_string a, perm_string b);
|
||||
@@ -120,4 +121,4 @@ class StringHeapLex : private StringHeap {
|
||||
StringHeapLex& operator= (const StringHeapLex&);
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif /* IVL_StringHeap_H */
|
||||
|
||||
@@ -48,7 +48,7 @@ LDRELOCFLAGS = @LDRELOCFLAGS@
|
||||
LDTARGETFLAGS = @LDTARGETFLAGS@
|
||||
|
||||
CPPFLAGS = $(INCLUDE_PATH) @CPPFLAGS@ @DEFS@ @PICFLAG@
|
||||
CFLAGS = @WARNING_FLAGS@ @CFLAGS@
|
||||
CFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CC@ @CFLAGS@
|
||||
|
||||
A = a_close.o a_compare_handles.o a_configure.o a_fetch_argc.o \
|
||||
a_fetch_argv.o a_fetch_dir.o a_fetch_fullname.o a_fetch_location.o \
|
||||
|
||||
@@ -69,9 +69,13 @@ int acc_configure(PLI_INT32 config_param, const char*value)
|
||||
fprintf(pli_trace, "acc_configure(config=%d, %s)\n",
|
||||
(int)config_param, value);
|
||||
}
|
||||
|
||||
#if 0
|
||||
vpi_printf("XXXX acc_configure(%d, %s)\n", (int)config_param,
|
||||
value);
|
||||
#else
|
||||
/* Parameter is not necessarily a string. */
|
||||
vpi_printf("XXXX acc_configure(%d, ...)\n", (int)config_param);
|
||||
#endif
|
||||
rc = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
# include <vpi_user.h>
|
||||
# include <veriuser.h>
|
||||
# include <acc_user.h>
|
||||
|
||||
/*
|
||||
* acc_fetch_argc implemented using VPI interface
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
# include <vpi_user.h>
|
||||
# include <veriuser.h>
|
||||
# include <acc_user.h>
|
||||
|
||||
/*
|
||||
* acc_fetch_argv implemented using VPI interface
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003 Stephen Williams (steve@picturel.com)
|
||||
* Copyright (c) 2003-2014 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
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
PLI_INT32 acc_fetch_direction(handle obj)
|
||||
{
|
||||
(void)obj; /* Parameter is not used. */
|
||||
if (pli_trace) {
|
||||
fprintf(pli_trace, "acc_fetch_direction: enter.\n");
|
||||
fflush(pli_trace);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2003-2014 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
int acc_fetch_location(p_location loc, handle obj)
|
||||
{
|
||||
(void)obj; /* Parameter is not used. */
|
||||
loc->line_no = 0;
|
||||
loc->filename = "<filename>";
|
||||
return 1;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003-2010 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2003-2014 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -40,3 +40,12 @@ const char* acc_fetch_type_str(PLI_INT32 type)
|
||||
vpi_printf("acc_fetch_type_str: type %d is what accType?\n", (int)type);
|
||||
return "acc_fetch_type_str(unknown)";
|
||||
}
|
||||
|
||||
/*
|
||||
* FIXME: What does this do? How should it be declared in acc_user.h?
|
||||
*/
|
||||
PLI_INT32 acc_fetch_paramtype(handle obj)
|
||||
{
|
||||
(void)obj; /* Parameter is not used. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003 Stephen Williams (steve@picturel.com)
|
||||
* Copyright (c) 2003-2014 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
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
handle acc_handle_hiconn(handle obj)
|
||||
{
|
||||
(void)obj; /* Parameter is not used. */
|
||||
if (pli_trace) {
|
||||
fprintf(pli_trace, "acc_handle_hiconn: enter.\n");
|
||||
fflush(pli_trace);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003 Stephen Williams (steve@picturel.com)
|
||||
* Copyright (c) 2003-2014 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
|
||||
@@ -25,6 +25,8 @@
|
||||
|
||||
handle acc_next_bit(handle ref, handle bit)
|
||||
{
|
||||
(void)ref; /* Parameter is not used. */
|
||||
(void)bit; /* Parameter is not used. */
|
||||
if (pli_trace) {
|
||||
fprintf(pli_trace, "acc_next_bit: enter.\n");
|
||||
fflush(pli_trace);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2003-2014 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -25,6 +25,8 @@
|
||||
|
||||
handle acc_next_port(handle ref, handle bit)
|
||||
{
|
||||
(void)ref; /* Parameter is not used. */
|
||||
(void)bit; /* Parameter is not used. */
|
||||
if (pli_trace) {
|
||||
fprintf(pli_trace, "acc_next_port: enter.\n");
|
||||
fflush(pli_trace);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002-2009 Michael Ruff (mruff at chiaro.com)
|
||||
* Copyright (c) 2002-2013 Michael Ruff (mruff at chiaro.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
|
||||
@@ -45,7 +45,7 @@ int acc_object_of_type(handle object, PLI_INT32 type)
|
||||
case accScope:
|
||||
if (vtype == vpiModule || vtype == vpiNamedBegin ||
|
||||
vtype == vpiNamedFork || vtype == vpiTask ||
|
||||
vtype == vpiFunction) rtn = 1;
|
||||
vtype == vpiFunction || vtype == vpiGenScope) rtn = 1;
|
||||
break;
|
||||
|
||||
case accNet: rtn = vtype == vpiNet; break;
|
||||
|
||||
+6
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003-2010 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2003-2014 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -162,6 +162,7 @@ void acc_vcl_add(handle obj, PLI_INT32(*consumer)(p_vc_record),
|
||||
|
||||
switch (vpi_get(vpiType, obj)) {
|
||||
case vpiNet:
|
||||
case vpiReg:
|
||||
cur = malloc(sizeof (struct vcl_record));
|
||||
cur->obj = obj;
|
||||
cur->consumer = consumer;
|
||||
@@ -195,5 +196,9 @@ void acc_vcl_add(handle obj, PLI_INT32(*consumer)(p_vc_record),
|
||||
void acc_vcl_delete(handle obj, PLI_INT32(*consumer)(p_vc_record),
|
||||
void*data, PLI_INT32 vcl_flag)
|
||||
{
|
||||
(void)obj; /* Parameter is not used. */
|
||||
(void)consumer; /* Parameter is not used. */
|
||||
(void)data; /* Parameter is not used. */
|
||||
(void)vcl_flag; /* Parameter is not used. */
|
||||
vpi_printf("XXXX acc_vcl_delete(...)\n");
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __config_H
|
||||
#define __config_H
|
||||
#ifndef IVL_config_H
|
||||
#define IVL_config_H
|
||||
/*
|
||||
* Copyright (c) 2003 Stephen Williams ([email protected])
|
||||
* Copyright (c) 2003-2014 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -37,4 +37,4 @@ typedef unsigned long ivl_u64_t;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif /* IVL_config_H */
|
||||
|
||||
+2
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2003-2014 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
static PLI_INT32 delay_callback(struct t_cb_data*cb)
|
||||
{
|
||||
(void)cb; /* Parameter is not used. */
|
||||
vpi_printf("XXXX delay_callback called.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2003-2014 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -25,6 +25,8 @@
|
||||
|
||||
struct t_tfexprinfo* tf_exprinfo(PLI_INT32 a, struct t_tfexprinfo*ip)
|
||||
{
|
||||
(void)a; /* Parameter is not used. */
|
||||
(void)ip; /* Parameter is not used. */
|
||||
if (pli_trace) {
|
||||
fprintf(pli_trace, "tf_exprinfo: enter.\n");
|
||||
fflush(pli_trace);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002-2011 Michael Ruff (mruff at chiaro.com)
|
||||
* Copyright (c) 2002-2014 Michael Ruff (mruff at chiaro.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
|
||||
@@ -39,14 +39,36 @@ static ivl_u64_t pow10u(PLI_INT32 val)
|
||||
}
|
||||
|
||||
static ivl_u64_t
|
||||
scale(int high, int low, void*obj) {
|
||||
vpiHandle hand = vpi_handle(vpiScope, vpi_handle(vpiSysTfCall,0));
|
||||
scale(int high, int low, void*obj)
|
||||
{
|
||||
ivl_u64_t scaled;
|
||||
|
||||
vpiHandle use_obj = obj;
|
||||
if (use_obj == 0) {
|
||||
/* If object is not passed in, then use current scope. */
|
||||
vpiHandle hand = vpi_handle(vpiScope, vpi_handle(vpiSysTfCall,0));
|
||||
use_obj = hand;
|
||||
} else {
|
||||
/* If object IS passed in, make sure it is a scope. If
|
||||
it is not, then get the scope of the object. We need
|
||||
a scope handle to go on. */
|
||||
switch (vpi_get(vpiType,use_obj)) {
|
||||
case vpiModule:
|
||||
case vpiGenScope:
|
||||
case vpiFunction:
|
||||
case vpiTask:
|
||||
case vpiNamedBegin:
|
||||
case vpiNamedFork:
|
||||
break;
|
||||
default:
|
||||
use_obj = vpi_handle(vpiScope, use_obj);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
scaled = high;
|
||||
scaled = (scaled << 32) | low;
|
||||
scaled /= pow10u(vpi_get(vpiTimeUnit,obj ? (vpiHandle)obj : hand) -
|
||||
vpi_get(vpiTimePrecision,0));
|
||||
scaled /= pow10u(vpi_get(vpiTimeUnit, use_obj) - vpi_get(vpiTimePrecision,0));
|
||||
|
||||
return scaled;
|
||||
}
|
||||
@@ -125,6 +147,8 @@ void tf_unscale_longdelay(void*obj, PLI_INT32 low, PLI_INT32 high,
|
||||
ivl_u64_t unscaled;
|
||||
vpiHandle hand = vpi_handle(vpiScope, vpi_handle(vpiSysTfCall,0));
|
||||
|
||||
(void)obj; /* Parameter is not used. */
|
||||
|
||||
unscaled = high;
|
||||
unscaled = (unscaled << 32) | low;
|
||||
unscaled *= pow(10, vpi_get(vpiTimeUnit, hand) -
|
||||
@@ -138,6 +162,8 @@ void tf_scale_realdelay(void*obj, double real, double *areal)
|
||||
{
|
||||
vpiHandle hand = vpi_handle(vpiScope, vpi_handle(vpiSysTfCall,0));
|
||||
|
||||
(void)obj; /* Parameter is not used. */
|
||||
|
||||
*areal = real / pow(10, vpi_get(vpiTimeUnit, hand) -
|
||||
vpi_get(vpiTimePrecision, 0));
|
||||
}
|
||||
@@ -146,6 +172,8 @@ void tf_unscale_realdelay(void*obj, double real, double *areal)
|
||||
{
|
||||
vpiHandle hand = vpi_handle(vpiScope, vpi_handle(vpiSysTfCall,0));
|
||||
|
||||
(void)obj; /* Parameter is not used. */
|
||||
|
||||
*areal = real * pow(10, vpi_get(vpiTimeUnit, hand) -
|
||||
vpi_get(vpiTimePrecision, 0));
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002 Michael Ruff (mruff at chiaro.com)
|
||||
* Copyright (c) 2002-2014 Michael Ruff (mruff at chiaro.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
|
||||
@@ -58,6 +58,8 @@ PLI_INT32 tf_message(PLI_INT32 level, char*facility,
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
(void)level; /* Parameter is not used. */
|
||||
|
||||
vpi_printf("%s[%s] ", facility, messno);
|
||||
|
||||
va_start(ap, fmt);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user